USB Composite Device on LPC1347

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

USB Composite Device on LPC1347

1,591 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ECamino on Fri Sep 21 14:23:32 MST 2012
Hi,

I need to create a USB composite device but I'm not having any luck with intializing an HID or I'll have descriptor issues. I see a really good app note, AN11232, with sample code to do this on LPC11Uxx. But it doesn't have code for LPCXpresso. Can someone explain how to port Keil projects to LPCX, or does anyone have sample code to create a USB composite device on LPC1347?

Thanks!

EC
0 Kudos
9 Replies

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Wed Sep 26 18:50:23 MST 2012

Quote:
I checked the .inf files in the CDC_inf folder, and they have the correct VID and PID.


For composite device, matched VID/PID isn't enough, on the INF file.
We have to specify the interface number of the CDC communication interface, too.
Appended "&MI_xx" specifies the interface number.

\lpc11Uxx.LPCXpreso.examples_using_ROMDrivers\ROM_USB_cdc\CDC_inf\lpc-vcom.inf

[DeviceList] 
%DESCRIPTION%=LPCVCOM, USB\VID_1FC9&PID_0011         ;; for non-composite CDC device
%DESCRIPTION%=LPCVCOM, USB\VID_1FC9&PID_0011&MI_00   ;; for composite CDC device


Tsuneo
0 Kudos

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ECamino on Wed Sep 26 12:18:37 MST 2012
Hi,

Thanks again for the help, Tsuneo. It worked just like you said! I was able to get an HID + HID + CDC (two interfaces) to enumerate on a LPC347 based from an LPC14Uxx project.

But I have one more issue, with the CDC driver. When the Windows Hardware Wizard prompts for the driver, I select:

\ROM_USB_cdc\CDC_inf

It then says it can't find the driver. I clicked back and selected manual install. I selected Ports(Com&LPT) and it started to run the driver install. I get a warning message about unsigned driver etc.

Then it asks to select the device driver to install for the hardware. In the Model box, "LPC13xxUSB VCom Port" is listed. If I click next, it will enumerate.

I'm guessing that driver was installed from another sample project I ran previously?

I checked the .inf files in the CDC_inf folder, and they have the correct VID and PID. Why won't those drivers work and why does it load with the other one?

Thanks,

EC
0 Kudos

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Tue Sep 25 01:31:56 MST 2012

Quote:
Is it possible to create a composite HID + HID?



To implement the second HID interface, you should have another usb_hid_init(), which sets up another context for the on-chip HID API. Here is the original code of usb_hid_init(),
lpc11uxx_usbd_hid.c

ErrorCode_t usb_hid_init(USBD_HANDLE_T hUsb, USB_INTERFACE_DESCRIPTOR* pIntfDesc, uint32_t* mem_base, uint32_t* mem_size)
{
  ...
  hid_param.mem_base = *mem_base;             // <---- (1)
  hid_param.mem_size = *mem_size;
  hid_param.intf_desc = (uint8_t*)pIntfDesc;  // <---- (2)
  /* user defined functions */
  hid_param.HID_GetReport = HID_GetReport;    // <---- (3)
  hid_param.HID_SetReport = HID_SetReport;
  hid_param.HID_EpIn_Hdlr  = HID_Ep_Hdlr;
  hid_param.HID_EpOut_Hdlr = HID_Ep_Hdlr;  
  hid_param.report_data  = reports_data;      // <---- (2)
  ...

(1) HID API holds its context on the RAM specified by hid_param.mem_base, each for each HID interface. For the second HID interface, your firmware has to assign another RAM space for the second context of HID API.

(2) hid_param.intf_desc takes the pointer to the second HID interface descriptor.
You should have this descriptor array on ROM, to feed it to pUsbApi->hw->Init()
const uint8_t USB_FsConfigDescriptor[] = {
Configuration descriptor
 - First HID Interface descriptor    // <---- the first hid_param.intf_desc points here
 - - First HID descriptor
 - - First HID interrupt IN descriptor
 - - First HID interrupt OUT descriptor (optional)
 - Second HID Interface descriptor   // <---- the second hid_param.intf_desc points here
 - - Second HID descriptor
 - - Second HID interrupt IN descriptor
 - - Second HID interrupt OUT descriptor (optional)
};


hid_param.report_data points the array which holds the second HID report descriptor.

(3) You'll provide another pair of callbacks (HID_GetReport, HID_SetReport, HID_EpIn_Hdlr and HID_EpOut_Hdlr) for the second HID interface.

Tsuneo
0 Kudos

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Mon Sep 24 16:21:06 MST 2012

Quote:
I see a constant "polling" going on where the Input Report is "0x3C" Why is that?



This ROM_USB_hid example also follows impractical Keil HID examples faithfully.
In this example, the first input report is loaded to the interrupt IN endpoint at Set_configuration, using this USB_Configure_Event() callback. USB_Configure_Event() puts loopback_report to the IN endpoint using WriteEP().
lpc11uxx_usbd_hid.c

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;
}


