LPC11U24 control endpoint communication with linux host machine

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC11U24 control endpoint communication with linux host machine

3,810 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by saraswathi on Thu May 09 05:59:57 MST 2013
[SIZE=2]Hi,[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]I have a problem in LPC11U24 when it communicating with linux host.[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]I have configured the LPC11U24 in HID mode. I have a linux host, which needs to communicate with the device(LPC11U24) using standard libusb commands. when I try to send some data to device using the libusb API "libusb_control_transfer()" I am getting the error LIBUSB_ERROR_PIPE(if the control request was not supported by the device this error occurs). The libusb APIs use control endpoint. Eventhough LPC11U24 has a contol endpoint, the host is not able to communicate. I am using the HID sample code "USB_ROM_HID" from "LPC11Uxx LPCXpresso Examples". In this code no endpoints are registered with the core.
Is there any sample code which will communicate with the linux host via control endpoint? [/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]Can anyone help me on this?[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]With regards[/SIZE]
[SIZE=2]Saraswathi C[/SIZE]
0 Kudos
Reply
11 Replies

3,287 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by saraswathi on Thu May 23 23:27:00 MST 2013
[COLOR=black]Hi Tsuneo,[/COLOR]
[COLOR=black][/COLOR]
[COLOR=black]I am able to solve the reset issue.[/COLOR]
[COLOR=black][/COLOR]
[COLOR=black]Initially I was trying to reset the device as below:[/COLOR]
[COLOR=black]pUsbApi->hw->Connect(hUsb, 0);[/COLOR]
[COLOR=black]/* Watchdog reset instructions */[/COLOR]
[COLOR=black]But this didn't work.[/COLOR]
[COLOR=black][/COLOR]
[COLOR=black]Then I tried as below:[/COLOR]
[COLOR=black]LPC_USB->DEVCMDSTAT |= (0<<16);[/COLOR]
[COLOR=black]/*delay*/[/COLOR]
[COLOR=black]/* Watchdog reset instructions */[/COLOR]
[COLOR=black][/COLOR]
[COLOR=black]Now after reset, host is able to communicate with the device properly.[/COLOR]
[COLOR=black][/COLOR]
[COLOR=black]With regards[/COLOR]
[COLOR=black]Saraswathi C[/COLOR]
0 Kudos
Reply

3,287 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by saraswathi on Wed May 22 06:05:02 MST 2013
Hi Tsuneo,

Thanks alot for the deatailed explanation. It really helped me to understand the functionalities of the APIs.

I am working on the Watchdog timer reset issue and I will update status of this soon.

With regards
Saraswathi C
0 Kudos
Reply

3,287 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Tue May 21 01:20:00 MST 2013
Here are answers to your questions.


Quote:
USB_Configure_Event() - Why is this function required?


For practical HID implementation, the WriteEP() code in USB_Configure_Event() is not required.

USB_Configure_Event() is called by the stack when Set_Configuration request comes from host - ie. at the end of enumeration. By this call, stack enables the endpoints on the USB configuration (other than EP0). Therefore, this callback is a good place to initialize the endpoint-related context (variables, flags, etc.).

The USB_ROM_HID example puts the "first" input report into the interrupt IN endpoint here, by calling WriteEP(). When this report is sent to host, the stack calls HID_Ep_Hdlr( USB_EVT_IN ). This example puts another input report in HID_Ep_Hdlr() callback, by WriteEP(). When the second report is sent to host, the stack calls HID_Ep_Hdlr( USB_EVT_IN ) again. HID host driver repeatedly polls the interrupt IN endpoint in the interval specified on the endpoint descriptor (bInterval field). In this way, USB_Configure_Event() kicks this chained endpoint interrupts. The device responds to EVERY IN transaction from the host, continuously.

Anyway, this is a BAD manner to use HID, as I always accuse. The first BAD example was made by Keil. Many successors have followed, including NXP, Microchip, etc.

On the commercial HID implementation, like keyboard and mouse, you'll see that the device sends an input report just when user touches/releases key(s), moves mouse. These devices sends the report asynchronously, just when the report should be sent.

