This source file includes following definitions.
- uslcom_match
- uslcom_attach
- uslcom_detach
- uslcom_activate
- uslcom_open
- uslcom_close
- uslcom_set
- uslcom_param
- ISSET
- uslcom_get_status
- uslcom_break
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/kernel.h>
22 #include <sys/conf.h>
23 #include <sys/tty.h>
24 #include <sys/device.h>
25
26 #include <dev/usb/usb.h>
27 #include <dev/usb/usbdi.h>
28 #include <dev/usb/usbdi_util.h>
29 #include <dev/usb/usbdevs.h>
30
31 #include <dev/usb/usbdevs.h>
32 #include <dev/usb/ucomvar.h>
33
34 #ifdef USLCOM_DEBUG
35 #define DPRINTFN(n, x) do { if (uslcomdebug > (n)) printf x; } while (0)
36 int uslcomdebug = 0;
37 #else
38 #define DPRINTFN(n, x)
39 #endif
40 #define DPRINTF(x) DPRINTFN(0, x)
41
42 #define USLCOMBUFSZ 256
43 #define USLCOM_CONFIG_NO 0
44 #define USLCOM_IFACE_NO 0
45
46 #define USLCOM_SET_DATA_BITS(x) (x << 8)
47
48 #define USLCOM_WRITE 0x41
49 #define USLCOM_READ 0xc1
50
51 #define USLCOM_UART 0x00
52 #define USLCOM_BAUD_RATE 0x01
53 #define USLCOM_DATA 0x03
54 #define USLCOM_BREAK 0x05
55 #define USLCOM_CTRL 0x07
56
57 #define USLCOM_UART_DISABLE 0x00
58 #define USLCOM_UART_ENABLE 0x01
59
60 #define USLCOM_CTRL_DTR_ON 0x0001
61 #define USLCOM_CTRL_DTR_SET 0x0100
62 #define USLCOM_CTRL_RTS_ON 0x0002
63 #define USLCOM_CTRL_RTS_SET 0x0200
64 #define USLCOM_CTRL_CTS 0x0010
65 #define USLCOM_CTRL_DSR 0x0020
66 #define USLCOM_CTRL_DCD 0x0080
67
68
69 #define USLCOM_BAUD_REF 0x384000
70
71 #define USLCOM_STOP_BITS_1 0x00
72 #define USLCOM_STOP_BITS_2 0x02
73
74 #define USLCOM_PARITY_NONE 0x00
75 #define USLCOM_PARITY_ODD 0x10
76 #define USLCOM_PARITY_EVEN 0x20
77
78 #define USLCOM_BREAK_OFF 0x00
79 #define USLCOM_BREAK_ON 0x01
80
81
82 struct uslcom_softc {
83 struct device sc_dev;
84 usbd_device_handle sc_udev;
85 usbd_interface_handle sc_iface;
86 struct device *sc_subdev;
87
88 u_char sc_msr;
89 u_char sc_lsr;
90
91 u_char sc_dying;
92 };
93
94 void uslcom_get_status(void *, int portno, u_char *lsr, u_char *msr);
95 void uslcom_set(void *, int, int, int);
96 int uslcom_param(void *, int, struct termios *);
97 int uslcom_open(void *sc, int portno);
98 void uslcom_close(void *, int);
99 void uslcom_break(void *sc, int portno, int onoff);
100
101 struct ucom_methods uslcom_methods = {
102 uslcom_get_status,
103 uslcom_set,
104 uslcom_param,
105 NULL,
106 uslcom_open,
107 uslcom_close,
108 NULL,
109 NULL,
110 };
111
112 static const struct usb_devno uslcom_devs[] = {
113 { USB_VENDOR_BALTECH, USB_PRODUCT_BALTECH_CARDREADER },
114 { USB_VENDOR_DYNASTREAM, USB_PRODUCT_DYNASTREAM_ANTDEVBOARD },
115 { USB_VENDOR_JABLOTRON, USB_PRODUCT_JABLOTRON_PC60B },
116 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARGUSISP },
117 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CRUMB128 },
118 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DEGREECONT },
119 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DESKTOPMOBILE },
120 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_IPLINK1220 },
121 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_HARP },
122 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_JTAG },
123 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_LIN },
124 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_POLOLU },
125 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_1 },
126 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_2 },
127 { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_SUNNTO },
128 { USB_VENDOR_SILABS2, USB_PRODUCT_SILABS2_DCU11CLONE },
129 { USB_VENDOR_USI, USB_PRODUCT_USI_MC60 }
130 };
131
132 int uslcom_match(struct device *, void *, void *);
133 void uslcom_attach(struct device *, struct device *, void *);
134 int uslcom_detach(struct device *, int);
135 int uslcom_activate(struct device *, enum devact);
136
137 struct cfdriver uslcom_cd = {
138 NULL, "uslcom", DV_DULL
139 };
140
141 const struct cfattach uslcom_ca = {
142 sizeof(struct uslcom_softc),
143 uslcom_match,
144 uslcom_attach,
145 uslcom_detach,
146 uslcom_activate,
147 };
148
149 int
150 uslcom_match(struct device *parent, void *match, void *aux)
151 {
152 struct usb_attach_arg *uaa = aux;
153
154 if (uaa->iface != NULL)
155 return UMATCH_NONE;
156
157 return (usb_lookup(uslcom_devs, uaa->vendor, uaa->product) != NULL) ?
158 UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
159 }
160
161 void
162 uslcom_attach(struct device *parent, struct device *self, void *aux)
163 {
164 struct uslcom_softc *sc = (struct uslcom_softc *)self;
165 struct usb_attach_arg *uaa = aux;
166 struct ucom_attach_args uca;
167 usb_interface_descriptor_t *id;
168 usb_endpoint_descriptor_t *ed;
169 usbd_status error;
170 char *devinfop;
171 int i;
172
173 bzero(&uca, sizeof(uca));
174 sc->sc_udev = uaa->device;
175 devinfop = usbd_devinfo_alloc(uaa->device, 0);
176 printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
177 usbd_devinfo_free(devinfop);
178
179 if (usbd_set_config_index(sc->sc_udev, USLCOM_CONFIG_NO, 1) != 0) {
180 printf("%s: could not set configuration no\n",
181 sc->sc_dev.dv_xname);
182 sc->sc_dying = 1;
183 return;
184 }
185
186
187 error = usbd_device2interface_handle(sc->sc_udev, USLCOM_IFACE_NO,
188 &sc->sc_iface);
189 if (error != 0) {
190 printf("%s: could not get interface handle\n",
191 sc->sc_dev.dv_xname);
192 sc->sc_dying = 1;
193 return;
194 }
195
196 id = usbd_get_interface_descriptor(sc->sc_iface);
197
198 uca.bulkin = uca.bulkout = -1;
199 for (i = 0; i < id->bNumEndpoints; i++) {
200 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
201 if (ed == NULL) {
202 printf("%s: no endpoint descriptor found for %d\n",
203 sc->sc_dev.dv_xname, i);
204 sc->sc_dying = 1;
205 return;
206 }
207
208 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
209 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
210 uca.bulkin = ed->bEndpointAddress;
211 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
212 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
213 uca.bulkout = ed->bEndpointAddress;
214 }
215
216 if (uca.bulkin == -1 || uca.bulkout == -1) {
217 printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
218 sc->sc_dying = 1;
219 return;
220 }
221
222 uca.ibufsize = USLCOMBUFSZ;
223 uca.obufsize = USLCOMBUFSZ;
224 uca.ibufsizepad = USLCOMBUFSZ;
225 uca.opkthdrlen = 0;
226 uca.device = sc->sc_udev;
227 uca.iface = sc->sc_iface;
228 uca.methods = &uslcom_methods;
229 uca.arg = sc;
230 uca.info = NULL;
231
232 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
233 &sc->sc_dev);
234
235 sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
236 }
237
238 int
239 uslcom_detach(struct device *self, int flags)
240 {
241 struct uslcom_softc *sc = (struct uslcom_softc *)self;
242 int rv = 0;
243
244 sc->sc_dying = 1;
245 if (sc->sc_subdev != NULL) {
246 rv = config_detach(sc->sc_subdev, flags);
247 sc->sc_subdev = NULL;
248 }
249
250 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
251 &sc->sc_dev);
252
253 return (rv);
254 }
255
256 int
257 uslcom_activate(struct device *self, enum devact act)
258 {
259 struct uslcom_softc *sc = (struct uslcom_softc *)self;
260 int rv = 0;
261
262 switch (act) {
263 case DVACT_ACTIVATE:
264 break;
265
266 case DVACT_DEACTIVATE:
267 if (sc->sc_subdev != NULL)
268 rv = config_deactivate(sc->sc_subdev);
269 sc->sc_dying = 1;
270 break;
271 }
272 return (rv);
273 }
274
275 int
276 uslcom_open(void *vsc, int portno)
277 {
278 struct uslcom_softc *sc = vsc;
279 usb_device_request_t req;
280 usbd_status err;
281
282 if (sc->sc_dying)
283 return (EIO);
284
285 req.bmRequestType = USLCOM_WRITE;
286 req.bRequest = USLCOM_UART;
287 USETW(req.wValue, USLCOM_UART_ENABLE);
288 USETW(req.wIndex, portno);
289 USETW(req.wLength, 0);
290 err = usbd_do_request(sc->sc_udev, &req, NULL);
291 if (err)
292 return (EIO);
293
294 return (0);
295 }
296
297 void
298 uslcom_close(void *vsc, int portno)
299 {
300 struct uslcom_softc *sc = vsc;
301 usb_device_request_t req;
302
303 if (sc->sc_dying)
304 return;
305
306 req.bmRequestType = USLCOM_WRITE;
307 req.bRequest = USLCOM_UART;
308 USETW(req.wValue, USLCOM_UART_DISABLE);
309 USETW(req.wIndex, portno);
310 USETW(req.wLength, 0);
311 usbd_do_request(sc->sc_udev, &req, NULL);
312 }
313
314 void
315 uslcom_set(void *vsc, int portno, int reg, int onoff)
316 {
317 struct uslcom_softc *sc = vsc;
318 usb_device_request_t req;
319 int ctl;
320
321 switch (reg) {
322 case UCOM_SET_DTR:
323 ctl = onoff ? USLCOM_CTRL_DTR_ON : 0;
324 ctl |= USLCOM_CTRL_DTR_SET;
325 break;
326 case UCOM_SET_RTS:
327 ctl = onoff ? USLCOM_CTRL_RTS_ON : 0;
328 ctl |= USLCOM_CTRL_RTS_SET;
329 break;
330 case UCOM_SET_BREAK:
331 uslcom_break(sc, portno, onoff);
332 return;
333 default:
334 return;
335 }
336 req.bmRequestType = USLCOM_WRITE;
337 req.bRequest = USLCOM_CTRL;
338 USETW(req.wValue, ctl);
339 USETW(req.wIndex, portno);
340 USETW(req.wLength, 0);
341 usbd_do_request(sc->sc_udev, &req, NULL);
342 }
343
344 int
345 uslcom_param(void *vsc, int portno, struct termios *t)
346 {
347 struct uslcom_softc *sc = (struct uslcom_softc *)vsc;
348 usbd_status err;
349 usb_device_request_t req;
350 int data;
351
352 switch (t->c_ospeed) {
353 case 600:
354 case 1200:
355 case 1800:
356 case 2400:
357 case 4800:
358 case 9600:
359 case 19200:
360 case 38400:
361 case 57600:
362 case 115200:
363 case 460800:
364 case 921600:
365 req.bmRequestType = USLCOM_WRITE;
366 req.bRequest = USLCOM_BAUD_RATE;
367 USETW(req.wValue, USLCOM_BAUD_REF / t->c_ospeed);
368 USETW(req.wIndex, portno);
369 USETW(req.wLength, 0);
370 err = usbd_do_request(sc->sc_udev, &req, NULL);
371 if (err)
372 return (EIO);
373 break;
374 default:
375 return (EINVAL);
376 }
377
378 if (ISSET(t->c_cflag, CSTOPB))
379 data = USLCOM_STOP_BITS_2;
380 else
381 data = USLCOM_STOP_BITS_1;
382 if (ISSET(t->c_cflag, PARENB)) {
383 if (ISSET(t->c_cflag, PARODD))
384 data |= USLCOM_PARITY_ODD;
385 else
386 data |= USLCOM_PARITY_EVEN;
387 } else
388 data |= USLCOM_PARITY_NONE;
389 switch (ISSET(t->c_cflag, CSIZE)) {
390 case CS5:
391 data |= USLCOM_SET_DATA_BITS(5);
392 break;
393 case CS6:
394 data |= USLCOM_SET_DATA_BITS(6);
395 break;
396 case CS7:
397 data |= USLCOM_SET_DATA_BITS(7);
398 break;
399 case CS8:
400 data |= USLCOM_SET_DATA_BITS(8);
401 break;
402 }
403
404 req.bmRequestType = USLCOM_WRITE;
405 req.bRequest = USLCOM_DATA;
406 USETW(req.wValue, data);
407 USETW(req.wIndex, portno);
408 USETW(req.wLength, 0);
409 err = usbd_do_request(sc->sc_udev, &req, NULL);
410 if (err)
411 return (EIO);
412
413 #if 0
414
415 if (ISSET(t->c_cflag, CRTSCTS))
416
417 } else if (ISSET(t->c_iflag, IXON|IXOFF)) {
418
419 } else {
420
421 }
422 #endif
423
424 return (0);
425 }
426
427 void
428 uslcom_get_status(void *vsc, int portno, u_char *lsr, u_char *msr)
429 {
430 struct uslcom_softc *sc = vsc;
431
432 if (msr != NULL)
433 *msr = sc->sc_msr;
434 if (lsr != NULL)
435 *lsr = sc->sc_lsr;
436 }
437
438 void
439 uslcom_break(void *vsc, int portno, int onoff)
440 {
441 struct uslcom_softc *sc = vsc;
442 usb_device_request_t req;
443 int brk = onoff ? USLCOM_BREAK_ON : USLCOM_BREAK_OFF;
444
445 req.bmRequestType = USLCOM_WRITE;
446 req.bRequest = USLCOM_BREAK;
447 USETW(req.wValue, brk);
448 USETW(req.wIndex, portno);
449 USETW(req.wLength, 0);
450 usbd_do_request(sc->sc_udev, &req, NULL);
451 }