Merge pull request #93 from zyp/master
[fw/stlink] / example / stm32f4 / STM32_USB_OTG_Driver / src / usb_dcd.c
1 /**
2   ******************************************************************************
3   * @file    usb_dcd.c
4   * @author  MCD Application Team
5   * @version V2.0.0
6   * @date    22-July-2011
7   * @brief   Peripheral Device Interface Layer
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 "usb_dcd.h"
24 #include "usb_bsp.h"
25
26
27 /** @addtogroup USB_OTG_DRIVER
28 * @{
29 */
30
31 /** @defgroup USB_DCD 
32 * @brief This file is the interface between EFSL ans Host mass-storage class
33 * @{
34 */
35
36
37 /** @defgroup USB_DCD_Private_Defines
38 * @{
39 */ 
40 /**
41 * @}
42 */ 
43
44
45 /** @defgroup USB_DCD_Private_TypesDefinitions
46 * @{
47 */ 
48 /**
49 * @}
50 */ 
51
52
53
54 /** @defgroup USB_DCD_Private_Macros
55 * @{
56 */ 
57 /**
58 * @}
59 */ 
60
61
62 /** @defgroup USB_DCD_Private_Variables
63 * @{
64 */ 
65 /**
66 * @}
67 */ 
68
69
70 /** @defgroup USB_DCD_Private_FunctionPrototypes
71 * @{
72 */ 
73
74 /**
75 * @}
76 */ 
77
78
79 /** @defgroup USB_DCD_Private_Functions
80 * @{
81 */ 
82
83
84
85 void DCD_Init(USB_OTG_CORE_HANDLE *pdev , 
86               USB_OTG_CORE_ID_TypeDef coreID)
87 {
88   uint32_t i;
89   USB_OTG_EP *ep;
90   
91   USB_OTG_SelectCore (pdev , coreID);
92   
93   pdev->dev.device_status = USB_OTG_DEFAULT;
94   pdev->dev.device_address = 0;
95   
96   /* Init ep structure */
97   for (i = 0; i < pdev->cfg.dev_endpoints ; i++)
98   {
99     ep = &pdev->dev.in_ep[i];
100     /* Init ep structure */
101     ep->is_in = 1;
102     ep->num = i;
103     ep->tx_fifo_num = i;
104     /* Control until ep is actvated */
105     ep->type = EP_TYPE_CTRL;
106     ep->maxpacket =  USB_OTG_MAX_EP0_SIZE;
107     ep->xfer_buff = 0;
108     ep->xfer_len = 0;
109   }
110   
111   for (i = 0; i < pdev->cfg.dev_endpoints; i++)
112   {
113     ep = &pdev->dev.out_ep[i];
114     /* Init ep structure */
115     ep->is_in = 0;
116     ep->num = i;
117     ep->tx_fifo_num = i;
118     /* Control until ep is activated */
119     ep->type = EP_TYPE_CTRL;
120     ep->maxpacket = USB_OTG_MAX_EP0_SIZE;
121     ep->xfer_buff = 0;
122     ep->xfer_len = 0;
123   }
124   
125   USB_OTG_DisableGlobalInt(pdev);
126   
127   /*Init the Core (common init.) */
128   USB_OTG_CoreInit(pdev);
129
130
131   /* Force Device Mode*/
132   USB_OTG_SetCurrentMode(pdev, DEVICE_MODE);
133   
134   /* Init Device */
135   USB_OTG_CoreInitDev(pdev);
136   
137   
138   /* Enable USB Global interrupt */
139   USB_OTG_EnableGlobalInt(pdev);
140 }
141
142
143 /**
144 * @brief  Configure an EP
145 * @param pdev : Device instance
146 * @param epdesc : Endpoint Descriptor
147 * @retval : status
148 */
149 uint32_t DCD_EP_Open(USB_OTG_CORE_HANDLE *pdev , 
150                      uint8_t ep_addr,
151                      uint16_t ep_mps,
152                      uint8_t ep_type)
153 {
154   USB_OTG_EP *ep;
155   
156   if ((ep_addr & 0x80) == 0x80)
157   {
158     ep = &pdev->dev.in_ep[ep_addr & 0x7F];
159   }
160   else
161   {
162     ep = &pdev->dev.out_ep[ep_addr & 0x7F];
163   }
164   ep->num   = ep_addr & 0x7F;
165   
166   ep->is_in = (0x80 & ep_addr) != 0;
167   ep->maxpacket = ep_mps;
168   ep->type = ep_type;
169   if (ep->is_in)
170   {
171     /* Assign a Tx FIFO */
172     ep->tx_fifo_num = ep->num;
173   }
174   /* Set initial data PID. */
175   if (ep_type == USB_OTG_EP_BULK )
176   {
177     ep->data_pid_start = 0;
178   }
179   USB_OTG_EPActivate(pdev , ep );
180   return 0;
181 }
182 /**
183 * @brief  called when an EP is disabled
184 * @param pdev: device instance
185 * @param ep_addr: endpoint address
186 * @retval : status
187 */
188 uint32_t DCD_EP_Close(USB_OTG_CORE_HANDLE *pdev , uint8_t  ep_addr)
189 {
190   USB_OTG_EP *ep;
191   
192   if ((ep_addr&0x80) == 0x80)
193   {
194     ep = &pdev->dev.in_ep[ep_addr & 0x7F];
195   }
196   else
197   {
198     ep = &pdev->dev.out_ep[ep_addr & 0x7F];
199   }
200   ep->num   = ep_addr & 0x7F;
201   ep->is_in = (0x80 & ep_addr) != 0;
202   USB_OTG_EPDeactivate(pdev , ep );
203   return 0;
204 }
205
206
207 /**
208 * @brief  DCD_EP_PrepareRx
209 * @param pdev: device instance
210 * @param ep_addr: endpoint address
211 * @param pbuf: pointer to Rx buffer
212 * @param buf_len: data length
213 * @retval : status
214 */
215 uint32_t   DCD_EP_PrepareRx( USB_OTG_CORE_HANDLE *pdev,
216                             uint8_t   ep_addr,
217                             uint8_t *pbuf,                        
218                             uint16_t  buf_len)
219 {
220   USB_OTG_EP *ep;
221   
222   ep = &pdev->dev.out_ep[ep_addr & 0x7F];
223   
224   /*setup and start the Xfer */
225   ep->xfer_buff = pbuf;  
226   ep->xfer_len = buf_len;
227   ep->xfer_count = 0;
228   ep->is_in = 0;
229   ep->num = ep_addr & 0x7F;
230   
231   if (pdev->cfg.dma_enable == 1)
232   {
233     ep->dma_addr = (uint32_t)pbuf;  
234   }
235   
236   if ( ep->num == 0 )
237   {
238     USB_OTG_EP0StartXfer(pdev , ep);
239   }
240   else
241   {
242     USB_OTG_EPStartXfer(pdev, ep );
243   }
244   return 0;
245 }
246
247 /**
248 * @brief  Transmit data over USB
249 * @param pdev: device instance
250 * @param ep_addr: endpoint address
251 * @param pbuf: pointer to Tx buffer
252 * @param buf_len: data length
253 * @retval : status
254 */
255 uint32_t  DCD_EP_Tx ( USB_OTG_CORE_HANDLE *pdev,
256                      uint8_t   ep_addr,
257                      uint8_t   *pbuf,
258                      uint32_t   buf_len)
259 {
260   USB_OTG_EP *ep;
261   
262   ep = &pdev->dev.in_ep[ep_addr & 0x7F];
263   
264   /* Setup and start the Transfer */
265   ep->is_in = 1;
266   ep->num = ep_addr & 0x7F;  
267   ep->xfer_buff = pbuf;
268   ep->dma_addr = (uint32_t)pbuf;  
269   ep->xfer_count = 0;
270   ep->xfer_len  = buf_len;
271   
272   if ( ep->num == 0 )
273   {
274     USB_OTG_EP0StartXfer(pdev , ep);
275   }
276   else
277   {
278     USB_OTG_EPStartXfer(pdev, ep );
279   }
280   return 0;
281 }
282
283
284 /**
285 * @brief  Stall an endpoint.
286 * @param pdev: device instance
287 * @param epnum: endpoint address
288 * @retval : status
289 */
290 uint32_t  DCD_EP_Stall (USB_OTG_CORE_HANDLE *pdev, uint8_t   epnum)
291 {
292   USB_OTG_EP *ep;
293   if ((0x80 & epnum) == 0x80)
294   {
295     ep = &pdev->dev.in_ep[epnum & 0x7F];
296   }
297   else
298   {
299     ep = &pdev->dev.out_ep[epnum];
300   }
301
302   ep->is_stall = 1;
303   ep->num   = epnum & 0x7F;
304   ep->is_in = ((epnum & 0x80) == 0x80);
305   
306   USB_OTG_EPSetStall(pdev , ep);
307   return (0);
308 }
309
310
311 /**
312 * @brief  Clear stall condition on endpoints.
313 * @param pdev: device instance
314 * @param epnum: endpoint address
315 * @retval : status
316 */
317 uint32_t  DCD_EP_ClrStall (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum)
318 {
319   USB_OTG_EP *ep;
320   if ((0x80 & epnum) == 0x80)
321   {
322     ep = &pdev->dev.in_ep[epnum & 0x7F];    
323   }
324   else
325   {
326     ep = &pdev->dev.out_ep[epnum];
327   }
328   
329   ep->is_stall = 0;  
330   ep->num   = epnum & 0x7F;
331   ep->is_in = ((epnum & 0x80) == 0x80);
332   
333   USB_OTG_EPClearStall(pdev , ep);
334   return (0);
335 }
336
337
338 /**
339 * @brief  This Function flushes the FIFOs.
340 * @param pdev: device instance
341 * @param epnum: endpoint address
342 * @retval : status
343 */
344 uint32_t  DCD_EP_Flush (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum)
345 {
346
347   if ((epnum & 0x80) == 0x80)
348   {
349     USB_OTG_FlushTxFifo(pdev, epnum & 0x7F);
350   }
351   else
352   {
353     USB_OTG_FlushRxFifo(pdev);
354   }
355
356   return (0);
357 }
358
359
360 /**
361 * @brief  This Function set USB device address
362 * @param pdev: device instance
363 * @param address: new device address
364 * @retval : status
365 */
366 void  DCD_EP_SetAddress (USB_OTG_CORE_HANDLE *pdev, uint8_t address)
367 {
368   USB_OTG_DCFG_TypeDef  dcfg;
369   dcfg.d32 = 0;
370   dcfg.b.devaddr = address;
371   USB_OTG_MODIFY_REG32( &pdev->regs.DREGS->DCFG, 0, dcfg.d32);
372 }
373
374 /**
375 * @brief  Connect device (enable internal pull-up)
376 * @param pdev: device instance
377 * @retval : None
378 */
379 void  DCD_DevConnect (USB_OTG_CORE_HANDLE *pdev)
380 {
381 #ifndef USE_OTG_MODE
382   USB_OTG_DCTL_TypeDef  dctl;
383   dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL);
384   /* Connect device */
385   dctl.b.sftdiscon  = 0;
386   USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCTL, dctl.d32);
387   USB_OTG_BSP_mDelay(3);
388 #endif
389 }
390
391
392 /**
393 * @brief  Disconnect device (disable internal pull-up)
394 * @param pdev: device instance
395 * @retval : None
396 */
397 void  DCD_DevDisconnect (USB_OTG_CORE_HANDLE *pdev)
398 {
399 #ifndef USE_OTG_MODE
400   USB_OTG_DCTL_TypeDef  dctl;
401   dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL);
402   /* Disconnect device for 3ms */
403   dctl.b.sftdiscon  = 1;
404   USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCTL, dctl.d32);
405   USB_OTG_BSP_mDelay(3);
406 #endif
407 }
408
409
410 /**
411 * @brief  returns the EP Status
412 * @param  pdev : Selected device
413 *         epnum : endpoint address
414 * @retval : EP status
415 */
416
417 uint32_t DCD_GetEPStatus(USB_OTG_CORE_HANDLE *pdev ,uint8_t epnum)
418 {
419   USB_OTG_EP *ep;
420   uint32_t Status = 0;  
421   
422   if ((0x80 & epnum) == 0x80)
423   {
424     ep = &pdev->dev.in_ep[epnum & 0x7F];    
425   }
426   else
427   {
428     ep = &pdev->dev.out_ep[epnum];
429   }
430   
431   Status = USB_OTG_GetEPStatus(pdev ,ep);
432
433   /* Return the current status */
434   return Status;
435 }
436
437 /**
438 * @brief  Set the EP Status
439 * @param  pdev : Selected device
440 *         Status : new Status
441 *         epnum : EP address
442 * @retval : None
443 */
444 void DCD_SetEPStatus (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum , uint32_t Status)
445 {
446   USB_OTG_EP *ep;
447   
448   if ((0x80 & epnum) == 0x80)
449   {
450     ep = &pdev->dev.in_ep[epnum & 0x7F];    
451   }
452   else
453   {
454     ep = &pdev->dev.out_ep[epnum];
455   }
456   
457    USB_OTG_SetEPStatus(pdev ,ep , Status);
458 }
459
460 /**
461 * @}
462 */ 
463
464 /**
465 * @}
466 */ 
467
468 /**
469 * @}
470 */
471
472 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/