Annotation of sys/dev/usb/ubsa.c, Revision 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