M480 BSP  V3.05.001
The Board Support Package for M480 Series
cdc_driver.c
Go to the documentation of this file.
1 /**************************************************************************/
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "NuMicro.h"
15 
16 #include "usb.h"
17 #include "usbh_lib.h"
18 #include "usbh_cdc.h"
19 
20 
22 
23 extern int cdc_config_parser(CDC_DEV_T *cdev);
24 
25 static CDC_DEV_T *g_cdev_list = NULL;
26 
27 static CDC_DEV_T *alloc_cdc_device(void)
28 {
29  CDC_DEV_T *cdev;
30 
31  cdev = (CDC_DEV_T *)usbh_alloc_mem(sizeof(CDC_DEV_T));
32  if (cdev == NULL)
33  return NULL;
34 
35  memset((char *)cdev, 0, sizeof(CDC_DEV_T));
36  cdev->ifnum_data = -1;
37  return cdev;
38 }
39 
40 void free_cdc_device(CDC_DEV_T *cdev)
41 {
42  usbh_free_mem(cdev, sizeof(CDC_DEV_T));
43 }
44 
45 static void add_new_cdc_device(CDC_DEV_T *cdev)
46 {
47  if (g_cdev_list == NULL)
48  {
49  cdev->next = NULL;
50  g_cdev_list = cdev;
51  }
52  else
53  {
54  cdev->next = g_cdev_list;
55  g_cdev_list = cdev;
56  }
57 }
58 
59 static void remove_cdc_device(CDC_DEV_T *cdev)
60 {
61  CDC_DEV_T *p;
62 
63  if (g_cdev_list == cdev)
64  {
65  g_cdev_list = g_cdev_list->next;
66  return;
67  }
68 
69  p = g_cdev_list;
70  while (p != NULL)
71  {
72  if (p->next == cdev)
73  {
74  p->next = cdev->next;
75  return;
76  }
77  p = p->next;
78  }
79  CDC_DBGMSG("Warning! remove_cdc_device 0x%x not found!\n", (int)cdev);
80 }
81 
82 /*
83  * Try to find the companion CDC interface of a DATA interface.
84  */
85 static CDC_DEV_T * find_cdc_com_iface(IFACE_T *iface_data)
86 {
87  CDC_DEV_T *p;
88 
89  p = g_cdev_list;
90  while (p != NULL)
91  {
92  if (p->ifnum_data == iface_data->if_num)
93  {
94  return p;
95  }
96  p = p->next;
97  }
98  return NULL;
99 }
100 
101 /*
102  * Try to find any temporary CDC device holder of data interface
103  */
104 static CDC_DEV_T * find_cdc_data_iface(int ifnum)
105 {
106  CDC_DEV_T *p;
107 
108  p = g_cdev_list;
109  while (p != NULL)
110  {
111  if ((p->iface_cdc == NULL) && (p->iface_data != NULL) &&
112  (p->ifnum_data == ifnum))
113  {
114  return p;
115  }
116  p = p->next;
117  }
118  return NULL;
119 }
120 
121 static int cdc_probe(IFACE_T *iface)
122 {
123  UDEV_T *udev = iface->udev;
124  ALT_IFACE_T *aif = iface->aif;
125  DESC_IF_T *ifd;
126  CDC_DEV_T *cdev, *d;
127  int ret;
128 
129  ifd = aif->ifd;
130 
131  /* Is this interface CDC class? */
132  if ((ifd->bInterfaceClass != USB_CLASS_COMM) && (ifd->bInterfaceClass != USB_CLASS_DATA))
133  return USBH_ERR_NOT_MATCHED;
134 
135  CDC_DBGMSG("cdc_probe %s - device (vid=0x%x, pid=0x%x), interface %d.\n",
136  (ifd->bInterfaceClass == USB_CLASS_COMM) ? "COMM" : "DATA",
137  udev->descriptor.idVendor, udev->descriptor.idProduct, ifd->bInterfaceNumber);
138 
139  if (ifd->bInterfaceClass == USB_CLASS_DATA)
140  {
141  cdev = find_cdc_com_iface(iface); /* If this CDC device may have been created in the previous inetrface probing? */
142  if (cdev == NULL)
143  {
144  CDC_DBGMSG("Warning! CDC device DTAT interface %d cannot find COMM interface!\n", iface->if_num);
145 
146  /* create a temporary CDC device holder */
147  cdev = alloc_cdc_device();
148  if (cdev == NULL)
149  return USBH_ERR_NOT_FOUND;
150 
151  cdev->udev = udev;
152  add_new_cdc_device(cdev);
153  cdev->ifnum_data = iface->if_num;
154  }
155  cdev->iface_data = iface;
156  iface->context = cdev;
157  return 0;
158  }
159 
160  /*------- Is CDC COMM interface ----------*/
161 
162  cdev = alloc_cdc_device();
163  if (cdev == NULL)
164  return USBH_ERR_NOT_FOUND;
165 
166  cdev->udev = udev;
167  cdev->iface_cdc = iface;
168  iface->context = (void *)cdev;
169 
170  ret = cdc_config_parser(cdev);
171  if (ret != 0)
172  {
173  CDC_DBGMSG("Parsing CDC desceiptor failed! 0x%x\n", ret);
174  free_cdc_device(cdev);
175  return -1;
176  }
177 
178  add_new_cdc_device(cdev);
179 
180  /* find temporary CDC device holder of data interface */
181  d = find_cdc_data_iface(cdev->ifnum_data); /* If this CDC device may have been created in the previous inetrface probing? */
182  if (d)
183  {
184  cdev->iface_data = d->iface_data;
185  cdev->iface_data->context = cdev;
186  remove_cdc_device(d);
187  free_cdc_device(d);
188  }
189 
190  return 0;
191 }
192 
193 static void cdc_disconnect(IFACE_T *iface)
194 {
195  IFACE_T *if_cdc, *if_data;
196  CDC_DEV_T *cdev;
197  int i;
198 
199  CDC_DBGMSG("CDC device interface %d disconnected!\n", iface->if_num);
200 
201  cdev = (CDC_DEV_T *)(iface->context);
202 
203  if (cdev == NULL)
204  return; /* should have been disconnected. */
205 
206  if_cdc = cdev->iface_cdc;
207  if_data = cdev->iface_data;
208 
209  /*
210  * Quit transfers of all endpoints of COMM and DATA interface.
211  */
212  if (if_cdc)
213  {
214  for (i = 0; i < if_cdc->aif->ifd->bNumEndpoints; i++)
215  {
216  if_cdc->udev->hc_driver->quit_xfer(NULL, &(if_cdc->aif->ep[i]));
217  }
218  }
219 
220  if (if_data)
221  {
222  for (i = 0; i < if_data->aif->ifd->bNumEndpoints; i++)
223  {
224  if_data->udev->hc_driver->quit_xfer(NULL, &(if_data->aif->ep[i]));
225  }
226  }
227 
228  if (cdev->utr_sts)
229  {
230  usbh_quit_utr(cdev->utr_sts); /* Quit the UTR */
231  free_utr(cdev->utr_sts);
232  cdev->utr_sts = NULL;
233  }
234  if (cdev->utr_rx)
235  {
236  usbh_quit_utr(cdev->utr_rx); /* Quit the UTR */
237  free_utr(cdev->utr_rx);
238  cdev->utr_rx = NULL;
239  }
240 
241  if_cdc->context = NULL;
242  if_data->context = NULL;
243 
244  remove_cdc_device(cdev);
245  free_cdc_device(cdev);
246 }
247 
248 
249 static UDEV_DRV_T cdc_driver =
250 {
251  cdc_probe,
252  cdc_disconnect,
253  NULL,
254  NULL,
255 };
256 
257 
259 
260 
265 void usbh_cdc_init(void)
266 {
267  g_cdev_list = NULL;
268  usbh_register_driver(&cdc_driver);
269 }
270 
271 
281 {
282  return g_cdev_list;
283 }
284 
285 
286 /*** (C) COPYRIGHT 2018~2019 Nuvoton Technology Corp. ***/
287 
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
NuMicro peripheral access layer header file.
UTR_T * utr_rx
Definition: usbh_cdc.h:185
int ifnum_data
Definition: usbh_cdc.h:180
USB Host library exported header file.
UTR_T * utr_sts
Definition: usbh_cdc.h:184
UDEV_T * udev
Definition: usbh_cdc.h:177
IFACE_T * iface_data
Definition: usbh_cdc.h:179
CDC_DEV_T * usbh_cdc_get_device_list(void)
Get a list of currently connected USB Hid devices.
Definition: cdc_driver.c:280
struct cdc_dev_t * next
Definition: usbh_cdc.h:191
UDEV_T * udev
Definition: usbh_uac.h:111
USB Host library header file.
USB Host CDC(Communication Device Class) driver header file.
#define NULL
NULL pointer.
Definition: M480.h:604
#define USBH_ERR_NOT_MATCHED
Definition: usbh_lib.h:36
IFACE_T * iface_cdc
Definition: usbh_cdc.h:178
void usbh_cdc_init(void)
Init USB Host CDC driver.
Definition: cdc_driver.c:265