PORTS Forum
Ports and Interfaces => USB => Topic started by: bajwa on April 20, 2011, 10:29:06 am
-
Hello everyone,
i am writing the custom Firmware code in assembly for a USB Stack implementing HID class for communication. i am facing a very strange problem:
When i attach the Device to the bus, The device is enumerated by windows without any error. After that the Host sends the device a SET_CONFIGURATION request with bConfigurationValue = 0 (indicating the device should remain in ADDRESSED_STATE), whilst when i see Port's description using USBTrace, i see correct Descriptor values that the device was programmed for. If the values are correct, then why the host is not sending a NonZero bConfigurationValue? ??? Due to this, the Device Manager tells me that the "Device is not functional".
Also, If i attach the hardware with a Windows XP installed PC, the computer recognizes it as a Generic HID Device, but i am unable to communicate anything to the device (using the Generic HID c# example by Jan Axelson) as the software throws the exception of "The device is not functional".
i am unable to understand how should i tackle this hurdle and where exactly the problem lies..
Please help, i have taken this up as my University project and i only have a week left :(
Following are the details:
Controller: PIC18F4550
Windows: Windows 7 (64 bit), Windows XP (32 bit)
The descriptor values:
(in PIC18F assembly, i am using RETLW instruction to keep the bytes word aligned in ROM space):
; Device Descriptor
Device_Descriptor
retlw 0x12 ; Size of this descriptor in bytes (ref USB 2.0 spec)
retlw USB_DESCRIPTOR_DEVICE ; Descriptor ID (ref USB 2.0 spec) (2 bytes)
retlw 0x00 ; USB Specification (BCD format) 2.00 (ref USB 2.0 spec) (2 bytes)
retlw 0x02
retlw 0x00 ; Class Code
retlw 0x00 ; Subclass code
retlw 0x00 ; Protocol code
retlw EP0_BUFFER_SIZE ; Max. Packet size for EP0
retlw 0x06
retlw 0xfe ; Vender ID (2 bytes)
retlw 0x3F
retlw 0x00 ; Product ID (2 bytes)
retlw 0x01
retlw 0x00 ; Device release number (BCD format) (2 bytes)
retlw 0x01 ; Manufacturer string index
retlw 0x02 ; Product string index
retlw 0x00 ; Device Serial Number String
retlw 0x01 ; Number of possible configurations
Device_Descriptor_End
; Configuration Descriptor
Config_Descriptor
retlw 0x09
retlw USB_DESCRIPTOR_CONFIG
retlw 0x29
retlw 0x00 ; Length of the subordinate descriptors
retlw 0x01 ; Number of interfaces in this config
retlw 0x01 ; ID for this config
retlw 0x00 ; Configuration String Index - none defined
retlw (0x80 | USB_POWER_OPTION) ; Attributes
retlw 0x40 ; Maximum Power Consumption
Config_Descriptor_End
; Interface Descriptor
Interface_Descriptor
retlw 0x09 ; Descriptor Size
retlw USB_DESCRIPTOR_INTERFACE ; Descriptor Type
retlw 0x00 ; Interface number
retlw 0x00 ; Alternate Setting number
retlw 0x02 ; Number of EndPoints in this interface
retlw USB_HID_DEVICE ; Class code
retlw 0x00 ; Subclass code
retlw 0x00 ; Protocol code
retlw 0x00 ; Interface string index
; 0x06 -> Usage page
; 0xff00 to 0xffff -> user specific range code by Specification
; 0x09 -> Usage item
; HID Class Specific Descriptors
HID_Class_Descriptor
retlw 0x09 ; Size
retlw USB_HID_CLASS_DESCRIPTOR ; Desccriptor Type
retlw 0x11
retlw 0x01 ; HID Specification Number (In BCD) => 1.11
retlw 0x00 ; Country Code (0x00 - not supported)
retlw 0x01 ; HID Number of Class Descriptors
retlw 0x22 ; Report Descriptor Type
retlw .28 ; Size of the report descriptor
retlw 0x00
HID_Class_Descriptor_End
;EndPoint Descriptor
Endpoint_Descriptor1_In
retlw 0x07 ; Size
retlw USB_DESCRIPTOR_ENDPOINT ; Type
retlw HID_EP | _EP_IN ; Endpoint Number
retlw _INTERRUPT ; Attribute - Type of transfer
retlw 0x40
retlw 0x00 ; Size
retlw 0x01 ; Interval of polling
Endpoint_Descriptor1_In_End
;EndPoint Descriptor
Endpoint_Descriptor1_Out
retlw 0x07 ; Size
retlw USB_DESCRIPTOR_ENDPOINT ; Type
retlw HID_EP | _EP_OUT ; Endpoint Number
retlw _INTERRUPT ; Attribute
retlw 0x40
retlw 0x00 ; Size
retlw 0x01 ; Interval of polling
Endpoint_Descriptor1_Out_End
Subordinate_Descriptors_End
; Language Code Descriptor 0 - Special descriptor to notify Host which language ID it uses
String_Descriptor0
retlw 0x04 ; Length
retlw USB_DESCRIPTOR_STRING ; Type
retlw 0x09 ; Language ID: 0x409 for U.S. English
retlw 0x04
String_Descriptor0_End
; Language Code Descriptor 1 - Manufacturer String
String_Descriptor1
retlw String_Descriptor2_Length
retlw USB_DESCRIPTOR_STRING
retlw 0x00
retlw 'S'
retlw 0x00
retlw 'i'
retlw 0x00
retlw 'g'
retlw 0x00
retlw 'm'
retlw 0x00
retlw 'a'
retlw 0x00
retlw ' '
retlw 'I'
retlw 0x00
retlw 'n'
retlw 0x00
retlw 'd'
retlw 0x00
retlw 'u'
retlw 0x00
retlw 's'
retlw 0x00
retlw 't'
retlw 0x00
retlw 'r'
retlw 0x00
retlw 'i'
retlw 0x00
retlw 'a'
retlw 0x00
retlw 'l'
retlw 0x00
retlw 's'
retlw 0x00
retlw ' '
retlw 0x00
retlw 'c'
retlw 0x00
retlw 'o'
retlw 0x00
retlw 'n'
retlw 0x00
retlw 't'
retlw 0x00
retlw 'r'
retlw 0x00
retlw 'o'
retlw 0x00
retlw 'l'
retlw 0x00
retlw 's'
retlw 0x00
String_Descriptor1_End
; Language Code Descriptor 2 - Product String
String_Descriptor2
retlw String_Descriptor2_Length
retlw USB_DESCRIPTOR_STRING
retlw 'U'
retlw 0x00
retlw 'S'
retlw 0x00
retlw 'B'
retlw 0x00
retlw ' '
retlw 0x00
retlw 'F'
retlw 0x00
retlw 'i'
retlw 0x00
retlw 'r'
retlw 0x00
retlw 'm'
retlw 0x00
retlw 'w'
retlw 0x00
retlw 'a'
retlw 0x00
retlw 'r'
retlw 0x00
retlw 'e'
retlw 0x00
String_Descriptor2_End
; String Descriptor - Unknown string, transmitted in case Host sent a non valid string descriptor index
unknown_string_Descriptor
retlw unknown_string_Descriptor_Length
retlw USB_DESCRIPTOR_STRING
retlw 'U'
retlw 0x00
retlw 'n'
retlw 0x00
retlw 'k'
retlw 0x00
retlw 'n'
retlw 0x00
retlw 'o'
retlw 0x00
retlw 'w'
retlw 0x00
retlw 'n'
retlw 0x00
retlw '!'
retlw 0x00
unknown_string_Descriptor_End
; Class Specific Descriptors - HID
HID_Descriptor1
retlw 0x06 ; Usage Page = 0xff00 (Vender Defined Page 1)
retlw 0x00
retlw 0xff
retlw 0x09
retlw 0x01 ; Usage = Vender Usage 1
retlw 0xa1
retlw 0x01 ; Collection = Application
retlw 0x19
retlw 0x01 ; Usage Minimum
retlw 0x29
retlw 0x40 ; Usage Maximum => 64 input usages total (0x01 to 0x40)
; POTENTIAL ERROR ! ->
retlw 0x15
retlw 0x00 ; Logical Mimimum (Data values can have the minimum value of 0)
retlw 0x25
retlw 0x40 ; Logical Maximum (Data values can have the maximum value of 255)
retlw 0x75
retlw 0x08 ; Report Size (8 bit filed size)
retlw 0x95
retlw 0x40 ; Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input",
; "Output", or "Feature" item)
retlw 0x81
retlw 0x00 ; Input (Data, Array, Abs): Instantiates input packet fields based on the above report
; size, count, logical min/max, and usage.
retlw 0x19
retlw 0x01 ; Usage Minimum
retlw 0x29
retlw 0x40 ; Usage Maximum //64 output usages total (0x01 to 0x40)
retlw 0x91
retlw 0x00 ; Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size
; and count as "Input" fields, since nothing new/different was specified to the parser
; since the "Input" item.
retlw 0xc0 ; End Collection
HID_Descriptor1_End
-
Enumeration isn't complete until the host sends a Set Configuration request > 0.
If the comment here is accurate:
retlw 0x40 ; Logical Maximum (Data values can have the maximum value of 255)
the value should be 0x00FF
Be sure the host is retrieving the entire report descriptor.
Array data is intended for devices like keyboards, where the device reports only the keys pressed rather than pressed/not pressed for every key. Your report has 64 Usages and 64 bytes. If each byte corresponds to a Usage, "data, variable, absolute" might be more appropriate.
You could try simplifying the report descriptor as a way to isolate the problem.
Jan
-
; Language Code Descriptor 1 - Manufacturer String
String_Descriptor1
retlw String_Descriptor2_Length
I can't see where you are defining String_Descriptor2_Length,
but it should probably be String_Descriptor1_Length ?
-
Well, the update is that the system is working now (at least sufficient to submit it in my university).
Thanks for the corrections :).
However there are still a couple problems unsolved:
1. The device is ALWAYS recognized by Windows XP (running on a 32 bit machine), but when i attach the same device with a 64 bit machine running Windows 7, the percentage drops down to 30-35%.. but once it's recognized, the system works perfect. What can be the reasons?
2. Also, if we attach other USB Devices, we see Manufacturer's string and Product's string in a balloon, but there are no such notifications for this device.. Should i assume that there are no such notifications for HID Class Devices, or there is some problem in the code?
3. Lastly, write now the windows desktop application has to query the system for any new data.. This is extremely cumbersome in case polling interval has to be less than 50 ms, as it will introduce huge lags (due to multiple abstraction layers in windows). Is there someway that the Generic Windows HID Driver (as the specification suggests) queries the device every frame for if it has any new data to send, and when the device does send, the desktop application is notified (maybe by some callback routine)? Please suggest some techniques.
Thank You so much for Your time and efforts :).
To Jan Axelson: Your books are wonderfully written and Your website is equally supportive! Great resources! Thank You for Your efforts that gives developers an easy time! :)
Regards,
bajwa.
-
1. A hardware protocol analyzer will show what is happening on the bus and is the quickest way to identify the problem. Otherwise use whatever debugging tools you have to watch what happens during enumeration.
2. You may need a digitally signed INF files to cause the strings to display.
3. Create a thread that constantly looks for new received HID data and notifies the main application. In my WinUSB example at lvr.com/winusb.htm, see the ReadDataViaInterruptTransfer routine.
I'm glad to hear you've found my books and website useful!
Jan