Annotation of sys/dev/usb/ubsa.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ubsa.c,v 1.30 2007/06/14 10:11:15 mbalmer Exp $ */
2: /* $NetBSD: ubsa.c,v 1.5 2002/11/25 00:51:33 fvdl Exp $ */
3: /*-
4: * Copyright (c) 2002, Alexander Kabaev <kan.FreeBSD.org>.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28: /*
29: * Copyright (c) 2001 The NetBSD Foundation, Inc.
30: * All rights reserved.
31: *
32: * This code is derived from software contributed to The NetBSD Foundation
33: * by Ichiro FUKUHARA (ichiro@ichiro.org).
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the NetBSD
46: * Foundation, Inc. and its contributors.
47: * 4. Neither the name of The NetBSD Foundation nor the names of its
48: * contributors may be used to endorse or promote products derived
49: * from this software without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
52: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
55: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61: * POSSIBILITY OF SUCH DAMAGE.
62: */
63:
64: #include <sys/cdefs.h>
65:
66: #include <sys/param.h>
67: #include <sys/systm.h>
68: #include <sys/kernel.h>
69: #include <sys/malloc.h>
70: #include <sys/device.h>
71: #include <sys/ioccom.h>
72: #include <sys/fcntl.h>
73: #include <sys/conf.h>
74: #include <sys/tty.h>
75: #include <sys/file.h>
76: #include <sys/selinfo.h>
77: #include <sys/proc.h>
78: #include <sys/vnode.h>
79: #include <sys/poll.h>
80: #include <sys/sysctl.h>
81:
82: #include <dev/usb/usb.h>
83: #include <dev/usb/usbcdc.h>
84:
85: #include <dev/usb/usbdi.h>
86: #include <dev/usb/usbdi_util.h>
87: #include <dev/usb/usbdevs.h>
88: #include <dev/usb/usb_quirks.h>
89:
90: #include <dev/usb/ucomvar.h>
91:
92: #ifdef USB_DEBUG
93: #define UBSA_DEBUG
94: #endif
95:
96: #ifdef UBSA_DEBUG
97: int ubsadebug = 0;
98:
99: #define DPRINTFN(n, x) do { if (ubsadebug > (n)) printf x; } while (0)
100: #else
101: #define DPRINTFN(n, x)
102: #endif
103: #define DPRINTF(x) DPRINTFN(0, x)
104:
105: #define UBSA_MODVER 1 /* module version */
106:
107: #define UBSA_CONFIG_INDEX 1
108: #define UBSA_IFACE_INDEX 0
109:
110: #define UBSA_INTR_INTERVAL 100 /* ms */
111:
112: #define UBSA_SET_BAUDRATE 0x00
113: #define UBSA_SET_STOP_BITS 0x01
114: #define UBSA_SET_DATA_BITS 0x02
115: #define UBSA_SET_PARITY 0x03
116: #define UBSA_SET_DTR 0x0A
117: #define UBSA_SET_RTS 0x0B
118: #define UBSA_SET_BREAK 0x0C
119: #define UBSA_SET_FLOW_CTRL 0x10
120:
121: #define UBSA_PARITY_NONE 0x00
122: #define UBSA_PARITY_EVEN 0x01
123: #define UBSA_PARITY_ODD 0x02
124: #define UBSA_PARITY_MARK 0x03
125: #define UBSA_PARITY_SPACE 0x04
126:
127: #define UBSA_FLOW_NONE 0x0000
128: #define UBSA_FLOW_OCTS 0x0001
129: #define UBSA_FLOW_ODSR 0x0002
130: #define UBSA_FLOW_IDSR 0x0004
131: #define UBSA_FLOW_IDTR 0x0008
132: #define UBSA_FLOW_IRTS 0x0010
133: #define UBSA_FLOW_ORTS 0x0020
134: #define UBSA_FLOW_UNKNOWN 0x0040
135: #define UBSA_FLOW_OXON 0x0080
136: #define UBSA_FLOW_IXON 0x0100
137:
138: /* line status register */
139: #define UBSA_LSR_TSRE 0x40 /* Transmitter empty: byte sent */
140: #define UBSA_LSR_TXRDY 0x20 /* Transmitter buffer empty */
141: #define UBSA_LSR_BI 0x10 /* Break detected */
142: #define UBSA_LSR_FE 0x08 /* Framing error: bad stop bit */
143: #define UBSA_LSR_PE 0x04 /* Parity error */
144: #define UBSA_LSR_OE 0x02 /* Overrun, lost incoming byte */
145: #define UBSA_LSR_RXRDY 0x01 /* Byte ready in Receive Buffer */
146: #define UBSA_LSR_RCV_MASK 0x1f /* Mask for incoming data or error */
147:
148: /* modem status register */
149: /* All deltas are from the last read of the MSR. */
150: #define UBSA_MSR_DCD 0x80 /* Current Data Carrier Detect */
151: #define UBSA_MSR_RI 0x40 /* Current Ring Indicator */
152: #define UBSA_MSR_DSR 0x20 /* Current Data Set Ready */
153: #define UBSA_MSR_CTS 0x10 /* Current Clear to Send */
154: #define UBSA_MSR_DDCD 0x08 /* DCD has changed state */
155: #define UBSA_MSR_TERI 0x04 /* RI has toggled low to high */
156: #define UBSA_MSR_DDSR 0x02 /* DSR has changed state */
157: #define UBSA_MSR_DCTS 0x01 /* CTS has changed state */
158:
159: struct ubsa_softc {
160: struct device sc_dev; /* base device */
161: usbd_device_handle sc_udev; /* USB device */
162: usbd_interface_handle sc_iface; /* interface */
163:
164: int sc_iface_number; /* interface number */
165:
166: int sc_intr_number; /* interrupt number */
167: usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
168: u_char *sc_intr_buf; /* interrupt buffer */
169: int sc_isize;
170:
171: u_char sc_dtr; /* current DTR state */
172: u_char sc_rts; /* current RTS state */
173:
174: u_char sc_lsr; /* Local status register */
175: u_char sc_msr; /* ubsa status register */
176:
177: struct device *sc_subdev; /* ucom device */
178:
179: u_char sc_dying; /* disconnecting */
180:
181: };
182:
183: void ubsa_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
184:
185: void ubsa_get_status(void *, int, u_char *, u_char *);
186: void ubsa_set(void *, int, int, int);
187: int ubsa_param(void *, int, struct termios *);
188: int ubsa_open(void *, int);
189: void ubsa_close(void *, int);
190:
191: void ubsa_break(struct ubsa_softc *sc, int onoff);
192: int ubsa_request(struct ubsa_softc *, u_int8_t, u_int16_t);
193: void ubsa_dtr(struct ubsa_softc *, int);
194: void ubsa_rts(struct ubsa_softc *, int);
195: void ubsa_baudrate(struct ubsa_softc *, speed_t);
196: void ubsa_parity(struct ubsa_softc *, tcflag_t);
197: void ubsa_databits(struct ubsa_softc *, tcflag_t);
198: void ubsa_stopbits(struct ubsa_softc *, tcflag_t);
199: void ubsa_flow(struct ubsa_softc *, tcflag_t, tcflag_t);
200:
201: struct ucom_methods ubsa_methods = {
202: ubsa_get_status,
203: ubsa_set,
204: ubsa_param,
205: NULL,
206: ubsa_open,
207: ubsa_close,
208: NULL,
209: NULL
210: };
211:
212: const struct usb_devno ubsa_devs[] = {
213: /* AnyDATA ADU-E100H */
214: { USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_E100H },
215: /* BELKIN F5U103 */
216: { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U103 },
217: /* BELKIN F5U120 */
218: { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U120 },
219: /* GoHubs GO-COM232 , Belkin F5U003 */
220: { USB_VENDOR_ETEK, USB_PRODUCT_ETEK_1COM },
221: /* GoHubs GO-COM232 */
222: { USB_VENDOR_GOHUBS, USB_PRODUCT_GOHUBS_GOCOM232 },
223: /* HUAWEI Mobile */
224: { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E618 },
225: /* Novatel Wireless U740 */
226: { USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MERLINU740 },
227: /* Option Vodafone Mobile Connect 3G */
228: { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G },
229: /* Option GlobeTrotter 3G FUSION */
230: { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GFUSION },
231: /* Option GlobeTrotter 3G QUAD */
232: { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD },
233: /* Option GlobeTrotter 3G QUAD PLUS */
234: { USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUADPLUS },
235: /* Peracom */
236: { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1 },
237: };
238: #define ubsa_lookup(v, p) usb_lookup(ubsa_devs, v, p)
239:
240: int ubsa_match(struct device *, void *, void *);
241: void ubsa_attach(struct device *, struct device *, void *);
242: int ubsa_detach(struct device *, int);
243: int ubsa_activate(struct device *, enum devact);
244:
245: struct cfdriver ubsa_cd = {
246: NULL, "ubsa", DV_DULL
247: };
248:
249: const struct cfattach ubsa_ca = {
250: sizeof(struct ubsa_softc),
251: ubsa_match,
252: ubsa_attach,
253: ubsa_detach,
254: ubsa_activate,
255: };
256:
257: int
258: ubsa_match(struct device *parent, void *match, void *aux)
259: {
260: struct usb_attach_arg *uaa = aux;
261:
262: if (uaa->iface != NULL)
263: return (UMATCH_NONE);
264:
265: return (ubsa_lookup(uaa->vendor, uaa->product) != NULL ?
266: UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
267: }
268:
269: void
270: ubsa_attach(struct device *parent, struct device *self, void *aux)
271: {
272: struct ubsa_softc *sc = (struct ubsa_softc *)self;
273: struct usb_attach_arg *uaa = aux;
274: usbd_device_handle dev = uaa->device;
275: usb_config_descriptor_t *cdesc;
276: usb_interface_descriptor_t *id;
277: usb_endpoint_descriptor_t *ed;
278: char *devinfop;
279: const char *devname = sc->sc_dev.dv_xname;
280: usbd_status err;
281: struct ucom_attach_args uca;
282: int i;
283:
284: devinfop = usbd_devinfo_alloc(dev, 0);
285: printf("\n%s: %s\n", devname, devinfop);
286: usbd_devinfo_free(devinfop);
287:
288: sc->sc_udev = dev;
289:
290: /*
291: * initialize rts, dtr variables to something
292: * different from boolean 0, 1
293: */
294: sc->sc_dtr = -1;
295: sc->sc_rts = -1;
296:
297: DPRINTF(("ubsa attach: sc = %p\n", sc));
298:
299: /* initialize endpoints */
300: uca.bulkin = uca.bulkout = -1;
301: sc->sc_intr_number = -1;
302: sc->sc_intr_pipe = NULL;
303:
304: /* Move the device into the configured state. */
305: err = usbd_set_config_index(dev, UBSA_CONFIG_INDEX, 1);
306: if (err) {
307: printf("%s: failed to set configuration: %s\n",
308: devname, usbd_errstr(err));
309: sc->sc_dying = 1;
310: goto error;
311: }
312:
313: /* get the config descriptor */
314: cdesc = usbd_get_config_descriptor(sc->sc_udev);
315:
316: if (cdesc == NULL) {
317: printf("%s: failed to get configuration descriptor\n",
318: devname);
319: sc->sc_dying = 1;
320: goto error;
321: }
322:
323: /* get the first interface */
324: err = usbd_device2interface_handle(dev, UBSA_IFACE_INDEX,
325: &sc->sc_iface);
326: if (err) {
327: printf("%s: failed to get interface: %s\n",
328: devname, usbd_errstr(err));
329: sc->sc_dying = 1;
330: goto error;
331: }
332:
333: /* Find the endpoints */
334:
335: id = usbd_get_interface_descriptor(sc->sc_iface);
336: sc->sc_iface_number = id->bInterfaceNumber;
337:
338: for (i = 0; i < id->bNumEndpoints; i++) {
339: ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
340: if (ed == NULL) {
341: printf("%s: no endpoint descriptor for %d\n",
342: sc->sc_dev.dv_xname, i);
343: sc->sc_dying = 1;
344: goto error;
345: }
346:
347: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
348: UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
349: sc->sc_intr_number = ed->bEndpointAddress;
350: sc->sc_isize = UGETW(ed->wMaxPacketSize);
351: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
352: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
353: uca.bulkin = ed->bEndpointAddress;
354: uca.ibufsize = UGETW(ed->wMaxPacketSize);
355: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
356: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
357: uca.bulkout = ed->bEndpointAddress;
358: uca.obufsize = UGETW(ed->wMaxPacketSize);
359: }
360: }
361:
362: if (sc->sc_intr_number == -1) {
363: printf("%s: Could not find interrupt in\n", devname);
364: sc->sc_dying = 1;
365: goto error;
366: }
367:
368: if (uca.bulkin == -1) {
369: printf("%s: Could not find data bulk in\n", devname);
370: sc->sc_dying = 1;
371: goto error;
372: }
373:
374: if (uca.bulkout == -1) {
375: printf("%s: Could not find data bulk out\n", devname);
376: sc->sc_dying = 1;
377: goto error;
378: }
379:
380: uca.portno = UCOM_UNK_PORTNO;
381: /* bulkin, bulkout set above */
382: uca.ibufsizepad = uca.ibufsize;
383: uca.opkthdrlen = 0;
384: uca.device = dev;
385: uca.iface = sc->sc_iface;
386: uca.methods = &ubsa_methods;
387: uca.arg = sc;
388: uca.info = NULL;
389:
390: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
391: &sc->sc_dev);
392:
393: DPRINTF(("ubsa: in = 0x%x, out = 0x%x, intr = 0x%x\n",
394: uca.bulkin, uca.bulkout, sc->sc_intr_number));
395:
396: sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
397:
398: error:
399: return;
400: }
401:
402: int
403: ubsa_detach(struct device *self, int flags)
404: {
405: struct ubsa_softc *sc = (struct ubsa_softc *)self;
406: int rv = 0;
407:
408:
409: DPRINTF(("ubsa_detach: sc = %p\n", sc));
410:
411: if (sc->sc_intr_pipe != NULL) {
412: usbd_abort_pipe(sc->sc_intr_pipe);
413: usbd_close_pipe(sc->sc_intr_pipe);
414: free(sc->sc_intr_buf, M_USBDEV);
415: sc->sc_intr_pipe = NULL;
416: }
417:
418: sc->sc_dying = 1;
419: if (sc->sc_subdev != NULL) {
420: rv = config_detach(sc->sc_subdev, flags);
421: sc->sc_subdev = NULL;
422: }
423:
424: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
425: &sc->sc_dev);
426:
427: return (rv);
428: }
429:
430: int
431: ubsa_activate(struct device *self, enum devact act)
432: {
433: struct ubsa_softc *sc = (struct ubsa_softc *)self;
434: int rv = 0;
435:
436: switch (act) {
437: case DVACT_ACTIVATE:
438: break;
439:
440: case DVACT_DEACTIVATE:
441: if (sc->sc_subdev != NULL)
442: rv = config_deactivate(sc->sc_subdev);
443: sc->sc_dying = 1;
444: break;
445: }
446: return (rv);
447: }
448:
449: int
450: ubsa_request(struct ubsa_softc *sc, u_int8_t request, u_int16_t value)
451: {
452: usb_device_request_t req;
453: usbd_status err;
454:
455: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
456: req.bRequest = request;
457: USETW(req.wValue, value);
458: USETW(req.wIndex, sc->sc_iface_number);
459: USETW(req.wLength, 0);
460:
461: err = usbd_do_request(sc->sc_udev, &req, 0);
462: if (err && err != USBD_STALLED)
463: printf("%s: ubsa_request: %s\n",
464: sc->sc_dev.dv_xname, usbd_errstr(err));
465: return (err);
466: }
467:
468: void
469: ubsa_dtr(struct ubsa_softc *sc, int onoff)
470: {
471:
472: DPRINTF(("ubsa_dtr: onoff = %d\n", onoff));
473:
474: if (sc->sc_dtr == onoff)
475: return;
476: sc->sc_dtr = onoff;
477:
478: ubsa_request(sc, UBSA_SET_DTR, onoff ? 1 : 0);
479: }
480:
481: void
482: ubsa_rts(struct ubsa_softc *sc, int onoff)
483: {
484:
485: DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
486:
487: if (sc->sc_rts == onoff)
488: return;
489: sc->sc_rts = onoff;
490:
491: ubsa_request(sc, UBSA_SET_RTS, onoff ? 1 : 0);
492: }
493:
494: void
495: ubsa_break(struct ubsa_softc *sc, int onoff)
496: {
497:
498: DPRINTF(("ubsa_rts: onoff = %d\n", onoff));
499:
500: ubsa_request(sc, UBSA_SET_BREAK, onoff ? 1 : 0);
501: }
502:
503: void
504: ubsa_set(void *addr, int portno, int reg, int onoff)
505: {
506: struct ubsa_softc *sc;
507:
508: sc = addr;
509: switch (reg) {
510: case UCOM_SET_DTR:
511: ubsa_dtr(sc, onoff);
512: break;
513: case UCOM_SET_RTS:
514: ubsa_rts(sc, onoff);
515: break;
516: case UCOM_SET_BREAK:
517: ubsa_break(sc, onoff);
518: break;
519: default:
520: break;
521: }
522: }
523:
524: void
525: ubsa_baudrate(struct ubsa_softc *sc, speed_t speed)
526: {
527: u_int16_t value = 0;
528:
529: DPRINTF(("ubsa_baudrate: speed = %d\n", speed));
530:
531: switch(speed) {
532: case B0:
533: break;
534: case B300:
535: case B600:
536: case B1200:
537: case B2400:
538: case B4800:
539: case B9600:
540: case B19200:
541: case B38400:
542: case B57600:
543: case B115200:
544: case B230400:
545: value = B230400 / speed;
546: break;
547: default:
548: DPRINTF(("%s: ubsa_param: unsupported baudrate, "
549: "forcing default of 9600\n",
550: sc->sc_dev.dv_xname));
551: value = B230400 / B9600;
552: break;
553: };
554:
555: if (speed == B0) {
556: ubsa_flow(sc, 0, 0);
557: ubsa_dtr(sc, 0);
558: ubsa_rts(sc, 0);
559: } else
560: ubsa_request(sc, UBSA_SET_BAUDRATE, value);
561: }
562:
563: void
564: ubsa_parity(struct ubsa_softc *sc, tcflag_t cflag)
565: {
566: int value;
567:
568: DPRINTF(("ubsa_parity: cflag = 0x%x\n", cflag));
569:
570: if (cflag & PARENB)
571: value = (cflag & PARODD) ? UBSA_PARITY_ODD : UBSA_PARITY_EVEN;
572: else
573: value = UBSA_PARITY_NONE;
574:
575: ubsa_request(sc, UBSA_SET_PARITY, value);
576: }
577:
578: void
579: ubsa_databits(struct ubsa_softc *sc, tcflag_t cflag)
580: {
581: int value;
582:
583: DPRINTF(("ubsa_databits: cflag = 0x%x\n", cflag));
584:
585: switch (cflag & CSIZE) {
586: case CS5: value = 0; break;
587: case CS6: value = 1; break;
588: case CS7: value = 2; break;
589: case CS8: value = 3; break;
590: default:
591: DPRINTF(("%s: ubsa_param: unsupported databits requested, "
592: "forcing default of 8\n",
593: sc->sc_dev.dv_xname));
594: value = 3;
595: }
596:
597: ubsa_request(sc, UBSA_SET_DATA_BITS, value);
598: }
599:
600: void
601: ubsa_stopbits(struct ubsa_softc *sc, tcflag_t cflag)
602: {
603: int value;
604:
605: DPRINTF(("ubsa_stopbits: cflag = 0x%x\n", cflag));
606:
607: value = (cflag & CSTOPB) ? 1 : 0;
608:
609: ubsa_request(sc, UBSA_SET_STOP_BITS, value);
610: }
611:
612: void
613: ubsa_flow(struct ubsa_softc *sc, tcflag_t cflag, tcflag_t iflag)
614: {
615: int value;
616:
617: DPRINTF(("ubsa_flow: cflag = 0x%x, iflag = 0x%x\n", cflag, iflag));
618:
619: value = 0;
620: if (cflag & CRTSCTS)
621: value |= UBSA_FLOW_OCTS | UBSA_FLOW_IRTS;
622: if (iflag & (IXON|IXOFF))
623: value |= UBSA_FLOW_OXON | UBSA_FLOW_IXON;
624:
625: ubsa_request(sc, UBSA_SET_FLOW_CTRL, value);
626: }
627:
628: int
629: ubsa_param(void *addr, int portno, struct termios *ti)
630: {
631: struct ubsa_softc *sc = addr;
632:
633: DPRINTF(("ubsa_param: sc = %p\n", sc));
634:
635: ubsa_baudrate(sc, ti->c_ospeed);
636: ubsa_parity(sc, ti->c_cflag);
637: ubsa_databits(sc, ti->c_cflag);
638: ubsa_stopbits(sc, ti->c_cflag);
639: ubsa_flow(sc, ti->c_cflag, ti->c_iflag);
640:
641: return (0);
642: }
643:
644: int
645: ubsa_open(void *addr, int portno)
646: {
647: struct ubsa_softc *sc = addr;
648: int err;
649:
650: if (sc->sc_dying)
651: return (ENXIO);
652:
653: DPRINTF(("ubsa_open: sc = %p\n", sc));
654:
655: if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
656: sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
657: err = usbd_open_pipe_intr(sc->sc_iface,
658: sc->sc_intr_number,
659: USBD_SHORT_XFER_OK,
660: &sc->sc_intr_pipe,
661: sc,
662: sc->sc_intr_buf,
663: sc->sc_isize,
664: ubsa_intr,
665: UBSA_INTR_INTERVAL);
666: if (err) {
667: printf("%s: cannot open interrupt pipe (addr %d)\n",
668: sc->sc_dev.dv_xname,
669: sc->sc_intr_number);
670: return (EIO);
671: }
672: }
673:
674: return (0);
675: }
676:
677: void
678: ubsa_close(void *addr, int portno)
679: {
680: struct ubsa_softc *sc = addr;
681: int err;
682:
683: if (sc->sc_dying)
684: return;
685:
686: DPRINTF(("ubsa_close: close\n"));
687:
688: if (sc->sc_intr_pipe != NULL) {
689: err = usbd_abort_pipe(sc->sc_intr_pipe);
690: if (err)
691: printf("%s: abort interrupt pipe failed: %s\n",
692: sc->sc_dev.dv_xname,
693: usbd_errstr(err));
694: err = usbd_close_pipe(sc->sc_intr_pipe);
695: if (err)
696: printf("%s: close interrupt pipe failed: %s\n",
697: sc->sc_dev.dv_xname,
698: usbd_errstr(err));
699: free(sc->sc_intr_buf, M_USBDEV);
700: sc->sc_intr_pipe = NULL;
701: }
702: }
703:
704: void
705: ubsa_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
706: {
707: struct ubsa_softc *sc = priv;
708: u_char *buf;
709:
710: buf = sc->sc_intr_buf;
711: if (sc->sc_dying)
712: return;
713:
714: if (status != USBD_NORMAL_COMPLETION) {
715: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
716: return;
717:
718: DPRINTF(("%s: ubsa_intr: abnormal status: %s\n",
719: sc->sc_dev.dv_xname, usbd_errstr(status)));
720: usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
721: return;
722: }
723:
724: /* incidentally, Belkin adapter status bits match UART 16550 bits */
725: sc->sc_lsr = buf[2];
726: sc->sc_msr = buf[3];
727:
728: DPRINTF(("%s: ubsa lsr = 0x%02x, msr = 0x%02x\n",
729: sc->sc_dev.dv_xname, sc->sc_lsr, sc->sc_msr));
730:
731: ucom_status_change((struct ucom_softc *)sc->sc_subdev);
732: }
733:
734: void
735: ubsa_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
736: {
737: struct ubsa_softc *sc = addr;
738:
739: DPRINTF(("ubsa_get_status\n"));
740:
741: if (lsr != NULL)
742: *lsr = sc->sc_lsr;
743: if (msr != NULL)
744: *msr = sc->sc_msr;
745: }
CVSweb