cancel
Showing results for 
Search instead for 
Did you mean: 

USB multi interface.

sangjin97
Associate II
Posted on June 09, 2010 at 06:41

hi~ all

I have developed USB firmware.

It send audio stream from imbedded board to PC.

But I need PC to send some short packet to imbedded board.

I want USB device operate as HID and audio(isochronous IN) at the same time.

And, I can not develop Windows device driver.

So, I need to use some profile supported by windows default driver.

Can I get some usefull USB prifile??

Thanks~!
4 REPLIES 4
tsuneo
Senior
Posted on June 11, 2010 at 17:36

Make an audio + HID composite device.

This combination is popular - HID interface passes volume/mute setting from device to PC.

Also, supported on in-box drivers on major OSes (Windows, MacOSX and Linux) without any INF file.

You can have an optional interrupt OUT endpoint on the HID interface, to pass the data from PC to the device.

OR

Set_Report (HidD_SetOutputReport() for WinXP and later) is available, too.

When the transfer occurs frequently, the interrupt OUT endpoint is better.

Before attaching the HID interface to the audio one, I recommend you to examine HID alone on a separate firmware.

For this firmware, ''Custom_HID'' example on the ST USB stack is a good starting point.

Modify this example,

- Move the endpoint address, so that they don't overlap with audio ones.

- Simplify the report descriptor, so that it fits to your requirement

When you satisfy on the modification, combine HID code into audio.

On the configuration descriptor set,

- Append HID interface / HID class / endpoint descriptors after the audio interface.

- Increase wTotalLength field on the config descriptor by above HID descriptors

- Increase bNumInterfaces field of the config descriptor by one

- Change bInterfaceNumber field of the HID interface to 2

- Drag in HID report descriptor.

For other source files, compare two projects (audio and HID) using a ''diff'' utility like WinMerge.

And them combine them.

As the interface number of HID interface moves from 0 to 2, you have to touch to the source code in which pInformation->USBwIndex0 is reffered on the HID source.

For example,

<pre>

usb_prop.c for HID

enum {

   INTERFACE_NUMBER_AUDIO_CTRL,

   INTERFACE_NUMBER_AUDIO_STREAM,

   INTERFACE_NUMBER_HID,

   NUM_OF_INTERFACES

};

RESULT CustomHID_Data_Setup(uint8_t RequestNo)

{

  uint8_t *(*CopyRoutine)(uint16_t);

  CopyRoutine = NULL;

  if ((RequestNo == GET_DESCRIPTOR)

      && (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))

  //  && (pInformation->USBwIndex0 == 0))                      // <------------ modified

      && (pInformation->USBwIndex0 == INTERFACE_NUMBER_HID ))  // <------------ to new interface number

</pre>

WinMerge

http://winmerge.org/

Tsuneo

sangjin97
Associate II
Posted on June 14, 2010 at 08:45

I really appreciate your reply.

It was helpfull to me.

But, I can not understand your example code.

I only changed the USB descript file. And I did not change any source code.

Now, PC detects my device as a audio device and HID device.

But several seconds later, windows returns error about HID.

Wondows' message is that ''This device cannot start. (Code 10)''.

For debug, I printed usb endpoint data on the screen using Hyper terminal(UART).

Bla bla bla.........             

Rx[0]-                            <- PC send NULL packet

Rx[0]- 80 06 20 03 09 04 FF 00

Tx[0]- 2A 03 50 00 56 00 20 00

Tx[0]- 20 00 20 00 4D 00 69 00

Tx[0]- 63 00 72 00 6F 00 70 00

Tx[0]- 68 00 6F 00 6E 00 65 00

Tx[0]- 20 00 20 00 20 00 20 00

Tx[0]- 20 00

Tx[0]-                            <- I send NULL packet

Rx[0]-

Rx[0]- 01 0B 00 00 01 00 00 00

Tx[0]-

Rx[0]- 21 01 00 01 00 02 01 00

Tx[0]- 00

Rx[0]- A1 82 00 02 00 02 02 00    <-PC request minimum volume value

Tx[0]- 00 00                      <- I send my minimum volume value

Tx[0]-

Rx[0]-

Rx[0]- A1 83 00 02 00 02 02 00    <- PC request Max volume

Tx[0]- 00 01                      <- I send my max volume

Tx[0]-

Rx[0]-

Rx[0]- A1 84 00 02 00 02 02 00    <- PC request Vol Resoution

Tx[0]- 04 00                      <- I send

Tx[0]-

Rx[0]-

Rx[0]- A1 81 00 02 00 02 02 00    <- PC request Current volume

Tx[0]- 00 01                      <- I send

Tx[0]-

Rx[0]-

Rx[0]- 21 01 00 02 00 02 02 00    <-- PC set my volume

Rx[0]- 80 00 <- volume value

Tx[0]-

Rx[0]- 21 0A 00 00 02 00 00 00    <-- What is that?? I did not send any response.

My code is based on KEIL example code.

Could you explain your example code in detail more?

Best regards :D

tsuneo
Senior
Posted on June 14, 2010 at 15:52

> Rx[0]- 21 0A 00 00 02 00 00 00    <-- What is that?? I did not send any response.

It's Set_Idle() request for HID interface.

 

When you get a SETUP stage of control transfer,

1) check bmRequestType field (the first byte) of the SETUP packet, first.

[D6:D5] bits on bmRequestType shows standard 00, class 01, Vendor 10 requests.

2) for standard request, move to the standard request handler

2') for class request,

the low-byte of wIndex field (the fifth byte) of the SETUP packet shows target interface number.

 

You've set the interface number of the HID interface to 2 on the config descriptor set.

 

> My code is based on KEIL example code.

 

Ah, then, just enabling USB_HID and tune 

USB_HID_IF_NUM value

 on usbcfg.h, 

 

usbcfg.h

#define USB_HID             1

 

#define USB_HID_IF_NUM      2

 

The request handler of KEIL example has already implemented above logic, as follows.

 

usbcore.c

void USB_EndPoint0 (U32 event) {

 

 

  switch (event) {

    case USB_EVT_SETUP:

      ...

      switch (SetupPacket.bmRequestType.BM.Type) {

 

        case REQUEST_STANDARD:

           ...

           ...

           ...

#if USB_CLASS

        case REQUEST_CLASS:

          switch (SetupPacket.bmRequestType.BM.Recipient) {

 

            case REQUEST_TO_DEVICE:

              goto stall_i;                                              /* not supported */

 

            case REQUEST_TO_INTERFACE:

#if USB_HID

              if (SetupPacket.wIndex.WB.L == USB_HID_IF_NUM) {   // <---- request to HID interface

                  ...

                  ...

              }

#endif  /* USB_HID */

#if USB_AUDIO

              if ((SetupPacket.wIndex.WB.L == USB_ADC_CIF_NUM)  ||

   // <---- request to Audio interface

  

                  (SetupPacket.wIndex.WB.L == USB_ADC_SIF1_NUM) ||

                  (SetupPacket.wIndex.WB.L == USB_ADC_SIF2_NUM)) {

                  ...

                  ...

              }

#endif  /* USB_AUDIO */

 

Tsuneo

sangjin97
Associate II
Posted on June 15, 2010 at 13:29

Thank you for your help.

It is really helpfull to me!!!

How can I ever repay you?

Thank you very much Mr,Tsuneo.

I really appreciate your help. 🙂

Best regards : )