The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/uvisor.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: uvisor.c,v 1.24.2.1 2004/07/10 13:32:56 tron 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  * Handspring Visor (Palmpilot compatible PDA) driver
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __KERNEL_RCSID(0, "$NetBSD: uvisor.c,v 1.24.2.1 2004/07/10 13:32:56 tron Exp $");
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/kernel.h>
   50 #include <sys/device.h>
   51 #include <sys/conf.h>
   52 #include <sys/tty.h>
   53 
   54 #include <dev/usb/usb.h>
   55 #include <dev/usb/usbhid.h>
   56 
   57 #include <dev/usb/usbdi.h>
   58 #include <dev/usb/usbdi_util.h>
   59 #include <dev/usb/usbdevs.h>
   60 
   61 #include <dev/usb/ucomvar.h>
   62 
   63 #ifdef UVISOR_DEBUG
   64 #define DPRINTF(x)      if (uvisordebug) printf x
   65 #define DPRINTFN(n,x)   if (uvisordebug>(n)) printf x
   66 int uvisordebug = 0;
   67 #else
   68 #define DPRINTF(x)
   69 #define DPRINTFN(n,x)
   70 #endif
   71 
   72 #define UVISOR_CONFIG_INDEX     0
   73 #define UVISOR_IFACE_INDEX      0
   74 
   75 /* From the Linux driver */
   76 /*
   77  * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
   78  * are available to be transfered to the host for the specified endpoint.
   79  * Currently this is not used, and always returns 0x0001
   80  */
   81 #define UVISOR_REQUEST_BYTES_AVAILABLE          0x01
   82 
   83 /*
   84  * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
   85  * is now closing the pipe. An empty packet is sent in response.
   86  */
   87 #define UVISOR_CLOSE_NOTIFICATION               0x02
   88 
   89 /*
   90  * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
   91  * get the endpoints used by the connection.
   92  */
   93 #define UVISOR_GET_CONNECTION_INFORMATION       0x03
   94 
   95 
   96 /*
   97  * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format
   98  */
   99 #define UVISOR_MAX_CONN 8
  100 struct uvisor_connection_info {
  101         uWord   num_ports;
  102         struct {
  103                 uByte   port_function_id;
  104                 uByte   port;
  105         } connections[UVISOR_MAX_CONN];
  106 };
  107 #define UVISOR_CONNECTION_INFO_SIZE 18
  108 
  109 /* struct uvisor_connection_info.connection[x].port_function_id defines: */
  110 #define UVISOR_FUNCTION_GENERIC         0x00
  111 #define UVISOR_FUNCTION_DEBUGGER        0x01
  112 #define UVISOR_FUNCTION_HOTSYNC         0x02
  113 #define UVISOR_FUNCTION_CONSOLE         0x03
  114 #define UVISOR_FUNCTION_REMOTE_FILE_SYS 0x04
  115 
  116 /*
  117  * Unknown PalmOS stuff.
  118  */
  119 #define UVISOR_GET_PALM_INFORMATION             0x04
  120 #define UVISOR_GET_PALM_INFORMATION_LEN         0x44
  121 
  122 struct uvisor_palm_connection_info {
  123         uByte   num_ports;
  124         uByte   endpoint_numbers_different;
  125         uWord   reserved1;
  126         struct {
  127                 uDWord  port_function_id;
  128                 uByte   port;
  129                 uByte   end_point_info;
  130                 uWord   reserved;
  131         } connections[UVISOR_MAX_CONN];
  132 };
  133 
  134 
  135 
  136 #define UVISORIBUFSIZE 64
  137 #define UVISOROBUFSIZE 1024
  138 
  139 struct uvisor_softc {
  140         USBBASEDEVICE           sc_dev;         /* base device */
  141         usbd_device_handle      sc_udev;        /* device */
  142         usbd_interface_handle   sc_iface;       /* interface */
  143 
  144         device_ptr_t            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 Static usbd_status uvisor_init(struct uvisor_softc *,
  153                                struct uvisor_connection_info *,
  154                                struct uvisor_palm_connection_info *);
  155 
  156 Static 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 
  176 };
  177 static const struct uvisor_type uvisor_devs[] = {
  178         {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR }, VISOR },
  179         {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO }, PALM4 },
  180         {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO600 }, PALM4 },
  181         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M500 }, PALM4 },
  182         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M505 }, PALM4 },
  183         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M515 }, PALM4 },
  184         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_I705 }, PALM4 },
  185         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M125 }, PALM4 },
  186         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M130 }, PALM4 },
  187         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_Z }, PALM4 },
  188         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_T }, PALM4 },
  189         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE31 }, PALM4 },
  190         {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE }, PALM4 },
  191         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40 }, PALM4 },
  192         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41 }, PALM4 },
  193         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360 }, PALM4 },
  194         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60 }, PALM4 },
  195         {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_35 }, 0 },
  196 /*      {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_25 }, PALM4 },*/
  197 };
  198 #define uvisor_lookup(v, p) ((struct uvisor_type *)usb_lookup(uvisor_devs, v, p))
  199 
  200 USB_DECLARE_DRIVER(uvisor);
  201 
  202 USB_MATCH(uvisor)
  203 {
  204         USB_MATCH_START(uvisor, uaa);
  205 
  206         if (uaa->iface != NULL)
  207                 return (UMATCH_NONE);
  208 
  209         DPRINTFN(20,("uvisor: vendor=0x%x, product=0x%x\n",
  210                      uaa->vendor, uaa->product));
  211 
  212         return (uvisor_lookup(uaa->vendor, uaa->product) != NULL ?
  213                 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
  214 }
  215 
  216 USB_ATTACH(uvisor)
  217 {
  218         USB_ATTACH_START(uvisor, sc, uaa);
  219         usbd_device_handle dev = uaa->device;
  220         usbd_interface_handle iface;
  221         usb_interface_descriptor_t *id;
  222         struct uvisor_connection_info coninfo;
  223         struct uvisor_palm_connection_info palmconinfo;
  224         usb_endpoint_descriptor_t *ed;
  225         char devinfo[1024];
  226         char *devname = USBDEVNAME(sc->sc_dev);
  227         int i, j, hasin, hasout, port;
  228         usbd_status err;
  229         struct ucom_attach_args uca;
  230 
  231         DPRINTFN(10,("\nuvisor_attach: sc=%p\n", sc));
  232 
  233         /* Move the device into the configured state. */
  234         err = usbd_set_config_index(dev, UVISOR_CONFIG_INDEX, 1);
  235         if (err) {
  236                 printf("\n%s: failed to set configuration, err=%s\n",
  237                        devname, usbd_errstr(err));
  238                 goto bad;
  239         }
  240 
  241         err = usbd_device2interface_handle(dev, UVISOR_IFACE_INDEX, &iface);
  242         if (err) {
  243                 printf("\n%s: failed to get interface, err=%s\n",
  244                        devname, usbd_errstr(err));
  245                 goto bad;
  246         }
  247 
  248         usbd_devinfo(dev, 0, devinfo);
  249         USB_ATTACH_SETUP;
  250         printf("%s: %s\n", devname, devinfo);
  251 
  252         sc->sc_flags = uvisor_lookup(uaa->vendor, uaa->product)->uv_flags;
  253 
  254         if ((sc->sc_flags & (VISOR | PALM4)) == 0) {
  255                 printf("%s: init failed, device type is neither visor nor palm\n", 
  256                     USBDEVNAME(sc->sc_dev));
  257                 goto bad;
  258         }
  259 
  260         id = usbd_get_interface_descriptor(iface);
  261 
  262         sc->sc_udev = dev;
  263         sc->sc_iface = iface;
  264 
  265         uca.ibufsize = UVISORIBUFSIZE;
  266         uca.obufsize = UVISOROBUFSIZE;
  267         uca.ibufsizepad = UVISORIBUFSIZE;
  268         uca.opkthdrlen = 0;
  269         uca.device = dev;
  270         uca.iface = iface;
  271         uca.methods = &uvisor_methods;
  272         uca.arg = sc;
  273 
  274         err = uvisor_init(sc, &coninfo, &palmconinfo);
  275         if (err) {
  276                 printf("%s: init failed, %s\n", USBDEVNAME(sc->sc_dev),
  277                        usbd_errstr(err));
  278                 goto bad;
  279         }
  280 
  281         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  282                            USBDEV(sc->sc_dev));
  283 
  284         if (sc->sc_flags & VISOR) {
  285                 sc->sc_numcon = UGETW(coninfo.num_ports);
  286                 if (sc->sc_numcon > UVISOR_MAX_CONN)
  287                         sc->sc_numcon = UVISOR_MAX_CONN;
  288 
  289                 /* Attach a ucom for each connection. */
  290                 for (i = 0; i < sc->sc_numcon; ++i) {
  291                         switch (coninfo.connections[i].port_function_id) {
  292                         case UVISOR_FUNCTION_GENERIC:
  293                                 uca.info = "Generic";
  294                                 break;
  295                         case UVISOR_FUNCTION_DEBUGGER:
  296                                 uca.info = "Debugger";
  297                                 break;
  298                         case UVISOR_FUNCTION_HOTSYNC:
  299                                 uca.info = "HotSync";
  300                                 break;
  301                         case UVISOR_FUNCTION_REMOTE_FILE_SYS:
  302                                 uca.info = "Remote File System";
  303                                 break;
  304                         default:
  305                                 uca.info = "unknown";
  306                                 break;
  307                         }
  308                         port = coninfo.connections[i].port;
  309                         uca.portno = port;
  310                         uca.bulkin = port | UE_DIR_IN;
  311                         uca.bulkout = port | UE_DIR_OUT;
  312                         /* Verify that endpoints exist. */
  313                         hasin = 0;
  314                         hasout = 0;
  315                         for (j = 0; j < id->bNumEndpoints; j++) {
  316                                 ed = usbd_interface2endpoint_descriptor(iface, j);
  317                                 if (ed == NULL)
  318                                         break;
  319                                 if (UE_GET_ADDR(ed->bEndpointAddress) == port &&
  320                                     (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
  321                                         if (UE_GET_DIR(ed->bEndpointAddress)
  322                                             == UE_DIR_IN)
  323                                                 hasin++;
  324                                         else
  325                                                 hasout++;
  326                                 }
  327                         }
  328                         if (hasin == 1 && hasout == 1)
  329                                 sc->sc_subdevs[i] = config_found_sm(self, &uca,
  330                                     ucomprint, ucomsubmatch);
  331                         else
  332                                 printf("%s: no proper endpoints for port %d (%d,%d)\n",
  333                                     USBDEVNAME(sc->sc_dev), port, hasin, hasout);
  334                 }
  335 
  336         } else {
  337                 sc->sc_numcon = palmconinfo.num_ports;
  338                 if (sc->sc_numcon > UVISOR_MAX_CONN)
  339                         sc->sc_numcon = UVISOR_MAX_CONN;
  340 
  341                 /* Attach a ucom for each connection. */
  342                 for (i = 0; i < sc->sc_numcon; ++i) {
  343                         /* 
  344                          * XXX this should copy out 4-char string from the 
  345                          * XXX port_function_id, but where would the string go?
  346                          * XXX uca.info is a const char *, not an array.
  347                          */
  348                         uca.info = "sync";
  349                         uca.portno = i;
  350                         if (palmconinfo.endpoint_numbers_different) {
  351                                 port = palmconinfo.connections[i].end_point_info;
  352                                 uca.bulkin = (port >> 4) | UE_DIR_IN;
  353                                 uca.bulkout = (port & 0xf) | UE_DIR_OUT;
  354                         } else {
  355                                 port = palmconinfo.connections[i].port;
  356                                 uca.bulkin = port | UE_DIR_IN;
  357                                 uca.bulkout = port | UE_DIR_OUT;
  358                         }
  359                         sc->sc_subdevs[i] = config_found_sm(self, &uca,
  360                             ucomprint, ucomsubmatch);
  361 
  362                             
  363                 }
  364         }
  365 
  366         USB_ATTACH_SUCCESS_RETURN;
  367 
  368 bad:
  369         DPRINTF(("uvisor_attach: ATTACH ERROR\n"));
  370         sc->sc_dying = 1;
  371         USB_ATTACH_ERROR_RETURN;
  372 }
  373 
  374 int
  375 uvisor_activate(device_ptr_t self, enum devact act)
  376 {
  377         struct uvisor_softc *sc = (struct uvisor_softc *)self;
  378         int rv = 0;
  379         int i;
  380 
  381         switch (act) {
  382         case DVACT_ACTIVATE:
  383                 return (EOPNOTSUPP);
  384                 break;
  385 
  386         case DVACT_DEACTIVATE:
  387                 for (i = 0; i < sc->sc_numcon; i++)
  388                         if (sc->sc_subdevs[i] != NULL)
  389                                 rv |= config_deactivate(sc->sc_subdevs[i]);
  390                 sc->sc_dying = 1;
  391                 break;
  392         }
  393         return (rv);
  394 }
  395 
  396 int
  397 uvisor_detach(device_ptr_t self, int flags)
  398 {
  399         struct uvisor_softc *sc = (struct uvisor_softc *)self;
  400         int rv = 0;
  401         int i;
  402 
  403         DPRINTF(("uvisor_detach: sc=%p flags=%d\n", sc, flags));
  404         sc->sc_dying = 1;
  405         for (i = 0; i < sc->sc_numcon; i++) {
  406                 if (sc->sc_subdevs[i] != NULL) {
  407                         rv |= config_detach(sc->sc_subdevs[i], flags);
  408                         sc->sc_subdevs[i] = NULL;
  409                 }
  410         }
  411 
  412         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  413                            USBDEV(sc->sc_dev));
  414 
  415 
  416         return (rv);
  417 }
  418 
  419 usbd_status
  420 uvisor_init(struct uvisor_softc *sc, struct uvisor_connection_info *ci,
  421     struct uvisor_palm_connection_info *cpi)
  422 {
  423         usbd_status err;
  424         usb_device_request_t req;
  425         int actlen;
  426         uWord avail;
  427 
  428         if (sc->sc_flags & VISOR) {
  429                 DPRINTF(("uvisor_init: getting Visor connection info\n"));
  430                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  431                 req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
  432                 USETW(req.wValue, 0);
  433                 USETW(req.wIndex, 0);
  434                 USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
  435                 err = usbd_do_request_flags(sc->sc_udev, &req, ci,
  436                     USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
  437                 if (err)
  438                         return (err);
  439         }
  440 
  441         if (sc->sc_flags & PALM4) {
  442                 DPRINTF(("uvisor_init: getting Palm connection info\n"));
  443                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  444                 req.bRequest = UVISOR_GET_PALM_INFORMATION;
  445                 USETW(req.wValue, 0);
  446                 USETW(req.wIndex, 0);
  447                 USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
  448                 err = usbd_do_request_flags(sc->sc_udev, &req, cpi,
  449                     USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
  450                 if (err)
  451                         return (err);
  452         }
  453 
  454         DPRINTF(("uvisor_init: getting available bytes\n"));
  455         req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  456         req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE;
  457         USETW(req.wValue, 0);
  458         USETW(req.wIndex, 5);
  459         USETW(req.wLength, sizeof avail);
  460         err = usbd_do_request(sc->sc_udev, &req, &avail);
  461         if (err)
  462                 return (err);
  463         DPRINTF(("uvisor_init: avail=%d\n", UGETW(avail)));
  464 
  465         DPRINTF(("uvisor_init: done\n"));
  466         return (err);
  467 }
  468 
  469 void
  470 uvisor_close(void *addr, int portno)
  471 {
  472         struct uvisor_softc *sc = addr;
  473         usb_device_request_t req;
  474         struct uvisor_connection_info coninfo; /* XXX ? */
  475         int actlen;
  476 
  477         if (sc->sc_dying)
  478                 return;
  479 
  480         req.bmRequestType = UT_READ_VENDOR_ENDPOINT; /* XXX read? */
  481         req.bRequest = UVISOR_CLOSE_NOTIFICATION;
  482         USETW(req.wValue, 0);
  483         USETW(req.wIndex, 0);
  484         USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
  485         (void)usbd_do_request_flags(sc->sc_udev, &req, &coninfo,
  486                   USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
  487 }

Cache object: 7091e61a3b3396fbd667f4f22ba3d359


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.