USB Composite Device

Tsuneo
Member

posted October 23, 2006 01:22 AM            

USB composite device

Examples

USB_CDC_HID_IAD_10.zip


May 10, 2008 rev 1.0 Initial release


This example implements a composite device of CDC (with IAD) and HID
The CDC interface is based on the code of
"USB CDC implementation for 'F32x and 'F34x"
In either interface, CDC and HID, the device loops back the OUT transfer to IN.

Passed USBCV R1.3.1, the ch9 and HID test
Tested on these Windows version,
- Windows Vista SP1
- WinXP SP3 (usbser.sys: 5.1.2600.5508, usbccgp.sys: 5.1.2600.5512)

On the original WinXP SP2 (usbser.sys, usbccgp.sys: 5.1.2600.2180),
the HID interface of the device works well, but CDC causes BSOD when a test app opens the VCP.


USB_HID_composite_01.zip


Oct 17, 2007 rev 0.1 Released just firmware


This example implements three HID interfaces to SiLabs 'F320/'F340 DK.
Each interface has an interrupt IN EP and an interrupt OUT EP.
The firmware loops back the data sent to the OUT EP to the IN EP, on each interface.

Passed the USB compliance test, USBCV 1.3, ch9 and HID test.
Tested on HClient host app example on WinDDK.


USB_Mouse_INT_01.zip


Oct 23, 2006 rev 0.1 Initial release


This is a demonstration which shows a composite device combined SiLabs USB_HID\MouseExample and USB_Interrupt (USB_INT)

  • When you are asked a device driver, specify the INF folder attached to this zip file.
  • USB_Interrupt host application and device driver works with this implementation without any change.


1. What is composite device
Composite device is defined in the USB spec as follows (usb_20.pdf 5.2.3),
"A device that has multiple interfaces controlled independently of each other is referred to as a composite device."

Using composite device, multiple functions are combined into a single device.
Ex.
- Keyboard + Mouse
- Video + USB Hard disk
- I/O device (HID + USB_bulk)

Another advantage of composite device is that it eases the device driver development.
OS assigns a separate device driver to each Interface of the composite device as follows. Therefore, a dedicated monolithic driver is not required for newly designed device; you can realize it using existing drivers.

+----------------------------+ +---------------------- | Composite Device | | Host PC | | | | Function 0 -- Interface 0 --------- Device driver A <---> | | | | Function 1 -- Interface 1 --------- Device driver B <---> +----------------------------+ +-----------------------


When OS has some required drivers as built-in, they are available for the composite device. These OS built-in device drivers are called as USB class driver.
"Approved Class Specification Documents" from USB.org
http://www.usb.org/developers/devclass_docs#approved

Windows have these built-in class drivers.
"USB FAQ: Introductory Level - USB Class Drivers" from MS WHDC
http://www.microsoft.com/whdc/system/bus/usb/USBFAQ_intro.mspx

Please note, available drivers for a composite device are not limited only to class drivers. Any driver can be applied, as long as it doesn't require a device class (class defined in device descriptor). For example, SiLabs USB_INT and USB_bulk drivers are also applicable for composite devices.


2. How Windows handles a composite device
When a device satisfies these three requirement, Windows system recognizes the device as a composite device.

  1. The class field of the device descriptor equals to zero: (bDeviceClass) = (0x00)
  2. Single Configuration
  3. Multiple Interfaces


 

[Note]
WinXP SP2, Win2k3 SP1 and Vista supports this alternative requirement.
1'. The class, subclass and protocol fields of the device are that of Interface Association Descriptor:
(bDeviceClass, bDeviceSubClass, bDeviceProtocol) = (0xEF, 0x02, 0x01)


When an USB device is plugged in to a PC, the system reads out the device descriptor of the device and makes these Device ID.

USB\VID_vvvv&PID_pppp
USB\VID_vvvv&PID_pppp&REV_rrrr
(vvvv, pppp, rrrr: four digit hex number for the VID, PID, device release number. Matches to idVendor/ idProduct/ bcdDevice, defined in the device descriptor)


The system searches device database on the registry, installed by INF files. When the system finds the Device ID in a device record, it assigns the device driver specified by the record. However, when it cannot find any matched record, and the device Configuration satisfies above criteria, the generic composite parent driver is loaded. This parent driver parses the Configuration of the device, and assigns this Device ID to each Interfaces.

USB\VID_vvvv&PID_pppp&MI_mm
USB\VID_vvvv&PID_pppp&REV_rrrr&MI_mm
(mm: Interface number of the corresponding function, two digit hex number)


As of the Interface which specifies a class, the system also assigns this Compatible ID.

USB\CLASS_cc
USB\CLASS_cc&SUBCLASS_ss
USB\CLASS_cc&SUBCLASS_ss&PROT_pp
(cc/ ss / pp: two digits hex number.
bInterfaceClass/ bInterfaceSubClass/ bInterfaceProtocol, from the Interface descriptor)


The system searches these Device ID and Compatible ID in the device database again. When it finds a matched record, it assigns the specified device driver to the Interface. However, when it cannot find any matched record, it shows 'New Hardware Wizard' to users and asks them to install the device driver.

"Enumeration of the Composite Parent Device" from MSDN
http://msdn2.microsoft.com/en-us/library/aa476434.aspx

3. Implementation
On USB application, firmware, device driver and host application are closely related. It is desirable to make separate prototypes of firmwares and host applications for each Interface first. After confirming them to work properly, combine them together.

3.1 Device firmware
When the source code is well organized, modification of the firmware is easy. Based on one of the prototypes, copy a part of code from other prototypes and insert it to corresponding part of the base source code.
In other word, the source codes should be organized considering to make it a composite device. When these parameters are defined by #define macro or enum instead of direct number in each prototype, the combination of prototypes is done smoothly.

  • Interface number
  • Endpoint address
  • Endpoint status (IDLE / HALT)

3.1.1 Descriptors

3.1.1.1 Device descriptor

  • bDeviceClass: Must be assigned to zero
  • idVendor, idProduct: VID/PID must be unique, to avoid conflict to other devices.

3.1.1.2 Configuration descriptor

  • wTotalLength: The total number of bytes of Configuration set, includes all of Interface sets
  • bNumInterfaces: Number of Interfaces included in this Configuration

Configuration set means these descriptors, for example.

Configuration descriptor
- Interface descriptor (0)
- - accessory descriptor, such as HID class descriptor, if any
- - Endpoint descriptors
- Interface descriptor (1)
- - accessory descriptor, such as HID class descriptor, if any
- - Endpoint descriptors

HID report descriptor and String descriptors are not included in the Configuration set.

3.1.1.3 Interface descriptors

  • bInterfaceNumber: Index of Interfaces, starting from zero
  • bInterfaceClass: Specify class code for this Interface

If any specific class code is not assigned to the Interface, set bInterfaceClass to 0xFF (Vendor specific). 0x00 (Reserved) would work, but 0xFF is better.

3.1.1.4 Endpoint descriptors

  • bEndpointAddress: must be unique on each Endpoint descriptor


Any duplicated Endpoint across Interfaces is not allowed in a composite device.


3.1.2 Standard requests


3.1.2.1 Additional Descriptor handling
Get_Descriptor must support additional descriptors asked by the host.

  • Configuration descriptor: return full Configuration set (see 3.1.1.2)
  • Class-specific descriptors:


When the descriptor type in request (MSB of wValue) is not Device(1), Configuration(2) or String(3), the request may be for class-specific descriptor (in full-speed devices). In this case, wIndex field of the Setup data shows the Interface number in question. According to the class specified by the Interface (wIndex), Get_Descriptor must return the class-specific descriptor specified by the MSB of wValue.

When the class supports Set_Descriptor request, it must be handled similarly to Get_Descriptor.

