I am trying to write a small C program to read and adjust the volume of a USB DAC (Apple USB-C to 3.5mm Dongle). I have been using this document as a reference, but have encountered an issue that I cannot seem to work around. I am receiving a LIBUSB_ERROR_PIPE response for my requests.
libusb_control_transfer(handle, 0b10100001, 0x81, 0x0200, 0x0200, mesg, 2, 500);
is the line I am using, the bmRequestType, bRequest comes from the document on page 68, wValue is 0x02 (VOLUME_CONTROL) with a lower 0 byte, wIndex comes from sniffing wireshark during a volume change (I have a feeling this is where I am failing, however I do not understand how the Terminal ID is sourced), mesg is 2 0x00 bytes, and wLength is 2. The full program is below.
#include <assert.h>
#include <libusb-1.0/libusb.h>
int main(int argc, char **argv) {
libusb_context *context;
libusb_device_handle *handle;
libusb_device *device;
libusb_device **devs;
ssize_t num_devs;
int i;
struct libusb_device_descriptor desc;
unsigned char buffer[256];
assert(!libusb_init(&context));
num_devs = libusb_get_device_list(context, &devs);
if (num_devs < 0) {
fprintf(stderr, "Error getting device list\n");
libusb_exit(context);
return 1;
}
for (i = 0; i < num_devs; ++i) {
libusb_device *dev = devs[i];
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
fprintf(stderr, "Failed to get device descriptor\n");
continue;
}
if(desc.idVendor == 0x05ac && desc.idProduct == 0x110a){
device = dev;
}
}
assert(!libusb_get_device_descriptor(device, &desc));
printf("Vendor ID: %04x\n", desc.idVendor);
printf("Product ID: %04x\n", desc.idProduct);
assert(libusb_open(device, &handle) == 0);
device = libusb_get_device(handle);
assert(libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, buffer, 256) >= 0);
printf("Manufacturer: %s\n", buffer);
assert(libusb_get_string_descriptor_ascii(handle, desc.iProduct, buffer, 256) >= 0);
printf("Product: %s\n", buffer);
if (libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buffer, 256) >= 0)
printf("Serial No: %s\n", buffer);
libusb_detach_kernel_driver(handle, 0);
libusb_claim_interface(handle, 0);
int result = libusb_control_transfer(handle, 0b10100001, 0x81, 0x0200, 0x0200, mesg, 2, 500);
printf(libusb_error_name(result));
printf("%d", result);
printf("\n");
libusb_release_interface(handle, 0);
libusb_attach_kernel_driver(handle, 0);
libusb_exit(context);
}
I think your bRequest
should be 0x1
instead of 0x81
:
int result = libusb_control_transfer(handle, 0b10100001 /* bmRequest */, 0x1 /* bRequest */, 0x0200 /* wValue */, 0x0200 /* wIndex */, mesg, 2 /* wLength */, 500);
I can't quote UAC 1.0 at you right now, but it's what I see in wireshark and your code succeeds, resulting in a volume that matches what I see in Audio MIDI Setup.app
.