Merge pull request #11198 from SteveCEvans/sce_rc2
[betaflight.git] / src / main / vcp_hal / usbd_cdc_hid.c
blob875e0ab9de034c333b913c4fddd84137b98d018e
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
20 * Author: Chris Hockuba (https://github.com/conkerkh)
24 #include "platform.h"
26 #ifdef USE_USB_CDC_HID
28 #include "usbd_conf.h"
29 #include "usbd_desc.h"
30 #include "usbd_ctlreq.h"
31 #include "usbd_def.h"
33 #include "usbd_cdc.h"
34 #include "usbd_hid.h"
36 #define USB_HID_CDC_CONFIG_DESC_SIZ (USB_HID_CONFIG_DESC_SIZ - 9 + USB_CDC_CONFIG_DESC_SIZ + 8)
38 #define HID_INTERFACE 0x0
39 #define HID_POOLING_INTERVAL 0x0A // 10ms - 100Hz update rate
41 #define CDC_COM_INTERFACE 0x1
43 #define USBD_VID 0x0483
44 #define USBD_PID 0x3256
46 __ALIGN_BEGIN uint8_t USBD_HID_CDC_DeviceDescriptor[USB_LEN_DEV_DESC] __ALIGN_END =
48 0x12, /*bLength */
49 USB_DESC_TYPE_DEVICE, /*bDescriptorType*/
50 0x00, 0x02, /*bcdUSB */
51 0xEF, /*bDeviceClass*/
52 0x02, /*bDeviceSubClass*/
53 0x01, /*bDeviceProtocol*/
54 USB_OTG_MAX_EP0_SIZE, /*bMaxPacketSize*/
55 LOBYTE(USBD_VID), HIBYTE(USBD_VID), /*idVendor*/
56 LOBYTE(USBD_PID),
57 HIBYTE(USBD_PID), /*idProduct*/
58 0x00, 0x02, /*bcdDevice rel. 2.00*/
59 USBD_IDX_MFC_STR, /*Index of manufacturer string*/
60 USBD_IDX_PRODUCT_STR, /*Index of product string*/
61 USBD_IDX_SERIAL_STR, /*Index of serial number string*/
62 USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/
65 __ALIGN_BEGIN static uint8_t USBD_HID_CDC_CfgDesc[USB_HID_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
67 0x09, /* bLength: Configuration Descriptor size */
68 USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
69 USB_HID_CDC_CONFIG_DESC_SIZ,
70 /* wTotalLength: Bytes returned */
71 0x00,
72 0x03, /*bNumInterfaces: 2 interfaces (1 for CDC, 1 for HID)*/
73 0x01, /*bConfigurationValue: Configuration value*/
74 0x00, /*iConfiguration: Index of string descriptor describing
75 the configuration*/
76 0xC0, /*bmAttributes: bus powered and Support Remote Wake-up */
77 0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
79 /************** Descriptor of Joystick Mouse interface ****************/
80 /* 09 */
81 0x09, /*bLength: Interface Descriptor size*/
82 USB_DESC_TYPE_INTERFACE, /*bDescriptorType: Interface descriptor type*/
83 HID_INTERFACE, /*bInterfaceNumber: Number of Interface*/
84 0x00, /*bAlternateSetting: Alternate setting*/
85 0x01, /*bNumEndpoints*/
86 0x03, /*bInterfaceClass: HID*/
87 0x00, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
88 0x00, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
89 0, /*iInterface: Index of string descriptor*/
90 /******************** Descriptor of Joystick Mouse HID ********************/
91 /* 18 */
92 0x09, /*bLength: HID Descriptor size*/
93 HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
94 0x11, /*bcdHID: HID Class Spec release number*/
95 0x01,
96 0x00, /*bCountryCode: Hardware target country*/
97 0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
98 0x22, /*bDescriptorType*/
99 HID_MOUSE_REPORT_DESC_SIZE, /*wItemLength: Total length of Report descriptor*/
100 0x00,
101 /******************** Descriptor of Mouse endpoint ********************/
102 /* 27 */
103 0x07, /*bLength: Endpoint Descriptor size*/
104 USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
106 HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
107 0x03, /*bmAttributes: Interrupt endpoint*/
108 HID_EPIN_SIZE, /*wMaxPacketSize: 8 Byte max */
109 0x00,
110 HID_POOLING_INTERVAL, /*bInterval: Polling Interval (10 ms)*/
111 /* 34 */
113 /******** /IAD should be positioned just before the CDC interfaces ******
114 IAD to associate the two CDC interfaces */
116 0x08, /* bLength */
117 0x0B, /* bDescriptorType */
118 0x01, /* bFirstInterface */
119 0x02, /* bInterfaceCount */
120 0x02, /* bFunctionClass */
121 0x02, /* bFunctionSubClass */
122 0x01, /* bFunctionProtocol */
123 0x00, /* iFunction (Index of string descriptor describing this function) */
125 /*Interface Descriptor */
126 0x09, /* bLength: Interface Descriptor size */
127 USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
128 /* Interface descriptor type */
129 CDC_COM_INTERFACE, /* bInterfaceNumber: Number of Interface */
130 0x00, /* bAlternateSetting: Alternate setting */
131 0x01, /* bNumEndpoints: One endpoints used */
132 0x02, /* bInterfaceClass: Communication Interface Class */
133 0x02, /* bInterfaceSubClass: Abstract Control Model */
134 0x01, /* bInterfaceProtocol: Common AT commands */
135 0x00, /* iInterface: */
137 /*Header Functional Descriptor*/
138 0x05, /* bLength: Endpoint Descriptor size */
139 0x24, /* bDescriptorType: CS_INTERFACE */
140 0x00, /* bDescriptorSubtype: Header Func Desc */
141 0x10, /* bcdCDC: spec release number */
142 0x01,
144 /*Call Management Functional Descriptor*/
145 0x05, /* bFunctionLength */
146 0x24, /* bDescriptorType: CS_INTERFACE */
147 0x01, /* bDescriptorSubtype: Call Management Func Desc */
148 0x00, /* bmCapabilities: D0+D1 */
149 0x02, /* bDataInterface: 2 */
151 /*ACM Functional Descriptor*/
152 0x04, /* bFunctionLength */
153 0x24, /* bDescriptorType: CS_INTERFACE */
154 0x02, /* bDescriptorSubtype: Abstract Control Management desc */
155 0x02, /* bmCapabilities */
157 /*Union Functional Descriptor*/
158 0x05, /* bFunctionLength */
159 0x24, /* bDescriptorType: CS_INTERFACE */
160 0x06, /* bDescriptorSubtype: Union func desc */
161 0x01, /* bMasterInterface: Communication class interface */
162 0x02, /* bSlaveInterface0: Data Class Interface */
164 /*Endpoint 2 Descriptor*/
165 0x07, /* bLength: Endpoint Descriptor size */
166 USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
167 CDC_CMD_EP, /* bEndpointAddress */
168 0x03, /* bmAttributes: Interrupt */
169 LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
170 HIBYTE(CDC_CMD_PACKET_SIZE),
171 0xFF, /* bInterval: */
173 /*---------------------------------------------------------------------------*/
175 /*Data class interface descriptor*/
176 0x09, /* bLength: Endpoint Descriptor size */
177 USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
178 0x02, /* bInterfaceNumber: Number of Interface */
179 0x00, /* bAlternateSetting: Alternate setting */
180 0x02, /* bNumEndpoints: Two endpoints used */
181 0x0A, /* bInterfaceClass: CDC */
182 0x00, /* bInterfaceSubClass: */
183 0x00, /* bInterfaceProtocol: */
184 0x00, /* iInterface: */
186 /*Endpoint OUT Descriptor*/
187 0x07, /* bLength: Endpoint Descriptor size */
188 USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
189 CDC_OUT_EP, /* bEndpointAddress */
190 0x02, /* bmAttributes: Bulk */
191 LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
192 HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
193 0x00, /* bInterval: ignore for Bulk transfer */
195 /*Endpoint IN Descriptor*/
196 0x07, /* bLength: Endpoint Descriptor size */
197 USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
198 CDC_IN_EP, /* bEndpointAddress */
199 0x02, /* bmAttributes: Bulk */
200 LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
201 HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
202 0x00, /* bInterval */
205 /* USB Standard Device Descriptor */
206 __ALIGN_BEGIN static uint8_t USBD_HID_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
208 USB_LEN_DEV_QUALIFIER_DESC,
209 USB_DESC_TYPE_DEVICE_QUALIFIER,
210 0x00,
211 0x02,
212 0x00,
213 0x00,
214 0x00,
215 0x40,
216 0x01,
217 0x00,
220 /* Wrapper related callbacks */
221 static uint8_t USBD_HID_CDC_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx);
222 static uint8_t USBD_HID_CDC_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx);
224 /* Control Endpoints*/
225 static uint8_t USBD_HID_CDC_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
226 static uint8_t USBD_HID_CDC_EP0_RxReady (USBD_HandleTypeDef *pdev);
228 /* Class Specific Endpoints*/
229 static uint8_t USBD_HID_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);
230 static uint8_t USBD_HID_CDC_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum);
232 static uint8_t *USBD_HID_CDC_GetFSCfgDesc (uint16_t *length);
233 uint8_t *USBD_HID_CDC_GetDeviceQualifierDescriptor (uint16_t *length); //Will be NULL Callback because it's unused
235 /* CDC interface class callbacks structure */
236 USBD_ClassTypeDef USBD_HID_CDC =
238 USBD_HID_CDC_Init,
239 USBD_HID_CDC_DeInit,
240 USBD_HID_CDC_Setup,
241 NULL, /* EP0_TxSent, */
242 USBD_HID_CDC_EP0_RxReady,
243 USBD_HID_CDC_DataIn,
244 USBD_HID_CDC_DataOut,
245 NULL,
246 NULL,
247 NULL,
248 NULL,
249 USBD_HID_CDC_GetFSCfgDesc,
250 NULL,
251 USBD_HID_CDC_GetDeviceQualifierDescriptor,
254 static uint8_t USBD_HID_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
256 //Init CDC
257 USBD_CDC.Init(pdev, cfgidx);
259 //Init HID
260 USBD_HID.Init(pdev, cfgidx);
262 return USBD_OK;
265 static uint8_t USBD_HID_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
267 //DeInit CDC
268 USBD_CDC.DeInit(pdev, cfgidx);
270 //DeInit HID
271 USBD_HID.DeInit(pdev, cfgidx);
273 return USBD_OK;
276 static uint8_t USBD_HID_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
278 switch(req->bmRequest & USB_REQ_RECIPIENT_MASK) {
279 case USB_REQ_RECIPIENT_INTERFACE:
280 if (req->wIndex == HID_INTERFACE) {
281 return USBD_HID.Setup(pdev, req);
283 else {
284 return USBD_CDC.Setup(pdev, req);
286 break;
287 case USB_REQ_RECIPIENT_ENDPOINT:
288 if (req->wIndex == HID_EPIN_ADDR) {
289 return USBD_HID.Setup(pdev, req);
290 } else {
291 return USBD_CDC.Setup(pdev, req);
293 break;
296 return USBD_OK;
299 static uint8_t USBD_HID_CDC_EP0_RxReady (USBD_HandleTypeDef *pdev)
301 return (USBD_CDC.EP0_RxReady(pdev));
304 static uint8_t USBD_HID_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
306 if (epnum == (CDC_IN_EP &~ 0x80)) {
307 return USBD_CDC.DataIn(pdev, epnum);
309 else {
310 return USBD_HID.DataIn(pdev, epnum);
313 return USBD_OK;
316 static uint8_t USBD_HID_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
318 if (epnum == (CDC_OUT_EP &~ 0x80)) {
319 return (USBD_CDC.DataOut(pdev, epnum));
322 return USBD_OK;
325 static uint8_t *USBD_HID_CDC_GetFSCfgDesc (uint16_t *length)
327 *length = sizeof(USBD_HID_CDC_CfgDesc);
328 return USBD_HID_CDC_CfgDesc;
331 uint8_t *USBD_HID_CDC_GetDeviceQualifierDescriptor (uint16_t *length)
333 *length = sizeof(USBD_HID_CDC_DeviceQualifierDesc);
334 return USBD_HID_CDC_DeviceQualifierDesc;
336 #endif