Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Bunch of changes to make the Palm Tungsten T work:



details:   https://anonhg.NetBSD.org/src/rev/690d8100f137
branches:  trunk
changeset: 550281:690d8100f137
user:      nathanw <nathanw%NetBSD.org@localhost>
date:      Sun Aug 03 21:59:26 2003 +0000

description:
Bunch of changes to make the Palm Tungsten T work:

* Mark the actual Handspring Visor as type "VISOR" and all others
  "PALM4" (notably, the Sony Clie 41 changes from Visor-type to
  Palm4-type).

* For Palm4-type devices, use the GET_PALM_CONNECTION_INFORMATION
  query instead of the GET_CONNECTION_INFORMATION query, and interpret
  the returned data structure appropriately. This permits attaching a
  ucom device to newer devices such as the Tungsten T that do not
  support the Visor-style query (data structure definition gleaned
  from the Linux 2.4.21 visor.c).

* Crank down UVISORBUFSIZE from 1024 to 64 to avoid a problem where
  the Palm device and the USB host controller deadlock. The USB host
  controller is expecting an early-end-of-transmission packet with 0
  data, and the Palm doesn't send one because it's already
  communicated the amount of data it's going to send in a header
  (which ucom/uvisor are oblivious to). This is the problem that has
  been known on the pilot-link lists as the "[Free]BSD USB problem",
  but not understood.

  XXX It would be better for the Palm protocol to be handled entirely
  in userland via ugen, since the serial protocol abstraction isn't
  really adequate for the amount of structure that's here, and the
  64-byte limit is just a workaround. The pilot-link tools aren't up
  to the task yet, though.

diffstat:

 sys/dev/usb/uvisor.c |  195 ++++++++++++++++++++++++++++++++------------------
 1 files changed, 123 insertions(+), 72 deletions(-)

diffs (294 lines):

diff -r 59f1380d252e -r 690d8100f137 sys/dev/usb/uvisor.c
--- a/sys/dev/usb/uvisor.c      Sun Aug 03 21:40:13 2003 +0000
+++ b/sys/dev/usb/uvisor.c      Sun Aug 03 21:59:26 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvisor.c,v 1.20 2003/04/11 01:30:10 simonb Exp $       */
+/*     $NetBSD: uvisor.c,v 1.21 2003/08/03 21:59:26 nathanw Exp $      */
 
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvisor.c,v 1.20 2003/04/11 01:30:10 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvisor.c,v 1.21 2003/08/03 21:59:26 nathanw Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -117,10 +117,23 @@
  * Unknown PalmOS stuff.
  */
 #define UVISOR_GET_PALM_INFORMATION            0x04
-#define UVISOR_GET_PALM_INFORMATION_LEN                0x14
+#define UVISOR_GET_PALM_INFORMATION_LEN                0x44
+
+struct uvisor_palm_connection_info {
+       uByte   num_ports;
+       uByte   endpoint_numbers_different;
+       uWord   reserved1;
+       struct {
+               uDWord  port_function_id;
+               uByte   port;
+               uByte   end_point_info;
+               uWord   reserved;
+       } connections[UVISOR_MAX_CONN];
+};
 
 
-#define UVISORIBUFSIZE 1024
+
+#define UVISORIBUFSIZE 64
 #define UVISOROBUFSIZE 1024
 
 struct uvisor_softc {
@@ -137,7 +150,8 @@
 };
 
 Static usbd_status uvisor_init(struct uvisor_softc *,
-                              struct uvisor_connection_info *);
+                              struct uvisor_connection_info *,
+                              struct uvisor_palm_connection_info *);
 
 Static void uvisor_close(void *, int);
 
@@ -157,9 +171,11 @@
        struct usb_devno        uv_dev;
        u_int16_t               uv_flags;
 #define PALM4  0x0001
+#define VISOR  0x0002
+
 };
 static const struct uvisor_type uvisor_devs[] = {
-       {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR }, 0 },
+       {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR }, VISOR },
        {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO }, PALM4 },
        {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M500 }, PALM4 },
        {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M505 }, PALM4 },
@@ -171,7 +187,7 @@
        {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_T }, PALM4 },
        {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE }, PALM4 },
        {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40 }, PALM4 },
-       {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41 }, 0 },
+       {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41 }, PALM4 },
        {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360 }, PALM4 },
        {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60 }, PALM4 },
 /*     {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_25 }, PALM4 },*/
