Re: [Alsa-user] Get SPDIF-in sample rate
2017-07-19 8:46 GMT+02:00 Clemens Ladisch: > The HID interface is managed by another driver. The kernel driver > already knows how to write to these registers with a control request > instead (see below). Could you check if a control read request works, > or if the response still goes through the HID pipe? > I've tried that, but unfortunately it didn't work. The input request reads zero bytes. Well, I think that means I'll have to use my workarount with libhidapi. Below is my code. I don't feel very confident on all those bmRequestType, bRequest, wValue and other parameters, I just used the ones from your example. May be later I will be able to sniff the communication of the card with its proprietary Windows driver, and if I get a different results I'll revert back to you. int cm106_read(libusb_device_handle *handle, char reg, uint16_t *data) { int res; unsigned char buf[4] = {0x30, // 0x20 to write, 0x30 to read 0x00, // DATAL 0x00, // DATAH reg}; // Register address if ((res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_ENDPOINT, LIBUSB_REQUEST_SET_CONFIGURATION, 0, 0, buf, 4, 0)) != 4) return res; if ((res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_ENDPOINT, LIBUSB_REQUEST_SET_CONFIGURATION, 0, 0, buf, 4, 0)) < 0) // <-- THIS FUNCTION RETURNS 0 return res; if (res != 3) { fprintf(stderr, "DEBUG Invalid response length" return -1; } if (buf[0] & 0xe0 != 0x20) // No register data in the input { fprintf(stderr, "DEBUG data: %02X %02X %02X\n", buf[0], buf[1], buf[2]); return -1; } *data = (((uint16_t)buf[2]) << 8) + buf[1]; return 0; } // Just for completeness, the below function successfully writes the data into cm106 registers int cm106_write(libusb_device_handle *handle, char reg, uint16_t data) { unsigned char buf[4] = {0x20, // 0x20 to write, 0x30 to read data & 0xff,// DATAL (data >> 8) & 0xff, // DATAH reg}; // Register address return libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_ENDPOINT, LIBUSB_REQUEST_SET_CONFIGURATION, 0, 0, buf, 4, 0); } Thank you for your support! Best regards Denis Shulyaka -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot___ Alsa-user mailing list Alsa-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-user
Re: [Alsa-user] Get SPDIF-in sample rate
Denis Shulyaka wrote: > 2017-07-18 8:47 GMT+02:00 Clemens Ladisch: > > > Does ALSA provide any general interface for the userspace applications > > > that indicates the SPDIF source sample rate? > > > > Yes, but the USB audio driver does not implement it because the USB > > audio specification does not define such an interface between the driver > > and the device. > > What could I use if I had a non-USB sound card with SPDIF-in? There would be a mixer control "IEC958 Capture Default" associated with the PCM device (i.e., not a real mixer control visible in alsamixer), containing the channel status bits; the "IEC958 Capture Mask" control defines which bits are valid. > > At the moment, you have to write the code yourself. But if you've > > tested it, we would be interested in integrating it into the kernel > > driver. > > The below program outputs the current SPDIF-In sample rate of my card. The HID interface is managed by another driver. The kernel driver already knows how to write to these registers with a control request instead (see below). Could you check if a control read request works, or if the response still goes through the HID pipe? Regards, Clemens -- static int snd_usb_cm106_write_int_reg(struct usb_device *dev, int reg, u16 value) { u8 buf[4]; buf[0] = 0x20; buf[1] = value & 0xff; buf[2] = (value >> 8) & 0xff; buf[3] = reg; return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, 0, 0, , 4); } -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Alsa-user mailing list Alsa-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-user
Re: [Alsa-user] Get SPDIF-in sample rate
2017-07-18 8:47 GMT+02:00 Clemens Ladisch: > In general, SPDIF inputs do not resample, and if you try to record with > the wrong sample rate, the result has the original sample rate and is > just labelled wrong. > That is a good news, but I would still prefer to know the sample rate because if I want to output it, I would need to open the output device with the correct sample rate, or I will still have a resampling. > Does ALSA provide any general interface for the userspace applications > > that indicates the SPDIF source sample rate? > > Yes, but the USB audio driver does not implement it because the USB > audio specification does not define such an interface between the driver > and the device. > What could I use if I had a non-USB sound card with SPDIF-in? > At the moment, you have to write the code yourself. But if you've > tested it, we would be interested in integrating it into the kernel > driver. > The below program outputs the current SPDIF-In sample rate of my card. The only problem with it is that my sense of perfection hurts when I'm working around the driver like that. All device-specific parts should be in kernel. [root@speaker cm106spdif]# gcc cm106spdif.c -l hidapi-libusb [root@speaker cm106spdif]# ./a.out 44.1K [root@speaker cm106spdif]# cat cm106spdif.c #include #include #include #include #include int cm106_read(hid_device *handle, char reg, uint16_t *data) { unsigned char buf[5] = {0x00,// report id for hidapi 0x30,// 0x20 to write, 0x30 to read 0x00,// DATAL 0x00,// DATAH reg};// Register address if (hid_write(handle, buf, 5) != 5) return -1; if (hid_read(handle, buf, 5) != 3) return -2; if (buf[0] & 0xe0 != 0x20)// No register data in the input report return -3; *data = (((uint16_t)buf[2]) << 8) + buf[1]; return 0; } int cm106_write(hid_device *handle, char reg, uint16_t data) { unsigned char buf[5] = {0x00,// report id for hidapi 0x20,// 0x20 to write, 0x30 to read data & 0xff,// DATAL (data >> 8),// DATAH reg};// Register address if (hid_write(handle, buf, 5) != 5) return -1; return 0; } int main(void) { hid_device *handle; uint16_t data = 0; unsigned char SPDFI_FREQ; if ( !(handle = hid_open(0xd8c, 0x102, NULL)) ) err(1, "hid_open: %ls", hid_error(handle)); if (cm106_read(handle, 3, ) < 0) err(2, "read: %ls", hid_error(handle)); //printf("data=%04X\n", data); SPDFI_FREQ = (data & 0x0180) >> 7; switch(SPDFI_FREQ) { case 0: printf("44.1K\n"); break; case 2: printf("48K\n"); break; case 3: printf("32K\n"); break; default: printf("reserved\n"); } hid_close(handle); hid_exit(); return 0; } Best regards, Denis Shulyaka -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot___ Alsa-user mailing list Alsa-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-user
Re: [Alsa-user] Get SPDIF-in sample rate
Denis Shulyaka wrote: > I have a CM106-based usb sound card (0d8c:0102) with SPDIF-In. My aim > is to decode the compressed audio formats that may come from this > source. And the first task for this is to get the original sample rate > of the source to avoid any resampling. In general, SPDIF inputs do not resample, and if you try to record with the wrong sample rate, the result has the original sample rate and is just labelled wrong. And in practice, everybody uses 48 kHz. > According to the CM106 datasheet, one can read the SPDIF-In sample > rate from SPDFI_FREQ bits (8~7 of register 03). > What is the correct way to do so? Can ALSA read those register bits? In theory, this would be possible. > Does ALSA provide any general interface for the userspace applications > that indicates the SPDIF source sample rate? Yes, but the USB audio driver does not implement it because the USB audio specification does not define such an interface between the driver and the device. > Should I attempt to communicate with the hardware with libusb, or can > I do it with ALSA only? At the moment, you have to write the code yourself. But if you've tested it, we would be interested in integrating it into the kernel driver. Regards, Clemens -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Alsa-user mailing list Alsa-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-user
[Alsa-user] Get SPDIF-in sample rate
Hi, I have a CM106-based usb sound card (0d8c:0102) with SPDIF-In. My aim is to decode the compressed audio formats that may come from this source. And the first task for this is to get the original sample rate of the source to avoid any resampling. According to the CM106 datasheet, one can read the SPDIF-In sample rate from SPDFI_FREQ bits (8~7 of register 03). What is the correct way to do so? Can ALSA read those register bits? Does ALSA provide any general interface for the userspace applications that indicates the SPDIF source sample rate? Should I attempt to communicate with the hardware with libusb, or can I do it with ALSA only? Please advise. Best regards, Denis Shulyaka -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot___ Alsa-user mailing list Alsa-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-user