GD32F1x0: USB/GD32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c Source File

GD32F1x0

usbd_cdc_core.c
Go to the documentation of this file.
1 
11 /* Includes ------------------------------------------------------------------*/
12 #include "usbd_cdc_core.h"
13 #include "usbd_enum.h"
14 
30 static uint8_t USBD_CDC_Init (void *pudev, uint8_t ConfigIndex);
31 static uint8_t USBD_CDC_DeInit (void *pudev, uint8_t ConfigIndex);
32 static uint8_t USBD_CDC_GetClassDescriptor (void *pudev, USB_DEVICE_REQ *req);
33 static uint8_t USBD_CDC_ClassReqHandle (void *pudev, USB_DEVICE_REQ *req);
34 static uint8_t USBD_CDC_GetInterface (void *pudev, USB_DEVICE_REQ *req);
35 static uint8_t USBD_CDC_SetInterface (void *pudev, USB_DEVICE_REQ *req);
36 static uint8_t USBD_CDC_EP0_RxReady (void *pudev);
37 static uint8_t USBD_CDC_DataIn (void *pudev, uint8_t EpID);
38 static uint8_t USBD_CDC_DataOut (void *pudev, uint8_t EpID);
39 static uint8_t USBD_CDC_SOF (void *pudev);
40 static uint8_t* USBD_CDC_GetCfgDesc (uint8_t USBSpeed, uint16_t *len);
41 
42 static void USBD_CDC_AsynchXferHandle (void *pudev);
43 
47 extern CDC_IF_Fop_TypeDef APP_FOPS;
48 
49 uint8_t USB_Tx_State = 0;
50 
51 static __IO uint32_t USBD_CDC_AltSet = 0;
52 
53 uint8_t USB_DATA_Buffer[USB_CDC_DATA_PACKET_SIZE];
54 uint8_t USB_CMD_Buffer[USB_CDC_CMD_PACKET_SIZE];
55 uint8_t APP_DATA_Buffer[APP_RX_DATA_SIZE];
56 
57 __IO uint32_t end_packet = 0;
58 
59 uint32_t AppBufInPtr = 0;
60 uint32_t AppBufOutPtr = 0;
61 uint32_t AppRxLength = 0;
62 
63 static uint32_t CDCCmd = 0xFF;
64 static uint32_t CDCLen = 0;
65 
66 /* USB CDC device class callbacks structure */
67 USBD_Class_cb_TypeDef USBD_CDC_cb =
68 {
69  USBD_CDC_Init,
70  USBD_CDC_DeInit,
71  USBD_CDC_GetClassDescriptor,
72  USBD_CDC_ClassReqHandle,
73  USBD_CDC_GetInterface,
74  USBD_CDC_SetInterface,
75  NULL,/* EP0_TxSent */
76  USBD_CDC_EP0_RxReady,
77  USBD_CDC_DataIn,
78  USBD_CDC_DataOut,
79  USBD_CDC_SOF,
80  USBD_CDC_GetCfgDesc,
81 };
82 
83 /* USB CDC device configuration descriptor set */
84 const uint8_t USBD_CDC_CfgDesc[USB_CDC_CONFIG_DESC_SIZE] =
85 {
86  /*Configuration Descriptor*/
87  0x09, /* bLength: configuration descriptor size */
88  USB_DESCTYPE_CONFIGURATION, /* bDescriptorType: configuration descriptor type */
89  USB_CDC_CONFIG_DESC_SIZE, /* wTotalLength: configuration descriptor set total length */
90  0x00,
91  0x02, /* bNumInterfaces: 2 interface */
92  0x01, /* bConfigurationValue: Configuration value */
93  0x00, /* iConfiguration: index of string descriptor describing the configuration */
94  0x80, /* bmAttributes: device attributes (bus powered and not support remote wakeup) */
95  0x32, /* bMaxPower 100 mA: this current is used for detectiong Vbus */
96 
97  /*Interface descriptor */
98  0x09, /* bLength: interface descriptor size */
99  USB_DESCTYPE_INTERFACE, /* bDescriptorType: interface descriptor type */
100  0x00, /* bInterfaceNumber: number of interface */
101  0x00, /* bAlternateSetting: alternate setting */
102  0x01, /* bNumEndpoints: 1 endpoint used for command IN */
103  0x02, /* bInterfaceClass: CDC class */
104  0x02, /* bInterfaceSubClass: abstract control model */
105  0x01, /* nInterfaceProtocol: common AT commands */
106  0x00, /* iInterface: index of interface string descriptor */
107 
108  /* Header functional descriptor */
109  0x05, /* bFunctionLength: the descriptor size */
110  0x24, /* bDescriptorType: CS_INTERFACE */
111  0x00, /* bDescriptorSubtype: header function descriptor */
112  0x10, /* bcdCDC: spec release number (CDC1.10) */
113  0x01,
114 
115  /* Call management functional descriptor */
116  0x05, /* bFunctionLength: the descriptor size */
117  0x24, /* bDescriptorType: CS_INTERFACE */
118  0x01, /* bDescriptorSubtype: Call Management Func Desc */
119  0x00, /* bmCapabilities: D0 is reset, D1 is ignored */
120  0x01, /* bDataInterface: 1 interface used for call management */
121 
122  /* ACM functional descriptor */
123  0x04, /* bFunctionLength: the dsecriptor length */
124  0x24, /* bDescriptorType: CS_INTERFACE */
125  0x02, /* bDescriptorSubtype: Abstract Control Management desc */
126  0x02, /* bmCapabilities: D1 */
127 
128  /* Union functional descriptor */
129  0x05, /* bFunctionLength: the descriptor length */
130  0x24, /* bDescriptorType: CS_INTERFACE */
131  0x06, /* bDescriptorSubtype: Union func desc */
132  0x00, /* bMasterInterface: Communication class interface */
133  0x01, /* bSlaveInterface0: Data Class Interface */
134 
135  /* Command endpoint descriptor */
136  0x07, /* bLength: endpoint descriptor size */
137  USB_DESCTYPE_ENDPOINT, /* bDescriptorType: endpoint descriptor type */
138  CDC_CMD_EP, /* bEndpointAddress: endpoint address(EP2_IN) */
139  0x03, /* bmAttributes: interrupt endpoint */
140  LOWBYTE(USB_CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: 8 bytes max */
141  HIGHBYTE(USB_CDC_CMD_PACKET_SIZE),
142  0x0A, /* bInterval: polling interval(10ms) */
143 
144  /* Data class interface descriptor */
145  0x09, /* bLength: interface descriptor size */
146  USB_DESCTYPE_INTERFACE, /* bDescriptorType: interface descriptor type */
147  0x01, /* bInterfaceNumber: number of interface */
148  0x00, /* bAlternateSetting: alternate setting */
149  0x02, /* bNumEndpoints: 2 endpoints used */
150  0x0A, /* bInterfaceClass: CDC class */
151  0x00, /* bInterfaceSubClass: no set */
152  0x00, /* bInterfaceProtocol: no set */
153  0x00, /* iInterface: no set */
154 
155  /* Data OUT endpoint descriptor */
156  0x07, /* bLength: endpoint descriptor size */
157  USB_DESCTYPE_ENDPOINT, /* bDescriptorType: endpoint descriptor type */
158  CDC_DATA_OUT_EP, /* bEndpointAddress: endpoint address(EP3_OUT) */
159  0x02, /* bmAttributes: bulk endpoint */
160  LOWBYTE(CDC_DATA_OUT_PACKET_SIZE), /* wMaxPacketSize: 64 bytes max */
161  HIGHBYTE(CDC_DATA_OUT_PACKET_SIZE),
162  0x00, /* bInterval: ignore for Bulk transfer */
163 
164  /* Data IN endpoint descriptor */
165  0x07, /* bLength: endpoint descriptor size */
166  USB_DESCTYPE_ENDPOINT, /* bDescriptorType: endpoint descriptor type */
167  CDC_DATA_IN_EP, /* bEndpointAddress: endpoint address(EP1_IN) */
168  0x02, /* bmAttributes: bulk endpoint */
169  LOWBYTE(CDC_DATA_IN_PACKET_SIZE), /* wMaxPacketSize: 64 bytes max */
170  HIGHBYTE(CDC_DATA_IN_PACKET_SIZE),
171  0x00 /* bInterval: ignore for bulk transfer */
172 };
173 
188 static uint8_t USBD_CDC_Init (void *pudev, uint8_t ConfigIndex)
189 {
190 #ifdef DOUBLE_BUFFER_TX
191  USB_EP_BufConfig(pudev, CDC_DATA_IN_EP, USB_DBL_BUFTYPE, BULK_TX_ADDRESS);
192 #else
193  USB_EP_BufConfig(pudev, CDC_DATA_IN_EP, USB_SNG_BUFTYPE, BULK_TX_ADDRESS);
194 #endif
195 
196  USB_EP_BufConfig(pudev, CDC_CMD_EP, USB_SNG_BUFTYPE, INT_TX_ADDRESS);
197 
198 #ifdef DOUBLE_BUFFER_RX
199  USB_EP_BufConfig(pudev, CDC_DATA_OUT_EP, USB_DBL_BUFTYPE, BULK_RX_ADDRESS);
200 #else
201  USB_EP_BufConfig(pudev, CDC_DATA_OUT_EP, USB_SNG_BUFTYPE, BULK_RX_ADDRESS);
202 #endif
203 
204  /* Initialize the data Tx/Rx endpoint */
205  USB_EP_Init(pudev, CDC_DATA_IN_EP, USB_EPTYPE_BULK, CDC_DATA_IN_PACKET_SIZE);
206  USB_EP_Init(pudev, CDC_DATA_OUT_EP, USB_EPTYPE_BULK, CDC_DATA_OUT_PACKET_SIZE);
207 
208  /* Initialize the command Tx endpoint */
209  USB_EP_Init(pudev, CDC_CMD_EP, USB_EPTYPE_INT, USB_CDC_CMD_PACKET_SIZE);
210 
211  /* Initialize the interface physical components */
212  APP_FOPS.pIf_Init(DEFAULT_CONFIG);
213 
214  /* Enable OUT endpoint prepare to receive next packet */
215  USB_EP_Rx(pudev, CDC_DATA_OUT_EP, (uint8_t*)(USB_DATA_Buffer), CDC_DATA_OUT_PACKET_SIZE);
216 
217  return USBD_OK;
218 }
219 
226 static uint8_t USBD_CDC_DeInit (void *pudev, uint8_t ConfigIndex)
227 {
228  /* Deinitialize the data Tx/Rx endpoint */
229  USB_EP_DeInit(pudev, CDC_DATA_IN_EP);
230  USB_EP_DeInit(pudev, CDC_DATA_OUT_EP);
231 
232  /* Deinitialize the command Tx endpoint */
233  USB_EP_DeInit(pudev, CDC_CMD_EP);
234 
235  /* Restore default state of the interface physical components */
236  APP_FOPS.pIf_DeInit();
237 
238  return USBD_OK;
239 }
240 
247 static uint8_t USBD_CDC_GetClassDescriptor (void *pudev, USB_DEVICE_REQ *req)
248 {
249  uint16_t len = USB_CDC_DESC_SIZE;
250  uint8_t *pbuf= (uint8_t*)USBD_CDC_CfgDesc + 9;
251 
252  if((req->wValue >> 8) == CDC_DESC_TYPE)
253  {
254  len = MIN(USB_CDC_DESC_SIZE, req->wLength);
255  pbuf = (uint8_t*)USBD_CDC_CfgDesc + 9 + (9 * USBD_ITF_MAX_NUM);
256  }
257 
258  USB_CtlTx (pudev, pbuf, len);
259 
260  return USBD_OK;
261 }
262 
269 static uint8_t USBD_CDC_ClassReqHandle (void *pudev, USB_DEVICE_REQ *req)
270 {
271  if (req->wLength)
272  {
273  if (req->bmRequestType & 0x80)
274  {
275  /* Request is from device to host */
276 
277  /* Get the request data from media access layer */
278  APP_FOPS.pIf_Ctrl(req->bRequest, USB_CMD_Buffer, req->wLength);
279 
280  /* Send the request data to the host */
281  USB_CtlTx (pudev, USB_CMD_Buffer, req->wLength);
282  }
283  else
284  {
285  /* Request is from host to device */
286 
287  /* Set the value of the current command to be processed */
288  CDCCmd = req->bRequest;
289  CDCLen = req->wLength;
290 
291  /* Enable EP0 prepare to receive command data packet */
292  USB_CtlRx (pudev, USB_CMD_Buffer, req->wLength);
293  }
294  }
295  else
296  {
297  /* The command to be handled in the media access layer */
298  APP_FOPS.pIf_Ctrl(req->bRequest, NULL, 0);
299  }
300 
301  return USBD_OK;
302 }
303 
310 static uint8_t USBD_CDC_GetInterface (void *pudev, USB_DEVICE_REQ *req)
311 {
312  USB_CtlTx (pudev, (uint8_t *)&USBD_CDC_AltSet, 1);
313 
314  return USBD_OK;
315 }
316 
323 static uint8_t USBD_CDC_SetInterface (void *pudev, USB_DEVICE_REQ *req)
324 {
325  if ((uint8_t)(req->wValue) < USBD_ITF_MAX_NUM)
326  {
327  USBD_CDC_AltSet = (uint8_t)(req->wValue);
328  }
329  else
330  {
331  /* Call the error management function (command will be nacked */
332  USBD_EnumError (pudev, req);
333  }
334 
335  return USBD_OK;
336 }
337 
343 static uint8_t USBD_CDC_EP0_RxReady (void *pudev)
344 {
345  if (CDCCmd != NO_CMD)
346  {
347  /* Process the command data */
348  APP_FOPS.pIf_Ctrl(CDCCmd, USB_CMD_Buffer, CDCLen);
349 
350  CDCCmd = NO_CMD;
351  CDCLen = 0;
352  }
353 
354  return USBD_OK;
355 }
356 
363 static uint8_t USBD_CDC_DataIn (void *pudev, uint8_t EpID)
364 {
365  uint16_t USB_Tx_length;
366 
367  if (USB_Tx_State == 1)
368  {
369  if (AppRxLength == 0)
370  {
371  if (end_packet == 1)
372  {
373  end_packet = 0;
374 
375  /*Send zero-length packet*/
376  USB_EP_Tx (pudev, CDC_DATA_IN_EP, 0, 0);
377  }
378  else
379  {
380  USB_Tx_State = 0;
381  }
382  }
383  else
384  {
385  if (AppRxLength > CDC_DATA_IN_PACKET_SIZE)
386  {
387  USB_Tx_length = CDC_DATA_IN_PACKET_SIZE;
388  }
389  else
390  {
391  USB_Tx_length = AppRxLength;
392  if (AppRxLength == CDC_DATA_IN_PACKET_SIZE) end_packet = 1;
393  }
394 
395  /* Prepare the available data buffer to be sent on IN endpoint */
396  USB_EP_Tx (pudev,
397  CDC_DATA_IN_EP,
398  &APP_DATA_Buffer[AppBufOutPtr],
399  USB_Tx_length);
400 
401  AppBufOutPtr += USB_Tx_length;
402  AppRxLength -= USB_Tx_length;
403  }
404  }
405 
406  return USBD_OK;
407 }
408 
415 static uint8_t USBD_CDC_DataOut (void *pudev, uint8_t EpID)
416 {
417  uint16_t USB_Rx_Cnt;
418 
419  /* Update the received data counter */
420  USB_Rx_Cnt = ((USB_DEVICE_HANDLE*)pudev)->dev.out_ep[EpID].xfer_count;
421 
422  /* USB received data will be immediately processed in media access layer */
423  APP_FOPS.pIf_DataRx(USB_DATA_Buffer, USB_Rx_Cnt);
424 
425  /* Enable Out endpoint prepare to receive next data packet */
426  USB_EP_Rx(pudev,
427  CDC_DATA_OUT_EP,
428  USB_DATA_Buffer,
429  CDC_DATA_OUT_PACKET_SIZE);
430 
431  return USBD_OK;
432 }
433 
439 static uint8_t USBD_CDC_SOF (void *pudev)
440 {
441  static uint8_t FrameCount = 0;
442 
443  if (FrameCount++ == CDC_IN_FRAME_INTERVAL)
444  {
445  /* Frame counter is reset */
446  FrameCount = 0;
447 
448  /* Handle asynchronous transmission between USB endpoint and Usart */
449  USBD_CDC_AsynchXferHandle(pudev);
450  }
451 
452  return USBD_OK;
453 }
454 
460 static void USBD_CDC_AsynchXferHandle (void *pudev)
461 {
462  uint16_t USB_Tx_length;
463 
464  if(USB_Tx_State != 1)
465  {
466  if(AppBufOutPtr == AppBufInPtr)
467  {
468  /* No data received by real usart */
469  return;
470  }
471 
472  if(AppBufOutPtr > AppBufInPtr) /* Need rollback */
473  {
474  AppRxLength = APP_RX_DATA_SIZE - AppBufOutPtr;
475  }
476  else
477  {
478  AppRxLength = AppBufInPtr - AppBufOutPtr;
479  }
480 
481  if (AppRxLength > CDC_DATA_IN_PACKET_SIZE)
482  {
483  USB_Tx_length = CDC_DATA_IN_PACKET_SIZE;
484  }
485  else
486  {
487  USB_Tx_length = AppRxLength;
488  if (USB_Tx_length == CDC_DATA_IN_PACKET_SIZE) end_packet = 1; /* Last packet will be sent */
489  }
490 
491  USB_EP_Tx (pudev,
492  CDC_DATA_IN_EP,
493  &APP_DATA_Buffer[AppBufOutPtr],
494  USB_Tx_length);
495 
496  /* Update Tx parameters */
497  AppBufOutPtr += USB_Tx_length;
498  AppRxLength -= USB_Tx_length;
499 
500  USB_Tx_State = 1;
501 
502  if (AppBufOutPtr == APP_RX_DATA_SIZE)
503  {
504  AppBufOutPtr = 0;
505  }
506  }
507 }
508 
515 static uint8_t *USBD_CDC_GetCfgDesc (uint8_t USBSpeed, uint16_t *len)
516 {
517  *len = sizeof (USBD_CDC_CfgDesc);
518 
519  return (uint8_t*)USBD_CDC_CfgDesc;
520 }
521 
542 /************************ (C) COPYRIGHT 2014 GIGADEVICE *****END OF FILE****/
#define CDC_CMD_EP
USB device class callback type define.
Definition: usb_core.h:153
void USB_EP_Tx(USB_CORE_HANDLE *pudev, uint8_t EpAddr, uint8_t *pbuf, uint16_t BufLen)
Endpoint prepare to transmit data.
Definition: usb_core.c:376
#define CDC_IN_FRAME_INTERVAL
Header file for the usbd_cdc_core.c file.
void USB_EP_DeInit(USB_CORE_HANDLE *pudev, uint8_t EpAddr)
Configure the endpoint when it is disabled.
Definition: usb_core.c:275
void USB_EP_Init(USB_CORE_HANDLE *pudev, uint8_t EpAddr, uint8_t EpType, uint16_t EpMps)
Endpoint initialization.
Definition: usb_core.c:169
uint8_t USB_CtlRx(USB_CORE_HANDLE *pudev, uint8_t *pbuf, uint16_t Len)
Receive data on the control pipe.
Definition: usb_core.c:577
uint8_t USB_CtlTx(USB_CORE_HANDLE *pudev, uint8_t *pbuf, uint16_t Len)
Transmit data on the control pipe.
Definition: usb_core.c:543
USB enumeration function prototypes.
#define USB_SNG_BUFTYPE
USB endpoint kind.
Definition: usb_core.h:52
void USB_EP_BufConfig(USB_CORE_HANDLE *pudev, uint8_t EpAddr, uint8_t EpKind, uint32_t BufAddr)
Configure buffer for endpoint.
Definition: usb_core.c:107
void USBD_EnumError(USB_DEVICE_HANDLE *pudev, USB_DEVICE_REQ *req)
Handle usb enumeration error event.
Definition: usbd_enum.c:755
USB standard device request struct.
Definition: usb_core.h:122
void USB_EP_Rx(USB_CORE_HANDLE *pudev, uint8_t EpAddr, uint8_t *pbuf, uint16_t BufLen)
Endpoint prepare to receive data.
Definition: usb_core.c:336
#define APP_RX_DATA_SIZE
Generated by   doxygen 1.8.10