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)
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)
26 #ifdef USE_USB_CDC_HID
28 #include "usbd_conf.h"
29 #include "usbd_desc.h"
30 #include "usbd_ctlreq.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
=
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*/
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 */
72 0x03, /*bNumInterfaces: 2 interfaces (1 for CDC, 1 for HID)*/
73 0x01, /*bConfigurationValue: Configuration value*/
74 0x00, /*iConfiguration: Index of string descriptor describing
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 ****************/
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 ********************/
92 0x09, /*bLength: HID Descriptor size*/
93 HID_DESCRIPTOR_TYPE
, /*bDescriptorType: HID*/
94 0x11, /*bcdHID: HID Class Spec release number*/
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*/
101 /******************** Descriptor of Mouse endpoint ********************/
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 */
110 HID_POOLING_INTERVAL
, /*bInterval: Polling Interval (10 ms)*/
113 /******** /IAD should be positioned just before the CDC interfaces ******
114 IAD to associate the two CDC interfaces */
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 */
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
,
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
=
241 NULL
, /* EP0_TxSent, */
242 USBD_HID_CDC_EP0_RxReady
,
244 USBD_HID_CDC_DataOut
,
249 USBD_HID_CDC_GetFSCfgDesc
,
251 USBD_HID_CDC_GetDeviceQualifierDescriptor
,
254 static uint8_t USBD_HID_CDC_Init(USBD_HandleTypeDef
*pdev
, uint8_t cfgidx
)
257 USBD_CDC
.Init(pdev
, cfgidx
);
260 USBD_HID
.Init(pdev
, cfgidx
);
265 static uint8_t USBD_HID_CDC_DeInit(USBD_HandleTypeDef
*pdev
, uint8_t cfgidx
)
268 USBD_CDC
.DeInit(pdev
, cfgidx
);
271 USBD_HID
.DeInit(pdev
, cfgidx
);
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
);
284 return USBD_CDC
.Setup(pdev
, req
);
287 case USB_REQ_RECIPIENT_ENDPOINT
:
288 if (req
->wIndex
== HID_EPIN_ADDR
) {
289 return USBD_HID
.Setup(pdev
, req
);
291 return USBD_CDC
.Setup(pdev
, req
);
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
);
310 return USBD_HID
.DataIn(pdev
, epnum
);
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
));
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
;