HID host driver (and host controller) repeatedly polls the interrupt IN endpoint for asynchronous transfer. By the USB spec, device IN endpoint can't initiate any transfer (transaction) by itself (until USB3.0). To implement asynchronous transfer, the IN endpoint should be polled by the host. Polling-IN transactions is the common USB practice to realize asynchronous transfer. There are many implementation of Polling-IN transactions, such as the bulk/interrupt IN endpoints of CDC, Printer, Still Image, CCID, etc. And the device is expected to put a transfer asynchronously, not continuously.

The coder of this example apparently doesn't know this USB practice. He should get more experience of practical USB implementation.


Quote:
If I comment the above function, the code will not work. Do you have an idea to solve this?


For practical implementation, you should call WriteEP() to the IN endpoint OUTSIDE of the HID_Ep_Hdlr(), just when your firmware likes to send the input report. ie. asynchronously.

For the OUT endpoint, HID_Ep_Hdlr() is called by the stack when a transaction (packet) comes from the host. In HID_Ep_Hdlr( USB_EVT_OUT ), your firmware reads out the packet using ReadEP(). It's so straightforward.

On the other hand for the IN endpoint, HID_Ep_Hdlr( USB_EVT_IN ) is called AFTER the packet is sent to host. Therefore, your firmware should puts the packet by WriteEP() outside of HID_Ep_Hdlr( USB_EVT_IN ). Otherwise, HID_Ep_Hdlr( USB_EVT_IN ) never occurs.

HID_Ep_Hdlr( USB_EVT_IN ) is available for these purposes:
a) Drop a flag which indicates that the IN endpoint is still occupied by the last packet.
b) Send the second and latter transactions (packets) of long transfer. (long transfer greater than 64 bytes is split into two or more transactions).


Quote:
Also, do you have an idea on calculating "ep_index" values for HID_EP_IN and
HID_EP_OUT endpoints for registering using the function pUsbApi->core->RegisterEpHandler(……)


"ep_index" expects PHYSICAL endpoint number, defined on "11.4.2 Fixed endpoint configuration" chapter of the LPC11Uxx User Manual. Your implementation is fine.


Quote:
After the reset USB is getting initialized and host is able to get the handle.


Isn't it a problem on the host side?
Does the host application really send the requests to the device?
Confirm it using a software sniffer on Linux.

Virtual USB Analyzer
http://vusb-analyzer.sourceforge.net

Tsuneo
0 Kudos
Reply

3,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Mon May 20 23:24:03 MST 2013
Sorry for my long absence,


Quote:
3)The control transfer function is giving me error while sending data from host to device.


I also confirmed this bug on the USB on-chip driver of LPC11Uxx.
These requests get STALL at the STATUS stage randomly.
- USB_ROM_HID: Set_Report
- USB_ROM_CDC: Set_Line_Coding

These symptom suggest that the bug lies in the Control Write process in the CORE ROM stack. To confirm it, I made a custom HID implementation using just HW and CORE ROM stack,  without HID ROM stack. This LPCXpresso project is attached to this post.

This implementation also suffered with this bug on Control Write transfer process.
And then I concluded that it's a bug on the CORE ROM stack. Maybe, an uninitialized variable would determine the STALL response of Control Write transfer process.

I'll post this bug to LPCWare | USB forum.

Tsuneo
0 Kudos
Reply

3,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by saraswathi on Mon May 20 06:48:39 MST 2013
Hi,

Once again I changed my design and now I am communicating between host and device using Control endpoint. After doing lot of modification to HID sample code, I am able to do bi-directional communication between host and device.

But now I am facing problem.
I have a situation where I need to do the reset of the device when it is connected to the host(with power). I am sending the command from host, and at device side I am using Watchdog timer for reset and I am able to do the device reset. After the reset USB is getting initialized and host is able to get the handle.
But host is not able to send the data to the device. This is because eventhough [B]USB_IRQn[/B] interrupt is enabled, [B]USB_IRQHandler()[/B] function is not executed. Along with this [B]HID_GetReport() [/B]and[B]HID_SetReport() [/B]functionsare not executed.

Is anyone know the reason for this?
Generally during USB initialization, all these functions are getting executed. Why is this not happening after Watchdog reset?

Can you please help me in solving this issue?