Interface and Endpoint descriptors cannot be directly accessed with Get_Descriptor or Set_Descriptor. Therefore, Get_Descriptor and Set_Descriptor have no need to support them.

3.1.2.2 Additional Interfaces handling
wIndex field of the Setup data shows the Interface number in question. When this Interface number matches to the additional Interfaces, handle the requests as follows.

  • Get_Status: return Zero
  • Get_Interface: return current alternate Interface number
  • Set_Interface: set current alternate Interface to one specified by the request


When the Interface in question doesn't have any alternate Interface, Get_Interface returns Zero. And Set_Interface succeeds when the wValue is Zero, otherwise return STALL.

3.1.2.3 Additional Endpoints handling

  • Get_Status: return HALT condition of the Endpoint
  • Clear_Feature: recover the Endpoint from HALT
  • Set_Feature: set the Endpoint to HALT
  • Set_Configuration: Setup additional Endpoints


When Get_Status, Clear_Feature and Set_Feature are issued to an Endpoint, wIndex field of the Setup data indicates the Endpoint address.

When the Interfaces doesn't have any alternate Interface, set up the Endpoints in Set_Configuration request. As of the Interface with any alternate Interface, set up the Endpoints belonging to the Interface in Set_Interface.


3.1.3 Class-specific requests

wIndex field of the Setup data of the request indicates the Interface to which this request is issued. Therefore, dispatch the request by wIndex first, and copy the each handler for class-specific requests from the prototypes under each case.


3.1.4 Endpoint handling

When the Endpoint address and Endpoint status are defined by macro, modification on this part finishes by copying the Endpoint handler of each prototype to the base one.


3.2 Device driver and host application
OS built-in class drivers are designed to work with composite devices. In most case, these drivers are applicable to composite devices without any change of default INF file. However, device drivers provided by vendors are not always designed to work with composite devices. INF file and host application code should be modified for these drivers. The device driver itself should work without any change. Of course, rare exception may exist.

3.2.1 INF file

When the device driver requires an INF file even for single use, the INF file is required as a part of composite device. The INF file defines the Device ID as follows.

USB\VID_vvvv&PID_pppp
USB\VID_vvvv&PID_pppp&REV_rrrr


For a composite device, the Interface number must be added to this Device ID.

USB\VID_vvvv&PID_pppp&MI_mm
USB\VID_vvvv&PID_pppp&REV_rrrr&MI_mm


For example, when you add the USB_Bulk function (Interface with bulk IN/OUT Endpoints) to your composite device as the Interface number 1, the Device ID in the INF file (SilabsBulk.inf) is modified as follows.

USB\VID_vvvv&PID_pppp&MI_01
(vvvv, pppp: VID/PID must be unique)


 


3.2.2 Endpoint address and pipe name / device path name

When two or more devices are combined into a single composite device, the Endpoint addresses must be often changed to fit to the newly designed device. Usually, the pipe name and device path name from device drivers are designed to hide the Endpoint address. Therefore, in most case, Endpoint address reassignment doesn't affect to the host application.

However, there are some drivers which expose the Endpoint address directly to the pipe name. For these drivers, the host application must be modified to reflect the Endpoint address assignment. Confirmation for this point is desirable before planning a new device.


     

  • OS built-in class drivers hide Endpoint address behind its device path name.
  • MS WinDDK bulkusb and isousb example driver hide Endpoint address behind the pipe name (a part of device path name).
  • SiLabs USB_INT and USB_Bulk device drivers hide it behind the pipe name (a part of device path name).
  • Cypress ezusb.sys driver hides Endpoint address behind its pipe number.
  • Cypress CyUSB.sys driver exposes Endpoint address directly. But when the code follows the example of CCyUSBDevice::BulkInEndPt in CyAPI.chm, the Endpoint address is hidden behind the index of the Endpoint array.


When a device applies the same class to multiple Interfaces, the host application should be modified to distinguish these Interfaces.

Tsuneo

[This message has been edited by Tsuneo (edited May 10, 2008).]

IP: Logged

Patryk
Member

posted October 23, 2006 05:51 AM         

Just some spottings/clarifications to make your excellent post perfect :-)

1. 3.1.2.1...
When the descriptor type in request (MSB of wValue) is not Device(1), Configuration(2) or String(3), the request may be for class-specific descriptor (in full-speed devices)."

For example HID devices - HID and report descriptors must be supported that way. And these devices can be (and mostly are) low-speed. Recipient field of bmRequestType (set to INTERFACE or ENDPOINT) should be used to distinguish class descriptors from standard ones.
USB Common Class Specification, p.8:
"3.11 Identifying Class and Vendor-Specific Requests and Descriptors
The standard GET_DESCRIPTOR request (with the bRequestType.Type field set to standard) is used to directly request class or vendor-specific descriptors. The class associated with such a request is determined by the class of the bmRequestType.Recipient. When the bmRequestType.Recipient field is set to INTERFACE or ENDPOINT, the wIndex field identifies the desired interface or endpoint. All endpoints within an interface use that interface抯 class, subclass and protocol."

2. "3.1.2.2 ...
When the Interface in question doesn't have any alternate Interface, Get_Interface returns Zero. And Set_Interface succeeds when the wValue is Zero, otherwise return STALL."

Set_Interface need not to be supported at all in such (most common) case.
USB 2.0 spec, p.259:
"9.4.10 Set Interface
If a device only supports a default setting for the specified interface, then a STALL may be returned in the Status stage of the request."

3. "3.2.2..."
USBIO.SYS driver from Thesycon driver exposes Endpoint address directly.

Regards,
Patryk

IP: Logged

Tsuneo
Member

posted October 17, 2007 09:31 AM            

Added an example, USB_HID_composite
See the first post.

Tsuneo

IP: Logged

MikeB
New Member

posted November 02, 2007 06:29 AM         

Tsuneo,

Thank you for providing this excellent example. Can you point me to a clear description of how one communicates with composite HID devices from Windows? I have found several examples for single devices but I have not yet worked out how this translates to the composite device case.

Many thanks.

Mike.

IP: Logged

LiMing.Sun
Member

posted November 02, 2007 09:33 PM            

Seems that the 3-HID composite devices share the same VID and PID,i just want to know how to distinguish them on host;
Besides,as mentioned by tsuneo,packets between the composite device and host may miss their order,we need to build some rules to arrange packets in their order for right HID.

IP: Logged

Tsuneo
Member

posted November 03, 2007 10:00 PM            

I was writing a host app example for the three HID composite firmware.

I'm using a note PC for the development of these personal projects, but the hard disk was broken on Wednesday of the last week. I have a recent backup for data files (one week ago), then the crash is not so much disastrous, I thought so at first time.

But it takes so long to recover the OS and applications on a new HD, because tons of heavy apps are installed, like KEIL (C51 and ARM), Xilinx and Altera, TI DSP, MS VS (2005,2003 VC6) and Office, Eclipse, etc. etc...
Then, this weekend is wasted out for installations.

Please wait for a while.


"Seems that the 3-HID composite devices share the same VID and PID,i just want to know how to distinguish them on host;"

As I wrote in the first post of this topic,
an independent device driver instance is assigned to each interface of the three HIDs. These instances share the same VID/PID, but the interface number is attached to the device ID.

USB\VID_vvvv&PID_pppp&MI_mm
(mm: Interface number of the corresponding function, two digit hex number)

Run msinfo32.exe (included in the Windows system) and you'll confirm it.

This is an example of msinfo32 output from MS Coding4Fun brog.
"Is that you? Writing Better Software for Cool USB Hardware"


(click image to zoom)


When the host app searches the device using SetupDi-API with the given VID/PID, it will find more than one instance. The usual code breaks the search loop when it finds a single instance, but the search loop should continue until no more matched instance is found.

