Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/thirdpin/libopencm3.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib/usb
diff options
context:
space:
mode:
authorAndrey Smirnov <ndreys@bulbasaur.(none)>2012-11-16 04:02:36 +0400
committerKarl Palsson <karlp@tweak.net.au>2015-03-30 03:07:32 +0300
commitdb58d5ae826ffa550d7bd336944c9635436b6e6e (patch)
tree1158fe798bb8e3848b9ca3ef44294c4a37f9eb16 /lib/usb
parentfd141a81313876e3dc9253d682f7314fa2a59718 (diff)
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>
Diffstat (limited to 'lib/usb')
-rw-r--r--lib/usb/usb_private.h3
-rw-r--r--lib/usb/usb_standard.c52
2 files changed, 43 insertions, 12 deletions
diff --git a/lib/usb/usb_private.h b/lib/usb/usb_private.h
index 81466dfa..4d8f7ed4 100644
--- a/lib/usb/usb_private.h
+++ b/lib/usb/usb_private.h
@@ -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 */
diff --git a/lib/usb/usb_standard.c b/lib/usb/usb_standard.c
index 885f077b..8bdc5c9d 100644
--- a/lib/usb/usb_standard.c
+++ b/lib/usb/usb_standard.c
@@ -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,