With regards
Saraswathi C
0 Kudos
Reply

3,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by saraswathi on Fri May 17 07:30:40 MST 2013
Hi Tsuneo,

Thank you for the reply.

I am planning to implement this on HID Interrupt endpoints. The reasons are,
1)I am not familiar with implementing vendor specific class and the user manual is not helping me in implementing this. Also, there is no sample code.
2)I have a restriction to use only libusb commands at host side.
3)The control transfer function is giving me error while sending data from host to device.


Hence I need your help in understanding one of the functions given in the sample code for HID interrupt transfer.

ErrorCode_t USB_Configure_Event (USBD_HANDLE_T hUsb) {
  USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*)hUsb;
  if (pCtrl->config_value) {                   /* Check if USB is configured */
    pUsbApi->hw->WriteEP(hUsb, HID_EP_IN, loopback_report, 1);
  }
  return LPC_OK;
}

Why is this function required?

When I used the HID sample code for Interrupt endpoint, I am facing situation where the very first request from host to device for reading the data, gives zero as read value. Any read requests from the host after the first request gives valid data. I believe, the very first zero values are from the above function. This this correct? If I comment the above function, the code will not work. Do you have an idea to solve this?


[COLOR=black]Also, do you have an idea on calculating "ep_index" values for HID_EP_IN and [/COLOR]
[COLOR=black]HID_EP_OUT endpoints for registering using the function pUsbApi->core->RegisterEpHandler(......)[/COLOR]

Currently I am using the values as below.
ep_indx = (((HID_EP_IN & 0x0F) << 1) + 1);
and
ep_indx = ((HID_EP_OUT & 0x0F) << 1);

I have referred CDC sample code for calculating this. The user manual doesn't contain any information on calculating these values. But I am not sure whether these values are correct.
If you have any idea, can you please confirm on this?


Your replies are helping me alot in proceeding with my work.
Thank you in advance.


With regards
Saraswathi C
0 Kudos
Reply

3,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Wed May 15 12:22:37 MST 2013

Quote:
why I am getting error code at host?



Ah, sorry. I didn't write it exactly on above post,
HID_SetReport() should return  LPC_OK for the second call, too.



Quote:
I have a situation where I need to send the address to read the flash and receive the read data from the device



Umm.. To satisfy your requirement, the SETUP packet for the request should hold 32bit address and transfer length.
You may split the 32bit addres into two 16bit values, and assign them to wValue and wIndex. The transfer size is assigned to the wLength field. But the problem of this scenario is that HID Get_/Set_Report aren't good for this purpose, because thsy use wIndex as the interface number. A custom handler for a custom (vendor) request should be implemented on the firmware.

I believe RegisterClassHandler() is available for this purpose. But the document description is vague, and there is no example of this routine.

I recommend you to implement it over bulk IN/OUT endpoints.
Leaving from HID, get into a vendor-specific class

Tsuneo
0 Kudos
Reply

3,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by saraswathi on Tue May 14 11:45:37 MST 2013
Hi Tsuneo,


  Thank you for the quick reply.


  Now I have configured the firmware for sending and receiving 64 bytes of data. Also, now I am able to receive the valid data and length values at HID_SetReport() callback function. However, the return value of libusb_conrol_transfer() API is -9(PIPE error). I am not able to understand, even though I receive the valid data and length values at device, why I am getting error code at host?
  Do you have any idea on this?


  I also have one more problem on libusb_control_transfer() API.
  The following is the libUSB API I am using for getting the data from device.


  libusb_control_transfer(dev_handle, (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE), HID_GET_REPORT, ((HID_REPORT_TYPE_INPUT<<8)|(CUSTOM_CMD)), INTERFACE_NUMBER, data, sizeof(data), 500)


  The following is the libUSB API I am using for sending the data to device.


  libusb_control_transfer(dev_handle, (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE), HID_SET_REPORT, ((HID_REPORT_TYPE_OUTPUT<<8)|(CUSTOM_CMD)), INTERFACE_NUMBER, data, sizeof(data), 500)


  I have a situation where I need to send the address to read the flash and receive the read data from the device. In this case I am not able to use the above mentioned commands. Is there any other way in control transfer to do the two way communication?
  Or I need to use interrupt endpoints for this type of communication?



  Can you please share your opinion on this?
  
  With regards
  Saraswathi C
