Add provisions to support multiple altsettings
This commit implements the support for one interface to have multiple altsettings. It also adds hook that user can use to perform actions when the alsetting switch is performed by host. Changes: * For backward compatibility, placed a pointer instead of allocating memory for whole interface struct. * Always execute callback (even if the current interface alternate-settings matches). * Multiple configuration support. Signed-off-by: Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
This commit is contained in:
parent
fd141a8131
commit
db58d5ae82
@ -89,6 +89,9 @@ extern int usbd_register_control_callback(usbd_device *usbd_dev, uint8_t type,
|
||||
extern int usbd_register_set_config_callback(usbd_device *usbd_dev,
|
||||
void (*callback)(usbd_device *usbd_dev, uint16_t wValue));
|
||||
|
||||
extern void usbd_register_set_altsetting_callback(usbd_device *usbd_dev,
|
||||
void (*callback)(usbd_device *usbd_dev, uint16_t wIndex, uint16_t wValue));
|
||||
|
||||
/* Functions to be provided by the hardware abstraction layer */
|
||||
extern void usbd_poll(usbd_device *usbd_dev);
|
||||
extern void usbd_disconnect(usbd_device *usbd_dev, bool disconnected);
|
||||
|
@ -163,7 +163,8 @@ struct usb_config_descriptor {
|
||||
|
||||
/* Descriptor ends here. The following are used internally: */
|
||||
const struct usb_interface {
|
||||
int num_altsetting;
|
||||
uint8_t *cur_altsetting;
|
||||
uint8_t num_altsetting;
|
||||
const struct usb_iface_assoc_descriptor *iface_assoc;
|
||||
const struct usb_interface_descriptor *altsetting;
|
||||
} *interface;
|
||||
|
@ -89,6 +89,9 @@ struct _usbd_device {
|
||||
void (*user_callback_set_config[MAX_USER_SET_CONFIG_CALLBACK])
|
||||
(usbd_device *usbd_dev, uint16_t wValue);
|
||||
|
||||
void (*user_callback_set_altsetting)(usbd_device *usbd_dev,
|
||||
uint16_t wIndex, uint16_t wValue);
|
||||
|
||||
const struct _usbd_driver *driver;
|
||||
|
||||
/* private driver data */
|
||||
|
@ -56,6 +56,13 @@ int usbd_register_set_config_callback(usbd_device *usbd_dev,
|
||||
return -1;
|
||||
}
|
||||
|
||||
void usbd_register_set_altsetting_callback(usbd_device *usbd_dev,
|
||||
void (*callback)(usbd_device *usbd_dev,
|
||||
uint16_t wIndex, uint16_t wValue))
|
||||
{
|
||||
usbd_dev->user_callback_set_altsetting = callback;
|
||||
}
|
||||
|
||||
static uint16_t build_config_descriptor(usbd_device *usbd_dev,
|
||||
uint8_t index, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
@ -294,32 +301,53 @@ static int usb_standard_set_interface(usbd_device *usbd_dev,
|
||||
struct usb_setup_data *req,
|
||||
uint8_t **buf, uint16_t *len)
|
||||
{
|
||||
(void)usbd_dev;
|
||||
(void)req;
|
||||
const struct usb_config_descriptor *cfx = &usbd_dev->config[usbd_dev->current_config - 1];
|
||||
const struct usb_interface *iface;
|
||||
|
||||
(void)buf;
|
||||
|
||||
/* FIXME: Adapt if we have more than one interface. */
|
||||
if (req->wValue != 0) {
|
||||
return 0;
|
||||
if (req->wIndex >= cfx->bNumInterfaces) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
|
||||
iface = &cfx->interface[req->wIndex];
|
||||
|
||||
if (req->wValue >= iface->num_altsetting) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
|
||||
if (iface->cur_altsetting) {
|
||||
*iface->cur_altsetting = req->wValue;
|
||||
} else if (req->wValue > 0) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
|
||||
if (usbd_dev->user_callback_set_altsetting) {
|
||||
usbd_dev->user_callback_set_altsetting(usbd_dev,
|
||||
req->wIndex, req->wValue);
|
||||
}
|
||||
|
||||
*len = 0;
|
||||
|
||||
return 1;
|
||||
return USBD_REQ_HANDLED;
|
||||
}
|
||||
|
||||
static int usb_standard_get_interface(usbd_device *usbd_dev,
|
||||
struct usb_setup_data *req,
|
||||
uint8_t **buf, uint16_t *len)
|
||||
{
|
||||
(void)usbd_dev;
|
||||
(void)req;
|
||||
(void)buf;
|
||||
uint8_t *cur_altsetting;
|
||||
const struct usb_config_descriptor *cfx = &usbd_dev->config[usbd_dev->current_config - 1];
|
||||
|
||||
if (req->wIndex >= cfx->bNumInterfaces) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
|
||||
/* FIXME: Adapt if we have more than one interface. */
|
||||
*len = 1;
|
||||
(*buf)[0] = 0;
|
||||
cur_altsetting = cfx->interface[req->wIndex].cur_altsetting;
|
||||
(*buf)[0] = (cur_altsetting) ? *cur_altsetting : 0;
|
||||
|
||||
return 1;
|
||||
return USBD_REQ_HANDLED;
|
||||
}
|
||||
|
||||
static int usb_standard_device_get_status(usbd_device *usbd_dev,
|
||||
|
Loading…
x
Reference in New Issue
Block a user