]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_hcd.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_hcd.c
1 /**
2   ******************************************************************************
3   * @file    stm32f4xx_hal_hcd.c
4   * @author  MCD Application Team
5   * @version V1.1.0
6   * @date    19-June-2014
7   * @brief   HCD 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     (#)Declare a HCD_HandleTypeDef handle structure, for example:
21        HCD_HandleTypeDef  hhcd;
22         
23     (#)Fill parameters of Init structure in HCD handle
24   
25     (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...) 
26
27     (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
28         (##) Enable the HCD/USB Low Level interface clock using the following macros
29              (+++) __OTGFS-OTG_CLK_ENABLE() or __OTGHS-OTG_CLK_ENABLE()
30              (+++) __OTGHSULPI_CLK_ENABLE() For High Speed Mode
31            
32         (##) Initialize the related GPIO clocks
33         (##) Configure HCD pin-out
34         (##) Configure HCD NVIC interrupt
35     
36     (#)Associate the Upper USB Host stack to the HAL HCD Driver:
37         (##) hhcd.pData = phost;
38
39     (#)Enable HCD transmission and reception:
40         (##) HAL_HCD_Start();
41
42   @endverbatim
43   ******************************************************************************
44   * @attention
45   *
46   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
47   *
48   * Redistribution and use in source and binary forms, with or without modification,
49   * are permitted provided that the following conditions are met:
50   *   1. Redistributions of source code must retain the above copyright notice,
51   *      this list of conditions and the following disclaimer.
52   *   2. Redistributions in binary form must reproduce the above copyright notice,
53   *      this list of conditions and the following disclaimer in the documentation
54   *      and/or other materials provided with the distribution.
55   *   3. Neither the name of STMicroelectronics nor the names of its contributors
56   *      may be used to endorse or promote products derived from this software
57   *      without specific prior written permission.
58   *
59   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
60   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
62   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
63   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
65   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
66   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
67   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
68   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69   *
70   ******************************************************************************
71   */ 
72
73 /* Includes ------------------------------------------------------------------*/
74 #include "stm32f4xx_hal.h"
75 /** @addtogroup STM32F4xx_HAL_Driver
76   * @{
77   */
78
79 /** @defgroup HCD 
80   * @brief HCD HAL module driver
81   * @{
82   */
83
84 #ifdef HAL_HCD_MODULE_ENABLED
85
86 /* Private typedef -----------------------------------------------------------*/
87 /* Private define ------------------------------------------------------------*/
88 /* Private macro -------------------------------------------------------------*/
89 /* Private variables ---------------------------------------------------------*/
90 /* Private function prototypes -----------------------------------------------*/
91 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
92 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum); 
93 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
94 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
95 /* Private functions ---------------------------------------------------------*/
96
97 /** @defgroup HCD_Private_Functions
98   * @{
99   */
100
101 /** @defgroup HCD_Group1 Initialization and de-initialization functions 
102  *  @brief    Initialization and Configuration functions 
103  *
104 @verbatim    
105  ===============================================================================
106           ##### Initialization and de-initialization functions #####
107  ===============================================================================
108     [..]  This section provides functions allowing to:
109  
110 @endverbatim
111   * @{
112   */
113
114 /**
115   * @brief  Initialize the host driver
116   * @param  hhcd: HCD handle
117   * @retval HAL status
118   */
119 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
120
121   /* Check the HCD handle allocation */
122   if(hhcd == HAL_NULL)
123   {
124     return HAL_ERROR;
125   }
126   
127   /* Check the parameters */
128   assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
129
130   hhcd->State = HAL_HCD_STATE_BUSY;
131   
132   /* Init the low level hardware : GPIO, CLOCK, NVIC... */
133   HAL_HCD_MspInit(hhcd);
134
135   /* Disable the Interrupts */
136  __HAL_HCD_DISABLE(hhcd);
137  
138  /*Init the Core (common init.) */
139  USB_CoreInit(hhcd->Instance, hhcd->Init);
140  
141  /* Force Host Mode*/
142  USB_SetCurrentMode(hhcd->Instance , USB_OTG_HOST_MODE);
143  
144  /* Init Host */
145  USB_HostInit(hhcd->Instance, hhcd->Init);
146  
147  hhcd->State= HAL_HCD_STATE_READY;
148  
149  return HAL_OK;
150 }
151
152 /**
153   * @brief  Initialize a host channel
154   * @param  hhcd: HCD handle
155   * @param  ch_num: Channel number.
156   *         This parameter can be a value from 1 to 15
157   * @param  epnum: Endpoint number.
158   *          This parameter can be a value from 1 to 15
159   * @param  dev_address : Current device address
160   *          This parameter can be a value from 0 to 255
161   * @param  speed: Current device speed.
162   *          This parameter can be one of these values:
163   *            HCD_SPEED_HIGH: High speed mode,
164   *            HCD_SPEED_FULL: Full speed mode,
165   *            HCD_SPEED_LOW: Low speed mode
166   * @param  ep_type: Endpoint Type.
167   *          This parameter can be one of these values:
168   *            EP_TYPE_CTRL: Control type,
169   *            EP_TYPE_ISOC: Isochrounous type,
170   *            EP_TYPE_BULK: Bulk type,
171   *            EP_TYPE_INTR: Interrupt type
172   * @param  mps: Max Packet Size.
173   *          This parameter can be a value from 0 to32K
174   * @retval HAL status
175   */
176 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd,  
177                                   uint8_t ch_num,
178                                   uint8_t epnum,
179                                   uint8_t dev_address,
180                                   uint8_t speed,
181                                   uint8_t ep_type,
182                                   uint16_t mps)
183 {
184   HAL_StatusTypeDef status = HAL_OK;
185   
186   __HAL_LOCK(hhcd); 
187   
188   hhcd->hc[ch_num].dev_addr = dev_address;
189   hhcd->hc[ch_num].max_packet = mps;
190   hhcd->hc[ch_num].ch_num = ch_num;
191   hhcd->hc[ch_num].ep_type = ep_type;
192   hhcd->hc[ch_num].ep_num = epnum & 0x7F;
193   hhcd->hc[ch_num].ep_is_in = ((epnum & 0x80) == 0x80);
194   hhcd->hc[ch_num].speed = speed;
195
196   status =  USB_HC_Init(hhcd->Instance, 
197                         ch_num,
198                         epnum,
199                         dev_address,
200                         speed,
201                         ep_type,
202                         mps);
203   __HAL_UNLOCK(hhcd); 
204   
205   return status;
206 }
207
208
209
210 /**
211   * @brief  Halt a host channel
212   * @param  hhcd: HCD handle
213   * @param  ch_num: Channel number.
214   *         This parameter can be a value from 1 to 15
215   * @retval HAL status
216   */
217 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd,  
218                                   uint8_t ch_num)
219 {
220   HAL_StatusTypeDef status = HAL_OK;
221   
222   __HAL_LOCK(hhcd);   
223   USB_HC_Halt(hhcd->Instance, ch_num);   
224   __HAL_UNLOCK(hhcd);
225   
226   return status;
227 }
228 /**
229   * @brief  DeInitialize the host driver
230   * @param  hhcd: HCD handle
231   * @retval HAL status
232   */
233 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
234 {
235   /* Check the HCD handle allocation */
236   if(hhcd == HAL_NULL)
237   {
238     return HAL_ERROR;
239   }
240   
241   hhcd->State = HAL_HCD_STATE_BUSY;
242   
243   /* DeInit the low level hardware */
244   HAL_HCD_MspDeInit(hhcd);
245   
246    __HAL_HCD_DISABLE(hhcd);
247   
248   hhcd->State = HAL_HCD_STATE_RESET; 
249   
250   return HAL_OK;
251 }
252
253 /**
254   * @brief  Initializes the HCD MSP.
255   * @param  hhcd: HCD handle
256   * @retval None
257   */
258 __weak void  HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
259 {
260   /* NOTE : This function Should not be modified, when the callback is needed,
261             the HAL_PCD_MspInit could be implenetd in the user file
262    */
263 }
264
265 /**
266   * @brief  DeInitializes HCD MSP.
267   * @param  hhcd: HCD handle
268   * @retval None
269   */
270 __weak void  HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhhcd)
271 {
272   /* NOTE : This function Should not be modified, when the callback is needed,
273             the HAL_PCD_MspDeInit could be implenetd in the user file
274    */
275 }
276
277 /**
278   * @}
279   */
280
281 /** @defgroup HCD_Group2 IO operation functions 
282   *  @brief   HCD IO operation functions
283   *
284 @verbatim
285  ===============================================================================
286                       ##### IO operation functions #####
287  ===============================================================================
288     This subsection provides a set of functions allowing to manage the USB Host Data 
289     Transfer
290        
291 @endverbatim
292   * @{
293   */
294   
295 /**                                
296   * @brief  Submit a new URB for processing 
297   * @param  hhcd: HCD handle
298   * @param  ch_num: Channel number.
299   *         This parameter can be a value from 1 to 15
300   * @param  direction: Channel number.
301   *          This parameter can be one of these values:
302   *           0 : Output / 1 : Input
303   * @param  ep_type: Endpoint Type.
304   *          This parameter can be one of these values:
305   *            EP_TYPE_CTRL: Control type/
306   *            EP_TYPE_ISOC: Isochrounous type/
307   *            EP_TYPE_BULK: Bulk type/
308   *            EP_TYPE_INTR: Interrupt type/
309   * @param  token: Endpoint Type.
310   *          This parameter can be one of these values:
311   *            0: HC_PID_SETUP / 1: HC_PID_DATA1
312   * @param  pbuff: pointer to URB data
313   * @param  length: Length of URB data
314   * @param  do_ping: activate do ping protocol (for high speed only).
315   *          This parameter can be one of these values:
316   *           0 : do ping inactive / 1 : do ping active 
317   * @retval HAL status
318   */
319 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
320                                             uint8_t ch_num, 
321                                             uint8_t direction ,
322                                             uint8_t ep_type,  
323                                             uint8_t token, 
324                                             uint8_t* pbuff, 
325                                             uint16_t length,
326                                             uint8_t do_ping) 
327 {
328   hhcd->hc[ch_num].ep_is_in = direction;
329   hhcd->hc[ch_num].ep_type  = ep_type; 
330   
331   if(token == 0)
332   {
333     hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
334   }
335   else
336   {
337     hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
338   }
339   
340   /* Manage Data Toggle */
341   switch(ep_type)
342   {
343   case EP_TYPE_CTRL:
344     if((token == 1) && (direction == 0)) /*send data */
345     {
346       if ( length == 0 )
347       { /* For Status OUT stage, Length==0, Status Out PID = 1 */
348         hhcd->hc[ch_num].toggle_out = 1;
349       }
350       
351       /* Set the Data Toggle bit as per the Flag */
352       if ( hhcd->hc[ch_num].toggle_out == 0)
353       { /* Put the PID 0 */
354         hhcd->hc[ch_num].data_pid = HC_PID_DATA0;    
355       }
356       else
357       { /* Put the PID 1 */
358         hhcd->hc[ch_num].data_pid = HC_PID_DATA1 ;
359       }
360       if(hhcd->hc[ch_num].urb_state  != URB_NOTREADY)
361       {
362         hhcd->hc[ch_num].do_ping = do_ping;
363       }
364     }
365     break;
366   
367   case EP_TYPE_BULK:
368     if(direction == 0)
369     {
370       /* Set the Data Toggle bit as per the Flag */
371       if ( hhcd->hc[ch_num].toggle_out == 0)
372       { /* Put the PID 0 */
373         hhcd->hc[ch_num].data_pid = HC_PID_DATA0;    
374       }
375       else
376       { /* Put the PID 1 */
377         hhcd->hc[ch_num].data_pid = HC_PID_DATA1 ;
378       }
379       if(hhcd->hc[ch_num].urb_state  != URB_NOTREADY)
380       {
381         hhcd->hc[ch_num].do_ping = do_ping;
382       }
383     }
384     else
385     {
386       if( hhcd->hc[ch_num].toggle_in == 0)
387       {
388         hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
389       }
390       else
391       {
392         hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
393       }
394     }
395     
396     break;
397   case EP_TYPE_INTR:
398     if(direction == 0)
399     {
400       /* Set the Data Toggle bit as per the Flag */
401       if ( hhcd->hc[ch_num].toggle_out == 0)
402       { /* Put the PID 0 */
403         hhcd->hc[ch_num].data_pid = HC_PID_DATA0;    
404       }
405       else
406       { /* Put the PID 1 */
407         hhcd->hc[ch_num].data_pid = HC_PID_DATA1 ;
408       }
409     }
410     else
411     {
412       if( hhcd->hc[ch_num].toggle_in == 0)
413       {
414         hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
415       }
416       else
417       {
418         hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
419       }
420     }
421     break;
422     
423   case EP_TYPE_ISOC: 
424     hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
425     break;
426       
427   }
428   
429   hhcd->hc[ch_num].xfer_buff = pbuff;
430   hhcd->hc[ch_num].xfer_len  = length;
431   hhcd->hc[ch_num].urb_state =   URB_IDLE;  
432   hhcd->hc[ch_num].xfer_count = 0 ;
433   hhcd->hc[ch_num].ch_num = ch_num;
434   hhcd->hc[ch_num].state = HC_IDLE;
435   
436   return USB_HC_StartXfer(hhcd->Instance, &(hhcd->hc[ch_num]), hhcd->Init.dma_enable);
437 }
438
439 /**
440   * @brief  This function handles HCD interrupt request.
441   * @param  hhcd: HCD handle
442   * @retval None
443   */
444 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
445 {
446   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
447   uint32_t i = 0 , interrupt = 0;
448   
449   /* ensure that we are in device mode */
450   if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
451   {
452     /* avoid spurious interrupt */
453     if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd)) 
454     {
455       return;
456     }
457     
458     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
459     {
460      /* incorrect mode, acknowledge the interrupt */
461       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
462     }
463     
464     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
465     {
466      /* incorrect mode, acknowledge the interrupt */
467       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
468     }
469
470     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
471     {
472      /* incorrect mode, acknowledge the interrupt */
473       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
474     }   
475     
476     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
477     {
478      /* incorrect mode, acknowledge the interrupt */
479       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
480     }     
481     
482     /* Handle Host Disconnect Interrupts */
483     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
484     {
485       
486       /* Cleanup HPRT */
487       USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
488         USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
489        
490       /* Handle Host Port Interrupts */
491       HAL_HCD_Disconnect_Callback(hhcd);
492        USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
493       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
494     }
495     
496     /* Handle Host Port Interrupts */
497     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
498     {
499       HCD_Port_IRQHandler (hhcd);
500     }
501     
502     /* Handle Host SOF Interrupts */
503     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
504     {
505       HAL_HCD_SOF_Callback(hhcd);
506       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
507     }
508           
509     /* Handle Host channel Interrupts */
510     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
511     {
512       
513       interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
514       for (i = 0; i < hhcd->Init.Host_channels ; i++)
515       {
516         if (interrupt & (1 << i))
517         {
518           if ((USBx_HC(i)->HCCHAR) &  USB_OTG_HCCHAR_EPDIR)
519           {
520             HCD_HC_IN_IRQHandler (hhcd, i);
521           }
522           else
523           {
524             HCD_HC_OUT_IRQHandler (hhcd, i);
525           }
526         }
527       }
528       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
529     } 
530     
531         /* Handle Rx Queue Level Interrupts */
532     if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL))
533     {
534       USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
535       
536       HCD_RXQLVL_IRQHandler (hhcd);
537       
538       USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
539     }
540     
541   }
542 }
543
544 /**
545   * @brief  SOF callback.
546   * @param  hhcd: HCD handle
547   * @retval None
548   */
549 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
550 {
551   /* NOTE : This function Should not be modified, when the callback is needed,
552             the HAL_HCD_SOF_Callback could be implenetd in the user file
553    */
554 }
555
556 /**
557   * @brief Connexion Event callback.
558   * @param  hhcd: HCD handle
559   * @retval None
560   */
561 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
562 {
563   /* NOTE : This function Should not be modified, when the callback is needed,
564             the HAL_HCD_Connect_Callback could be implenetd in the user file
565    */
566 }
567
568 /**
569   * @brief  Disonnexion Event callback.
570   * @param  hhcd: HCD handle
571   * @retval None
572   */
573 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
574 {
575   /* NOTE : This function Should not be modified, when the callback is needed,
576             the HAL_HCD_Disconnect_Callback could be implenetd in the user file
577    */
578
579
580 /**
581   * @brief  Notify URB state change callback.
582   * @param  hhcd: HCD handle
583   * @param  chnum: Channel number.
584   *         This parameter can be a value from 1 to 15
585   * @param  urb_state:
586   *          This parameter can be one of these values:
587   *            URB_IDLE/
588   *            URB_DONE/
589   *            URB_NOTREADY/
590   *            URB_NYET/ 
591   *            URB_ERROR/  
592   *            URB_STALL/    
593   * @retval None
594   */
595 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
596 {
597   /* NOTE : This function Should not be modified, when the callback is needed,
598             the HAL_HCD_HC_NotifyURBChange_Callback could be implenetd in the user file
599    */
600 }
601
602 /**
603   * @}
604   */
605
606 /** @defgroup HCD_Group3 Peripheral Control functions 
607  *  @brief   management functions 
608  *
609 @verbatim   
610  ===============================================================================
611                       ##### Peripheral Control functions #####
612  ===============================================================================  
613     [..]
614     This subsection provides a set of functions allowing to control the HCD data 
615     transfers.
616
617 @endverbatim
618   * @{
619   */
620
621 /**
622   * @brief  Start the host driver
623   * @param  hhcd: HCD handle
624   * @retval HAL status
625   */
626 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
627
628   __HAL_LOCK(hhcd); 
629   __HAL_HCD_ENABLE(hhcd);
630   USB_DriveVbus(hhcd->Instance, 1);  
631   __HAL_UNLOCK(hhcd); 
632   return HAL_OK;
633 }
634
635 /**
636   * @brief  Stop the host driver
637   * @param  hhcd: HCD handle
638   * @retval HAL status
639   */
640
641 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
642
643   __HAL_LOCK(hhcd); 
644   USB_StopHost(hhcd->Instance);
645   __HAL_UNLOCK(hhcd); 
646   return HAL_OK;
647 }
648
649 /**
650   * @brief  Reset the host port
651   * @param  hhcd: HCD handle
652   * @retval HAL status
653   */
654 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
655 {
656   return (USB_ResetPort(hhcd->Instance));
657 }
658
659 /**
660   * @}
661   */
662
663 /** @defgroup HCD_Group4 Peripheral State functions 
664  *  @brief   Peripheral State functions 
665  *
666 @verbatim   
667  ===============================================================================
668                       ##### Peripheral State functions #####
669  ===============================================================================  
670     [..]
671     This subsection permits to get in run-time the status of the peripheral 
672     and the data flow.
673
674 @endverbatim
675   * @{
676   */
677
678 /**
679   * @brief  Return the HCD state
680   * @param  hhcd: HCD handle
681   * @retval HAL state
682   */
683 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
684 {
685   return hhcd->State;
686 }
687
688 /**
689   * @brief  Return  URB state for a channel
690   * @param  hhcd: HCD handle
691   * @param  chnum: Channel number.
692   *         This parameter can be a value from 1 to 15
693   * @retval URB state.
694   *          This parameter can be one of these values:
695   *            URB_IDLE/
696   *            URB_DONE/
697   *            URB_NOTREADY/
698   *            URB_NYET/ 
699   *            URB_ERROR/  
700   *            URB_STALL      
701   */
702 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
703 {
704   return hhcd->hc[chnum].urb_state;
705 }
706
707
708 /**
709   * @brief  Return the last host transfer size
710   * @param  hhcd: HCD handle
711   * @param  chnum: Channel number.
712   *         This parameter can be a value from 1 to 15
713   * @retval last transfer size in byte
714   */
715 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
716 {
717   return hhcd->hc[chnum].xfer_count; 
718 }
719   
720 /**
721   * @brief  Return the Host Channel state
722   * @param  hhcd: HCD handle
723   * @param  chnum: Channel number.
724   *         This parameter can be a value from 1 to 15
725   * @retval Host channel state
726   *          This parameter can be one of the these values:
727   *            HC_IDLE/
728   *            HC_XFRC/
729   *            HC_HALTED/
730   *            HC_NYET/ 
731   *            HC_NAK/  
732   *            HC_STALL/ 
733   *            HC_XACTERR/  
734   *            HC_BBLERR/  
735   *            HC_DATATGLERR/    
736   */
737 HCD_HCStateTypeDef  HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
738 {
739   return hhcd->hc[chnum].state;
740 }
741
742 /**
743   * @brief  Return the current Host frame number
744   * @param  hhcd: HCD handle
745   * @retval Current Host frame number
746   */
747 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
748 {
749   return (USB_GetCurrentFrame(hhcd->Instance));
750 }
751
752 /**
753   * @brief  Return the Host enumeration speed
754   * @param  hhcd: HCD handle
755   * @retval Enumeration speed
756   */
757 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
758 {
759   return (USB_GetHostSpeed(hhcd->Instance));
760 }
761
762 /**
763   * @}
764   */
765
766 /**
767   * @brief  This function handles Host Channel IN interrupt requests.
768   * @param  hhcd: HCD handle
769   * @param  chnum: Channel number.
770   *         This parameter can be a value from 1 to 15
771   * @retval none
772   */
773 static void HCD_HC_IN_IRQHandler   (HCD_HandleTypeDef *hhcd, uint8_t chnum)
774 {
775   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
776     
777   if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_AHBERR)
778   {
779     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
780     __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
781   }  
782   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_ACK)
783   {
784     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
785   }
786   
787   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_STALL)  
788   {
789     __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
790     hhcd->hc[chnum].state = HC_STALL;
791     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
792     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);    
793     USB_HC_Halt(hhcd->Instance, chnum);    
794   }
795   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_DTERR)
796   {
797     __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
798     USB_HC_Halt(hhcd->Instance, chnum);  
799     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);    
800     hhcd->hc[chnum].state = HC_DATATGLERR;
801     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
802   }    
803   
804   if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_FRMOR)
805   {
806     __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
807     USB_HC_Halt(hhcd->Instance, chnum);  
808     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
809   }
810   
811   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_XFRC)
812   {
813     
814     if (hhcd->Init.dma_enable)
815     {
816       hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].xfer_len - \
817                                (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
818     }
819     
820     hhcd->hc[chnum].state = HC_XFRC;
821     hhcd->hc[chnum].ErrCnt = 0;
822     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
823     
824     
825     if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||
826         (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
827     {
828       __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
829       USB_HC_Halt(hhcd->Instance, chnum); 
830       __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
831       
832     }
833     else if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
834     {
835       USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
836       hhcd->hc[chnum].urb_state = URB_DONE; 
837       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
838     }
839     hhcd->hc[chnum].toggle_in ^= 1;
840     
841   }
842   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_CHH)
843   {
844     __HAL_HCD_MASK_HALT_HC_INT(chnum); 
845     
846     if(hhcd->hc[chnum].state == HC_XFRC)
847     {
848       hhcd->hc[chnum].urb_state  = URB_DONE;      
849     }
850     
851     else if (hhcd->hc[chnum].state == HC_STALL) 
852     {
853       hhcd->hc[chnum].urb_state  = URB_STALL;
854     }   
855     
856     else if((hhcd->hc[chnum].state == HC_XACTERR) ||
857             (hhcd->hc[chnum].state == HC_DATATGLERR))
858     {
859       if(hhcd->hc[chnum].ErrCnt++ > 3)
860       {      
861         hhcd->hc[chnum].ErrCnt = 0;
862         hhcd->hc[chnum].urb_state = URB_ERROR;
863       }
864       else
865       {
866         hhcd->hc[chnum].urb_state = URB_NOTREADY;
867       }
868       
869       /* re-activate the channel  */
870       USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;         
871       USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;      
872     }
873     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
874     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
875   }  
876   
877   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_TXERR)
878   {
879     __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
880      hhcd->hc[chnum].ErrCnt++;
881      hhcd->hc[chnum].state = HC_XACTERR;
882      USB_HC_Halt(hhcd->Instance, chnum);     
883      __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
884   }
885   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)
886   {  
887     if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
888     {
889       __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
890       USB_HC_Halt(hhcd->Instance, chnum);  
891     }
892     else if  ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||
893               (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
894     {
895       /* re-activate the channel  */
896       USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;         
897       USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
898    
899     }
900     hhcd->hc[chnum].state = HC_NAK;
901      __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
902   }
903 }
904
905 /**
906   * @brief  This function handles Host Channel OUT interrupt requests.
907   * @param  hhcd: HCD handle
908   * @param  chnum: Channel number.
909   *         This parameter can be a value from 1 to 15
910   * @retval none
911   */
912 static void HCD_HC_OUT_IRQHandler  (HCD_HandleTypeDef *hhcd, uint8_t chnum)
913 {
914   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
915   
916   if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_AHBERR)
917   {
918     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
919     __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
920   }  
921   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_ACK)
922   {
923     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
924     
925     if( hhcd->hc[chnum].do_ping == 1)
926     {
927       hhcd->hc[chnum].state = HC_NYET;     
928       __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
929       USB_HC_Halt(hhcd->Instance, chnum); 
930       hhcd->hc[chnum].urb_state  = URB_NOTREADY;
931     }
932   }
933   
934   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NYET)
935   {
936     hhcd->hc[chnum].state = HC_NYET;
937     hhcd->hc[chnum].ErrCnt= 0;    
938     __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
939     USB_HC_Halt(hhcd->Instance, chnum);      
940     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
941     
942   }  
943   
944   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_FRMOR)
945   {
946     __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
947     USB_HC_Halt(hhcd->Instance, chnum);  
948     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
949   }
950   
951   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_XFRC)
952   {
953       hhcd->hc[chnum].ErrCnt = 0;  
954     __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
955     USB_HC_Halt(hhcd->Instance, chnum);   
956     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
957     hhcd->hc[chnum].state = HC_XFRC;
958
959   }  
960
961   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_STALL)  
962   {
963     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);  
964     __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
965     USB_HC_Halt(hhcd->Instance, chnum);   
966     hhcd->hc[chnum].state = HC_STALL;    
967   }
968
969   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)
970   {  
971     hhcd->hc[chnum].ErrCnt = 0;  
972     __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
973     USB_HC_Halt(hhcd->Instance, chnum);   
974     hhcd->hc[chnum].state = HC_NAK;
975     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
976   }
977
978   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_TXERR)
979   {
980     __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
981     USB_HC_Halt(hhcd->Instance, chnum);      
982     hhcd->hc[chnum].state = HC_XACTERR;  
983      __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
984   }
985   
986   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_DTERR)
987   {
988     __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
989     USB_HC_Halt(hhcd->Instance, chnum);      
990     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
991     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);    
992     hhcd->hc[chnum].state = HC_DATATGLERR;
993   }
994   
995   
996   else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_CHH)
997   {
998     __HAL_HCD_MASK_HALT_HC_INT(chnum); 
999     
1000     if(hhcd->hc[chnum].state == HC_XFRC)
1001     {
1002       hhcd->hc[chnum].urb_state  = URB_DONE;
1003       if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK)
1004       {
1005         hhcd->hc[chnum].toggle_out ^= 1; 
1006       }      
1007     }
1008     else if (hhcd->hc[chnum].state == HC_NAK) 
1009     {
1010       hhcd->hc[chnum].urb_state  = URB_NOTREADY;
1011     }  
1012     
1013     else if (hhcd->hc[chnum].state == HC_NYET) 
1014     {
1015       hhcd->hc[chnum].urb_state  = URB_NOTREADY;
1016       hhcd->hc[chnum].do_ping = 0;
1017     }   
1018     
1019     else if (hhcd->hc[chnum].state == HC_STALL) 
1020     {
1021       hhcd->hc[chnum].urb_state  = URB_STALL;
1022     } 
1023     
1024     else if((hhcd->hc[chnum].state == HC_XACTERR) ||
1025             (hhcd->hc[chnum].state == HC_DATATGLERR))
1026     {
1027       if(hhcd->hc[chnum].ErrCnt++ > 3)
1028       {      
1029         hhcd->hc[chnum].ErrCnt = 0;
1030         hhcd->hc[chnum].urb_state = URB_ERROR;
1031       }
1032       else
1033       {
1034         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1035       }
1036       
1037       /* re-activate the channel  */
1038       USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;         
1039       USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;      
1040     }
1041     
1042     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1043     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);  
1044   }
1045
1046
1047 /**
1048   * @brief  This function handles Rx Queue Level interrupt requests.
1049   * @param  hhcd: HCD handle
1050   * @retval none
1051   */
1052 static void HCD_RXQLVL_IRQHandler  (HCD_HandleTypeDef *hhcd)
1053 {
1054   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;  
1055   uint8_t                       channelnum =0;  
1056   uint32_t                      pktsts;
1057   uint32_t                      pktcnt; 
1058   uint32_t                      temp = 0;
1059   
1060   temp = hhcd->Instance->GRXSTSP ;
1061   channelnum = temp &  USB_OTG_GRXSTSP_EPNUM;  
1062   pktsts = (temp &  USB_OTG_GRXSTSP_PKTSTS) >> 17;
1063   pktcnt = (temp &  USB_OTG_GRXSTSP_BCNT) >> 4;
1064     
1065   switch (pktsts)
1066   {
1067   case GRXSTS_PKTSTS_IN:
1068     /* Read the data into the host buffer. */
1069     if ((pktcnt > 0) && (hhcd->hc[channelnum].xfer_buff != (void  *)0))
1070     {  
1071       
1072       USB_ReadPacket(hhcd->Instance, hhcd->hc[channelnum].xfer_buff, pktcnt);
1073      
1074       /*manage multiple Xfer */
1075       hhcd->hc[channelnum].xfer_buff += pktcnt;           
1076       hhcd->hc[channelnum].xfer_count  += pktcnt;
1077         
1078       if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0)
1079       {
1080         /* re-activate the channel when more packets are expected */
1081         USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS; 
1082         USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
1083         hhcd->hc[channelnum].toggle_in ^= 1;
1084       }
1085     }
1086     break;
1087
1088   case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1089     break;
1090   case GRXSTS_PKTSTS_IN_XFER_COMP:
1091   case GRXSTS_PKTSTS_CH_HALTED:
1092   default:
1093     break;
1094   }
1095 }
1096
1097 /**
1098   * @brief  This function handles Host Port interrupt requests.
1099   * @param  hhcd: HCD handle
1100   * @retval None
1101   */
1102 static void HCD_Port_IRQHandler  (HCD_HandleTypeDef *hhcd)
1103 {
1104   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;  
1105   __IO uint32_t hprt0, hprt0_dup;
1106   
1107   /* Handle Host Port Interrupts */
1108   hprt0 = USBx_HPRT0;
1109   hprt0_dup = USBx_HPRT0;
1110   
1111   hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
1112                  USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
1113   
1114   /* Check wether Port Connect Detected */
1115   if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1116   {  
1117     if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1118     {
1119       USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
1120       HAL_HCD_Connect_Callback(hhcd);
1121     }
1122     hprt0_dup  |= USB_OTG_HPRT_PCDET;
1123     
1124   }
1125   
1126   /* Check whether Port Enable Changed */
1127   if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1128   {
1129     hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1130     
1131     if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1132     {    
1133       if(hhcd->Init.phy_itface  == USB_OTG_EMBEDDED_PHY)
1134       {
1135         if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1136         {
1137           USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_6_MHZ );
1138         }
1139         else
1140         {
1141           USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
1142         }
1143       }
1144       else
1145       {
1146         if(hhcd->Init.speed == HCD_SPEED_FULL)
1147         {
1148           USBx_HOST->HFIR = (uint32_t)60000;
1149         }
1150       }
1151       HAL_HCD_Connect_Callback(hhcd);
1152       
1153       if(hhcd->Init.speed == HCD_SPEED_HIGH)
1154       {
1155         USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); 
1156       }
1157     }
1158     else
1159     {
1160       /* Cleanup HPRT */
1161       USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
1162         USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
1163       
1164       USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); 
1165     }    
1166   }
1167   
1168   /* Check For an overcurrent */
1169   if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1170   {
1171     hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1172   }
1173
1174   /* Clear Port Interrupts */
1175   USBx_HPRT0 = hprt0_dup;
1176 }
1177
1178 /**
1179   * @}
1180   */
1181
1182 #endif /* HAL_HCD_MODULE_ENABLED */
1183 /**
1184   * @}
1185   */
1186
1187 /**
1188   * @}
1189   */
1190
1191 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/