These instances are distinguished by the device "path" string.
The DevicePath strings are almost same as "PNP Device ID" of msinfo32,
and contains different "MI_mm".

Tsuneo

[This message has been edited by Tsuneo (edited November 03, 2007).]

IP: Logged

MikeB
New Member

posted November 05, 2007 05:21 AM         

Tsuneo,

I'm sorry for your laptop problems. Thanks for the extra explanation.

Mike.

IP: Logged

Tsuneo
Member

posted May 10, 2008 08:10 AM            

Added an example of a composite device, CDC (with IAD) + HID, to the first post.

Interface Association Descriptor (IAD)

There are classes like CDC, which consists of multiple interfaces.
IAD emphasize these bound interfaces which belongs to single class on the configuration set.

On the Device descriptor, the triad (Class, Subclass, Protocol) is set to that of IAD as follows.

0xEF, // bDeviceClass (Misc)0x02, // bDeviceSubClass (common)0x01, // bDeviceProtocol (IAD)

On the Config descriptor set, IAD is placed just before the interface descriptors which are tied together.

// Interface Association Descriptorsizeof(Tinterface_association_descriptor), // bLengthDSC_TYPE_IAD, // bDescriptorType = 110x00, // bFirstInterface0x02, // bInterfaceCount0x02, // bFunctionClass (Communication Class)0x02, // bFunctionSubClass (Abstract Control Model)0x01, // bFunctionProcotol (V.25ter, Common AT commands)0x00, // iInterface }, // // Follows the first interface bound by the IAD //


IAD declares the index of the first interface, and the number of the bound interfaces, placed contiguously. The triad on the IAD matches to that of the main interface of the class.

There is no other difference from ordinary composite devices.

Tsuneo

IP: Logged

smhinchy
New Member

posted May 13, 2008 04:20 PM         

Hello,

Should this example work out of the box? I am using SiLabs IDE 3.3, SDCC Version 2.8.0 and Windows XP SP2. The program compiles and downloads, but when I run it I get the USB three dings and nothing else.

Any suggestions?

Shawn

IP: Logged

vanmierlo
Member

posted May 14, 2008 04:01 AM            

In the ReadMe.txt Tsuneo wrote that it works on WinXP SP3 and Vista SP1. I suggest installing the latest SP.

Maarten

IP: Logged

xiaofan
Member

posted May 15, 2008 03:42 AM         

As discussed previously, you need two hot fixes for Windows XP SP2.
http://www.cygnal.org/ubb/Forum9/HTML/001572.html

It is easier to use Windows XP SP3. I have tested a dual CDC-ACM IAD USB Composite device under Windows XP SP3 and it is working.

IP: Logged

ryyu
New Member

posted May 15, 2008 09:48 PM            

I am currently studying USB HID.
I want to make a composite HID mouse + keyboard.Besides, I have downloaded the USB_HID_composite_01. However, I don't know how to control the cursor or keyboard through that example. Therefore, could anyone give me some more helpful examples, Thanks

Ray

IP: Logged

Tsuneo
Member

posted May 15, 2008 11:49 PM            

Hello Ray,

I recommend you to make separated mouse and keyboard implementations at first.
Then, combine them into a single composite device.

SiLabs provides a mouse example.
C:\SiLabs\MCU\Examples\C8051F320_1\USB_HID\MouseExample
C:\SiLabs\MCU\Examples\C8051F34x\USB_HID\MouseExample

Then, you have to make a keyboard implementation.
The USB keyboard and mouse implementation is fully described on the USB HID spec.

USB HID spec 1.11
http://www.usb.org/developers/devclass_docs/HID1_11.pdf"
HID Usage Table 1.12
http://www.usb.org/developers/devclass_docs/Hut1_12.pdf

Of course, the HID spec is massive one and it isn't written just for keyboard and mouse. Then, you have to extract the concerning description from the spec.
This topic guides you how to find the keyboard implementation on the spec.
USB HID KEYBOARD (Search a Programmer)

On the spec, the mouse description follows the keyboard one.


You have to assign different VID/PID (at least PID) for the single keyboard, and the composite device implementation.

If you assign the same VID/PID to another implementation, delete the device instance on the Device Manager, once.

You can see all instances on the Device Manager using following procedure.
1) Copy these two lines to a blank text file, and rename the file to DevManager.bat
set devmgr_show_nonpresent_devices=1
start devmgmt.msc

2) Double click DevManager.bat, and Device Manager comes up.
From 'View' menu, select 'Show hidden devices'

Tsuneo

IP: Logged

xiaofan
Member

posted May 16, 2008 03:31 AM         

There is another way to do this without using a composite device. You can actually implement using an HID device with two reports, one for keyboard and one for mouse.

IP: Logged

xiaofan
Member

posted May 16, 2008 03:41 AM         

Example from ST.
Keyboard + Mouse + Gamepad:

http://www.st.com/stonline/books/pdf/docs/6904.pdf

The code is here:
http://www.st.com/mcu/forums-cat-5673-12.html

IP: Logged

Tsuneo
Member

posted May 16, 2008 04:28 AM            

Ah, you are talking about multiple top-level collections.
It was discussed once on this topic.

multiple HID and one MSD on a -340

The flaw of this method is that it doesn't support boot device.

Tsuneo

IP: Logged

Robonz
New Member

posted May 20, 2008 09:40 AM         

Hi Tsuneo

Firstly thanks for all your reference code I hope Silabs are sending you money or beer or something, because you have helped us a lot over the years. I dont know how you find the time to do all the posting you do.

Two of us have been working on an urgent bug for a commercial product we sell. We have spent 4 x 12 hour days to find the cause using a bus analyser. The root cause was quite simple but it took us a long time. I thought I would share this fix with you all.

When you have firmware that must turn off USB interrupts for timing critical reasons there is a catch with the current code.

A sent stall flag can arrive with a setup packet in one interrupt. All our previous code did not turn off interrupts. Sent stalls always (well we didnt have a bus analyser) came as a seperate interrupt.

Here is the fix, but it doesnt work, see
http://www.cygnal.org/ubb/Forum9/HTML/001600.html

if (ControlReg & rbSTSTL){
POLL_WRITE_BYTE(E0CSR, 0);
Ep_Status[0] = EP_IDLE;
// DO NOT return;
}
// continue processing other interrupt flags. If you return you could ignore an out packet like we were. This results in a very intermitent packet loss and can crash Vista during S3 resuming.

Cheers
Keith

[This message has been edited by Robonz (edited May 21, 2008).]

IP: Logged

Tsuneo
Member

posted May 21, 2008 03:36 AM            

Thanks Keith,

You make me aware the problem of STALL handling here.

Following USB spec, STALL condition of the default endpoint is cleared just by SETUP packet from the host. Then, the stack has to clear SDSTL and return to EP_IDLE, just when the engine receives SETUP.