0 Kudos
Reply

3,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Tue May 14 04:52:17 MST 2013

Quote:
However, HID_SetReport is not able to receive the data sent by the host.

HID_SetReport() is called by the stack [B]twice[/B].

The first call occurs at the SETUP stage of Set_Report request. At this call, the stack passes 0 to the [B]length[/B] parameter. Your firmware is expected to examine the SETUP packet for Report type and Report ID, to determine if this request is accepted. If your firmware accepts this request, your firmware may change a report buffer over pBuffer, and returns LPC_OK.

The second call is issued at the DATA stage. In this time, the stack passes real number of received bytes to the [B]length[/B] parameter. *pBuffer holds the received report.

Did you catch the second call?

Anyway, this HID_SetReport() behavior is not written on the USB On-Chip driver section of LPC11Uxx manual. I wasn't aware of it until I read this example.


Quote:
If I have to send and receive 64 bytes of data via control endpoint what are the changes I need to do on this sample code?


As a HID device, HID_INPUT_REPORT_BYTES and HID_OUTPUT_REPORT_BYTES macro (in hid_lpc11uxx_usbdesc.c) are replaced from 1 to 64. And then, the report descriptor (HID_ReportDescriptor[]) declares 64 bytes report.

But as you are running the HID device on libusb, you don't need to follow above HID practice ;-) Just send/receive 64 bytes over HID_SetReport()/HID_GetReport() on the firmware, and libusb_control_transfer().

Tsuneo
0 Kudos
Reply

3,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by saraswathi on Mon May 13 03:56:28 MST 2013
Thank you for the reply.
Yes, I am using the sample code from the above mentioned link. Now I am able to call the call back functions,
ErrorCode_t HID_GetReport( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* plength)
and
ErrorCode_t HID_SetReport( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length)

The HID_GetReport function sends 1 byte of data to linux host.
However, HID_SetReport is not able to receive the data sent by the host. I am sending 1 byte of data from linux host via control endpoint and the data read by HID_SetReport (i.e. pBuffer value) is zero.
Do you have any idea, even though I copy a valid data at host why pBuffer value at device is zero in HID_SetReport function?

If I have to send and receive 64 bytes of data via control endpoint what are the changes I need to do on this sample code?

With regards
Saraswathi C



Quote: Tsuneo
Sound like you are working on USB_ROM_HID example of this bundle,
"Sample Code Bundle for LPC11Uxx Peripherals using LPCXpresso"
http://www.lpcware.com/content/nxpfile/sample-code-bundle-lpc11uxx-peripherals-using-lpcxpresso



This error occurs when the device rejects the control request sent by your PC.
HID device may support Get_/Set_Report, Get_/Set_Idle, Get_/Set_Protocol class requests, other than the standard device requests. If you would send any other request to a standard HID device, this request should get above error.

What kind of request do you like to send?
ie. what is the value of these members of the SETUP packet of your request?
- bmRequestType
- bRequest
- wValue
- wIndex
- wLength

For custom requests, you have to implement custom handler code to the device.

Tsuneo

0 Kudos
Reply

3,286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Sat May 11 07:45:57 MST 2013
Sound like you are working on USB_ROM_HID example of this bundle,
"Sample Code Bundle for LPC11Uxx Peripherals using LPCXpresso"
http://www.lpcware.com/content/nxpfile/sample-code-bundle-lpc11uxx-peripherals-using-lpcxpresso


Quote:
LIBUSB_ERROR_PIPE(if the control request was not supported by the device this error occurs)



This error occurs when the device rejects the control request sent by your PC.
HID device may support Get_/Set_Report, Get_/Set_Idle, Get_/Set_Protocol class requests, other than the standard device requests. If you would send any other request to a standard HID device, this request should get above error.

What kind of request do you like to send?
ie. what is the value of these members of the SETUP packet of your request?
- bmRequestType
- bRequest
- wValue
- wIndex
- wLength

For custom requests, you have to implement custom handler code to the device.

Tsuneo
0 Kudos
Reply