libusb - How to select an alternate setting of a u

2020-07-30 00:50发布

问题:

I have a USB sound card that has the following setup and allows for stereo recording with 48000hz 2 channels 16 bit, so I'm trying to set it up that way:

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]
    ]
]

I'm trying to select and use the incoming interface with the alternate setting for stereo input and do the same thing with the interface for the stereo output. For the input, I've tried to do it natively with the following code:

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;
    }
    ...

I'm getting the following error at when setting the alternate interface:

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

and also tried to do it from java with the following code upon receiving the permission to use the device:

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);

I'm getting the following error:

Error (status 6: **UNKNOWN**)

What am I missing?

回答1:

I think it would be highly unusual for the libusb_set_interface_alt_setting call itself to cause the SIGSEGV. I would expect that either a prior call would cause this, or the SIGSEGV is an indirect effect of the call. That is, this call changes the alternate setting, which effectively starts the transfer of audio data. If the buffers, other data structures or the callback are not setup correctly a SIGSEGV may result.

In your situation, I would put more debug messages in the code, including in the library and your callback to try to narrow down the last thing before the crash.

If the code was working for a "mono" device, have a look at what has changed in the move to "Stereo". Perhaps the data-packet size (buffers) needs to be larger.

As far as the Java version is concerned, the error 6 may be related to the fact that you don't seem to be detaching any kernel drivers or claiming the interface before trying to change the alternate setting.

In the past I found it necessary to detach kernel drivers from each and every interface including HID interfaces to free up the allocated bus bandwidth before starting the audio.

Finally, if the free version of usbEffects (Android App) works with this device, you can connect adb to the phone via Wi-Fi and run the app with the device connected to see the debug messages that will tell if the requestType, request etc parameters are correct for this hardware.