Nano100BN Series BSP  V3.03.002
The Board Support Package for Nano100BN 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  case REQ_CLASS: // Class
124  {
126  {
128  }
129  break;
130  }
131  case REQ_VENDOR: // Vendor
132  {
134  {
136  }
137  break;
138  }
139  default: // reserved
140  {
141  /* Setup error, stall the device */
144  break;
145  }
146  }
147 }
148 
159 {
160  uint32_t u32Len;
161 
162  g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
163  u32Len = 0;
164  u32Len = g_usbd_SetupPacket[7];
165  u32Len <<= 8;
166  u32Len += g_usbd_SetupPacket[6];
167 
168  switch (g_usbd_SetupPacket[3])
169  {
170  // Get Device Descriptor
171  case DESC_DEVICE:
172  {
173  u32Len = Minimum(u32Len, LEN_DEVICE);
174  USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len);
175  USBD_PrepareCtrlOut(0,0);
176  break;
177  }
178  // Get Configuration Descriptor
179  case DESC_CONFIG:
180  {
181  uint32_t u32TotalLen;
182 
183  u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3];
184  u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);
185 
186  if (u32Len > u32TotalLen)
187  {
188  u32Len = u32TotalLen;
189  if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
190  {
191  g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
192  }
193  }
194  USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len);
195  USBD_PrepareCtrlOut(0,0);
196  break;
197  }
198  // Get HID Descriptor
199  case DESC_HID:
200  {
201  /* CV3.0 HID Class Descriptor Test,
202  Need to indicate index of the HID Descriptor within gu8ConfigDescriptor, specifically HID Composite device. */
203  uint32_t u32ConfigDescOffset; // u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index)
204  u32Len = Minimum(u32Len, LEN_HID);
205  u32ConfigDescOffset = g_usbd_sInfo->gu32ConfigHidDescIdx[g_usbd_SetupPacket[4]];
206  USBD_PrepareCtrlIn((uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len);
207  USBD_PrepareCtrlOut(0,0);
208  break;
209  }
210  // Get Report Descriptor
211  case DESC_HID_RPT:
212  {
214  {
216  if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
217  {
218  g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
219  }
220  }
222  USBD_PrepareCtrlOut(0,0);
223  break;
224  }
225  // Get String Descriptor
226  case DESC_STRING:
227  {
228  // Get String Descriptor
229  if(g_usbd_SetupPacket[2] < 4)
230  {
231  if (u32Len > g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0])
232  {
234  if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
235  {
236  g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
237  }
238  }
240  USBD_PrepareCtrlOut(0, 0);
241  }
242  else
243  {
244  // Not support. Reply STALL.
247  }
248  break;
249  }
250  default:
251  // Not support. Reply STALL.
254  break;
255  }
256 }
257 
268 {
269  /* clear global variables for new request */
270  g_usbd_CtrlInPointer = 0;
271  g_usbd_CtrlInSize = 0;
272 
273  if (g_usbd_SetupPacket[0] & 0x80) /* request data transfer direction */
274  {
275  // Device to host
276  switch (g_usbd_SetupPacket[1])
277  {
278  case GET_CONFIGURATION:
279  {
280  // Return current configuration setting
281  /* Data stage */
282  M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbConfig;
285  /* Status stage */
286  USBD_PrepareCtrlOut(0,0);
287  break;
288  }
289  case GET_DESCRIPTOR:
290  {
292  break;
293  }
294  case GET_INTERFACE:
295  {
296  // Return current interface setting
297  /* Data stage */
298  M8(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0)) = g_usbd_UsbAltInterface;
301  /* Status stage */
302  USBD_PrepareCtrlOut(0,0);
303  break;
304  }
305  case GET_STATUS:
306  {
307  // Device
308  if(g_usbd_SetupPacket[0] == 0x80)
309  {
310  uint8_t u8Tmp;
311 
312  u8Tmp = 0;
313  if(g_usbd_sInfo->gu8ConfigDesc[7] & 0x40) u8Tmp |= 1; // Self-Powered/Bus-Powered.
314  if(g_usbd_sInfo->gu8ConfigDesc[7] & 0x20) u8Tmp |= (g_usbd_RemoteWakeupEn << 1); // Remote wake up
315 
317  }
318  // Interface
319  else if (g_usbd_SetupPacket[0] == 0x81)
321  // Endpoint
322  else if (g_usbd_SetupPacket[0] == 0x82)
323  {
324  uint8_t ep = g_usbd_SetupPacket[4] & 0xF;
326  }
327 
329  /* Data stage */
332  /* Status stage */
333  USBD_PrepareCtrlOut(0,0);
334  break;
335  }
336  default:
337  {
338  /* Setup error, stall the device */
341  break;
342  }
343  }
344  }
345  else
346  {
347  // Host to device
348  switch (g_usbd_SetupPacket[1])
349  {
350  case CLEAR_FEATURE:
351  {
352  if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
353  {
354 
355  int32_t epNum, i;
356 
357  /* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
358  a flag: g_u32EpStallLock is added to support it */
359  epNum = g_usbd_SetupPacket[4] & 0xF;
360  for(i = 0; i < USBD_MAX_EP; i++)
361  {
362  if(((USBD->EP[i].CFG & 0xF) == epNum) && ((g_u32EpStallLock & (1 << i)) == 0))
364  }
365  }
366  else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
368  /* Status stage */
371  break;
372  }
373  case SET_ADDRESS:
374  {
375  g_usbd_UsbAddr = g_usbd_SetupPacket[2];
376 
377  // DATA IN for end of setup
378  /* Status Stage */
381  break;
382  }
383  case SET_CONFIGURATION:
384  {
385  g_usbd_UsbConfig = g_usbd_SetupPacket[2];
386 
389 
390  if (g_usbd_UsbConfig == 0)
391  {
392  int volatile i;
393 
394  /* Reset PID DATA0 */
395  for (i = 2; i < USBD_MAX_EP; i++)
396  USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
397  }
398 
399  // DATA IN for end of setup
400  /* Status stage */
403  break;
404  }
405 
406  case SET_FEATURE:
407  {
408  if (g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
410  else if (g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
412 
413  /* Status stage */
416  break;
417  }
418 
419  case SET_INTERFACE:
420  {
421  g_usbd_UsbAltInterface = g_usbd_SetupPacket[2];
422 
424  g_usbd_pfnSetInterface(g_usbd_UsbAltInterface);
425 
426  /* Status stage */
429  break;
430  }
431 
432  default:
433  {
434  /* Setup error, stall the device */
437  break;
438  }
439  }
440  }
441 }
442 
453 void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size)
454 {
455  if(u32Size > g_usbd_CtrlMaxPktSize)
456  {
457  // Data size > MXPLD
458  g_usbd_CtrlInPointer = pu8Buf + g_usbd_CtrlMaxPktSize;
459  g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize;
461  USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), pu8Buf, g_usbd_CtrlMaxPktSize);
462  USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
463  }
464  else
465  {
466  // Data size <= MXPLD
467  g_usbd_CtrlInPointer = 0;
468  g_usbd_CtrlInSize = 0;
470  USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), pu8Buf, u32Size);
471  USBD_SET_PAYLOAD_LEN(EP0, u32Size);
472  }
473 }
474 
484 void USBD_CtrlIn(void)
485 {
486  if(g_usbd_CtrlInSize)
487  {
488  // Process remained data
489  if(g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize)
490  {
491  // Data size > MXPLD
492  USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize);
493  USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
494  g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize;
495  g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
496  }
497  else
498  {
499  // Data size <= MXPLD
500  USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize);
501  USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize);
502  g_usbd_CtrlInPointer = 0;
503  g_usbd_CtrlInSize = 0;
504  }
505  }
506  else
507  {
508  // In ACK for Set address
509  if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == SET_ADDRESS))
510  {
511  if((USBD_GET_ADDR() != g_usbd_UsbAddr) && (USBD_GET_ADDR() == 0))
512  {
513  USBD_SET_ADDR(g_usbd_UsbAddr);
514  }
515  }
516 
517  /* For the case of data size is integral times maximum packet size */
518  if(g_usbd_CtrlInZeroFlag)
519  {
521  g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
522  }
523  }
524 }
525 
536 void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
537 {
538  g_usbd_CtrlOutPointer = pu8Buf;
539  g_usbd_CtrlOutSize = 0;
540  g_usbd_CtrlOutSizeLimit = u32Size;
541  USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
542 }
543 
553 void USBD_CtrlOut(void)
554 {
555  uint32_t u32Size;
556 
557  if (g_usbd_CtrlOutToggle != (USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk))
558  {
559  g_usbd_CtrlOutToggle = USBD->EPSTS & USBD_EPSTS_EPSTS1_Msk;
560  if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
561  {
562  u32Size = USBD_GET_PAYLOAD_LEN(EP1);
563  USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1), u32Size);
564  g_usbd_CtrlOutPointer += u32Size;
565  g_usbd_CtrlOutSize += u32Size;
566  }
567  }
568  else
569  {
570  USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
571  }
572 }
573 
583 void USBD_SwReset(void)
584 {
585  int i;
586 
587  // Reset all variables for protocol
588  g_usbd_CtrlInPointer = 0;
589  g_usbd_CtrlInSize = 0;
590  g_usbd_CtrlOutPointer = 0;
591  g_usbd_CtrlOutSize = 0;
592  g_usbd_CtrlOutSizeLimit = 0;
593  memset(g_usbd_SetupPacket, 0, 8);
594 
595  /* Reset PID DATA0 */
596  for (i=0; i<USBD_MAX_EP; i++)
597  USBD->EP[i].CFG &= ~USBD_CFG_DSQ_SYNC_Msk;
598 
599  // Reset USB device address
600  USBD_SET_ADDR(0);
601 }
602 
603 
614 {
615  g_usbd_pfnVendorRequest = pfnVendorReq;
616 }
626 void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
627 {
628  g_usbd_pfnSetConfigCallback = pfnSetConfigCallback;
629 }
630 
631 void USBD_LockEpStall(uint32_t u32EpBitmap)
632 {
633  g_u32EpStallLock = u32EpBitmap;
634 }
635 
636 
637 
void USBD_GetDescriptor(void)
Get Descriptor request.
Definition: usbd.c:158
#define M8(addr)
Get a 8-bit unsigned value from specified address.
void USBD_StandardRequest(void)
Process USB standard request.
Definition: usbd.c:267
#define USBD_INT_BUS
Definition: usbd.h:122
#define USBD_INT_WAKEUP
Definition: usbd.h:125
void(* SET_INTERFACE_REQ)(uint32_t u32AltInterface)
Definition: usbd.h:488
#define USBD_INT_USB
Definition: usbd.h:123
#define USBD
Pointer to USBD register structure.
void CLK_SysTickDelay(uint32_t us)
This function execute delay function.
Definition: clk.c:559
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:241
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:453
#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:626
#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:297
void(* CLASS_REQ)(void)
Definition: usbd.h:486
volatile uint8_t g_usbd_RemoteWakeupEn
Definition: usbd.c:19
void USBD_SwReset(void)
Clear all software flags.
Definition: usbd.c:583
uint32_t * gu32HidReportSize
Definition: usbd.h:32
#define USBD_ENABLE_INT(intr)
Enable USBD interrupt.
Definition: usbd.h:248
#define USBD_GET_EP_BUF_ADDR(ep)
Get buffer for USB endpoint.
Definition: usbd.h:342
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:234
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:408
#define USBD_SET_EP_STALL(ep)
Set USB endpoint stall state.
Definition: usbd.h:354
#define USBD_GET_PAYLOAD_LEN(ep)
Get USB payload size (OUT data)
Definition: usbd.h:319
#define Minimum(a, b)
Compare two input numbers and return minimum one.
Definition: usbd.h:185
#define USBD_INT_FLDET
Definition: usbd.h:124
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:312
#define USBD_SET_SE0()
Force USB PHY Transceiver to Drive SE0.
Definition: usbd.h:220
#define USBD_CLR_SE0()
Release SE0.
Definition: usbd.h:227
void USBD_CtrlOut(void)
Start Control OUT transfer.
Definition: usbd.c:553
#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:463
SET_INTERFACE_REQ g_usbd_pfnSetInterface
Definition: usbd.c:43
void USBD_LockEpStall(uint32_t u32EpBitmap)
Definition: usbd.c:631
void USBD_CtrlIn(void)
Start Control IN transfer.
Definition: usbd.c:484
void USBD_ProcessSetupPacket(void)
Process Setup Packet.
Definition: usbd.c:110
void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)
USBD Set Vendor Request.
Definition: usbd.c:613
#define EP0
Definition: usbd.h:49
void(* SET_CONFIG_CB)(void)
Definition: usbd.h:489
void(* VENDOR_REQ)(void)
Definition: usbd.h:484
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:536
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:394