root/dev/usb/uvisor.c

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

DEFINITIONS

This source file includes following definitions.
  1. uvisor_match
  2. uvisor_attach
  3. uvisor_activate
  4. uvisor_detach
  5. uvisor_init
  6. uvisor_close

    1 /*      $OpenBSD: uvisor.c,v 1.35 2007/06/14 10:11:16 mbalmer Exp $     */
    2 /*      $NetBSD: uvisor.c,v 1.21 2003/08/03 21:59:26 nathanw Exp $      */
    3 
    4 /*
    5  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (lennart@augustsson.net) at
   10  * Carlstedt Research & Technology.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *        This product includes software developed by the NetBSD
   23  *        Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * Handspring Visor (Palmpilot compatible PDA) driver
   43  */
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/kernel.h>
   48 #include <sys/device.h>
   49 #include <sys/conf.h>
   50 #include <sys/tty.h>
   51 
   52 #include <dev/usb/usb.h>
   53 #include <dev/usb/usbhid.h>
   54 
   55 #include <dev/usb/usbdi.h>
   56 #include <dev/usb/usbdi_util.h>
   57 #include <dev/usb/usbdevs.h>
   58 
   59 #include <dev/usb/ucomvar.h>
   60 
   61 #ifdef UVISOR_DEBUG
   62 #define DPRINTF(x)      if (uvisordebug) printf x
   63 #define DPRINTFN(n,x)   if (uvisordebug>(n)) printf x
   64 int uvisordebug = 0;
   65 #else
   66 #define DPRINTF(x)
   67 #define DPRINTFN(n,x)
   68 #endif
   69 
   70 #define UVISOR_CONFIG_INDEX     0
   71 #define UVISOR_IFACE_INDEX      0
   72 
   73 /* From the Linux driver */
   74 /*
   75  * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
   76  * are available to be transfered to the host for the specified endpoint.
   77  * Currently this is not used, and always returns 0x0001
   78  */
   79 #define UVISOR_REQUEST_BYTES_AVAILABLE          0x01
   80 
   81 /*
   82  * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
   83  * is now closing the pipe. An empty packet is sent in response.
   84  */
   85 #define UVISOR_CLOSE_NOTIFICATION               0x02
   86 
   87 /*
   88  * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
   89  * get the endpoints used by the connection.
   90  */
   91 #define UVISOR_GET_CONNECTION_INFORMATION       0x03
   92 
   93 
   94 /*
   95  * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format
   96  */
   97 #define UVISOR_MAX_CONN 8
   98 struct uvisor_connection_info {
   99         uWord   num_ports;
  100         struct {
  101                 uByte   port_function_id;
  102                 uByte   port;
  103         } connections[UVISOR_MAX_CONN];
  104 };
  105 #define UVISOR_CONNECTION_INFO_SIZE 18
  106 
  107 /* struct uvisor_connection_info.connection[x].port_function_id defines: */
  108 #define UVISOR_FUNCTION_GENERIC         0x00
  109 #define UVISOR_FUNCTION_DEBUGGER        0x01
  110 #define UVISOR_FUNCTION_HOTSYNC         0x02
  111 #define UVISOR_FUNCTION_CONSOLE         0x03
  112 #define UVISOR_FUNCTION_REMOTE_FILE_SYS 0x04
  113 
  114 /*
  115  * Unknown PalmOS stuff.
  116  */
  117 #define UVISOR_GET_PALM_INFORMATION             0x04
  118 #define UVISOR_GET_PALM_INFORMATION_LEN         0x44
  119 
  120 struct uvisor_palm_connection_info {
  121         uByte   num_ports;
  122         uByte   endpoint_numbers_different;
  123         uWord   reserved1;
  124         struct {
  125                 uDWord  port_function_id;
  126                 uByte   port;
  127                 uByte   end_point_info;
  128                 uWord   reserved;
  129         } connections[UVISOR_MAX_CONN];
  130 };
  131 
  132 #define UVISORIBUFSIZE 64
  133 #define UVISOROBUFSIZE 1024
  134 
  135 struct uvisor_softc {
  136         struct device           sc_dev;         /* base device */
  137         usbd_device_handle      sc_udev;        /* device */
  138         usbd_interface_handle   sc_iface;       /* interface */
  139 /* 
  140  * added sc_vendor for later interrogation in failed initialisations
  141  */
  142         int                     sc_vendor;      /* USB device vendor */
  143 
  144         struct device           *sc_subdevs[UVISOR_MAX_CONN];
  145         int                     sc_numcon;
  146 
  147         u_int16_t               sc_flags;
  148 
  149         u_char                  sc_dying;
  150 };
  151 
  152 usbd_status uvisor_init(struct uvisor_softc *,
  153                                struct uvisor_connection_info *,
  154                                struct uvisor_palm_connection_info *);
  155 
  156 void uvisor_close(void *, int);
  157 
  158 
  159 struct ucom_methods uvisor_methods = {
  160         NULL,
  161         NULL,
  162         NULL,
  163         NULL,
  164         NULL,
  165         uvisor_close,
  166         NULL,
  167         NULL,
  168 };
  169 
  170 struct uvisor_type {
  171         struct usb_devno        uv_dev;
  172         u_int16_t               uv_flags;       
  173 #define PALM4   0x0001
  174 #define VISOR   0x0002
  175 #define NOFRE   0x0004
  176 #define CLIE4   (VISOR|NOFRE)
  177 };
  178 static const struct uvisor_type uvisor_devs[] = {
  179         {{ USB_VENDOR_ACEECA, USB_PRODUCT_ACEECA_MEZ1000 }, PALM4 },
  180         {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR }, VISOR },
  181         {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO }, PALM4 },
  182         {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO600 }, VISOR },
  183         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M500 }, PALM4 },
  184         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M505 }, PALM4 },
  185         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M515 }, PALM4 },
  186         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_I705 }, PALM4 },
  187         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M125 }, PALM4 },
  188         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M130 }, PALM4 },
  189         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_Z }, PALM4 },
  190         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_T }, PALM4 },
  191         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE }, PALM4 },
  192         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE_31 }, PALM4 },
  193         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40 }, PALM4 },
  194         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41 }, PALM4 },
  195         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360 }, PALM4 },
  196         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60 }, PALM4 },
  197         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TJ25 }, PALM4 },
  198 /*      {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_25 }, PALM4 },*/
  199         {{ USB_VENDOR_GARMIN, USB_PRODUCT_GARMIN_IQUE3600 }, PALM4 },
  200         {{ USB_VENDOR_TAPWAVE, USB_PRODUCT_TAPWAVE_ZODIAC }, PALM4 },
  201 };
  202 #define uvisor_lookup(v, p) ((struct uvisor_type *)usb_lookup(uvisor_devs, v, p))
  203 
  204 int uvisor_match(struct device *, void *, void *); 
  205 void uvisor_attach(struct device *, struct device *, void *); 
  206 int uvisor_detach(struct device *, int); 
  207 int uvisor_activate(struct device *, enum devact); 
  208 
  209 struct cfdriver uvisor_cd = { 
  210         NULL, "uvisor", DV_DULL 
  211 }; 
  212 
  213 const struct cfattach uvisor_ca = { 
  214         sizeof(struct uvisor_softc), 
  215         uvisor_match, 
  216         uvisor_attach, 
  217         uvisor_detach, 
  218         uvisor_activate, 
  219 };
  220 
  221 int
  222 uvisor_match(struct device *parent, void *match, void *aux)
  223 {
  224         struct usb_attach_arg *uaa = aux;
  225 
  226         if (uaa->iface != NULL)
  227                 return (UMATCH_NONE);
  228 
  229         DPRINTFN(20,("uvisor: vendor=0x%x, product=0x%x\n",
  230                      uaa->vendor, uaa->product));
  231 
  232         return (uvisor_lookup(uaa->vendor, uaa->product) != NULL ?
  233                 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
  234 }
  235 
  236 void
  237 uvisor_attach(struct device *parent, struct device *self, void *aux)
  238 {
  239         struct uvisor_softc *sc = (struct uvisor_softc *)self;
  240         struct usb_attach_arg *uaa = aux;
  241         usbd_device_handle dev = uaa->device;
  242         usbd_interface_handle iface;
  243         usb_interface_descriptor_t *id;
  244         struct uvisor_connection_info coninfo;
  245         struct uvisor_palm_connection_info palmconinfo;
  246         usb_endpoint_descriptor_t *ed;
  247         char *devinfop;
  248         char *devname = sc->sc_dev.dv_xname;
  249         int i, j, hasin, hasout, port;
  250         usbd_status err;
  251         struct ucom_attach_args uca;
  252 
  253         DPRINTFN(10,("\nuvisor_attach: sc=%p\n", sc));
  254 
  255         /* Move the device into the configured state. */
  256         err = usbd_set_config_index(dev, UVISOR_CONFIG_INDEX, 1);
  257         if (err) {
  258                 printf("\n%s: failed to set configuration, err=%s\n",
  259                        devname, usbd_errstr(err));
  260                 goto bad;
  261         }
  262 
  263         err = usbd_device2interface_handle(dev, UVISOR_IFACE_INDEX, &iface);
  264         if (err) {
  265                 printf("\n%s: failed to get interface, err=%s\n",
  266                        devname, usbd_errstr(err));
  267                 goto bad;
  268         }
  269 
  270         devinfop = usbd_devinfo_alloc(dev, 0);
  271         printf("\n%s: %s\n", devname, devinfop);
  272         usbd_devinfo_free(devinfop);
  273 
  274         sc->sc_flags = uvisor_lookup(uaa->vendor, uaa->product)->uv_flags;
  275         sc->sc_vendor = uaa->vendor;
  276         
  277         if ((sc->sc_flags & (VISOR | PALM4)) == 0) {
  278                 printf("%s: device is neither visor nor palm\n", 
  279                     sc->sc_dev.dv_xname);
  280                 goto bad;
  281         }
  282 
  283         id = usbd_get_interface_descriptor(iface);
  284 
  285         sc->sc_udev = dev;
  286         sc->sc_iface = iface;
  287 
  288         uca.ibufsize = UVISORIBUFSIZE;
  289         uca.obufsize = UVISOROBUFSIZE;
  290         uca.ibufsizepad = UVISORIBUFSIZE;
  291         uca.opkthdrlen = 0;
  292         uca.device = dev;
  293         uca.iface = iface;
  294         uca.methods = &uvisor_methods;
  295         uca.arg = sc;
  296 
  297         err = uvisor_init(sc, &coninfo, &palmconinfo);
  298         if (err) {
  299                 printf("%s: init failed, %s\n", sc->sc_dev.dv_xname,
  300                        usbd_errstr(err));
  301                 goto bad;
  302         }
  303 
  304         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  305                            &sc->sc_dev);
  306 
  307         if (sc->sc_flags & VISOR) {
  308                 sc->sc_numcon = UGETW(coninfo.num_ports);
  309                 if (sc->sc_numcon > UVISOR_MAX_CONN)
  310                         sc->sc_numcon = UVISOR_MAX_CONN;
  311 
  312                 /* Attach a ucom for each connection. */
  313                 for (i = 0; i < sc->sc_numcon; ++i) {
  314                         switch (coninfo.connections[i].port_function_id) {
  315                         case UVISOR_FUNCTION_GENERIC:
  316                                 uca.info = "Generic";
  317                                 break;
  318                         case UVISOR_FUNCTION_DEBUGGER:
  319                                 uca.info = "Debugger";
  320                                 break;
  321                         case UVISOR_FUNCTION_HOTSYNC:
  322                                 uca.info = "HotSync";
  323                                 break;
  324                         case UVISOR_FUNCTION_REMOTE_FILE_SYS:
  325                                 uca.info = "Remote File System";
  326                                 break;
  327                         default:
  328                                 uca.info = "unknown";
  329                                 break;
  330                         }
  331                         port = coninfo.connections[i].port;
  332                         uca.portno = port;
  333                         uca.bulkin = port | UE_DIR_IN;
  334                         uca.bulkout = port | UE_DIR_OUT;
  335                         /* Verify that endpoints exist. */
  336                         hasin = 0;
  337                         hasout = 0;
  338                         for (j = 0; j < id->bNumEndpoints; j++) {
  339                                 ed = usbd_interface2endpoint_descriptor(iface, j);
  340                                 if (ed == NULL)
  341                                         break;
  342                                 if (UE_GET_ADDR(ed->bEndpointAddress) == port &&
  343                                     (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
  344                                         if (UE_GET_DIR(ed->bEndpointAddress)
  345                                             == UE_DIR_IN)
  346                                                 hasin++;
  347                                         else
  348                                                 hasout++;
  349                                 }
  350                         }
  351                         if (hasin == 1 && hasout == 1)
  352                                 sc->sc_subdevs[i] = config_found_sm(self, &uca,
  353                                     ucomprint, ucomsubmatch);
  354                         else
  355                                 printf("%s: no proper endpoints for port %d (%d,%d)\n",
  356                                     sc->sc_dev.dv_xname, port, hasin, hasout);
  357                 }
  358         } else {
  359                 sc->sc_numcon = palmconinfo.num_ports;
  360                 if (sc->sc_numcon > UVISOR_MAX_CONN)
  361                         sc->sc_numcon = UVISOR_MAX_CONN;
  362 
  363                 /* Attach a ucom for each connection. */
  364                 for (i = 0; i < sc->sc_numcon; ++i) {
  365                         /*
  366                          * XXX this should copy out 4-char string from the
  367                          * XXX port_function_id, but where would the string go?
  368                          * XXX uca.info is a const char *, not an array.
  369                          */
  370                         uca.info = "sync";
  371                         uca.portno = i;
  372                         if (palmconinfo.endpoint_numbers_different) {
  373                                 port = palmconinfo.connections[i].end_point_info;
  374                                 uca.bulkin = (port >> 4) | UE_DIR_IN;
  375                                 uca.bulkout = (port & 0xf) | UE_DIR_OUT;
  376                         } else {
  377                                 port = palmconinfo.connections[i].port;
  378                                 uca.bulkin = port | UE_DIR_IN;
  379                                 uca.bulkout = port | UE_DIR_OUT;
  380                         }
  381                         sc->sc_subdevs[i] = config_found_sm(self, &uca,
  382                             ucomprint, ucomsubmatch);
  383                 }
  384         }
  385 
  386         return;
  387 
  388 bad:
  389         DPRINTF(("uvisor_attach: ATTACH ERROR\n"));
  390         sc->sc_dying = 1;
  391 }
  392 
  393 int
  394 uvisor_activate(struct device *self, enum devact act)
  395 {
  396         struct uvisor_softc *sc = (struct uvisor_softc *)self;
  397         int rv = 0;
  398         int i;
  399 
  400         switch (act) {
  401         case DVACT_ACTIVATE:
  402                 break;
  403 
  404         case DVACT_DEACTIVATE:
  405                 for (i = 0; i < sc->sc_numcon; i++)
  406                         if (sc->sc_subdevs[i] != NULL)
  407                                 rv = config_deactivate(sc->sc_subdevs[i]);
  408                 sc->sc_dying = 1;
  409                 break;
  410         }
  411         return (rv);
  412 }
  413 
  414 int
  415 uvisor_detach(struct device *self, int flags)
  416 {
  417         struct uvisor_softc *sc = (struct uvisor_softc *)self;
  418         int rv = 0;
  419         int i;
  420 
  421         DPRINTF(("uvisor_detach: sc=%p flags=%d\n", sc, flags));
  422         sc->sc_dying = 1;
  423         for (i = 0; i < sc->sc_numcon; i++) {
  424                 if (sc->sc_subdevs[i] != NULL) {
  425                         rv |= config_detach(sc->sc_subdevs[i], flags);
  426                         sc->sc_subdevs[i] = NULL;
  427                 }
  428         }
  429 
  430         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  431                            &sc->sc_dev);
  432 
  433         return (rv);
  434 }
  435 
  436 usbd_status
  437 uvisor_init(struct uvisor_softc *sc, struct uvisor_connection_info *ci,
  438     struct uvisor_palm_connection_info *cpi)
  439 {
  440         usbd_status err;
  441         usb_device_request_t req;
  442         int actlen;
  443         uWord avail;
  444 
  445         if (sc->sc_flags & PALM4) {
  446                 DPRINTF(("uvisor_init: getting Palm connection info\n"));
  447                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  448                 req.bRequest = UVISOR_GET_PALM_INFORMATION;
  449                 USETW(req.wValue, 0);
  450                 USETW(req.wIndex, 0);
  451                 USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
  452                 err = usbd_do_request_flags(sc->sc_udev, &req, cpi,
  453                     USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
  454                 if (err == USBD_STALLED && sc->sc_vendor == USB_VENDOR_SONY) {
  455                         /* some sony clie devices stall on palm4 requests,
  456                          * switch them over to using visor. dont do free space
  457                          * checks on them since they dont like them either.
  458                          */
  459                         DPRINTF(("switching role for CLIE probe\n"));
  460                         sc->sc_flags = CLIE4;
  461                         err = 0;
  462                 }
  463                 if (err)
  464                         return (err);
  465         }
  466         
  467         if (sc->sc_flags & VISOR) {
  468                 DPRINTF(("uvisor_init: getting Visor connection info\n"));
  469                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  470                 req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
  471                 USETW(req.wValue, 0);
  472                 USETW(req.wIndex, 0);
  473                 USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
  474                 err = usbd_do_request_flags(sc->sc_udev, &req, ci,
  475                     USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
  476                 if (err)
  477                         return (err);
  478         }
  479         
  480         if (sc->sc_flags & NOFRE)
  481                 return (err);
  482         
  483         DPRINTF(("uvisor_init: getting available bytes\n"));
  484         req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  485         req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE;
  486         USETW(req.wValue, 0);
  487         USETW(req.wIndex, 5);
  488         USETW(req.wLength, sizeof avail);
  489         err = usbd_do_request(sc->sc_udev, &req, &avail);
  490         if (err)
  491                 return (err);
  492         DPRINTF(("uvisor_init: avail=%d\n", UGETW(avail)));
  493         DPRINTF(("uvisor_init: done\n"));
  494         return (err);
  495 }
  496 
  497 void
  498 uvisor_close(void *addr, int portno)
  499 {
  500         struct uvisor_softc *sc = addr;
  501         usb_device_request_t req;
  502         struct uvisor_connection_info coninfo; /* XXX ? */
  503         int actlen;
  504 
  505         if (sc->sc_dying)
  506                 return;
  507 
  508         req.bmRequestType = UT_READ_VENDOR_ENDPOINT; /* XXX read? */
  509         req.bRequest = UVISOR_CLOSE_NOTIFICATION;
  510         USETW(req.wValue, 0);
  511         USETW(req.wIndex, 0);
  512         USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
  513         (void)usbd_do_request_flags(sc->sc_udev, &req, &coninfo,
  514                   USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
  515 }

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