Subject: Help Wanted with USB Code
To: None <tech-kern@netbsd.org>
From: Curt Sampson <cjs@cynic.net>
List: tech-kern
Date: 12/10/2001 00:53:23
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