| 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
280 CDC_DEV_T * usbh_cdc_get_device_list(void)
281 {
282 return g_cdev_list;
283 }
284
285
286 /*** (C) COPYRIGHT 2018~2019 Nuvoton Technology Corp. ***/
287
USBH_ERR_NOT_FOUND
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
NuMicro.h
NuMicro peripheral access layer header file.
cdc_dev_t::utr_rx
UTR_T * utr_rx
Definition: usbh_cdc.h:185
cdc_dev_t::ifnum_data
int ifnum_data
Definition: usbh_cdc.h:180
usbh_lib.h
USB Host library exported header file.
cdc_dev_t::utr_sts
UTR_T * utr_sts
Definition: usbh_cdc.h:184
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_cdc_get_device_list
CDC_DEV_T * usbh_cdc_get_device_list(void)
Get a list of currently connected USB Hid devices.
Definition: cdc_driver.c:280
cdc_dev_t::next
struct cdc_dev_t * next
Definition: usbh_cdc.h:191
uac_dev_t::udev
UDEV_T * udev
Definition: usbh_uac.h:111
usb.h
USB Host library header file.
usbh_cdc.h
USB Host CDC(Communication Device Class) driver header file.
NULL
#define NULL
NULL pointer.
Definition: M480.h:604
USBH_ERR_NOT_MATCHED
#define USBH_ERR_NOT_MATCHED
Definition: usbh_lib.h:36
cdc_dev_t::iface_cdc
IFACE_T * iface_cdc
Definition: usbh_cdc.h:178
cdc_dev_t
Definition: usbh_cdc.h:175
usbh_cdc_init
void usbh_cdc_init(void)
Init USB Host CDC driver.
Definition: cdc_driver.c:265