1 /*
2 * Copyright (c) 2022, sakumisu
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "usbd_core.h"
7 #include "usbd_cdc_acm.h"
8
9 const char *stop_name[] = { "1", "1.5", "2" };
10 const char *parity_name[] = { "N", "O", "E", "M", "S" };
11
cdc_acm_class_interface_request_handler(uint8_t busid,struct usb_setup_packet * setup,uint8_t ** data,uint32_t * len)12 static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
13 {
14 USB_LOG_DBG("CDC Class request: "
15 "bRequest 0x%02x\r\n",
16 setup->bRequest);
17
18 struct cdc_line_coding line_coding;
19 bool dtr, rts;
20 uint8_t intf_num = LO_BYTE(setup->wIndex);
21
22 switch (setup->bRequest) {
23 case CDC_REQUEST_SET_LINE_CODING:
24
25 /*******************************************************************************/
26 /* Line Coding Structure */
27 /*-----------------------------------------------------------------------------*/
28 /* Offset | Field | Size | Value | Description */
29 /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
30 /* 4 | bCharFormat | 1 | Number | Stop bits */
31 /* 0 - 1 Stop bit */
32 /* 1 - 1.5 Stop bits */
33 /* 2 - 2 Stop bits */
34 /* 5 | bParityType | 1 | Number | Parity */
35 /* 0 - None */
36 /* 1 - Odd */
37 /* 2 - Even */
38 /* 3 - Mark */
39 /* 4 - Space */
40 /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
41 /*******************************************************************************/
42 memcpy(&line_coding, *data, setup->wLength);
43 USB_LOG_DBG("Set intf:%d linecoding <%d %d %s %s>\r\n",
44 intf_num,
45 (unsigned int)line_coding.dwDTERate,
46 line_coding.bDataBits,
47 parity_name[line_coding.bParityType],
48 stop_name[line_coding.bCharFormat]);
49
50 usbd_cdc_acm_set_line_coding(busid, intf_num, &line_coding);
51 break;
52
53 case CDC_REQUEST_SET_CONTROL_LINE_STATE:
54 dtr = (setup->wValue & 0x0001);
55 rts = (setup->wValue & 0x0002);
56 USB_LOG_DBG("Set intf:%d DTR 0x%x,RTS 0x%x\r\n",
57 intf_num,
58 dtr,
59 rts);
60 usbd_cdc_acm_set_dtr(busid, intf_num, dtr);
61 usbd_cdc_acm_set_rts(busid, intf_num, rts);
62 break;
63
64 case CDC_REQUEST_GET_LINE_CODING:
65 usbd_cdc_acm_get_line_coding(busid, intf_num, &line_coding);
66 memcpy(*data, &line_coding, 7);
67 *len = 7;
68 USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
69 intf_num,
70 (unsigned int)line_coding.dwDTERate,
71 line_coding.bCharFormat,
72 line_coding.bParityType,
73 line_coding.bDataBits);
74 break;
75 case CDC_REQUEST_SEND_BREAK:
76 usbd_cdc_acm_send_break(busid, intf_num);
77 break;
78 default:
79 USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
80 return -1;
81 }
82
83 return 0;
84 }
85
usbd_cdc_acm_init_intf(uint8_t busid,struct usbd_interface * intf)86 struct usbd_interface *usbd_cdc_acm_init_intf(uint8_t busid, struct usbd_interface *intf)
87 {
88 (void)busid;
89
90 intf->class_interface_handler = cdc_acm_class_interface_request_handler;
91 intf->class_endpoint_handler = NULL;
92 intf->vendor_handler = NULL;
93 intf->notify_handler = NULL;
94
95 return intf;
96 }
97
usbd_cdc_acm_set_line_coding(uint8_t busid,uint8_t intf,struct cdc_line_coding * line_coding)98 __WEAK void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
99 {
100 (void)busid;
101 (void)intf;
102 (void)line_coding;
103 }
104
usbd_cdc_acm_get_line_coding(uint8_t busid,uint8_t intf,struct cdc_line_coding * line_coding)105 __WEAK void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding)
106 {
107 (void)busid;
108 (void)intf;
109
110 line_coding->dwDTERate = 2000000;
111 line_coding->bDataBits = 8;
112 line_coding->bParityType = 0;
113 line_coding->bCharFormat = 0;
114 }
115
usbd_cdc_acm_set_dtr(uint8_t busid,uint8_t intf,bool dtr)116 __WEAK void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
117 {
118 (void)busid;
119 (void)intf;
120 (void)dtr;
121 }
122
usbd_cdc_acm_set_rts(uint8_t busid,uint8_t intf,bool rts)123 __WEAK void usbd_cdc_acm_set_rts(uint8_t busid, uint8_t intf, bool rts)
124 {
125 (void)busid;
126 (void)intf;
127 (void)rts;
128 }
129
usbd_cdc_acm_send_break(uint8_t busid,uint8_t intf)130 __WEAK void usbd_cdc_acm_send_break(uint8_t busid, uint8_t intf)
131 {
132 (void)busid;
133 (void)intf;
134 }
135