However, my code (and SiLabs' also) clears SDSTL when it sees STSTL bit, ie. when the STALL is sent to the host, before it sees SETUP. Usually, it works fine, because the host sends SETUP next to STALL reception, but it is not guaranteed.

I should examine the behavior of the engine on this STALL handling more.
The "if" clause which sees rbSTSTL may be deleted entirely.

Tsuneo

IP: Logged

scene
New Member

posted August 01, 2008 05:01 AM         

Hi Tsuneo,

I wonder if you could help me with me with a related question.

I have a situation where I need to emulate a commercial HID device which is supplied with it's own vendor driver (say, a touch screen). Additionally, I want to add keyboard and mouse interfaces to this device to make a composite device. The VID/PID will 'copied' from the commercial HID device.

I would like Windows to bind the original vendor driver to the device and also bind it's KB/Mouse drivers to the other interfaces.

Is this possible?

In my initial experiments I cannot get the original vendor driver to bind if any additional interfaces are added to the original descriptors. Would IAD help?

Thanks.

Ray.

[This message has been edited by scene (edited August 01, 2008).]

IP: Logged

Tsuneo
Member

posted August 01, 2008 06:34 AM            

Hello Ray,

"Is this possible?

Sound like possible.

"In my initial experiments I cannot get the original vendor driver to bind if any additional interfaces are added to the original descriptors.

Did you modify the INF file of the original device?
The custom HID device should have an INF file, to bind it to the custom device driver.
As I wrote in above "3.2.1 INF file" section, you have to modify the Device ID on the INF file. Find the Device ID like USB\VID_vvvv&PID_pppp, and add the interface number, USB\VID_vvvv&PID_pppp&MI_mm

After modifying the INF file, delete the device instance of the original HID device once. Device instance records are held on the registry. Windows doesn't refresh it automatically, even when the device or INF file is changed. You have to do it manually. This utility is handy for this job.

USBDeview
http://www.nirsoft.net/utils/usb_devices_view.html

For the additional keyboard and mouse, no INF file is required.

Tsuneo

IP: Logged

scene
New Member

posted August 01, 2008 09:08 AM         

Thanks for your prompt reply.

Is there ANY way to do this without editing the .inf file?

Alternatively, is there a way to make the vendor driver bind to the first interface found?

Ray.

[This message has been edited by scene (edited August 01, 2008).]

IP: Logged

Tsuneo
Member

posted August 03, 2008 02:16 AM            

In above post, I described a popular method.
But some tablet manufacturers implement the HID device in another way.

I examined a Wacom tablet and it's device driver.
This tablet is a generic HID device with digitizer usage.

===>Device Descriptor<===bLength: 0x12bDescriptorType: 0x01bcdUSB: 0x0100bDeviceClass: 0x00 -> This is an Interface Class Defined DevicebDeviceSubClass: 0x00bDeviceProtocol: 0x00bMaxPacketSize0: 0x08 = (8) BytesidVendor: 0x056A = WACOM Co., Ltd.idProduct: 0x0021bcdDevice: 0x0101iManufacturer: 0x01 English (United States) "Tablet"iProduct: 0x02 English (United States) "GD-0608-U"iSerialNumber: 0x00bNumConfigurations: 0x01

===>Configuration Descriptor<===bLength: 0x09bDescriptorType: 0x02wTotalLength: 0x0022 -> ValidatedbNumInterfaces: 0x01bConfigurationValue: 0x01iConfiguration: 0x00bmAttributes: 0x80 -> Bus PoweredMaxPower: 0xFA = 500 mA

===>Interface Descriptor<===bLength: 0x09bDescriptorType: 0x04bInterfaceNumber: 0x00bAlternateSetting: 0x00bNumEndpoints: 0x01bInterfaceClass: 0x03 -> HID Interface ClassbInterfaceSubClass: 0x01bInterfaceProtocol: 0x02CAUTION: This may be an invalid bInterfaceProtocoliInterface: 0x00

===>HID Descriptor<===bLength: 0x09bDescriptorType: 0x21bcdHID: 0x0100bCountryCode: 0x00bNumDescriptors: 0x01bDescriptorType: 0x22wDescriptorLength: 0x004E

===>Endpoint Descriptor<===bLength: 0x07bDescriptorType: 0x05bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1bmAttributes: 0x03 -> Interrupt Transfer TypewMaxPacketSize: 0x000A = 0x0A bytesbInterval: 0x05

HID Report DescriptorUsage Page: 13 (Digitizer)Usage: 1 (Digitizer)Collection Report ID: 2Usage: 0 (Undefined)Report Size: 8Report Count: 9Logical Minimum: 0Logical Maximum: 255Input: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

Usage: 58 (Program Change Keys)Logical Maximum: 2Report Count: 1Feature: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

Report ID: 3Usage: 0 (Undefined)Logical Maximum: 255Feature: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

Report ID: 4Usage: 58 (Program Change Keys)Logical Maximum: 1Feature: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

Report ID: 5Usage: 0 (Undefined)Logical Maximum: 255Report Count: 8Feature: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

Report ID: 6Usage: 0 (Undefined)Feature: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

Report ID: 7Usage: 0 (Undefined)Report Count: 4Feature: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

Report ID: 8Usage: 0 (Undefined)Feature: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

End Collection

As this device tree shows, this HID tablet is recognized as generic HID device with the built-in HID driver using the default input.inf on Windows. Instead of providing a custom device driver directly to this device, Wacom installs HID minidrivers for the two virtual HID devices, one for mouse and one for keyboard. The minidrivers catch the generic HID device, and translate the device traffic into those of HID mouse and keyboard. Clever way.

Device managerDevice connection tree

ACPI- PCI bus - Host controller - USB root hub- USB Human Interface device USB\VID_056A&PID_0021\6&39649F58&0&4- - HID device HID\VID_056A&PID_0021\7&AC1626&0&0000

Wacom virtual HID Driver ROOT\HIDCLASS\0000- Wacom HID Pen HID\WACOMVIRTUALHID&COL01\1&2D595CA7&0&0000- Wacom HID Digitizer HID\WACOMVIRTUALHID&COL02\1&2D595CA7&0&0001- Wacom Mouse HID\WACOMVIRTUALHID&COL03\1&2D595CA7&0&0002- HID device HID\WACOMVIRTUALHID&COL04\1&2D595CA7&0&0003

Virtual Keyboard Driver ROOT\HIDCLASS\0001- Virtual Keyboard Interface HID\WACOMVKHID&COL01\1&4784345&0&0000- Virtual Keyboard HID\WACOMVKHID&COL02\1&4784345&0&0001- Virtual Media Keys HID\WACOMVKHID&COL03\1&4784345&0&0002

For this configuration, there is no need to modify the INF file to make it a composite device or top-level collections.

Tsuneo

IP: Logged

egawtry
Member

posted October 13, 2008 07:18 PM            

Tsuneo (or anyone who knows),

I implemented this setup, but while I see the CDC just fine, I am not seeing the HID when I enumerate HIDs. Any ideas? If I have to I can post code, but I would like to avoid posting huge amounts of code.

Above you mention changes to the INF file - could that be an issue? I am using my standard CDC driver INF.

-Erik

IP: Logged

Tsuneo
Member

posted October 13, 2008 08:39 PM            

Hi Erik,

At the top of the first post of this topic, I posted a composite device of CDC and HID, USB_CDC_HID_IAD_10.zip

For a composite device of CDC, IAD (Interface Association Descriptor) is required. And it is supported after WinXP SP3 and Vista SP1.

Tsuneo

IP: Logged

egawtry
Member

posted October 15, 2008 03:28 PM            

Ok, I must be a dummy because I cannot figure out several things:

1. Why do you have only one buffer for both input and output packets?

2. What do you mean by "loopback"?

3. Why was everything moved to the main loop and polled instead of leaving it in the interrupt? (Timing?)

==================================

I am seeing the CDC and HID interfaces, but I cannot get the HID to read/write (it is always NULLs on the PC end). Any ideas there?

Thanks,
-Erik

IP: Logged

Tsuneo
Member

posted October 16, 2008 12:51 PM            

"1. Why do you have only one buffer for both input and output packets?"

For loopback.
I could use two separate buffers for IN and OUT, and copy the contents from OUT to IN.
But I cut the corners


"2. What do you mean by "loopback"?"

Loopback means, sending back the output report from the host directly to the host.
Orthodox way to check communication.


"3. Why was everything moved to the main loop and polled instead of leaving it in the interrupt? (Timing?)"

Which interrupt do you mean?
If it is the Endpoint interrupt, it's because,
- to show the variety of the endpoint handling
- to make the modification target clear

When the data load/unload is handled in the endpoint interrupts, its timing is determined by the host.
When it is handled in a main loop task, or in an other interrupt like timer ISR, its timing is determined by the event on the device side. ie. it is possible that the device returns an input report just when a user pushes a key.

If the USB routines, POLL_WRITE_BYTE, etc., are called in a main loop task, these calls are guarded by disabling USB interrupt around the call, as the example shows.

If the USB routines are called an other ISR like timer, no guard is required, but the interrupt priority of the ISR should be the same as USB ISR.


"but I cannot get the HID to read/write"

Modify Jan Axelson's HID example for host app, and check it.
http://www.lvr.com/hidpage.htm
These examples fill just the first 2 bytes of the output report.
Modify it to fill full 64 bytes, and run the example.

Tsuneo

IP: Logged

egawtry
Member

posted October 17, 2008 09:48 AM            

"Loopback means, sending back the output report from the host directly to the host.
Orthodox way to check communication."

Why would I want to do that? I just want to send packets to and from the device, like in the HID from INT example. I cannot do everything from the InputReport and OutputReport calls - the USB HID spec says that to do that is bad.

I guess I will have to hack on it to resolve this.

-Erik

IP: Logged

Tsuneo
Member

posted October 17, 2008 10:35 AM            

"Why would I want to do that?"

Of course, you don't need to do that, once the USB side has been established. But I needed it to test the implementation. Also, it was needed to show the implementation works fine.

As this topic has been discussed on the composite device, I posted the simplest implementation just along with the theme. The usage of HID endpoints was discussed on "How to convert USB_Interrupt (USB_INT) to HID". Then apply the experience to the HID endpoints to extend them.

If you don't like this focused approach and request more detailed examples, sorry, it's beyond my personal project.


"I cannot do everything from the InputReport and OutputReport calls - the USB HID spec says that to do that is bad.

Huh?
Do you confuse interrupt endpoints with class specific requests?
I don't see any violation of HID spec on my implementation at this point.

Tsuneo

IP: Logged

egawtry
Member

posted October 17, 2008 11:29 AM            

Tsuneo,

Your code is something like this:
===============================
EUSB0_save = EIE1 & 0x02; // save USB interrupt enable bit
EIE1 &= ~0x02; // disable USB interrupt temporarily

OUT3_FIFO_loaded = FALSE;
IN3_FIFO_empty = FALSE;

POLL_WRITE_BYTE( INDEX, 3 ); // loop back the data from OUT EP to IN EP
// unload packet from OUT FIFO
FIFO_Read_xdata( FIFO_EP3, EP3_PACKET_SIZE, HID_InOut_Packet );
POLL_WRITE_BYTE( EOUTCSRL, 0 ); // Clear Out Packet ready bit
// load packet to IN FIFO
FIFO_Write_xdata( FIFO_EP3, EP3_PACKET_SIZE, HID_InOut_Packet );
POLL_WRITE_BYTE( EINCSRL, rbInINPRDY ); // set FIFO ready flag

EIE1 |= EUSB0_save; // restore USB interrupt
===============================

That is great for loopback, but where do you handle the read and write of the basic data to the Host? In the "HID from INT" (good job there, btw) code, it is in the handler, but all you do in this handler is echo the data back to the host. There is no way to change it in the 34x. If I change the HID_InOut_Packet, it gets erased by the read before the write back to the host even occurs.

-Erik

IP: Logged

Tsuneo
Member

posted October 17, 2008 01:31 PM            

OK, this is the separated version, without any cutting corner

Tsuneo

USB_Main.h//-----------------------------------------------------------------------------// Global variables//-----------------------------------------------------------------------------

extern BYTE xdata HID_Out_Packet[ HID_OUT_REPORT_SIZE ]; // Last packet received from hostextern BYTE xdata HID_In_Packet[ HID_IN_REPORT_SIZE ]; // packet to send to host

USB_Main.c

// HID loopback supportBYTE xdata HID_Out_Packet[ HID_OUT_REPORT_SIZE ]; // Last packet received from hostBYTE xdata HID_In_Packet[ HID_IN_REPORT_SIZE ]; // packet to send to host

void main(void){ ... { // task2: USB EP3 handling - HID support // loopback from OUT to IN unsigned char EUSB0_save; unsigned char idx;

// Read out from HID OUT EP if ( (Ep_StatusOUT3 != EP_HALT) && OUT3_FIFO_loaded ) { // To prevent conflict with USB interrupt EUSB0_save = EIE1 & 0x02; // save USB interrupt enable bit EIE1 &= ~0x02; // disable USB interrupt temporarily

OUT3_FIFO_loaded = FALSE;

POLL_WRITE_BYTE( INDEX, 3 ); // unload packet from OUT FIFO FIFO_Read_xdata( FIFO_EP3, HID_OUT_REPORT_SIZE, HID_Out_Packet ); POLL_WRITE_BYTE( EOUTCSRL, 0 ); // Clear Out Packet ready bit

EIE1 |= EUSB0_save; // restore USB interrupt }

// Write to HID IN EP if ( (Ep_StatusIN3 != EP_HALT) && IN3_FIFO_empty ) { // copy data for loopback for ( idx = 0; idx < HID_OUT_REPORT_SIZE; idx++ ) HID_In_Packet[idx] = HID_Out_Packet[idx];

// To prevent conflict with USB interrupt EUSB0_save = EIE1 & 0x02; // save USB interrupt enable bit EIE1 &= ~0x02; // disable USB interrupt temporarily

IN3_FIFO_empty = FALSE;

POLL_WRITE_BYTE( INDEX, 3 ); // load packet to IN FIFO FIFO_Write_xdata( FIFO_EP3, HID_IN_REPORT_SIZE, HID_In_Packet ); POLL_WRITE_BYTE( EINCSRL, rbInINPRDY ); // set FIFO ready flag

EIE1 |= EUSB0_save; // restore USB interrupt } } }}

USB_Class_Request.c//-----------------------------------------------------------------------------// Get_Report//-----------------------------------------------------------------------------

static void Get_Report( void ){ if ( (Setup.bmRequestType == IN_CL_INTERFACE) && (Setup.wValue.c[LSB] == 0) ) // Report ID { switch ( Setup.wValue.c[MSB] ) { case HID_REPORT_TYPE_INPUT: // Input report DataPtr = (BYTE *)HID_In_Packet; // <------- modified DataSize = HID_IN_REPORT_SIZE; setup_handled = TRUE; break;

[This message has been edited by Tsuneo (edited October 17, 2008).]

IP: Logged

egawtry
Member

posted October 17, 2008 02:12 PM            

Wow! That is exactly what I did to make it work! Great minds think alike, eh? :-)

Thank you for the code.

-Erik

IP: Logged

jeremy
Member

posted November 05, 2008 04:49 PM         

In Usb_Reset(), the status of each EP is set to EP_HALT:

Ep_StatusIN1 = EP_HALT;

Why is this necessary? The EP is only set to EP_IDLE on another SET_CONFIG. I'm finding Windows is issuing a USB reset, and my firmware then stops responding because the EP is "halted".

IP: Logged

Tsuneo
Member

posted November 05, 2008 07:02 PM            

In Usb_Reset(), the status of each EP is set to EP_HALT:
Ep_StatusIN1 = EP_HALT;

Why is this necessary? The EP is only set to EP_IDLE on another SET_CONFIG.

I don't think this implementation has any problem.

When the device receives bus reset, the device state moves to the DEFAULT state. EP1-3 should not respond to any access from the host side until the device state moves to CONFIGURED by Set_Configuration.

In other word, to access the EPs other than the default EP, the host should issue Set_Address and Set_Configuration after bus reset - ie. re-enumeration.


"I'm finding Windows is issuing a USB reset, and my firmware then stops responding because the EP is "halted".

Windows often put bus reset, unnecessarily.
But as long as I know, Windows always does re-enumeration after bus reset.

If it doesn't, it's a bug of Windows.
Please show the details when it occurs.
it's worth to report the bug to MS.

Tsuneo

IP: Logged

egawtry
Member

posted November 10, 2008 12:34 PM            

Tsuneo,

Any idea on how to get the pair of connections from Windows? (HID+CDC) I can easily find all the 342's HID and CDC connections, but there isn't any way I have found to pair them up.

I am currently pairing them assuming that they are enumerated in order, eg. the first HID is the first CDC, the second HID is the second CDC, etc. - but I don't trust that algorythm. Windows has to have a call or a registry entry for Multi interfaces.

Thanks for any ideas.

-Erik

IP: Logged

Tsuneo
Member

posted November 11, 2008 07:59 AM            

Hi Erik,

"Any idea on how to get the pair of connections from Windows? (HID+CDC) I can easily find all the 342's HID and CDC connections, but there isn't any way I have found to pair them up."

Do you mean,
You have several composite devices (HID + CDC) of same VID/PID, connected to single PC. You want to match the device handles of HID and CDC in pair from the same device.


Match the pair using the serial number on the device.

a) HID device path and serial number

HID device is counted up using SetupDi- API, as usual.
You'll see a typical example in this file.

C:\SiLabs\MCU\Examples\C8051F34x\USB\USB_HID\BlinkyExample\Host\HIDDevice.cpp
CHIDDevice::GetHidDevicePath()

After opening the device handle using CreatFile, serial number of the HID device is retrieved using this API,

HidD_GetSerialNumberString()
http://msdn.microsoft.com/en-us/library/ms790939.aspx


b) COM port and serial number

In this topic, I posted a short snippet that lists up COM port and serial number for CP210x. Actually, this snippet is applied to CDC virtual COM port, too, just by changing the VID/PID.

"CP2102 & Vista registry"
http://www.cygnal.org/ubb/Forum9/HTML/001659.html

For your composite device,

CString deviceID( _T("USB\\VID_10C4&PID_EA60\\") ); // device ID of CP210x VCP

Modify above line like,

CString deviceID( _T("USB\\VID_vvvv&PID_pppp&MI_mm\\") );

where,
vvvv, pppp: 4 digit hex number of the VID/PID of your device
mm: 2 digit hex number for CDC communication interface

Then, you can retrieve COM port and serial number in a pair.
Using this COM port number, you'll get the device handle for the COM port.


Combine a) and b).
For example,
- Search a HID device, open it and get the serial number, first
- Then, search a COM port of this serial number, using b)
- Repeat for all HID device

