root/dev/usb/uipaq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uipaq_match
  2. uipaq_attach
  3. uipaq_dtr
  4. uipaq_rts
  5. uipaq_break
  6. uipaq_set
  7. uipaq_activate
  8. uipaq_detach

    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 

/* [<][>][^][v][top][bottom][index][help] */