1 /******************************************************************************************************************************************
2 * 文件名称: usbh_cdc_core.c
3 * 功能说明:
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0      2020年11月3日
7 * 升级记录:
8 *
9 *
10 *******************************************************************************************************************************************
11 * @attention
12 *
13 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
14 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
15 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
16 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
17 * -ECTION WITH THEIR PRODUCTS.
18 *
19 * COPYRIGHT 2012 Synwit Technology
20 *******************************************************************************************************************************************/
21 #include <stdlib.h>
22 #include <string.h>
23 #include "SWM341.h"
24 #include "usbh_core.h"
25 #include "usbh_stdreq.h"
26 #include "usbh_cdc_core.h"
27 #include "usbh_cdc_funct.h"
28 
29 
30 USBH_Class_cb_t USBH_CDC_cb =
31 {
32     USBH_CDC_Init,
33     USBH_CDC_DeInit,
34     USBH_CDC_Request,
35     USBH_CDC_Process
36 };
37 
38 
39 volatile USBH_CDC_Info_t USBH_CDC_Info;
40 
41 
42 /******************************************************************************************************************************************
43 * 函数名称: USBH_CDC_Init()
44 * 功能说明:
45 * 输    入: 无
46 * 输    出: 无
47 * 注意事项: 无
48 ******************************************************************************************************************************************/
USBH_CDC_Init(USBH_Info_t * phost)49 USBH_Status USBH_CDC_Init(USBH_Info_t *phost)
50 {
51     USB_EpDesc_t *pEpIn, *pEpOut, *pEpCtrl;
52 
53     if((phost->Device.Dev_Desc.bDeviceClass == USB_CDC_CLASS) &&
54        (phost->Device.Intf_Desc[0].bInterfaceClass == USB_CDC_CTRL_CLASS) &&
55        (phost->Device.Intf_Desc[1].bInterfaceClass == USB_CDC_DATA_CLASS))
56     {
57         pEpCtrl = &phost->Device.Ep_Desc[0][0];
58 
59         if(phost->Device.Ep_Desc[1][0].bEndpointAddress & USB_EP_IN)
60         {
61             pEpIn  = &phost->Device.Ep_Desc[1][0];
62             pEpOut = &phost->Device.Ep_Desc[1][1];
63         }
64         else
65         {
66             pEpIn  = &phost->Device.Ep_Desc[1][1];
67             pEpOut = &phost->Device.Ep_Desc[1][0];
68         }
69 
70         USBH_CDC_Info.InEp       = pEpIn->bEndpointAddress;
71         USBH_CDC_Info.InEpSize   = pEpIn->wMaxPacketSize;
72         USBH_CDC_Info.OutEp      = pEpOut->bEndpointAddress;
73         USBH_CDC_Info.OutEpSize  = pEpOut->wMaxPacketSize;
74         USBH_CDC_Info.CtrlEp     = pEpCtrl->bEndpointAddress;
75         USBH_CDC_Info.CtrlEpSize = pEpCtrl->wMaxPacketSize;
76 
77         USBH_CDC_DeInit(phost);
78     }
79     else
80     {
81         if(phost->usr_cb->DeviceNotSupported)
82             phost->usr_cb->DeviceNotSupported();
83 
84         return USBH_NOT_SUPPORTED;
85     }
86 
87     return USBH_OK;
88 }
89 
90 
91 /******************************************************************************************************************************************
92 * 函数名称: USBH_CDC_DeInit()
93 * 功能说明:
94 * 输    入: 无
95 * 输    出: 无
96 * 注意事项: 无
97 ******************************************************************************************************************************************/
USBH_CDC_DeInit(USBH_Info_t * phost)98 void USBH_CDC_DeInit(USBH_Info_t *phost)
99 {
100     USBH_CDC_Info.InEpDATAX = 0;
101     USBH_CDC_Info.OutEpDATAX = 0;
102     USBH_CDC_Info.CtrlEpDATAX = 0;
103 
104     USBH_CDC_Info.TxWrPtr = 0;
105     USBH_CDC_Info.TxRdPtr = 0;
106     USBH_CDC_Info.RxWrPtr = 0;
107     USBH_CDC_Info.RxRdPtr = 0;
108 
109     USBH_CDC_Info.state = USBH_CDC_SEND;
110     USBH_CDC_Info.reqState = CDC_GET_LINE_CODING;
111 }
112 
113 
114 /******************************************************************************************************************************************
115 * 函数名称: USBH_CDC_Request()
116 * 功能说明:
117 * 输    入: 无
118 * 输    出: 无
119 * 注意事项: 无
120 ******************************************************************************************************************************************/
USBH_CDC_Request(USBH_Info_t * phost)121 USBH_Status USBH_CDC_Request(USBH_Info_t *phost)
122 {
123     USBH_Status status = USBH_BUSY;
124     USBH_Status reqStatus;
125 
126     switch(USBH_CDC_Info.reqState)
127     {
128     case CDC_SET_LINE_CODING:
129         reqStatus = USBH_CDC_SetLineCoding(phost);
130         if(reqStatus == USBH_OK)
131         {
132             USBH_CDC_Info.reqState = CDC_GET_LINE_CODING ;
133         }
134         if(reqStatus == USBH_NOT_SUPPORTED)
135         {
136             USBH_CDC_Info.reqState = CDC_CLR_STALL;
137         }
138         break;
139 
140     case CDC_GET_LINE_CODING:
141         reqStatus = USBH_CDC_GetLineCoding(phost);
142         if(reqStatus == USBH_OK)
143         {
144             USBH_CDC_Info.reqState = CDC_SET_CONTROL_LINE;
145         }
146         break;
147 
148     case CDC_SET_CONTROL_LINE:
149         reqStatus = USBH_CDC_SetControlLine(phost);
150         if(reqStatus == USBH_OK)
151         {
152             status = USBH_OK;
153         }
154         break;
155 
156     case CDC_CLR_STALL:
157         reqStatus = USBH_ClrFeature(phost, 0);
158         if(reqStatus == USBH_OK )
159         {
160             phost->Ctrl.toggle_out = 0;
161 
162             USBH_CDC_Info.reqState = CDC_GET_LINE_CODING ;
163         }
164         break;
165     }
166 
167     return status;
168 }
169 
170 
171 /******************************************************************************************************************************************
172 * 函数名称: USBH_CDC_Process()
173 * 功能说明:
174 * 输    入: 无
175 * 输    出: 无
176 * 注意事项: 无
177 ******************************************************************************************************************************************/
USBH_CDC_Process(USBH_Info_t * phost)178 USBH_Status USBH_CDC_Process(USBH_Info_t *phost)
179 {
180     static uint32_t FrameNbr = 0;
181     static uint32_t size;
182     uint32_t available, space;
183     USBH_Status status = USBH_OK;
184     USBH_Resp resp;
185 
186     switch(USBH_CDC_Info.state)
187     {
188     case USBH_CDC_SEND:
189         available = USBH_CDC_Info.TxWrPtr - USBH_CDC_Info.TxRdPtr;
190         if((available >= USBH_CDC_Info.OutEpSize) || ((available > 0) && (abs((int)USBH->FRAMENR - (int)USBH_CDC_Info.TxFrameNbr) > 10)))
191         {
192             USBH_CDC_Info.TxFrameNbr = USBH->FRAMENR;
193 
194             size = (available > USBH_CDC_Info.OutEpSize) ? USBH_CDC_Info.OutEpSize : available;
195 
196             if(USBH_SendOutPacket(phost->Device.Address, USBH_CDC_Info.OutEp, USBH_CDC_Info.OutEpDATAX, (uint8_t *)&USBH_CDC_Info.TxBuff[USBH_CDC_Info.TxRdPtr], size))
197             {
198                 USBH_CDC_Info.state = USBH_CDC_SEND_WAIT;
199             }
200         }
201         else
202         {
203             USBH_CDC_Info.state = USBH_CDC_READ;
204         }
205         break;
206 
207     case USBH_CDC_SEND_WAIT:
208         resp = USBH_State();
209         if(resp != USBR_NO)
210         {
211             if(resp == USBR_ACK)
212             {
213                 USBH_CDC_Info.OutEpDATAX ^= 1;
214 
215                 USBH_CDC_Info.TxRdPtr += size;
216                 if(USBH_CDC_Info.TxRdPtr == USBH_CDC_Info.TxWrPtr)  // USBH_CDC_Info.TxBuff 中数据已全部发出
217                 {
218                     USBH_CDC_Info.TxRdPtr = 0;
219                     USBH_CDC_Info.TxWrPtr = 0;
220                 }
221             }
222 
223             USBH_CDC_Info.state = USBH_CDC_READ;
224         }
225         break;
226 
227     case USBH_CDC_READ:
228         space = USBH_CDC_BUFF_SIZE - USBH_CDC_Info.RxWrPtr;
229         if((space >= USBH_CDC_Info.InEpSize) && (abs((int)USBH->FRAMENR - (int)USBH_CDC_Info.TxFrameNbr) > 10))
230         {
231             USBH_CDC_Info.RxFrameNbr = USBH->FRAMENR;
232 
233             if(USBH_SendInPacket(phost->Device.Address, USBH_CDC_Info.InEp, USBH_CDC_Info.InEpDATAX, USBH_CDC_Info.InEpSize))
234             {
235                 USBH_CDC_Info.state = USBH_CDC_READ_WAIT;
236             }
237         }
238         break;
239 
240     case USBH_CDC_READ_WAIT:
241         resp = USBH_State();
242         if(resp != USBR_NO)
243         {
244             if(resp == USBR_ACK)
245             {
246                 USBH_CDC_Info.InEpDATAX ^= 1;
247 
248                 size = USBH_ReadRxBuffer((uint8_t *)&USBH_CDC_Info.RxBuff[USBH_CDC_Info.RxWrPtr], USBH_CDC_Info.InEpSize);
249                 USBH_CDC_Info.RxWrPtr += size;
250             }
251 
252             USBH_CDC_Info.state = USBH_CDC_SEND;
253         }
254         break;
255 
256     case USBH_CDC_CTRL:
257         break;
258     }
259 
260     return status;
261 }
262 
263 
264 /******************************************************************************************************************************************
265 * 函数名称: USBH_CDC_Process()
266 * 功能说明:
267 * 输    入: 无
268 * 输    出: 无
269 * 注意事项: 无
270 ******************************************************************************************************************************************/
USBH_CDC_Send(uint8_t * data,uint16_t size)271 uint32_t USBH_CDC_Send(uint8_t *data, uint16_t size)
272 {
273     uint16_t space = USBH_CDC_BUFF_SIZE - USBH_CDC_Info.TxWrPtr;    // 可写入数据个数
274 
275     if(space >= size)
276     {
277         __disable_irq();
278 
279         memcpy((uint8_t *)&USBH_CDC_Info.TxBuff[USBH_CDC_Info.TxWrPtr], data, size);
280         USBH_CDC_Info.TxWrPtr += size;
281 
282         __enable_irq();
283 
284         return size;
285     }
286 
287     return 0;
288 }
289 
290 
291 /******************************************************************************************************************************************
292 * 函数名称: USBH_CDC_Process()
293 * 功能说明:
294 * 输    入: 无
295 * 输    出: 无
296 * 注意事项: 无
297 ******************************************************************************************************************************************/
USBH_CDC_Read(uint8_t * buff,uint16_t size)298 uint32_t USBH_CDC_Read(uint8_t *buff, uint16_t size)
299 {
300     uint16_t available = USBH_CDC_Info.RxWrPtr - USBH_CDC_Info.RxRdPtr;
301 
302     if(size > available)
303         size = available;
304 
305     if(size)
306     {
307         __disable_irq();
308 
309         memcpy(buff, (uint8_t *)&USBH_CDC_Info.RxBuff[USBH_CDC_Info.RxRdPtr], size);
310 
311         USBH_CDC_Info.RxRdPtr += size;
312         if(USBH_CDC_Info.RxRdPtr == USBH_CDC_Info.RxWrPtr)  // USBH_CDC_Info.RxBuff 中数据已全部读出
313         {
314             USBH_CDC_Info.RxRdPtr = 0;
315             USBH_CDC_Info.RxWrPtr = 0;
316         }
317 
318         __enable_irq();
319     }
320 
321     return size;
322 }
323