ソースを参照

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

sakumisu 1 年間 前
コミット
ac3be8cb3a
4 ファイル変更53 行追加30 行削除
  1. 25 17
      class/audio/usbd_audio.c
  2. 1 1
      class/audio/usbd_audio.h
  3. 26 11
      class/audio/usbh_audio.c
  4. 1 1
      class/audio/usbh_audio.h

+ 25 - 17
class/audio/usbd_audio.c

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

+ 1 - 1
class/audio/usbd_audio.h

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

+ 26 - 11
class/audio/usbh_audio.c

@@ -184,21 +184,21 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name)
     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;
     int ret;
     uint8_t feature_id = 0xff;
     uint8_t intf;
     uint16_t volume_hex;
-    uint16_t volume_max;
-    uint16_t volume_add;
+    int volume_min_db;
+    int volume_max_db;
 
     if (!audio_class || !audio_class->hport) {
         return -USB_ERR_INVAL;
     }
 
-    if (volume > 100) {
+    if ((volume_db > 127) || (volume_db < -127)) {
         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->wLength = 2;
 
-    /* change volume range start with zero */
-    volume_add = 0x10000 - audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min;
-    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 (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min < 0x8000) {
+        volume_min_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min / 256;
+    } else {
+        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_hex >= volume_add) {
-        volume_hex = volume_hex - volume_add;
+    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 = 0x10000 - (volume_add - volume_hex);
+        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);

+ 1 - 1
class/audio/usbh_audio.h

@@ -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_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);
 
 void usbh_audio_run(struct usbh_audio *audio_class);