| M480 BSP V3.05.001 The Board Support Package for M480 Series

cdc_core.c
Go to the documentation of this file.
1 /**************************************************************************/
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13
14 #include "NuMicro.h"
15
16 #include "usb.h"
17 #include "usbh_lib.h"
18 #include "usbh_cdc.h"
19
20
33 #define USB_XFER_TIMEOUT 100
35
46 int32_t usbh_cdc_get_line_coding(CDC_DEV_T *cdev, LINE_CODING_T *line_code)
47 {
48 uint32_t xfer_len;
49 int ret;
50
51 if (cdev == NULL)
52 return USBH_ERR_INVALID_PARAM;
53
54 if (cdev->iface_cdc == NULL)
55 return USBH_ERR_INVALID_PARAM;
56
57 ret = usbh_ctrl_xfer(cdev->udev,
58 REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE, /* bmRequestType */
59 CDC_GET_LINE_CODING, /* bRequest */
60 0, /* wValue */
61 cdev->iface_cdc->if_num, /* wIndex */
62 7, /* wLength */
63 (uint8_t *)line_code, /* data buffer */
64 &xfer_len, CDC_CMD_TIMEOUT);
65
66
67 if ((ret < 0) || (xfer_len != 7))
68 {
69 CDC_DBGMSG("GET_LINE_CODIN command failed. %d, %d\n", ret, xfer_len);
70 return ret;
71 }
72 return ret;
73 }
74
75
85 int32_t usbh_cdc_set_line_coding(CDC_DEV_T *cdev, LINE_CODING_T *line_code)
86 {
87 uint32_t xfer_len;
88 int ret;
89
90 if (cdev == NULL)
91 return USBH_ERR_NOT_FOUND;
92
93 if (cdev->iface_cdc == NULL)
94 return USBH_ERR_NOT_FOUND;
95
96 if ((line_code->stop_bits != 0) && (line_code->stop_bits != 1) &&
97 (line_code->stop_bits != 2))
98 return USBH_ERR_INVALID_PARAM;
99
100 if (line_code->parity > 4)
101 return USBH_ERR_INVALID_PARAM;
102
103 if ((line_code->data_bits != 5) && (line_code->data_bits != 6) &&
104 (line_code->data_bits != 7) && (line_code->data_bits != 8) &&
105 (line_code->data_bits != 16))
106 return USBH_ERR_INVALID_PARAM;
107
108 ret = usbh_ctrl_xfer(cdev->udev,
109 REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE, /* bmRequestType */
110 CDC_SET_LINE_CODING, /* bRequest */
111 0, /* wValue */
112 cdev->iface_cdc->if_num, /* wIndex */
113 7, /* wLength */
114 (uint8_t *)line_code, /* data buffer */
115 &xfer_len, CDC_CMD_TIMEOUT);
116
117 if (ret < 0)
118 {
119 CDC_DBGMSG("SET_LINE_CODIN command failed. %d\n", ret);
120 return ret;
121 }
122 return 0;
123 }
124
135 int32_t usbh_cdc_set_control_line_state(CDC_DEV_T *cdev, int active_carrier, int DTE_present)
136 {
137 uint32_t xfer_len;
138 int ret;
139 uint16_t ctrl_bitmap = 0;
140
141 if (cdev == NULL)
142 return USBH_ERR_INVALID_PARAM;
143
144 if (cdev->iface_cdc == NULL)
145 return USBH_ERR_INVALID_PARAM;
146
147 if (active_carrier)
148 ctrl_bitmap |= 0x02;
149
150 if (DTE_present)
151 ctrl_bitmap |= 0x01;
152
153 ret = usbh_ctrl_xfer(cdev->udev,
154 REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE, /* bmRequestType */
155 CDC_SET_CONTROL_LINE_STATE, /* bRequest */
156 ctrl_bitmap, /* wValue */
157 cdev->iface_cdc->if_num, /* wIndex */
158 0, /* wLength */
159 NULL, /* data buffer */
160 &xfer_len, CDC_CMD_TIMEOUT);
161
162
163 if (ret)
164 {
165 CDC_DBGMSG("SET_CONTROL_LINE_STATE command failed. %d\n", ret);
166 return ret;
167 }
168 return ret;
169 }
170
172 /*
173 * CDC INT-in complete function
174 */
175 static void cdc_int_in_irq(UTR_T *utr)
176 {
177 CDC_DEV_T *cdev;
178 int ret;
179
180 //CDC_DBGMSG("cdc_int_in_irq. %d\n", utr->xfer_len);
181
182 cdev = (CDC_DEV_T *)utr->context;
183
184 if (utr->status)
185 {
186 CDC_DBGMSG("cdc_int_in_irq - has error: 0x%x\n", utr->status);
187 return;
188 }
189
190 if (cdev->sts_func && utr->xfer_len)
191 cdev->sts_func(cdev, utr->buff, utr->xfer_len);
192
193 utr->xfer_len = 0;
194 ret = usbh_int_xfer(utr);
195 if (ret)
196 {
197 CDC_DBGMSG("cdc_int_in_irq - failed to submit interrupt-in request (%d)", ret);
198 free_utr(utr);
199 cdev->utr_sts = NULL;
200 }
201 }
202
204
213 int32_t usbh_cdc_start_polling_status(CDC_DEV_T *cdev, CDC_CB_FUNC *func)
214 {
215 EP_INFO_T *ep;
216 UTR_T *utr;
217 int ret;
218
219 if ((cdev == NULL) || (cdev->iface_cdc == NULL))
220 return USBH_ERR_NOT_FOUND;
221
222 if (!func || cdev->utr_sts)
223 return USBH_ERR_INVALID_PARAM;
224
225 ep = cdev->ep_sts;
226 if (ep == NULL)
227 {
228 ep = usbh_iface_find_ep(cdev->iface_cdc, 0, EP_ADDR_DIR_IN | EP_ATTR_TT_INT);
229 if (ep == NULL)
230 {
231 CDC_DBGMSG("Interrupt-in endpoint not found in this CDC device!\n");
232 return USBH_ERR_EP_NOT_FOUND;
233 }
234 cdev->ep_sts = ep;
235 }
236
237 utr = alloc_utr(cdev->udev);
238 if (utr == NULL)
239 {
240 CDC_DBGMSG("Failed to allocated UTR!\n");
241 return USBH_ERR_MEMORY_OUT;
242 }
243
244 utr->buff = (uint8_t *)cdev->sts_buff;
245 utr->context = cdev;
246 utr->ep = ep;
247 utr->data_len = ep->wMaxPacketSize;
248 if (utr->data_len > CDC_STATUS_BUFF_SIZE)
249 {
250 CDC_DBGMSG("Warning! CDC_STATUS_BUFF_SIZE %d is smaller than max. packet size %d!\n", CDC_STATUS_BUFF_SIZE, ep->wMaxPacketSize);
251 utr->data_len = CDC_STATUS_BUFF_SIZE;
252 }
253 utr->xfer_len = 0;
254 utr->func = cdc_int_in_irq;
255
256 cdev->utr_sts = utr;
257 cdev->sts_func = func;
258
259 ret = usbh_int_xfer(utr);
260 if (ret < 0)
261 {
262 CDC_DBGMSG("Error - failed to submit interrupt read request (%d)", ret);
263 free_utr(utr);
264 cdev->utr_sts = NULL;
265 return ret;
266 }
267
268 return 0;
269 }
271 /*
272 * CDC BULK-in complete function
273 */
274 static void cdc_bulk_in_irq(UTR_T *utr)
275 {
276 CDC_DEV_T *cdev;
277
278 //CDC_DBGMSG("cdc_bulk_in_irq. %d\n", utr->xfer_len);
279
280 cdev = (CDC_DEV_T *)utr->context;
281
282 if (utr->status)
283 {
284 CDC_DBGMSG("cdc_bulk_in_irq - has error: 0x%x\n", utr->status);
285 return;
286 }
287
288 if (cdev->rx_func)
289 cdev->rx_func(cdev, utr->buff, utr->xfer_len);
290
291 free_utr(utr);
292 cdev->utr_rx = NULL;
293 cdev->rx_busy = 0;
294 }
295
297
306 int32_t usbh_cdc_start_to_receive_data(CDC_DEV_T *cdev, CDC_CB_FUNC *func)
307 {
308 EP_INFO_T *ep;
309 UTR_T *utr;
310 int ret;
311
312 if ((cdev == NULL) || (cdev->iface_data == NULL))
313 return USBH_ERR_NOT_FOUND;
314
315 if (!func)
316 return USBH_ERR_INVALID_PARAM;
317
318 ep = cdev->ep_rx;
319 if (ep == NULL)
320 {
321 ep = usbh_iface_find_ep(cdev->iface_data, 0, EP_ADDR_DIR_IN | EP_ATTR_TT_BULK);
322 if (ep == NULL)
323 {
324 CDC_DBGMSG("Bulk-in endpoint not found in this CDC device!\n");
325 return USBH_ERR_EP_NOT_FOUND;
326 }
327 cdev->ep_rx = ep;
328 }
329
330 utr = alloc_utr(cdev->udev);
331 if (utr == NULL)
332 {
333 CDC_DBGMSG("Failed to allocated UTR!\n");
334 return USBH_ERR_MEMORY_OUT;
335 }
336
337 utr->buff = (uint8_t *)cdev->rx_buff;
338 utr->context = cdev;
339 utr->ep = ep;
340 utr->data_len = ep->wMaxPacketSize;
341 if (utr->data_len > CDC_RX_BUFF_SIZE)
342 {
343 CDC_DBGMSG("Warning! CDC_RX_BUFF_SIZE %d is smaller than max. packet size %d!\n", CDC_RX_BUFF_SIZE, ep->wMaxPacketSize);
344 utr->data_len = CDC_RX_BUFF_SIZE;
345 }
346 utr->xfer_len = 0;
347 utr->func = cdc_bulk_in_irq;
348
349 cdev->rx_func = func;
350 cdev->utr_rx = utr;
351 cdev->rx_busy = 1;
352
353 ret = usbh_bulk_xfer(utr);
354 if (ret < 0)
355 {
356 CDC_DBGMSG("Error - failed to submit bulk in request (%d)", ret);
357 free_utr(utr);
358 cdev->utr_rx = NULL;
359 cdev->rx_busy = 0;
360 return ret;
361 }
362 return 0;
363 }
365 /*
366 * CDC BULK-in complete function
367 */
368 static volatile int bulk_out_done;
369 static void cdc_bulk_out_irq(UTR_T *utr)
370 {
371 bulk_out_done = 1;
372 }
374
383 int32_t usbh_cdc_send_data(CDC_DEV_T *cdev, uint8_t *buff, int buff_len)
384 {
385 EP_INFO_T *ep;
386 UTR_T *utr;
387 uint32_t t0;
388 int ret;
389
390 if ((cdev == NULL) || (cdev->iface_data == NULL))
391 return USBH_ERR_NOT_FOUND;
392
393 ep = cdev->ep_tx;
394 if (ep == NULL)
395 {
396 ep = usbh_iface_find_ep(cdev->iface_data, 0, EP_ADDR_DIR_OUT | EP_ATTR_TT_BULK);
397 if (ep == NULL)
398 {
399 CDC_DBGMSG("Bulk-out endpoint not found in this CDC device!\n");
400 return USBH_ERR_EP_NOT_FOUND;
401 }
402 cdev->ep_tx = ep;
403 }
404
405 utr = alloc_utr(cdev->udev);
406 if (utr == NULL)
407 {
408 CDC_DBGMSG("Failed to allocated UTR!\n");
409 return USBH_ERR_MEMORY_OUT;
410 }
411
412 utr->context = cdev;
413 utr->ep = ep;
414 utr->buff = buff;
415 utr->data_len = buff_len;
416 utr->xfer_len = 0;
417 utr->func = cdc_bulk_out_irq;
418 bulk_out_done = 0;
419
420 ret = usbh_bulk_xfer(utr);
421 if (ret < 0)
422 {
423 CDC_DBGMSG("Error - failed to submit bulk in request (%d)", ret);
424 free_utr(utr);
425 return ret;
426 }
427
428 t0 = get_ticks();
429 while (bulk_out_done == 0)
430 {
431 if (get_ticks() - t0 > USB_XFER_TIMEOUT)
432 {
433 usbh_quit_utr(utr);
434 free_utr(utr);
435 return USBH_ERR_TIMEOUT;
436 }
437 }
438
439 free_utr(utr);
440 return 0;
441 }
442 /* end of group USBH_EXPORTED_FUNCTIONS */
444 /* end of group USBH_Library */
446 /* end of group Library */
448
449
450 /*** (C) COPYRIGHT 2018~2019 Nuvoton Technology Corp. ***/
451
452
USBH_ERR_NOT_FOUND
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
cdc_dev_t::rx_busy
uint8_t rx_busy
Definition: usbh_cdc.h:190
USBH_ERR_INVALID_PARAM
#define USBH_ERR_INVALID_PARAM
Definition: usbh_lib.h:38
usbh_cdc_send_data
int32_t usbh_cdc_send_data(struct cdc_dev_t *cdev, uint8_t *buff, int buff_len)
Send a block of data via CDC device's bulk-out transfer pipe.
Definition: cdc_core.c:383
USBH_ERR_TIMEOUT
#define USBH_ERR_TIMEOUT
Definition: usbh_lib.h:46
usbh_cdc_set_line_coding
int32_t usbh_cdc_set_line_coding(CDC_DEV_T *cdev, LINE_CODING_T *line_code)
SET_LINE_CODING request.
Definition: cdc_core.c:85
LINE_CODING_T
LINE_CODING_T
Definition: usbh_cdc.h:169
NuMicro.h
NuMicro peripheral access layer header file.
usbh_cdc_start_to_receive_data
int32_t usbh_cdc_start_to_receive_data(struct cdc_dev_t *cdev, CDC_CB_FUNC *func)
Make CDC device start to receive data from bulk-in transfer pipe.
Definition: cdc_core.c:306
cdc_dev_t::sts_func
CDC_CB_FUNC * sts_func
Definition: usbh_cdc.h:188
cdc_dev_t::utr_rx
UTR_T * utr_rx
Definition: usbh_cdc.h:185
usbh_lib.h
USB Host library exported header file.
cdc_dev_t::ep_sts
EP_INFO_T * ep_sts
Definition: usbh_cdc.h:181
cdc_dev_t::rx_func
CDC_CB_FUNC * rx_func
Definition: usbh_cdc.h:189
cdc_dev_t::utr_sts
UTR_T * utr_sts
Definition: usbh_cdc.h:184
usbh_cdc_set_control_line_state
HIDDEN_SYMBOLS int32_t usbh_cdc_set_control_line_state(struct cdc_dev_t *cdev, int active_carrier, int DTE_present)
SET_CONTROL_LINE_STATE request.
Definition: cdc_core.c:135
get_ticks
uint32_t get_ticks(void)
A function return current tick count.
cdc_dev_t::udev
UDEV_T * udev
Definition: usbh_cdc.h:177
cdc_dev_t::iface_data
IFACE_T * iface_data
Definition: usbh_cdc.h:179
USBH_ERR_MEMORY_OUT
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
USBH_ERR_EP_NOT_FOUND
#define USBH_ERR_EP_NOT_FOUND
Definition: usbh_lib.h:40
cdc_dev_t::ep_tx
EP_INFO_T * ep_tx
Definition: usbh_cdc.h:183
usbh_cdc_get_line_coding
int32_t usbh_cdc_get_line_coding(CDC_DEV_T *cdev, LINE_CODING_T *line_code)
GET_LINE_CODING request.
Definition: cdc_core.c:46
usbh_cdc_start_polling_status
int32_t usbh_cdc_start_polling_status(struct cdc_dev_t *cdev, CDC_CB_FUNC *func)
Start purge the CDC device's interrupt-in transfer pipe.
Definition: cdc_core.c:213
usb.h
USB Host library header file.
usbh_cdc.h
USB Host CDC(Communication Device Class) driver header file.
CDC_CB_FUNC
void() CDC_CB_FUNC(struct cdc_dev_t *cdev, uint8_t *rdata, int data_len)
Definition: usbh_lib.h:120
cdc_dev_t::ep_rx
EP_INFO_T * ep_rx
Definition: usbh_cdc.h:182
NULL
#define NULL
NULL pointer.
Definition: M480.h:604
cdc_dev_t::rx_buff
uint32_t rx_buff[CDC_RX_BUFF_SIZE/4]
Definition: usbh_cdc.h:187
cdc_dev_t::iface_cdc
IFACE_T * iface_cdc
Definition: usbh_cdc.h:178
cdc_dev_t
Definition: usbh_cdc.h:175
cdc_dev_t::sts_buff
uint32_t sts_buff[CDC_STATUS_BUFF_SIZE/4]
Definition: usbh_cdc.h:186