]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_pcd.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_STM / TARGET_STM32F4 / stm32f4xx_hal_pcd.c
1 /**
2   ******************************************************************************
3   * @file    stm32f4xx_hal_pcd.c
4   * @author  MCD Application Team
5   * @version V1.1.0
6   * @date    19-June-2014
7   * @brief   PCD HAL module driver.
8   *          This file provides firmware functions to manage the following 
9   *          functionalities of the USB Peripheral Controller:
10   *           + Initialization and de-initialization functions
11   *           + IO operation functions
12   *           + Peripheral Control functions 
13   *           + Peripheral State functions
14   *         
15   @verbatim
16   ==============================================================================
17                     ##### How to use this driver #####
18   ==============================================================================
19     [..]
20       The PCD HAL driver can be used as follows:
21
22      (#) Declare a PCD_HandleTypeDef handle structure, for example:
23          PCD_HandleTypeDef  hpcd;
24         
25      (#) Fill parameters of Init structure in HCD handle
26   
27      (#) Call HAL_PCD_Init() API to initialize the HCD peripheral (Core, Device core, ...) 
28
29      (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
30          (##) Enable the PCD/USB Low Level interface clock using 
31               (+++) __OTGFS-OTG_CLK_ENABLE()/__OTGHS-OTG_CLK_ENABLE();
32               (+++) __OTGHSULPI_CLK_ENABLE(); (For High Speed Mode)
33            
34          (##) Initialize the related GPIO clocks
35          (##) Configure PCD pin-out
36          (##) Configure PCD NVIC interrupt
37     
38      (#)Associate the Upper USB device stack to the HAL PCD Driver:
39          (##) hpcd.pData = pdev;
40
41      (#)Enable HCD transmission and reception:
42          (##) HAL_PCD_Start();
43
44   @endverbatim
45   ******************************************************************************
46   * @attention
47   *
48   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
49   *
50   * Redistribution and use in source and binary forms, with or without modification,
51   * are permitted provided that the following conditions are met:
52   *   1. Redistributions of source code must retain the above copyright notice,
53   *      this list of conditions and the following disclaimer.
54   *   2. Redistributions in binary form must reproduce the above copyright notice,
55   *      this list of conditions and the following disclaimer in the documentation
56   *      and/or other materials provided with the distribution.
57   *   3. Neither the name of STMicroelectronics nor the names of its contributors
58   *      may be used to endorse or promote products derived from this software
59   *      without specific prior written permission.
60   *
61   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
62   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
65   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
67   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
68   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
69   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
70   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
71   *
72   ******************************************************************************
73   */ 
74
75 /* Includes ------------------------------------------------------------------*/
76 #include "stm32f4xx_hal.h"
77
78 /** @addtogroup STM32F4xx_HAL_Driver
79   * @{
80   */
81
82 /** @defgroup PCD 
83   * @brief PCD HAL module driver
84   * @{
85   */
86
87 #ifdef HAL_PCD_MODULE_ENABLED
88
89 /* Private typedef -----------------------------------------------------------*/
90 /* Private define ------------------------------------------------------------*/
91 /* Private macro -------------------------------------------------------------*/
92 #define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
93 #define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
94 /* Private variables ---------------------------------------------------------*/
95 /* Private function prototypes -----------------------------------------------*/
96 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
97 /* Private functions ---------------------------------------------------------*/
98
99 /** @defgroup PCD_Private_Functions
100   * @{
101   */
102
103 /** @defgroup PCD_Group1 Initialization and de-initialization functions 
104  *  @brief    Initialization and Configuration functions 
105  *
106 @verbatim    
107  ===============================================================================
108             ##### Initialization and de-initialization functions #####
109  ===============================================================================
110     [..]  This section provides functions allowing to:
111  
112 @endverbatim
113   * @{
114   */
115
116 /**
117   * @brief  Initializes the PCD according to the specified
118   *         parameters in the PCD_InitTypeDef and create the associated handle.
119   * @param  hpcd: PCD handle
120   * @retval HAL status
121   */
122 HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
123
124   uint32_t i = 0;
125   
126   /* Check the PCD handle allocation */
127   if(hpcd == HAL_NULL)
128   {
129     return HAL_ERROR;
130   }
131   
132   /* Check the parameters */
133   assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
134
135   hpcd->State = HAL_PCD_STATE_BUSY;
136   
137   /* Init the low level hardware : GPIO, CLOCK, NVIC... */
138   HAL_PCD_MspInit(hpcd);
139
140   /* Disable the Interrupts */
141  __HAL_PCD_DISABLE(hpcd);
142  
143  /*Init the Core (common init.) */
144  USB_CoreInit(hpcd->Instance, hpcd->Init);
145  
146  /* Force Device Mode*/
147  USB_SetCurrentMode(hpcd->Instance , USB_OTG_DEVICE_MODE);
148  
149  /* Init endpoints structures */
150  for (i = 0; i < 15 ; i++)
151  {
152    /* Init ep structure */
153    hpcd->IN_ep[i].is_in = 1;
154    hpcd->IN_ep[i].num = i;
155    hpcd->IN_ep[i].tx_fifo_num = i;
156    /* Control until ep is actvated */
157    hpcd->IN_ep[i].type = EP_TYPE_CTRL;
158    hpcd->IN_ep[i].maxpacket =  0;
159    hpcd->IN_ep[i].xfer_buff = 0;
160    hpcd->IN_ep[i].xfer_len = 0;
161  }
162  
163  for (i = 0; i < 15 ; i++)
164  {
165    hpcd->OUT_ep[i].is_in = 0;
166    hpcd->OUT_ep[i].num = i;
167    hpcd->IN_ep[i].tx_fifo_num = i;
168    /* Control until ep is activated */
169    hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
170    hpcd->OUT_ep[i].maxpacket = 0;
171    hpcd->OUT_ep[i].xfer_buff = 0;
172    hpcd->OUT_ep[i].xfer_len = 0;
173    
174    hpcd->Instance->DIEPTXF[i] = 0;
175  }
176  
177  /* Init Device */
178  USB_DevInit(hpcd->Instance, hpcd->Init);
179  
180  hpcd->State= HAL_PCD_STATE_READY;
181  
182  USB_DevDisconnect (hpcd->Instance);  
183  return HAL_OK;
184 }
185
186 /**
187   * @brief  DeInitializes the PCD peripheral 
188   * @param  hpcd: PCD handle
189   * @retval HAL status
190   */
191 HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
192 {
193   /* Check the PCD handle allocation */
194   if(hpcd == HAL_NULL)
195   {
196     return HAL_ERROR;
197   }
198
199   hpcd->State = HAL_PCD_STATE_BUSY;
200   
201   /* Stop Device */
202   HAL_PCD_Stop(hpcd);
203     
204   /* DeInit the low level hardware */
205   HAL_PCD_MspDeInit(hpcd);
206   
207   hpcd->State = HAL_PCD_STATE_RESET; 
208   
209   return HAL_OK;
210 }
211
212 /**
213   * @brief  Initializes the PCD MSP.
214   * @param  hpcd: PCD handle
215   * @retval None
216   */
217 __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
218 {
219   /* NOTE : This function Should not be modified, when the callback is needed,
220             the HAL_PCD_MspInit could be implenetd in the user file
221    */
222 }
223
224 /**
225   * @brief  DeInitializes PCD MSP.
226   * @param  hpcd: PCD handle
227   * @retval None
228   */
229 __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
230 {
231   /* NOTE : This function Should not be modified, when the callback is needed,
232             the HAL_PCD_MspDeInit could be implenetd in the user file
233    */
234 }
235
236 /**
237   * @}
238   */
239
240 /** @defgroup PCD_Group2 IO operation functions 
241  *  @brief   Data transfers functions 
242  *
243 @verbatim   
244  ===============================================================================
245                       ##### IO operation functions #####
246  ===============================================================================  
247     [..]
248     This subsection provides a set of functions allowing to manage the PCD data 
249     transfers.
250
251 @endverbatim
252   * @{
253   */
254   
255 /**
256   * @brief  Start The USB OTG Device.
257   * @param  hpcd: PCD handle
258   * @retval HAL status
259   */
260 HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
261
262   __HAL_LOCK(hpcd); 
263   USB_DevConnect (hpcd->Instance);  
264   __HAL_PCD_ENABLE(hpcd);
265   __HAL_UNLOCK(hpcd); 
266   return HAL_OK;
267 }
268
269 /**
270   * @brief  Stop The USB OTG Device.
271   * @param  hpcd: PCD handle
272   * @retval HAL status
273   */
274 HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
275
276   __HAL_LOCK(hpcd); 
277   __HAL_PCD_DISABLE(hpcd);
278   USB_StopDevice(hpcd->Instance);
279   USB_DevDisconnect (hpcd->Instance);
280   __HAL_UNLOCK(hpcd); 
281   return HAL_OK;
282 }
283
284 /**
285   * @brief  This function handles PCD interrupt request.
286   * @param  hpcd: PCD handle
287   * @retval HAL status
288   */
289 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
290 {
291   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
292   uint32_t i = 0, ep_intr = 0, epint = 0, epnum = 0;
293   uint32_t fifoemptymsk = 0, temp = 0;
294   USB_OTG_EPTypeDef *ep;
295     
296   /* ensure that we are in device mode */
297   if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
298   {
299     /* avoid spurious interrupt */
300     if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd)) 
301     {
302       return;
303     }
304     
305     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
306     {
307      /* incorrect mode, acknowledge the interrupt */
308       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
309     }
310     
311     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
312     {
313       epnum = 0;
314       
315       /* Read in the device interrupt bits */
316       ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
317       
318       while ( ep_intr )
319       {
320         if (ep_intr & 0x1)
321         {
322           epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum);
323           
324           if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
325           {
326             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
327             
328             if(hpcd->Init.dma_enable == 1)
329             {
330               hpcd->OUT_ep[epnum].xfer_count = hpcd->OUT_ep[epnum].maxpacket- (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); 
331               hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket;            
332             }
333             
334             HAL_PCD_DataOutStageCallback(hpcd, epnum);
335             if(hpcd->Init.dma_enable == 1)
336             {
337               if((epnum == 0) && (hpcd->OUT_ep[epnum].xfer_len == 0))
338               {
339                  /* this is ZLP, so prepare EP0 for next setup */
340                 USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup);
341               }              
342             }
343           }
344           
345           if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
346           {
347             /* Inform the upper layer that a setup packet is available */
348             HAL_PCD_SetupStageCallback(hpcd);
349             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
350           }
351           
352           if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
353           {
354             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
355           }
356         }
357         epnum++;
358         ep_intr >>= 1;
359       }
360     }
361     
362     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
363     {
364       /* Read in the device interrupt bits */
365       ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
366       
367       epnum = 0;
368       
369       while ( ep_intr )
370       {
371         if (ep_intr & 0x1) /* In ITR */
372         {
373           epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum);
374
375            if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
376           {
377             fifoemptymsk = 0x1 << epnum;
378             USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
379             
380             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
381             
382             if (hpcd->Init.dma_enable == 1)
383             {
384               hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket; 
385             }
386                                       
387             HAL_PCD_DataInStageCallback(hpcd, epnum);
388
389             if (hpcd->Init.dma_enable == 1)
390             {
391               /* this is ZLP, so prepare EP0 for next setup */
392               if((epnum == 0) && (hpcd->IN_ep[epnum].xfer_len == 0))
393               {
394                 /* prepare to rx more setup packets */
395                 USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup);
396               }
397             }           
398           }
399            if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
400           {
401             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
402           }
403           if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
404           {
405             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
406           }
407           if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
408           {
409             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
410           }
411           if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
412           {
413             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
414           }       
415           if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
416           {
417             PCD_WriteEmptyTxFifo(hpcd , epnum);
418           }
419         }
420         epnum++;
421         ep_intr >>= 1;
422       }
423     }
424     
425     /* Handle Resume Interrupt */
426     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
427     {    
428      /* Clear the Remote Wake-up Signaling */
429       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
430      
431      HAL_PCD_ResumeCallback(hpcd);
432
433      __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
434     }
435     
436     /* Handle Suspend Interrupt */
437     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
438     {
439
440       if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
441       {
442         
443         HAL_PCD_SuspendCallback(hpcd);
444       }
445       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
446     }
447     
448
449
450     /* Handle Reset Interrupt */
451     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
452     {
453       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; 
454       USB_FlushTxFifo(hpcd->Instance ,  0 );
455       
456       for (i = 0; i < hpcd->Init.dev_endpoints ; i++)
457       {
458         USBx_INEP(i)->DIEPINT = 0xFF;
459         USBx_OUTEP(i)->DOEPINT = 0xFF;
460       }
461       USBx_DEVICE->DAINT = 0xFFFFFFFF;
462       USBx_DEVICE->DAINTMSK |= 0x10001;
463       
464       if(hpcd->Init.use_dedicated_ep1)
465       {
466         USBx_DEVICE->DOUTEP1MSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM); 
467         USBx_DEVICE->DINEP1MSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);  
468       }
469       else
470       {
471         USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
472         USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
473       }
474       
475       /* Set Default Address to 0 */
476       USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
477       
478       /* setup EP0 to receive SETUP packets */
479       USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
480         
481       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
482     }
483     
484     /* Handle Enumeration done Interrupt */
485     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
486     {
487       USB_ActivateSetup(hpcd->Instance);
488       hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
489       
490       if ( USB_GetDevSpeed(hpcd->Instance) == USB_OTG_SPEED_HIGH)
491       {
492         hpcd->Init.speed            = USB_OTG_SPEED_HIGH;
493         hpcd->Init.ep0_mps          = USB_OTG_HS_MAX_PACKET_SIZE ;    
494         hpcd->Instance->GUSBCFG |= (USB_OTG_GUSBCFG_TRDT_0 | USB_OTG_GUSBCFG_TRDT_3);
495       }
496       else
497       {
498         hpcd->Init.speed            = USB_OTG_SPEED_FULL;
499         hpcd->Init.ep0_mps          = USB_OTG_FS_MAX_PACKET_SIZE ;  
500         hpcd->Instance->GUSBCFG |= (USB_OTG_GUSBCFG_TRDT_0 | USB_OTG_GUSBCFG_TRDT_2);
501       }
502       
503       HAL_PCD_ResetCallback(hpcd);
504       
505       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
506     }
507     
508      
509     /* Handle RxQLevel Interrupt */
510     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
511     {
512       USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
513       temp = USBx->GRXSTSP;
514       ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
515       
516       if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
517       {
518         if((temp & USB_OTG_GRXSTSP_BCNT) != 0)
519         {
520           USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4);
521           ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
522           ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
523         }
524       }
525       else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_SETUP_UPDT)
526       {
527         USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8);
528         ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
529       }
530       USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
531     }
532     
533     /* Handle SOF Interrupt */
534     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
535     {
536       HAL_PCD_SOFCallback(hpcd);
537       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
538     }
539     
540     /* Handle Incomplete ISO IN Interrupt */
541     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
542     {
543       HAL_PCD_ISOINIncompleteCallback(hpcd, epnum);
544       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
545     } 
546     
547     /* Handle Incomplete ISO OUT Interrupt */
548     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
549     {
550       HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum);
551       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
552     } 
553     
554     /* Handle Connection event Interrupt */
555     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
556     {
557       HAL_PCD_ConnectCallback(hpcd);
558       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
559     } 
560     
561     /* Handle Disconnection event Interrupt */
562     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
563     {
564       temp = hpcd->Instance->GOTGINT;
565       
566       if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
567       {
568         HAL_PCD_DisconnectCallback(hpcd);
569       }
570       hpcd->Instance->GOTGINT |= temp;
571     }
572   }
573 }
574
575 /**
576   * @brief  Data out stage callbacks
577   * @param  hpcd: PCD handle
578   * @retval None
579   */
580  __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
581 {
582   /* NOTE : This function Should not be modified, when the callback is needed,
583             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
584    */ 
585 }
586
587 /**
588   * @brief  Data IN stage callbacks
589   * @param  hpcd: PCD handle
590   * @retval None
591   */
592  __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
593 {
594   /* NOTE : This function Should not be modified, when the callback is needed,
595             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
596    */ 
597 }
598 /**
599   * @brief  Setup stage callback
600   * @param  hpcd: PCD handle
601   * @retval None
602   */
603  __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
604 {
605   /* NOTE : This function Should not be modified, when the callback is needed,
606             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
607    */ 
608 }
609
610 /**
611   * @brief  USB Start Of Frame callbacks
612   * @param  hpcd: PCD handle
613   * @retval None
614   */
615  __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
616 {
617   /* NOTE : This function Should not be modified, when the callback is needed,
618             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
619    */ 
620 }
621
622 /**
623   * @brief  USB Reset callbacks
624   * @param  hpcd: PCD handle
625   * @retval None
626   */
627  __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
628 {
629   /* NOTE : This function Should not be modified, when the callback is needed,
630             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
631    */ 
632 }
633
634
635 /**
636   * @brief  Suspend event callbacks
637   * @param  hpcd: PCD handle
638   * @retval None
639   */
640  __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
641 {
642   /* NOTE : This function Should not be modified, when the callback is needed,
643             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
644    */ 
645 }
646
647 /**
648   * @brief  Resume event callbacks
649   * @param  hpcd: PCD handle
650   * @retval None
651   */
652  __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
653 {
654   /* NOTE : This function Should not be modified, when the callback is needed,
655             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
656    */ 
657 }
658
659 /**
660   * @brief  Incomplete ISO OUT callbacks
661   * @param  hpcd: PCD handle
662   * @retval None
663   */
664  __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
665 {
666   /* NOTE : This function Should not be modified, when the callback is needed,
667             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
668    */ 
669 }
670
671 /**
672   * @brief  Incomplete ISO IN  callbacks
673   * @param  hpcd: PCD handle
674   * @retval None
675   */
676  __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
677 {
678   /* NOTE : This function Should not be modified, when the callback is needed,
679             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
680    */ 
681 }
682
683 /**
684   * @brief  Connection event callbacks
685   * @param  hpcd: PCD handle
686   * @retval None
687   */
688  __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
689 {
690   /* NOTE : This function Should not be modified, when the callback is needed,
691             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
692    */ 
693 }
694
695 /**
696   * @brief  Disconnection event callbacks
697   * @param  hpcd: PCD handle
698   * @retval None
699   */
700  __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
701 {
702   /* NOTE : This function Should not be modified, when the callback is needed,
703             the HAL_PCD_DataOutStageCallback could be implenetd in the user file
704    */ 
705 }
706
707 /**
708   * @}
709   */
710   
711 /** @defgroup PCD_Group3 Peripheral Control functions 
712  *  @brief   management functions 
713  *
714 @verbatim   
715  ===============================================================================
716                       ##### Peripheral Control functions #####
717  ===============================================================================  
718     [..]
719     This subsection provides a set of functions allowing to control the PCD data 
720     transfers.
721
722 @endverbatim
723   * @{
724   */
725
726 /**
727   * @brief  Send an amount of data in blocking mode 
728   * @param  hpcd: PCD handle
729   * @retval HAL status
730   */
731 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
732 {
733   __HAL_LOCK(hpcd); 
734   USB_DevConnect(hpcd->Instance);
735   __HAL_UNLOCK(hpcd); 
736   return HAL_OK;
737 }
738
739 /**
740   * @brief  Send an amount of data in blocking mode 
741   * @param  hpcd: PCD handle
742   * @retval HAL status
743   */
744 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
745 {
746   __HAL_LOCK(hpcd); 
747   USB_DevDisconnect(hpcd->Instance);
748   __HAL_UNLOCK(hpcd); 
749   return HAL_OK;
750 }
751
752 /**
753   * @brief  Set the USB Device address 
754   * @param  hpcd: PCD handle
755   * @param  address: new device address
756   * @retval HAL status
757   */
758 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
759 {
760   __HAL_LOCK(hpcd); 
761   USB_SetDevAddress(hpcd->Instance, address);
762   __HAL_UNLOCK(hpcd);   
763   return HAL_OK;
764 }
765 /**
766   * @brief  Open and configure an endpoint
767   * @param  hpcd: PCD handle
768   * @param  ep_addr: endpoint address
769   * @param  ep_mps: endpoint max packert size
770   * @param  ep_type: endpoint type   
771   * @retval HAL status
772   */
773 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
774 {
775   HAL_StatusTypeDef  ret = HAL_OK;
776   USB_OTG_EPTypeDef *ep;
777   
778   if ((ep_addr & 0x80) == 0x80)
779   {
780     ep = &hpcd->IN_ep[ep_addr & 0x7F];
781   }
782   else
783   {
784     ep = &hpcd->OUT_ep[ep_addr & 0x7F];
785   }
786   ep->num   = ep_addr & 0x7F;
787   
788   ep->is_in = (0x80 & ep_addr) != 0;
789   ep->maxpacket = ep_mps;
790   ep->type = ep_type;
791   if (ep->is_in)
792   {
793     /* Assign a Tx FIFO */
794     ep->tx_fifo_num = ep->num;
795   }
796   /* Set initial data PID. */
797   if (ep_type == EP_TYPE_BULK )
798   {
799     ep->data_pid_start = 0;
800   }
801   
802   __HAL_LOCK(hpcd); 
803   USB_ActivateEndpoint(hpcd->Instance , ep);
804   __HAL_UNLOCK(hpcd);   
805   return ret;
806 }
807
808
809 /**
810   * @brief  Deactivate an endpoint
811   * @param  hpcd: PCD handle
812   * @param  ep_addr: endpoint address
813   * @retval HAL status
814   */
815 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
816 {  
817   USB_OTG_EPTypeDef *ep;
818   
819   if ((ep_addr & 0x80) == 0x80)
820   {
821     ep = &hpcd->IN_ep[ep_addr & 0x7F];
822   }
823   else
824   {
825     ep = &hpcd->OUT_ep[ep_addr & 0x7F];
826   }
827   ep->num   = ep_addr & 0x7F;
828   
829   ep->is_in = (0x80 & ep_addr) != 0;
830   
831   __HAL_LOCK(hpcd); 
832   USB_DeactivateEndpoint(hpcd->Instance , ep);
833   __HAL_UNLOCK(hpcd);   
834   return HAL_OK;
835 }
836
837
838 /**
839   * @brief  Receive an amount of data  
840   * @param  hpcd: PCD handle
841   * @param  ep_addr: endpoint address
842   * @param  pBuf: pointer to the reception buffer   
843   * @param  len: amount of data to be received
844   * @retval HAL status
845   */
846 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
847 {
848   
849   USB_OTG_EPTypeDef *ep;
850   
851   ep = &hpcd->OUT_ep[ep_addr & 0x7F];
852   
853   /*setup and start the Xfer */
854   ep->xfer_buff = pBuf;  
855   ep->xfer_len = len;
856   ep->xfer_count = 0;
857   ep->is_in = 0;
858   ep->num = ep_addr & 0x7F;
859   
860   if (hpcd->Init.dma_enable == 1)
861   {
862     ep->dma_addr = (uint32_t)pBuf;  
863   }
864   
865   __HAL_LOCK(hpcd); 
866   
867   if ((ep_addr & 0x7F) == 0 )
868   {
869     USB_EP0StartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
870   }
871   else
872   {
873     USB_EPStartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
874   }
875   __HAL_UNLOCK(hpcd); 
876   
877   return HAL_OK;
878 }
879
880 /**
881   * @brief  Get Received Data Size
882   * @param  hpcd: PCD handle
883   * @param  ep_addr: endpoint address
884   * @retval Data Size
885   */
886 uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
887 {
888   return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count;
889 }
890 /**
891   * @brief  Send an amount of data  
892   * @param  hpcd: PCD handle
893   * @param  ep_addr: endpoint address
894   * @param  pBuf: pointer to the transmission buffer   
895   * @param  len: amount of data to be sent
896   * @retval HAL status
897   */
898 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
899 {
900   USB_OTG_EPTypeDef *ep;
901   
902   ep = &hpcd->IN_ep[ep_addr & 0x7F];
903   
904   /*setup and start the Xfer */
905   ep->xfer_buff = pBuf;  
906   ep->xfer_len = len;
907   ep->xfer_count = 0;
908   ep->is_in = 1;
909   ep->num = ep_addr & 0x7F;
910   
911   if (hpcd->Init.dma_enable == 1)
912   {
913     ep->dma_addr = (uint32_t)pBuf;  
914   }
915   
916   __HAL_LOCK(hpcd); 
917   
918   if ((ep_addr & 0x7F) == 0 )
919   {
920     USB_EP0StartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
921   }
922   else
923   {
924     USB_EPStartXfer(hpcd->Instance , ep, hpcd->Init.dma_enable);
925   }
926   
927   __HAL_UNLOCK(hpcd);
928      
929   return HAL_OK;
930 }
931
932 /**
933   * @brief  Set a STALL condition over an endpoint
934   * @param  hpcd: PCD handle
935   * @param  ep_addr: endpoint address
936   * @retval HAL status
937   */
938 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
939 {
940   USB_OTG_EPTypeDef *ep;
941   
942   if ((0x80 & ep_addr) == 0x80)
943   {
944     ep = &hpcd->IN_ep[ep_addr & 0x7F];
945   }
946   else
947   {
948     ep = &hpcd->OUT_ep[ep_addr];
949   }
950   
951   ep->is_stall = 1;
952   ep->num   = ep_addr & 0x7F;
953   ep->is_in = ((ep_addr & 0x80) == 0x80);
954   
955   
956   __HAL_LOCK(hpcd); 
957   USB_EPSetStall(hpcd->Instance , ep);
958   if((ep_addr & 0x7F) == 0)
959   {
960     USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
961   }
962   __HAL_UNLOCK(hpcd); 
963   
964   return HAL_OK;
965 }
966
967 /**
968   * @brief  Clear a STALL condition over in an endpoint
969   * @param  hpcd: PCD handle
970   * @param  ep_addr: endpoint address
971   * @retval HAL status
972   */
973 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
974 {
975   USB_OTG_EPTypeDef *ep;
976   
977   if ((0x80 & ep_addr) == 0x80)
978   {
979     ep = &hpcd->IN_ep[ep_addr & 0x7F];
980   }
981   else
982   {
983     ep = &hpcd->OUT_ep[ep_addr];
984   }
985   
986   ep->is_stall = 0;
987   ep->num   = ep_addr & 0x7F;
988   ep->is_in = ((ep_addr & 0x80) == 0x80);
989   
990   __HAL_LOCK(hpcd); 
991   USB_EPClearStall(hpcd->Instance , ep);
992   __HAL_UNLOCK(hpcd); 
993     
994   return HAL_OK;
995 }
996
997 /**
998   * @brief  Flush an endpoint
999   * @param  hpcd: PCD handle
1000   * @param  ep_addr: endpoint address
1001   * @retval HAL status
1002   */
1003 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1004 {
1005   __HAL_LOCK(hpcd); 
1006   
1007   if ((ep_addr & 0x80) == 0x80)
1008   {
1009     USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F);
1010   }
1011   else
1012   {
1013     USB_FlushRxFifo(hpcd->Instance);
1014   }
1015   
1016   __HAL_UNLOCK(hpcd); 
1017     
1018   return HAL_OK;
1019 }
1020
1021 /**
1022   * @brief  HAL_PCD_ActiveRemoteWakeup : active remote wakeup signalling
1023   * @param  hpcd: PCD handle
1024   * @retval HAL status
1025   */
1026 HAL_StatusTypeDef HAL_PCD_ActiveRemoteWakeup(PCD_HandleTypeDef *hpcd)
1027 {
1028   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;  
1029     
1030   if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
1031   {
1032     /* active Remote wakeup signaling */
1033     USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG;
1034   }
1035   return HAL_OK;  
1036 }
1037
1038 /**
1039   * @brief  HAL_PCD_DeActiveRemoteWakeup : de-active remote wakeup signalling
1040   * @param  hpcd: PCD handle
1041   * @retval HAL status
1042   */
1043 HAL_StatusTypeDef HAL_PCD_DeActiveRemoteWakeup(PCD_HandleTypeDef *hpcd)
1044 {
1045   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;  
1046   
1047   /* active Remote wakeup signaling */
1048    USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG);
1049   return HAL_OK;  
1050 }
1051 /**
1052   * @}
1053   */
1054   
1055 /** @defgroup PCD_Group4 Peripheral State functions 
1056  *  @brief   Peripheral State functions 
1057  *
1058 @verbatim   
1059  ===============================================================================
1060                       ##### Peripheral State functions #####
1061  ===============================================================================  
1062     [..]
1063     This subsection permits to get in run-time the status of the peripheral 
1064     and the data flow.
1065
1066 @endverbatim
1067   * @{
1068   */
1069
1070 /**
1071   * @brief  Return the PCD state
1072   * @param  hpcd: PCD handle
1073   * @retval HAL state
1074   */
1075 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1076 {
1077   return hpcd->State;
1078 }
1079 /**
1080   * @}
1081   */
1082
1083 /**
1084   * @brief  DCD_WriteEmptyTxFifo
1085   *         check FIFO for the next packet to be loaded
1086   * @param  hpcd: PCD handle
1087   * @retval HAL status
1088   */
1089 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
1090 {
1091   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;  
1092   USB_OTG_EPTypeDef *ep;
1093   int32_t len = 0;
1094   uint32_t len32b;
1095   uint32_t fifoemptymsk = 0;
1096
1097   ep = &hpcd->IN_ep[epnum];
1098   len = ep->xfer_len - ep->xfer_count;
1099   
1100   if (len > ep->maxpacket)
1101   {
1102     len = ep->maxpacket;
1103   }
1104   
1105   
1106   len32b = (len + 3) / 4;
1107  
1108   while  ( (USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b &&
1109           ep->xfer_count < ep->xfer_len &&
1110             ep->xfer_len != 0)
1111   {
1112     /* Write the FIFO */
1113     len = ep->xfer_len - ep->xfer_count;
1114     
1115     if (len > ep->maxpacket)
1116     {
1117       len = ep->maxpacket;
1118     }
1119     len32b = (len + 3) / 4;
1120     
1121     USB_WritePacket(USBx, ep->xfer_buff, epnum, len, hpcd->Init.dma_enable); 
1122     
1123     ep->xfer_buff  += len;
1124     ep->xfer_count += len;
1125   }
1126   
1127   if(len <= 0)
1128   {
1129     fifoemptymsk = 0x1 << epnum;
1130     USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1131     
1132   }
1133   
1134   return HAL_OK;  
1135 }
1136
1137 /**
1138   * @}
1139   */
1140
1141 #endif /* HAL_PCD_MODULE_ENABLED */
1142 /**
1143   * @}
1144   */
1145
1146 /**
1147   * @}
1148   */
1149
1150 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/