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>&copy; 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