[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     ! 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