@@ -201,6 +217,7 @@
        usbd_interface_handle iface;
        usb_interface_descriptor_t *id;
        struct uvisor_connection_info coninfo;
+       struct uvisor_palm_connection_info palmconinfo;
        usb_endpoint_descriptor_t *ed;
        char devinfo[1024];
        char *devname = USBDEVNAME(sc->sc_dev);
@@ -231,6 +248,12 @@
 
        sc->sc_flags = uvisor_lookup(uaa->vendor, uaa->product)->uv_flags;
 
+       if ((sc->sc_flags & (VISOR | PALM4)) == 0) {
+               printf("%s: init failed, device type is neither visor nor palm\n", 
+                   USBDEVNAME(sc->sc_dev));
+               goto bad;
+       }
+
        id = usbd_get_interface_descriptor(iface);
 
        sc->sc_udev = dev;
@@ -245,7 +268,7 @@
        uca.methods = &uvisor_methods;
        uca.arg = sc;
 
-       err = uvisor_init(sc, &coninfo);
+       err = uvisor_init(sc, &coninfo, &palmconinfo);
        if (err) {
                printf("%s: init failed, %s\n", USBDEVNAME(sc->sc_dev),
                       usbd_errstr(err));
@@ -255,53 +278,86 @@
        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                           USBDEV(sc->sc_dev));
 
