This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

am3352 usb can not read/write 18 hids

Other Parts Discussed in Thread: AM3352, AM3517

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!

  • Did you use the EHCI port or OTG port on AM3517?
    AM335x use MUSB controller, which does not support such use case, that is why musb_schedule() returns "NO SPACE" error.
  • Hi,thanks for your reply.I use EHCI port on AM3517 and in AM3352,my usb topology is :

    AM3352_MUSB ---->A USB hub with 4 ports ---->each port connect another USB hub with 7 ports ---->so I can connect 28 hids,bu I only connect 18 hids.

    You said that "AM335x use MUSB controller, which does not support such use case, that is why musb_schedule() returns "NO SPACE" error",is it meanning thart my usb topology can not be supported in AM3352 but works  in AM3517?The function musb_schedule() returns "NO SPACE" error,is it meaning that no 'transmit endpoint' or no 'receive endpoint' for comminucation?Can you give me some advice for using my usb topology in AM3352,thanks!

  • No, this use case is not supported by AM335x. It is not about its topology, but MUSB controller on AM335x has limited resource to support these many HID devices, each of them requires one RX Interrupt endpoint.

    It might works with AM3517, because EHCI manages its internal resource completely different. By the way EHCI does not use musb drivers, so musb_schedule() is not called for EHCI at all.

    I would recommend you to move to other SoC, for example AM437x, which uses xHCI host controller. Please note that if you want to connect 28 HID devices to AM437x, you will have to use both xHCI controllers on AM437x.
  • OK,I get it .Thank you very much.