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