Tsuneo

[This message has been edited by Tsuneo (edited November 11, 2008).]

IP: Logged

Myst1uk
New Member

posted November 12, 2008 05:52 AM         

I have a simple question.. is it possible to modify one of the silicon labs HID examples to use an isochronous endpoint?

IP: Logged

Tsuneo
Member

posted November 13, 2008 04:39 AM            

"is it possible to modify one of the silicon labs HID examples to use an isochronous endpoint?"

It's possible, but USB_Interrupt example is better.
HID examples has HID specific request handlers.

Tsuneo

IP: Logged

egawtry
Member

posted November 17, 2008 09:15 AM            

Tsuneo,

I have already tried all you have suggested except for the serial number idea. I will try that. If I get it to work I will post it.

One note, the MI_mm does NOT match between HID and CDC devices, in fact, the CDC device string does not include the MI_mm string. Also the MI_mm for the HID gets changed from the string in the INF to a random number.

-Erik

P.S. I tried your CDC serial number routine. It doesn't work. The DeviceID stuff on the right is junk.

[This message has been edited by egawtry (edited November 17, 2008).]

IP: Logged

egawtry
Member

posted November 17, 2008 01:39 PM            

Figured it out:

// Get the address of the selected deviceBOOL GetSerialNumberForCDC(LPCWSTR lpDevPath, LPWSTR lpAddress, UINT cbAddress){ // Check the VID PID WCHAR *ptrVID, *ptrPID, *ptrMI, *ptrCode;WORD wVID, wPID, wMI;

