1 /**
2   ******************************************************************************
3   * @file    usbd_core.c
4   * @author  MCD Application Team
5   * @version V2.4.2
6   * @date    11-December-2015
7   * @brief   This file provides all the USBD core functions.
8   ******************************************************************************
9   * @attention
10   *
11   * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
12   *
13   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
14   * You may not use this file except in compliance with the License.
15   * You may obtain a copy of the License at:
16   *
17   *        http://www.st.com/software_license_agreement_liberty_v2
18   *
19   * Unless required by applicable law or agreed to in writing, software
20   * distributed under the License is distributed on an "AS IS" BASIS,
21   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22   * See the License for the specific language governing permissions and
23   * limitations under the License.
24   *
25   ******************************************************************************
26   */
27 
28 /* Includes ------------------------------------------------------------------*/
29 #include "usbd_core.h"
30 
31 /** @addtogroup STM32_USBD_DEVICE_LIBRARY
32 * @{
33 */
34 
35 
36 /** @defgroup USBD_CORE
37 * @brief usbd core module
38 * @{
39 */
40 
41 /** @defgroup USBD_CORE_Private_TypesDefinitions
42 * @{
43 */
44 /**
45 * @}
46 */
47 
48 
49 /** @defgroup USBD_CORE_Private_Defines
50 * @{
51 */
52 
53 /**
54 * @}
55 */
56 
57 
58 /** @defgroup USBD_CORE_Private_Macros
59 * @{
60 */
61 /**
62 * @}
63 */
64 
65 
66 
67 
68 /** @defgroup USBD_CORE_Private_FunctionPrototypes
69 * @{
70 */
71 
72 /**
73 * @}
74 */
75 
76 /** @defgroup USBD_CORE_Private_Variables
77 * @{
78 */
79 
80 /**
81 * @}
82 */
83 
84 /** @defgroup USBD_CORE_Private_Functions
85 * @{
86 */
87 
88 /**
89 * @brief  USBD_Init
90 *         Initializes the device stack and load the class driver
91 * @param  pdev: device instance
92 * @param  pdesc: Descriptor structure address
93 * @param  id: Low level core index
94 * @retval None
95 */
USBD_Init(USBD_HandleTypeDef * pdev,USBD_DescriptorsTypeDef * pdesc,uint8_t id)96 USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id)
97 {
98   /* Check whether the USB Host handle is valid */
99   if(pdev == NULL)
100   {
101     USBD_ErrLog("Invalid Device handle");
102     return USBD_FAIL;
103   }
104 
105   /* Unlink previous class*/
106   if(pdev->pClass != NULL)
107   {
108     pdev->pClass = NULL;
109   }
110 
111   /* Assign USBD Descriptors */
112   if(pdesc != NULL)
113   {
114     pdev->pDesc = pdesc;
115   }
116 
117   /* Set Device initial State */
118   pdev->dev_state  = USBD_STATE_DEFAULT;
119   pdev->id = id;
120   /* Initialize low level driver */
121   USBD_LL_Init(pdev);
122 
123   return USBD_OK;
124 }
125 
126 /**
127 * @brief  USBD_DeInit
128 *         Re-Initialize th device library
129 * @param  pdev: device instance
130 * @retval status: status
131 */
USBD_DeInit(USBD_HandleTypeDef * pdev)132 USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
133 {
134   /* Set Default State */
135   pdev->dev_state  = USBD_STATE_DEFAULT;
136 
137   /* Free Class Resources */
138   pdev->pClass->DeInit(pdev, pdev->dev_config);
139 
140     /* Stop the low level driver  */
141   USBD_LL_Stop(pdev);
142 
143   /* Initialize low level driver */
144   USBD_LL_DeInit(pdev);
145 
146   return USBD_OK;
147 }
148 
149 
150 /**
151   * @brief  USBD_RegisterClass
152   *         Link class driver to Device Core.
153   * @param  pDevice : Device Handle
154   * @param  pclass: Class handle
155   * @retval USBD Status
156   */
USBD_RegisterClass(USBD_HandleTypeDef * pdev,USBD_ClassTypeDef * pclass)157 USBD_StatusTypeDef  USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
158 {
159   USBD_StatusTypeDef   status = USBD_OK;
160   if(pclass != 0)
161   {
162     /* link the class to the USB Device handle */
163     pdev->pClass = pclass;
164     status = USBD_OK;
165   }
166   else
167   {
168     USBD_ErrLog("Invalid Class handle");
169     status = USBD_FAIL;
170   }
171 
172   return status;
173 }
174 
175 /**
176   * @brief  USBD_Start
177   *         Start the USB Device Core.
178   * @param  pdev: Device Handle
179   * @retval USBD Status
180   */
USBD_Start(USBD_HandleTypeDef * pdev)181 USBD_StatusTypeDef  USBD_Start  (USBD_HandleTypeDef *pdev)
182 {
183 
184   /* Start the low level driver  */
185   USBD_LL_Start(pdev);
186 
187   return USBD_OK;
188 }
189 
190 /**
191   * @brief  USBD_Stop
192   *         Stop the USB Device Core.
193   * @param  pdev: Device Handle
194   * @retval USBD Status
195   */
USBD_Stop(USBD_HandleTypeDef * pdev)196 USBD_StatusTypeDef  USBD_Stop   (USBD_HandleTypeDef *pdev)
197 {
198   /* Free Class Resources */
199   pdev->pClass->DeInit(pdev, pdev->dev_config);
200 
201   /* Stop the low level driver  */
202   USBD_LL_Stop(pdev);
203 
204   return USBD_OK;
205 }
206 
207 /**
208 * @brief  USBD_RunTestMode
209 *         Launch test mode process
210 * @param  pdev: device instance
211 * @retval status
212 */
USBD_RunTestMode(USBD_HandleTypeDef * pdev)213 USBD_StatusTypeDef  USBD_RunTestMode (USBD_HandleTypeDef  *pdev)
214 {
215   return USBD_OK;
216 }
217 
218 
219 /**
220 * @brief  USBD_SetClassConfig
221 *        Configure device and start the interface
222 * @param  pdev: device instance
223 * @param  cfgidx: configuration index
224 * @retval status
225 */
226 
USBD_SetClassConfig(USBD_HandleTypeDef * pdev,uint8_t cfgidx)227 USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef  *pdev, uint8_t cfgidx)
228 {
229   USBD_StatusTypeDef   ret = USBD_FAIL;
230 
231   if(pdev->pClass != NULL)
232   {
233     /* Set configuration  and Start the Class*/
234     if(pdev->pClass->Init(pdev, cfgidx) == 0)
235     {
236       ret = USBD_OK;
237     }
238   }
239   return ret;
240 }
241 
242 /**
243 * @brief  USBD_ClrClassConfig
244 *         Clear current configuration
245 * @param  pdev: device instance
246 * @param  cfgidx: configuration index
247 * @retval status: USBD_StatusTypeDef
248 */
USBD_ClrClassConfig(USBD_HandleTypeDef * pdev,uint8_t cfgidx)249 USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef  *pdev, uint8_t cfgidx)
250 {
251   /* Clear configuration  and De-initialize the Class process*/
252   pdev->pClass->DeInit(pdev, cfgidx);
253   return USBD_OK;
254 }
255 
256 
257 /**
258 * @brief  USBD_SetupStage
259 *         Handle the setup stage
260 * @param  pdev: device instance
261 * @retval status
262 */
USBD_LL_SetupStage(USBD_HandleTypeDef * pdev,uint8_t * psetup)263 USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
264 {
265 
266   USBD_ParseSetupRequest(&pdev->request, psetup);
267 
268   pdev->ep0_state = USBD_EP0_SETUP;
269   pdev->ep0_data_len = pdev->request.wLength;
270 
271   switch (pdev->request.bmRequest & 0x1F)
272   {
273   case USB_REQ_RECIPIENT_DEVICE:
274     USBD_StdDevReq (pdev, &pdev->request);
275     break;
276 
277   case USB_REQ_RECIPIENT_INTERFACE:
278     USBD_StdItfReq(pdev, &pdev->request);
279     break;
280 
281   case USB_REQ_RECIPIENT_ENDPOINT:
282     USBD_StdEPReq(pdev, &pdev->request);
283     break;
284 
285   default:
286     USBD_LL_StallEP(pdev , pdev->request.bmRequest & 0x80);
287     break;
288   }
289   return USBD_OK;
290 }
291 
292 /**
293 * @brief  USBD_DataOutStage
294 *         Handle data OUT stage
295 * @param  pdev: device instance
296 * @param  epnum: endpoint index
297 * @retval status
298 */
USBD_LL_DataOutStage(USBD_HandleTypeDef * pdev,uint8_t epnum,uint8_t * pdata)299 USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata)
300 {
301   USBD_EndpointTypeDef    *pep;
302 
303   if(epnum == 0)
304   {
305     pep = &pdev->ep_out[0];
306 
307     if ( pdev->ep0_state == USBD_EP0_DATA_OUT)
308     {
309       if(pep->rem_length > pep->maxpacket)
310       {
311         pep->rem_length -=  pep->maxpacket;
312 
313         USBD_CtlContinueRx (pdev,
314                             pdata,
315                             MIN(pep->rem_length ,pep->maxpacket));
316       }
317       else
318       {
319         if((pdev->pClass->EP0_RxReady != NULL)&&
320            (pdev->dev_state == USBD_STATE_CONFIGURED))
321         {
322           pdev->pClass->EP0_RxReady(pdev);
323         }
324         USBD_CtlSendStatus(pdev);
325       }
326     }
327   }
328   else if((pdev->pClass->DataOut != NULL)&&
329           (pdev->dev_state == USBD_STATE_CONFIGURED))
330   {
331     pdev->pClass->DataOut(pdev, epnum);
332   }
333   return USBD_OK;
334 }
335 
336 /**
337 * @brief  USBD_DataInStage
338 *         Handle data in stage
339 * @param  pdev: device instance
340 * @param  epnum: endpoint index
341 * @retval status
342 */
USBD_LL_DataInStage(USBD_HandleTypeDef * pdev,uint8_t epnum,uint8_t * pdata)343 USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uint8_t *pdata)
344 {
345   USBD_EndpointTypeDef    *pep;
346 
347   if(epnum == 0)
348   {
349     pep = &pdev->ep_in[0];
350 
351     if ( pdev->ep0_state == USBD_EP0_DATA_IN)
352     {
353       if(pep->rem_length > pep->maxpacket)
354       {
355         pep->rem_length -=  pep->maxpacket;
356 
357         USBD_CtlContinueSendData (pdev,
358                                   pdata,
359                                   pep->rem_length);
360 
361         /* Prepare endpoint for premature end of transfer */
362         USBD_LL_PrepareReceive (pdev,
363                                 0,
364                                 NULL,
365                                 0);
366       }
367       else
368       { /* last packet is MPS multiple, so send ZLP packet */
369         if((pep->total_length % pep->maxpacket == 0) &&
370            (pep->total_length >= pep->maxpacket) &&
371              (pep->total_length < pdev->ep0_data_len ))
372         {
373 
374           USBD_CtlContinueSendData(pdev , NULL, 0);
375           pdev->ep0_data_len = 0;
376 
377         /* Prepare endpoint for premature end of transfer */
378         USBD_LL_PrepareReceive (pdev,
379                                 0,
380                                 NULL,
381                                 0);
382         }
383         else
384         {
385           if((pdev->pClass->EP0_TxSent != NULL)&&
386              (pdev->dev_state == USBD_STATE_CONFIGURED))
387           {
388             pdev->pClass->EP0_TxSent(pdev);
389           }
390           USBD_CtlReceiveStatus(pdev);
391         }
392       }
393     }
394     if (pdev->dev_test_mode == 1)
395     {
396       USBD_RunTestMode(pdev);
397       pdev->dev_test_mode = 0;
398     }
399   }
400   else if((pdev->pClass->DataIn != NULL)&&
401           (pdev->dev_state == USBD_STATE_CONFIGURED))
402   {
403     pdev->pClass->DataIn(pdev, epnum);
404   }
405   return USBD_OK;
406 }
407 
408 /**
409 * @brief  USBD_LL_Reset
410 *         Handle Reset event
411 * @param  pdev: device instance
412 * @retval status
413 */
414 
USBD_LL_Reset(USBD_HandleTypeDef * pdev)415 USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef  *pdev)
416 {
417   /* Open EP0 OUT */
418   USBD_LL_OpenEP(pdev,
419               0x00,
420               USBD_EP_TYPE_CTRL,
421               USB_MAX_EP0_SIZE);
422 
423   pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
424 
425   /* Open EP0 IN */
426   USBD_LL_OpenEP(pdev,
427               0x80,
428               USBD_EP_TYPE_CTRL,
429               USB_MAX_EP0_SIZE);
430 
431   pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
432   /* Upon Reset call user call back */
433   pdev->dev_state = USBD_STATE_DEFAULT;
434 
435   if (pdev->pClassData)
436     pdev->pClass->DeInit(pdev, pdev->dev_config);
437 
438 
439   return USBD_OK;
440 }
441 
442 
443 
444 
445 /**
446 * @brief  USBD_LL_Reset
447 *         Handle Reset event
448 * @param  pdev: device instance
449 * @retval status
450 */
USBD_LL_SetSpeed(USBD_HandleTypeDef * pdev,USBD_SpeedTypeDef speed)451 USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef  *pdev, USBD_SpeedTypeDef speed)
452 {
453   pdev->dev_speed = speed;
454   return USBD_OK;
455 }
456 
457 /**
458 * @brief  USBD_Suspend
459 *         Handle Suspend event
460 * @param  pdev: device instance
461 * @retval status
462 */
463 
USBD_LL_Suspend(USBD_HandleTypeDef * pdev)464 USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef  *pdev)
465 {
466   pdev->dev_old_state =  pdev->dev_state;
467   pdev->dev_state  = USBD_STATE_SUSPENDED;
468   return USBD_OK;
469 }
470 
471 /**
472 * @brief  USBD_Resume
473 *         Handle Resume event
474 * @param  pdev: device instance
475 * @retval status
476 */
477 
USBD_LL_Resume(USBD_HandleTypeDef * pdev)478 USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef  *pdev)
479 {
480   pdev->dev_state = pdev->dev_old_state;
481   return USBD_OK;
482 }
483 
484 /**
485 * @brief  USBD_SOF
486 *         Handle SOF event
487 * @param  pdev: device instance
488 * @retval status
489 */
490 
USBD_LL_SOF(USBD_HandleTypeDef * pdev)491 USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef  *pdev)
492 {
493   if(pdev->dev_state == USBD_STATE_CONFIGURED)
494   {
495     if(pdev->pClass->SOF != NULL)
496     {
497       pdev->pClass->SOF(pdev);
498     }
499   }
500   return USBD_OK;
501 }
502 
503 /**
504 * @brief  USBD_IsoINIncomplete
505 *         Handle iso in incomplete event
506 * @param  pdev: device instance
507 * @retval status
508 */
USBD_LL_IsoINIncomplete(USBD_HandleTypeDef * pdev,uint8_t epnum)509 USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef  *pdev, uint8_t epnum)
510 {
511   return USBD_OK;
512 }
513 
514 /**
515 * @brief  USBD_IsoOUTIncomplete
516 *         Handle iso out incomplete event
517 * @param  pdev: device instance
518 * @retval status
519 */
USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef * pdev,uint8_t epnum)520 USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef  *pdev, uint8_t epnum)
521 {
522   return USBD_OK;
523 }
524 
525 /**
526 * @brief  USBD_DevConnected
527 *         Handle device connection event
528 * @param  pdev: device instance
529 * @retval status
530 */
USBD_LL_DevConnected(USBD_HandleTypeDef * pdev)531 USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef  *pdev)
532 {
533   return USBD_OK;
534 }
535 
536 /**
537 * @brief  USBD_DevDisconnected
538 *         Handle device disconnection event
539 * @param  pdev: device instance
540 * @retval status
541 */
USBD_LL_DevDisconnected(USBD_HandleTypeDef * pdev)542 USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef  *pdev)
543 {
544   /* Free Class Resources */
545   pdev->dev_state = USBD_STATE_DEFAULT;
546   pdev->pClass->DeInit(pdev, pdev->dev_config);
547 
548   return USBD_OK;
549 }
550 /**
551 * @}
552 */
553 
554 
555 /**
556 * @}
557 */
558 
559 
560 /**
561 * @}
562 */
563 
564 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
565 
566