When the device engine completes to send above first input report, the endpoint interrupt occurs, and HID_Ep_Hdlr() callback is called with USB_EVT_IN. HID_Ep_Hdlr(USB_EVT_IN) fills another input report (loopback_report) to the IN endpoint using WriteEP().
lpc11uxx_usbd_hid.c

/*
 *  USB Endpoint 1 Event Callback
 *   Called automatically on USB Endpoint 1 Event
 *    Parameter:       event
 */

ErrorCode_t HID_Ep_Hdlr (USBD_HANDLE_T hUsb, void* data, uint32_t event) 
{
  USB_HID_CTRL_T* pHidCtrl = (USB_HID_CTRL_T*)data;

  switch (event) {
    case USB_EVT_IN:
      pUsbApi->hw->WriteEP(hUsb, pHidCtrl->epin_adr, loopback_report, 1);     // <----
      break;
    case USB_EVT_OUT:
      pUsbApi->hw->ReadEP(hUsb, pHidCtrl->epout_adr, loopback_report);
      break;
  }
  return LPC_OK;
}

When the transfer of the second input report finishes, HID_Ep_Hdlr(USB_EVT_IN) is called again. In this way, the hardware-interrupt chain continues, every time the interrupt IN transaction comes from host.

This new on-chip driver (LPC11Uxx and LPC1347) is well designed, comparing to the former one (LPC1343), on which I've criticized severely At least, we can modify above behavior easily.

To stop chained interrupts on the interrupt IN endpoint,
1) Don't fill the first input report at USB_Configure_Event()
2) Don't fill the second (and later) input reports at HID_Ep_Hdlr(USB_EVT_IN)

Elsewhere on your code, when your firmware want to send an input report, your input report is put to the IN endpoint using pUsbApi->hw->WriteEP().

Tsuneo
0 Kudos

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ECamino on Mon Sep 24 14:00:32 MST 2012
Hi,

Is it possible to create a composite HID + HID?


I want to do that before I try to add the CDC.


I changed the USB descriptors in the project to add another HID interface adding a single in endpoint at address x82. I created a keyboard report descriptor and in my code I'm calling it HID_ReportDescriptor2[].


I changed the hid_param.max reports to 2, and I added this code:

