update(class/audio): change volume unit with dB, fix uac2.0 volume range

This commit is contained in:
sakumisu
2024-11-25 12:44:32 +08:00
parent a72ecd2202
commit ac3be8cb3a
4 changed files with 54 additions and 31 deletions

View File

@@ -136,27 +136,26 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
memcpy(&volume, *data, *len); memcpy(&volume, *data, *len);
if (volume < 0x8000) { if (volume < 0x8000) {
volume_db = volume / 256; volume_db = volume / 256;
} else if (volume > 0x8000) { } else {
volume_db = (0xffff - volume + 1) / -256; volume_db = (volume - 0x10000) / 256;
} }
volume_db += 128; /* 0 ~ 255 */ USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
usbd_audio_set_volume(busid, ep, ch, volume_db); usbd_audio_set_volume(busid, ep, ch, volume_db);
break; break;
case AUDIO_REQUEST_GET_CUR: case AUDIO_REQUEST_GET_CUR:
volume_db = usbd_audio_get_volume(busid, ep, ch); volume_db = usbd_audio_get_volume(busid, ep, ch);
volume_db -= 128;
if (volume_db >= 0) { if (volume_db >= 0) {
volume = volume_db * 256; volume = volume_db * 256;
} else { } else {
volume = volume_db * 256 + 0xffff + 1; volume = volume_db * 256 + 0x10000;
} }
USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
memcpy(*data, &volume, 2); memcpy(*data, &volume, 2);
*len = 2; *len = 2;
break; break;
case AUDIO_REQUEST_GET_MIN: case AUDIO_REQUEST_GET_MIN:
(*data)[0] = 0x00; /* -2560/256 dB */ (*data)[0] = 0x00; /* -100 dB */
(*data)[1] = 0xdb; (*data)[1] = 0x9c;
*len = 2; *len = 2;
break; break;
case AUDIO_REQUEST_GET_MAX: case AUDIO_REQUEST_GET_MAX:
@@ -165,7 +164,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
*len = 2; *len = 2;
break; break;
case AUDIO_REQUEST_GET_RES: case AUDIO_REQUEST_GET_RES:
(*data)[0] = 0x00; /* -256/256 dB */ (*data)[0] = 0x00; /* 1 dB */
(*data)[1] = 0x01; (*data)[1] = 0x01;
*len = 2; *len = 2;
break; break;
@@ -178,22 +177,31 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
case AUDIO_REQUEST_CUR: case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) { if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
volume_db = usbd_audio_get_volume(busid, ep, ch); volume_db = usbd_audio_get_volume(busid, ep, ch);
volume = volume_db; if (volume_db >= 0) {
volume = volume_db * 256;
} else {
volume = volume_db * 256 + 0x10000;
}
USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
memcpy(*data, &volume, 2); memcpy(*data, &volume, 2);
*len = 2; *len = 2;
} else { } else {
memcpy(&volume, *data, *len); memcpy(&volume, *data, *len);
volume_db = volume; if (volume < 0x8000) {
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume); volume_db = volume / 256;
} else {
volume_db = (volume - 0x10000) / 256;
}
USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db);
usbd_audio_set_volume(busid, ep, ch, volume_db); usbd_audio_set_volume(busid, ep, ch, volume_db);
} }
break; break;
case AUDIO_REQUEST_RANGE: case AUDIO_REQUEST_RANGE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) { if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
*((uint16_t *)(*data + 0)) = 1; *((uint16_t *)(*data + 0)) = 1;
*((uint16_t *)(*data + 2)) = 0; *((uint16_t *)(*data + 2)) = 0x9c00; /* MIN -100 dB */
*((uint16_t *)(*data + 4)) = 100; *((uint16_t *)(*data + 4)) = 0x0000; /* MAX 0 dB */
*((uint16_t *)(*data + 6)) = 1; *((uint16_t *)(*data + 6)) = 0x100; /* RES 1 dB */
*len = 8; *len = 8;
} else { } else {
} }
@@ -312,12 +320,12 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid,
return intf; return intf;
} }
__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume) __WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db)
{ {
(void)busid; (void)busid;
(void)ep; (void)ep;
(void)ch; (void)ch;
(void)volume; (void)volume_db;
} }
__WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch) __WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch)

View File

@@ -27,7 +27,7 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface
void usbd_audio_open(uint8_t busid, uint8_t intf); void usbd_audio_open(uint8_t busid, uint8_t intf);
void usbd_audio_close(uint8_t busid, uint8_t intf); void usbd_audio_close(uint8_t busid, uint8_t intf);
void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume); void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db);
int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch); int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch);
void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute); void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute);
bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch); bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch);

View File

@@ -184,21 +184,21 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
return ret; return ret;
} }
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume) int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db)
{ {
struct usb_setup_packet *setup; struct usb_setup_packet *setup;
int ret; int ret;
uint8_t feature_id = 0xff; uint8_t feature_id = 0xff;
uint8_t intf; uint8_t intf;
uint16_t volume_hex; uint16_t volume_hex;
uint16_t volume_max; int volume_min_db;
uint16_t volume_add; int volume_max_db;
if (!audio_class || !audio_class->hport) { if (!audio_class || !audio_class->hport) {
return -USB_ERR_INVAL; return -USB_ERR_INVAL;
} }
if (volume > 100) { if ((volume_db > 127) || (volume_db < -127)) {
return -USB_ERR_INVAL; return -USB_ERR_INVAL;
} }
@@ -271,15 +271,30 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint
setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf;
setup->wLength = 2; setup->wLength = 2;
/* change volume range start with zero */ if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min < 0x8000) {
volume_add = 0x10000 - audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min; volume_min_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min / 256;
volume_max = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max + volume_add;
volume_hex = volume * volume_max / 100.0;
if (volume_hex >= volume_add) {
volume_hex = volume_hex - volume_add;
} else { } else {
volume_hex = 0x10000 - (volume_add - volume_hex); volume_min_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min - 0x10000) / 256;
}
if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max < 0x8000) {
volume_max_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max / 256;
} else {
volume_max_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max - 0x10000) / 256;
}
USB_LOG_INFO("Get ch:%d dB range: %d dB ~ %d dB\r\n", volume_min_db, volume_max_db);
if (volume_db >= 0) {
volume_hex = volume_db * 256;
if (volume_hex > audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max) {
return -USB_ERR_RANGE;
}
} else {
volume_hex = volume_db * 256 + 0x10000;
if (volume_hex < audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min) {
return -USB_ERR_RANGE;
}
} }
memcpy(g_audio_buf, &volume_hex, 2); memcpy(g_audio_buf, &volume_hex, 2);

View File

@@ -59,7 +59,7 @@ extern "C" {
int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution); int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution);
int usbh_audio_close(struct usbh_audio *audio_class, const char *name); int usbh_audio_close(struct usbh_audio *audio_class, const char *name);
int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume); int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db);
int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute); int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute);
void usbh_audio_run(struct usbh_audio *audio_class); void usbh_audio_run(struct usbh_audio *audio_class);