[BACK]Return to uipaq.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/uipaq.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: uipaq.c,v 1.12 2007/06/14 10:11:16 mbalmer Exp $      */
                      2:
                      3: /*
                      4:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Lennart Augustsson (lennart@augustsson.net) at
                      9:  * Carlstedt Research & Technology.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *        This product includes software developed by the NetBSD
                     22:  *        Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * iPAQ driver
                     42:  *
                     43:  * 19 July 2003:       Incorporated changes suggested by Sam Lawrance from
                     44:  *                     the uppc module
                     45:  *
                     46:  *
                     47:  * Contact isis@cs.umd.edu if you have any questions/comments about this driver
                     48:  */
                     49:
                     50: #include <sys/param.h>
                     51: #include <sys/systm.h>
                     52: #include <sys/kernel.h>
                     53: #include <sys/device.h>
                     54: #include <sys/conf.h>
                     55: #include <sys/tty.h>
                     56:
                     57: #include <dev/usb/usb.h>
                     58: #include <dev/usb/usbhid.h>
                     59:
                     60: #include <dev/usb/usbcdc.h>    /*UCDC_* stuff */
                     61:
                     62: #include <dev/usb/usbdi.h>
                     63: #include <dev/usb/usbdi_util.h>
                     64: #include <dev/usb/usbdevs.h>
                     65:
                     66: #include <dev/usb/ucomvar.h>
                     67:
                     68: #ifdef UIPAQ_DEBUG
                     69: #define DPRINTF(x)     if (uipaqdebug) printf x
                     70: #define DPRINTFN(n,x)  if (uipaqdebug>(n)) printf x
                     71: int uipaqdebug = 0;
                     72: #else
                     73: #define DPRINTF(x)
                     74: #define DPRINTFN(n,x)
                     75: #endif
                     76:
                     77: #define UIPAQ_CONFIG_NO                1
                     78: #define UIPAQ_IFACE_INDEX      0
                     79:
                     80: #define UIPAQIBUFSIZE 1024
                     81: #define UIPAQOBUFSIZE 1024
                     82:
                     83: struct uipaq_softc {
                     84:        struct device            sc_dev;        /* base device */
                     85:        usbd_device_handle       sc_udev;       /* device */
                     86:        usbd_interface_handle    sc_iface;      /* interface */
                     87:
                     88:        struct device           *sc_subdev;     /* ucom uses that */
                     89:        u_int16_t                sc_lcr;        /* state for DTR/RTS */
                     90:
                     91:        u_int16_t                sc_flags;
                     92:
                     93:        u_char                   sc_dying;
                     94: };
                     95:
                     96: /* Callback routines */
                     97: void   uipaq_set(void *, int, int, int);
                     98:
                     99:
                    100: /* Support routines. */
                    101: /* based on uppc module by Sam Lawrance */
                    102: void   uipaq_dtr(struct uipaq_softc *sc, int onoff);
                    103: void   uipaq_rts(struct uipaq_softc *sc, int onoff);
                    104: void   uipaq_break(struct uipaq_softc* sc, int onoff);
                    105:
                    106:
                    107: struct ucom_methods uipaq_methods = {
                    108:        NULL,
                    109:        uipaq_set,
                    110:        NULL,
                    111:        NULL,
                    112:        NULL,   /*open*/
                    113:        NULL,   /*close*/
                    114:        NULL,
                    115:        NULL
                    116: };
                    117:
                    118: struct uipaq_type {
                    119:        struct usb_devno        uv_dev;
                    120:        u_int16_t               uv_flags;
                    121: };
                    122:
                    123: static const struct uipaq_type uipaq_devs[] = {
                    124:        {{ USB_VENDOR_HP, USB_PRODUCT_HP_2215 }, 0 },
                    125:        {{ USB_VENDOR_HP, USB_PRODUCT_HP_568J }, 0},
                    126:        {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQPOCKETPC} , 0},
                    127:        {{ USB_VENDOR_CASIO, USB_PRODUCT_CASIO_BE300} , 0},
                    128:        {{ USB_VENDOR_ASUS, USB_PRODUCT_ASUS_MYPAL_A730} , 0}
                    129: };
                    130:
                    131: #define uipaq_lookup(v, p) ((struct uipaq_type *)usb_lookup(uipaq_devs, v, p))
                    132:
                    133: int uipaq_match(struct device *, void *, void *);
                    134: void uipaq_attach(struct device *, struct device *, void *);
                    135: int uipaq_detach(struct device *, int);
                    136: int uipaq_activate(struct device *, enum devact);
                    137:
                    138: struct cfdriver uipaq_cd = {
                    139:        NULL, "uipaq", DV_DULL
                    140: };
                    141:
                    142: const struct cfattach uipaq_ca = {
                    143:        sizeof(struct uipaq_softc),
                    144:        uipaq_match,
                    145:        uipaq_attach,
                    146:        uipaq_detach,
                    147:        uipaq_activate,
                    148: };
                    149:
                    150: int
                    151: uipaq_match(struct device *parent, void *match, void *aux)
                    152: {
                    153:        struct usb_attach_arg *uaa = aux;
                    154:
                    155:        if (uaa->iface != NULL)
                    156:                return (UMATCH_NONE);
                    157:
                    158:        DPRINTFN(20,("uipaq: vendor=0x%x, product=0x%x\n",
                    159:            uaa->vendor, uaa->product));
                    160:
                    161:        return (uipaq_lookup(uaa->vendor, uaa->product) != NULL ?
                    162:            UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
                    163: }
                    164:
                    165: void
                    166: uipaq_attach(struct device *parent, struct device *self, void *aux)
                    167: {
                    168:        struct uipaq_softc *sc = (struct uipaq_softc *)self;
                    169:        struct usb_attach_arg *uaa = aux;
                    170:        usbd_device_handle dev = uaa->device;
                    171:        usbd_interface_handle iface;
                    172:        usb_interface_descriptor_t *id;
                    173:        usb_endpoint_descriptor_t *ed;
                    174:        char *devinfop;
                    175:        char *devname = sc->sc_dev.dv_xname;
                    176:        int i;
                    177:        usbd_status err;
                    178:        struct ucom_attach_args uca;
                    179:
                    180:        DPRINTFN(10,("\nuipaq_attach: sc=%p\n", sc));
                    181:
                    182:        /* Move the device into the configured state. */
                    183:        err = usbd_set_config_no(dev, UIPAQ_CONFIG_NO, 1);
                    184:        if (err) {
                    185:                printf("\n%s: failed to set configuration, err=%s\n",
                    186:                    devname, usbd_errstr(err));
                    187:                goto bad;
                    188:        }
                    189:
                    190:        err = usbd_device2interface_handle(dev, UIPAQ_IFACE_INDEX, &iface);
                    191:        if (err) {
                    192:                printf("\n%s: failed to get interface, err=%s\n",
                    193:                    devname, usbd_errstr(err));
                    194:                goto bad;
                    195:        }
                    196:
                    197:        devinfop = usbd_devinfo_alloc(dev, 0);
                    198:        printf("\n%s: %s\n", devname, devinfop);
                    199:        usbd_devinfo_free(devinfop);
                    200:
                    201:        sc->sc_flags = uipaq_lookup(uaa->vendor, uaa->product)->uv_flags;
                    202:
                    203:        id = usbd_get_interface_descriptor(iface);
                    204:
                    205:        sc->sc_udev = dev;
                    206:        sc->sc_iface = iface;
                    207:
                    208:        uca.ibufsize = UIPAQIBUFSIZE;
                    209:        uca.obufsize = UIPAQOBUFSIZE;
                    210:        uca.ibufsizepad = UIPAQIBUFSIZE;
                    211:        uca.opkthdrlen = 0;
                    212:        uca.device = dev;
                    213:        uca.iface = iface;
                    214:        uca.methods = &uipaq_methods;
                    215:        uca.arg = sc;
                    216:        uca.portno = UCOM_UNK_PORTNO;
                    217:        uca.info = "Generic";
                    218:
                    219: /*     err = uipaq_init(sc);
                    220:        if (err) {
                    221:                printf("%s: init failed, %s\n", sc->sc_dev.dv_xname,
                    222:                    usbd_errstr(err));
                    223:                goto bad;
                    224:        }*/
                    225:
                    226:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                    227:            &sc->sc_dev);
                    228:
                    229:        uca.bulkin = uca.bulkout = -1;
                    230:        for (i=0; i<id->bNumEndpoints; i++) {
                    231:                ed = usbd_interface2endpoint_descriptor(iface, i);
                    232:                if (ed == NULL) {
                    233:                        printf("%s: no endpoint descriptor for %d\n",
                    234:                                        devname,i);
                    235:                        goto bad;
                    236:                }
                    237:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                    238:                    (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
                    239:                        uca.bulkin = ed->bEndpointAddress;
                    240:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
                    241:                    (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
                    242:                        uca.bulkout = ed->bEndpointAddress;
                    243:                }
                    244:        }
                    245:        if (uca.bulkin != -1 && uca.bulkout != -1)
                    246:                sc->sc_subdev = config_found_sm(self, &uca,
                    247:                    ucomprint, ucomsubmatch);
                    248:        else
                    249:                printf("%s: no proper endpoints found (%d,%d) \n",
                    250:                    devname, uca.bulkin, uca.bulkout);
                    251:
                    252:        return;
                    253:
                    254: bad:
                    255:        DPRINTF(("uipaq_attach: ATTACH ERROR\n"));
                    256:        sc->sc_dying = 1;
                    257: }
                    258:
                    259:
                    260: void
                    261: uipaq_dtr(struct uipaq_softc* sc, int onoff)
                    262: {
                    263:        usb_device_request_t req;
                    264:        usbd_status err;
                    265:        int retries = 3;
                    266:
                    267:        DPRINTF(("%s: uipaq_dtr: onoff=%x\n", sc->sc_dev.dv_xname, onoff));
                    268:
                    269:        /* Avoid sending unnecessary requests */
                    270:        if (onoff && (sc->sc_lcr & UCDC_LINE_DTR))
                    271:                return;
                    272:        if (!onoff && !(sc->sc_lcr & UCDC_LINE_DTR))
                    273:                return;
                    274:
                    275:        /* Other parameters depend on reg */
                    276:        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
                    277:        req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
                    278:        sc->sc_lcr = onoff ? sc->sc_lcr | UCDC_LINE_DTR : sc->sc_lcr & ~UCDC_LINE_DTR;
                    279:        USETW(req.wValue, sc->sc_lcr);
                    280:        USETW(req.wIndex, 0x0);
                    281:        USETW(req.wLength, 0);
                    282:
                    283:        /* Fire off the request a few times if necessary */
                    284:        while (retries) {
                    285:                err = usbd_do_request(sc->sc_udev, &req, NULL);
                    286:                if (!err)
                    287:                        break;
                    288:                retries--;
                    289:        }
                    290: }
                    291:
                    292:
                    293: void
                    294: uipaq_rts(struct uipaq_softc* sc, int onoff)
                    295: {
                    296:        usb_device_request_t req;
                    297:        usbd_status err;
                    298:        int retries = 3;
                    299:
                    300:        DPRINTF(("%s: uipaq_rts: onoff=%x\n", sc->sc_dev.dv_xname, onoff));
                    301:
                    302:        /* Avoid sending unnecessary requests */
                    303:        if (onoff && (sc->sc_lcr & UCDC_LINE_RTS)) return;
                    304:        if (!onoff && !(sc->sc_lcr & UCDC_LINE_RTS)) return;
                    305:
                    306:        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
                    307:        req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
                    308:        sc->sc_lcr = onoff ? sc->sc_lcr | UCDC_LINE_RTS : sc->sc_lcr & ~UCDC_LINE_RTS;
                    309:        USETW(req.wValue, sc->sc_lcr);
                    310:        USETW(req.wIndex, 0x0);
                    311:        USETW(req.wLength, 0);
                    312:
                    313:        while (retries) {
                    314:                err = usbd_do_request(sc->sc_udev, &req, NULL);
                    315:                if (!err)
                    316:                        break;
                    317:                retries--;
                    318:        }
                    319: }
                    320:
                    321:
                    322: void
                    323: uipaq_break(struct uipaq_softc* sc, int onoff)
                    324: {
                    325:        usb_device_request_t req;
                    326:        usbd_status err;
                    327:        int retries = 3;
                    328:
                    329:        DPRINTF(("%s: uipaq_break: onoff=%x\n", sc->sc_dev.dv_xname, onoff));
                    330:
                    331:        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
                    332:        req.bRequest = UCDC_SEND_BREAK;
                    333:
                    334:        USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF);
                    335:        USETW(req.wIndex, 0x0);
                    336:        USETW(req.wLength, 0);
                    337:
                    338:        while (retries) {
                    339:                err = usbd_do_request(sc->sc_udev, &req, NULL);
                    340:                if (!err)
                    341:                        break;
                    342:                retries--;
                    343:        }
                    344: }
                    345:
                    346:
                    347: void
                    348: uipaq_set(void *addr, int portno, int reg, int onoff)
                    349: {
                    350:        struct uipaq_softc* sc = addr;
                    351:
                    352:        switch (reg) {
                    353:        case UCOM_SET_DTR:
                    354:                uipaq_dtr(addr, onoff);
                    355:                break;
                    356:        case UCOM_SET_RTS:
                    357:                uipaq_rts(addr, onoff);
                    358:                break;
                    359:        case UCOM_SET_BREAK:
                    360:                uipaq_break(addr, onoff);
                    361:                break;
                    362:        default:
                    363:                printf("%s: unhandled set request: reg=%x onoff=%x\n",
                    364:                    sc->sc_dev.dv_xname, reg, onoff);
                    365:                return;
                    366:        }
                    367: }
                    368:
                    369:
                    370: int
                    371: uipaq_activate(struct device *self, enum devact act)
                    372: {
                    373:        struct uipaq_softc *sc = (struct uipaq_softc *)self;
                    374:        int rv = 0;
                    375:
                    376:        switch (act) {
                    377:        case DVACT_ACTIVATE:
                    378:                break;
                    379:
                    380:        case DVACT_DEACTIVATE:
                    381:                if (sc->sc_subdev != NULL)
                    382:                        rv = config_deactivate(sc->sc_subdev);
                    383:                sc->sc_dying = 1;
                    384:                break;
                    385:        }
                    386:        return (rv);
                    387: }
                    388:
                    389: int
                    390: uipaq_detach(struct device *self, int flags)
                    391: {
                    392:        struct uipaq_softc *sc = (struct uipaq_softc *)self;
                    393:        int rv = 0;
                    394:
                    395:        DPRINTF(("uipaq_detach: sc=%p flags=%d\n", sc, flags));
                    396:        sc->sc_dying = 1;
                    397:        if (sc->sc_subdev != NULL) {
                    398:                rv |= config_detach(sc->sc_subdev, flags);
                    399:                sc->sc_subdev = NULL;
                    400:        }
                    401:
                    402:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
                    403:            &sc->sc_dev);
                    404:
                    405:        return (rv);
                    406: }
                    407:

CVSweb