EFM32 Happy Gecko Software Documentation  efm32hg-doc-5.1.2
em_usbhep.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_usbtypes.h"
22 #include "em_usbhal.h"
23 #include "em_usbh.h"
24 
27 /*
28  * USBHEP_CtrlEpHandler() is called each time a packet has been transmitted
29  * or recieved on host channels serving a device default endpoint (EP0).
30  * A state machine navigate us through the phases of a control transfer
31  * according to "chapter 9" in the USB spec.
32  */
33 void USBHEP_CtrlEpHandler( USBH_Ep_TypeDef *ep, USB_Status_TypeDef result )
34 {
35 uint8_t direction;
36 
37  switch ( ep->state )
38  {
39  /* ------- Setup stage ------------------------------------------------ */
40  case H_EP_SETUP: /* SETUP packet sent successfully */
41  if ( result == USB_STATUS_OK )
42  {
43  direction = ep->setup.bmRequestType & USB_SETUP_DIR_MASK;
44 
45  /* Check if there is a data stage */
46  if ( ep->setup.wLength != 0 )
47  {
48  if ( direction == USB_SETUP_DIR_D2H ) /* Data direction is IN */
49  {
50  USBH_CtlReceiveData( ep, ep->setup.wLength );
51  ep->state = H_EP_DATA_IN;
52  break;
53  }
54  else /* Data direction is OUT */
55  {
56  USBH_CtlSendData( ep, ep->setup.wLength );
57  ep->state = H_EP_DATA_OUT;
58  break;
59  }
60  }
61  USBH_CtlReceiveData( ep, 0 ); /* No data stage */
62  ep->state = H_EP_STATUS_IN; /* Get zero length in status packet */
63  break;
64  }
65 
66  ep->setupErrCnt++;
67 
68  /*
69  * After a halt condition is encountered or an error is detected by the
70  * host, a control endpoint is allowed to recover by accepting the next
71  * SETUP package. If the next Setup package is not accepted, a device
72  * reset will ultimately be needed.
73  */
74 
75  if ( ( ep->setupErrCnt == 1 ) && ( ep->timeout != 0 ) )
76  {
77  USBH_CtlSendSetup( ep ); /* Retry */
78  break;
79  }
80  USBHEP_TransferDone( ep, result );
81  break;
82 
83 
84  /* ------- Data IN stage ---------------------------------------------- */
85  case H_EP_DATA_IN: /* Data received */
86  if ( result == USB_STATUS_OK )
87  {
88  USBH_CtlSendData( ep, 0 ); /* Send zero length out status packet */
89  ep->state = H_EP_STATUS_OUT;
90  break;
91  }
92  USBHEP_TransferDone( ep, result );
93  break;
94 
95 
96  /* ------- Data OUT stage --------------------------------------------- */
97  case H_EP_DATA_OUT: /* Data sent */
98  if ( result == USB_STATUS_OK )
99  {
100  USBH_CtlReceiveData( ep, 0 ); /* Get zero length in status packet */
101  ep->state = H_EP_STATUS_IN;
102  break;
103  }
104  USBHEP_TransferDone( ep, result );
105  break;
106 
107 
108  /* ------- Status IN/OUT stage ---------------------------------------- */
109  case H_EP_STATUS_IN: /* Status packet received */
110  case H_EP_STATUS_OUT : /* Status packet sent */
111  USBHEP_TransferDone( ep, result );
112  break;
113 
114 
115  case H_EP_IDLE:
116  break;
117  }
118 }
119 
120 /*
121  * USBHEP_EpHandler() is called each time a packet has been transmitted
122  * or recieved on a host channel serving a non-control device endpoint.
123  */
124 void USBHEP_EpHandler( USBH_Ep_TypeDef *ep, USB_Status_TypeDef result )
125 {
126  switch ( ep->state )
127  {
128  case H_EP_DATA_IN:
129  case H_EP_DATA_OUT:
130  USBHEP_TransferDone( ep, result );
131  break;
132 
133  default:
134  case H_EP_IDLE:
135  break;
136  }
137 }
138 
139 /*
140  * USBHEP_TransferDone() is called on transfer completion on all types of
141  * device endpoints.
142  */
143 void USBHEP_TransferDone( USBH_Ep_TypeDef *ep, USB_Status_TypeDef result )
144 {
145  int hcnum;
147 
148  ep->xferCompleted = true;
149  ep->xferStatus = result;
150  ep->state = H_EP_IDLE;
151 
152  if ( ep->type == USB_EPTYPE_CTRL )
153  {
154  hcnum = ep->setup.Direction == USB_SETUP_DIR_IN ? ep->hcIn : ep->hcOut;
155 
156  if ( ep->timeout )
157  USBTIMER_Stop( ep->hcOut + HOSTCH_TIMER_INDEX );
158 
159  ep->xferred = hcs[ hcnum ].xferred;
160  ep->remaining = hcs[ hcnum ].remaining;
161 
162  hcs[ ep->hcIn ].idle = true;
163  hcs[ ep->hcOut ].idle = true;
164 
165  if ( ep->setup.wLength == 0 )
166  {
167  ep->xferred = 0;
168  }
169  }
170  else
171  {
172  hcnum = ep->in ? ep->hcIn : ep->hcOut;
173 
174  if ( ep->timeout || ep->type == USB_EPTYPE_INTR )
175  USBTIMER_Stop( hcnum + HOSTCH_TIMER_INDEX );
176 
177  hcs[ hcnum ].idle = true;
178  ep->xferred = hcs[ hcnum ].xferred;
179  ep->remaining = hcs[ hcnum ].remaining;
180  }
181 
182  if ( ep->xferCompleteCb )
183  {
184  callback = ep->xferCompleteCb;
185  ep->xferCompleteCb = NULL;
186  (callback)( result, ep->xferred, ep->remaining );
187  }
188 }
189 
192 #endif /* defined( USB_HOST ) */
193 #endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
#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.
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define USB_SETUP_DIR_MASK
Definition: em_usb.h:68
#define USB_SETUP_DIR_IN
Definition: em_usb.h:67
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 USB_EPTYPE_CTRL
Definition: em_usb.h:177
USB protocol stack library API for EFM32/EZR32.
#define USB_EPTYPE_INTR
Definition: em_usb.h:180
USB protocol stack library, low level USB peripheral access.
USB protocol stack library, internal type definitions.