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 
47 {
48  uint32_t xfer_len;
49  int ret;
50 
51  if (cdev == NULL)
53 
54  if (cdev->iface_cdc == NULL)
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 
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))
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 
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 
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 
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
uint8_t rx_busy
Definition: usbh_cdc.h:190
#define USBH_ERR_INVALID_PARAM
Definition: usbh_lib.h:38
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
#define USBH_ERR_TIMEOUT
Definition: usbh_lib.h:46
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
Definition: usbh_cdc.h:169
NuMicro peripheral access layer header file.
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_CB_FUNC * sts_func
Definition: usbh_cdc.h:188
UTR_T * utr_rx
Definition: usbh_cdc.h:185
USB Host library exported header file.
EP_INFO_T * ep_sts
Definition: usbh_cdc.h:181
CDC_CB_FUNC * rx_func
Definition: usbh_cdc.h:189
UTR_T * utr_sts
Definition: usbh_cdc.h:184
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
uint32_t get_ticks(void)
A function return current tick count.
UDEV_T * udev
Definition: usbh_cdc.h:177
IFACE_T * iface_data
Definition: usbh_cdc.h:179
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
#define USBH_ERR_EP_NOT_FOUND
Definition: usbh_lib.h:40
EP_INFO_T * ep_tx
Definition: usbh_cdc.h:183
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
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 Host library header file.
USB Host CDC(Communication Device Class) driver header file.
void() CDC_CB_FUNC(struct cdc_dev_t *cdev, uint8_t *rdata, int data_len)
Definition: usbh_lib.h:120
EP_INFO_T * ep_rx
Definition: usbh_cdc.h:182
#define NULL
NULL pointer.
Definition: M480.h:604
uint32_t rx_buff[CDC_RX_BUFF_SIZE/4]
Definition: usbh_cdc.h:187
IFACE_T * iface_cdc
Definition: usbh_cdc.h:178
uint32_t sts_buff[CDC_STATUS_BUFF_SIZE/4]
Definition: usbh_cdc.h:186