if( cbAddress == 0 ) return FALSE;

// Initialize *lpAddress = NULL;wVID = wPID = wMI = 0;

// Get the VID and PID for the enum searchptrVID = wcsstr(lpDevPath, L"vid_"); ptrPID = wcsstr(lpDevPath, L"pid_");ptrMI = wcsstr(lpDevPath, L"mi_"); if( ptrVID ) wVID = (WORD)_xtoi(ptrVID+4);if( ptrPID ) wPID = (WORD)_xtoi(ptrPID+4); // Get the MI and the CODE pointerif( ptrMI ) { wMI = (WORD)_xtoi(ptrMI+3); ptrMI += 3;while( *ptrMI && (*ptrMI != '#') ) ++ptrMI; if( *ptrMI == '#' ) ptrCode = ++ptrMI; else ptrCode = NULL; } elsereturn FALSE;

// found the code? if( ptrCode ) { // Find the USB enumed entry WCHAR wszKey[256];swprintf_s(wszKey, _countof(wszKey), L"SYSTEM\\ControlSet001\\Enum\\USB\\VID_%04X&PID_%04X", wVID, wPID);HKEY hKeyEnum, hKeyItem;if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, wszKey, 0, KEY_READ, &hKeyEnum) == ERROR_SUCCESS ){ // Search the sub-keys WCHAR wszName[256]; UINT iIndex = 0;while( RegEnumKey(hKeyEnum, iIndex++, wszName, _countof(wszName)) == ERROR_SUCCESS ){ // Open the sub-keyif( RegOpenKeyEx(hKeyEnum, wszName, 0, KEY_READ, &hKeyItem) == ERROR_SUCCESS ){ WCHAR wszData[256]; DWORD lData = _countof(wszData)*sizeof(WCHAR);DWORD dwType = REG_SZ;

// Check the ParentIdPrefix for a matchif( RegQueryValueEx(hKeyItem, L"ParentIdPrefix", NULL, &dwType, (LPBYTE)wszData, &lData) == ERROR_SUCCESS ){ if( !wcsncmp(wszData, ptrCode, 10) ) { // Found the address! wcscpy_s(lpAddress, cbAddress, wszName);RegCloseKey(hKeyItem); break; } }RegCloseKey(hKeyItem); } } RegCloseKey(hKeyEnum); } }if( *lpAddress ) return TRUE;

return FALSE;}

Note: _xtoi() just converts a Hex string

Note2: Fixed 11/19/2008: Change compare to only 10 chars to make it XP compatible.


[This message has been edited by egawtry (edited November 19, 2008).]

[This message has been edited by egawtry (edited December 07, 2008).]

IP: Logged

Tsuneo
Member

posted November 17, 2008 04:37 PM            

"I tried your CDC serial number routine. It doesn't work. The DeviceID stuff on the right is junk."

I see.
It works when the device is not a composite device.
Usually, InstaceID derives from serial number. However, the InstaceID of each interface of composite device isn't serial number, but a location ID. Just the composite parent has the serial number.


I found a good answer on this issue,


"Re: SetupDiGetDeviceRegistryProperty - Usb - Address - Busnumber"

"Bernhard"
To find the hid device I used the HID Guid, but I want also to find the CDC
device on the same composite device. Is it possible to readout the parent-id
of both devices?

From: "Doron Holan [MSFT]"
you can use the CM APIs to find the parent DEVINST of both the HID and the CDC device and see if it returns the same DEVINST

