Annotation of sys/dev/usb/uark.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: uark.c,v 1.10 2007/06/14 10:11:15 mbalmer Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 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 UARK_DEBUG
! 35: #define DPRINTFN(n, x) do { if (uarkdebug > (n)) printf x; } while (0)
! 36: int uarkebug = 0;
! 37: #else
! 38: #define DPRINTFN(n, x)
! 39: #endif
! 40: #define DPRINTF(x) DPRINTFN(0, x)
! 41:
! 42: #define UARKBUFSZ 256
! 43: #define UARK_CONFIG_NO 0
! 44: #define UARK_IFACE_NO 0
! 45:
! 46: #define UARK_SET_DATA_BITS(x) (x - 5)
! 47:
! 48: #define UARK_PARITY_NONE 0x00
! 49: #define UARK_PARITY_ODD 0x08
! 50: #define UARK_PARITY_EVEN 0x18
! 51:
! 52: #define UARK_STOP_BITS_1 0x00
! 53: #define UARK_STOP_BITS_2 0x04
! 54:
! 55: #define UARK_BAUD_REF 3000000
! 56:
! 57: #define UARK_WRITE 0x40
! 58: #define UARK_READ 0xc0
! 59:
! 60: #define UARK_REQUEST 0xfe
! 61:
! 62: struct uark_softc {
! 63: struct device sc_dev;
! 64: usbd_device_handle sc_udev;
! 65: usbd_interface_handle sc_iface;
! 66: struct device *sc_subdev;
! 67:
! 68: u_char sc_msr;
! 69: u_char sc_lsr;
! 70:
! 71: u_char sc_dying;
! 72: };
! 73:
! 74: void uark_get_status(void *, int portno, u_char *lsr, u_char *msr);
! 75: void uark_set(void *, int, int, int);
! 76: int uark_param(void *, int, struct termios *);
! 77: int uark_open(void *sc, int);
! 78: void uark_break(void *, int, int);
! 79: int uark_cmd(struct uark_softc *, uint16_t, uint16_t);
! 80:
! 81: struct ucom_methods uark_methods = {
! 82: uark_get_status,
! 83: uark_set,
! 84: uark_param,
! 85: NULL,
! 86: NULL,
! 87: NULL,
! 88: NULL,
! 89: NULL,
! 90: };
! 91:
! 92: static const struct usb_devno uark_devs[] = {
! 93: { USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116 }
! 94: };
! 95:
! 96: int uark_match(struct device *, void *, void *);
! 97: void uark_attach(struct device *, struct device *, void *);
! 98: int uark_detach(struct device *, int);
! 99: int uark_activate(struct device *, enum devact);
! 100:
! 101: struct cfdriver uark_cd = {
! 102: NULL, "uark", DV_DULL
! 103: };
! 104:
! 105: const struct cfattach uark_ca = {
! 106: sizeof(struct uark_softc),
! 107: uark_match,
! 108: uark_attach,
! 109: uark_detach,
! 110: uark_activate,
! 111: };
! 112:
! 113: int
! 114: uark_match(struct device *parent, void *match, void *aux)
! 115: {
! 116: struct usb_attach_arg *uaa = aux;
! 117:
! 118: if (uaa->iface != NULL)
! 119: return UMATCH_NONE;
! 120:
! 121: return (usb_lookup(uark_devs, uaa->vendor, uaa->product) != NULL) ?
! 122: UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
! 123: }
! 124:
! 125: void
! 126: uark_attach(struct device *parent, struct device *self, void *aux)
! 127: {
! 128: struct uark_softc *sc = (struct uark_softc *)self;
! 129: struct usb_attach_arg *uaa = aux;
! 130: struct ucom_attach_args uca;
! 131: usb_interface_descriptor_t *id;
! 132: usb_endpoint_descriptor_t *ed;
! 133: usbd_status error;
! 134: char *devinfop;
! 135: int i;
! 136:
! 137: bzero(&uca, sizeof(uca));
! 138: sc->sc_udev = uaa->device;
! 139: devinfop = usbd_devinfo_alloc(uaa->device, 0);
! 140: printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
! 141: usbd_devinfo_free(devinfop);
! 142:
! 143: if (usbd_set_config_index(sc->sc_udev, UARK_CONFIG_NO, 1) != 0) {
! 144: printf("%s: could not set configuration no\n",
! 145: sc->sc_dev.dv_xname);
! 146: sc->sc_dying = 1;
! 147: return;
! 148: }
! 149:
! 150: /* get the first interface handle */
! 151: error = usbd_device2interface_handle(sc->sc_udev, UARK_IFACE_NO,
! 152: &sc->sc_iface);
! 153: if (error != 0) {
! 154: printf("%s: could not get interface handle\n",
! 155: sc->sc_dev.dv_xname);
! 156: sc->sc_dying = 1;
! 157: return;
! 158: }
! 159:
! 160: id = usbd_get_interface_descriptor(sc->sc_iface);
! 161:
! 162: uca.bulkin = uca.bulkout = -1;
! 163: for (i = 0; i < id->bNumEndpoints; i++) {
! 164: ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
! 165: if (ed == NULL) {
! 166: printf("%s: no endpoint descriptor found for %d\n",
! 167: sc->sc_dev.dv_xname, i);
! 168: sc->sc_dying = 1;
! 169: return;
! 170: }
! 171:
! 172: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
! 173: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
! 174: uca.bulkin = ed->bEndpointAddress;
! 175: else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
! 176: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
! 177: uca.bulkout = ed->bEndpointAddress;
! 178: }
! 179:
! 180: if (uca.bulkin == -1 || uca.bulkout == -1) {
! 181: printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
! 182: sc->sc_dying = 1;
! 183: return;
! 184: }
! 185:
! 186: uca.ibufsize = UARKBUFSZ;
! 187: uca.obufsize = UARKBUFSZ;
! 188: uca.ibufsizepad = UARKBUFSZ;
! 189: uca.opkthdrlen = 0;
! 190: uca.device = sc->sc_udev;
! 191: uca.iface = sc->sc_iface;
! 192: uca.methods = &uark_methods;
! 193: uca.arg = sc;
! 194: uca.info = NULL;
! 195:
! 196: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
! 197: &sc->sc_dev);
! 198:
! 199: sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
! 200: }
! 201:
! 202: int
! 203: uark_detach(struct device *self, int flags)
! 204: {
! 205: struct uark_softc *sc = (struct uark_softc *)self;
! 206: int rv = 0;
! 207:
! 208: sc->sc_dying = 1;
! 209: if (sc->sc_subdev != NULL) {
! 210: rv = config_detach(sc->sc_subdev, flags);
! 211: sc->sc_subdev = NULL;
! 212: }
! 213:
! 214: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
! 215: &sc->sc_dev);
! 216:
! 217: return (rv);
! 218: }
! 219:
! 220: int
! 221: uark_activate(struct device *self, enum devact act)
! 222: {
! 223: struct uark_softc *sc = (struct uark_softc *)self;
! 224: int rv = 0;
! 225:
! 226: switch (act) {
! 227: case DVACT_ACTIVATE:
! 228: break;
! 229:
! 230: case DVACT_DEACTIVATE:
! 231: if (sc->sc_subdev != NULL)
! 232: rv = config_deactivate(sc->sc_subdev);
! 233: sc->sc_dying = 1;
! 234: break;
! 235: }
! 236: return (rv);
! 237: }
! 238:
! 239: void
! 240: uark_set(void *vsc, int portno, int reg, int onoff)
! 241: {
! 242: struct uark_softc *sc = vsc;
! 243:
! 244: switch (reg) {
! 245: case UCOM_SET_BREAK:
! 246: uark_break(sc, portno, onoff);
! 247: return;
! 248: case UCOM_SET_DTR:
! 249: case UCOM_SET_RTS:
! 250: default:
! 251: return;
! 252: }
! 253: }
! 254:
! 255: int
! 256: uark_param(void *vsc, int portno, struct termios *t)
! 257: {
! 258: struct uark_softc *sc = (struct uark_softc *)vsc;
! 259: int data;
! 260:
! 261: switch (t->c_ospeed) {
! 262: case 300:
! 263: case 600:
! 264: case 1200:
! 265: case 1800:
! 266: case 2400:
! 267: case 4800:
! 268: case 9600:
! 269: case 19200:
! 270: case 38400:
! 271: case 57600:
! 272: case 115200:
! 273: uark_cmd(sc, 3, 0x83);
! 274: uark_cmd(sc, 0, (UARK_BAUD_REF / t->c_ospeed) & 0xFF);
! 275: uark_cmd(sc, 1, (UARK_BAUD_REF / t->c_ospeed) >> 8);
! 276: uark_cmd(sc, 3, 0x03);
! 277: break;
! 278: default:
! 279: return (EINVAL);
! 280: }
! 281:
! 282: if (ISSET(t->c_cflag, CSTOPB))
! 283: data = UARK_STOP_BITS_2;
! 284: else
! 285: data = UARK_STOP_BITS_1;
! 286:
! 287: if (ISSET(t->c_cflag, PARENB)) {
! 288: if (ISSET(t->c_cflag, PARODD))
! 289: data |= UARK_PARITY_ODD;
! 290: else
! 291: data |= UARK_PARITY_EVEN;
! 292: } else
! 293: data |= UARK_PARITY_NONE;
! 294:
! 295: switch (ISSET(t->c_cflag, CSIZE)) {
! 296: case CS5:
! 297: data |= UARK_SET_DATA_BITS(5);
! 298: break;
! 299: case CS6:
! 300: data |= UARK_SET_DATA_BITS(6);
! 301: break;
! 302: case CS7:
! 303: data |= UARK_SET_DATA_BITS(7);
! 304: break;
! 305: case CS8:
! 306: data |= UARK_SET_DATA_BITS(8);
! 307: break;
! 308: }
! 309:
! 310: uark_cmd(sc, 3, 0x00);
! 311: uark_cmd(sc, 3, data);
! 312:
! 313: #if 0
! 314: /* XXX flow control */
! 315: if (ISSET(t->c_cflag, CRTSCTS))
! 316: /* rts/cts flow ctl */
! 317: } else if (ISSET(t->c_iflag, IXON|IXOFF)) {
! 318: /* xon/xoff flow ctl */
! 319: } else {
! 320: /* disable flow ctl */
! 321: }
! 322: #endif
! 323:
! 324: return (0);
! 325: }
! 326:
! 327: void
! 328: uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr)
! 329: {
! 330: struct uark_softc *sc = vsc;
! 331:
! 332: if (msr != NULL)
! 333: *msr = sc->sc_msr;
! 334: if (lsr != NULL)
! 335: *lsr = sc->sc_lsr;
! 336: }
! 337:
! 338: void
! 339: uark_break(void *vsc, int portno, int onoff)
! 340: {
! 341: #ifdef UARK_DEBUG
! 342: struct uark_softc *sc = vsc;
! 343:
! 344: printf("%s: break %s!\n", sc->sc_dev.dv_xname,
! 345: onoff ? "on" : "off");
! 346:
! 347: if (onoff)
! 348: /* break on */
! 349: uark_cmd(sc, 4, 0x01);
! 350: else
! 351: uark_cmd(sc, 4, 0x00);
! 352: #endif
! 353: }
! 354:
! 355: int
! 356: uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value)
! 357: {
! 358: usb_device_request_t req;
! 359: usbd_status err;
! 360:
! 361: req.bmRequestType = UARK_WRITE;
! 362: req.bRequest = UARK_REQUEST;
! 363: USETW(req.wValue, value);
! 364: USETW(req.wIndex, index);
! 365: USETW(req.wLength, 0);
! 366: err = usbd_do_request(sc->sc_udev, &req, NULL);
! 367:
! 368: if (err)
! 369: return (EIO);
! 370:
! 371: return (0);
! 372: }
CVSweb