mtp_template.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * Copyright (c) 2025 sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. */
  7. #include "usbd_core.h"
  8. #include "usbd_mtp.h"
  9. #if 1
  10. #error "commercial charge"
  11. #endif
  12. #ifndef CONFIG_USBDEV_MTP_THREAD
  13. #warning mtp depends on filesystem, suggest to enable CONFIG_USBDEV_MTP_THREAD
  14. #endif
  15. #define WCID_VENDOR_CODE 0x01
  16. __ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
  17. ///////////////////////////////////////
  18. /// MS OS string descriptor
  19. ///////////////////////////////////////
  20. 0x12, /* bLength */
  21. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  22. /* MSFT100 */
  23. 'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
  24. '1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
  25. WCID_VENDOR_CODE, /* bVendorCode */
  26. 0x00, /* bReserved */
  27. };
  28. __ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
  29. ///////////////////////////////////////
  30. /// WCID descriptor
  31. ///////////////////////////////////////
  32. 0x28, 0x00, 0x00, 0x00, /* dwLength */
  33. 0x00, 0x01, /* bcdVersion */
  34. 0x04, 0x00, /* wIndex */
  35. 0x01, /* bCount */
  36. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
  37. ///////////////////////////////////////
  38. /// WCID function descriptor
  39. ///////////////////////////////////////
  40. 0x00, /* bFirstInterfaceNumber */
  41. 0x01, /* bReserved */
  42. /* MTP */
  43. 'M', 'T', 'P', 0x00, 0x00, 0x00, 0x00, 0x00, /* cCID_8 */
  44. /* */
  45. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
  46. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
  47. };
  48. __ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
  49. ///////////////////////////////////////
  50. /// WCID property descriptor
  51. ///////////////////////////////////////
  52. 0x8e, 0x00, 0x00, 0x00, /* dwLength */
  53. 0x00, 0x01, /* bcdVersion */
  54. 0x05, 0x00, /* wIndex */
  55. 0x01, 0x00, /* wCount */
  56. ///////////////////////////////////////
  57. /// registry propter descriptor
  58. ///////////////////////////////////////
  59. 0x84, 0x00, 0x00, 0x00, /* dwSize */
  60. 0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
  61. 0x28, 0x00, /* wPropertyNameLength */
  62. /* DeviceInterfaceGUID */
  63. 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
  64. 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
  65. 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
  66. 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
  67. 'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
  68. 0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
  69. /* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
  70. '{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
  71. 'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
  72. '5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
  73. '4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
  74. '8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
  75. 'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
  76. '-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
  77. 'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
  78. 'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
  79. '6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
  80. };
  81. const uint8_t bos_descriptor[] = {
  82. 0x05, 0x0f, 0x16, 0x00, 0x02,
  83. 0x07, 0x10, 0x02, 0x06, 0x00, 0x00, 0x00,
  84. 0x0a, 0x10, 0x03, 0x00, 0x0f, 0x00, 0x01, 0x01, 0xf4, 0x01
  85. };
  86. /*!< endpoint address */
  87. #define MTP_IN_EP 0x81
  88. #define MTP_OUT_EP 0x02
  89. #define MTP_INT_EP 0x83
  90. /*!< config descriptor size */
  91. #define USB_CONFIG_SIZE (9 + MTP_DESCRIPTOR_LEN)
  92. static const uint8_t device_descriptor[] = {
  93. USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0201, 0x01)
  94. };
  95. static const uint8_t config_descriptor_hs[] = {
  96. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  97. MTP_DESCRIPTOR_INIT(0x00, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP, USB_BULK_EP_MPS_HS, 0x02),
  98. };
  99. static const uint8_t config_descriptor_fs[] = {
  100. USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  101. MTP_DESCRIPTOR_INIT(0x00, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP, USB_BULK_EP_MPS_FS, 0x02),
  102. };
  103. static const uint8_t device_quality_descriptor[] = {
  104. USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, 0x01),
  105. };
  106. static const uint8_t other_speed_config_descriptor_hs[] = {
  107. USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  108. MTP_DESCRIPTOR_INIT(0x00, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP, USB_BULK_EP_MPS_FS, 0x02),
  109. };
  110. static const uint8_t other_speed_config_descriptor_fs[] = {
  111. USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  112. MTP_DESCRIPTOR_INIT(0x00, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP, USB_BULK_EP_MPS_HS, 0x02),
  113. };
  114. static const char *string_descriptors[] = {
  115. (const char[]){ 0x09, 0x04 }, /* Langid */
  116. "CherryUSB", /* Manufacturer */
  117. "CherryUSB MTP DEMO", /* Product */
  118. "2025053000", /* Serial Number */
  119. };
  120. static const uint8_t *device_descriptor_callback(uint8_t speed)
  121. {
  122. (void)speed;
  123. return device_descriptor;
  124. }
  125. static const uint8_t *config_descriptor_callback(uint8_t speed)
  126. {
  127. if (speed == USB_SPEED_HIGH) {
  128. return config_descriptor_hs;
  129. } else if (speed == USB_SPEED_FULL) {
  130. return config_descriptor_fs;
  131. } else {
  132. return NULL;
  133. }
  134. }
  135. static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
  136. {
  137. (void)speed;
  138. return device_quality_descriptor;
  139. }
  140. static const uint8_t *other_speed_config_descriptor_callback(uint8_t speed)
  141. {
  142. if (speed == USB_SPEED_HIGH) {
  143. return other_speed_config_descriptor_hs;
  144. } else if (speed == USB_SPEED_FULL) {
  145. return other_speed_config_descriptor_fs;
  146. } else {
  147. return NULL;
  148. }
  149. }
  150. static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
  151. {
  152. (void)speed;
  153. if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
  154. return NULL;
  155. }
  156. return string_descriptors[index];
  157. }
  158. const uint8_t *WINUSB_IFx_WCIDProperties[] = {
  159. WINUSB_IF0_WCIDProperties,
  160. };
  161. struct usb_msosv1_descriptor msosv1_desc = {
  162. .string = WCID_StringDescriptor_MSOS,
  163. .vendor_code = WCID_VENDOR_CODE,
  164. .compat_id = WINUSB_WCIDDescriptor,
  165. .comp_id_property = WINUSB_IFx_WCIDProperties,
  166. };
  167. const struct usb_bos_descriptor bos_desc = {
  168. .string = bos_descriptor,
  169. .string_len = 22
  170. };
  171. const struct usb_descriptor mtp_descriptor = {
  172. .device_descriptor_callback = device_descriptor_callback,
  173. .config_descriptor_callback = config_descriptor_callback,
  174. .device_quality_descriptor_callback = device_quality_descriptor_callback,
  175. .other_speed_descriptor_callback = other_speed_config_descriptor_callback,
  176. .string_descriptor_callback = string_descriptor_callback,
  177. .bos_descriptor = &bos_desc,
  178. .msosv1_descriptor = &msosv1_desc,
  179. };
  180. static void usbd_event_handler(uint8_t busid, uint8_t event)
  181. {
  182. switch (event) {
  183. case USBD_EVENT_RESET:
  184. break;
  185. case USBD_EVENT_CONNECTED:
  186. break;
  187. case USBD_EVENT_DISCONNECTED:
  188. break;
  189. case USBD_EVENT_RESUME:
  190. break;
  191. case USBD_EVENT_SUSPEND:
  192. break;
  193. case USBD_EVENT_CONFIGURED:
  194. break;
  195. case USBD_EVENT_SET_REMOTE_WAKEUP:
  196. break;
  197. case USBD_EVENT_CLR_REMOTE_WAKEUP:
  198. break;
  199. default:
  200. break;
  201. }
  202. }
  203. static struct usbd_interface intf0;
  204. extern void usbd_mtp_mount();
  205. void mtp_init(uint8_t busid, uint32_t reg_base)
  206. {
  207. usbd_mtp_mount();
  208. usbd_desc_register(busid, &mtp_descriptor);
  209. usbd_add_interface(busid, usbd_mtp_init_intf(&intf0, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP));
  210. usbd_initialize(busid, reg_base, usbd_event_handler);
  211. }