To get the parent DevInst,

For HID,
In the course of the count up of the HID device using SetupDi-APIs,
- get SP _DEVINFO_DATA DeviceInfoData by SetupDiGetDeviceInterfaceDetail
- Feed DeviceInfoData.DevInst to CM_Get_Parent, and get the parent's DevInst

For CDC,
In the course of the snippet on
"CP2102 & Vista registry"
- SP _DEVINFO_DATA devInfo is returned by SetupDiEnumDeviceInfo
- Feed devInfo.DevInst to CM_Get_Parent, and get the parent's DevInst


CM_Get_Parent
http://msdn.microsoft.com/en-us/library/ms791198.aspx

Tsuneo

IP: Logged

egawtry
Member

posted November 18, 2008 07:52 PM            

"I found a good answer on this issue"


I get wildly different numbers from CM_Get_Parent(). I have tried going up the tree with no success.

I am also getting "OK" as my serial number from HidD_GetSerialNumberString() - looks like a parsing error. Of course, this messes up my matching by Serial Number. Now I have the CDC serial number, but not the HID!

-Erik

P.S. Figured out the "OK". Mia culpa. The Serial Number method works again.

[This message has been edited by egawtry (edited November 19, 2008).]

IP: Logged

egawtry
Member

posted December 10, 2008 08:00 PM            

Tsuneo,

I have an implementation of the HID/CDC going. The problem is that if I send CDC serial data from the PC to the 340 in a steady stream, it stops receiving after 384 characters (my buffer is 240 chars). The funny thing is that it will still transmit to the PC unerringly.

Any ideas? Should I post a zip of my code?

Thanks,
-Erik

P.S. More details - if I send chumks of less than 384 chars it will send forever, but the second I use a 384 char chunk it dies.

[This message has been edited by egawtry (edited December 12, 2008).]

IP: Logged

egawtry
Member

posted December 12, 2008 04:22 PM            

Found it! It was a bug in the Handle_Out3.

There needs to be two changes:
1. The Ep_StatusOUT2 can be EP_HALT or EP_STALL, so check for not EP_IDLE:

if ( Ep_StatusOUT2 != EP_IDLE ) return; // If endpoint is ready

2. The fifo will fill, and then jam unless there is a check for size:

if ( OUT2_FIFO_loaded && (TXcount < (TXBUFSIZE-EP2_OUT_PACKET_SIZE)) ) // FIFO has data?{ OUT2_FIFO_loaded = FALSE;

#2 also is a bug in the standard CDC implementation.

-Erik

IP: Logged

egawtry
Member

posted December 30, 2008 09:22 AM            

Question:

How is stall handled? The reason I ask is I am having serious FIFO overruns on the USB. If the packet is not retrieved from the 34x's FIFO in time, it seems like another is stuffed by the host into the FIFO and lost. If I enable RTS/CTS on the host end, then it doesn't lose anything, but it also destablizes the host serial port within a few hundred bytes and starts randomly jumping around in the FIFO.

HID works great.

Thanks,
-Erik

IP: Logged

egawtry
Member

posted January 03, 2009 11:45 AM            

Well, got it fixed.

I moved the loaded flag to inside the size check so that the routine will call again if the size is too small, and I also added an else to send a stall.

