hi:
I'm using am3352 connect my device whit 18 hids throught USB Hub,but only 9
hids can be read/write while my app running.When my app read/write the tenth
hid,it always return -28 in the linux kernel.Actually,while read/write the tenth
hid: the function "musb_schedule" in the drivers/usb/musb/musb_host.c always
return -ENOSPC.
Here is the "musb_schedule" function:
/* schedule nodes correspond to peripheral endpoints, like an OHCI QH.
* the software schedule associates multiple such nodes with a given
* host side hardware endpoint + direction; scheduling may activate
* that hardware endpoint.
*/
static int
musb_schedule(
struct musb *musb,
struct musb_qh *qh,
int is_in)
{
int idle;
int best_diff;
int best_end, epnum;
struct musb_hw_ep *hw_ep = NULL;
struct list_head *head = NULL;
u8 toggle;
u8 txtype;
struct urb *urb = next_urb(qh);
/* use fixed hardware for control and bulk */
if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
head = &musb->control;
hw_ep = musb->control_ep;
goto success;
}
/* else, periodic transfers get muxed to other endpoints */
/*
* We know this qh hasn't been scheduled, so all we need to do
* is choose which hardware endpoint to put it on ...
*
* REVISIT what we really want here is a regular schedule tree
* like e.g. OHCI uses.
*/
best_diff = 4096;
best_end = -1;
for (epnum = 1, hw_ep = musb->endpoints + 1;
epnum < musb->nr_endpoints;
epnum++, hw_ep++) {
int diff;
if (musb_ep_get_qh(hw_ep, is_in) != NULL)
continue;
if (hw_ep == musb->bulk_ep)
continue;
if (is_in)
diff = hw_ep->max_packet_sz_rx;
else
diff = hw_ep->max_packet_sz_tx;
diff -= (qh->maxpacket * qh->hb_mult);
if (diff >= 0 && best_diff > diff) {
/*
* Mentor controller has a bug in that if we schedule
* a BULK Tx transfer on an endpoint that had earlier
* handled ISOC then the BULK transfer has to start on
* a zero toggle. If the BULK transfer starts on a 1
* toggle then this transfer will fail as the mentor
* controller starts the Bulk transfer on a 0 toggle
* irrespective of the programming of the toggle bits
* in the TXCSR register. Check for this condition
* while allocating the EP for a Tx Bulk transfer. If
* so skip this EP.
*/
hw_ep = musb->endpoints + epnum;
toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in);
txtype = (musb_readb(hw_ep->regs, MUSB_TXTYPE)
>> 4) & 0x3;
if (!is_in && (qh->type == USB_ENDPOINT_XFER_BULK) &&
toggle && (txtype == USB_ENDPOINT_XFER_ISOC))
continue;
best_diff = diff;
best_end = epnum;
}
}
/* use bulk reserved ep1 if no other ep is free */
if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
hw_ep = musb->bulk_ep;
if (is_in)
head = &musb->in_bulk;
else
head = &musb->out_bulk;
/* Enable bulk RX/TX NAK timeout scheme when bulk requests are
* multiplexed. This scheme doen't work in high speed to full
* speed scenario as NAK interrupts are not coming from a
* full speed device connected to a high speed device.
* NAK timeout interval is 8 (128 uframe or 16ms) for HS and
* 4 (8 frame or 8ms) for FS device.
*/
if (qh->dev)
qh->intv_reg =
(USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4;
goto success;
} else if (best_end < 0) {
return -ENOSPC;
}
idle = 1;
qh->mux = 0;
hw_ep = musb->endpoints + best_end;
dev_dbg(musb->controller, "qh %p periodic slot %d\n", qh, best_end);
success:
if (head) {
idle = list_empty(head);
list_add_tail(&qh->ring, head);
qh->mux = 1;
}
qh->hw_ep = hw_ep;
qh->hep->hcpriv = qh;
if (idle)
musb_start_urb(musb, is_in, qh);
return 0;
}
My linux kernel is:linux-3.2.0-psp04.06.00.11-58bc965 and my app uses libusb-1.0
to read/write hids.My device works nornally in am3517.Now I don't kown how to solve
this probrom,had somebody met this probrom?Is it bsp bugs?Or other reason ? thanks!