ugen & uhci hang on 5.3-RELEASE and 6.0-CURRENT
Adam Kropelin
akropel1 at rochester.rr.com
Wed Mar 16 17:34:22 PST 2005
Hans Petter Selasky wrote:
> On Wednesday 16 March 2005 01:32, Adam Kropelin wrote:
>>
>> kernel: usbd_start_next: pipe=0xc1a83c00, xfer=0
>> kernel: usb_transfer_complete: pipe=0xc1f6cb80 xfer=0xc1a9d400
>> status=0 actlen=5
>> kernel: usb_transfer_complete: repeat=1 new head=0xc1a9d400
>> kernel: usb0: host controller process error
>> kernel: usb0: host controller halted
>>
>
> According to your logs, the USB driver stops after a device interrupt
> transfer. This might be an indication that the QH's must be dequeued
> from the schedule before they are updated.
>
> Could you have tried my USB driver and see if the problem goes away?
>
> Download the three files below into a new directory and type
> "make install" (to uninstall type "make deinstall")
> http://home.c2i.net/hselasky/isdn4bsd/privat/usb/Makefile
> http://home.c2i.net/hselasky/isdn4bsd/privat/usb/new_usb_1_5_4.diff.bz2
> http://home.c2i.net/hselasky/isdn4bsd/privat/usb/new_usb_1_5_4.tar.bz2
I gave your driver a run and it seems all of the USB_DO_REQUEST ioctls are
now failing with EPERM. I am playing some games with transfer lengths that
might have an affect on things. I've included the code I use for GetReport
requests which documents the length munging.
--Adam
/*
* Fetch a report from a device given an fd for the device's control
* endpoint, the populated item structure describing the report, and
* a data buffer in which to store the result. Returns report length
* (in bytes) on success and -1 on failure.
*/
int hidu_get_report(int fd, hid_item_t* item, unsigned char* data)
{
int rc, len;
struct usb_ctl_request req;
unsigned char buf[100];
Dmsg4(200, "get_report: id=0x%02x, kind=%d, length=%d pos=%d\n",
item->report_ID, item->kind, item->report_size, item->pos);
#if 0
/*
* Length is report size (in bits) rounded up to nearest
* byte, plus one additional byte for the report tag.
*/
len = (item->report_size+7)/8+1;
#else
/*
* Some reports seem to be longer than the above calculation says.
* Either APC has bogus length fields in their descriptors or
* libusbhid is buggy. The FreeBSD kernel corrupts its memory when
* this happens, resulting in a panic shortly thereafter. Work around
* the problem by using a plenty large buffer and letting the transfer
* return less than was requested.
*/
len = sizeof(buf);
#endif
memset(buf, 0, sizeof(buf));
req.ucr_flags = USBD_SHORT_XFER_OK;
req.ucr_actlen = 0;
req.ucr_addr = 0;
req.ucr_data = buf;
req.ucr_request.bmRequestType = UT_READ_CLASS_INTERFACE;
req.ucr_request.bRequest = UR_GET_REPORT;
USETW(req.ucr_request.wValue, ((item->kind+1) << 8) | item->report_ID);
USETW(req.ucr_request.wIndex, 0);
USETW(req.ucr_request.wLength, len);
Dmsg2(200, "get_report: wValue=0x%04x, wLength=%d\n",
UGETW(req.ucr_request.wValue), UGETW(req.ucr_request.wLength));
rc = ioctl(fd, USB_DO_REQUEST, &req);
if (rc)
{
Dmsg1(100, "Error getting report: %s\n", strerror(-rc));
return -1;
}
if (debug_level >= 300)
{
printf( "%02x: ", item->report_ID);
for (rc=0; rc<req.ucr_actlen; rc++)
printf("%02x,", buf[rc]);
printf("\n");
}
memcpy(data, buf, req.ucr_actlen);
return req.ucr_actlen;
}
More information about the freebsd-usb
mailing list