EFM32 Happy Gecko Software Documentation  efm32hg-doc-5.1.2
em_usbh.c
Go to the documentation of this file.
1 /***************************************************************************/
16 #include "em_device.h"
17 #if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
18 #include "em_usb.h"
19 #if defined( USB_HOST )
20 
21 #include "em_cmu.h"
22 #include "em_core.h"
23 #include "em_usbtypes.h"
24 #include "em_usbhal.h"
25 #include "em_usbh.h"
26 #if ( USB_VBUSOVRCUR_PORT != USB_VBUSOVRCUR_PORT_NONE )
27 #include "em_gpio.h"
28 #endif
29 
32 USBH_Hc_TypeDef hcs[ NUM_HC_USED + 2 ];
33 int USBH_attachRetryCount;
34 USBH_Init_TypeDef USBH_initData;
35 volatile USBH_PortState_TypeDef USBH_portStatus;
36 const USBH_AttachTiming_TypeDef USBH_attachTiming[]=
37 {
38  /* debounceTime resetTime */
39  { 200, 75 },
40  { 200, 100 },
41  { 200, 50 },
42 };
43 
44 #define PORT_VBUS_DELAY 250
45 #define DEFAULT_CTRL_TIMEOUT 1000
46 
47 static void Timeout( int hcnum );
48 
49 #if defined( __ICCARM__ )
50 #pragma diag_suppress=Pe175
51 #endif
52 
53 static void Timeout0(void){ Timeout(0); }
54 static void Timeout1(void){ Timeout(1); }
55 static void Timeout2(void){ Timeout(2); }
56 static void Timeout3(void){ Timeout(3); }
57 static void Timeout4(void){ Timeout(4); }
58 static void Timeout5(void){ Timeout(5); }
59 static void Timeout6(void){ Timeout(6); }
60 static void Timeout7(void){ Timeout(7); }
61 static void Timeout8(void){ Timeout(8); }
62 static void Timeout9(void){ Timeout(9); }
63 static void Timeout10(void){ Timeout(10); }
64 static void Timeout11(void){ Timeout(11); }
65 static void Timeout12(void){ Timeout(12); }
66 static void Timeout13(void){ Timeout(13); }
67 
68 #if defined( __ICCARM__ )
69 #pragma diag_default=Pe175
70 #endif
71 
72 static const USBTIMER_Callback_TypeDef hcTimeoutFunc[ MAX_NUM_HOSTCHANNELS ]=
73 {
74  Timeout0, Timeout1, Timeout2, Timeout3, Timeout4, Timeout5,
75  Timeout6, Timeout7, Timeout8, Timeout9, Timeout10, Timeout11,
76  Timeout12, Timeout13
77 };
78 
79 static void Timeout( int hcnum )
80 {
81  uint32_t hcchar;
82  USBH_Hc_TypeDef *hc;
83  USBH_Ep_TypeDef *ep;
84 
85 #if defined( __GNUC__ )
86 #pragma GCC diagnostic push
87 #pragma GCC diagnostic ignored "-Warray-bounds"
88 #endif
89 
90  hc = &hcs[ hcnum ];
91 
92 #if defined( __GNUC__ )
93 #pragma GCC diagnostic pop
94 #endif
95 
96  hcchar = USBHHAL_GetHcChar( hcnum );
97  ep = hc->ep;
98 
99  if ( ep->type != USB_EPTYPE_INTR )
100  {
101  USBHHAL_HCHalt( hcnum, hcchar );
102  hc->status |= HCS_TIMEOUT;
103  ep->timeout = 0;
104  if ( !hc->idle )
105  USBHEP_TransferDone( hc->ep, USB_STATUS_TIMEOUT );
106  }
107  else
108  {
109  if ( !ep->timeout )
110  {
111  /* Restart the channel */
112  USBHHAL_HCStart( hcnum );
113  USBTIMER_Start( hcnum + HOSTCH_TIMER_INDEX,
114  ep->epDesc.bInterval, hcTimeoutFunc[ hcnum ] );
115  }
116  else
117  {
118  ep->timeout -= SL_MIN( ep->timeout, ep->epDesc.bInterval );
119  if ( ep->timeout )
120  {
121  /* Restart the channel */
122  USBHHAL_HCStart( hcnum );
123  USBTIMER_Start( hcnum + HOSTCH_TIMER_INDEX,
124  SL_MIN( ep->timeout, ep->epDesc.bInterval ),
125  hcTimeoutFunc[ hcnum ] );
126  }
127  else
128  {
129  USBHHAL_HCHalt( hcnum, hcchar );
130  hc->status |= HCS_TIMEOUT;
131  if ( !hc->idle )
132  USBHEP_TransferDone( hc->ep, USB_STATUS_TIMEOUT );
133  }
134  }
135  }
136 }
137 
140 /***************************************************************************/
162 int USBH_AssignHostChannel( USBH_Ep_TypeDef *ep, uint8_t hcnum )
163 {
164  ep->type = ep->epDesc.bmAttributes & CONFIG_DESC_BM_TRANSFERTYPE;
165  ep->in = ( ep->epDesc.bEndpointAddress & USB_SETUP_DIR_MASK ) != 0;
166  ep->packetSize = ep->epDesc.wMaxPacketSize;
167  ep->addr = ep->epDesc.bEndpointAddress;
168  ep->state = H_EP_IDLE;
169 
170  if ( ep == NULL )
171  {
172  DEBUG_USB_API_PUTS( "\nUSBH_AssignHostChannel(),"
173  " ep NULL pointer" );
174  EFM_ASSERT( false );
175  return USB_STATUS_ILLEGAL;
176  }
177 
178  if ( hcnum >= MAX_NUM_HOSTCHANNELS )
179  {
180  DEBUG_USB_API_PUTS( "\nUSBH_AssignHostChannel(),"
181  " Illegal host channel number" );
182  EFM_ASSERT( false );
183  return USB_STATUS_ILLEGAL;
184  }
185 
186  if ( ep->in )
187  {
188  ep->hcIn = hcnum;
189  }
190  else
191  {
192  ep->hcOut = hcnum;
193  }
194 
195  return USB_STATUS_OK;
196 }
197 
198 /***************************************************************************/
249 int USBH_ControlMsg( USBH_Ep_TypeDef *ep,
250  uint8_t bmRequestType,
251  uint8_t bRequest,
252  uint16_t wValue,
253  uint16_t wIndex,
254  uint16_t wLength,
255  void *data,
256  int timeout,
257  USB_XferCompleteCb_TypeDef callback )
258 {
260 
261  if ( ep == NULL )
262  {
263  DEBUG_USB_API_PUTS( "\nUSBH_ControlMsg(), ep NULL pointer" );
264  EFM_ASSERT( false );
265  return USB_STATUS_ILLEGAL;
266  }
267 
268  if ( !USBH_DeviceConnected() )
269  {
270  DEBUG_USB_API_PUTS( "\nUSBH_ControlMsg(), No device connected" );
271  return USB_STATUS_ILLEGAL;
272  }
273 
274  if ( (uint32_t)data & 3 )
275  {
276  DEBUG_USB_API_PUTS( "\nUSBH_ControlMsg(), Misaligned data buffer" );
277  EFM_ASSERT( false );
278  return USB_STATUS_ILLEGAL;
279  }
280 
282  if ( ep->state != H_EP_IDLE )
283  {
285  DEBUG_USB_API_PUTS( "\nUSBH_ControlMsg(), Endpoint is busy" );
286  return USB_STATUS_EP_BUSY;
287  }
288 
289  if ( !hcs[ ep->hcIn ].idle || !hcs[ ep->hcOut ].idle )
290  {
292  DEBUG_USB_API_PUTS( "\nUSBH_ControlMsg(), Host channel is busy" );
293  return USB_STATUS_HC_BUSY;
294  }
295 
296  ep->setup.bmRequestType = bmRequestType;
297  ep->setup.bRequest = bRequest;
298  ep->setup.wValue = wValue;
299  ep->setup.wIndex = wIndex;
300  ep->setup.wLength = wLength;
301 
302  ep->xferCompleted = false;
303  ep->state = H_EP_SETUP;
304  ep->xferCompleteCb = callback;
305  ep->buf = data;
306  ep->xferred = 0;
307  ep->timeout = timeout;
308  ep->setupErrCnt = 0;
309 
310  if ( timeout )
311  {
312  USBTIMER_Start( ep->hcOut + HOSTCH_TIMER_INDEX,
313  timeout, hcTimeoutFunc[ ep->hcOut ] );
314  }
315 
316  USBH_CtlSendSetup( ep );
318  return USB_STATUS_OK;
319 }
320 
321 /***************************************************************************/
370 int USBH_ControlMsgB( USBH_Ep_TypeDef *ep,
371  uint8_t bmRequestType,
372  uint8_t bRequest,
373  uint16_t wValue,
374  uint16_t wIndex,
375  uint16_t wLength,
376  void *data,
377  int timeout )
378 {
379  int retVal;
380 
382  {
383  DEBUG_USB_API_PUTS( "\nUSBH_ControlMsgB() called with int's disabled" );
384  EFM_ASSERT( false );
385  return USB_STATUS_ILLEGAL;
386  }
387 
388  retVal = USBH_ControlMsg( ep,
389  bmRequestType,
390  bRequest,
391  wValue,
392  wIndex,
393  wLength,
394  data,
395  timeout,
396  NULL );
397 
398  if ( retVal == USB_STATUS_OK )
399  {
400  while ( ! ep->xferCompleted );
401 
402  if ( ( retVal = ep->xferStatus ) == USB_STATUS_OK )
403  {
404  retVal = ep->xferred;
405  }
406  }
407 
408  return retVal;
409 }
410 
413 USB_Status_TypeDef USBH_CtlReceiveData( USBH_Ep_TypeDef *ep, uint16_t length )
414 {
415  USBH_Hc_TypeDef *hc;
416 
417  ep->in = true;
418  ep->toggle = USB_PID_DATA1;
419  ep->remaining = length;
420 
421  hc = &hcs[ ep->hcIn ];
422  hc->buf = ep->buf;
423  hc->xferred = 0;
424  hc->remaining = length;
425 
426  USBHHAL_HCStart( ep->hcIn );
427 
428  return USB_STATUS_OK;
429 }
430 
431 #if defined( USB_RAW_API )
432 int USBH_CtlRxRaw( uint8_t pid, USBH_Ep_TypeDef *ep, void *data, int byteCount )
433 {
434  uint16_t packets, len;
435  int hcnum, retval;
436  uint32_t hcchar, status;
438 
439  hcnum = ep->hcIn;
440  if ( byteCount > 0 )
441  packets = ( byteCount + ep->packetSize - 1 ) / ep->packetSize;
442  else
443  packets = 1;
444  len = packets * ep->packetSize;
445 
447 
448  USB->HC[ hcnum ].INTMSK = USB_HC_INT_STALL | USB_HC_INT_NAK | USB_HC_INT_ACK;
449  USB->HC[ hcnum ].INT = 0xFFFFFFFF; /* Clear all interrupt flags */
450  NVIC_ClearPendingIRQ( USB_IRQn );
451  USB->HAINTMSK |= 1 << hcnum; /* Enable host channel interrupt */
452  USB->HC[ hcnum ].CHAR = /* Program HCCHAR register */
453  ( ep->parentDevice->addr << _USB_HC_CHAR_DEVADDR_SHIFT ) |
454  ( ( ep->addr & USB_EPNUM_MASK ) << _USB_HC_CHAR_EPNUM_SHIFT ) |
455  ( ep->type << _USB_HC_CHAR_EPTYPE_SHIFT ) |
456  ( ep->packetSize << _USB_HC_CHAR_MPS_SHIFT ) |
457  ( USB_HC_CHAR_EPDIR ) |
458  ( ep->parentDevice->speed ==
459  HPRT_L_SPEED >> _USB_HPRT_PRTSPD_SHIFT
460  ? USB_HC_CHAR_LSPDDEV : 0 );
461  USB->HC[ hcnum ].TSIZ =
462  ( ( len << _USB_HC_TSIZ_XFERSIZE_SHIFT ) &
463  _USB_HC_TSIZ_XFERSIZE_MASK ) |
464  ( ( packets << _USB_HC_TSIZ_PKTCNT_SHIFT ) &
465  _USB_HC_TSIZ_PKTCNT_MASK ) |
466  ( ( pid << _USB_HC_TSIZ_PID_SHIFT ) &
467  _USB_HC_TSIZ_PID_MASK );
468  USB->HC[ hcnum ].DMAADDR = (uint32_t)data;
469  hcchar = ( USB->HC[ hcnum ].CHAR & ~USB_HC_CHAR_CHDIS ) | USB_HC_CHAR_CHENA;
470  USB->HC[ hcnum ].CHAR = hcchar;
471 
472  /* Start polling for interrupt */
473  retval = USB_STATUS_EP_ERROR;
474  while ( ( USBHAL_GetCoreInts() & USB_GINTSTS_HCHINT ) == 0 ){}
475  if ( USBHHAL_GetHostChannelInts() & ( 1 << hcnum ) )
476  {
477  status = USBHHAL_GetHcInts( hcnum );
478  hcchar |= USB_HC_CHAR_CHDIS;
479  USB->HC[ hcnum ].CHAR = hcchar;
480  USB->HC[ hcnum ].INTMSK = 0;
481  USB->HC[ hcnum ].INT = 0xFFFFFFFF;
482 
483  if ( status & USB_HC_INT_STALL )
484  retval = USB_STATUS_EP_STALLED;
485  else if ( status & USB_HC_INT_NAK )
486  retval = USB_STATUS_EP_NAK;
487  else if ( status & USB_HC_INT_ACK )
488  retval = USB_STATUS_OK;
489  }
490 
491  NVIC_ClearPendingIRQ( USB_IRQn );
493  return retval;
494 }
495 #endif
496 
497 USB_Status_TypeDef USBH_CtlSendData( USBH_Ep_TypeDef *ep, uint16_t length )
498 {
499  USBH_Hc_TypeDef *hc;
500 
501  ep->in = false;
502  ep->toggle = USB_PID_DATA1;
503  ep->remaining = length;
504 
505  hc = &hcs[ ep->hcOut ];
506  hc->buf = ep->buf;
507  hc->xferred = 0;
508  hc->remaining = length;
509 
510  USBHHAL_HCStart( ep->hcOut );
511 
512  return USB_STATUS_OK;
513 }
514 
515 USB_Status_TypeDef USBH_CtlSendSetup( USBH_Ep_TypeDef *ep )
516 {
517  USBH_Hc_TypeDef *hc;
518 
519  hc = &hcs[ ep->hcOut ];
520  hc->buf = (uint8_t*)&ep->setup;
521  hc->xferred = 0;
522  hc->remaining = USB_SETUP_PKT_SIZE;
523  hc->ep = ep;
524  hcs[ ep->hcIn ].ep = ep;
525 
526  ep->toggle = USB_PID_SETUP;
527  ep->remaining = USB_SETUP_PKT_SIZE;
528 
529  ep->in = true;
530  USBHHAL_HCInit( ep->hcIn );
531 
532  ep->in = false;
533  USBHHAL_HCInit( ep->hcOut );
534 
535  USBHHAL_HCStart( ep->hcOut );
536 
537  return USB_STATUS_OK;
538 }
539 
540 #if defined( USB_RAW_API )
541 int USBH_CtlTxRaw( uint8_t pid, USBH_Ep_TypeDef *ep, void *data, int byteCount )
542 {
543  uint16_t packets;
544  int hcnum, retval;
545  uint32_t hcchar, status;
547 
548  hcnum = ep->hcOut;
549  if ( byteCount > 0 )
550  packets = ( byteCount + ep->packetSize - 1 ) / ep->packetSize;
551  else
552  packets = 1;
553 
555 
556  USB->HC[ hcnum ].INTMSK = USB_HC_INT_STALL | USB_HC_INT_NAK | USB_HC_INT_ACK;
557  USB->HC[ hcnum ].INT = 0xFFFFFFFF; /* Clear all interrupt flags */
558  NVIC_ClearPendingIRQ( USB_IRQn );
559  USB->HAINTMSK |= 1 << hcnum; /* Enable host channel interrupt */
560  USB->HC[ hcnum ].CHAR = /* Program HCCHAR register */
561  ( ep->parentDevice->addr << _USB_HC_CHAR_DEVADDR_SHIFT ) |
562  ( ( ep->addr & USB_EPNUM_MASK ) << _USB_HC_CHAR_EPNUM_SHIFT ) |
563  ( ep->type << _USB_HC_CHAR_EPTYPE_SHIFT ) |
564  ( ep->packetSize << _USB_HC_CHAR_MPS_SHIFT ) |
565  ( ep->parentDevice->speed ==
566  HPRT_L_SPEED >> _USB_HPRT_PRTSPD_SHIFT
567  ? USB_HC_CHAR_LSPDDEV : 0 );
568  USB->HC[ hcnum ].TSIZ =
569  ( ( byteCount << _USB_HC_TSIZ_XFERSIZE_SHIFT ) &
570  _USB_HC_TSIZ_XFERSIZE_MASK ) |
571  ( ( packets << _USB_HC_TSIZ_PKTCNT_SHIFT ) &
572  _USB_HC_TSIZ_PKTCNT_MASK ) |
573  ( ( pid << _USB_HC_TSIZ_PID_SHIFT ) &
574  _USB_HC_TSIZ_PID_MASK );
575  USB->HC[ hcnum ].DMAADDR = (uint32_t)data;
576  hcchar = ( USB->HC[ hcnum ].CHAR & ~USB_HC_CHAR_CHDIS ) | USB_HC_CHAR_CHENA;
577  USB->HC[ hcnum ].CHAR = hcchar;
578 
579  /* Start polling for interrupt */
580  retval = USB_STATUS_EP_ERROR;
581  while ( ( USBHAL_GetCoreInts() & USB_GINTSTS_HCHINT ) == 0 ){}
582  if ( USBHHAL_GetHostChannelInts() & ( 1 << hcnum ) )
583  {
584  status = USBHHAL_GetHcInts( hcnum );
585  hcchar |= USB_HC_CHAR_CHDIS;
586  USB->HC[ hcnum ].CHAR = hcchar;
587  USB->HC[ hcnum ].INTMSK = 0;
588  USB->HC[ hcnum ].INT = 0xFFFFFFFF;
589 
590  if ( status & USB_HC_INT_STALL )
591  retval = USB_STATUS_EP_STALLED;
592  else if ( status & USB_HC_INT_NAK )
593  retval = USB_STATUS_EP_NAK;
594  else if ( status & USB_HC_INT_ACK )
595  retval = USB_STATUS_OK;
596  }
597 
598  NVIC_ClearPendingIRQ( USB_IRQn );
600  return retval;
601 }
602 #endif
603 
606 /***************************************************************************/
613 bool USBH_DeviceConnected( void )
614 {
615  return USBH_portStatus == H_PORT_CONNECTED;
616 }
617 
618 /***************************************************************************/
648 int USBH_GetConfigurationDescriptorB( USBH_Device_TypeDef *device,
649  void *buf, int len,
650  uint8_t configIndex )
651 {
652  if ( device == NULL )
653  {
654  DEBUG_USB_API_PUTS( "\nUSBH_GetConfigurationDescriptorB(),"
655  " device NULL pointer" );
656  EFM_ASSERT( false );
657  return USB_STATUS_ILLEGAL;
658  }
659 
660  if ( buf == NULL )
661  {
662  DEBUG_USB_API_PUTS( "\nUSBH_GetConfigurationDescriptorB(),"
663  " buf NULL pointer" );
664  EFM_ASSERT( false );
665  return USB_STATUS_ILLEGAL;
666  }
667 
668  return USBH_ControlMsgB( &device->ep0,
670  USB_SETUP_TYPE_STANDARD_MASK, /* bmRequestType */
671  GET_DESCRIPTOR, /* bRequest */
672  (USB_CONFIG_DESCRIPTOR << 8) | configIndex,/* wValue */
673  0, /* wIndex */
674  len, /* wLength */
675  buf, /* void* data */
676  DEFAULT_CTRL_TIMEOUT ); /* int timeout */
677 }
678 
679 /***************************************************************************/
705 int USBH_GetDeviceDescriptorB( USBH_Device_TypeDef *device,
706  void *buf, int len )
707 {
708  if ( device == NULL )
709  {
710  DEBUG_USB_API_PUTS( "\nUSBH_GetDeviceDescriptorB(),"
711  " device NULL pointer" );
712  EFM_ASSERT( false );
713  return USB_STATUS_ILLEGAL;
714  }
715 
716  if ( buf == NULL )
717  {
718  DEBUG_USB_API_PUTS( "\nUSBH_GetDeviceDescriptorB(),"
719  " buf NULL pointer" );
720  EFM_ASSERT( false );
721  return USB_STATUS_ILLEGAL;
722  }
723 
724  return USBH_ControlMsgB( &device->ep0,
726  USB_SETUP_TYPE_STANDARD_MASK, /* bmRequestType */
727  GET_DESCRIPTOR, /* bRequest */
728  USB_DEVICE_DESCRIPTOR << 8, /* wValue */
729  0, /* wIndex */
730  len, /* wLength */
731  buf, /* void* data */
732  DEFAULT_CTRL_TIMEOUT ); /* int timeout */
733 }
734 
735 /***************************************************************************/
742 uint8_t USBH_GetPortSpeed( void )
743 {
744  return USBHHAL_GetPortSpeed();
745 }
746 
747 /***************************************************************************/
780 int USBH_GetStringB( USBH_Device_TypeDef *device, uint8_t *buf, int bufLen,
781  uint8_t stringIndex, uint16_t langID )
782 {
783  int retVal;
785 
786  if ( device == NULL )
787  {
788  DEBUG_USB_API_PUTS( "\nUSBH_GetStringB(), device NULL pointer" );
789  EFM_ASSERT( false );
790  return USB_STATUS_ILLEGAL;
791  }
792 
793  if ( buf == NULL )
794  {
795  DEBUG_USB_API_PUTS( "\nUSBH_GetStringB(), buf NULL pointer" );
796  EFM_ASSERT( false );
797  return USB_STATUS_ILLEGAL;
798  }
799 
800  retVal = USBH_ControlMsgB(
801  &device->ep0,
803  USB_SETUP_TYPE_STANDARD_MASK, /* bmRequestType */
804  GET_DESCRIPTOR, /* bRequest */
805  (USB_STRING_DESCRIPTOR << 8) | stringIndex,/* wValue */
806  langID, /* wIndex */
807  SL_MIN( bufLen, 255 ), /* wLength */
808  buf, /* void* data */
809  DEFAULT_CTRL_TIMEOUT ); /* int timeout */
810 
811  if ( retVal > 2 )
812  {
813  sd = (USB_StringDescriptor_TypeDef*)buf;
814  if ( sd->len )
815  {
816  sd->name[ (sd->len - 2) / sizeof( char16_t ) ] = '\0';
817  }
818  }
819  return retVal;
820 }
821 
822 /***************************************************************************/
839 int USBH_Init( const USBH_Init_TypeDef *p )
840 {
841  if ( p == NULL )
842  {
843  DEBUG_USB_API_PUTS( "\nUSBH_Init(), init struct NULL pointer" );
844  EFM_ASSERT( false );
845  return USB_STATUS_ILLEGAL;
846  }
847 
848  if ( ( p->rxFifoSize < MIN_EP_FIFO_SIZE_INBYTES )
849  || ( p->nptxFifoSize < MIN_EP_FIFO_SIZE_INBYTES )
850  || ( p->ptxFifoSize < MIN_EP_FIFO_SIZE_INBYTES )
851  || ( (p->rxFifoSize + p->nptxFifoSize + p->ptxFifoSize) >
852  (MAX_HOST_FIFO_SIZE_INWORDS * 4) ) )
853  {
854  DEBUG_USB_API_PUTS( "\nUSBH_Init(), Illegal Tx/Rx FIFO memory configuration" );
855  EFM_ASSERT( false );
856  return USB_STATUS_ILLEGAL;
857  }
858  USBH_initData = *p;
859 
861  USBTIMER_Init();
862  USBH_portStatus = H_PORT_DISCONNECTED;
863 
864  /* Enable USB clock. */
866  CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
868  )
869 
870  /* Enable USB interrupt. */
871  NVIC_ClearPendingIRQ( USB_IRQn );
872  NVIC_EnableIRQ( USB_IRQn );
873 
874  return USB_STATUS_OK;
875 }
876 
877 /***************************************************************************/
911 int USBH_InitDeviceData( USBH_Device_TypeDef *device,
912  const uint8_t *buf,
913  USBH_Ep_TypeDef *ep,
914  int numEp,
915  uint8_t deviceSpeed )
916 {
917  int i;
918 
919  if ( device == NULL )
920  {
921  DEBUG_USB_API_PUTS( "\nUSBH_InitDeviceData(), device NULL pointer" );
922  EFM_ASSERT( false );
923  return USB_STATUS_ILLEGAL;
924  }
925 
926  memset( device, 0, sizeof( USBH_Device_TypeDef ) );
927 
928  device->ep = ep;
929  device->addr = 0;
930  device->numEp = numEp;
931  device->speed = deviceSpeed;
932 
933  device->ep0.packetSize = 8;
934  if ( buf ) /* Copy EP0 data from buffer filled by USBH_QueryDevice() */
935  {
936  memcpy( &device->ep0,
937  &((USBH_Device_TypeDef*)buf)->ep0, sizeof( USBH_Ep_TypeDef ) );
938  }
939  device->ep0.parentDevice = device;
940  device->ep0.type = USB_EPTYPE_CTRL;
941  device->ep0.hcOut = 0;
942  device->ep0.hcIn = 1;
943 
944  if ( ep )
945  {
946  for ( i=0; i<numEp; i++ )
947  {
948  memset( &device->ep[i], 0, sizeof( USBH_Ep_TypeDef ) );
949  device->ep[i].parentDevice = device;
950  device->ep[i].toggle = USB_PID_DATA0;
951  }
952  }
953 
954  if ( buf )/* Copy descriptor data from buffer filled by USBH_QueryDevice() */
955  {
956  memcpy( &device->devDesc,
957  &((USBH_Device_TypeDef*)buf)->devDesc, USB_DEVICE_DESCSIZE );
958  memcpy( &device->confDesc,
959  &((USBH_Device_TypeDef*)buf)->confDesc, USB_CONFIG_DESCSIZE );
960  memcpy( &device->itfDesc,
961  USBH_QGetInterfaceDescriptor( buf, 0, 0 ), USB_INTERFACE_DESCSIZE );
962 
963  if ( ep )
964  {
965  for ( i=0; i<numEp; i++ )
966  {
967  memcpy( &device->ep[i].epDesc,
968  USBH_QGetEndpointDescriptor( buf, 0, 0, i ),
970  }
971  }
972  }
973 
974  return USB_STATUS_OK;
975 }
976 
977 /***************************************************************************/
989 int USBH_PortReset( void )
990 {
992  {
993  DEBUG_USB_API_PUTS( "\nUSBH_PortReset() called with int's disabled" );
994  EFM_ASSERT( false );
995  return USB_STATUS_ILLEGAL;
996  }
997 
998  USBH_portStatus = H_PORT_CONNECTED_RESETTING;
1000  USBHHAL_PortReset( true );
1001  )
1002 
1003  USBTIMER_DelayMs( 50 ); /* USB Reset delay */
1004 
1006  USBHHAL_PortReset( false );
1007  )
1008 
1009  USBTIMER_DelayMs( 100 ); /* Reset recovery time */
1010  USBH_portStatus = H_PORT_DISCONNECTED;
1011  return USB_STATUS_OK;
1012 }
1013 
1014 /***************************************************************************/
1022 int USBH_PortResume( void )
1023 {
1025  {
1026  DEBUG_USB_API_PUTS( "\nUSBH_PortResume() called with int's disabled" );
1027  EFM_ASSERT( false );
1028  return USB_STATUS_ILLEGAL;
1029  }
1030 
1032  USBHHAL_PortResume( true );
1033  )
1034 
1035  USBTIMER_DelayMs( 30 );
1036 
1038  USBHHAL_PortResume( false );
1039  )
1040 
1041  return USB_STATUS_OK;
1042 }
1043 
1044 /***************************************************************************/
1048 void USBH_PortSuspend( void )
1049 {
1051  USBHHAL_PortSuspend();
1052  )
1053 }
1054 
1057 int USBH_PortVbusOn( bool on )
1058 {
1060  {
1061  DEBUG_USB_API_PUTS( "\nUSBH_PortVbusOn() called with int's disabled" );
1062  EFM_ASSERT( false );
1063  return USB_STATUS_ILLEGAL;
1064  }
1065 
1067  USBHHAL_VbusOn( on );
1068 
1069  if ( !on )
1070  {
1071  USBH_portStatus = H_PORT_DISCONNECTED;
1072  }
1073  )
1074 
1075  USBTIMER_DelayMs( PORT_VBUS_DELAY );
1076  return USB_STATUS_OK;
1077 }
1078 
1081 #if defined( USB_USE_PRINTF )
1082 /***************************************************************************/
1102 int USBH_PrintConfigurationDescriptor(
1104  int maxLen )
1105 {
1106  char *c;
1107  int remaining;
1108 
1109  if ( config == NULL )
1110  {
1111  DEBUG_USB_API_PUTS( "\nUSBH_PrintConfigurationDescriptor(),"
1112  " config NULL pointer" );
1113  EFM_ASSERT( false );
1114  return USB_STATUS_ILLEGAL;
1115  }
1116 
1117  USB_PRINTF( "\n\nConfiguration descriptor:" );
1118  USB_PRINTF( "\n bLength %d", config->bLength );
1119  USB_PRINTF( "\n bDescriptorType 0x%02X", config->bDescriptorType );
1120  USB_PRINTF( "\n wTotalLength %d", config->wTotalLength );
1121  USB_PRINTF( "\n bNumInterfaces %d", config->bNumInterfaces );
1122  USB_PRINTF( "\n bConfigurationValue %d", config->bConfigurationValue );
1123  USB_PRINTF( "\n iConfiguration %d", config->iConfiguration );
1124  USB_PRINTF( "\n bmAttributes 0x%02X", config->bmAttributes );
1125  USB_PRINTF( "\n bMaxPower %d\n", config->bMaxPower );
1126 
1127  maxLen -= config->bLength;
1128  if ( maxLen > 0 )
1129  {
1130  remaining = SL_MIN( config->wTotalLength - config->bLength, maxLen );
1131  if ( remaining > 0 )
1132  {
1133  USB_PUTCHAR( '\n' );
1134  c = (char*)(config + 1);
1135  while ( remaining-- )
1136  {
1137  USB_PRINTF( "0x%02X ", *c++ );
1138  }
1139  USB_PUTCHAR( '\n' );
1140  }
1141  }
1142 
1143  return USB_STATUS_OK;
1144 }
1145 
1146 /***************************************************************************/
1163 int USBH_PrintDeviceDescriptor( const USB_DeviceDescriptor_TypeDef *device )
1164 {
1165  if ( device == NULL )
1166  {
1167  DEBUG_USB_API_PUTS( "\nUSBH_PrintDeviceDescriptor(),"
1168  " device NULL pointer" );
1169  EFM_ASSERT( false );
1170  return USB_STATUS_ILLEGAL;
1171  }
1172 
1173  USB_PRINTF( "\n\nDevice descriptor:" );
1174  USB_PRINTF( "\n bLength %d", device->bLength );
1175  USB_PRINTF( "\n bDescriptorType 0x%02X", device->bDescriptorType );
1176  USB_PRINTF( "\n bcdUSB 0x%04X", device->bcdUSB );
1177  USB_PRINTF( "\n bDeviceClass %d", device->bDeviceClass );
1178  USB_PRINTF( "\n bDeviceSubClass %d", device->bDeviceSubClass );
1179  USB_PRINTF( "\n bDeviceProtocol %d", device->bDeviceProtocol );
1180  USB_PRINTF( "\n bMaxPacketSize %d", device->bMaxPacketSize0 );
1181  USB_PRINTF( "\n idVendor 0x%04X", device->idVendor );
1182  USB_PRINTF( "\n idProduct 0x%04X", device->idProduct );
1183  USB_PRINTF( "\n bcdDevice 0x%04X", device->bcdDevice );
1184  USB_PRINTF( "\n iManufacturer %d", device->iManufacturer );
1185  USB_PRINTF( "\n iProduct %d", device->iProduct );
1186  USB_PRINTF( "\n iSerialNumber %d", device->iSerialNumber );
1187  USB_PRINTF( "\n bNumConfigurations %d\n", device->bNumConfigurations );
1188 
1189  return USB_STATUS_OK;
1190 }
1191 
1192 /***************************************************************************/
1209 int USBH_PrintEndpointDescriptor(
1210  const USB_EndpointDescriptor_TypeDef *endpoint )
1211 {
1212  if ( endpoint == NULL )
1213  {
1214  DEBUG_USB_API_PUTS( "\nUSBH_PrintEndpointDescriptor(),"
1215  " endpoint NULL pointer" );
1216  EFM_ASSERT( false );
1217  return USB_STATUS_ILLEGAL;
1218  }
1219 
1220  USB_PRINTF( "\n\nEndpoint descriptor:" );
1221  USB_PRINTF( "\n bLength %d", endpoint->bLength );
1222  USB_PRINTF( "\n bDescriptorType 0x%02X", endpoint->bDescriptorType );
1223  USB_PRINTF( "\n bEndpointAddress 0x%02X", endpoint->bEndpointAddress );
1224  USB_PRINTF( "\n bmAttributes 0x%02X", endpoint->bmAttributes );
1225  USB_PRINTF( "\n wMaxPacketSize %d", endpoint->wMaxPacketSize );
1226  USB_PRINTF( "\n bInterval %d\n", endpoint->bInterval );
1227 
1228  return USB_STATUS_OK;
1229 }
1230 
1231 /***************************************************************************/
1248 int USBH_PrintInterfaceDescriptor(
1249  const USB_InterfaceDescriptor_TypeDef *interface )
1250 {
1251  if ( interface == NULL )
1252  {
1253  DEBUG_USB_API_PUTS( "\nUSBH_PrintInterfaceDescriptor(),"
1254  " interface NULL pointer" );
1255  EFM_ASSERT( false );
1256  return USB_STATUS_ILLEGAL;
1257  }
1258 
1259  USB_PRINTF( "\n\nInterface descriptor:" );
1260  USB_PRINTF( "\n bLength %d", interface->bLength );
1261  USB_PRINTF( "\n bDescriptorType 0x%02X", interface->bDescriptorType );
1262  USB_PRINTF( "\n bInterfaceNumber %d", interface->bInterfaceNumber );
1263  USB_PRINTF( "\n bAlternateSetting %d", interface->bAlternateSetting );
1264  USB_PRINTF( "\n bNumEndpoints %d", interface->bNumEndpoints );
1265  USB_PRINTF( "\n bInterfaceClass 0x%02X", interface->bInterfaceClass );
1266  USB_PRINTF( "\n bInterfaceSubClass 0x%02X", interface->bInterfaceSubClass );
1267  USB_PRINTF( "\n bInterfaceProtocol 0x%02X", interface->bInterfaceProtocol );
1268  USB_PRINTF( "\n iInterface %d\n", interface->iInterface );
1269 
1270  return USB_STATUS_OK;
1271 }
1272 #endif /* defined( USB_USE_PRINTF ) */
1273 
1274 #if defined( __ICCARM__ )
1275 #pragma diag_suppress=Pa039
1276 #endif
1277 /***************************************************************************/
1297 void USBH_PrintString( const char *pre,
1299  const char *post )
1300 {
1301  char *c;
1302 
1303  if ( pre )
1304  {
1305  USB_PUTS( pre );
1306  }
1307 
1308  if ( s )
1309  {
1310  c = (char*)&s->name;
1311  while ( *c )
1312  {
1313  USB_PUTCHAR( *c );
1314  c += 2;
1315  }
1316  }
1317 
1318  if ( post )
1319  {
1320  USB_PUTS( post );
1321  }
1322 }
1323 #if defined( __ICCARM__ )
1324 #pragma diag_default=Pa039
1325 #endif
1326 
1327  /*
1328  * A request for a configuration descriptor returns the configuration
1329  * descriptor, all interface descriptors, and endpoint descriptors for all
1330  * of the interfaces in a single request.
1331  * The first interface descriptor follows the configuration descriptor.
1332  * The endpoint descriptors for the first interface follow the first interface
1333  * descriptor.
1334  * If there are additional interfaces, their interface descriptor and endpoint
1335  * descriptors follow the first interface's endpoint descriptors.
1336  * Class-specific and/or vendor-specific descriptors follow the standard
1337  * descriptors they extend or modify.
1338  */
1339 
1340 /***************************************************************************/
1360 USB_ConfigurationDescriptor_TypeDef *USBH_QGetConfigurationDescriptor(
1361  const uint8_t *buf, int configIndex )
1362 {
1363  int i;
1364  const uint8_t *start, *end;
1366 
1367  dev = USBH_QGetDeviceDescriptor( buf );
1368  if ( dev )
1369  {
1370  if ( configIndex < dev->bNumConfigurations )
1371  {
1372  /* Start of first configuration descriptor */
1373  start = buf + sizeof( USBH_Device_TypeDef );
1374 
1375  /* Find end of avaiable data, NOTE: ep contains end of buf ! */
1376  end = SL_MIN(
1377  start + ((USB_ConfigurationDescriptor_TypeDef*)start)->wTotalLength,
1378  (uint8_t*)(((USBH_Device_TypeDef*)buf)->ep));
1379 
1380  /* Scan through, looking for correct configuration descriptor */
1381  i = 0;
1382  while ( start < end )
1383  {
1384  if ( *start == 0 )
1385  return NULL;
1386 
1387  if ( ( *start == USB_CONFIG_DESCSIZE ) &&
1388  ( *(start+1) == USB_CONFIG_DESCRIPTOR ) )
1389  {
1390  if ( i == configIndex )
1391  {
1392  return (USB_ConfigurationDescriptor_TypeDef*)start;
1393  }
1394  i++;
1395  }
1396 
1397  start += *start;
1398  }
1399  }
1400  }
1401  return NULL;
1402 }
1403 
1404 /***************************************************************************/
1416 USB_DeviceDescriptor_TypeDef *USBH_QGetDeviceDescriptor( const uint8_t *buf )
1417 {
1418  USB_DeviceDescriptor_TypeDef *dev = &((USBH_Device_TypeDef*)buf)->devDesc;
1419 
1420  if ( buf == NULL )
1421  {
1422  DEBUG_USB_API_PUTS( "\nUSBH_QGetDeviceDescriptor(), buf NULL pointer" );
1423  EFM_ASSERT( false );
1424  return NULL;
1425  }
1426 
1427  if ( ( dev->bLength == USB_DEVICE_DESCSIZE ) &&
1429  {
1430  return dev;
1431  }
1432  return NULL;
1433 }
1434 
1435 /***************************************************************************/
1463 USB_EndpointDescriptor_TypeDef *USBH_QGetEndpointDescriptor(
1464  const uint8_t *buf, int configIndex, int interfaceIndex, int endpointIndex )
1465 {
1466  int i;
1467  uint8_t *start, *end;
1469 
1470  itf = USBH_QGetInterfaceDescriptor( buf, configIndex, interfaceIndex );
1471  if ( itf )
1472  {
1473  if ( endpointIndex < itf->bNumEndpoints )
1474  {
1475  /* First possible endpoint descriptor */
1476  start = (uint8_t*)itf + USB_INTERFACE_DESCSIZE;
1477 
1478  /* Search until start of next interface decsriptor, or to end of buf */
1479  end = (uint8_t*)USBH_QGetInterfaceDescriptor(
1480  buf, configIndex, interfaceIndex + 1 );
1481  if ( end == NULL )
1482  {
1483  /* NOTE: ep contains end of buf ! */
1484  end = (uint8_t*)((USBH_Device_TypeDef*)buf)->ep;
1485  }
1486 
1487  /* Scan through, looking for correct endpoint descriptor */
1488  i = 0;
1489  while ( start < end )
1490  {
1491  if ( *start == 0 )
1492  return NULL;
1493 
1494  if ( ( *start == USB_ENDPOINT_DESCSIZE ) &&
1495  ( *(start+1) == USB_ENDPOINT_DESCRIPTOR ) )
1496  {
1497  if ( i == endpointIndex )
1498  {
1499  return (USB_EndpointDescriptor_TypeDef*)start;
1500  }
1501  i++;
1502  }
1503 
1504  start += *start;
1505  }
1506  }
1507  }
1508  return NULL;
1509 }
1510 
1511 /***************************************************************************/
1535 USB_InterfaceDescriptor_TypeDef *USBH_QGetInterfaceDescriptor(
1536  const uint8_t *buf, int configIndex, int interfaceIndex )
1537 {
1538  int i;
1539  uint8_t *start, *end;
1541 
1542  conf = USBH_QGetConfigurationDescriptor( buf, configIndex );
1543  if ( conf )
1544  {
1545  if ( interfaceIndex < conf->bNumInterfaces )
1546  {
1547  /* First interface descriptor */
1548  start = (uint8_t*)conf + USB_CONFIG_DESCSIZE;
1549 
1550  /* Search until start of next config decsriptor, or to end of buf */
1551  end = (uint8_t*)USBH_QGetConfigurationDescriptor( buf, configIndex + 1 );
1552  if ( end == NULL )
1553  {
1554  /* NOTE: ep contains end of buf ! */
1555  end = (uint8_t*)((USBH_Device_TypeDef*)buf)->ep;
1556  }
1557 
1558  /* Scan through, looking for correct interface descriptor */
1559  i = 0;
1560  while ( start < end )
1561  {
1562  if ( *start == 0 )
1563  return NULL;
1564 
1565  if ( ( *start == USB_INTERFACE_DESCSIZE ) &&
1566  ( *(start+1) == USB_INTERFACE_DESCRIPTOR ) )
1567  {
1568  if ( ( i == interfaceIndex ) &&
1569  ( i ==
1570  ((USB_InterfaceDescriptor_TypeDef*)start)->bInterfaceNumber ) )
1571  {
1572  return (USB_InterfaceDescriptor_TypeDef*)start;
1573  }
1574  i++;
1575  }
1576 
1577  start += *start;
1578  }
1579  }
1580  }
1581  return NULL;
1582 }
1583 
1584 /***************************************************************************/
1615 int USBH_QueryDeviceB( uint8_t *buf, size_t bufsize, uint8_t deviceSpeed )
1616 {
1617  USBH_Device_TypeDef *device = (USBH_Device_TypeDef*)buf;
1618 
1619  USBH_InitDeviceData( device, NULL, NULL, 0, deviceSpeed );
1620 
1621  device->speed = deviceSpeed;
1622  device->ep = (USBH_Ep_TypeDef*)(buf+bufsize);/* Save buffer end addr here ! */
1623 
1624  /* Get the first 8 bytes of the device desc to figure out device EP0 size */
1625  if ( 8 != USBH_GetDeviceDescriptorB( device,
1626  &device->devDesc,
1627  SL_MIN( 8U, bufsize ) ) )
1628  {
1629  return USB_STATUS_REQ_ERR;
1630  }
1631  device->ep0.packetSize = device->devDesc.bMaxPacketSize0;
1632 
1633  /* Get entire device descriptor */
1634  if ( USB_DEVICE_DESCSIZE != USBH_GetDeviceDescriptorB(
1635  device,
1636  buf + sizeof( USBH_Device_TypeDef ),
1637  SL_MIN( (size_t)USB_DEVICE_DESCSIZE, bufsize ) ) )
1638  {
1639  return USB_STATUS_REQ_ERR;
1640  }
1641  memcpy( &device->devDesc,
1642  buf + sizeof( USBH_Device_TypeDef ), USB_DEVICE_DESCSIZE );
1643 
1644  /* Get configuration descriptor. */
1645  if ( USB_CONFIG_DESCSIZE != USBH_GetConfigurationDescriptorB(
1646  device,
1647  buf + sizeof( USBH_Device_TypeDef ),
1648  SL_MIN( (size_t)USB_CONFIG_DESCSIZE,
1649  bufsize - (size_t)USB_DEVICE_DESCSIZE ),
1650  0 ) )
1651  {
1652  return USB_STATUS_REQ_ERR;
1653  }
1654  memcpy( &device->confDesc,
1655  buf + sizeof( USBH_Device_TypeDef ), USB_CONFIG_DESCSIZE );
1656 
1657  /* Get complete configuration descriptor. NOTE: Descriptor data is */
1658  /* appended at the end of the device data structure ! */
1659  if ( ( USB_CONFIG_DESCSIZE + USB_INTERFACE_DESCSIZE ) >
1660  USBH_GetConfigurationDescriptorB(
1661  device,
1662  buf + sizeof( USBH_Device_TypeDef ),
1663  SL_MIN( device->confDesc.wTotalLength,
1664  bufsize - sizeof( USBH_Device_TypeDef )),
1665  0 ) )
1666  {
1667  return USB_STATUS_REQ_ERR;
1668  }
1669 
1670  return USB_STATUS_OK;
1671 }
1672 
1673 /***************************************************************************/
1706 int USBH_Read( USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout,
1707  USB_XferCompleteCb_TypeDef callback )
1708 {
1709  USBH_Hc_TypeDef *hc = &hcs[ ep->hcIn ];
1711 
1712  if ( ep == NULL )
1713  {
1714  DEBUG_USB_API_PUTS( "\nUSBH_Read(), ep NULL pointer" );
1715  EFM_ASSERT( false );
1716  return USB_STATUS_ILLEGAL;
1717  }
1718 
1719  if ( !USBH_DeviceConnected() )
1720  {
1721  DEBUG_USB_API_PUTS( "\nUSBH_Read(), No device connected" );
1722  return USB_STATUS_ILLEGAL;
1723  }
1724 
1725  if ( ( byteCount > MAX_XFER_LEN ) ||
1726  ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER ) )
1727  {
1728  DEBUG_USB_API_PUTS( "\nUSBH_Read(), Illegal transfer size" );
1729  EFM_ASSERT( false );
1730  return USB_STATUS_ILLEGAL;
1731  }
1732 
1733  if ( (uint32_t)data & 3 )
1734  {
1735  DEBUG_USB_API_PUTS( "\nUSBH_Read(), Misaligned data buffer" );
1736  EFM_ASSERT( false );
1737  return USB_STATUS_ILLEGAL;
1738  }
1739 
1741  if ( ep->state != H_EP_IDLE )
1742  {
1743  CORE_EXIT_ATOMIC();
1744  DEBUG_USB_API_PUTS( "\nUSBH_Read(), Endpoint is busy" );
1745  return USB_STATUS_EP_BUSY;
1746  }
1747 
1748  if ( !ep->in )
1749  {
1750  CORE_EXIT_ATOMIC();
1751  DEBUG_USB_API_PUTS( "\nUSBH_Read(), Illegal EP direction" );
1752  EFM_ASSERT( false );
1753  return USB_STATUS_ILLEGAL;
1754  }
1755 
1756  if ( !hc->idle )
1757  {
1758  CORE_EXIT_ATOMIC();
1759  DEBUG_USB_API_PUTS( "\nUSBH_Read(), Host channel is busy" );
1760  return USB_STATUS_HC_BUSY;
1761  }
1762 
1763  ep->xferCompleted = false;
1764  ep->state = H_EP_DATA_IN;
1765  ep->xferCompleteCb = callback;
1766  ep->buf = data;
1767  ep->remaining = byteCount;
1768  ep->xferred = 0;
1769  ep->timeout = timeout;
1770 
1771  hc->buf = data;
1772  hc->xferred = 0;
1773  hc->remaining = byteCount;
1774  hc->ep = ep;
1775 
1776  if ( ep->type == USB_EPTYPE_INTR )
1777  {
1778  if ( timeout )
1779  timeout = SL_MIN( timeout, ep->epDesc.bInterval );
1780  else
1781  timeout = ep->epDesc.bInterval;
1782  }
1783 
1784  if ( timeout )
1785  {
1786  USBTIMER_Start( ep->hcIn + HOSTCH_TIMER_INDEX,
1787  timeout, hcTimeoutFunc[ ep->hcIn ] );
1788  }
1789 
1790  USBHHAL_HCInit( ep->hcIn );
1791  USBHHAL_HCStart( ep->hcIn );
1792  CORE_EXIT_ATOMIC();
1793  return USB_STATUS_OK;
1794 }
1795 
1796 /***************************************************************************/
1827 int USBH_ReadB( USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout )
1828 {
1829  int retVal;
1830 
1832  {
1833  DEBUG_USB_API_PUTS( "\nUSBH_ReadB() called with int's disabled" );
1834  EFM_ASSERT( false );
1835  return USB_STATUS_ILLEGAL;
1836  }
1837 
1838  retVal = USBH_Read( ep, data, byteCount, timeout, NULL );
1839 
1840  if ( retVal == USB_STATUS_OK )
1841  {
1842  while ( ! ep->xferCompleted );
1843 
1844  if ( ( retVal = ep->xferStatus ) == USB_STATUS_OK )
1845  {
1846  retVal = ep->xferred;
1847  }
1848  }
1849 
1850  return retVal;
1851 }
1852 
1853 /***************************************************************************/
1873 int USBH_SetAddressB( USBH_Device_TypeDef *device, uint8_t deviceAddress )
1874 {
1875  int retVal;
1876 
1877  if ( device == NULL )
1878  {
1879  DEBUG_USB_API_PUTS( "\nUSBH_SetAddressB(), device NULL pointer" );
1880  EFM_ASSERT( false );
1881  return USB_STATUS_ILLEGAL;
1882  }
1883 
1884  if ( deviceAddress > USB_MAX_DEVICE_ADDRESS )
1885  {
1886  DEBUG_USB_API_PUTS( "\nUSBH_SetAddressB(), Illegal device address" );
1887  EFM_ASSERT( false );
1888  return USB_STATUS_ILLEGAL;
1889  }
1890 
1891  retVal = USBH_ControlMsgB(
1892  &device->ep0,
1894  USB_SETUP_TYPE_STANDARD_MASK, /* bmRequestType */
1895  SET_ADDRESS, /* bRequest */
1896  deviceAddress, /* wValue */
1897  0, /* wIndex */
1898  0, /* wLength */
1899  NULL, /* void* data */
1900  DEFAULT_CTRL_TIMEOUT ); /* int timeout */
1901 
1902  if ( retVal == USB_STATUS_OK )
1903  {
1904  device->addr = deviceAddress;
1905  }
1906  return retVal;
1907 }
1908 
1909 /***************************************************************************/
1930 int USBH_SetAltInterfaceB( USBH_Device_TypeDef *device,
1931  uint8_t interfaceIndex, uint8_t alternateSetting )
1932 {
1933  int i, retVal;
1934 
1935  if ( device == NULL )
1936  {
1937  DEBUG_USB_API_PUTS( "\nUSBH_SetAltInterfaceB(), device NULL pointer" );
1938  EFM_ASSERT( false );
1939  return USB_STATUS_ILLEGAL;
1940  }
1941 
1942  retVal = USBH_ControlMsgB(
1943  &device->ep0,
1945  USB_SETUP_TYPE_STANDARD_MASK, /* bmRequestType */
1946  SET_INTERFACE, /* bRequest */
1947  alternateSetting, /* wValue */
1948  interfaceIndex, /* wIndex */
1949  0, /* wLength */
1950  NULL, /* void* data */
1951  DEFAULT_CTRL_TIMEOUT ); /* int timeout */
1952 
1953  if ( retVal == USB_STATUS_OK )
1954  {
1955  // Alternate settings are mutually exclusive within the interface
1956 
1957  // We should:
1958  // Deactivate ep's in previous alternate interface setting
1959  // Activate ep's in the new alternate setting of the interface
1960 
1961  for ( i=0; i<device->numEp; i++ ) /* Reset all data toggles */
1962  {
1963  device->ep[i].toggle = USB_PID_DATA0;
1964  }
1965  }
1966 
1967  return retVal;
1968 }
1969 
1970 /***************************************************************************/
1990 int USBH_SetConfigurationB( USBH_Device_TypeDef *device, uint8_t configValue )
1991 {
1992  int i, retVal;
1993 
1994  if ( device == NULL )
1995  {
1996  DEBUG_USB_API_PUTS( "\nUSBH_SetConfigurationB(), device NULL pointer" );
1997  EFM_ASSERT( false );
1998  return USB_STATUS_ILLEGAL;
1999  }
2000 
2001  retVal = USBH_ControlMsgB(
2002  &device->ep0,
2004  USB_SETUP_TYPE_STANDARD_MASK, /* bmRequestType */
2005  SET_CONFIGURATION, /* bRequest */
2006  configValue, /* wValue */
2007  0, /* wIndex */
2008  0, /* wLength */
2009  NULL, /* void* data */
2010  DEFAULT_CTRL_TIMEOUT ); /* int timeout */
2011 
2012  if ( retVal == USB_STATUS_OK )
2013  {
2014  // Configurations are mutually exclusive within the device
2015 
2016  // Should:
2017  // Deactivate ep's in previous configuration
2018  // Activate ep's in new configuration
2019 
2020  for ( i=0; i<device->numEp; i++ ) /* Reset all data toggles */
2021  {
2022  device->ep[i].toggle = USB_PID_DATA0;
2023  }
2024  }
2025 
2026  return retVal;
2027 }
2028 
2029 /***************************************************************************/
2044 int USBH_StallEpB( USBH_Ep_TypeDef *ep )
2045 {
2046  if ( ep == NULL )
2047  {
2048  DEBUG_USB_API_PUTS( "\nUSBH_StallEpB(), ep NULL pointer" );
2049  EFM_ASSERT( false );
2050  return USB_STATUS_ILLEGAL;
2051  }
2052 
2053  return USBH_ControlMsgB( &ep->parentDevice->ep0,
2055  USB_SETUP_TYPE_STANDARD_MASK, /* bmRequestType */
2056  SET_FEATURE, /* bRequest */
2057  USB_FEATURE_ENDPOINT_HALT, /* wValue */
2058  ep->addr, /* wIndex */
2059  0, /* wLength */
2060  NULL, /* void* data */
2061  DEFAULT_CTRL_TIMEOUT ); /* int timeout */
2062 }
2063 
2064 /***************************************************************************/
2071 void USBH_Stop( void )
2072 {
2073  int i;
2074 
2075  USBTIMER_Stop( HOSTPORT_TIMER_INDEX );
2076  for ( i = 0; i < NUM_HC_USED + 2; i++ )
2077  {
2078  USBTIMER_Stop( i + HOSTCH_TIMER_INDEX );
2079  }
2081  USBHAL_DisableGlobalInt();
2082  )
2083  USBH_PortVbusOn( false );
2084  USBHAL_DisablePhyPins();
2085  /* Turn off USB clocks. */
2086  CMU->HFCORECLKEN0 &= ~(CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC);
2087 }
2088 
2089 /***************************************************************************/
2104 int USBH_UnStallEpB( USBH_Ep_TypeDef *ep )
2105 {
2106  int retVal;
2107 
2108  if ( ep == NULL )
2109  {
2110  DEBUG_USB_API_PUTS( "\nUSBH_UnStallEpB(), ep NULL pointer" );
2111  EFM_ASSERT( false );
2112  return USB_STATUS_ILLEGAL;
2113  }
2114 
2115  retVal = USBH_ControlMsgB( &ep->parentDevice->ep0,
2117  USB_SETUP_TYPE_STANDARD_MASK, /* bmRequestType */
2118  CLEAR_FEATURE, /* bRequest */
2119  USB_FEATURE_ENDPOINT_HALT, /* wValue */
2120  ep->addr, /* wIndex */
2121  0, /* wLength */
2122  NULL, /* void* data */
2123  DEFAULT_CTRL_TIMEOUT ); /* int timeout */
2124 
2125  if ( retVal == USB_STATUS_OK )
2126  {
2127  ep->toggle = USB_PID_DATA0;
2128  }
2129 
2130  return retVal;
2131 }
2132 
2135 static void InitUsb( void )
2136 {
2137  int i;
2138 
2139  memset( hcs, 0, sizeof( hcs ) );
2140  for ( i = 0; i < NUM_HC_USED + 2; i++ )
2141  {
2142  hcs[ i ].idle = true;
2143  }
2144 
2146  USBHHAL_CoreInit( USBH_initData.rxFifoSize, USBH_initData.nptxFifoSize,
2147  USBH_initData.ptxFifoSize );
2148  NVIC_ClearPendingIRQ( USB_IRQn );
2149  )
2150 }
2151 
2154 /***************************************************************************/
2181 int USBH_WaitForDeviceConnectionB( uint8_t *buf, int timeoutInSeconds )
2182 {
2183  bool xferError;
2184  USBH_Device_TypeDef *device;
2185  int accumulatedTime, deadLine;
2186 
2187  if ( buf == NULL )
2188  {
2189  DEBUG_USB_API_PUTS( "\nUSBH_WaitForDeviceConnectionB(),"
2190  " buf NULL pointer" );
2191  EFM_ASSERT( false );
2192  return USB_STATUS_ILLEGAL;
2193  }
2194 
2195  xferError = false;
2196  accumulatedTime = 0;
2197  USBH_attachRetryCount = 0;
2198  deadLine = timeoutInSeconds * 1000;
2199  device = (USBH_Device_TypeDef*)buf;
2200 
2201  while ( 1 )
2202  {
2203  /* If USB is enabled, turn it off. */
2204  if ( USBHHAL_InitializedAndPowered() )
2205  {
2206  USBH_PortVbusOn( false );
2207  if ( deadLine )
2208  accumulatedTime += PORT_VBUS_DELAY;
2209  }
2210 
2211  /* Reset and init USB core. */
2212  InitUsb();
2213  if ( deadLine )
2214  accumulatedTime += 50;
2215 
2216  /* Turn on VBUS. */
2217  USBH_PortVbusOn( true );
2218  DEBUG_USB_INT_LO_PUTCHAR( '1' );
2219  if ( deadLine )
2220  accumulatedTime += PORT_VBUS_DELAY;
2221 
2222  /* Enable interrupts from USB core. */
2224  USBHHAL_EnableInts();
2225  USBHAL_EnableGlobalInt();
2226  )
2227 
2228  /* Wait for device connection. */
2229  while ( 1 )
2230  {
2231  if ( USBH_DeviceConnected() )
2232  break;
2233 
2234  if ( ( deadLine ) &&
2235  ( accumulatedTime >= deadLine ) )
2236  {
2237  return USB_STATUS_TIMEOUT;
2238  }
2239 
2240 #if ( USB_VBUSOVRCUR_PORT != USB_VBUSOVRCUR_PORT_NONE )
2241  if ( GPIO_PinInGet( USB_VBUSOVRCUR_PORT, USB_VBUSOVRCUR_PIN ) ==
2242  USB_VBUSOVRCUR_POLARITY )
2243  {
2244  DEBUG_USB_INT_LO_PUTCHAR( '~' );
2245  USBHHAL_PortReset( false );
2246  USBHHAL_VbusOn( false );
2247  USBTIMER_Stop( HOSTPORT_TIMER_INDEX );
2248  USBH_portStatus = H_PORT_OVERCURRENT;
2250  }
2251 #endif
2252  USBTIMER_DelayMs( 50 );
2253  if ( deadLine )
2254  accumulatedTime += 50;
2255  }
2256 
2257  /* Reset recovery time, the USB standard says 10ms. Extend the */
2258  /* timeout to be lenient with non compliant devices. */
2259  USBTIMER_DelayMs( 100 );
2260  if ( deadLine )
2261  accumulatedTime += 100;
2262 
2263  /* Do one USB transfer to check if device connection is OK. */
2264 
2265  USBH_InitDeviceData( device, NULL, NULL, 0, USBH_GetPortSpeed() );
2266 
2267  /* Get the first 8 bytes of the device descriptor */
2268  if ( 8 == USBH_GetDeviceDescriptorB( device, &device->devDesc, 8 ) )
2269  {
2270  return USB_STATUS_OK;
2271  }
2272  else
2273  {
2274  xferError = true;
2275  if ( deadLine )
2276  accumulatedTime += DEFAULT_CTRL_TIMEOUT;
2277  }
2278 
2279  /* Disable USB, power down VBUS. */
2280  USBH_Stop();
2281  /* Enable USB clocks again, USBH_Stop() turns them off. */
2282  CMU->HFCORECLKEN0 |= CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC;
2283 
2284  if ( deadLine )
2285  accumulatedTime += PORT_VBUS_DELAY;
2286 
2287  if ( ( deadLine ) &&
2288  ( accumulatedTime >= deadLine ) )
2289  break;
2290 
2291  USBH_attachRetryCount = ( USBH_attachRetryCount + 1 ) %
2292  ( sizeof( USBH_attachTiming ) /
2293  sizeof( USBH_AttachTiming_TypeDef ) );
2294  }
2295 
2296  if ( xferError )
2298 
2299  return USB_STATUS_TIMEOUT;
2300 }
2301 
2302 /***************************************************************************/
2333 int USBH_Write( USBH_Ep_TypeDef *ep, void *data, int byteCount,
2334  int timeout, USB_XferCompleteCb_TypeDef callback )
2335 {
2336  USBH_Hc_TypeDef *hc = &hcs[ ep->hcOut ];
2338 
2339  if ( ep == NULL )
2340  {
2341  DEBUG_USB_API_PUTS( "\nUSBH_Write(), ep NULL pointer" );
2342  EFM_ASSERT( false );
2343  return USB_STATUS_ILLEGAL;
2344  }
2345 
2346  if ( !USBH_DeviceConnected() )
2347  {
2348  DEBUG_USB_API_PUTS( "\nUSBH_Write(), No device connected" );
2349  return USB_STATUS_ILLEGAL;
2350  }
2351 
2352  if ( ( byteCount > MAX_XFER_LEN ) ||
2353  ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER ) )
2354  {
2355  DEBUG_USB_API_PUTS( "\nUSBH_Write(), Illegal transfer size" );
2356  EFM_ASSERT( false );
2357  return USB_STATUS_ILLEGAL;
2358  }
2359 
2360  if ( (uint32_t)data & 3 )
2361  {
2362  DEBUG_USB_API_PUTS( "\nUSBH_Write(), Misaligned data buffer" );
2363  EFM_ASSERT( false );
2364  return USB_STATUS_ILLEGAL;
2365  }
2366 
2368  if ( ep->state != H_EP_IDLE )
2369  {
2370  CORE_EXIT_ATOMIC();
2371  DEBUG_USB_API_PUTS( "\nUSBH_Write(), Endpoint is busy" );
2372  return USB_STATUS_EP_BUSY;
2373  }
2374 
2375  if ( ep->in )
2376  {
2377  CORE_EXIT_ATOMIC();
2378  DEBUG_USB_API_PUTS( "\nUSBH_Write(), Illegal EP direction" );
2379  EFM_ASSERT( false );
2380  return USB_STATUS_ILLEGAL;
2381  }
2382 
2383  if ( !hc->idle )
2384  {
2385  CORE_EXIT_ATOMIC();
2386  DEBUG_USB_API_PUTS( "\nUSBH_Write(), Host channel is busy" );
2387  return USB_STATUS_HC_BUSY;
2388  }
2389 
2390  ep->xferCompleted = false;
2391  ep->state = H_EP_DATA_OUT;
2392  ep->xferCompleteCb = callback;
2393  ep->buf = data;
2394  ep->remaining = byteCount;
2395  ep->xferred = 0;
2396  ep->timeout = timeout;
2397 
2398  hc->buf = data;
2399  hc->xferred = 0;
2400  hc->remaining = byteCount;
2401  hc->ep = ep;
2402 
2403  if ( ep->type == USB_EPTYPE_INTR )
2404  {
2405  if ( timeout )
2406  timeout = SL_MIN( timeout, ep->epDesc.bInterval );
2407  else
2408  timeout = ep->epDesc.bInterval;
2409  }
2410 
2411  if ( timeout )
2412  {
2413  USBTIMER_Start( ep->hcOut + HOSTCH_TIMER_INDEX,
2414  timeout, hcTimeoutFunc[ ep->hcOut ] );
2415  }
2416 
2417  USBHHAL_HCInit( ep->hcOut );
2418  USBHHAL_HCStart( ep->hcOut );
2419  CORE_EXIT_ATOMIC();
2420  return USB_STATUS_OK;
2421 }
2422 
2423 /***************************************************************************/
2452 int USBH_WriteB( USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout )
2453 {
2454  int retVal;
2455 
2457  {
2458  DEBUG_USB_API_PUTS( "\nUSBH_WriteB() called with int's disabled" );
2459  EFM_ASSERT( false );
2460  return USB_STATUS_ILLEGAL;
2461  }
2462 
2463  retVal = USBH_Write( ep, data, byteCount, timeout, NULL );
2464 
2465  if ( retVal == USB_STATUS_OK )
2466  {
2467  while ( ! ep->xferCompleted );
2468 
2469  if ( ( retVal = ep->xferStatus ) == USB_STATUS_OK )
2470  {
2471  retVal = ep->xferred;
2472  }
2473  }
2474 
2475  return retVal;
2476 }
2477 
2478 /******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************/
2824 #endif /* defined( USB_HOST ) */
2825 #endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
Clock management unit (CMU) API.
void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
Select reference clock/oscillator used for a clock branch.
Definition: em_cmu.c:2521
#define SET_INTERFACE
Definition: em_usb.h:96
#define USB_INTERFACE_DESCSIZE
Definition: em_usb.h:154
#define CMU_HFCORECLKEN0_USB
Definition: efm32hg_cmu.h:892
#define SET_CONFIGURATION
Definition: em_usb.h:94
#define CORE_IN_IRQ_CONTEXT()
Definition: em_core.h:213
#define USB_EPNUM_MASK
Definition: em_usb.h:187
#define CORE_DECLARE_IRQ_STATE
Definition: em_core.h:85
#define USB_SETUP_DIR_D2H
Definition: em_usb.h:69
void USBTIMER_Stop(uint32_t id)
Stop a timer.
Definition: em_usbtimer.c:306
USB protocol stack library API for EFM32/EZR32.
#define USB_SETUP_DIR_H2D
Definition: em_usb.h:70
#define USB
#define USB_STRING_DESCRIPTOR
Definition: em_usb.h:126
#define USB_SETUP_RECIPIENT_ENDPOINT
Definition: em_usb.h:83
int USB_PRINTF(const char *format,...)
Transmit "printf" formated data on the debug serial port.
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define USB_SETUP_DIR_MASK
Definition: em_usb.h:68
void(* USBTIMER_Callback_TypeDef)(void)
USBTIMER callback function.
Definition: em_usb.h:673
void USBTIMER_DelayMs(uint32_t msec)
Active wait millisecond delay function. Can also be used inside interrupt handlers.
Definition: em_usbtimer.c:138
USB Interface Descriptor.
Definition: em_usb.h:459
int(* USB_XferCompleteCb_TypeDef)(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining)
USB transfer callback function.
Definition: em_usb.h:663
USB_Status_TypeDef
USB transfer status enumerator.
Definition: em_usb.h:319
#define CORE_ENTER_ATOMIC()
Definition: em_core.h:138
#define USB_DEVICE_DESCRIPTOR
Definition: em_usb.h:124
#define CORE_ATOMIC_SECTION(yourcode)
Definition: em_core.h:126
#define SET_ADDRESS
Definition: em_usb.h:90
#define USB_CONFIG_DESCSIZE
Definition: em_usb.h:153
void USB_PUTS(const char *p)
Transmit a zero terminated string on the debug serial port.
General Purpose IO (GPIO) peripheral API.
#define USB_EPTYPE_CTRL
Definition: em_usb.h:177
unsigned short char16_t
Definition: em_usb.h:246
#define CONFIG_DESC_BM_TRANSFERTYPE
Definition: em_usb.h:194
USB protocol stack library API for EFM32/EZR32.
USB Endpoint Descriptor.
Definition: em_usb.h:500
#define USB_SETUP_RECIPIENT_DEVICE
Definition: em_usb.h:81
Core interrupt handling API.
#define USB_SETUP_RECIPIENT_INTERFACE
Definition: em_usb.h:82
#define USB_DEVICE_DESCSIZE
Definition: em_usb.h:152
#define CLEAR_FEATURE
Definition: em_usb.h:88
#define CMU_HFCORECLKEN0_USBC
Definition: efm32hg_cmu.h:887
#define USB_SETUP_TYPE_STANDARD_MASK
Definition: em_usb.h:76
#define CORE_IRQ_DISABLED()
Definition: em_core.h:210
#define CORE_EXIT_ATOMIC()
Definition: em_core.h:142
#define USB_INTERFACE_DESCRIPTOR
Definition: em_usb.h:128
#define SET_FEATURE
Definition: em_usb.h:89
#define USB_ENDPOINT_DESCSIZE
Definition: em_usb.h:155
#define USB_EPTYPE_INTR
Definition: em_usb.h:180
#define USB_MAX_DEVICE_ADDRESS
Definition: em_usb.h:189
#define GET_DESCRIPTOR
Definition: em_usb.h:91
#define USB_FEATURE_ENDPOINT_HALT
Definition: em_usb.h:199
USB protocol stack library, low level USB peripheral access.
void USBTIMER_Init(void)
Activate the hardware timer used to pace the 1 millisecond timer system.
Definition: em_usbtimer.c:193
#define SL_MIN(a, b)
Macro for getting minimum value. No sideeffects, a and b are evaluated once only. ...
Definition: em_common.h:137
USB Configuration Descriptor.
Definition: em_usb.h:430
#define USB_CONFIG_DESCRIPTOR
Definition: em_usb.h:125
#define USB_SETUP_PKT_SIZE
Definition: em_usb.h:186
USB protocol stack library, internal type definitions.
USB Device Descriptor.
Definition: em_usb.h:406
int USB_PUTCHAR(char c)
Transmit a single char on the debug serial port.
void USBTIMER_Start(uint32_t id, uint32_t timeout, USBTIMER_Callback_TypeDef callback)
Start a timer.
Definition: em_usbtimer.c:237
__STATIC_INLINE unsigned int GPIO_PinInGet(GPIO_Port_TypeDef port, unsigned int pin)
Read the pad value for a single pin in a GPIO port.
Definition: em_gpio.h:781
#define USB_ENDPOINT_DESCRIPTOR
Definition: em_usb.h:129
USB String Descriptor.
Definition: em_usb.h:514
#define CMU