Good day to all,
I am using MCB1760 board.
I want to use EP1 for OUT EP in my application.
As a start I have modified the RTX_HID code as below.
The device is detecting.
When I run the HID_Client on the PC I can select the device.
But after selecting the device it is getting struct.
Changes are made as given below: USB_ConfigDescriptor in usbdesc.c: Added EP1 output descriptor. USB_EndPoint1 task of usbuser.c: Added USB_EVT_OUT functionality.
Please suggest
const U8 USB_ConfigDescriptor[] = { /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, /* bLength */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL( /* wTotalLength */ 1*USB_CONFIGUARTION_DESC_SIZE + 1*USB_INTERFACE_DESC_SIZE + 1*HID_DESC_SIZE + 2*USB_ENDPOINT_DESC_SIZE //Updated on 09-11-11 ), 0x01, /* bNumInterfaces */ 0x01, /* bConfigurationValue: 0x01 is used to select this configuration */ 0x00, /* iConfiguration: no string to describe this configuration */ USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes */ /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(100), /* bMaxPower, device power consumption is 100 mA */
/* Interface 0, Alternate Setting 0, HID Class */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x02, /* bNumEndpoints */ //Updated to 2 on 09-11-11 USB_DEVICE_CLASS_HUMAN_INTERFACE, /* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x04, /* iInterface */ /* HID Class Descriptor */ /* HID_DESC_OFFSET = 0x0012 */ HID_DESC_SIZE, /* bLength */ HID_HID_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(0x0100), /* 1.00 */ /* bcdHID */ 0x00, /* bCountryCode */ 0x01, /* bNumDescriptors */ HID_REPORT_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(HID_REPORT_DESC_SIZE), /* wDescriptorLength */ /* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x20, /* 32ms */ /* bInterval */ /* Endpoint, HID Interrupt Out */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x20, /* 32ms */ /* bInterval */ /* Terminator */ 0 /* bLength */ };
#if (USB_EP_EVENT & (1 << 1)) __task void USB_EndPoint1 (void) { U16 evt;
for (;;) { os_evt_wait_or(0xFFFF, 0xFFFF); /* Wait for an Event */ evt = os_evt_get(); /* Get Event Flags */
if (evt & USB_EVT_IN) { GetInReport(); USB_WriteEP(HID_EP_IN, &InReport, sizeof(InReport)); } if (evt & USB_EVT_OUT) { USB_ReadEP(HID_EP_IN, &OutReport); SetOutReport(); } } } #endif
Your mods of the firmware seem fine, maybe, though it's hard to decipher your above code. Sound like a problem of HID_Client (Windows application), rather than the firmware.
To confirm it, run your device with SimpleHIDWrite.
SimpleHIDWrite (*1) www.lvr.com/.../SimpleHIDWrite3.zip
Plug-in your device, and run SimpleHIDWrite. Click "Keil MCB1700 HID" on the top list. Type in - Report ID box - 0 - next box - any number Click "Write" button at the bottom
If you see LEDs on/off by the number you typed in, your device working fine.
(*1) The original source code (Delphi) is included in Human Interface Device controller suite www.soft-gems.net/index.php
Tsuneo
Thank you Tsuneo,
I tried with the SimpleHIDwrite. The device is getting detecting. Only the ReportID box is visible. Next box is not there. If I enter 00 or any value in the ReportID box, the write button is not getting enabled. Please suggest.
Lingaraju
> Only the ReportID box is visible. Next box is not there.
Umm The report descriptor of your RTX_HID seems different from mine. Are we seeing different revision of the example? On my side, Report Descriptor is defined as follows.
C:\Keil\ARM\Boards\Keil\MCB1700\RL\USB\RTX_HID\usbdesc.c /*---------------------------------------------------------------------------- * U S B - K e r n e l *---------------------------------------------------------------------------- * Name: usbdesc.c * Purpose: USB Descriptors * Version: V1.20 * Note(s): RTX Version *---------------------------------------------------------------------------- * This file is part of the uVision/ARM development tools. * This software may only be used under the terms of a valid, current, * end user licence from KEIL for a compatible version of KEIL software * development tools. Nothing else gives you the right to use this software. * * This software is supplied "AS IS" without warranties of any kind. * * Copyright (c) 2009 Keil - An ARM Company. All rights reserved. *---------------------------------------------------------------------------- * History: * V1.20 Changed string descriptor handling * Changed HID Report Descriptor * V1.00 Initial Version *----------------------------------------------------------------------------*/ ... /*------------------------------------------------------------------------------ HID Report Descriptor *------------------------------------------------------------------------------*/ /* Bit Input Output 0 Joystick LED0 1 Joystick LED1 2 Joystick LED2 3 Joystick LED3 4 Joystick LED4 5 --- LED5 6 --- LED6 7 --- LED7 */ #define HID_INPUT_REPORT_BYTES 1 /* size of report in Bytes */ #define HID_OUTPUT_REPORT_BYTES 1 /* size of report in Bytes */ #define HID_FEATURE_REPORT_BYTES 1 /* size of report in Bytes */ const U8 HID_ReportDescriptor[] = { HID_UsagePageVendor( 0x00 ), HID_Usage ( 0x01 ), HID_Collection ( HID_Application ), HID_LogicalMin ( 0 ), /* value range: 0 - 0xFF */ HID_LogicalMaxS ( 0xFF ), HID_ReportSize ( 8 ), /* 8 bits */ HID_ReportCount ( HID_INPUT_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Input ( HID_Data | HID_Variable | HID_Absolute ), HID_ReportCount ( HID_OUTPUT_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Output ( HID_Data | HID_Variable | HID_Absolute ), HID_ReportCount ( HID_FEATURE_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Feature ( HID_Data | HID_Variable | HID_Absolute ), HID_EndCollection, }; const U16 HID_ReportDescSize = sizeof(HID_ReportDescriptor);
Thanks for the reply Tsuneo.
I checked. The usbdesc.c I am using is same v2.0. I verified all the contents of the report descriptor array, it is same as yours.
Please suggest.
> I verified all the contents of the report descriptor array, it is same as yours.
I'm not sure what occurs here. You clicked a HID device other than "Keil MCB1700 HID" on the top list of SimpleHIDWrite dialog? OR Does your uVision work space point a different source file?
Hi Tsuneo, you are right. I had not selected any HID device. Now I have selected "Keil MCB1700 HID". I entered 00 for Report ID box and 01 in the second box and clicked on write. LED P1.28 glown. Again I entered 03 in the second box and clicked on write the SimpleHIDWrite got struck and no other LED glown.
please suggest.
Regards Lingaraju
> Again I entered 03 in the second box and clicked on write the SimpleHIDWrite got struck
The firmware doesn't read out the interrupt OUT endpoint. So, SimpleHIDWrite got stuck.
In your USB_EndPoint1(), USB_ReadEP() should take HID_EP_OUT, instead of HID_EP_IN
USB_ReadEP(HID_EP_IN, &OutReport); // <---- USB_ReadEP(HID_EP_OUT, &OutReport);
Hi Tsuneo,
Thanks for the support. I changed accordingly. It is working.
I will start chacking my application, if any problem I will get back to you.
Hi,
I have modified my code to receive or transmit more than 64 bytes according to the suggestions posted in the forum. If I run the SimpleHIDwrite on the PC it is detecting. SetReport and GetReport are woring. When I click on the "Write", it is showing error as Access Violation at address at 00000000. Read of address 00000000.
The size of the descriptor modified and the code modified is given below. Please suggest.
#define HID_INPUT_REPORT_BYTES 64 /* size of report in Bytes */ #define HID_OUTPUT_REPORT_BYTES 64 /* size of report in Bytes */ #define HID_FEATURE_REPORT_BYTES 64 /* size of report in Bytes */ const U8 HID_ReportDescriptor[] = { HID_UsagePageVendor( 0x00 ), HID_Usage ( 0x01 ), HID_Collection ( HID_Application ), HID_LogicalMin ( 0 ), /* value range: 0 - 0xFF */ HID_LogicalMaxS ( 0xFF ), HID_ReportSize ( 8 ), /* 8 bits */ HID_ReportCount ( HID_INPUT_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Input ( HID_Data | HID_Variable | HID_Absolute ), HID_ReportCount ( HID_OUTPUT_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Output ( HID_Data | HID_Variable | HID_Absolute ), HID_ReportCount ( HID_FEATURE_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Feature ( HID_Data | HID_Variable | HID_Absolute ), HID_EndCollection, }; const U16 HID_ReportDescSize = sizeof(HID_ReportDescriptor); #if (USB_EP_EVENT & (1 << 1)) __task void USB_EndPoint1 (void) { U16 evt; static U32 out_report_size = 0; static U32 in_report_size = 0; static U32 in_index=0; U32 in_send_size=0; U32 i=0; for (;;) { os_evt_wait_or(0xFFFF, 0xFFFF); /* Wait for an Event */ evt = os_evt_get(); /* Get Event Flags */ if (evt & USB_EVT_IN) { if ( in_report_size == 0 ) { // this interrupt is caused by the last packet? os_sem_send( USB_IN_EP1_Semaphore ); // IN EP1 is free } else { // there remains bytes to be sent in_send_size = HID_IN_EP_MAXPACKET_SIZE; // pick up a packet size if ( in_report_size < HID_IN_EP_MAXPACKET_SIZE ) { in_send_size = in_report_size; } // pass it to the endpoint USB_WriteEP( HID_EP_IN, &InReport[in_index], in_send_size ); in_report_size -= in_send_size; // move counter and index by sent size in_index += in_send_size; } } if (evt & USB_EVT_OUT) { out_report_size += USB_ReadEP( HID_EP_OUT, &OutReport[out_report_size] ); if(out_report_size == HID_OUTPUT_REPORT_BYTES) { os_sem_wait( USB_IN_EP1_Semaphore, 0xffff );// wait until IN EP is available for(i=0;i<out_report_size;i++) { InReport[i] = OutReport[i]; } in_report_size = out_report_size; in_index = 0; out_report_size = 0; // force EP1 IN interrupt manually LPC_USB->USBEpIntSet = 1 << EPAdr(HID_EP_IN); } } } } #endif
I am in the deadline crisis. Any help at the earliest possible will be appreciated. Please suggest.
Seems (almost) fine. You've taken the code form this topic, and modified a little. http://www.keil.com/forum/19729/
Did you modify USB_Core() task for USB_Configuration event, too?
The original Keil RTX_HID continuously sends input report. To start this sequential reports, it puts the first report at USB_Configuration handler in USB_Core() task. But your modification sends the input report just when an output report completes, for loop back. The first report in USB_Configuration event is deleted.
usbuser.c U32 out_report_size = 0; U32 in_report_size = 0; U32 in_index = 0; OS_SEM USB_IN_EP1_Semaphore; __task void USB_Core (void) { ... ... #if USB_CONFIGURE_EVENT if (evt & USB_EVT_SET_CFG) { if (USB_Configuration) { /* Check if USB is configured */ // <--- comment these two lines // GetInReport(); // USB_WriteEP(HID_EP_IN, &InReport, sizeof(InReport)); // <--- add these three lines out_report_size = 0; in_report_size = 0; in_index = 0; os_sem_init( USB_IN_EP1_Semaphore, 1 ); } } #endif
To speed up the response, set bInterval value on the endpoint descriptors to 1 ms.
Thanks for the reply.
I changed the code asper your suggestion and checked, but still it is giving the same error.
According to me, with the earlier code also the device was not sending the inrport array repeatedly since the in_report_size variable value will be '0'(zero) untill the USB_EVT_OUT gets the data and loads it to the inreport array.
I think the problem is something else.
regards Lingaraju
> SimpleHIDWrite: Violation at address at 00000000. Read of address 00000000
Umm.. It seems a bug of SimpleHIDWrite, which appears when 64 bytes or more is assigned. Confirmed with this firmware on Olimex LPC1766-STK. www.8052.com/.../MCB1760_RTX_HID_64BytesOver_loopback.zip This firmware works fine, but SimpleHIDWrite causes above error.
Test your firmware on another test bench, for example, Jan Axelson's HID page http://www.lvr.com/hidpage.htm generic_hid_cs_50 www.lvr.com/.../generic_hid_cs_50.zip
It is working fine with generic_hid_50 software. It really helped me to find the problem.