kopia lustrzana https://github.com/skuep/AIOC
Implemented a rudimentary Host OS detection for better MacOS support for UAC2.0
rodzic
bb71ef3d28
commit
ea57a6b2d9
|
@ -651,6 +651,17 @@ void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedba
|
||||||
feedback_param->method = AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED;
|
feedback_param->method = AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tud_audio_feedback_format_correction_cb(uint8_t func_id)
|
||||||
|
{
|
||||||
|
/* Use the quirk detection to detect whether we need format correction (10.14) according to the USB specification (MacOS)
|
||||||
|
* or whether we use no correction (16.16) as a quirk (Windows). Linux works either way. */
|
||||||
|
if (tud_speed_get() == TUSB_SPEED_FULL) {
|
||||||
|
return USB_DescUAC2Quirk() ? false : true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift)
|
TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift)
|
||||||
{
|
{
|
||||||
static uint32_t prev_cycles = 0;
|
static uint32_t prev_cycles = 0;
|
||||||
|
|
|
@ -27,6 +27,23 @@
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "stm32f3xx_hal.h"
|
#include "stm32f3xx_hal.h"
|
||||||
|
|
||||||
|
/* For quirk detection, borrowed from tinyusb uac2_speaker_fb example */
|
||||||
|
static tusb_desc_type_t desc_req_buf[2];
|
||||||
|
static int desc_req_idx = 0;
|
||||||
|
|
||||||
|
void quirk_host_os_hint_desc_cb(tusb_desc_type_t desc) {
|
||||||
|
if (desc == TUSB_DESC_DEVICE) {
|
||||||
|
desc_req_idx = 0;
|
||||||
|
} else if (desc_req_idx < 2 && (desc == TUSB_DESC_CONFIGURATION || desc == TUSB_DESC_BOS || desc == TUSB_DESC_STRING)) {
|
||||||
|
// Skip redundant request
|
||||||
|
if (desc_req_idx == 0 || (desc_req_idx > 0 && desc_req_buf[desc_req_idx - 1] != desc)) {
|
||||||
|
desc_req_buf[desc_req_idx++] = desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Device Descriptors
|
// Device Descriptors
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
@ -54,6 +71,8 @@ uint8_t const* tud_descriptor_device_cb(void) {
|
||||||
desc_device.idVendor = (settingsRegMap[SETTINGS_REG_USBID] & SETTINGS_REG_USBID_VID_MASK) >> SETTINGS_REG_USBID_VID_OFFS;
|
desc_device.idVendor = (settingsRegMap[SETTINGS_REG_USBID] & SETTINGS_REG_USBID_VID_MASK) >> SETTINGS_REG_USBID_VID_OFFS;
|
||||||
desc_device.idProduct = (settingsRegMap[SETTINGS_REG_USBID] & SETTINGS_REG_USBID_PID_MASK) >> SETTINGS_REG_USBID_PID_OFFS;
|
desc_device.idProduct = (settingsRegMap[SETTINGS_REG_USBID] & SETTINGS_REG_USBID_PID_MASK) >> SETTINGS_REG_USBID_PID_OFFS;
|
||||||
|
|
||||||
|
quirk_host_os_hint_desc_cb(TUSB_DESC_DEVICE);
|
||||||
|
|
||||||
return (uint8_t const*) &desc_device;
|
return (uint8_t const*) &desc_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,57 +144,65 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
||||||
AIOC_DFU_RT_DESC_LEN \
|
AIOC_DFU_RT_DESC_LEN \
|
||||||
)
|
)
|
||||||
|
|
||||||
uint8_t const desc_fs_configuration[] = {
|
/* Make this as template, due to quirks necessary in feedback endpoint size */
|
||||||
// Config number, interface count, string index, total length, attribute, power in mA
|
#define CONFIG_DESC(_quirk) \
|
||||||
TUD_CONFIG_DESCRIPTOR(
|
TUD_CONFIG_DESCRIPTOR( \
|
||||||
/* config_num */ 1,
|
/* config_num */ 1, \
|
||||||
/* _itfcount */ ITF_NUM_TOTAL,
|
/* _itfcount */ ITF_NUM_TOTAL, \
|
||||||
/* _stridx */ 0x00,
|
/* _stridx */ 0x00, \
|
||||||
/* _total_len */ CONFIG_TOTAL_LEN,
|
/* _total_len */ CONFIG_TOTAL_LEN, \
|
||||||
/* _attribute */ 0x00,
|
/* _attribute */ 0x00, \
|
||||||
/* _power_ma */ 100
|
/* _power_ma */ 100 \
|
||||||
),
|
), \
|
||||||
|
AIOC_AUDIO_DESCRIPTOR( \
|
||||||
AIOC_AUDIO_DESCRIPTOR(
|
/* _itfnum */ ITF_NUM_AUDIO_CONTROL, \
|
||||||
/* _itfnum */ ITF_NUM_AUDIO_CONTROL,
|
/* _stridx */ STR_IDX_AUDIOITF, \
|
||||||
/* _stridx */ STR_IDX_AUDIOITF,
|
/* _nBytesPerSample */ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE, \
|
||||||
/* _nBytesPerSample */ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE,
|
/* _nBitsUsedPerSample */ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE*8, \
|
||||||
/* _nBitsUsedPerSample */ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE*8,
|
/* _epin */ EPNUM_AUDIO_IN, \
|
||||||
/* _epin */ EPNUM_AUDIO_IN,
|
/* _epinsize */ CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX, \
|
||||||
/* _epinsize */ CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX,
|
/* _epout */ EPNUM_AUDIO_OUT, \
|
||||||
/* _epout */ EPNUM_AUDIO_OUT,
|
/* _epoutsize */ CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX, \
|
||||||
/* _epoutsize */ CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX,
|
/* _epfb */ EPNUM_AUDIO_FB, \
|
||||||
/* _epfb */ EPNUM_AUDIO_FB
|
/* epfbsize */ ((_quirk) ? 4 : 3) \
|
||||||
),
|
), \
|
||||||
AIOC_HID_DESCRIPTOR(
|
AIOC_HID_DESCRIPTOR( \
|
||||||
/* _itfnum */ ITF_NUM_HID,
|
/* _itfnum */ ITF_NUM_HID, \
|
||||||
/* _stridx */ STR_IDX_HIDITF,
|
/* _stridx */ STR_IDX_HIDITF, \
|
||||||
/* _boot_protocol */HID_ITF_PROTOCOL_NONE,
|
/* _boot_protocol */HID_ITF_PROTOCOL_NONE, \
|
||||||
/*_report_desc_len*/sizeof(desc_hid_report),
|
/*_report_desc_len*/sizeof(desc_hid_report), \
|
||||||
/* _epin */ EPNUM_HID_IN,
|
/* _epin */ EPNUM_HID_IN, \
|
||||||
/* _epsize */ CFG_TUD_HID_EP_BUFSIZE,
|
/* _epsize */ CFG_TUD_HID_EP_BUFSIZE, \
|
||||||
/* _ep_interval */ 0x20
|
/* _ep_interval */ 0x20 \
|
||||||
),
|
), \
|
||||||
|
AIOC_CDC_DESCRIPTOR( \
|
||||||
AIOC_CDC_DESCRIPTOR(
|
/* _itfnum */ ITF_NUM_CDC_0, \
|
||||||
/* _itfnum */ ITF_NUM_CDC_0,
|
/* _stridx */ STR_IDX_CDCITF, \
|
||||||
/* _stridx */ STR_IDX_CDCITF,
|
/* _ep_notif */ EPNUM_CDC_0_NOTIF, \
|
||||||
/* _ep_notif */ EPNUM_CDC_0_NOTIF,
|
/* _ep_notif_size */ 8, \
|
||||||
/* _ep_notif_size */ 8,
|
/* _epout */ EPNUM_CDC_0_OUT, \
|
||||||
/* _epout */ EPNUM_CDC_0_OUT,
|
/* _epin */ EPNUM_CDC_0_IN, \
|
||||||
/* _epin */ EPNUM_CDC_0_IN,
|
/* _epsize */ CFG_TUD_CDC_EP_BUFSIZE \
|
||||||
/* _epsize */ CFG_TUD_CDC_EP_BUFSIZE
|
), \
|
||||||
),
|
AIOC_DFU_RT_DESCRIPTOR( \
|
||||||
|
/* _itfnum */ ITF_NUM_DFU_RT, \
|
||||||
AIOC_DFU_RT_DESCRIPTOR(
|
/* _stridx */ STR_IDX_DFU_RT, \
|
||||||
/* _itfnum */ ITF_NUM_DFU_RT,
|
|
||||||
/* _stridx */ STR_IDX_DFU_RT,
|
|
||||||
/* _attr */ DFU_ATTR_WILL_DETACH | \
|
/* _attr */ DFU_ATTR_WILL_DETACH | \
|
||||||
DFU_ATTR_CAN_UPLOAD | \
|
DFU_ATTR_CAN_UPLOAD | \
|
||||||
DFU_ATTR_CAN_DOWNLOAD,
|
DFU_ATTR_CAN_DOWNLOAD, \
|
||||||
/* _timeout */ 255, /* not used if WILL_DETACH */
|
/* _timeout */ 255, /* not used if WILL_DETACH */ \
|
||||||
/* _xfer_size */ 2048 /* max size for stm32 dfu bootloader */
|
/* _xfer_size */ 2048 /* max size for stm32 dfu bootloader */ \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
uint8_t const desc_fs_configuration_quirk[] = {
|
||||||
|
/* quirk is required for Windows, Linux doesn't care.
|
||||||
|
* (see https://github.com/hathach/tinyusb/pull/2328/commits/6a67bac47c0f83eebd63ca99654ed26e51b21145) */
|
||||||
|
CONFIG_DESC(/* quirk */1)
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t const desc_fs_configuration[] = {
|
||||||
|
/* no quirk is required for MacOS, Linux doesn't care */
|
||||||
|
CONFIG_DESC(/* quirk */0)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||||
|
@ -185,8 +212,16 @@ uint8_t const* tud_descriptor_configuration_cb(uint8_t index) {
|
||||||
(void) index; // for multiple configurations
|
(void) index; // for multiple configurations
|
||||||
|
|
||||||
TU_ASSERT(!TUD_OPT_HIGH_SPEED);
|
TU_ASSERT(!TUD_OPT_HIGH_SPEED);
|
||||||
|
|
||||||
|
quirk_host_os_hint_desc_cb(TUSB_DESC_CONFIGURATION);
|
||||||
|
|
||||||
|
/* Try to guess the host OS so we can apply the quirk where needed */
|
||||||
|
if (USB_DescUAC2Quirk()) {
|
||||||
|
return desc_fs_configuration_quirk;
|
||||||
|
} else {
|
||||||
return desc_fs_configuration;
|
return desc_fs_configuration;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// String Descriptors
|
// String Descriptors
|
||||||
|
@ -312,5 +347,18 @@ const uint16_t * tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||||
buffer[0] = len + 2;
|
buffer[0] = len + 2;
|
||||||
buffer[1] = TUSB_DESC_STRING;
|
buffer[1] = TUSB_DESC_STRING;
|
||||||
|
|
||||||
|
quirk_host_os_hint_desc_cb(TUSB_DESC_STRING);
|
||||||
|
|
||||||
return (void *) buffer;
|
return (void *) buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool USB_DescUAC2Quirk(void)
|
||||||
|
{
|
||||||
|
if ( (desc_req_buf[0] == TUSB_DESC_STRING) && (desc_req_buf[1] == TUSB_DESC_BOS || desc_req_buf[1] == TUSB_DESC_CONFIGURATION) ) {
|
||||||
|
/* This pattern of descriptor requests is only found on MacOS devices. MacOS needs the non-quirked descriptor */
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
/* Other patterns hint to Windows, which requires the quirk. Or Linux, which doesn't care and works either way */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef USB_DESCRIPTORS_H_
|
#ifndef USB_DESCRIPTORS_H_
|
||||||
#define USB_DESCRIPTORS_H_
|
#define USB_DESCRIPTORS_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/* Interfaces */
|
/* Interfaces */
|
||||||
enum USB_DESCRIPTORS_ITF {
|
enum USB_DESCRIPTORS_ITF {
|
||||||
ITF_NUM_AUDIO_CONTROL = 0,
|
ITF_NUM_AUDIO_CONTROL = 0,
|
||||||
|
@ -104,7 +106,7 @@ enum USB_STRING_IDX {
|
||||||
TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN + \
|
TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN + \
|
||||||
TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN)
|
TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN)
|
||||||
|
|
||||||
#define AIOC_AUDIO_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epinsize, _epout, _epoutsize, _epfb) \
|
#define AIOC_AUDIO_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epinsize, _epout, _epoutsize, _epfb, _epfbsize) \
|
||||||
/* Standard Interface Association Descriptor (IAD) */ \
|
/* Standard Interface Association Descriptor (IAD) */ \
|
||||||
TUD_AUDIO_DESC_IAD(_itfnum, AUDIO_NUM_INTERFACES, /*_stridx*/ 0x00), \
|
TUD_AUDIO_DESC_IAD(_itfnum, AUDIO_NUM_INTERFACES, /*_stridx*/ 0x00), \
|
||||||
/* Audio Control Interface */ \
|
/* Audio Control Interface */ \
|
||||||
|
@ -138,7 +140,7 @@ enum USB_STRING_IDX {
|
||||||
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ \
|
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ \
|
||||||
TUD_AUDIO_DESC_CS_AS_ISO_EP(AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, 0x0000), \
|
TUD_AUDIO_DESC_CS_AS_ISO_EP(AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, 0x0000), \
|
||||||
/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ \
|
/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ \
|
||||||
TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_epfb, 1), \
|
TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_epfb, _epfbsize, 1), \
|
||||||
/* Microphone Interface */ \
|
/* Microphone Interface */ \
|
||||||
/* Standard AS Interface Descriptor(4.9.1) */ \
|
/* Standard AS Interface Descriptor(4.9.1) */ \
|
||||||
/* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */ \
|
/* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */ \
|
||||||
|
@ -174,4 +176,6 @@ enum USB_STRING_IDX {
|
||||||
|
|
||||||
#define AIOC_DFU_RT_DESCRIPTOR TUD_DFU_RT_DESCRIPTOR
|
#define AIOC_DFU_RT_DESCRIPTOR TUD_DFU_RT_DESCRIPTOR
|
||||||
|
|
||||||
|
bool USB_DescUAC2Quirk(void);
|
||||||
|
|
||||||
#endif /* USB_DESCRIPTORS_H_ */
|
#endif /* USB_DESCRIPTORS_H_ */
|
||||||
|
|
Ładowanie…
Reference in New Issue