Hi,
working with the SMT32 processor, I've some troubles with the usb interface. I want to install two HID interface descriptors (each has one endpoint - endpoint1 and endpoint4).
In the device manager of my computer, I get two usb HID interfaces - which sounds good; but there's only a communication with the endpoint1 not with the endpoint4!
void USB_EndPoint3 (DWORD event) { }
This function will be never called!
I tried to debug the code and I found out that at the beginning I get a Set-Address command with the addr 0x86 (which sounds good for these two endpoints); after that the host reads the usb device descriptor and the string descriptors; after that dataoutstage function is called, but the EP0Data.pData is 0x00...
void USB_DataOutStage (void) { DWORD cnt; cnt = USB_ReadEP(0x00, EP0Data.pData); EP0Data.pData += cnt; EP0Data.Count -= cnt; }
After that an reset event occured; I don't know why...
And the whole process will start from the beginning; except that the endpoint4 won't be configurated again; that means Set-Address command includes only the first endpoint1 but not the endpoint4!
At the moment I've no idea where the problem could be!
void USB_Configure_Event (void) { unsigned char InReportKeyboard[5]; unsigned char InReportTouch[6]; //es werden nur demo packets an die inputs geschickt keien richtigen daten memset( &InReportKeyboard[0], 0, sizeof(InReportKeyboard) ); memset( &InReportTouch[0], 0, sizeof(InReportTouch) ); if (USB_Configuration) { /* Check if USB is configured */ USB_WriteEP(0x81, InReportKeyboard, sizeof(InReportKeyboard)); USB_WriteEP(0x84, InReportTouch, sizeof(InReportTouch)); } }
Do someone know if this function is correct with these two USB_WriteEP calls?
These are my descriptors:
const BYTE USB_ConfigDescriptor[] = { /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, /* bLength */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL( /* wTotalLength */ USB_CONFIGUARTION_DESC_SIZE + USB_INTERFACE_DESC_SIZE + HID_DESC_SIZE + USB_ENDPOINT_DESC_SIZE + /* interface two: descriptor length */ USB_INTERFACE_DESC_SIZE + HID_DESC_SIZE + USB_ENDPOINT_DESC_SIZE ), 0x02, /* bNumInterfaces */ 0x01, /* bConfigurationValue */ 0x00, /* iConfiguration */ USB_CONFIG_SELF_POWERED //USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes */ /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(0), //USB_CONFIG_POWER_MA(100), /* bMaxPower */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x01, /* bNumEndpoints */ USB_DEVICE_CLASS_HUMAN_INTERFACE, /* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x5E, 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), USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x0008), /* wMaxPacketSize (muss so groß sein, dass das kompl. pkt reinpasst an daten */ 0x25, USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x01, /* bInterfaceNumber -> zweites interface im configuration descriptor */ 0x00, /* bAlternateSetting */ 0x01, /* bNumEndpoints -> wieviele endpoints besitzt dieses interface */ USB_DEVICE_CLASS_HUMAN_INTERFACE, /* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x00, 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_2), USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(4), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x0008), /* wMaxPacketSize (muss so groß sein, dass das kompl. pkt (report descriptor) reinpasst an daten */ 0x20, /* Terminator */ 0 /* bLength */
best regards Jan
Moved from SiLabs USB forum, because the target MCU is STM32, and the firmware is based on KEIL example. www.cygnal.org/.../002075.html
A brief summary of the discussion on above thread,
1) The OP observed bus reset and Clear_Feature( ENDPOINT_HALT ) for EP4, after enumeration finishes. It was thought as error recovery sequence for EP4 by the host HID class driver. This problem was solved by changing the USB_EP_NUM value on usbcnfg.h
usbcnfg.h #define USB_EP_NUM 2 // <---- 5 ( = 1 + 4 )
2) Revised report descriptor was proposed for the first HID interface, which provides system keyboard.
// Report format // Input report - 1 byte // byte value // 0 0: not pressed, 1: Space bar, 2: Down arrow, 3: Up arrow // // Output report - 1 byte // byte // 0 0x00 - 0xFF // // Feature report - HID_FEATURE_REPORT_BYTES // byte // 0 0x00 - 0xFF // .. // HID_FEATURE_REPORT_BYTES - 1 // const BYTE HID_ReportDescriptor[] = { HID_UsagePage( 0x01 ), // Generic Desktop HID_Usage ( 0x06 ), // keyboard HID_Collection ( HID_Application ), // --------- common globals ----- HID_ReportSize ( 8 ), // 8 bits HID_LogicalMin ( 0x00 ), // value range: 0 - // --------- input report ----- HID_LogicalMax ( 0x03 ), // value range: 0 - 3 HID_ReportCount ( 1 ), // 1 byte HID_UsagePage( 0x07 ), // Keycode page HID_Usage( 0x00 ), // key null - not pressed HID_Usage( 0x2C ), // Space bar HID_Usage( 0x51 ), // Down arrow HID_Usage( 0x52 ), // Up arrow HID_Input ( HID_Data | HID_Array ), // --------- output report ----- HID_LogicalMaxS ( 0xFF ), // value range: 0 - 0xFF HID_UsagePageVendor( 0x01 ), // Vendor specific page HID_Usage ( 0x01 ), HID_Output ( HID_Data | HID_Variable | HID_Absolute ), // --------- feature report ----- HID_ReportCount ( HID_FEATURE_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Feature ( HID_Data | HID_Variable | HID_Absolute ), HID_EndCollection, };
This report descriptor is under testing on the OP side.
3) Four options are proposed for the second HID top-level collection for touchscreen
a) Generic Desktop - Mouse b) Generic Desktop - Joystick (or GamePad) c) Digitizer page - Pen (or Touchscreen) d) Vendor specific device
Tsuneo
I got the encoder working; In the device manager, I can see another keyboard HID interface.
Everything seems to be fine, but if I change the vendor ID and / or the product ID -> the USB HID device will be unknown. No keyboard device will be available in the device manager. Both report descriptors won't be read by the host.
Is it correct, that there are some information stored in the registry (which driver has to be loaded for this USB connection and so on)?
Jan
I will try to use the version a) - writing my own calibration method.
> if I change the vendor ID and / or the product ID -> the USB HID device will be unknown.
When you change VID/PID, the device is recognized as a new device for Windows. Applying the default INF, input.inf, Windows will make up new registry entries for the device, without any intervention of user.
Did you assign a new VID/PID, which is not occupied by other USB device? USBDeview lists up all USB devices with VID/PID, regardless of current connection. Check it on USBDeview.
USBDeview www.nirsoft.net/.../usb_devices_view.html
In development, you can assign any VID/PID, unless it is occupied by other device on your PC. Higher end of VID, such as 0xFFF0 is likely not occupied yet. When you release the device, get official VID/PID for your device.
Even if you would assign unique VID/PID, but above problem occurs, it suggests firmware bug on enumeration. To catch a clue, take a trace on a hardware analyzer or software sniffer. The enumeration sequence is captured using software sniffers, like USBlyzer "Capture Hot-plugged" option.
USBlyzer (1 month trial) http://www.usblyzer.com/
What is the first error on the log?
It's a little bit strange. If I start the host with the connected usb device, the device won't be shown as keyboard in the device manager.
If I try to search for new connected hardware (in the device manager), then the device will be found and shown. Therefore I'm not able to find the existing error using USBlyzer, because this software always search for new connected devices at startup.
I've some volatile global variables for the encoder part; if I delete them (6 volatile char variables) the device will be recognized by the host after booting.
The stack-size is big enough.
If I start the host with the device connected to the usb port (with new vendor and product ID), the device will be shown as unknown in the device manager. After a while, windows tries to talk to the device a second time, and after that both HID interrfaces from the device will be shown in the device manager (without any kind of error)....
ok I deleted the whole code for the encoder - getting the same problem; the device is always listened in the device manager as "other devices".
summary:
a) booten -> device manager shows usb device -> "other devices" -> after a while -> some usb resets occur -> usb device is shown as keyboard and mouse HID device
b) host is already running -> connect usb device -> device manager shows device as keyboard and mouse device (as expected)
In both ways, I use a new vendor and product ID.
Is your device bus-powered (supplied by USB line), or self-powered (has stand alone power supply) ?
KEIL examples are made for bus-powered devices. For self-powered, you have to add several process to your code. - VBUS detection - USB physical connection detection and additional initialization
That's a point. My device is self-powered.
> VBUS detection - USB physical connection detection and additional initialization
I'm using an external pullup on data+ line for the correct detection of the usb device (full-speed). I can enable / disable the usb detection by the device controller, because the pullup 1k5 is directly connected to an GPIO.
By the way, is my report descriptor for the touch (configurated as mouse device) ok?
const BYTE HID_ReportDescriptor2[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) 0x05, 0x01, // USAGE PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7F, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x06, // INPUT (Data,Var,Relative) 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION };
In the device manager, I can see a second HID usb mouse device.
unsigned short coordinate[2]; GetValue(&coordinate[0]); USB_WriteEP(0x82, (BYTE *) &coordinate[0], 2 * sizeof(unsigned int));
I'm not sure if this USB_WriteEP() will work. Moreover is it better to use LOGICAL_MINIMUM, LOGICAL_MAXIMUM (-127, 127) or (0, 255)?
const WORD HID_ReportDescSize = sizeof(HID_ReportDescriptor); //report descriptor touchscreen const BYTE HID_ReportDescriptor2[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) 0x05, 0x01, // USAGE PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) HID_LogicalMin ( 0x000 ), HID_LogicalMaxS ( 0x320 ), // max value 800px HID_ReportSize ( 16 ), HID_ReportCount ( 2 ), HID_Input ( HID_Data | HID_Variable | HID_Absolute), //0x81, 0x06, // INPUT (Data,Var,Relative) 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION };
I can't uss the relative values in the original descriptor therefore I will use absolute values. The maximum size of the display is 800px -> therefore one 16bit value for each length (height and width) will be enough.
Therefore I changed the usb report descriptor to this one. In USBlyzer I can see the values transmitted, but the mouse is always at the left top corner...
Here's my endpoint descriptor - I only changed the size to 32bit.
/* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(2), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x0020), /* wMaxPacketSize */ 0x0A, /* 8ms */ /* bInterval */
One small additional question: is it possible to add a feature report to the report descriptor of a mouse? If I only read, that it is not possible to add a output report to a mouse...
const WORD HID_ReportDescSize = sizeof(HID_ReportDescriptor); //report descriptor touchscreen const BYTE HID_ReportDescriptor2[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) 0x05, 0x01, // USAGE PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) HID_LogicalMin ( 0x000 ), HID_LogicalMaxS ( 0x320 ), // max value 800px HID_ReportSize ( 16 ), HID_ReportCount ( 2 ), HID_Input ( HID_Data | HID_Variable | HID_Absolute), //0x81, 0x06, // INPUT (Data,Var,Relative) 0xc0, // END_COLLECTION HID_ReportCount ( HID_FEATURE_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Feature ( HID_Data | HID_Variable | HID_Absolute ), 0xc0, // END_COLLECTION };