Subject: Re: Help Wanted with USB Code
To: Curt Sampson <cjs@cynic.net>
From: Lennart Augustsson <lennart@augustsson.net>
List: tech-kern
Date: 12/09/2001 17:42:06
It looks like the Linux code sets wLength to 0x14 whereas you set it to 250.

    -- Lennart


Curt Sampson wrote:

> Problem summary: I'm a loser who doesn't know his back-end from
> his front-end when it comes to our USB subsystem, so I need help
> doing something fairly trivial.
>
> Details:
>
> I just bought a Sony Clie 600 (the Japanese version of the 610).
> It comes with a USB cradle which seems mostly Visor-compatable.
> However, there are some tweaks needed to get it (and apparently
> any of the USB-cradle PalmOS 4.x devices) to work. Since the Linux
> guys seem to have it going, I tried to port their patches to NetBSD.
>
> What I'm stuck on at the moment is some "unknown data" that apparently
> need to be transferred before normal visor-type operations can
> start. The Linux driver does this:
>
>         response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION,
>                                         0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
>         if (response < 0) {
>                 err(__FUNCTION__ " - error getting connection information");
>         } else {
>                 struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer;
>                 char *string;
>
>                 le16_to_cpus(&connection_info->num_ports);
>                 info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports);
>                 for (i = 0; i < connection_info->num_ports; ++i) {
>                         switch (connection_info->connections[i].port_function_id) {
>                                 case VISOR_FUNCTION_GENERIC:
>                                         string = "Generic";
>                                         break;
>                                 case VISOR_FUNCTION_DEBUGGER:
>                                         string = "Debugger";
>                                         break;
>                                 case VISOR_FUNCTION_HOTSYNC:
>                                         string = "HotSync";
>                                         break;
>                                 case VISOR_FUNCTION_CONSOLE:
>                                         string = "Console";
>                                         break;
>                                 case VISOR_FUNCTION_REMOTE_FILE_SYS:
>                                         string = "Remote File System";
>                                         break;
>                                 default:
>                                         string = "unknown";
>                                         break;
>                         }
>                         info("%s: port %d, is for %s use and is bound to ttyUSB%d", serial->type->name, connection_info->connections[i].port, string, serial->minor + i);
>                 }
>         }
>
>         if (serial->dev->descriptor.idVendor == PALM_VENDOR_ID) {
>                 /* Palm USB Hack */
>                 response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
>                                             PALM_GET_SOME_UNKNOWN_INFORMATION,
>                                             0xc2, 0x0000, 0x0000, transfer_buffer,
>                                             0x14, 300);
>                 if (response < 0) {
>                         err(__FUNCTION__ " - error getting first unknown palm command");
>                 } else {
>                         usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
>                 }
>                 response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
>                                             PALM_GET_SOME_UNKNOWN_INFORMATION,
>                                             0xc2, 0x0000, 0x0000, transfer_buffer,
>                                             0x14, 300);
>                 if (response < 0) {
>                         err(__FUNCTION__ " - error getting second unknown palm command");
>                 } else {
>                         usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
>                 }
>         }
>
>         /* ask for the number of bytes available, but ignore the response as it is broken */
>         response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE,
>                                         0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
>         if (response < 0) {
>                 err(__FUNCTION__ " - error getting bytes available request");
>         }
>
> The "Palm USB Hack" portion is what I'm attempting to emulate at
> the moment. However, with this code:
>
>         /* (Junkbuf is a 250 byte automatic char[] (i.e., on the stack).) */
>
>         if ((vendor == USB_VENDOR_PALM) || (vendor == USB_VENDOR_SONY))
>         {
>                 /*
>                  * XXX In the Linux driver comments, this has been claimed at
>                  * various times to be either a Palm USB hack or a PalmOS 4.0
>                  * hack. But even when claimed to be a 4.0 hack, it's also
>                  * being applied to PalmOS 3.5 devices (the 3.5 Clie and maybe
>                  * the m500, if that's 3.5). This needs to be tested with a 3.5
>                  * USB device to see if it really works with that.
>                  */
>                 DPRINTF(("uvisor_init: PalmOS USB/4.0 hack\n"));
>                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
>                 req.bRequest = UVISOR_GET_SOME_UNKNOWN_INFORMATION;
>                 USETW(req.wValue, 0);
>                 USETW(req.wIndex, 0);
>                 USETW(req.wLength, sizeof junkbuf);
>                 err = usbd_do_request(sc->sc_udev, &req, &junkbuf);
>                 if (err) {
>                         DPRINTF(("uvisor_init: unknown 1 failed: %d", err));
>                         return (err);
>                 }
>                 DPRINTF(("uvisor_init: unknown data 1\n"));
>
>                 req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
>                 req.bRequest = UVISOR_GET_SOME_UNKNOWN_INFORMATION;
>                 USETW(req.wValue, 0);
>                 USETW(req.wIndex, 0);
>                 USETW(req.wLength, sizeof junkbuf);
>                 err = usbd_do_request(sc->sc_udev, &req, &junkbuf);
>                 if (err) {
>                         DPRINTF(("uvisor_init: unknown 2 failed: %d", err));
>                         return (err);
>                 }
>                 DPRINTF(("uvisor_init: unknown data 2\n"));
>         }
>
> inserted between the "getting connection info" and "getting available
> bytes" portion of uvisor.c (around line 375), I get
>
>     uvisor0: Palm, Inc. Palm Handheld, rev 1.00/1.00, addr 2
>     uvisor_init: getting connection info
>     usb_schedsoftintr: polling=0
>     uvisor_init: PalmOS USB/4.0 hack
>     usb_schedsoftintr: polling=0
>     usb_schedsoftintr: polling=0
>     uvisor_init: unknown 1 failed: 17
>     uvisor0: init failed, STALLED
>     uvisor_attach: ATTACH ERROR
>
> Can someone throw me a bone and tell me what I'm doing wrong, here?
>
> And while we're at it, what's the deal with the "uhub0: device
> problem, disabling port n" messages? I seem to get a lot of these
> with various unsupported devices, and looking at the code it makes
> it look like the device just isn't responding to a status request.
> Is there something more I can do (under NetBSD) to figure out why
> these devices aren't supported? Or is this a "run it under Windows
> with the USB sniffer" kind of situation?
>
> cjs
> --
> Curt Sampson  <cjs@cynic.net>   917 532 4208   http://www.netbsd.org
>     Don't you know, in this new Dark Age, we're all light.  --XTC