Merge pull request #93 from zyp/master
[fw/stlink] / example / stm32f4 / STM32_USB_Device_Library / Core / src / usbd_core.c
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 */
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 */
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 */
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 */
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 */
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
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
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
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
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
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 */
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 */
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 */
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 */
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 */
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