usb_helpers.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdint.h>
  7. #include <stdbool.h>
  8. #include <stdlib.h>
  9. #include <assert.h>
  10. #include "usb/usb_helpers.h"
  11. #include "usb/usb_types_ch9.h"
  12. // ---------------------------------------- Configuration Descriptor Parsing -------------------------------------------
  13. const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset)
  14. {
  15. assert(cur_desc != NULL && offset != NULL);
  16. if (*offset >= wTotalLength) {
  17. return NULL; //We have traversed the entire configuration descriptor
  18. }
  19. if (*offset + cur_desc->bLength >= wTotalLength) {
  20. return NULL; //Next descriptor is out of bounds
  21. }
  22. //Return the next descriptor, update offset
  23. const usb_standard_desc_t *ret_desc = (const usb_standard_desc_t *)(((uint32_t)cur_desc) + cur_desc->bLength);
  24. *offset += cur_desc->bLength;
  25. return ret_desc;
  26. }
  27. const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset)
  28. {
  29. assert(cur_desc != NULL && offset != NULL);
  30. int offset_temp = *offset; //We only want to update offset if we've actually found a descriptor
  31. //Keep stepping over descriptors until we find one of bDescriptorType or until we go out of bounds
  32. const usb_standard_desc_t *ret_desc = usb_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp);
  33. while (ret_desc != NULL) {
  34. if (ret_desc->bDescriptorType == bDescriptorType) {
  35. break;
  36. }
  37. ret_desc = usb_parse_next_descriptor(ret_desc, wTotalLength, &offset_temp);
  38. }
  39. if (ret_desc != NULL) {
  40. //We've found a descriptor. Update the offset
  41. *offset = offset_temp;
  42. }
  43. return ret_desc;
  44. }
  45. int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber)
  46. {
  47. assert(config_desc != NULL);
  48. int offset = 0;
  49. //Find the first interface descriptor of bInterfaceNumber
  50. const usb_intf_desc_t *first_intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, 0, &offset);
  51. if (first_intf_desc == NULL) {
  52. return -1; //bInterfaceNumber not found
  53. }
  54. int num_alt_setting = 0;
  55. const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)first_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset);
  56. while (next_intf_desc != NULL) {
  57. if (next_intf_desc->bInterfaceNumber != bInterfaceNumber) {
  58. break;
  59. }
  60. num_alt_setting++;
  61. next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset);
  62. }
  63. return num_alt_setting;
  64. }
  65. const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset)
  66. {
  67. assert(config_desc != NULL);
  68. if (bInterfaceNumber >= config_desc->bNumInterfaces) {
  69. return NULL; //bInterfaceNumber is out of range
  70. }
  71. //Walk to first interface descriptor of bInterfaceNumber
  72. int offset_temp = 0;
  73. const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)config_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
  74. while (next_intf_desc != NULL) {
  75. if (next_intf_desc->bInterfaceNumber == bInterfaceNumber) {
  76. break; //We found the first interface descriptor with matching bInterfaceNumber
  77. }
  78. next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
  79. }
  80. if (next_intf_desc == NULL) {
  81. return NULL; //Couldn't find a interface with bInterfaceNumber
  82. }
  83. //Keep walking until an interface descriptor matching bInterfaceNumber and bAlternateSetting is found
  84. while (next_intf_desc != NULL) {
  85. if (next_intf_desc->bInterfaceNumber == bInterfaceNumber + 1) {
  86. //We've walked past our target bInterfaceNumber
  87. next_intf_desc = NULL;
  88. break;
  89. }
  90. if (next_intf_desc->bAlternateSetting == bAlternateSetting) {
  91. //We've found our target interface descriptor
  92. break;
  93. }
  94. //Get the next interface descriptor
  95. next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
  96. }
  97. if (next_intf_desc != NULL && offset != NULL) {
  98. *offset = offset_temp;
  99. }
  100. return next_intf_desc;
  101. }
  102. const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset)
  103. {
  104. assert(intf_desc != NULL && offset != NULL);
  105. if (index >= intf_desc->bNumEndpoints) {
  106. return NULL; //Index is out of range
  107. }
  108. //Walk to the Nth endpoint descriptor we find
  109. int offset_temp = *offset;
  110. bool ep_found = true;
  111. const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)intf_desc;
  112. for (int i = 0; i <= index; i++) {
  113. next_desc = usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_desc, wTotalLength, USB_B_DESCRIPTOR_TYPE_ENDPOINT, &offset_temp);
  114. if (next_desc == NULL) {
  115. ep_found = false;
  116. break;
  117. }
  118. }
  119. if (ep_found) {
  120. *offset = offset_temp;
  121. return (const usb_ep_desc_t *)next_desc;
  122. }
  123. return NULL;
  124. }
  125. const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset)
  126. {
  127. assert(config_desc != NULL);
  128. //Find the interface descriptor
  129. int offset_intf;
  130. const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf);
  131. if (intf_desc == NULL) {
  132. return NULL;
  133. }
  134. //Walk endpoint descriptors until one matching bEndpointAddress is found
  135. int offset_ep;
  136. bool ep_found = false;
  137. const usb_ep_desc_t *ep_desc = NULL;
  138. for (int index = 0; index < intf_desc->bNumEndpoints; index++) {
  139. offset_ep = offset_intf;
  140. ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, index, config_desc->wTotalLength, &offset_ep);
  141. if (ep_desc == NULL) {
  142. break;
  143. }
  144. if (ep_desc->bEndpointAddress == bEndpointAddress) {
  145. ep_found = true;
  146. break;
  147. }
  148. }
  149. if (ep_found && offset != NULL) {
  150. *offset = offset_ep;
  151. }
  152. return ep_desc;
  153. }
  154. // ------------------------------------------------------ Misc ---------------------------------------------------------