USB Control Transfer使用libusb获取AudioStreaming描述符

时间:2017-11-10 18:31:51

标签: android c android-ndk usb libusb

我目前正在使用libusb(1.0.9)为我的Android应用程序支持USB麦克风(Samson Q1U)。我从设备获得数据流没有问题,但我想读取有关数据格式(位深度,采样率,通道)的信息。到目前为止,USB一直很混乱,所以请原谅我在下面使用它的尝试。问题是控制转移,我不相信它设置正确。我尝试了许多不同的传输参数组合,但都有返回错误代码-1,-7和& -9。任何帮助都会很棒。

基本上,我想得到这个描述符:

AudioStreaming Interface Descriptor:
    bLength                23
    bDescriptorType        36
    bDescriptorSubtype      2 (FORMAT_TYPE)
    bFormatType             1 (FORMAT_TYPE_I)
    bNrChannels             1
    bSubframeSize           2
    bBitResolution         16
    bSamFreqType            5 Discrete
    tSamFreq[ 0]         8000
    tSamFreq[ 1]        11025
    tSamFreq[ 2]        22050
    tSamFreq[ 3]        44100
    tSamFreq[ 4]        48000

这是我的控制转移代码:

extern "C" void Java_com_example_test_LibUsb_nativeGetAudioInfo(JNIEnv *env, jobject obj){

libusb_init(NULL);
devh = libusb_open_device_with_vid_pid(NULL,VID,PID);
libusb_kernel_driver_active(devh, 0);
libusb_detach_kernel_driver(devh, 0);
libusb_claim_interface(devh, 0);
libusb_set_interface_alt_setting(devh,0,0);

uint8_t requestType = 0b1 | 0b01 | 0b00001;
uint8_t bRequest = 0x06;
uint16_t wValue = 0x24;
uint16_t wIndex = 0;
unsigned char data[23];
unsigned int timeout = 1000;

int rc = libusb_control_transfer(devh, requestType, bRequest, wValue, wIndex, data, sizeof(data), timeout);
LOGD("%d",rc);

int cnt = 0;
if(rc > 0){

    char bLength = data[cnt++];
    char bDescriptorType = data[cnt++];
    char bDescriptorSubtype = data[cnt++];
    char bFormatType = data[cnt++];
    char bNrChannels = data[cnt++];
    char bSubframeSize = data[cnt++];
    char bBitResolution = data[cnt++];
    char bSamFreqType = data[cnt++];

    int rates[bSamFreqType];

    LOGD("%d",bNrChannels);
    LOGD("%d",bBitResolution);

    for(int i = 0;i < bSamFreqType;i++){
        char byte1 = data[cnt++];
        char byte2 = data[cnt++];
        char byte3 = data[cnt++];

        rates[i] = ((byte1 & 0xFF) << 8 | (byte2 & 0xFF) << 16 | (byte3 & 0xFF) << 24);
        LOGD("%d",rates[i]);
    }

}

libusb_exit(NULL);

}

以下是完整的设备描述符:

