Merge pull request #1369 from tannewt/host_string_desc
Add host string descriptor functions
This commit is contained in:
		| @@ -38,6 +38,7 @@ | ||||
| #define TU_MIN(_x, _y)        ( ( (_x) < (_y) ) ? (_x) : (_y) ) | ||||
| #define TU_MAX(_x, _y)        ( ( (_x) > (_y) ) ? (_x) : (_y) ) | ||||
|  | ||||
| #define TU_U16(_high, _low)   ((uint16_t) (((_high) << 8) | (_low))) | ||||
| #define TU_U16_HIGH(_u16)     ((uint8_t) (((_u16) >> 8) & 0x00ff)) | ||||
| #define TU_U16_LOW(_u16)      ((uint8_t) ((_u16)       & 0x00ff)) | ||||
| #define U16_TO_U8S_BE(_u16)   TU_U16_HIGH(_u16), TU_U16_LOW(_u16) | ||||
| @@ -349,7 +350,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 | ||||
|   } | ||||
|  | ||||
|   // not found return the key value in hex | ||||
|   sprintf(not_found, "0x%08lX", (unsigned long) key); | ||||
|   snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key); | ||||
|  | ||||
|   return not_found; | ||||
| } | ||||
|   | ||||
| @@ -407,6 +407,7 @@ bool tud_init (uint8_t rhport) | ||||
|   if ( tud_inited() ) return true; | ||||
|  | ||||
|   TU_LOG2("USBD init\r\n"); | ||||
|   TU_LOG2_INT(sizeof(usbd_device_t)); | ||||
|  | ||||
|   tu_varclr(&_usbd_dev); | ||||
|  | ||||
|   | ||||
| @@ -35,6 +35,19 @@ | ||||
|  extern "C" { | ||||
| #endif | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Configuration | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| #ifndef CFG_TUH_ENDPOINT_MAX | ||||
|   #define CFG_TUH_ENDPOINT_MAX   (CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3) | ||||
| //  #ifdef TUP_HCD_ENDPOINT_MAX | ||||
| //    #define CFG_TUH_ENDPPOINT_MAX   TUP_HCD_ENDPOINT_MAX | ||||
| //  #else | ||||
| //    #define | ||||
| //  #endif | ||||
| #endif | ||||
|  | ||||
|  //--------------------------------------------------------------------+ | ||||
| // MACRO CONSTANT TYPEDEF | ||||
| //--------------------------------------------------------------------+ | ||||
| @@ -81,17 +94,6 @@ typedef struct | ||||
|  | ||||
| } hcd_event_t; | ||||
|  | ||||
| #if CFG_TUH_ENABLED | ||||
| // Max number of endpoints per device | ||||
| enum { | ||||
|   // TODO better computation | ||||
|   HCD_MAX_ENDPOINT = CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3), | ||||
|   HCD_MAX_XFER     = HCD_MAX_ENDPOINT*2, | ||||
| }; | ||||
|  | ||||
| //#define HCD_MAX_ENDPOINT 16 | ||||
| //#define HCD_MAX_XFER 16 | ||||
|  | ||||
| typedef struct { | ||||
|   uint8_t rhport; | ||||
|   uint8_t hub_addr; | ||||
| @@ -99,8 +101,6 @@ typedef struct { | ||||
|   uint8_t speed; | ||||
| } hcd_devtree_info_t; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Controller API | ||||
| //--------------------------------------------------------------------+ | ||||
|   | ||||
| @@ -54,7 +54,7 @@ static inline hub_interface_t* get_itf(uint8_t dev_addr) | ||||
|   return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX]; | ||||
| } | ||||
|  | ||||
| #if CFG_TUSB_DEBUG | ||||
| #if CFG_TUSB_DEBUG >= 2 | ||||
| static char const* const _hub_feature_str[] = | ||||
| { | ||||
|   [HUB_FEATURE_PORT_CONNECTION          ] = "PORT_CONNECTION", | ||||
|   | ||||
							
								
								
									
										231
									
								
								src/host/usbh.c
									
									
									
									
									
								
							
							
						
						
									
										231
									
								
								src/host/usbh.c
									
									
									
									
									
								
							| @@ -37,15 +37,14 @@ | ||||
| // USBH Configuration | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| // TODO remove,update | ||||
| #ifndef CFG_TUH_EP_MAX | ||||
| #define CFG_TUH_EP_MAX          9 | ||||
| #endif | ||||
|  | ||||
| #ifndef CFG_TUH_TASK_QUEUE_SZ | ||||
| #define CFG_TUH_TASK_QUEUE_SZ   16 | ||||
| #endif | ||||
|  | ||||
| #ifndef CFG_TUH_INTERFACE_MAX | ||||
| #define CFG_TUH_INTERFACE_MAX   8 | ||||
| #endif | ||||
|  | ||||
| // Debug level of USBD | ||||
| #define USBH_DBG_LVL   2 | ||||
|  | ||||
| @@ -72,7 +71,7 @@ typedef struct | ||||
| } usbh_dev0_t; | ||||
|  | ||||
| typedef struct { | ||||
|   // port | ||||
|   // port, must be same layout as usbh_dev0_t | ||||
|   uint8_t rhport; | ||||
|   uint8_t hub_addr; | ||||
|   uint8_t hub_port; | ||||
| @@ -87,10 +86,11 @@ typedef struct { | ||||
|   }; | ||||
|  | ||||
|   //------------- device descriptor -------------// | ||||
|   uint8_t  ep0_size; | ||||
|  | ||||
|   uint16_t vid; | ||||
|   uint16_t pid; | ||||
|  | ||||
|   uint8_t  ep0_size; | ||||
|   uint8_t  i_manufacturer; | ||||
|   uint8_t  i_product; | ||||
|   uint8_t  i_serial; | ||||
| @@ -101,8 +101,8 @@ typedef struct { | ||||
|   //------------- device -------------// | ||||
|   volatile uint8_t state;            // device state, value from enum tusbh_device_state_t | ||||
|  | ||||
|   uint8_t itf2drv[16];               // map interface number to driver (0xff is invalid) | ||||
|   uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) | ||||
|   uint8_t itf2drv[CFG_TUH_INTERFACE_MAX];  // map interface number to driver (0xff is invalid) | ||||
|   uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ) | ||||
|  | ||||
|   struct TU_ATTR_PACKED | ||||
|   { | ||||
| @@ -111,7 +111,7 @@ typedef struct { | ||||
|     volatile bool claimed : 1; | ||||
|  | ||||
|     // TODO merge ep2drv here, 4-bit should be sufficient | ||||
|   }ep_status[CFG_TUH_EP_MAX][2]; | ||||
|   }ep_status[CFG_TUH_ENDPOINT_MAX][2]; | ||||
|  | ||||
|   // Mutex for claiming endpoint, only needed when using with preempted RTOS | ||||
| #if CFG_TUSB_OS != OPT_OS_NONE | ||||
| @@ -249,7 +249,6 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid) | ||||
|   *vid = *pid = 0; | ||||
|  | ||||
|   TU_VERIFY(tuh_mounted(dev_addr)); | ||||
|  | ||||
|   usbh_device_t const* dev = get_device(dev_addr); | ||||
|  | ||||
|   *vid = dev->vid; | ||||
| @@ -273,6 +272,107 @@ void osal_task_delay(uint32_t msec) | ||||
| } | ||||
| #endif | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Descriptors | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) | ||||
| { | ||||
|   tusb_control_request_t const request = | ||||
|   { | ||||
|     .bmRequestType_bit = | ||||
|     { | ||||
|       .recipient = TUSB_REQ_RCPT_DEVICE, | ||||
|       .type      = TUSB_REQ_TYPE_STANDARD, | ||||
|       .direction = TUSB_DIR_IN | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_GET_DESCRIPTOR, | ||||
|     .wValue   = tu_htole16( TU_U16(type, index) ), | ||||
|     .wIndex   = 0, | ||||
|     .wLength  = tu_htole16(len) | ||||
|   }; | ||||
|  | ||||
|   TU_ASSERT( tuh_control_xfer(daddr, &request, buffer, complete_cb) ); | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) | ||||
| { | ||||
|   return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb); | ||||
| } | ||||
|  | ||||
| bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) | ||||
| { | ||||
|   return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb); | ||||
| } | ||||
|  | ||||
| bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t index, | ||||
|                                void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) | ||||
| { | ||||
|   tusb_control_request_t const request = | ||||
|   { | ||||
|     .bmRequestType_bit = | ||||
|     { | ||||
|       .recipient = TUSB_REQ_RCPT_DEVICE, | ||||
|       .type      = TUSB_REQ_TYPE_STANDARD, | ||||
|       .direction = TUSB_DIR_IN | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_GET_DESCRIPTOR, | ||||
|     .wValue   = tu_htole16( TU_U16(TUSB_DESC_STRING, index) ), | ||||
|     .wIndex   = tu_htole16(language_id), | ||||
|     .wLength  = tu_htole16(len) | ||||
|   }; | ||||
|  | ||||
|   TU_ASSERT( tuh_control_xfer(daddr, &request, buffer, complete_cb) ); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| // Get manufacturer string descriptor | ||||
| bool tuh_descriptor_string_manufacturer_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) | ||||
| { | ||||
|   TU_VERIFY(tuh_mounted(daddr)); | ||||
|   usbh_device_t const* dev = get_device(daddr); | ||||
|   return tuh_descriptor_string_get(daddr, language_id, dev->i_manufacturer, buffer, len, complete_cb); | ||||
| } | ||||
|  | ||||
| // Get product string descriptor | ||||
| bool tuh_descriptor_string_product_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) | ||||
| { | ||||
|   TU_VERIFY(tuh_mounted(daddr)); | ||||
|   usbh_device_t const* dev = get_device(daddr); | ||||
|   return tuh_descriptor_string_get(daddr, language_id, dev->i_product, buffer, len, complete_cb); | ||||
| } | ||||
|  | ||||
| // Get serial string descriptor | ||||
| bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb) | ||||
| { | ||||
|   TU_VERIFY(tuh_mounted(daddr)); | ||||
|   usbh_device_t const* dev = get_device(daddr); | ||||
|   return tuh_descriptor_string_get(daddr, language_id, dev->i_serial, buffer, len, complete_cb); | ||||
| } | ||||
|  | ||||
| bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_complete_cb_t complete_cb) | ||||
| { | ||||
|   TU_LOG2("Set Configuration = %d\r\n", config_num); | ||||
|   tusb_control_request_t const request = | ||||
|   { | ||||
|     .bmRequestType_bit = | ||||
|     { | ||||
|       .recipient = TUSB_REQ_RCPT_DEVICE, | ||||
|       .type      = TUSB_REQ_TYPE_STANDARD, | ||||
|       .direction = TUSB_DIR_OUT | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_SET_CONFIGURATION, | ||||
|     .wValue   = tu_htole16(config_num), | ||||
|     .wIndex   = 0, | ||||
|     .wLength  = 0 | ||||
|   }; | ||||
|  | ||||
|   TU_ASSERT( tuh_control_xfer(daddr, &request, NULL, complete_cb) ); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // CLASS-USBD API (don't require to verify parameters) | ||||
| //--------------------------------------------------------------------+ | ||||
| @@ -288,6 +388,7 @@ bool tuh_init(uint8_t rhport) | ||||
|   if (_usbh_initialized) return _usbh_initialized; | ||||
|  | ||||
|   TU_LOG2("USBH init\r\n"); | ||||
|   TU_LOG2_INT(sizeof(usbh_device_t)); | ||||
|  | ||||
|   tu_memclr(_usbh_devices, sizeof(_usbh_devices)); | ||||
|   tu_memclr(&_dev0, sizeof(_dev0)); | ||||
| @@ -561,6 +662,7 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port | ||||
|       tu_memclr(dev->ep_status, sizeof(dev->ep_status)); | ||||
|  | ||||
|       dev->state = TUSB_DEVICE_STATE_UNPLUG; | ||||
|       dev->configured = false; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -585,7 +687,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) | ||||
| { | ||||
|   usbh_device_t* dev = get_device(dev_addr); | ||||
|  | ||||
|   for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++) | ||||
|   for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) | ||||
|   { | ||||
|     // continue with next valid interface | ||||
|     // TODO skip IAD binding interface such as CDCs | ||||
| @@ -600,7 +702,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) | ||||
|   } | ||||
|  | ||||
|   // all interface are configured | ||||
|   if (itf_num == sizeof(dev->itf2drv)) | ||||
|   if (itf_num == CFG_TUH_INTERFACE_MAX) | ||||
|   { | ||||
|     // Invoke callback if available | ||||
|     if (tuh_mount_cb) tuh_mount_cb(dev_addr); | ||||
| @@ -609,7 +711,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Enumeration Process | ||||
| // is a lengthy process with a seires of control transfer to configure | ||||
| // is a lengthy process with a series of control transfer to configure | ||||
| // newly attached device. Each step is handled by a function in this | ||||
| // section | ||||
| // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating | ||||
| @@ -732,23 +834,10 @@ static bool enum_request_addr0_device_desc(void) | ||||
|   uint8_t const addr0 = 0; | ||||
|   TU_ASSERT( usbh_edpt_control_open(addr0, 8) ); | ||||
|  | ||||
|   //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// | ||||
|   // Get first 8 bytes of device descriptor for Control Endpoint size | ||||
|   TU_LOG2("Get 8 byte of Device Descriptor\r\n"); | ||||
|   tusb_control_request_t const request = | ||||
|   { | ||||
|     .bmRequestType_bit = | ||||
|     { | ||||
|       .recipient = TUSB_REQ_RCPT_DEVICE, | ||||
|       .type      = TUSB_REQ_TYPE_STANDARD, | ||||
|       .direction = TUSB_DIR_IN | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_GET_DESCRIPTOR, | ||||
|     .wValue   = TUSB_DESC_DEVICE << 8, | ||||
|     .wIndex   = 0, | ||||
|     .wLength  = 8 | ||||
|   }; | ||||
|   TU_ASSERT( tuh_control_xfer(addr0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) ); | ||||
|  | ||||
|   TU_ASSERT(tuh_descriptor_device_get(addr0, _usbh_ctrl_buf, 8, enum_get_addr0_device_desc_complete)); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| @@ -827,7 +916,7 @@ static bool enum_request_set_addr(void) | ||||
|       .direction = TUSB_DIR_OUT | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_SET_ADDRESS, | ||||
|     .wValue   = new_addr, | ||||
|     .wValue   = tu_htole16(new_addr), | ||||
|     .wIndex   = 0, | ||||
|     .wLength  = 0 | ||||
|   }; | ||||
| @@ -856,22 +945,8 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c | ||||
|  | ||||
|   // Get full device descriptor | ||||
|   TU_LOG2("Get Device Descriptor\r\n"); | ||||
|   tusb_control_request_t const new_request = | ||||
|   { | ||||
|     .bmRequestType_bit = | ||||
|     { | ||||
|       .recipient = TUSB_REQ_RCPT_DEVICE, | ||||
|       .type      = TUSB_REQ_TYPE_STANDARD, | ||||
|       .direction = TUSB_DIR_IN | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_GET_DESCRIPTOR, | ||||
|     .wValue   = TUSB_DESC_DEVICE << 8, | ||||
|     .wIndex   = 0, | ||||
|     .wLength  = sizeof(tusb_desc_device_t) | ||||
|   }; | ||||
|  | ||||
|   TU_ASSERT(tuh_control_xfer(new_addr, &new_request, _usbh_ctrl_buf, enum_get_device_desc_complete)); | ||||
|  | ||||
|   TU_ASSERT(tuh_descriptor_device_get(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), enum_get_device_desc_complete)); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| @@ -885,29 +960,16 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request | ||||
|  | ||||
|   dev->vid            = desc_device->idVendor; | ||||
|   dev->pid            = desc_device->idProduct; | ||||
|   dev->i_manufacturer = desc_device->iManufacturer; | ||||
|   dev->i_product      = desc_device->iProduct; | ||||
|   dev->i_serial       = desc_device->iSerialNumber; | ||||
| //  dev->i_manufacturer = desc_device->iManufacturer; | ||||
| //  dev->i_product      = desc_device->iProduct; | ||||
| //  dev->i_serial       = desc_device->iSerialNumber; | ||||
|  | ||||
| //  if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); | ||||
|  | ||||
|   TU_LOG2("Get 9 bytes of Configuration Descriptor\r\n"); | ||||
|   tusb_control_request_t const new_request = | ||||
|   { | ||||
|     .bmRequestType_bit = | ||||
|     { | ||||
|       .recipient = TUSB_REQ_RCPT_DEVICE, | ||||
|       .type      = TUSB_REQ_TYPE_STANDARD, | ||||
|       .direction = TUSB_DIR_IN | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_GET_DESCRIPTOR, | ||||
|     .wValue   = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), | ||||
|     .wIndex   = 0, | ||||
|     .wLength  = 9 | ||||
|   }; | ||||
|  | ||||
|   TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_9byte_config_desc_complete) ); | ||||
|  | ||||
|   // Get 9-byte for total length | ||||
|   uint8_t const config_idx = CONFIG_NUM - 1; | ||||
|   TU_LOG2("Get Configuration[0] Descriptor (9 bytes)\r\n"); | ||||
|   TU_ASSERT( tuh_descriptor_configuration_get(dev_addr, config_idx, _usbh_ctrl_buf, 9, enum_get_9byte_config_desc_complete) ); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| @@ -925,24 +987,9 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r | ||||
|   TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE); | ||||
|  | ||||
|   // Get full configuration descriptor | ||||
|   TU_LOG2("Get Configuration Descriptor\r\n"); | ||||
|   tusb_control_request_t const new_request = | ||||
|   { | ||||
|     .bmRequestType_bit = | ||||
|     { | ||||
|       .recipient = TUSB_REQ_RCPT_DEVICE, | ||||
|       .type      = TUSB_REQ_TYPE_STANDARD, | ||||
|       .direction = TUSB_DIR_IN | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_GET_DESCRIPTOR, | ||||
|     .wValue   = (TUSB_DESC_CONFIGURATION << 8) | (CONFIG_NUM - 1), | ||||
|     .wIndex   = 0, | ||||
|     .wLength  = total_len | ||||
|  | ||||
|   }; | ||||
|  | ||||
|   TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, _usbh_ctrl_buf, enum_get_config_desc_complete) ); | ||||
|  | ||||
|   uint8_t const config_idx = CONFIG_NUM - 1; | ||||
|   TU_LOG2("Get Configuration[0] Descriptor\r\n"); | ||||
|   TU_ASSERT( tuh_descriptor_configuration_get(dev_addr, config_idx, _usbh_ctrl_buf, total_len, enum_get_config_desc_complete) ); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| @@ -955,23 +1002,7 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request | ||||
|   // Driver open aren't allowed to make any usb transfer yet | ||||
|   TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) ); | ||||
|  | ||||
|   TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM); | ||||
|   tusb_control_request_t const new_request = | ||||
|   { | ||||
|     .bmRequestType_bit = | ||||
|     { | ||||
|       .recipient = TUSB_REQ_RCPT_DEVICE, | ||||
|       .type      = TUSB_REQ_TYPE_STANDARD, | ||||
|       .direction = TUSB_DIR_OUT | ||||
|     }, | ||||
|     .bRequest = TUSB_REQ_SET_CONFIGURATION, | ||||
|     .wValue   = CONFIG_NUM, | ||||
|     .wIndex   = 0, | ||||
|     .wLength  = 0 | ||||
|   }; | ||||
|  | ||||
|   TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, enum_set_config_complete) ); | ||||
|  | ||||
|   TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, enum_set_config_complete) ); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -38,7 +38,7 @@ | ||||
| // MACRO CONSTANT TYPEDEF | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); | ||||
| typedef bool (*tuh_control_complete_cb_t)(uint8_t daddr, tusb_control_request_t const * request, xfer_result_t result); | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // APPLICATION API | ||||
| @@ -57,29 +57,60 @@ void tuh_task(void); | ||||
| extern void hcd_int_handler(uint8_t rhport); | ||||
| #define tuh_int_handler   hcd_int_handler | ||||
|  | ||||
| bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid); | ||||
| tusb_speed_t tuh_speed_get(uint8_t dev_addr); | ||||
| bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid); | ||||
|  | ||||
| tusb_speed_t tuh_speed_get(uint8_t daddr); | ||||
|  | ||||
| // Check if device is connected and configured | ||||
| bool tuh_mounted(uint8_t dev_addr); | ||||
| bool tuh_mounted(uint8_t daddr); | ||||
|  | ||||
| // Check if device is suspended | ||||
| static inline bool tuh_suspended(uint8_t dev_addr) | ||||
| TU_ATTR_ALWAYS_INLINE | ||||
| static inline bool tuh_suspended(uint8_t daddr) | ||||
| { | ||||
|   // TODO implement suspend & resume on host | ||||
|   (void) dev_addr; | ||||
|   (void) daddr; | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| // Check if device is ready to communicate with | ||||
| TU_ATTR_ALWAYS_INLINE | ||||
| static inline bool tuh_ready(uint8_t dev_addr) | ||||
| static inline bool tuh_ready(uint8_t daddr) | ||||
| { | ||||
|   return tuh_mounted(dev_addr) && !tuh_suspended(dev_addr); | ||||
|   return tuh_mounted(daddr) && !tuh_suspended(daddr); | ||||
| } | ||||
|  | ||||
| // Carry out control transfer | ||||
| bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); | ||||
| bool tuh_control_xfer (uint8_t daddr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| // Set Configuration | ||||
| // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 | ||||
| bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| //------------- descriptors -------------// | ||||
|  | ||||
| // Get an descriptor | ||||
| bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, | ||||
|                         void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| // Get device descriptor | ||||
| bool tuh_descriptor_device_get(uint8_t daddr, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| // Get configuration descriptor | ||||
| bool tuh_descriptor_configuration_get(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| // Get string descriptor | ||||
| bool tuh_descriptor_string_get(uint8_t daddr, uint16_t language_id, uint8_t index, | ||||
|                                void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| // Get manufacturer string descriptor | ||||
| bool tuh_descriptor_string_manufacturer_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| // Get product string descriptor | ||||
| bool tuh_descriptor_string_product_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| // Get serial string descriptor | ||||
| bool tuh_descriptor_string_serial_get(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_control_complete_cb_t complete_cb); | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // APPLICATION CALLBACK | ||||
| @@ -87,10 +118,10 @@ bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, | ||||
| //TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); | ||||
|  | ||||
| // Invoked when device is mounted (configured) | ||||
| TU_ATTR_WEAK void tuh_mount_cb (uint8_t dev_addr); | ||||
| TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); | ||||
|  | ||||
| /// Invoked when device is unmounted (bus reset/unplugged) | ||||
| TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); | ||||
| TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
|   | ||||
| @@ -35,6 +35,7 @@ | ||||
| // INCLUDE | ||||
| //--------------------------------------------------------------------+ | ||||
| #include "common/tusb_common.h" | ||||
| #include "host/hcd.h" | ||||
| #include "portable/ehci/ehci_api.h" | ||||
| #include "ci_hs_type.h" | ||||
|  | ||||
|   | ||||
| @@ -58,6 +58,9 @@ | ||||
|  | ||||
| #define FRAMELIST_SIZE                  (1024 >> FRAMELIST_SIZE_BIT_VALUE) | ||||
|  | ||||
| #define QHD_MAX      (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX) | ||||
| #define QTD_MAX      QHD_MAX | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   ehci_link_t period_framelist[FRAMELIST_SIZE]; | ||||
| @@ -73,8 +76,8 @@ typedef struct | ||||
|     ehci_qtd_t qtd; | ||||
|   }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1]; | ||||
|  | ||||
|   ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; | ||||
|   ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); | ||||
|   ehci_qhd_t qhd_pool[QHD_MAX]; | ||||
|   ehci_qtd_t qtd_pool[QTD_MAX] TU_ATTR_ALIGNED(32); | ||||
|  | ||||
|   ehci_registers_t* regs; | ||||
|  | ||||
| @@ -189,7 +192,11 @@ static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) | ||||
|       prev = list_next(prev) ) | ||||
|   { | ||||
|     // TODO check type for ISO iTD and siTD | ||||
|     // TODO Suppress cast-align warning | ||||
|     #pragma GCC diagnostic push | ||||
|     #pragma GCC diagnostic ignored "-Wcast-align" | ||||
|     ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev); | ||||
|     #pragma GCC diagnostic pop | ||||
|     if ( qhd->dev_addr == dev_addr ) | ||||
|     { | ||||
|       // TODO deactive all TD, wait for QHD to inactive before removal | ||||
| @@ -474,7 +481,7 @@ static void async_advance_isr(uint8_t rhport) | ||||
|   (void) rhport; | ||||
|  | ||||
|   ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; | ||||
|   for(uint32_t i = 0; i < HCD_MAX_ENDPOINT; i++) | ||||
|   for(uint32_t i = 0; i < QHD_MAX; i++) | ||||
|   { | ||||
|     if ( qhd_pool[i].removing ) | ||||
|     { | ||||
| @@ -542,7 +549,7 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint32_t interval_ms) | ||||
|   // TODO abstract max loop guard for period | ||||
|   while( !next_item.terminate && | ||||
|       !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && | ||||
|       max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX) | ||||
|       max_loop < (QHD_MAX + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX) | ||||
|   { | ||||
|     switch ( next_item.type ) | ||||
|     { | ||||
| @@ -714,7 +721,7 @@ void hcd_int_handler(uint8_t rhport) | ||||
| //------------- queue head helper -------------// | ||||
| static inline ehci_qhd_t* qhd_find_free (void) | ||||
| { | ||||
|   for (uint32_t i=0; i<HCD_MAX_ENDPOINT; i++) | ||||
|   for (uint32_t i=0; i<QHD_MAX; i++) | ||||
|   { | ||||
|     if ( !ehci_data.qhd_pool[i].used ) return &ehci_data.qhd_pool[i]; | ||||
|   } | ||||
| @@ -731,7 +738,7 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) | ||||
| { | ||||
|   ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; | ||||
|  | ||||
|   for(uint32_t i=0; i<HCD_MAX_ENDPOINT; i++) | ||||
|   for(uint32_t i=0; i<QHD_MAX; i++) | ||||
|   { | ||||
|     if ( (qhd_pool[i].dev_addr == dev_addr) && | ||||
|           ep_addr == tu_edpt_addr(qhd_pool[i].ep_number, qhd_pool[i].pid) ) | ||||
| @@ -746,7 +753,7 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) | ||||
| //------------- TD helper -------------// | ||||
| static inline ehci_qtd_t* qtd_find_free(void) | ||||
| { | ||||
|   for (uint32_t i=0; i<HCD_MAX_XFER; i++) | ||||
|   for (uint32_t i=0; i<QTD_MAX; i++) | ||||
|   { | ||||
|     if ( !ehci_data.qtd_pool[i].used ) return &ehci_data.qtd_pool[i]; | ||||
|   } | ||||
|   | ||||
| @@ -101,8 +101,8 @@ typedef struct | ||||
|  | ||||
| 	// Word 2: qTQ Token | ||||
| 	volatile uint32_t ping_err             : 1  ; ///< For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator | ||||
| 	volatile uint32_t non_hs_split_state   : 1  ; ///< Used by HC to track the state of slipt transaction | ||||
| 	volatile uint32_t non_hs_missed_uframe : 1  ; ///< HC misses a complete slip transaction | ||||
| 	volatile uint32_t non_hs_split_state   : 1  ; ///< Used by HC to track the state of split transaction | ||||
| 	volatile uint32_t non_hs_missed_uframe : 1  ; ///< HC misses a complete split transaction | ||||
| 	volatile uint32_t xact_err             : 1  ; ///< Error (Timeout, CRC, Bad PID ... ) | ||||
| 	volatile uint32_t babble_err           : 1  ; ///< Babble detected, also set Halted bit to 1 | ||||
| 	volatile uint32_t buffer_err           : 1  ; ///< Data overrun/underrun error | ||||
|   | ||||
| @@ -125,7 +125,7 @@ typedef struct | ||||
|     uint16_t            bda[2*2]; | ||||
|   }; | ||||
|   endpoint_state_t endpoint[2]; | ||||
|   pipe_state_t pipe[HCD_MAX_XFER * 2]; | ||||
|   pipe_state_t pipe[CFG_TUH_ENDPOINT_MAX * 2]; | ||||
|   uint32_t     in_progress; /* Bitmap. Each bit indicates that a transfer of the corresponding pipe is in progress */ | ||||
|   uint32_t     pending;     /* Bitmap. Each bit indicates that a transfer of the corresponding pipe will be resume the next frame */ | ||||
|   bool         need_reset;  /* The device has not been reset after connection. */ | ||||
| @@ -142,7 +142,7 @@ int find_pipe(uint8_t dev_addr, uint8_t ep_addr) | ||||
| { | ||||
|   /* Find the target pipe */ | ||||
|   int num; | ||||
|   for (num = 0; num < HCD_MAX_XFER * 2; ++num) { | ||||
|   for (num = 0; num < CFG_TUH_ENDPOINT_MAX * 2; ++num) { | ||||
|     pipe_state_t *p = &_hcd.pipe[num]; | ||||
|     if ((p->dev_addr == dev_addr) && (p->ep_addr == ep_addr)) | ||||
|       return num; | ||||
| @@ -463,7 +463,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) | ||||
|   const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); | ||||
|   NVIC_DisableIRQ(USB0_IRQn); | ||||
|   pipe_state_t *p   = &_hcd.pipe[0]; | ||||
|   pipe_state_t *end = &_hcd.pipe[HCD_MAX_XFER * 2]; | ||||
|   pipe_state_t *end = &_hcd.pipe[CFG_TUH_ENDPOINT_MAX * 2]; | ||||
|   for (;p != end; ++p) { | ||||
|     if (p->dev_addr == dev_addr) | ||||
|       tu_memclr(p, sizeof(*p)); | ||||
| @@ -511,7 +511,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const | ||||
|   // TU_LOG1("O %u %x\n", dev_addr, ep_addr); | ||||
|   /* Find a free pipe */ | ||||
|   pipe_state_t *p = &_hcd.pipe[0]; | ||||
|   pipe_state_t *end = &_hcd.pipe[HCD_MAX_XFER * 2]; | ||||
|   pipe_state_t *end = &_hcd.pipe[CFG_TUH_ENDPOINT_MAX * 2]; | ||||
|   if (dev_addr || ep_addr) { | ||||
|     p += 2; | ||||
|     for (; p < end && (p->dev_addr || p->ep_addr); ++p) ; | ||||
|   | ||||
| @@ -313,7 +313,7 @@ static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) | ||||
|  | ||||
|   ohci_ed_t* ed_pool = ohci_data.ed_pool; | ||||
|  | ||||
|   for(uint32_t i=0; i<HCD_MAX_ENDPOINT; i++) | ||||
|   for(uint32_t i=0; i<ED_MAX; i++) | ||||
|   { | ||||
|     if ( (ed_pool[i].dev_addr == dev_addr) && | ||||
|           ep_addr == tu_edpt_addr(ed_pool[i].ep_number, ed_pool[i].pid == PID_IN) ) | ||||
| @@ -329,7 +329,7 @@ static ohci_ed_t * ed_find_free(void) | ||||
| { | ||||
|   ohci_ed_t* ed_pool = ohci_data.ed_pool; | ||||
|  | ||||
|   for(uint8_t i = 0; i < HCD_MAX_ENDPOINT; i++) | ||||
|   for(uint8_t i = 0; i < ED_MAX; i++) | ||||
|   { | ||||
|     if ( !ed_pool[i].used ) return &ed_pool[i]; | ||||
|   } | ||||
| @@ -368,7 +368,7 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) | ||||
|  | ||||
| static ohci_gtd_t * gtd_find_free(void) | ||||
| { | ||||
|   for(uint8_t i=0; i < HCD_MAX_XFER; i++) | ||||
|   for(uint8_t i=0; i < GTD_MAX; i++) | ||||
|   { | ||||
|     if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; | ||||
|   } | ||||
|   | ||||
| @@ -42,6 +42,9 @@ enum { | ||||
|   OHCI_MAX_ITD = 4 | ||||
| }; | ||||
|  | ||||
| #define ED_MAX       (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX) | ||||
| #define GTD_MAX      ED_MAX | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // OHCI Data Structure | ||||
| //--------------------------------------------------------------------+ | ||||
| @@ -162,8 +165,8 @@ typedef struct TU_ATTR_ALIGNED(256) | ||||
|   }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1]; | ||||
|  | ||||
|   //  ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32 | ||||
|   ohci_ed_t ed_pool[HCD_MAX_ENDPOINT]; | ||||
|   ohci_gtd_t gtd_pool[HCD_MAX_XFER]; | ||||
|   ohci_ed_t ed_pool[ED_MAX]; | ||||
|   ohci_gtd_t gtd_pool[GTD_MAX]; | ||||
|  | ||||
|   volatile uint16_t frame_number_hi; | ||||
|  | ||||
|   | ||||
| @@ -58,8 +58,12 @@ void rp2040_usb_init(void) | ||||
|   unreset_block_wait(RESETS_RESET_USBCTRL_BITS); | ||||
|  | ||||
|   // Clear any previous state just in case | ||||
|   // TODO Suppress warning array-bounds with gcc11 | ||||
| #pragma GCC diagnostic push | ||||
| #pragma GCC diagnostic ignored "-Warray-bounds" | ||||
|   memset(usb_hw, 0, sizeof(*usb_hw)); | ||||
|   memset(usb_dpram, 0, sizeof(*usb_dpram)); | ||||
| #pragma GCC diagnostic pop | ||||
|  | ||||
|   // Mux the controller to the onboard usb phy | ||||
|   usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Ha Thach
					Ha Thach