1 /**
2 ******************************************************************************
3 * @file usbd_core.c
4 * @author MCD Application Team
5 * @version V1.0.0
6 * @date 22-July-2011
7 * @brief This file provides all the USBD core functions.
8 ******************************************************************************
9 * @attention
10 *
11 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
12 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
13 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
14 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
15 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
16 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
17 *
18 * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
19 ******************************************************************************
20 */
21
22 /* Includes ------------------------------------------------------------------*/
23 #include "usbd_core.h"
24 #include "usbd_req.h"
25 #include "usbd_ioreq.h"
26 #include "usb_dcd_int.h"
27 #include "usb_bsp.h"
28
29 /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
30 * @{
31 */
32
33
34 /** @defgroup USBD_CORE
35 * @brief usbd core module
36 * @{
37 */
38
39 /** @defgroup USBD_CORE_Private_TypesDefinitions
40 * @{
41 */
42 /**
43 * @}
44 */
45
46
47 /** @defgroup USBD_CORE_Private_Defines
48 * @{
49 */
50
51 /**
52 * @}
53 */
54
55
56 /** @defgroup USBD_CORE_Private_Macros
57 * @{
58 */
59 /**
60 * @}
61 */
62
63
64
65
66 /** @defgroup USBD_CORE_Private_FunctionPrototypes
67 * @{
68 */
69 static uint8_t USBD_SetupStage(USB_OTG_CORE_HANDLE *pdev);
70 static uint8_t USBD_DataOutStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum);
71 static uint8_t USBD_DataInStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum);
72 static uint8_t USBD_SOF(USB_OTG_CORE_HANDLE *pdev);
73 static uint8_t USBD_Reset(USB_OTG_CORE_HANDLE *pdev);
74 static uint8_t USBD_Suspend(USB_OTG_CORE_HANDLE *pdev);
75 static uint8_t USBD_Resume(USB_OTG_CORE_HANDLE *pdev);
76 #ifdef VBUS_SENSING_ENABLED
77 static uint8_t USBD_DevConnected(USB_OTG_CORE_HANDLE *pdev);
78 static uint8_t USBD_DevDisconnected(USB_OTG_CORE_HANDLE *pdev);
79 #endif
80 static uint8_t USBD_IsoINIncomplete(USB_OTG_CORE_HANDLE *pdev);
81 static uint8_t USBD_IsoOUTIncomplete(USB_OTG_CORE_HANDLE *pdev);
82 /**
83 * @}
84 */
85
86 /** @defgroup USBD_CORE_Private_Variables
87 * @{
88 */
89
90
91
92 USBD_DCD_INT_cb_TypeDef USBD_DCD_INT_cb =
93 {
94 USBD_DataOutStage,
95 USBD_DataInStage,
96 USBD_SetupStage,
97 USBD_SOF,
98 USBD_Reset,
99 USBD_Suspend,
100 USBD_Resume,
101 USBD_IsoINIncomplete,
102 USBD_IsoOUTIncomplete,
103 #ifdef VBUS_SENSING_ENABLED
104 USBD_DevConnected,
105 USBD_DevDisconnected,
106 #endif
107 };
108
109 USBD_DCD_INT_cb_TypeDef *USBD_DCD_INT_fops = &USBD_DCD_INT_cb;
110 /**
111 * @}
112 */
113
114 /** @defgroup USBD_CORE_Private_Functions
115 * @{
116 */
117
118 /**
119 * @brief USBD_Init
120 * Initailizes the device stack and load the class driver
121 * @param pdev: device instance
122 * @param core_address: USB OTG core ID
123 * @param class_cb: Class callback structure address
124 * @param usr_cb: User callback structure address
125 * @retval None
126 */
USBD_Init(USB_OTG_CORE_HANDLE * pdev,USB_OTG_CORE_ID_TypeDef coreID,USBD_DEVICE * pDevice,USBD_Class_cb_TypeDef * class_cb,USBD_Usr_cb_TypeDef * usr_cb)127 void USBD_Init(USB_OTG_CORE_HANDLE *pdev,
128 USB_OTG_CORE_ID_TypeDef coreID,
129 USBD_DEVICE *pDevice,
130 USBD_Class_cb_TypeDef *class_cb,
131 USBD_Usr_cb_TypeDef *usr_cb)
132 {
133 /* Hardware Init */
134 USB_OTG_BSP_Init(pdev);
135
136 USBD_DeInit(pdev);
137
138 /*Register class and user callbacks */
139 pdev->dev.class_cb = class_cb;
140 pdev->dev.usr_cb = usr_cb;
141 pdev->dev.usr_device = pDevice;
142
143 /* set USB OTG core params */
144 DCD_Init(pdev , coreID);
145
146 /* Upon Init call usr callback */
147 pdev->dev.usr_cb->Init();
148
149 /* Enable Interrupts */
150 USB_OTG_BSP_EnableInterrupt(pdev);
151 }
152
153 /**
154 * @brief USBD_DeInit
155 * Re-Initialize th deviuce library
156 * @param pdev: device instance
157 * @retval status: status
158 */
USBD_DeInit(USB_OTG_CORE_HANDLE * pdev)159 USBD_Status USBD_DeInit(USB_OTG_CORE_HANDLE *pdev)
160 {
161 /* Software Init */
162
163 return USBD_OK;
164 }
165
166 /**
167 * @brief USBD_SetupStage
168 * Handle the setup stage
169 * @param pdev: device instance
170 * @retval status
171 */
USBD_SetupStage(USB_OTG_CORE_HANDLE * pdev)172 static uint8_t USBD_SetupStage(USB_OTG_CORE_HANDLE *pdev)
173 {
174 USB_SETUP_REQ req;
175
176 USBD_ParseSetupRequest(pdev , &req);
177
178 switch (req.bmRequest & 0x1F)
179 {
180 case USB_REQ_RECIPIENT_DEVICE:
181 USBD_StdDevReq (pdev, &req);
182 break;
183
184 case USB_REQ_RECIPIENT_INTERFACE:
185 USBD_StdItfReq(pdev, &req);
186 break;
187
188 case USB_REQ_RECIPIENT_ENDPOINT:
189 USBD_StdEPReq(pdev, &req);
190 break;
191
192 default:
193 DCD_EP_Stall(pdev , req.bmRequest & 0x80);
194 break;
195 }
196 return USBD_OK;
197 }
198
199 /**
200 * @brief USBD_DataOutStage
201 * Handle data out stage
202 * @param pdev: device instance
203 * @param epnum: endpoint index
204 * @retval status
205 */
USBD_DataOutStage(USB_OTG_CORE_HANDLE * pdev,uint8_t epnum)206 static uint8_t USBD_DataOutStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum)
207 {
208 USB_OTG_EP *ep;
209
210 if(epnum == 0)
211 {
212 ep = &pdev->dev.out_ep[0];
213 if ( pdev->dev.device_state == USB_OTG_EP0_DATA_OUT)
214 {
215 if(ep->rem_data_len > ep->maxpacket)
216 {
217 ep->rem_data_len -= ep->maxpacket;
218
219 if(pdev->cfg.dma_enable == 1)
220 {
221 /* in slave mode this, is handled by the RxSTSQLvl ISR */
222 ep->xfer_buff += ep->maxpacket;
223 }
224 USBD_CtlContinueRx (pdev,
225 ep->xfer_buff,
226 MIN(ep->rem_data_len ,ep->maxpacket));
227 }
228 else
229 {
230 if((pdev->dev.class_cb->EP0_RxReady != NULL)&&
231 (pdev->dev.device_status == USB_OTG_CONFIGURED))
232 {
233 pdev->dev.class_cb->EP0_RxReady(pdev);
234 }
235 USBD_CtlSendStatus(pdev);
236 }
237 }
238 }
239 else if((pdev->dev.class_cb->DataOut != NULL)&&
240 (pdev->dev.device_status == USB_OTG_CONFIGURED))
241 {
242 pdev->dev.class_cb->DataOut(pdev, epnum);
243 }
244 return USBD_OK;
245 }
246
247 /**
248 * @brief USBD_DataInStage
249 * Handle data in stage
250 * @param pdev: device instance
251 * @param epnum: endpoint index
252 * @retval status
253 */
USBD_DataInStage(USB_OTG_CORE_HANDLE * pdev,uint8_t epnum)254 static uint8_t USBD_DataInStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum)
255 {
256 USB_OTG_EP *ep;
257
258 if(epnum == 0)
259 {
260 ep = &pdev->dev.in_ep[0];
261 if ( pdev->dev.device_state == USB_OTG_EP0_DATA_IN)
262 {
263 if(ep->rem_data_len > ep->maxpacket)
264 {
265 ep->rem_data_len -= ep->maxpacket;
266 if(pdev->cfg.dma_enable == 1)
267 {
268 /* in slave mode this, is handled by the TxFifoEmpty ISR */
269 ep->xfer_buff += ep->maxpacket;
270 }
271 USBD_CtlContinueSendData (pdev,
272 ep->xfer_buff,
273 ep->rem_data_len);
274 }
275 else
276 { /* last packet is MPS multiple, so send ZLP packet */
277 if((ep->total_data_len % ep->maxpacket == 0) &&
278 (ep->total_data_len >= ep->maxpacket) &&
279 (ep->total_data_len < ep->ctl_data_len ))
280 {
281
282 USBD_CtlContinueSendData(pdev , NULL, 0);
283 ep->ctl_data_len = 0;
284 }
285 else
286 {
287 if((pdev->dev.class_cb->EP0_TxSent != NULL)&&
288 (pdev->dev.device_status == USB_OTG_CONFIGURED))
289 {
290 pdev->dev.class_cb->EP0_TxSent(pdev);
291 }
292 USBD_CtlReceiveStatus(pdev);
293 }
294 }
295 }
296 }
297 else if((pdev->dev.class_cb->DataIn != NULL)&&
298 (pdev->dev.device_status == USB_OTG_CONFIGURED))
299 {
300 pdev->dev.class_cb->DataIn(pdev, epnum);
301 }
302 return USBD_OK;
303 }
304
305 /**
306 * @brief USBD_Reset
307 * Handle Reset event
308 * @param pdev: device instance
309 * @retval status
310 */
311
USBD_Reset(USB_OTG_CORE_HANDLE * pdev)312 static uint8_t USBD_Reset(USB_OTG_CORE_HANDLE *pdev)
313 {
314 /* Open EP0 OUT */
315 DCD_EP_Open(pdev,
316 0x00,
317 USB_OTG_MAX_EP0_SIZE,
318 EP_TYPE_CTRL);
319
320 /* Open EP0 IN */
321 DCD_EP_Open(pdev,
322 0x80,
323 USB_OTG_MAX_EP0_SIZE,
324 EP_TYPE_CTRL);
325
326 /* Upon Reset call usr call back */
327 pdev->dev.device_status = USB_OTG_DEFAULT;
328 pdev->dev.usr_cb->DeviceReset(pdev->cfg.speed);
329
330 return USBD_OK;
331 }
332
333 /**
334 * @brief USBD_Resume
335 * Handle Resume event
336 * @param pdev: device instance
337 * @retval status
338 */
339
USBD_Resume(USB_OTG_CORE_HANDLE * pdev)340 static uint8_t USBD_Resume(USB_OTG_CORE_HANDLE *pdev)
341 {
342 /* Upon Resume call usr call back */
343 pdev->dev.usr_cb->DeviceResumed();
344 pdev->dev.device_status = USB_OTG_CONFIGURED;
345 return USBD_OK;
346 }
347
348
349 /**
350 * @brief USBD_Suspend
351 * Handle Suspend event
352 * @param pdev: device instance
353 * @retval status
354 */
355
USBD_Suspend(USB_OTG_CORE_HANDLE * pdev)356 static uint8_t USBD_Suspend(USB_OTG_CORE_HANDLE *pdev)
357 {
358
359 pdev->dev.device_status = USB_OTG_SUSPENDED;
360 /* Upon Resume call usr call back */
361 pdev->dev.usr_cb->DeviceSuspended();
362 return USBD_OK;
363 }
364
365
366 /**
367 * @brief USBD_SOF
368 * Handle SOF event
369 * @param pdev: device instance
370 * @retval status
371 */
372
USBD_SOF(USB_OTG_CORE_HANDLE * pdev)373 static uint8_t USBD_SOF(USB_OTG_CORE_HANDLE *pdev)
374 {
375 if(pdev->dev.class_cb->SOF)
376 {
377 pdev->dev.class_cb->SOF(pdev);
378 }
379 return USBD_OK;
380 }
381 /**
382 * @brief USBD_SetCfg
383 * Configure device and start the interface
384 * @param pdev: device instance
385 * @param cfgidx: configuration index
386 * @retval status
387 */
388
USBD_SetCfg(USB_OTG_CORE_HANDLE * pdev,uint8_t cfgidx)389 USBD_Status USBD_SetCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx)
390 {
391 pdev->dev.class_cb->Init(pdev, cfgidx);
392
393 /* Upon set config call usr call back */
394 pdev->dev.usr_cb->DeviceConfigured();
395 return USBD_OK;
396 }
397
398 /**
399 * @brief USBD_ClrCfg
400 * Clear current configuration
401 * @param pdev: device instance
402 * @param cfgidx: configuration index
403 * @retval status: USBD_Status
404 */
USBD_ClrCfg(USB_OTG_CORE_HANDLE * pdev,uint8_t cfgidx)405 USBD_Status USBD_ClrCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx)
406 {
407 pdev->dev.class_cb->DeInit(pdev, cfgidx);
408 return USBD_OK;
409 }
410
411 /**
412 * @brief USBD_IsoINIncomplete
413 * Handle iso in incomplete event
414 * @param pdev: device instance
415 * @retval status
416 */
USBD_IsoINIncomplete(USB_OTG_CORE_HANDLE * pdev)417 static uint8_t USBD_IsoINIncomplete(USB_OTG_CORE_HANDLE *pdev)
418 {
419 pdev->dev.class_cb->IsoINIncomplete(pdev);
420 return USBD_OK;
421 }
422
423 /**
424 * @brief USBD_IsoOUTIncomplete
425 * Handle iso out incomplete event
426 * @param pdev: device instance
427 * @retval status
428 */
USBD_IsoOUTIncomplete(USB_OTG_CORE_HANDLE * pdev)429 static uint8_t USBD_IsoOUTIncomplete(USB_OTG_CORE_HANDLE *pdev)
430 {
431 pdev->dev.class_cb->IsoOUTIncomplete(pdev);
432 return USBD_OK;
433 }
434
435 #ifdef VBUS_SENSING_ENABLED
436 /**
437 * @brief USBD_DevConnected
438 * Handle device connection event
439 * @param pdev: device instance
440 * @retval status
441 */
USBD_DevConnected(USB_OTG_CORE_HANDLE * pdev)442 static uint8_t USBD_DevConnected(USB_OTG_CORE_HANDLE *pdev)
443 {
444 pdev->dev.usr_cb->DeviceConnected();
445 return USBD_OK;
446 }
447
448 /**
449 * @brief USBD_DevDisconnected
450 * Handle device disconnection event
451 * @param pdev: device instance
452 * @retval status
453 */
USBD_DevDisconnected(USB_OTG_CORE_HANDLE * pdev)454 static uint8_t USBD_DevDisconnected(USB_OTG_CORE_HANDLE *pdev)
455 {
456 pdev->dev.usr_cb->DeviceDisconnected();
457 pdev->dev.class_cb->DeInit(pdev, 0);
458 return USBD_OK;
459 }
460 #endif
461 /**
462 * @}
463 */
464
465
466 /**
467 * @}
468 */
469
470
471 /**
472 * @}
473 */
474
475 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
476
477