Device Descriptor:
bLength                18
bDescriptorType         1
bcdUSB               1.10
bDeviceClass            0 (Defined at Interface level)
bDeviceSubClass         0 
bDeviceProtocol         0 
bMaxPacketSize0         8
idVendor           0x17a0 Samson Technologies Corp.
idProduct          0x0002 Q1U dynamic microphone
bcdDevice            0.01
iManufacturer           1 
iProduct                2 
iSerial                 0 
bNumConfigurations      1
  Configuration Descriptor:
  bLength                 9
  bDescriptorType         2
  wTotalLength          177
  bNumInterfaces          2
  bConfigurationValue     1
  iConfiguration          0 
  bmAttributes         0x80
    (Bus Powered)
  MaxPower               90mA
  Interface Descriptor:
    bLength                 9
    bDescriptorType         4
    bInterfaceNumber        0
    bAlternateSetting       0
    bNumEndpoints           0
    bInterfaceClass         1 Audio
    bInterfaceSubClass      1 Control Device
    bInterfaceProtocol      0 
    iInterface              0 
    AudioControl Interface Descriptor:
      bLength                 9
      bDescriptorType        36
      bDescriptorSubtype      1 (HEADER)
      bcdADC               1.00
      wTotalLength           40
      bInCollection           1
      baInterfaceNr( 0)       1
    AudioControl Interface Descriptor:
      bLength                12
      bDescriptorType        36
      bDescriptorSubtype      2 (INPUT_TERMINAL)
      bTerminalID             1
      wTerminalType      0x0201 Microphone
      bAssocTerminal          2
      bNrChannels             2
      wChannelConfig     0x0003
        Left Front (L)
        Right Front (R)
      iChannelNames           0 
      iTerminal               0 
    AudioControl Interface Descriptor:
      bLength                 9
      bDescriptorType        36
      bDescriptorSubtype      3 (OUTPUT_TERMINAL)
      bTerminalID             2
      wTerminalType      0x0101 USB Streaming
      bAssocTerminal          1
      bSourceID               3
      iTerminal               0 
    AudioControl Interface Descriptor:
      bLength                10
      bDescriptorType        36
      bDescriptorSubtype      6 (FEATURE_UNIT)
      bUnitID                 3
      bSourceID               1
      bControlSize            1
      bmaControls( 0)      0x01
        Mute Control
      bmaControls( 1)      0x02
        Volume Control
      bmaControls( 2)      0x02
        Volume Control
      iFeature                0 
  Interface Descriptor:
    bLength                 9
    bDescriptorType         4
    bInterfaceNumber        1
    bAlternateSetting       0
    bNumEndpoints           0
    bInterfaceClass         1 Audio
    bInterfaceSubClass      2 Streaming
    bInterfaceProtocol      0 
    iInterface              0 
  Interface Descriptor:
    bLength                 9
    bDescriptorType         4
    bInterfaceNumber        1
    bAlternateSetting       1
    bNumEndpoints           1
    bInterfaceClass         1 Audio
    bInterfaceSubClass      2 Streaming
    bInterfaceProtocol      0 
    iInterface              0 
    AudioStreaming Interface Descriptor:
      bLength                 7
      bDescriptorType        36
      bDescriptorSubtype      1 (AS_GENERAL)
      bTerminalLink           2
      bDelay                  1 frames
      wFormatTag              1 PCM
    AudioStreaming Interface Descriptor:
      bLength                23
      bDescriptorType        36
      bDescriptorSubtype      2 (FORMAT_TYPE)
      bFormatType             1 (FORMAT_TYPE_I)
      bNrChannels             1
      bSubframeSize           2
      bBitResolution         16
      bSamFreqType            5 Discrete
      tSamFreq[ 0]         8000
      tSamFreq[ 1]        11025
      tSamFreq[ 2]        22050
      tSamFreq[ 3]        44100
      tSamFreq[ 4]        48000
    Endpoint Descriptor:
      bLength                 9
      bDescriptorType         5
      bEndpointAddress     0x81  EP 1 IN
      bmAttributes            5
        Transfer Type            Isochronous
        Synch Type               Asynchronous
        Usage Type               Data
      wMaxPacketSize     0x0064  1x 100 bytes
      bInterval               1
      bRefresh                0
      bSynchAddress           0
      AudioControl Endpoint Descriptor:
        bLength                 7
        bDescriptorType        37
        bDescriptorSubtype      1 (EP_GENERAL)
        bmAttributes         0x01
        Sampling Frequency
        bLockDelayUnits         0 Undefined
        wLockDelay              0 Undefined
  Interface Descriptor:
    bLength                 9
    bDescriptorType         4
    bInterfaceNumber        1
    bAlternateSetting       2
    bNumEndpoints           1
    bInterfaceClass         1 Audio
    bInterfaceSubClass      2 Streaming
    bInterfaceProtocol      0 
    iInterface              0 
    AudioStreaming Interface Descriptor:
      bLength                 7
      bDescriptorType        36
      bDescriptorSubtype      1 (AS_GENERAL)
      bTerminalLink           2
      bDelay                  1 frames
      wFormatTag              1 PCM
    AudioStreaming Interface Descriptor:
      bLength                23
      bDescriptorType        36
      bDescriptorSubtype      2 (FORMAT_TYPE)
      bFormatType             1 (FORMAT_TYPE_I)
      bNrChannels             2
      bSubframeSize           2
      bBitResolution         16
      bSamFreqType            5 Discrete
      tSamFreq[ 0]         8000
      tSamFreq[ 1]        11025
      tSamFreq[ 2]        22050
      tSamFreq[ 3]        44100
      tSamFreq[ 4]        48000
    Endpoint Descriptor:
      bLength                 9
      bDescriptorType         5
      bEndpointAddress     0x81  EP 1 IN
      bmAttributes            5
        Transfer Type            Isochronous
        Synch Type               Asynchronous
        Usage Type               Data
      wMaxPacketSize     0x00c8  1x 200 bytes
      bInterval               1
      bRefresh                0
      bSynchAddress           0
      AudioControl Endpoint Descriptor:
        bLength                 7
        bDescriptorType        37
        bDescriptorSubtype      1 (EP_GENERAL)
        bmAttributes         0x01
          Sampling Frequency
        bLockDelayUnits         0 Undefined
        wLockDelay              0 Undefined

