1
votes

I'm trying to prototype some code on Arduino which simulates USB composite device - which consist of audio and HID functionality. What I'd like to achieve is to have ability to control volume by pressing physical button on Arduino - which will generate HID volume up/down event to host. I'd expect that changing volume will set audio even if Arduino is not selected as default device.

On the Windows I can control volume even if Arduino is not default audio device - which means I can connect two or more of Arduino devices and set valid volume independently. On the Linux (with ALSA/PulseAudio) it seems that HID Volume Up/Down works ONLY for default device - which means I cannot use two Arduino devices and control their volume independently.

I can also observe that if default audio device is different then Arduino there is no USB message with SET_CUR from the host.

Is there anything that I could configure in the ALSA/PulseAudio to achieve desired result? Or maybe HID approach should be reworked?

Below is definition of HID message I am using:

static const uint8_t JoystickHIDDescriptor[] = 
{
    0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xa1, 0x01,                    // COLLECTION (Application)
        0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
        0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
        0x09, 0xe9,                    //   USAGE (Volume Up)
        0x09, 0xea,                    //   USAGE (Volume Down)
        0x75, 0x01,                    //   REPORT_SIZE (1)
        0x95, 0x02,                    //   REPORT_COUNT (2)
        0x81, 0x06,                    //   INPUT (Data,Var,Rel)
        0x09, 0xe2,                    //   USAGE (Mute)
        0x95, 0x01,                    //   REPORT_COUNT (1)
        0x81, 0x06,                    //   INPUT (Data,Var,Rel)
        0x95, 0x05,                    //   REPORT_COUNT (5)
        0x81, 0x07,                    //   INPUT (Data,Var,Rel)
    0xc0                           // END_COLLECTION
};

1

1 Answers

1
votes

If you use HID then you may check this one

https://github.com/pzprovi/hid

Take a look here entire project. There is two keyboard void functions. you may test keyboard2() example is just for you.

https://github.com/pzprovi/hid/blob/master/MultiKey/MultiKey.c

Just replace it and try to case all your array elements from JoystickHIDDescriptor like this one example at the bottom

    void Keyboard2(void)
{

  if(!HIDTxHandleBusy(lastINTransmission))
    {
        switch(getInput())
        {
            case INPUT_NONE:
                // if we don't send this, the vol +/- will continue to roll on and on...
                hid_report_in[0] = 0x00;
                hid_report_in[1] = 0x00;
                hid_report_in[2] = 0x00;
                lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x03);
                break;
            case INPUT_VOLUME_UP:
                hid_report_in[0] = 0x01;
                hid_report_in[1] = 0xE9;
                hid_report_in[2] = 0x00;
                lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x03);
                break;
            case INPUT_VOLUME_DOWN:
                hid_report_in[0] = 0x01;
                hid_report_in[1] = 0xEA;
                hid_report_in[2] = 0x00;
                lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x03);
                break;
            case INPUT_VOLUME_MUTE:
                hid_report_in[0] = 0x01;
                hid_report_in[1] = 0xE2;
                hid_report_in[2] = 0x00;
                lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x03);
                break;
            default:
                // no need to send anything.
                break;
        }
    }

}

0x09, 0xe9, // USAGE (Volume Up) 0x09, 0xea,
// USAGE (Volume Down)

Put break point and check all your hardware buttons on your device. Then add for vol up this code:

  hid_report_in[0] = 0x01;
                hid_report_in[1] = 0xE9;
                hid_report_in[2] = 0x00;
                lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x03);

and vol down this one:

hid_report_in[0] = 0x01;
                hid_report_in[1] = 0xEA;
                hid_report_in[2] = 0x00;
                lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x03);