-       sc->sc_numcon = UGETW(coninfo.num_ports);
-       if (sc->sc_numcon > UVISOR_MAX_CONN)
-               sc->sc_numcon = UVISOR_MAX_CONN;
+       if (sc->sc_flags & VISOR) {
+               sc->sc_numcon = UGETW(coninfo.num_ports);
+               if (sc->sc_numcon > UVISOR_MAX_CONN)
+                       sc->sc_numcon = UVISOR_MAX_CONN;
 
-       /* Attach a ucom for each connection. */
-       for (i = 0; i < sc->sc_numcon; ++i) {
-               switch (coninfo.connections[i].port_function_id) {
-               case UVISOR_FUNCTION_GENERIC:
-                       uca.info = "Generic";
-                       break;
-               case UVISOR_FUNCTION_DEBUGGER:
-                       uca.info = "Debugger";
-                       break;
-               case UVISOR_FUNCTION_HOTSYNC:
-                       uca.info = "HotSync";
-                       break;
-               case UVISOR_FUNCTION_REMOTE_FILE_SYS:
-                       uca.info = "Remote File System";
-                       break;
-               default:
-                       uca.info = "unknown";
-                       break;
+               /* Attach a ucom for each connection. */
+               for (i = 0; i < sc->sc_numcon; ++i) {
+                       switch (coninfo.connections[i].port_function_id) {
+                       case UVISOR_FUNCTION_GENERIC:
+                               uca.info = "Generic";
+                               break;
+                       case UVISOR_FUNCTION_DEBUGGER:
+                               uca.info = "Debugger";
+                               break;
+                       case UVISOR_FUNCTION_HOTSYNC:
+                               uca.info = "HotSync";
+                               break;
+                       case UVISOR_FUNCTION_REMOTE_FILE_SYS:
+                               uca.info = "Remote File System";
+                               break;
+                       default:
+                               uca.info = "unknown";
+                               break;
+                       }
+                       port = coninfo.connections[i].port;
+                       uca.portno = port;
+                       uca.bulkin = port | UE_DIR_IN;
+                       uca.bulkout = port | UE_DIR_OUT;
+                       /* Verify that endpoints exist. */
+                       hasin = 0;
+                       hasout = 0;
+                       for (j = 0; j < id->bNumEndpoints; j++) {
+                               ed = usbd_interface2endpoint_descriptor(iface, j);
+                               if (ed == NULL)
+                                       break;
+                               if (UE_GET_ADDR(ed->bEndpointAddress) == port &&
+                                   (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
+                                       if (UE_GET_DIR(ed->bEndpointAddress)
+                                           == UE_DIR_IN)
+                                               hasin++;
+                                       else
+                                               hasout++;
+                               }
+                       }
+                       if (hasin == 1 && hasout == 1)
+                               sc->sc_subdevs[i] = config_found_sm(self, &uca,
+                                   ucomprint, ucomsubmatch);
+                       else
+                               printf("%s: no proper endpoints for port %d (%d,%d)\n",
+                                   USBDEVNAME(sc->sc_dev), port, hasin, hasout);
                }
-               port = coninfo.connections[i].port;
-               uca.portno = port;
-               uca.bulkin = port | UE_DIR_IN;
-               uca.bulkout = port | UE_DIR_OUT;
-               /* Verify that endpoints exist. */
-               for (hasin = hasout = j = 0; j < id->bNumEndpoints; j++) {
-                       ed = usbd_interface2endpoint_descriptor(iface, j);
-                       if (ed == NULL)
-                               break;
-                       if (UE_GET_ADDR(ed->bEndpointAddress) == port &&
-                           (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
-                               if (UE_GET_DIR(ed->bEndpointAddress)
-                                   == UE_DIR_IN)
-                                       hasin++;
-                               else
-                                       hasout++;
+
+       } else {
+               sc->sc_numcon = palmconinfo.num_ports;
+               if (sc->sc_numcon > UVISOR_MAX_CONN)
+                       sc->sc_numcon = UVISOR_MAX_CONN;
+
+               /* Attach a ucom for each connection. */
+               for (i = 0; i < sc->sc_numcon; ++i) {
+                       /* 
+                        * XXX this should copy out 4-char string from the 
+                        * XXX port_function_id, but where would the string go?
+                        * XXX uca.info is a const char *, not an array.
+                        */
+                       uca.info = "sync";
+                       uca.portno = i;
+                       if (palmconinfo.endpoint_numbers_different) {
+                               port = palmconinfo.connections[i].end_point_info;
+                               uca.bulkin = (port >> 4) | UE_DIR_IN;
+                               uca.bulkout = (port & 0xf) | UE_DIR_OUT;
+                       } else {
+                               port = palmconinfo.connections[i].port;
+                               uca.bulkin = port | UE_DIR_IN;
+                               uca.bulkout = port | UE_DIR_OUT;
                        }
-               }
-               if (hasin == 1 && hasout == 1)
                        sc->sc_subdevs[i] = config_found_sm(self, &uca,
                            ucomprint, ucomsubmatch);
-               else
-                       printf("%s: no proper endpoints for port %d (%d,%d)\n",
-                           USBDEVNAME(sc->sc_dev), port, hasin, hasout);
+
+                           
+               }
        }
 
        USB_ATTACH_SUCCESS_RETURN;
@@ -358,41 +414,36 @@
 }
 
 usbd_status
-uvisor_init(struct uvisor_softc *sc, struct uvisor_connection_info *ci)
+uvisor_init(struct uvisor_softc *sc, struct uvisor_connection_info *ci,
+    struct uvisor_palm_connection_info *cpi)
 {
        usbd_status err;
        usb_device_request_t req;
        int actlen;
        uWord avail;
-       char buffer[256];
 
-       DPRINTF(("uvisor_init: getting connection info\n"));
-       req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
-       req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
-       USETW(req.wValue, 0);
-       USETW(req.wIndex, 0);
-       USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
-       err = usbd_do_request_flags(sc->sc_udev, &req, ci,
-                 USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
-       if (err)
-               return (err);
+       if (sc->sc_flags & VISOR) {
+               DPRINTF(("uvisor_init: getting Visor connection info\n"));
+               req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
+               req.bRequest = UVISOR_GET_CONNECTION_INFORMATION;
+               USETW(req.wValue, 0);
+               USETW(req.wIndex, 0);
+               USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
+               err = usbd_do_request_flags(sc->sc_udev, &req, ci,
+                   USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
+               if (err)
+                       return (err);
+       }
 
        if (sc->sc_flags & PALM4) {
-               /* Palm OS 4.0 Hack */
+               DPRINTF(("uvisor_init: getting Palm connection info\n"));
                req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
                req.bRequest = UVISOR_GET_PALM_INFORMATION;
                USETW(req.wValue, 0);
                USETW(req.wIndex, 0);
                USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
-               err = usbd_do_request(sc->sc_udev, &req, buffer);
-               if (err)
-                       return (err);
-               req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
-               req.bRequest = UVISOR_GET_PALM_INFORMATION;
-               USETW(req.wValue, 0);
-               USETW(req.wIndex, 0);
-               USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
-               err = usbd_do_request(sc->sc_udev, &req, buffer);
+               err = usbd_do_request_flags(sc->sc_udev, &req, cpi,
+                   USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT);
                if (err)
                        return (err);
        }



Home | Main Index | Thread Index | Old Index