summaryrefslogtreecommitdiff
path: root/src/device/usbd.c
diff options
context:
space:
mode:
authorhathach <[email protected]>2019-07-30 10:24:36 +0700
committerGitHub <[email protected]>2019-07-30 10:24:36 +0700
commit1e7f1de4d766e846ec43d5b345a7dc545d98335b (patch)
treee09333dd599e92d0686ca5e2bcf928b1cf60165a /src/device/usbd.c
parent1ee9ef4f2b7c6acfab6c398a4f57ca22036958f7 (diff)
parent00a9e492cdf04ea17379218996d2713bcaaaff51 (diff)
Merge pull request #89 from hathach/develop
resolve #35 (vendor class), implement #86 (webusb)
Diffstat (limited to 'src/device/usbd.c')
-rw-r--r--src/device/usbd.c216
1 files changed, 132 insertions, 84 deletions
diff --git a/src/device/usbd.c b/src/device/usbd.c
index a68953151..a6eda79de 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -43,20 +43,20 @@
typedef struct {
struct TU_ATTR_PACKED
{
- volatile uint8_t connected : 1;
- volatile uint8_t configured : 1;
- volatile uint8_t suspended : 1;
+ volatile uint8_t connected : 1;
+ volatile uint8_t configured : 1;
+ volatile uint8_t suspended : 1;
- uint8_t remote_wakeup_en : 1; // enable/disable by host
- uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute
- uint8_t self_powered : 1; // configuration descriptor's attribute
+ uint8_t remote_wakeup_en : 1; // enable/disable by host
+ uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute
+ uint8_t self_powered : 1; // configuration descriptor's attribute
};
uint8_t ep_busy_map[2]; // bit mask for busy endpoint
uint8_t ep_stall_map[2]; // bit map for stalled endpoint
- uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
- uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid )
+ uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
+ uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid )
}usbd_device_t;
static usbd_device_t _usbd_dev = { 0 };
@@ -67,80 +67,80 @@ static usbd_device_t _usbd_dev = { 0 };
typedef struct {
uint8_t class_code;
- void (* init ) (void);
- bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length);
- bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request);
- bool (* control_request_complete ) (uint8_t rhport, tusb_control_request_t const * request);
- bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t, uint32_t);
- void (* sof ) (uint8_t rhport);
- void (* reset ) (uint8_t);
+ void (* init ) (void);
+ void (* reset ) (uint8_t rhport);
+ bool (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length);
+ bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request);
+ bool (* control_complete ) (uint8_t rhport, tusb_control_request_t const * request);
+ bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
+ void (* sof ) (uint8_t rhport);
} usbd_class_driver_t;
static usbd_class_driver_t const usbd_class_drivers[] =
{
#if CFG_TUD_CDC
- {
- .class_code = TUSB_CLASS_CDC,
- .init = cdcd_init,
- .open = cdcd_open,
- .control_request = cdcd_control_request,
- .control_request_complete = cdcd_control_request_complete,
- .xfer_cb = cdcd_xfer_cb,
- .sof = NULL,
- .reset = cdcd_reset
- },
+ {
+ .class_code = TUSB_CLASS_CDC,
+ .init = cdcd_init,
+ .reset = cdcd_reset,
+ .open = cdcd_open,
+ .control_request = cdcd_control_request,
+ .control_complete = cdcd_control_complete,
+ .xfer_cb = cdcd_xfer_cb,
+ .sof = NULL
+ },
#endif
#if CFG_TUD_MSC
- {
- .class_code = TUSB_CLASS_MSC,
- .init = mscd_init,
- .open = mscd_open,
- .control_request = mscd_control_request,
- .control_request_complete = mscd_control_request_complete,
- .xfer_cb = mscd_xfer_cb,
- .sof = NULL,
- .reset = mscd_reset
- },
+ {
+ .class_code = TUSB_CLASS_MSC,
+ .init = mscd_init,
+ .reset = mscd_reset,
+ .open = mscd_open,
+ .control_request = mscd_control_request,
+ .control_complete = mscd_control_complete,
+ .xfer_cb = mscd_xfer_cb,
+ .sof = NULL
+ },
#endif
#if CFG_TUD_HID
- {
- .class_code = TUSB_CLASS_HID,
- .init = hidd_init,
- .open = hidd_open,
- .control_request = hidd_control_request,
- .control_request_complete = hidd_control_request_complete,
- .xfer_cb = hidd_xfer_cb,
- .sof = NULL,
- .reset = hidd_reset
- },
+ {
+ .class_code = TUSB_CLASS_HID,
+ .init = hidd_init,
+ .reset = hidd_reset,
+ .open = hidd_open,
+ .control_request = hidd_control_request,
+ .control_complete = hidd_control_complete,
+ .xfer_cb = hidd_xfer_cb,
+ .sof = NULL
+ },
#endif
#if CFG_TUD_MIDI
- {
- .class_code = TUSB_CLASS_AUDIO,
- .init = midid_init,
- .open = midid_open,
- .control_request = midid_control_request,
- .control_request_complete = midid_control_request_complete,
- .xfer_cb = midid_xfer_cb,
- .sof = NULL,
- .reset = midid_reset
- },
+ {
+ .class_code = TUSB_CLASS_AUDIO,
+ .init = midid_init,
+ .open = midid_open,
+ .reset = midid_reset,
+ .control_request = midid_control_request,
+ .control_complete = midid_control_complete,
+ .xfer_cb = midid_xfer_cb,
+ .sof = NULL
+ },
#endif
- #if CFG_TUD_CUSTOM_CLASS
- {
- .class_code = TUSB_CLASS_VENDOR_SPECIFIC,
- .init = cusd_init,
- .open = cusd_open,
- .control_request = cusd_control_request,
- .control_request_complete = cusd_control_request_complete,
- .xfer_cb = cusd_xfer_cb,
- .sof = NULL,
- .reset = cusd_reset
- },
+ #if CFG_TUD_VENDOR
+ {
+ .class_code = TUSB_CLASS_VENDOR_SPECIFIC,
+ .init = vendord_init,
+ .reset = vendord_reset,
+ .open = vendord_open,
+ .control_request = tud_vendor_control_request_cb,
+ .control_complete = tud_vendor_control_complete_cb,
+ .xfer_cb = vendord_xfer_cb,
+ .sof = NULL
+ },
#endif
};
@@ -237,7 +237,6 @@ static void usbd_reset(uint8_t rhport)
while(1) // the mainloop
{
application_code();
-
tud_task(); // tinyusb device task
}
}
@@ -347,6 +346,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
{
usbd_control_set_complete_callback(NULL);
+ // Vendor request
+ if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR )
+ {
+ TU_VERIFY(tud_vendor_control_request_cb);
+
+ if (tud_vendor_control_complete_cb) usbd_control_set_complete_callback(tud_vendor_control_complete_cb);
+ return tud_vendor_control_request_cb(rhport, p_request);
+ }
+
switch ( p_request->bmRequestType_bit.recipient )
{
//------------- Device Requests e.g in enumeration -------------//
@@ -370,7 +378,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
case TUSB_REQ_GET_CONFIGURATION:
{
uint8_t cfgnum = _usbd_dev.configured ? 1 : 0;
- usbd_control_xfer(rhport, p_request, &cfgnum, 1);
+ tud_control_xfer(rhport, p_request, &cfgnum, 1);
}
break;
@@ -382,7 +390,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
_usbd_dev.configured = cfg_num ? 1 : 0;
if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) );
- usbd_control_status(rhport, p_request);
+ tud_control_status(rhport, p_request);
}
break;
@@ -396,7 +404,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Host may enable remote wake up before suspending especially HID device
_usbd_dev.remote_wakeup_en = true;
- usbd_control_status(rhport, p_request);
+ tud_control_status(rhport, p_request);
break;
case TUSB_REQ_CLEAR_FEATURE:
@@ -405,7 +413,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Host may disable remote wake up after resuming
_usbd_dev.remote_wakeup_en = false;
- usbd_control_status(rhport, p_request);
+ tud_control_status(rhport, p_request);
break;
case TUSB_REQ_GET_STATUS:
@@ -414,7 +422,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// - Bit 0: Self Powered
// - Bit 1: Remote Wakeup enabled
uint16_t status = (_usbd_dev.self_powered ? 1 : 0) | (_usbd_dev.remote_wakeup_en ? 2 : 0);
- usbd_control_xfer(rhport, p_request, &status, 2);
+ tud_control_xfer(rhport, p_request, &status, 2);
}
break;
@@ -431,10 +439,34 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
TU_VERIFY(drvid < USBD_CLASS_DRIVER_COUNT);
- usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_request_complete );
+ switch ( p_request->bRequest )
+ {
+ case TUSB_REQ_GET_INTERFACE:
+ {
+ // TODO not support alternate interface yet
+ uint8_t alternate = 0;
+ tud_control_xfer(rhport, p_request, &alternate, 1);
+ }
+ break;
+
+ case TUSB_REQ_SET_INTERFACE:
+ {
+ uint8_t alternate = (uint8_t) p_request->wValue;
+
+ // TODO not support alternate interface yet
+ TU_ASSERT(alternate == 0);
- // stall control endpoint if driver return false
- return usbd_class_drivers[drvid].control_request(rhport, p_request);
+ tud_control_status(rhport, p_request);
+ }
+ break;
+
+ default:
+ // forward to class driver
+ // stall control endpoint if driver return false
+ usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_complete);
+ TU_ASSERT(usbd_class_drivers[drvid].control_request(rhport, p_request));
+ break;
+ }
}
break;
@@ -448,7 +480,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
case TUSB_REQ_GET_STATUS:
{
uint16_t status = usbd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000;
- usbd_control_xfer(rhport, p_request, &status, 2);
+ tud_control_xfer(rhport, p_request, &status, 2);
}
break;
@@ -457,7 +489,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
{
usbd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex));
}
- usbd_control_status(rhport, p_request);
+ tud_control_status(rhport, p_request);
break;
case TUSB_REQ_SET_FEATURE:
@@ -465,7 +497,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
{
usbd_edpt_stall(rhport, tu_u16_low(p_request->wIndex));
}
- usbd_control_status(rhport, p_request);
+ tud_control_status(rhport, p_request);
break;
// Unknown/Unsupported request
@@ -520,7 +552,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id;
uint16_t itf_len=0;
- TU_ASSERT( usbd_class_drivers[drv_id].open( rhport, desc_itf, &itf_len ) );
+ TU_ASSERT( usbd_class_drivers[drv_id].open(rhport, desc_itf, &itf_len) );
TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) );
mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, itf_len, drv_id);
@@ -563,13 +595,29 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
switch(desc_type)
{
case TUSB_DESC_DEVICE:
- return usbd_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), sizeof(tusb_desc_device_t));
+ return tud_control_xfer(rhport, p_request, (void*) tud_descriptor_device_cb(), sizeof(tusb_desc_device_t));
+ break;
+
+ case TUSB_DESC_BOS:
+ {
+ // requested by host if USB > 2.0 ( i.e 2.1 or 3.x )
+ if (!tud_descriptor_bos_cb) return false;
+
+ tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb();
+ uint16_t total_len;
+ memcpy(&total_len, &desc_bos->wTotalLength, 2); // possibly mis-aligned memory
+
+ return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len);
+ }
break;
case TUSB_DESC_CONFIGURATION:
{
tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index);
- return usbd_control_xfer(rhport, p_request, (void*) desc_config, desc_config->wTotalLength);
+ uint16_t total_len;
+ memcpy(&total_len, &desc_config->wTotalLength, 2); // possibly mis-aligned memory
+
+ return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len);
}
break;
@@ -577,8 +625,8 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
// String Descriptor always uses the desc set from user
if ( desc_index == 0xEE )
{
- // The 0xEE index string is a Microsoft USB extension.
- // It can be used to tell Windows what driver it should use for the device !!!
+ // The 0xEE index string is a Microsoft OS Descriptors.
+ // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
return false;
}else
{
@@ -586,7 +634,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
TU_ASSERT(desc_str);
// first byte of descriptor is its size
- return usbd_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]);
+ return tud_control_xfer(rhport, p_request, (void*) desc_str, desc_str[0]);
}
break;