void CDC_Handle_Bulk_HostOUT( void ){static BYTE FIFO_Cnt, first_cnt, second_cnt; static Ttxcnt pos; bit turnover;static BYTE ControlReg; // Temporary storage for EP control register

if ( (Ep_StatusOUT2 == EP_IDLE) ) // If endpoint is ready{ if ( OUT2_FIFO_loaded ) // FIFO has packet? {EIE1 &= ~0x02; // disable USB interruptPOLL_WRITE_BYTE(INDEX, 2); // Set index to endpoint 2 registersPOLL_READ_BYTE(EOUTCNTL, FIFO_Cnt); // read out number of bytes on the FIFOpos = (TXBUFSIZE - TXcount); if( pos > 8 ) pos -= 8;if( pos >= FIFO_Cnt ) // if any room on the buffer to read out the FIFO{ OUT2_FIFO_loaded = FALSE; // total - offsetpos = TXBUFSIZE - TXWTIdx; // consider on wrap around of ring bufferif ( FIFO_Cnt < pos ) { first_cnt = FIFO_Cnt; second_cnt = 0;turnover = FALSE; } else { first_cnt = (BYTE)pos;second_cnt = FIFO_Cnt - first_cnt; turnover = TRUE; }FIFO_READ_FUNC( FIFO_EP2, first_cnt, &TXBuffer[ TXWTIdx ] ); // read bytes from FIFOif ( second_cnt != 0 ) FIFO_READ_FUNC( FIFO_EP2, second_cnt, TXBuffer );POLL_WRITE_BYTE(EOUTCSRL, 0); // Clear Out Packet ready and stalled bitsif ( turnover ) // maintainance of buffer parametersTXWTIdx = second_cnt; else TXWTIdx += FIFO_Cnt;TXcount += FIFO_Cnt; TXReady = (TXcount > 0); } // Not enough space to remove packet from hardware FIFO else {POLL_READ_BYTE(EOUTCSRL, ControlReg); // Read control register // stalled? if( !(ControlReg&rbOutSDSTL) ) { // Set the stall to prevent extra packets ControlReg |= rbOutSDSTL;} // Clear the Stall int flag ControlReg &= ~rbOutSTSTL;POLL_WRITE_BYTE(EOUTCSRL, ControlReg); }TXFull = (TXcount >= TXBUFSIZE-1);EIE1 |= 0x02; // enable USB interrupt } }}

-Erik

[This message has been edited by egawtry (edited January 05, 2009).]

IP: Logged

egawtry
Member

posted January 26, 2009 09:52 AM            

Does anyone have INF files for Vista 64? The Vista 32 ones don't work. Since the CDC/HID uses built in drivers, there shouldn't be a driver certification problem...

-Erik

IP: Logged

Patryk
Member

posted January 26, 2009 02:42 PM         

There was some post recently (about VCP driver I think). Vista 64 allows only signed drivers. Need to disable "driver security" (if I remember correctly) to overcome this.

IP: Logged

charlie8
New Member

posted January 26, 2009 11:46 PM            

Hi Tsuneo and all,

I have implemented two single interface HID devices(one Mouse and one Keyboard)and tested it with XP-SP3. Individually they work fine.

When I combine them as a composite device, only the first interface works. Windows recognizes it as composite device with two HID interfaces but indicates the second HID running into error while binding. If the first one is Mouse, then Keyboard fails; if the first one is Keyboard, then Mouse fails.

USB bus analyzer shows that Get Descriptor for HID class request fails for the second interface - Windows sends out a SETUP token but no IN token to follow; after three times, it stops.

Any help or ideas are highly appreciated.

Thanks
Charlie

IP: Logged

egawtry
Member

posted January 28, 2009 11:05 AM            

Charlie,

Sounds familiar. Do you have the MI part of the PID/VID in place?

If not, add "&MI_00" to the end of the MYDEV000 string.

===========================

Patryk,

Since we are using the built-in Vista drivers, signing shouldn't be a problem.

===========================

-Erik

[This message has been edited by egawtry (edited January 28, 2009).]

IP: Logged

Patryk
Member

posted January 29, 2009 07:02 AM         

Erik - remember that driver and it's INF file are integral parts of driver package that is being signed. Since there is no default INF file for CDC driver (signed together), you must provide one, and I'm sure it's not signed yet :-)

IP: Logged

egawtry
Member

posted January 29, 2009 10:30 AM            

So you are saying that we need to pay MS to certify their own drivers? Man, what a racket.

-Erik

IP: Logged

WITTROCK
Member

posted January 29, 2009 11:26 AM            

So you are saying that we need to pay MS to certify their own drivers? Man, what a racket.

Hey, I thought all this was going to change once Grand Pupa Bill Gates left! I guess not.

-WITTROCK

IP: Logged

Patryk
Member

posted January 30, 2009 01:58 AM         

Erik - partially true: MS driver (binary) plus your's INF file.

IP: Logged

egawtry
Member

posted February 06, 2009 07:03 PM            

Workaround:

1. Boot Vista64 with driver signing disabled.
2. Install the driver. (must be a signed SYS driver, INF doesn't matter). Like usual, say YES to the Are you sure question.
3. Use immediately or Reboot.
4. Drivers are working.

======================================
Fixed Vista INF file for x86/x64:
======================================
; CDC_ACM.vista.inf
;
; INF file for CDC/HID
;

[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4d36e978-e325-11ce-bfc1-08002be10318}
Provider=%MYCORP%
LayoutFile=mdmcpq.inf
DriverVer=02/06/2009,6.0.0.1

[Manufacturer]
%MYCORP%=MYCORP,NTamd64

[MYCORP]
%DEV000%= DEV000,NT,USB\VID_10C4&PID_8888&MI_00

[MYCORP.NTamd64]
%DEV000%= DEV000,NTamd64,USB\VID_10C4&PID_8888&MI_00

[DestinationDirs]
FakeModemCopyFileSection=12
DefaultDestDir = 12

[DEV000.NT]
include=mdmcpq.inf
CopyFiles=FakeModemCopyFileSection
AddReg=DEV000.NT.AddReg

[DEV000.NTamd64]
include=mdmcpq.inf
CopyFiles=FakeModemCopyFileSection
AddReg=DEV000.NTamd64.AddReg

[DEV000.NT.HW]
AddReg=DEV000.NT.HW.AddReg

[DEV000.NTamd64.HW]
AddReg=DEV000.NTamd64.HW.AddReg

[DEV000.NT.AddReg]
HKR,,NTMPDriver,,*ntkern
HKR,,NTMPDriver,,usbser.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
HKR,,PortSubClass,1,01

[DEV000.NTamd64.AddReg]
HKR,,NTMPDriver,,*ntkern
HKR,,NTMPDriver,,usbser.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
HKR,,PortSubClass,1,01

[DEV000.NT.HW.AddReg]
HKR,,"UpperFilters",0x00010000,"serenum"

[DEV000.NTamd64.HW.AddReg]
HKR,,"UpperFilters",0x00010000,"serenum"

;-------------- Service installation
; Port Driver (function driver for this device)
[DEV000.NT.Services]
AddService = usbser, 0x00000002, Service_Inst
AddService = Serenum,,Serenum_Service_Inst

[DEV000.NTamd64.Services]
AddService = usbser, 0x00000002, Service_Inst
AddService = Serenum,,Serenum_Service_Inst

; -------------- Serial Port Driver install sections
[Service_Inst]
DisplayName = %Serial.SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\usbser.sys
LoadOrderGroup = Base

; -------------- Serenum Driver install section
[Serenum_Service_Inst]
DisplayName = %Serenum.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\serenum.sys
LoadOrderGroup = PNP Filter

[Strings]
MYCORP = "My Company" ; Your company name
DEV000 = "My Device" ; Device description
Serial.SvcDesc = "CDC ACM Driver" ; Device driver description

Serenum.SVCDESC = "Serenum Filter Driver"
===================================

-Erik

[This message has been edited by egawtry (edited February 06, 2009).]

IP: Logged

egawtry
Member

posted April 16, 2009 10:02 AM            

I am getting a strange problem on a customer's machine (Windows XP SP2). Everything installs great, they see the COM port, but nothing goes in or out of the PC. The HID section works just fine. The hardware works on several other computers.

I have removed, manually deleted the OEMXX.INF in the Windows/INF folder and reinstalled, still no dice.

Anyone with any ideas?

Thanks,
-Erik

IP: Logged

ferika
Member

posted July 21, 2011 05:50 AM            

BOARD: C8051F320DK
-------------------

If i had error in USB_Type.h file:

//#include
#include //have 320 !!!

then the communication working ok! But with the right setting:

#include
//#include

had no communication to the virtual COM. Any idea?

IP: Logged

egawtry
Member

posted July 21, 2011 11:25 AM            

Please repost with fixed <>.

IP: Logged

arunj123
New Member

posted November 25, 2011 10:56 PM            

COM port number for usb serial can be found by using wmi services. Here is an example.
http://collectns.blogspot.com/2011/11/vbscript-for-detecting-usb-serial-com.html

------------------
Frmkla
http://collectns.blogspot.com

IP: Logged

Tsuneo
Member

posted November 25, 2011 11:49 PM            

For COM port number scan using WMI, this one is simpler.

http://www.microchip.com/forums/fb.ashx?m=560699

Tsuneo

 

egawtry
Member
posted April 27, 2009 07:55 PM             This is because the USB Composite Device thread is getting too long.

IP: Logged

egawtry
Member
posted April 27, 2009 08:01 PM             I am having issues with XPSP2 and CDC ports. The HID works great, but the CDC only sends the class messages, it will not send any data. Updating to XPSP3 fixes the issue, but requiring customers to do that is not an option.

Anyone know what the problem is?

Thanks,
-Erik

IP: Logged

ReneK
Member
posted April 28, 2009 02:52 AM             This is a bug that got fixed with SP3. If SP3 is not an option, you need to drop usbser.sys and make your own driver. See:

The Usbser.sys driver may not load when a USB device uses an IAD to define a function that has multiple interfaces, and this function uses the Usbser.sys driver file in Windows XP

IP: Logged

xiaofan
Member
posted April 28, 2009 04:14 AM          The hot fixes from Microsoft are necessary if you run XP SP2. They are not necessary if you run Vista or XP SP3.
http://support.microsoft.com/kb/918365/en-us
http://support.microsoft.com/kb/935892/en-us

IP: Logged

egawtry
Member
posted April 28, 2009 09:24 AM             Wow! Thanks Rene and Xaiofan! I'll try 'em out.

-Erik

[This message has been edited by egawtry (edited April 28, 2009).]

IP: Logged

egawtry
Member
posted April 29, 2009 10:03 AM             The bug mentioned in the knowledge base was exactly the issue I see, but the hotfix didn't fix it.

Any other ideas?

Thanks,
-Erik

IP: Logged

xiaofan
Member
posted May 02, 2009 09:38 AM          I believe you need two hot fixes for XP SP2. Last time I tried it and it worked for me.

IP: Logged

xiaofan
Member
posted May 02, 2009 09:39 AM          I mean you need both hot fixes in the two links I posted.

IP: Logged

egawtry
Member
posted May 02, 2009 02:23 PM             The second hotfix you posted has to do with hibernation on a Tablet PC. Are you sure about the number?

Thanks,
-Erik

IP: Logged

xiaofan
Member
posted May 02, 2009 11:43 PM          Yes. This is according to the past posts in usb.org.

IP: Logged

xiaofan
Member
posted May 02, 2009 11:46 PM          Usbccgp.sys is very important file for USB Composite device.

IP: Logged

xiaofan
Member
posted May 03, 2009 08:00 AM          Faq from lvr.com
http://www.lvr.com/serport.htm

IP: Logged

egawtry
Member
posted May 04, 2009 12:08 PM             Wow, with that second hotfix, it worked!

Thanks to all.

-Erik

[This message has been edited by egawtry (edited May 04, 2009).]

 

http://www.cygnal.org/ubb/Forum9/HTML/001050.html

http://www.cygnal.org/ubb/Forum9/HTML/001816.html

 

你可能感兴趣的:(USB Composite Device)