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/serial/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.9 2001/01/23 14:04:14 augustss Exp $      */
    2 /*      $FreeBSD$ */
    3 
    4 /* Also already merged from NetBSD:
    5  *      $NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $
    6  *      $NetBSD: uvisor.c,v 1.13 2002/02/11 15:11:49 augustss Exp $
    7  *      $NetBSD: uvisor.c,v 1.14 2002/02/27 23:00:03 augustss Exp $
    8  *      $NetBSD: uvisor.c,v 1.15 2002/06/16 15:01:31 augustss Exp $
    9  *      $NetBSD: uvisor.c,v 1.16 2002/07/11 21:14:36 augustss Exp $
   10  *      $NetBSD: uvisor.c,v 1.17 2002/08/13 11:38:15 augustss Exp $
   11  *      $NetBSD: uvisor.c,v 1.18 2003/02/05 00:50:14 augustss Exp $
   12  *      $NetBSD: uvisor.c,v 1.19 2003/02/07 18:12:37 augustss Exp $
   13  *      $NetBSD: uvisor.c,v 1.20 2003/04/11 01:30:10 simonb Exp $
   14  */
   15 
   16 /*-
   17  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
   18  *
   19  * Copyright (c) 2000 The NetBSD Foundation, Inc.
   20  * All rights reserved.
   21  *
   22  * This code is derived from software contributed to The NetBSD Foundation
   23  * by Lennart Augustsson (lennart@augustsson.net) at
   24  * Carlstedt Research & Technology.
   25  *
   26  * Redistribution and use in source and binary forms, with or without
   27  * modification, are permitted provided that the following conditions
   28  * are met:
   29  * 1. Redistributions of source code must retain the above copyright
   30  *    notice, this list of conditions and the following disclaimer.
   31  * 2. Redistributions in binary form must reproduce the above copyright
   32  *    notice, this list of conditions and the following disclaimer in the
   33  *    documentation and/or other materials provided with the distribution.
   34  *
   35  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   36  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   37  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   39  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   40  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   41  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   42  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   43  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   44  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   45  * POSSIBILITY OF SUCH DAMAGE.
   46  */
   47 
   48 /*
   49  * Handspring Visor (Palmpilot compatible PDA) driver
   50  */
   51 
   52 #include <sys/stdint.h>
   53 #include <sys/stddef.h>
   54 #include <sys/param.h>
   55 #include <sys/queue.h>
   56 #include <sys/types.h>
   57 #include <sys/systm.h>
   58 #include <sys/kernel.h>
   59 #include <sys/bus.h>
   60 #include <sys/module.h>
   61 #include <sys/lock.h>
   62 #include <sys/mutex.h>
   63 #include <sys/condvar.h>
   64 #include <sys/sysctl.h>
   65 #include <sys/sx.h>
   66 #include <sys/unistd.h>
   67 #include <sys/callout.h>
   68 #include <sys/malloc.h>
   69 #include <sys/priv.h>
   70 
   71 #include <dev/usb/usb.h>
   72 #include <dev/usb/usbdi.h>
   73 #include <dev/usb/usbdi_util.h>
   74 #include "usbdevs.h"
   75 
   76 #define USB_DEBUG_VAR uvisor_debug
   77 #include <dev/usb/usb_debug.h>
   78 #include <dev/usb/usb_process.h>
   79 
   80 #include <dev/usb/serial/usb_serial.h>
   81 
   82 #ifdef USB_DEBUG
   83 static int uvisor_debug = 0;
   84 
   85 static SYSCTL_NODE(_hw_usb, OID_AUTO, uvisor, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
   86     "USB uvisor");
   87 SYSCTL_INT(_hw_usb_uvisor, OID_AUTO, debug, CTLFLAG_RWTUN,
   88     &uvisor_debug, 0, "Debug level");
   89 #endif
   90 
   91 #define UVISOR_CONFIG_INDEX     0
   92 #define UVISOR_IFACE_INDEX      0
   93 
   94 /*
   95  * The following buffer sizes are hardcoded due to the way the Palm
   96  * firmware works. It looks like the device is not short terminating
   97  * the data transferred.
   98  */
   99 #define UVISORIBUFSIZE         0        /* Use wMaxPacketSize */
  100 #define UVISOROBUFSIZE         32       /* bytes */
  101 #define UVISOROFRAMES          32       /* units */
  102 
  103 /* From the Linux driver */
  104 /*
  105  * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
  106  * are available to be transferred to the host for the specified endpoint.
  107  * Currently this is not used, and always returns 0x0001
  108  */
  109 #define UVISOR_REQUEST_BYTES_AVAILABLE          0x01
  110 
  111 /*
  112  * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
  113  * is now closing the pipe. An empty packet is sent in response.
  114  */
  115 #define UVISOR_CLOSE_NOTIFICATION               0x02
  116 
  117 /*
  118  * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
  119  * get the endpoints used by the connection.
  120  */
  121 #define UVISOR_GET_CONNECTION_INFORMATION       0x03
  122 
  123 /*
  124  * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format
  125  */
  126 #define UVISOR_MAX_CONN 8
  127 struct uvisor_connection_info {
  128         uWord   num_ports;
  129         struct {
  130                 uByte   port_function_id;
  131                 uByte   port;
  132         } __packed connections[UVISOR_MAX_CONN];
  133 } __packed;
  134 
  135 #define UVISOR_CONNECTION_INFO_SIZE 18
  136 
  137 /* struct uvisor_connection_info.connection[x].port defines: */
  138 #define UVISOR_ENDPOINT_1               0x01
  139 #define UVISOR_ENDPOINT_2               0x02
  140 
  141 /* struct uvisor_connection_info.connection[x].port_function_id defines: */
  142 #define UVISOR_FUNCTION_GENERIC         0x00
  143 #define UVISOR_FUNCTION_DEBUGGER        0x01
  144 #define UVISOR_FUNCTION_HOTSYNC         0x02
  145 #define UVISOR_FUNCTION_CONSOLE         0x03
  146 #define UVISOR_FUNCTION_REMOTE_FILE_SYS 0x04
  147 
  148 /*
  149  * Unknown PalmOS stuff.
  150  */
  151 #define UVISOR_GET_PALM_INFORMATION             0x04
  152 #define UVISOR_GET_PALM_INFORMATION_LEN         0x44
  153 
  154 struct uvisor_palm_connection_info {
  155         uByte   num_ports;
  156         uByte   endpoint_numbers_different;
  157         uWord   reserved1;
  158         struct {
  159                 uDWord  port_function_id;
  160                 uByte   port;
  161                 uByte   end_point_info;
  162                 uWord   reserved;
  163         } __packed connections[UVISOR_MAX_CONN];
  164 } __packed;
  165 
  166 enum {
  167         UVISOR_BULK_DT_WR,
  168         UVISOR_BULK_DT_RD,
  169         UVISOR_N_TRANSFER,
  170 };
  171 
  172 struct uvisor_softc {
  173         struct ucom_super_softc sc_super_ucom;
  174         struct ucom_softc sc_ucom;
  175 
  176         struct usb_xfer *sc_xfer[UVISOR_N_TRANSFER];
  177         struct usb_device *sc_udev;
  178         struct mtx sc_mtx;
  179 
  180         uint16_t sc_flag;
  181 #define UVISOR_FLAG_PALM4       0x0001
  182 #define UVISOR_FLAG_VISOR       0x0002
  183 #define UVISOR_FLAG_PALM35      0x0004
  184 #define UVISOR_FLAG_SEND_NOTIFY 0x0008
  185 
  186         uint8_t sc_iface_no;
  187         uint8_t sc_iface_index;
  188 };
  189 
  190 /* prototypes */
  191 
  192 static device_probe_t uvisor_probe;
  193 static device_attach_t uvisor_attach;
  194 static device_detach_t uvisor_detach;
  195 static void uvisor_free_softc(struct uvisor_softc *);
  196 
  197 static usb_callback_t uvisor_write_callback;
  198 static usb_callback_t uvisor_read_callback;
  199 
  200 static usb_error_t uvisor_init(struct uvisor_softc *, struct usb_device *,
  201                     struct usb_config *);
  202 static void     uvisor_free(struct ucom_softc *);
  203 static void     uvisor_cfg_open(struct ucom_softc *);
  204 static void     uvisor_cfg_close(struct ucom_softc *);
  205 static void     uvisor_start_read(struct ucom_softc *);
  206 static void     uvisor_stop_read(struct ucom_softc *);
  207 static void     uvisor_start_write(struct ucom_softc *);
  208 static void     uvisor_stop_write(struct ucom_softc *);
  209 
  210 static const struct usb_config uvisor_config[UVISOR_N_TRANSFER] = {
  211         [UVISOR_BULK_DT_WR] = {
  212                 .type = UE_BULK,
  213                 .endpoint = UE_ADDR_ANY,
  214                 .direction = UE_DIR_OUT,
  215                 .bufsize = UVISOROBUFSIZE * UVISOROFRAMES,
  216                 .frames = UVISOROFRAMES,
  217                 .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
  218                 .callback = &uvisor_write_callback,
  219         },
  220 
  221         [UVISOR_BULK_DT_RD] = {
  222                 .type = UE_BULK,
  223                 .endpoint = UE_ADDR_ANY,
  224                 .direction = UE_DIR_IN,
  225                 .bufsize = UVISORIBUFSIZE,
  226                 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
  227                 .callback = &uvisor_read_callback,
  228         },
  229 };
  230 
  231 static const struct ucom_callback uvisor_callback = {
  232         .ucom_cfg_open = &uvisor_cfg_open,
  233         .ucom_cfg_close = &uvisor_cfg_close,
  234         .ucom_start_read = &uvisor_start_read,
  235         .ucom_stop_read = &uvisor_stop_read,
  236         .ucom_start_write = &uvisor_start_write,
  237         .ucom_stop_write = &uvisor_stop_write,
  238         .ucom_free = &uvisor_free,
  239 };
  240 
  241 static device_method_t uvisor_methods[] = {
  242         DEVMETHOD(device_probe, uvisor_probe),
  243         DEVMETHOD(device_attach, uvisor_attach),
  244         DEVMETHOD(device_detach, uvisor_detach),
  245         DEVMETHOD_END
  246 };
  247 
  248 static driver_t uvisor_driver = {
  249         .name = "uvisor",
  250         .methods = uvisor_methods,
  251         .size = sizeof(struct uvisor_softc),
  252 };
  253 
  254 static const STRUCT_USB_HOST_ID uvisor_devs[] = {
  255 #define UVISOR_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
  256         UVISOR_DEV(ACEECA, MEZ1000, UVISOR_FLAG_PALM4),
  257         UVISOR_DEV(ALPHASMART, DANA_SYNC, UVISOR_FLAG_PALM4),
  258         UVISOR_DEV(GARMIN, IQUE_3600, UVISOR_FLAG_PALM4),
  259         UVISOR_DEV(FOSSIL, WRISTPDA, UVISOR_FLAG_PALM4),
  260         UVISOR_DEV(HANDSPRING, VISOR, UVISOR_FLAG_VISOR),
  261         UVISOR_DEV(HANDSPRING, TREO, UVISOR_FLAG_PALM4),
  262         UVISOR_DEV(HANDSPRING, TREO600, UVISOR_FLAG_PALM4),
  263         UVISOR_DEV(PALM, M500, UVISOR_FLAG_PALM4),
  264         UVISOR_DEV(PALM, M505, UVISOR_FLAG_PALM4),
  265         UVISOR_DEV(PALM, M515, UVISOR_FLAG_PALM4),
  266         UVISOR_DEV(PALM, I705, UVISOR_FLAG_PALM4),
  267         UVISOR_DEV(PALM, M125, UVISOR_FLAG_PALM4),
  268         UVISOR_DEV(PALM, M130, UVISOR_FLAG_PALM4),
  269         UVISOR_DEV(PALM, TUNGSTEN_Z, UVISOR_FLAG_PALM4),
  270         UVISOR_DEV(PALM, TUNGSTEN_T, UVISOR_FLAG_PALM4),
  271         UVISOR_DEV(PALM, ZIRE, UVISOR_FLAG_PALM4),
  272         UVISOR_DEV(PALM, ZIRE31, UVISOR_FLAG_PALM4),
  273         UVISOR_DEV(SAMSUNG, I500, UVISOR_FLAG_PALM4),
  274         UVISOR_DEV(SONY, CLIE_40, 0),
  275         UVISOR_DEV(SONY, CLIE_41, 0),
  276         UVISOR_DEV(SONY, CLIE_S360, UVISOR_FLAG_PALM4),
  277         UVISOR_DEV(SONY, CLIE_NX60, UVISOR_FLAG_PALM4),
  278         UVISOR_DEV(SONY, CLIE_35, UVISOR_FLAG_PALM35),
  279 /*  UVISOR_DEV(SONY, CLIE_25, UVISOR_FLAG_PALM4 ), */
  280         UVISOR_DEV(SONY, CLIE_TJ37, UVISOR_FLAG_PALM4),
  281 /*  UVISOR_DEV(SONY, CLIE_TH55, UVISOR_FLAG_PALM4 ), See PR 80935 */
  282         UVISOR_DEV(TAPWAVE, ZODIAC, UVISOR_FLAG_PALM4),
  283 #undef UVISOR_DEV
  284 };
  285 
  286 DRIVER_MODULE(uvisor, uhub, uvisor_driver, NULL, NULL);
  287 MODULE_DEPEND(uvisor, ucom, 1, 1, 1);
  288 MODULE_DEPEND(uvisor, usb, 1, 1, 1);
  289 MODULE_VERSION(uvisor, 1);
  290 USB_PNP_HOST_INFO(uvisor_devs);
  291 
  292 static int
  293 uvisor_probe(device_t dev)
  294 {
  295         struct usb_attach_arg *uaa = device_get_ivars(dev);
  296 
  297         if (uaa->usb_mode != USB_MODE_HOST) {
  298                 return (ENXIO);
  299         }
  300         if (uaa->info.bConfigIndex != UVISOR_CONFIG_INDEX) {
  301                 return (ENXIO);
  302         }
  303         if (uaa->info.bIfaceIndex != UVISOR_IFACE_INDEX) {
  304                 return (ENXIO);
  305         }
  306         return (usbd_lookup_id_by_uaa(uvisor_devs, sizeof(uvisor_devs), uaa));
  307 }
  308 
  309 static int
  310 uvisor_attach(device_t dev)
  311 {
  312         struct usb_attach_arg *uaa = device_get_ivars(dev);
  313         struct uvisor_softc *sc = device_get_softc(dev);
  314         struct usb_config uvisor_config_copy[UVISOR_N_TRANSFER];
  315         int error;
  316 
  317         DPRINTF("sc=%p\n", sc);
  318         memcpy(uvisor_config_copy, uvisor_config,
  319             sizeof(uvisor_config_copy));
  320 
  321         device_set_usb_desc(dev);
  322 
  323         mtx_init(&sc->sc_mtx, "uvisor", NULL, MTX_DEF);
  324         ucom_ref(&sc->sc_super_ucom);
  325 
  326         sc->sc_udev = uaa->device;
  327 
  328         /* configure the device */
  329 
  330         sc->sc_flag = USB_GET_DRIVER_INFO(uaa);
  331         sc->sc_iface_no = uaa->info.bIfaceNum;
  332         sc->sc_iface_index = UVISOR_IFACE_INDEX;
  333 
  334         error = uvisor_init(sc, uaa->device, uvisor_config_copy);
  335 
  336         if (error) {
  337                 DPRINTF("init failed, error=%s\n",
  338                     usbd_errstr(error));
  339                 goto detach;
  340         }
  341         error = usbd_transfer_setup(uaa->device, &sc->sc_iface_index,
  342             sc->sc_xfer, uvisor_config_copy, UVISOR_N_TRANSFER,
  343             sc, &sc->sc_mtx);
  344         if (error) {
  345                 DPRINTF("could not allocate all pipes\n");
  346                 goto detach;
  347         }
  348 
  349         error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
  350             &uvisor_callback, &sc->sc_mtx);
  351         if (error) {
  352                 DPRINTF("ucom_attach failed\n");
  353                 goto detach;
  354         }
  355         ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
  356 
  357         return (0);
  358 
  359 detach:
  360         uvisor_detach(dev);
  361         return (ENXIO);
  362 }
  363 
  364 static int
  365 uvisor_detach(device_t dev)
  366 {
  367         struct uvisor_softc *sc = device_get_softc(dev);
  368 
  369         DPRINTF("sc=%p\n", sc);
  370 
  371         ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
  372         usbd_transfer_unsetup(sc->sc_xfer, UVISOR_N_TRANSFER);
  373 
  374         device_claim_softc(dev);
  375 
  376         uvisor_free_softc(sc);
  377 
  378         return (0);
  379 }
  380 
  381 UCOM_UNLOAD_DRAIN(uvisor);
  382 
  383 static void
  384 uvisor_free_softc(struct uvisor_softc *sc)
  385 {
  386         if (ucom_unref(&sc->sc_super_ucom)) {
  387                 mtx_destroy(&sc->sc_mtx);
  388                 device_free_softc(sc);
  389         }
  390 }
  391 
  392 static void
  393 uvisor_free(struct ucom_softc *ucom)
  394 {
  395         uvisor_free_softc(ucom->sc_parent);
  396 }
  397 
  398 static usb_error_t
  399 uvisor_init(struct uvisor_softc *sc, struct usb_device *udev, struct usb_config *config)
  400 {
  401         usb_error_t err = 0;
  402         struct usb_device_request req;
  403         struct uvisor_connection_info coninfo;
  404         struct uvisor_palm_connection_info pconinfo;
  405         uint16_t actlen;
  406         uint8_t buffer[256];
  407 
  408         if (sc->sc_flag & UVISOR_FLAG_VISOR) {
  409                 DPRINTF("getting connection info\n");
  410                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  411                 req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
  412                 USETW(req.wValue, 0);
  413                 USETW(req.wIndex, 0);
  414                 USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
  415                 err = usbd_do_request_flags(udev, NULL,
  416                     &req, &coninfo, USB_SHORT_XFER_OK,
  417                     &actlen, USB_DEFAULT_TIMEOUT);
  418 
  419                 if (err) {
  420                         goto done;
  421                 }
  422         }
  423 #ifdef USB_DEBUG
  424         if (sc->sc_flag & UVISOR_FLAG_VISOR) {
  425                 uint16_t i, np;
  426                 const char *desc;
  427 
  428                 np = UGETW(coninfo.num_ports);
  429                 if (np > UVISOR_MAX_CONN) {
  430                         np = UVISOR_MAX_CONN;
  431                 }
  432                 DPRINTF("Number of ports: %d\n", np);
  433 
  434                 for (i = 0; i < np; ++i) {
  435                         switch (coninfo.connections[i].port_function_id) {
  436                         case UVISOR_FUNCTION_GENERIC:
  437                                 desc = "Generic";
  438                                 break;
  439                         case UVISOR_FUNCTION_DEBUGGER:
  440                                 desc = "Debugger";
  441                                 break;
  442                         case UVISOR_FUNCTION_HOTSYNC:
  443                                 desc = "HotSync";
  444                                 break;
  445                         case UVISOR_FUNCTION_REMOTE_FILE_SYS:
  446                                 desc = "Remote File System";
  447                                 break;
  448                         default:
  449                                 desc = "unknown";
  450                                 break;
  451                         }
  452                         DPRINTF("Port %d is for %s\n",
  453                             coninfo.connections[i].port, desc);
  454                 }
  455         }
  456 #endif
  457 
  458         if (sc->sc_flag & UVISOR_FLAG_PALM4) {
  459                 uint8_t port;
  460 
  461                 /* Palm OS 4.0 Hack */
  462                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  463                 req.bRequest = UVISOR_GET_PALM_INFORMATION;
  464                 USETW(req.wValue, 0);
  465                 USETW(req.wIndex, 0);
  466                 USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
  467 
  468                 err = usbd_do_request_flags
  469                     (udev, NULL, &req, &pconinfo, USB_SHORT_XFER_OK,
  470                     &actlen, USB_DEFAULT_TIMEOUT);
  471 
  472                 if (err) {
  473                         goto done;
  474                 }
  475                 if (actlen < 12) {
  476                         DPRINTF("too little data\n");
  477                         err = USB_ERR_INVAL;
  478                         goto done;
  479                 }
  480                 if (pconinfo.endpoint_numbers_different) {
  481                         port = pconinfo.connections[0].end_point_info;
  482                         config[0].endpoint = (port & 0xF);      /* output */
  483                         config[1].endpoint = (port >> 4);       /* input */
  484                 } else {
  485                         port = pconinfo.connections[0].port;
  486                         config[0].endpoint = (port & 0xF);      /* output */
  487                         config[1].endpoint = (port & 0xF);      /* input */
  488                 }
  489 #if 0
  490                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  491                 req.bRequest = UVISOR_GET_PALM_INFORMATION;
  492                 USETW(req.wValue, 0);
  493                 USETW(req.wIndex, 0);
  494                 USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
  495                 err = usbd_do_request(udev, &req, buffer);
  496                 if (err) {
  497                         goto done;
  498                 }
  499 #endif
  500         }
  501         if (sc->sc_flag & UVISOR_FLAG_PALM35) {
  502                 /* get the config number */
  503                 DPRINTF("getting config info\n");
  504                 req.bmRequestType = UT_READ;
  505                 req.bRequest = UR_GET_CONFIG;
  506                 USETW(req.wValue, 0);
  507                 USETW(req.wIndex, 0);
  508                 USETW(req.wLength, 1);
  509 
  510                 err = usbd_do_request(udev, NULL, &req, buffer);
  511                 if (err) {
  512                         goto done;
  513                 }
  514                 /* get the interface number */
  515                 DPRINTF("get the interface number\n");
  516                 req.bmRequestType = UT_READ_DEVICE;
  517                 req.bRequest = UR_GET_INTERFACE;
  518                 USETW(req.wValue, 0);
  519                 USETW(req.wIndex, 0);
  520                 USETW(req.wLength, 1);
  521                 err = usbd_do_request(udev, NULL, &req, buffer);
  522                 if (err) {
  523                         goto done;
  524                 }
  525         }
  526 #if 0
  527         uWord wAvail;
  528 
  529         DPRINTF("getting available bytes\n");
  530         req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
  531         req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE;
  532         USETW(req.wValue, 0);
  533         USETW(req.wIndex, 5);
  534         USETW(req.wLength, sizeof(wAvail));
  535         err = usbd_do_request(udev, NULL, &req, &wAvail);
  536         if (err) {
  537                 goto done;
  538         }
  539         DPRINTF("avail=%d\n", UGETW(wAvail));
  540 #endif
  541 
  542         DPRINTF("done\n");
  543 done:
  544         return (err);
  545 }
  546 
  547 static void
  548 uvisor_cfg_open(struct ucom_softc *ucom)
  549 {
  550         return;
  551 }
  552 
  553 static void
  554 uvisor_cfg_close(struct ucom_softc *ucom)
  555 {
  556         struct uvisor_softc *sc = ucom->sc_parent;
  557         uint8_t buffer[UVISOR_CONNECTION_INFO_SIZE];
  558         struct usb_device_request req;
  559         usb_error_t err;
  560 
  561         req.bmRequestType = UT_READ_VENDOR_ENDPOINT;    /* XXX read? */
  562         req.bRequest = UVISOR_CLOSE_NOTIFICATION;
  563         USETW(req.wValue, 0);
  564         USETW(req.wIndex, 0);
  565         USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
  566 
  567         err = ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
  568             &req, buffer, 0, 1000);
  569         if (err) {
  570                 DPRINTFN(0, "close notification failed, error=%s\n",
  571                     usbd_errstr(err));
  572         }
  573 }
  574 
  575 static void
  576 uvisor_start_read(struct ucom_softc *ucom)
  577 {
  578         struct uvisor_softc *sc = ucom->sc_parent;
  579 
  580         usbd_transfer_start(sc->sc_xfer[UVISOR_BULK_DT_RD]);
  581 }
  582 
  583 static void
  584 uvisor_stop_read(struct ucom_softc *ucom)
  585 {
  586         struct uvisor_softc *sc = ucom->sc_parent;
  587 
  588         usbd_transfer_stop(sc->sc_xfer[UVISOR_BULK_DT_RD]);
  589 }
  590 
  591 static void
  592 uvisor_start_write(struct ucom_softc *ucom)
  593 {
  594         struct uvisor_softc *sc = ucom->sc_parent;
  595 
  596         usbd_transfer_start(sc->sc_xfer[UVISOR_BULK_DT_WR]);
  597 }
  598 
  599 static void
  600 uvisor_stop_write(struct ucom_softc *ucom)
  601 {
  602         struct uvisor_softc *sc = ucom->sc_parent;
  603 
  604         usbd_transfer_stop(sc->sc_xfer[UVISOR_BULK_DT_WR]);
  605 }
  606 
  607 static void
  608 uvisor_write_callback(struct usb_xfer *xfer, usb_error_t error)
  609 {
  610         struct uvisor_softc *sc = usbd_xfer_softc(xfer);
  611         struct usb_page_cache *pc;
  612         uint32_t actlen;
  613         uint8_t x;
  614 
  615         switch (USB_GET_STATE(xfer)) {
  616         case USB_ST_SETUP:
  617         case USB_ST_TRANSFERRED:
  618 tr_setup:
  619                 for (x = 0; x != UVISOROFRAMES; x++) {
  620                         usbd_xfer_set_frame_offset(xfer, 
  621                             x * UVISOROBUFSIZE, x);
  622 
  623                         pc = usbd_xfer_get_frame(xfer, x);
  624                         if (ucom_get_data(&sc->sc_ucom, pc, 0,
  625                             UVISOROBUFSIZE, &actlen)) {
  626                                 usbd_xfer_set_frame_len(xfer, x, actlen);
  627                         } else {
  628                                 break;
  629                         }
  630                 }
  631                 /* check for data */
  632                 if (x != 0) {
  633                         usbd_xfer_set_frames(xfer, x);
  634                         usbd_transfer_submit(xfer);
  635                 }
  636                 break;
  637 
  638         default:                        /* Error */
  639                 if (error != USB_ERR_CANCELLED) {
  640                         /* try to clear stall first */
  641                         usbd_xfer_set_stall(xfer);
  642                         goto tr_setup;
  643                 }
  644                 break;
  645         }
  646 }
  647 
  648 static void
  649 uvisor_read_callback(struct usb_xfer *xfer, usb_error_t error)
  650 {
  651         struct uvisor_softc *sc = usbd_xfer_softc(xfer);
  652         struct usb_page_cache *pc;
  653         int actlen;
  654 
  655         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
  656 
  657         switch (USB_GET_STATE(xfer)) {
  658         case USB_ST_TRANSFERRED:
  659                 pc = usbd_xfer_get_frame(xfer, 0);
  660                 ucom_put_data(&sc->sc_ucom, pc, 0, actlen);
  661 
  662         case USB_ST_SETUP:
  663 tr_setup:
  664                 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
  665                 usbd_transfer_submit(xfer);
  666                 return;
  667 
  668         default:                        /* Error */
  669                 if (error != USB_ERR_CANCELLED) {
  670                         /* try to clear stall first */
  671                         usbd_xfer_set_stall(xfer);
  672                         goto tr_setup;
  673                 }
  674                 return;
  675         }
  676 }

Cache object: a5ea4c42f44c5c36301077522944330c


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