1 个答案:

答案 0 :(得分:0)

我也在使用 libusb 库从Android上的USB麦克风录制。

我试图使用 libusb 接口来解析描述符,例如 libusb_get_config_descriptor(),但不幸的是它没有用。

我的解决方案是自己做。 在USB documentation类中使用getRawDescriptors() + UsbDeviceConnection方法:

//parse audio interface descriptors of TYPE 1 FORMAT (PCM) - get all recording settings
public static List<UsbAudioInfo>  ParseUsbRawDescriptor(byte[] rawDesc)
{
    //list of settings my flat custom class
    List<UsbAudioInfo>  list = new ArrayList<>();

    final int INTERFACE = 4;
    final int AUDIO = 1;
    final int STREAMING = 2;

    //Timber.i("Descriptor length: " + rawDesc.length);
    int idVendor = ((rawDesc[9] & 0xff) << 8) | (rawDesc[8] & 0xff);
    int idProduct = ((rawDesc[11] & 0xff) << 8) | (rawDesc[10] & 0xff);

    int bLength = 0;
    for(int i = 0; i<rawDesc.length; i+=bLength) {

        bLength = rawDesc[i];
        int bDescriptorType  = rawDesc[i+1];

        if (bDescriptorType == INTERFACE)
        {
            int bInterfaceNumber = rawDesc[i+2];
            int bAlternateSetting = rawDesc[i+3];
            int bNumEndpoints = rawDesc[i+4];
            int bInterfaceClass = rawDesc[i+5];
            int bInterfaceSubClass =  rawDesc[i+6];

            //interested only in ADUIO  STREAMING interface with endpoints (support only PCM >> Type I Format Type Descriptor)
            if (bInterfaceClass == AUDIO && bInterfaceSubClass == STREAMING && bNumEndpoints>0)
            {
                //AudioStreaming Interface Descriptor: (AS_GENERAL)
                bLength += rawDesc[i+bLength];

                //AudioStreaming Interface Descriptor: (FORMAT_TYPE)
                int ftbLength = rawDesc[i+bLength];

                //before we proceed check if IN endpoint (recording) => jump to endpoint desc
                int bEndpointAddress =  rawDesc[i+bLength+ftbLength + 2];
                int direction = bEndpointAddress & 0x80; // 10000000b; Bit 7
                //only recording
                if (direction == USB_DIR_IN)
                {
                    int epaddress = bEndpointAddress & 0xff;
                    int epmaxpacket = ((rawDesc[i+bLength+ftbLength+5] & 0xff) << 8) | (rawDesc[i+bLength+ftbLength+4] & 0xff);
                    //PCM TYPE_1 descrtiptor
                    //http://www.usb.org/developers/docs/devclass_docs/frmts10.pdf
                    int bNrChannels = rawDesc[i+bLength + 4];
                    int bBitResolution = rawDesc[i+bLength + 6];
                    int bSamFreqType = rawDesc[i+bLength + 7];

                    int ratesind = i+bLength + 8;

                    for( int s = 0; s < bSamFreqType; s++)
                    {
                        //3 byte int:
                        byte b1 =  rawDesc[ratesind + s*3 + 0];
                        byte b2 =  rawDesc[ratesind + s*3 + 1];
                        byte b3 =  rawDesc[ratesind + s*3 + 2];

                        int rate = (b1 & 0xFF) | ((b2 & 0xFF) << 8) | ((b3 & 0x0F) << 16);

                        //store in my custom  object
                        UsbAudioInfo info = new UsbAudioInfo();
                        info.SAMPLING_RATE = rate;
                        info.ALTSET_NUM = bAlternateSetting;
                        info.CHANNELS = bNrChannels;
                        info.ENDPOINT_ADDRESS = epaddress;
                        info.ENDPOINT_MAXPCKSIZE = epmaxpacket;
                        info.FORMAT = bBitResolution;
                        info.INTERFACE_NUM = bInterfaceNumber;
                        info.VID = idVendor;
                        info.PID = idProduct;

                        list.add(info);
                    }
                }
            }
        }
    }

    return list;
}