[LEFT][FONT=Arial][SIZE=2][/SIZE][/FONT]
[FONT=Arial][SIZE=2]reports_data[1].[COLOR=#0000c0][COLOR=#0000c0]len[/COLOR][/COLOR] = HID_ReportDescSize2;[/SIZE][/FONT]
[FONT=Arial][SIZE=2]reports_data[1].[COLOR=#0000c0][COLOR=#0000c0]idle_time[/COLOR][/COLOR] = 0;[/SIZE][/FONT][/LEFT]
[FONT=Arial][SIZE=2]reports_data[1].[COLOR=#0000c0][COLOR=#0000c0]desc[/COLOR][/COLOR] = ([COLOR=#005032][COLOR=#005032]uint8_t[/COLOR][/COLOR] *)&HID_ReportDescriptor2[0];[/SIZE][/FONT]

[SIZE=2][/SIZE]
I build and run, and I get LPC_OK on return from :
[SIZE=2][/SIZE]

[LEFT][SIZE=2][FONT=Arial]ret = usb_hid_init(hUsb, ([COLOR=#005032][COLOR=#005032]USB_INTERFACE_DESCRIPTOR[/COLOR][/COLOR] *)&USB_FsConfigDescriptor[[B][COLOR=#7f0055][COLOR=#7f0055]sizeof[/COLOR][/COLOR][/B][/FONT][/SIZE][FONT=Arial][SIZE=2]([COLOR=#005032][COLOR=#005032]USB_CONFIGURATION_DESCRIPTOR[/COLOR][/COLOR])], [/SIZE][/FONT][/LEFT]
[FONT=Arial][SIZE=2]&usb_param.[COLOR=#0000c0][COLOR=#0000c0]mem_base[/COLOR][/COLOR], &usb_param.[COLOR=#0000c0][COLOR=#0000c0]mem_size[/COLOR][/COLOR]);[/SIZE][/FONT]

[SIZE=2][/SIZE]
I see in my USB protocol analyzer, there is a get request for interface 1 report descriptor, but it doesn't seem to be sent out to the PC. Here are the descriptors from the analyzer:

[B][SIZE=2][/SIZE][/B]
[B][SIZE=2][B]Connection Status[/B]Device connected[B]Current Configuration[/B]1[B]Speed[/B]Full[B]Device Address[/B]1[B]Number Of Open Pipes[/B]3
[B]Device Descriptor[/B] LPC11Uxx HID

Offset
FieldSizeValueDescription0bLength112h1bDescriptorType101hDevice2bcdUSB20200hUSB Spec 2.04bDeviceClass100hClass info in Ifc Descriptors5bDeviceSubClass100h6bDeviceProtocol100h7bMaxPacketSize0140h64 bytes8idVendor21FC9h10idProduct20107h12bcdDevice20100h1.0014iManufacturer101h"NXP Semiconductors"15iProduct102h"LPC11Uxx HID"16iSerialNumber103h"ABCD123456789"17bNumConfigurations101h

[B]Configuration Descriptor 1[/B] Self Powered
OffsetFieldSizeValueDescription0bLength109h1bDescriptorType102hConfiguration2wTotalLength20042h4bNumInterfaces102h5bConfigurationValue101h6iConfiguration100h7bmAttributes1C0hSelf Powered4..0: Reserved...00000 5: Remote Wakeup..0..... No6: Self Powered.1...... Yes7: Reserved (set to one)
(bus-powered for 1.0)1....... 8bMaxPower132h100 mA

[B]Interface Descriptor 0/0[/B] HID, 2 Endpoints
OffsetFieldSizeValueDescription0bLength109h1bDescriptorType104hInterface2bInterfaceNumber100h3bAlternateSetting100h4bNumEndpoints102h5bInterfaceClass103hHID6bInterfaceSubClass100h7bInterfaceProtocol100h8iInterface104h"HID"
[B]HID Descriptor[/B]
OffsetFieldSizeValueDescription0bLength109h1bDescriptorType121hHID2bcdHID20100h1.004bCountryCode100h5bNumDescriptors101h6bDescriptorType122hReport7wDescriptorLength20021h33 bytes
[B]Endpoint Descriptor 81[/B] 1 In, Interrupt, 32 ms
OffsetFieldSizeValueDescription0bLength107h1bDescriptorType105hEndpoint2bEndpointAddress181h1 In3bmAttributes103hInterrupt1..0: Transfer Type......11 Interrupt7..2: Reserved000000.. 4wMaxPacketSize20004h4 bytes6bInterval120h32 ms
[B]Endpoint Descriptor 01[/B] 1 Out, Interrupt, 32 ms
OffsetFieldSizeValueDescription0bLength107h1bDescriptorType105hEndpoint2bEndpointAddress101h1 Out3bmAttributes103hInterrupt1..0: Transfer Type......11 Interrupt7..2: Reserved000000.. 4wMaxPacketSize20004h4 bytes6bInterval120h32 ms


[B]Interface Descriptor 1/0[/B] HID, 1 Endpoint
OffsetFieldSizeValueDescription0bLength109h1bDescriptorType104hInterface2bInterfaceNumber101h3bAlternateSetting100h4bNumEndpoints101h5bInterfaceClass103hHID6bInterfaceSubClass101hBoot Interface7bInterfaceProtocol101hKeyboard8iInterface100h
[B]HID Descriptor[/B]
OffsetFieldSizeValueDescription0bLength109h1bDescriptorType121hHID2bcdHID20100h1.004bCountryCode100h5bNumDescriptors101h6bDescriptorType122hReport7wDescriptorLength2003Fh63 bytes
[B]Endpoint Descriptor 82[/B] 2 In, Interrupt, 32 ms
OffsetFieldSizeValueDescription0bLength107h1bDescriptorType105hEndpoint2bEndpointAddress182h2 In3bmAttributes103hInterrupt1..0: Transfer Type......11 Interrupt7..2: Reserved000000.. 4wMaxPacketSize20008h8 bytes6bInterval120h32 ms


[B]Interface 0 HID Report Descriptor[/B] Vendor-Defined 1
Item Tag (Value)Raw DataUsage Page (Vendor-Defined 1)06 00 FF Usage (Vendor-Defined 1)09 01 Collection (Application)A1 01     Logical Minimum (0)15 00     Logical Maximum (255)26 FF 00     Report Size (8)75 08     Report Count (1)95 01     Usage (Vendor-Defined 1)09 01     [B]Input[/B] (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)81 02     Report Count (1)95 01     Usage (Vendor-Defined 1)09 01     [B]Output[/B] (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit)91 02     Report Count (1)95 01     Usage (Vendor-Defined 1)09 01     [B]Feature[/B] (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit)B1 02 End CollectionC0 [/SIZE][/B]
[B][SIZE=2][/SIZE][/B]

Is there something else I have to do to get the second report descriptor to get through?
0 Kudos

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ECamino on Mon Sep 24 07:28:01 MST 2012
Hi Tsuneo, Thanks for the help!
  
I downloaded the files and decided to try porting over the LPC11U24 to the LPC1347 as you suggested. 
  
The application runs.  But since it's interrupt based, I was expecting only to see data on the USB pipe when a call is made.  Instead, I see a constant "polling" going on where the Input Report is "0x3C"  Why is that?
  
For other people new to this platform that may need help in porting their projects, here's what I had to do (for Debug configuation):
  
1. add CMSISV2p10_LPCU13xx to workspace.
2. add LPC13Uxx_DriverLib to workspace.
3. project properties > C/C++ build > MCU settings: change target to LPC1347
4. project properties > C/C++ General > Paths and Symbols > inlcude tab > GNU C: EDIT the include directories to the CMSIS and Drive Lib.
5. project properties > C/C++ General > Paths and Symbols >  Libraries tab > EDIT the names as above.
6. project properties > C/C++ General > Paths and Symbols >  Library Paths tab > EDIT the names as above.
7. click OK
  
In project source folders:
8. exlude cr_startup_LPC11U.c, add to src directory cr_startup_LPC13U.c
9. in main.c edit line 22 "LPC13Uxx.h"
10. in main.c edit line 110 , change "USB_IRQn" to "USB_IRQ_IRQn" (LPC13Uxx.h IRQn_Type structure is different).

EC
0 Kudos

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Sat Sep 22 09:22:22 MST 2012
Ah sorry, you are working on the USB on-chip driver of LPC1347

The USB engine and the on-chip driver of LPC1347 is same as LPC11Uxx.
Then, start with this example, and port it to LPC1347.

USB ROM Driver examples using LPCXpresso for LPC11Uxx
http://www.lpcware.com/content/nxpfile/usb-rom-driver-examples-using-lpcxpresso-lpc11uxx


Quote:
I can't get the HID module to initialize. So looking at other projects using the same ROM module/drivers, I'm expecting to see somewhere where the HID parameters are initialized similarly to how the cdc_params are initialized in the ROM_USB_cdc demo



In main(), call usb_hid_init() after initialization of CDC API, befor "enable IRQ".
usb_hid_init() is provided in ROM_USB_hid\src\lpc11uxx_usbd_hid.c
The pointer to the HID interface descriptor on the full confif set is passed to usb_hid_init()
For the second HID interface, you may need to duplicate and modify usb_hid_init(), so that it can hold separate parameters.

int main (void)
{
  ...
  ret = pUsbApi->hw->Init(...);   // <-- pass full config descriptor set
  ...
  ret = pUsbApi->cdc->init(...);  // <-- init of CDC API
  ...
  ret = usb_hid_init(...);        // <-- init of HID API

   /* enable IRQ */


Tsuneo
0 Kudos

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ECamino on Sat Sep 22 05:13:17 MST 2012
I was able to do composite devices on Microchip parts, but now we're  trying to get it to work on NXP and it's much different!  I'm trying to create ROM CDC + ROM HID + ROM HID.  What's frustrating is that there are a lot of example projects but it seems like the projects are all set up differently, and it's hard to know what to take from where and how to change it so that it will all work.  I've been working with a project for LPC1347 called ROM_USB_cdc.  I'm  using the code in main as a guide to initializing HID param structures,  and I'm looking at an AN that details how to create a composite device  with CDC using the IAP descritptor...long story short, I can't get the  HID module to initialize.  So looking at other projects using the same ROM module/drivers, I'm expecting to see somewhere where the HID parameters are initialized similarly to how the cdc_params are initialized in the ROM_USB_cdc demo, but how it's done in other projects isn't obvious.  Thanks for the feedback on LPC17xx.  I'll see if I can port one.  I tried porting composite device.  LPC11Uxx and I could not get it to build.
0 Kudos

983 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Sat Sep 22 04:34:43 MST 2012
1) What is the class you are combining with HID, on your composite device?
Is it HID + HID?
2) Which type of HID device(s), keyboard, mouse, joystick, or vendor-specific HID?

CodeRed has already ported many Keil (NXP) examples to LPCXpresso projects, including USB examples. Import them from zip files in this folder.
C:\nxp\lpcxpresso_xxx\Examples\LPC1000\LPC17xx\

Tsuneo
0 Kudos