usbd_cdc.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /**
  2. * @file usbd_cdc.c
  3. * @brief
  4. *
  5. * Copyright (c) 2022 sakumisu
  6. *
  7. * Licensed to the Apache Software Foundation (ASF) under one or more
  8. * contributor license agreements. See the NOTICE file distributed with
  9. * this work for additional information regarding copyright ownership. The
  10. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  11. * "License"); you may not use this file except in compliance with the
  12. * License. You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  18. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  19. * License for the specific language governing permissions and limitations
  20. * under the License.
  21. *
  22. */
  23. #include "usbd_core.h"
  24. #include "usbd_cdc.h"
  25. const char *stop_name[] = { "1", "1.5", "2" };
  26. const char *parity_name[] = { "N", "O", "E", "M", "S" };
  27. /* Device data structure */
  28. struct usbd_cdc {
  29. struct cdc_line_coding line_coding;
  30. bool dtr;
  31. bool rts;
  32. uint8_t intf_num;
  33. usb_slist_t list;
  34. };
  35. static usb_slist_t usbd_cdc_head = USB_SLIST_OBJECT_INIT(usbd_cdc_head);
  36. #ifndef CONFIG_USBDEV_CDC_ACM_UART
  37. struct usbd_cdc g_usbd_cdc_acm_class;
  38. static void usbd_cdc_acm_reset(void)
  39. {
  40. memset(&g_usbd_cdc_acm_class, 0, sizeof(struct usbd_cdc));
  41. g_usbd_cdc_acm_class.line_coding.dwDTERate = 2000000;
  42. g_usbd_cdc_acm_class.line_coding.bDataBits = 8;
  43. g_usbd_cdc_acm_class.line_coding.bParityType = 0;
  44. g_usbd_cdc_acm_class.line_coding.bCharFormat = 0;
  45. }
  46. #endif
  47. /**
  48. * @brief Handler called for Class requests not handled by the USB stack.
  49. *
  50. * @param setup Information about the request to execute.
  51. * @param len Size of the buffer.
  52. * @param data Buffer containing the request result.
  53. *
  54. * @return 0 on success, negative errno code on fail.
  55. */
  56. static int cdc_acm_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
  57. {
  58. USB_LOG_DBG("CDC Class request: "
  59. "bRequest 0x%02x\r\n",
  60. setup->bRequest);
  61. struct usbd_cdc *current_cdc_acm_class = NULL;
  62. uint8_t intf = LO_BYTE(setup->wIndex);
  63. #ifdef CONFIG_USBDEV_CDC_ACM_UART
  64. usb_slist_t *i;
  65. usb_slist_for_each(i, &usbd_cdc_head)
  66. {
  67. struct usbd_cdc *cdc_acm_class = usb_slist_entry(i, struct usbd_cdc, list);
  68. if (cdc_acm_class->intf_num == intf) {
  69. current_cdc_acm_class = cdc_acm_class;
  70. break;
  71. }
  72. }
  73. if (current_cdc_acm_class == NULL) {
  74. return -2;
  75. }
  76. #else
  77. current_cdc_acm_class = &g_usbd_cdc_acm_class;
  78. #endif
  79. switch (setup->bRequest) {
  80. case CDC_REQUEST_SET_LINE_CODING:
  81. /*******************************************************************************/
  82. /* Line Coding Structure */
  83. /*-----------------------------------------------------------------------------*/
  84. /* Offset | Field | Size | Value | Description */
  85. /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
  86. /* 4 | bCharFormat | 1 | Number | Stop bits */
  87. /* 0 - 1 Stop bit */
  88. /* 1 - 1.5 Stop bits */
  89. /* 2 - 2 Stop bits */
  90. /* 5 | bParityType | 1 | Number | Parity */
  91. /* 0 - None */
  92. /* 1 - Odd */
  93. /* 2 - Even */
  94. /* 3 - Mark */
  95. /* 4 - Space */
  96. /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
  97. /*******************************************************************************/
  98. memcpy(&current_cdc_acm_class->line_coding, *data, setup->wLength);
  99. USB_LOG_DBG("Set intf:%d linecoding <%d %d %s %s>\r\n",
  100. current_cdc_acm_class->line_coding.dwDTERate,
  101. current_cdc_acm_class->line_coding.bDataBits,
  102. parity_name[current_cdc_acm_class->line_coding.bParityType],
  103. stop_name[current_cdc_acm_class->line_coding.bCharFormat]);
  104. usbd_cdc_acm_set_line_coding(intf, current_cdc_acm_class->line_coding.dwDTERate, current_cdc_acm_class->line_coding.bDataBits,
  105. current_cdc_acm_class->line_coding.bParityType, current_cdc_acm_class->line_coding.bCharFormat);
  106. break;
  107. case CDC_REQUEST_SET_CONTROL_LINE_STATE: {
  108. current_cdc_acm_class->dtr = (setup->wValue & 0x0001);
  109. current_cdc_acm_class->rts = (setup->wValue & 0x0002);
  110. USB_LOG_DBG("Set intf:%d DTR 0x%x,RTS 0x%x\r\n",
  111. current_cdc_acm_class->dtr, current_cdc_acm_class->rts);
  112. usbd_cdc_acm_set_dtr(intf, current_cdc_acm_class->dtr);
  113. usbd_cdc_acm_set_rts(intf, current_cdc_acm_class->rts);
  114. } break;
  115. case CDC_REQUEST_GET_LINE_CODING:
  116. *data = (uint8_t *)(&current_cdc_acm_class->line_coding);
  117. *len = 7;
  118. USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
  119. current_cdc_acm_class->line_coding.dwDTERate,
  120. current_cdc_acm_class->line_coding.bCharFormat,
  121. current_cdc_acm_class->line_coding.bParityType,
  122. current_cdc_acm_class->line_coding.bDataBits);
  123. break;
  124. default:
  125. USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
  126. return -1;
  127. }
  128. return 0;
  129. }
  130. static void cdc_notify_handler(uint8_t event, void *arg)
  131. {
  132. switch (event) {
  133. case USBD_EVENT_RESET:
  134. #ifndef CONFIG_USBDEV_CDC_ACM_UART
  135. usbd_cdc_acm_reset();
  136. #endif
  137. break;
  138. default:
  139. break;
  140. }
  141. }
  142. int usbd_cdc_acm_alloc(uint8_t intf)
  143. {
  144. struct usbd_cdc *cdc_acm_class = usb_malloc(sizeof(struct usbd_cdc));
  145. if (cdc_acm_class == NULL) {
  146. USB_LOG_ERR("no memory to alloc for cdc_acm_class\r\n");
  147. return -1;
  148. }
  149. memset(cdc_acm_class, 0, sizeof(struct usbd_cdc));
  150. cdc_acm_class->line_coding.dwDTERate = 2000000;
  151. cdc_acm_class->line_coding.bDataBits = 8;
  152. cdc_acm_class->line_coding.bParityType = 0;
  153. cdc_acm_class->line_coding.bCharFormat = 0;
  154. cdc_acm_class->intf_num = intf;
  155. usb_slist_add_tail(&usbd_cdc_head, &cdc_acm_class->list);
  156. return 0;
  157. }
  158. void usbd_cdc_add_acm_interface(usbd_class_t *devclass, usbd_interface_t *intf)
  159. {
  160. static usbd_class_t *last_class = NULL;
  161. if (last_class != devclass) {
  162. last_class = devclass;
  163. usbd_class_register(devclass);
  164. }
  165. intf->class_handler = cdc_acm_class_request_handler;
  166. intf->custom_handler = NULL;
  167. intf->vendor_handler = NULL;
  168. intf->notify_handler = cdc_notify_handler;
  169. usbd_class_add_interface(devclass, intf);
  170. #ifdef CONFIG_USBDEV_CDC_ACM_UART
  171. usbd_cdc_acm_alloc(intf->intf_num);
  172. #endif
  173. }
  174. __WEAK void usbd_cdc_acm_set_line_coding(uint8_t intf, uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits)
  175. {
  176. }
  177. __WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
  178. {
  179. }
  180. __WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
  181. {
  182. }