HID OUT endpoint in a loop

Technical questions regarding the XTC tools and programming with XMOS.
genap
Experienced Member
Posts: 99
Joined: Sat Aug 31, 2013 11:23 pm

HID OUT endpoint in a loop

Post by genap »

Hello,
I am using HID communication (IN and OUT interrupt endpoints) in a main loop of my custom code. It's supposed to check for OUT messages every loop iteration.
The code looks like this:

Code: Select all

while (1)
{
  /* Receive a buffer (512-bytes) of data from the host */
  host_transfer_length = XUD_GetBuffer(ep_from_host, (ubuf, char[HID_BUFFER_SIZE*4]));
  if(host_transfer_length < 0) 
  {
      XUD_ResetEndpoint(ep_from_host, ep_to_host);
  }
  else if (host_transfer_length > 0)
  {
    Develop_hid();

    /* Send the modified buffer back to the host */
    host_transfer_length = XUD_SetBuffer(ep_to_host, (ubuf, char[HID_BUFFER_SIZE*4]), host_transfer_length);
    if(host_transfer_length < 0)
      XUD_ResetEndpoint(ep_from_host, ep_to_host);
  }
    
  /*** Custom code **/
  /*.........................*/
  /*****************/
  
}
The BIG problem is that Custom code executes only when message is received on OUT endpoint.
The XUD_GetBuffer() blocks execution waiting for a message.
Is there any way around it (I don't have any extra cores available)?
Like using a streaming channel or something like that.
But I have no idea how to do it in this case.

Please advise.
Thank you,
Gennady


User avatar
Ross
XCore Expert
Posts: 968
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

There is a section in the XUD documentation entitled "Advanced Usage" I think this should include what you are trying to do...

It involves using a select statement and a some provided select handler functions. E.g:

Code: Select all

ExampleEndpoint(chanend c_ep_out)
{
    unsigned char rxBuffer [1024];
    int length, 
    XUD_Result_t result;
     
    XUD_ep ep_out = XUD_InitEp(c_ep_out); 

   /* Mark OUT endpoint as ready to receive */ 
   XUD_SetReady_Out(ep_out , rxBuffer); 

  while (1) 
  {
       select 
       {
           case XUD_GetData_Select(c_ep_out , ep_out, length, result):

              /* Packet from host recieved */
              for(int i = 0; i< length; i++) 
              {
                  /* Process packet ... */ 
              }
              /* Mark EP as ready again */ 
              XUD_SetReady_Out(ep_out , rxBuffer); 

              break;

       case /* some other case... */
               
          break;

      default:
           / * no events pending - run some other code.. */
          break;
    }
           
} 
genap
Experienced Member
Posts: 99
Joined: Sat Aug 31, 2013 11:23 pm

Post by genap »

Hi Ross,
thank you for the reply.

I've already implemented the routine with the select you mention.
Seems like it works fine, and came just in time :)
The one thing I needed to do which is not in a document -
after development of the incoming message I need to put XUD_SetReady_In(),
otherwise message will not be sent on the IN endpoint.

Also I couldn't figure out if I can change the size of a message I send on the IN endpoint.
It works only if I use in the XUD_SetReady_In() the packet size set in the HID descriptor.

other than that it's exactly what I need.
Gennady
User avatar
Ross
XCore Expert
Posts: 968
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

genap wrote:Hi Ross,
thank you for the reply.

I've already implemented the routine with the select you mention.
Seems like it works fine, and came just in time :)
:)
genap wrote: The one thing I needed to do which is not in a document -
after development of the incoming message I need to put XUD_SetReady_In(),
otherwise message will not be sent on the IN endpoint.
XUD_SetReady_In() is listed in the example and the API reference. Can you explain what you mean please?
genap wrote: Also I couldn't figure out if I can change the size of a message I send on the IN endpoint.
It works only if I use in the XUD_SetReady_In() the packet size set in the HID descriptor.

other than that it's exactly what I need.
Gennady
XUD_SetReady_In() takes a length parameter. If this doesn't match your HID descriptor you could upset the host driver - depends on its implementation really.
genap
Experienced Member
Posts: 99
Joined: Sat Aug 31, 2013 11:23 pm

Post by genap »

Ross wrote: XUD_SetReady_In() is listed in the example and the API reference. Can you explain what you mean please?
In the example XUD_SetReady_In() is used as:

Code: Select all

case XUD_SetData_Select():
   . . . . . . . . . . . . . .
   XUD_SetReady_In();
   break;

If I use it as in the example, IN endpoint continuously sends non-stop messages.
I think it reenables sending every time the message is sent.

So instead I insert XUD_SetReady_In() only when I need to send a message on the IN endpoint.
User avatar
Ross
XCore Expert
Posts: 968
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

genap wrote: So instead I insert XUD_SetReady_In() only when I need to send a message on the IN endpoint.
Ah I see. Yes this the correct usage.