Nano100AN Series BSP  V3.02.002
The Board Support Package for Nano100AN Series
usbd.c
Go to the documentation of this file.
1 /**************************************************************************/
13 #include <string.h>
14 #include "Nano100Series.h"
15 
16 /*--------------------------------------------------------------------------*/
17 /* Global variables for Control Pipe */
18 uint8_t g_usbd_SetupPacket[8] = {0};
19 volatile uint8_t g_usbd_RemoteWakeupEn = 0;
24 static volatile uint8_t *g_usbd_CtrlInPointer = 0;
25 static volatile uint32_t g_usbd_CtrlInSize = 0;
26 static volatile uint8_t *g_usbd_CtrlOutPointer = 0;
27 static volatile uint32_t g_usbd_CtrlOutSize = 0;
28 static volatile uint32_t g_usbd_CtrlOutSizeLimit = 0;
29 static volatile uint32_t g_usbd_UsbAddr = 0;
30 static volatile uint32_t g_usbd_CtrlMaxPktSize = 8;
31 static volatile uint32_t g_usbd_UsbAltInterface = 0;
32 static volatile uint32_t g_usbd_CtrlOutToggle = 0;
33 static volatile uint8_t g_usbd_CtrlInZeroFlag = 0ul;
34 volatile uint32_t g_usbd_UsbConfig = 0;
40 
45 uint32_t g_u32EpStallLock = 0;
54 void USBD_Open(S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
55 {
56  g_usbd_sInfo = param;
57  g_usbd_pfnClassRequest = pfnClassReq;
58  g_usbd_pfnSetInterface = pfnSetInterface;
59 
60  /* get EP0 maximum packet size */
61  g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7];
62 
63  /* Initial USB engine */
64  USBD->CTL = 0x29f;
65  USBD->PDMA |= USBD_PDMA_BYTEM_Msk;
66  /* Force SE0, and then clear it to connect*/
67  USBD_SET_SE0();
68 }
69 
79 void USBD_Start(void)
80 {
81  /* Enable USB-related interrupts. */
83  CLK_SysTickDelay(100000);
84  USBD_CLR_SE0();
85 }
86 
96 void USBD_GetSetupPacket(uint8_t *buf)
97 {
99 }
100 
111 {
112  g_usbd_CtrlOutToggle = 0;
113  // Setup packet process
115 
116  switch (g_usbd_SetupPacket[0] & 0x60) /* request type */
117  {
118  case REQ_STANDARD: // Standard
119  {
121  break;
122  }
123 
124  case REQ_CLASS: // Class
125  {
127  {
129  }
130 
131  break;
132  }
133 
134  case REQ_VENDOR: // Vendor
135  {
137  {
139  }
140 
141  break;
142  }
143 
144  default: // reserved
145  {
146  /* Setup error, stall the device */
149  break;
150  }
151  }
152 }
153 
164 {
165  uint32_t u32Len;
166 
167  g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
168  u32Len = 0;
169  u32Len = g_usbd_SetupPacket[7];
170  u32Len <<= 8;
171  u32Len += g_usbd_SetupPacket[6];
172 
173  switch (g_usbd_SetupPacket[3])
174  {
175  // Get Device Descriptor
176  case DESC_DEVICE:
177  {
178  u32Len = Minimum(u32Len, LEN_DEVICE);
179  USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len);
180  USBD_PrepareCtrlOut(0, 0);
181  break;
182  }
183 
184  // Get Configuration Descriptor
185  case DESC_CONFIG:
186  {
187  uint32_t u32TotalLen;
188 
189  u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3];
190  u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);
191 
192  if (u32Len > u32TotalLen)
193  {
194  u32Len = u32TotalLen;
195 
196  if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
197  {
198  g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
199  }
200  }
201 
202  USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len);
203  USBD_PrepareCtrlOut(0, 0);
204  break;
205  }
206 
207  // Get HID Descriptor
208  case DESC_HID:
209  {
210  /* CV3.0 HID Class Descriptor Test,
211  Need to indicate index of the HID Descriptor within gu8ConfigDescriptor, specifically HID Composite device. */
212  uint32_t u32ConfigDescOffset; // u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index)
213  u32Len = Minimum(u32Len, LEN_HID);
214  u32ConfigDescOffset = g_usbd_sInfo->gu32ConfigHidDescIdx[g_usbd_SetupPacket[4]];
215  USBD_PrepareCtrlIn((uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len);
216  USBD_PrepareCtrlOut(0, 0);
217  break;
218  }
219 
220  // Get Report Descriptor
221  case DESC_HID_RPT:
222  {
224  {
226 
227  if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
228  {
229  g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
230  }
231  }
232 
234  USBD_PrepareCtrlOut(0, 0);
235  break;
236  }
237 
238  // Get String Descriptor
239  case DESC_STRING:
240  {
241  // Get String Descriptor
242  if (g_usbd_SetupPacket[2] < 4)
243  {
244  if (u32Len > g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0])
245  {
247 
248  if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
249  {
250  g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
251  }
252  }
253 
255  USBD_PrepareCtrlOut(0, 0);
256  }
257  else
258  {
259  // Not support. Reply STALL.
262  }
263 
264  break;
265  }
266 
267  default:
268  // Not support. Reply STALL.
271  break;
272  }
273 }
274 
285 {
286  /* clear global variables for new request */
287  g_usbd_CtrlInPointer = 0;
288  g_usbd_CtrlInSize = 0;
289 
290  if (g_usbd_SetupPacket[0] & 0x80) /* request data transfer direction */
291  {
292  // Device to host
293  switch (g_usbd_SetupPacket[1])
294  {
295  case GET_CONFIGURATION:
296  {
297  // Return current configuration setting
298  /* Data stage */
299  M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbConfig;
302  /* Status stage */
303  USBD_PrepareCtrlOut(0, 0);
304  break;
305  }
306 
307  case GET_DESCRIPTOR:
308  {
310  break;
311  }
312 
313  case GET_INTERFACE:
314  {
315  // Return current interface setting
316  /* Data stage */
317  M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbAltInterface;
320  /* Status stage */
321  USBD_PrepareCtrlOut(0, 0);
322  break;
323  }
324 
325  case GET_STATUS:
326  {
327  // Device
328  if (g_usbd_SetupPacket[0] == 0x80)
329  {
330  uint8_t u8Tmp;
331 
332  u8Tmp = 0;
333 
334  if (g_usbd_sInfo->gu8ConfigDesc[7] & 0x40) u8Tmp |= 1; // Self-Powered/Bus-Powered.
335 
336  if (g_usbd_sInfo->gu8ConfigDesc[7] & 0x20) u8Tmp |= (g_usbd_RemoteWakeupEn << 1); // Remote wake up
337 
339  }
340  // Interface
341  else if (g_usbd_SetupPacket[0] == 0x81)
343  // Endpoint
344  else if (g_usbd_SetupPacket[0] == 0x82)
345  {
346  uint8_t ep = g_usbd_SetupPacket[4] & 0xF;
348  }
349 
351  /* Data stage */
354  /* Status stage */
355  USBD_PrepareCtrlOut(0, 0);
356  break;
357  }
358 
359  default:
360  {
361  /* Setup error, stall the device */
364  break;
365  }
366  }
367  }
368  else
369  {
370  // Host to device
371  switch (g_usbd_SetupPacket[1])
372  {
373  case CLEAR_FEATURE:
374  {
375  if (g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
376  {
377 
378  int32_t epNum, i;
379 
380  /* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
381  a flag: g_u32EpStallLock is added to support it */
382  epNum = g_usbd_SetupPacket[4] & 0xF;
383 
384  for (i = 0; i < USBD_MAX_EP; i++)
385  {
386  if (((USBD->EP[i].CFG & 0xF) == epNum) && ((g_u32EpStallLock & (1 << i)) == 0))
388  }
389  }
390  else if (g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
392 
393  /* Status stage */
396  break;
397  }
398 
399  case SET_ADDRESS:
400  {
401  g_usbd_UsbAddr = g_usbd_SetupPacket[2];
402 
403  // DATA IN for end of setup
404  /* Status Stage */
407  break;
408  }
409 
410  case SET_CONFIGURATION:
411  {
412  g_usbd_UsbConfig = g_usbd_SetupPacket[2];
413 
416 
417  if (g_usbd_UsbConfig == 0)
418  {
419  int volatile i;
420 
421  /* Reset PID DATA0 */
422  for (i = 2; i < USBD_MAX_EP; i++)
423  USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
424  }
425 
426  // DATA IN for end of setup
427  /* Status stage */
430  break;
431  }
432 
433  case SET_FEATURE:
434  {
435  if (g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
437  else if (g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
439 
440  /* Status stage */
443  break;
444  }
445 
446  case SET_INTERFACE:
447  {
448  g_usbd_UsbAltInterface = g_usbd_SetupPacket[2];
449 
451  g_usbd_pfnSetInterface(g_usbd_UsbAltInterface);
452 
453  /* Status stage */
456  break;
457  }
458 
459  default:
460  {
461  /* Setup error, stall the device */
464  break;
465  }
466  }
467  }
468 }
469 
480 void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size)
481 {
482  if (u32Size > g_usbd_CtrlMaxPktSize)
483  {
484  // Data size > MXPLD
485  g_usbd_CtrlInPointer = pu8Buf + g_usbd_CtrlMaxPktSize;
486  g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize;
488  USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), pu8Buf, g_usbd_CtrlMaxPktSize);
489  USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
490  }
491  else
492  {
493  // Data size <= MXPLD
494  g_usbd_CtrlInPointer = 0;
495  g_usbd_CtrlInSize = 0;
497  USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), pu8Buf, u32Size);
498  USBD_SET_PAYLOAD_LEN(EP0, u32Size);
499  }
500 }
501 
511 void USBD_CtrlIn(void)
512 {
513  if (g_usbd_CtrlInSize)
514  {
515  // Process remained data
516  if (g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize)
517  {
518  // Data size > MXPLD
519  USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize);
520  USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
521  g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize;
522  g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
523  }
524  else
525  {
526  // Data size <= MXPLD
527  USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize);
528  USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize);
529  g_usbd_CtrlInPointer = 0;
530  g_usbd_CtrlInSize = 0;
531  }
532  }
533  else
534  {
535  // In ACK for Set address
536  if ((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == SET_ADDRESS))
537  {
538  if ((USBD_GET_ADDR() != g_usbd_UsbAddr) && (USBD_GET_ADDR() == 0))
539  {
540  USBD_SET_ADDR(g_usbd_UsbAddr);
541  }
542  }
543 
544  /* For the case of data size is integral times maximum packet size */
545  if (g_usbd_CtrlInZeroFlag)
546  {
548  g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
549  }
550  }
551 }
552 
563 void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
564 {
565  g_usbd_CtrlOutPointer = pu8Buf;
566  g_usbd_CtrlOutSize = 0;
567  g_usbd_CtrlOutSizeLimit = u32Size;
568  USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
569 }
570 
580 void USBD_CtrlOut(void)
581 {
582  uint32_t u32Size;
583 
584  if (g_usbd_CtrlOutToggle != (USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk))
585  {
586  g_usbd_CtrlOutToggle = USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk;
587 
588  if (g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
589  {
590  u32Size = USBD_GET_PAYLOAD_LEN(EP1);
591  USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1), u32Size);
592  g_usbd_CtrlOutPointer += u32Size;
593  g_usbd_CtrlOutSize += u32Size;
594  }
595  }
596  else
597  {
598  USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
599  }
600 }
601 
611 void USBD_SwReset(void)
612 {
613  int i;
614 
615  // Reset all variables for protocol
616  g_usbd_CtrlInPointer = 0;
617  g_usbd_CtrlInSize = 0;
618  g_usbd_CtrlOutPointer = 0;
619  g_usbd_CtrlOutSize = 0;
620  g_usbd_CtrlOutSizeLimit = 0;
621  memset(g_usbd_SetupPacket, 0, 8);
622 
623  /* Reset PID DATA0 */
624  for (i = 0; i < USBD_MAX_EP; i++)
625  USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
626 
627  // Reset USB device address
628  USBD_SET_ADDR(0);
629 }
630 
631 
642 {
643  g_usbd_pfnVendorRequest = pfnVendorReq;
644 }
654 void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
655 {
656  g_usbd_pfnSetConfigCallback = pfnSetConfigCallback;
657 }
658 
659 void USBD_LockEpStall(uint32_t u32EpBitmap)
660 {
661  g_u32EpStallLock = u32EpBitmap;
662 }
663 
664 
665 
void USBD_GetDescriptor(void)
Get Descriptor request.
Definition: usbd.c:163
#define M8(addr)
Get a 8-bit unsigned value from specified address.
void USBD_StandardRequest(void)
Process USB standard request.
Definition: usbd.c:284
#define USBD_INT_BUS
Definition: usbd.h:120
#define USBD_INT_WAKEUP
Definition: usbd.h:123
void(* SET_INTERFACE_REQ)(uint32_t u32AltInterface)
Definition: usbd.h:483
#define USBD_INT_USB
Definition: usbd.h:121
#define USBD
Pointer to USBD register structure.
void CLK_SysTickDelay(uint32_t us)
This function execute delay function.
Definition: clk.c:564
void USBD_Start(void)
USBD Start.
Definition: usbd.c:79
CLASS_REQ g_usbd_pfnClassRequest
Definition: usbd.c:42
#define USBD_CFG_SSTALL_Msk
uint32_t g_u32EpStallLock
Definition: usbd.c:45
#define USBD_GET_ADDR()
Get USBD address.
Definition: usbd.h:237
SET_CONFIG_CB g_usbd_pfnSetConfigCallback
Definition: usbd.c:44
Nano100 series peripheral access layer header file. This file contains all the peripheral register's ...
#define NULL
NULL pointer.
#define USBD_CFG_DSQ_SYNC_Msk
uint8_t * gu8DevDesc
Definition: usbd.h:28
VENDOR_REQ g_usbd_pfnVendorRequest
Definition: usbd.c:41
void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size)
Prepare Control IN transaction.
Definition: usbd.c:480
#define EP1
Definition: usbd.h:50
void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
The callback function which called when get SET CONFIGURATION request.
Definition: usbd.c:654
#define USBD_BUF_BASE
Definition: usbd.h:45
void USBD_Open(S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
USBD Initial, Enable clock and reset USB.
Definition: usbd.c:54
#define USBD_SET_DATA1(ep)
Set USB data1 token.
Definition: usbd.h:293
void(* CLASS_REQ)(void)
Definition: usbd.h:482
volatile uint8_t g_usbd_RemoteWakeupEn
Definition: usbd.c:19
void USBD_SwReset(void)
Clear all software flags.
Definition: usbd.c:611
uint32_t * gu32HidReportSize
Definition: usbd.h:32
#define USBD_ENABLE_INT(intr)
Enable USBD interrupt.
Definition: usbd.h:244
#define USBD_GET_EP_BUF_ADDR(ep)
Get buffer for USB endpoint.
Definition: usbd.h:338
S_USBD_INFO_T * g_usbd_sInfo
Definition: usbd.c:39
uint8_t ** gu8HidReportDesc
Definition: usbd.h:31
uint8_t * gu8ConfigDesc
Definition: usbd.h:29
#define USBD_SET_ADDR(addr)
Set USBD address.
Definition: usbd.h:230
uint8_t g_usbd_SetupPacket[8]
Definition: usbd.c:18
static __INLINE void USBD_SetStall(uint8_t epnum)
Set USB endpoint stall state.
Definition: usbd.h:404
#define USBD_SET_EP_STALL(ep)
Set USB endpoint stall state.
Definition: usbd.h:350
#define USBD_GET_PAYLOAD_LEN(ep)
Get USB payload size (OUT data)
Definition: usbd.h:315
#define Minimum(a, b)
Compare two input numbers and return minimum one.
Definition: usbd.h:181
#define USBD_INT_FLDET
Definition: usbd.h:122
void USBD_GetSetupPacket(uint8_t *buf)
Get Setup Packet.
Definition: usbd.c:96
#define USBD_SET_PAYLOAD_LEN(ep, size)
Set USB payload size (IN data)
Definition: usbd.h:308
#define USBD_SET_SE0()
Force USB PHY Transceiver to Drive SE0.
Definition: usbd.h:216
#define USBD_CLR_SE0()
Release SE0.
Definition: usbd.h:223
void USBD_CtrlOut(void)
Start Control OUT transfer.
Definition: usbd.c:580
#define USBD_PDMA_BYTEM_Msk
#define USBD_MAX_EP
Definition: usbd.h:47
static __INLINE uint32_t USBD_GetStall(uint8_t epnum)
Get USB endpoint stall state.
Definition: usbd.h:459
SET_INTERFACE_REQ g_usbd_pfnSetInterface
Definition: usbd.c:43
void USBD_LockEpStall(uint32_t u32EpBitmap)
Definition: usbd.c:659
void USBD_CtrlIn(void)
Start Control IN transfer.
Definition: usbd.c:511
void USBD_ProcessSetupPacket(void)
Process Setup Packet.
Definition: usbd.c:110
void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)
USBD Set Vendor Request.
Definition: usbd.c:641
#define EP0
Definition: usbd.h:49
void(* SET_CONFIG_CB)(void)
Definition: usbd.h:484
void(* VENDOR_REQ)(void)
Definition: usbd.h:481
uint8_t ** gu8StringDesc
Definition: usbd.h:30
uint32_t * gu32ConfigHidDescIdx
Definition: usbd.h:33
#define USBD_EPSTS_EPSTS1_Msk
void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
Prepare Control OUT transaction.
Definition: usbd.c:563
static __INLINE void USBD_MemCopy(uint8_t *dest, uint8_t *src, int32_t size)
To support byte access between USB SRAM and system SRAM.
Definition: usbd.h:390