libusb - 如何为立体声录音选择usb-soundcard的备用设置?

时间:2016-01-27 13:53:27

标签: android audio java-native-interface usb libusb

我有一个USB声卡,具有以下设置,允许使用4800hz 2声道16位立体声录音,所以我试图以这种方式进行设置:

UsbConfiguration[mId=1,mName=null, mAttributes=160, mMaxPower=50, 
    mInterfaces=[                                                                
        UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=1,mSubclass=1,mProtocol=0,
            mEndpoints=[]
        UsbInterface[mId=1,mAlternateSetting=0,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[]
        UsbInterface[mId=1,mAlternateSetting=1,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=384,mInterval=1]]
        UsbInterface[mId=1,mAlternateSetting=2,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=576,mInterval=1]]
        UsbInterface[mId=1,mAlternateSetting=3,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=192,mInterval=1]]
        UsbInterface[mId=2,mAlternateSetting=0,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[]
        UsbInterface[mId=2,mAlternateSetting=1,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=196,mInterval=1]]
        UsbInterface[mId=2,mAlternateSetting=2,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=294,mInterval=1]]
        UsbInterface[mId=2,mAlternateSetting=3,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=388,mInterval=1]]
        UsbInterface[mId=2,mAlternateSetting=4,mName=null,mClass=1,mSubclass=2,mProtocol=0,
            mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=582,mInterval=1]]
        UsbInterface[mId=3,mAlternateSetting=0,mName=null,mClass=3,mSubclass=0,mProtocol=0,
            mEndpoints=[UsbEndpoint[mAddress=130,mAttributes=3,mMaxPacketSize=16,mInterval=16]
    ]
]

我试图选择并使用具有立体声输入的备用设置的传入接口,并使用立体声输出的接口执行相同的操作。 对于输入,我尝试使用以下代码原生地执行此操作:

int AndroidUSBAudioIO_start(int sampleRate, int bufferSize, void *callback, void *clientData) {
    int rc = -1;

    if (androidUSBAudioIO == NULL) {
        androidUSBAudioIO = (AndroidUSBAudioIOInternals *) malloc(sizeof(AndroidUSBAudioIOInternals));
    }
    androidUSBAudioIO->samplerate = sampleRate;
    androidUSBAudioIO->buffersize = bufferSize;
    androidUSBAudioIO->callback = (audioUSBProcessingCallback *) callback;
    androidUSBAudioIO->clientData = clientData;
    androidUSBAudioIO->maruStream = 0;
    androidUSBAudioIO->isSetup = 0;
    androidUSBAudioIO->isPlaying = 0;

    rc = libusb_init(NULL);
    if (rc < 0) {          
    }

    androidUSBAudioIO->deviceHandle = libusb_open_device_with_vid_pid(NULL, VID, PID);
    if (!androidUSBAudioIO->deviceHandle) {
        rc = -1;
        goto out;
    }
    rc = libusb_reset_device(androidUSBAudioIO->deviceHandle);
    if (rc < 0) {
        goto out;
    }
    rc = libusb_set_configuration(androidUSBAudioIO->deviceHandle, 1);
    if (rc < 0) {
    }
    rc = libusb_kernel_driver_active(androidUSBAudioIO->deviceHandle, IFACE_NUM);
    if (rc == 1) {
        rc = libusb_detach_kernel_driver(androidUSBAudioIO->deviceHandle, IFACE_NUM);
        if (rc < 0) {
            goto out;
        }
    }
    rc = libusb_claim_interface(androidUSBAudioIO->deviceHandle, IFACE_NUM);
    if (rc < 0) {
        goto out;
    }

    rc = libusb_set_interface_alt_setting(androidUSBAudioIO->deviceHandle, 1, 2);
    if (rc < 0) {
        printf("libusb_claim_interface: %s.\n", libusb_error_name(rc));
        goto out;
    }
    ...

我在设置备用接口时遇到以下错误:

Fatal signal 11 (SIGSEGV) at 0x0000001d (code=1), thread 10303

并且在收到使用设备的权限后,还尝试使用以下代码从java中执行此操作:

UsbDeviceConnection mUsbDevConn = mUsbManager.openDevice(mAudioDevice);
int mReqType = 0x01; //
int mRequest = 0x0B; // SET_INTERFACE USB SPEC CONSTANT
int mValue = 0x02; // alt settings
int mIndex = 0x01; // interface nr
byte[] mBuffer = null;
int mLength = 0;
int mTimout = 1000;
mUsbDevConn.controlTransfer(UsbConstants.USB_DIR_OUT | mReqType, mRequest, mValue, mIndex, mBuffer, mLength, mTimout);

我收到以下错误:

Error (status 6: **UNKNOWN**)

我错过了什么?

1 个答案:

答案 0 :(得分:2)

我认为libusb_set_interface_alt_setting调用本身导致SIGSEGV是非常不寻常的。我希望先前的调用会导致这种情况,或者SIGSEGV是调用的间接影响。也就是说,此调用会更改备用设置,从而有效地开始传输音频数据。如果未正确设置缓冲区,其他数据结构或回调,则可能导致SIGSEGV。

在您的情况下,我会在代码中添加更多调试消息,包括在库和回调中,以尝试缩小崩溃前的最后一件事。

如果代码适用于&#34; mono&#34;设备,看看转移到&#34; Stereo&#34;的变化。数据包大小(缓冲区)可能需要更大。

就Java版本而言,错误6可能与您在尝试更改备用设置之前似乎没有分离任何内核驱动程序或声明接口这一事实有关。

过去我发现有必要从包括HID接口在内的每个接口分离内核驱动程序,以便在启动音频之前释放分配的总线带宽。

最后,如果usbEffects(Android App)的免费版本适用于此设备,您可以通过Wi-Fi将adb连接到手机,并在连接设备的情况下运行应用程序以查看将告知requestType的调试消息,请求等参数对于此硬件是正确的。