@@ -297,6 +297,144 @@ static const uint8_t singstar_mic_config_descriptor[] = {
297297 0 /* bLength */
298298};
299299
300+ static const USBDescStrings ak5370_desc_strings = {
301+ " " ,
302+ " AKM " ,
303+ " AK5370 " ,
304+ };
305+
306+ static const uint8_t ak5370_mic_dev_desc[] = {
307+ 0x12 , // bLength
308+ 0x01 , // bDescriptorType (Device)
309+ 0x10 , 0x01 , // bcdUSB 1.10
310+ 0x00 , // bDeviceClass (Use class information in the Interface Descriptors)
311+ 0x00 , // bDeviceSubClass
312+ 0x00 , // bDeviceProtocol
313+ 0x08 , // bMaxPacketSize0 8
314+ 0x56 , 0x05 , // idVendor 0x0556
315+ 0x01 , 0x00 , // idProduct 0x01
316+ 0x01 , 0x00 , // bcdDevice 0.01
317+ 0x01 , // iManufacturer (String Index)
318+ 0x02 , // iProduct (String Index)
319+ 0x00 , // iSerialNumber (String Index)
320+ 0x01 , // bNumConfigurations 1
321+
322+ // 18 bytes
323+ };
324+
325+ static const uint8_t ak5370_mic_config_desc[] = {
326+ 0x09 , // bLength
327+ 0x02 , // bDescriptorType (Configuration)
328+ 0x76 , 0x00 , // wTotalLength 118
329+ 0x02 , // bNumInterfaces 2
330+ 0x01 , // bConfigurationValue
331+ 0x00 , // iConfiguration (String Index)
332+ 0x80 , // bmAttributes
333+ 0x2D , // bMaxPower 90mA
334+
335+ 0x09 , // bLength
336+ 0x04 , // bDescriptorType (Interface)
337+ 0x00 , // bInterfaceNumber 0
338+ 0x00 , // bAlternateSetting
339+ 0x00 , // bNumEndpoints 0
340+ 0x01 , // bInterfaceClass (Audio)
341+ 0x01 , // bInterfaceSubClass (Audio Control)
342+ 0x00 , // bInterfaceProtocol
343+ 0x00 , // iInterface (String Index)
344+
345+ 0x09 , // bLength
346+ 0x24 , // bDescriptorType (See Next Line)
347+ 0x01 , // bDescriptorSubtype (CS_INTERFACE -> HEADER)
348+ 0x00 , 0x01 , // bcdADC 1.00
349+ 0x26 , 0x00 , // wTotalLength 38
350+ 0x01 , // binCollection 0x01
351+ 0x01 , // baInterfaceNr 1
352+
353+ 0x0C , // bLength
354+ 0x24 , // bDescriptorType (See Next Line)
355+ 0x02 , // bDescriptorSubtype (CS_INTERFACE -> INPUT_TERMINAL)
356+ 0x01 , // bTerminalID
357+ 0x01 , 0x02 , // wTerminalType (Microphone)
358+ 0x02 , // bAssocTerminal
359+ 0x01 , // bNrChannels 1
360+ 0x00 , 0x00 , // wChannelConfig
361+ 0x00 , // iChannelNames
362+ 0x00 , // iTerminal
363+
364+ 0x09 , // bLength
365+ 0x24 , // bDescriptorType (See Next Line)
366+ 0x03 , // bDescriptorSubtype (CS_INTERFACE -> OUTPUT_TERMINAL)
367+ 0x02 , // bTerminalID
368+ 0x01 , 0x01 , // wTerminalType (USB Streaming)
369+ 0x01 , // bAssocTerminal
370+ 0x03 , // bSourceID
371+ 0x00 , // iTerminal
372+
373+ 0x08 , // bLength
374+ 0x24 , // bDescriptorType (See Next Line)
375+ 0x06 , // bDescriptorSubtype (CS_INTERFACE -> FEATURE_UNIT)
376+ 0x03 , // bUnitID
377+ 0x01 , // bSourceID
378+ 0x01 , // bControlSize 1
379+ 0x43 , 0x00 , // bmaControls[0] (Mute,Volume,Automatic)
380+
381+ 0x09 , // bLength
382+ 0x04 , // bDescriptorType (Interface)
383+ 0x01 , // bInterfaceNumber 1
384+ 0x00 , // bAlternateSetting
385+ 0x00 , // bNumEndpoints 0
386+ 0x01 , // bInterfaceClass (Audio)
387+ 0x02 , // bInterfaceSubClass (Audio Streaming)
388+ 0x00 , // bInterfaceProtocol
389+ 0x00 , // iInterface (String Index)
390+
391+ 0x09 , // bLength
392+ 0x04 , // bDescriptorType (Interface)
393+ 0x01 , // bInterfaceNumber 1
394+ 0x01 , // bAlternateSetting
395+ 0x01 , // bNumEndpoints 1
396+ 0x01 , // bInterfaceClass (Audio)
397+ 0x02 , // bInterfaceSubClass (Audio Streaming)
398+ 0x00 , // bInterfaceProtocol
399+ 0x00 , // iInterface (String Index)
400+
401+ 0x07 , // bLength
402+ 0x24 , // bDescriptorType (See Next Line)
403+ 0x01 , // bDescriptorSubtype (CS_INTERFACE -> AS_GENERAL)
404+ 0x02 , // bTerminalLink
405+ 0x01 , // bDelay 1
406+ 0x01 , 0x00 , // wFormatTag (PCM)
407+
408+ 0x17 , // bLength
409+ 0x24 , // bDescriptorType (See Next Line)
410+ 0x02 , // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
411+ 0x01 , // bFormatType 1
412+ 0x01 , // bNrChannels (Mono)
413+ 0x02 , // bSubFrameSize 2
414+ 0x10 , // bBitResolution 16
415+ 0x05 , // bSamFreqType 5
416+ 0x40 , 0x1F , 0x00 , // tSamFreq[1] 8000 Hz
417+ 0x11 , 0x2B , 0x00 , // tSamFreq[2] 11025 Hz
418+ 0x22 , 0x56 , 0x00 , // tSamFreq[3] 22050 Hz
419+ 0x44 , 0xAC , 0x00 , // tSamFreq[4] 44100 Hz
420+ 0x80 , 0xBB , 0x00 , // tSamFreq[5] 48000 Hz
421+
422+ 0x07 , // bLength
423+ 0x05 , // bDescriptorType (See Next Line)
424+ 0x81 , // bEndpointAddress (IN/D2H)
425+ 0x01 , // bmAttributes (Isochronous, No Sync, Data EP)
426+ 0x64 , 0x00 , // wMaxPacketSize 100
427+ 0x01 , // bInterval 1 (unit depends on device speed)
428+
429+ 0x07 , // bLength
430+ 0x25 , // bDescriptorType (See Next Line)
431+ 0x01 , // bDescriptorSubtype (CS_ENDPOINT -> EP_GENERAL)
432+ 0x01 , // bmAttributes (Sampling Freq Control)
433+ 0x00 , // bLockDelayUnits
434+ 0x00 , 0x00 , // wLockDelay 0
435+
436+ // 118 bytes
437+ };
300438
301439static void singstar_mic_handle_reset (USBDevice *dev)
302440{
@@ -317,50 +455,60 @@ static int usb_audio_get_control(SINGSTARMICState *s, uint8_t attrib,
317455 int length, uint8_t *data)
318456{
319457 uint8_t cs = cscn >> 8 ;
320- uint8_t cn = cscn - 1 ; /* -1 for the non-present master control */
458+ uint8_t cn = cscn - 1 , i_cn = 0 , max_cn = 0 ; /* -1 for the non-present master control */
321459 uint32_t aid = ATTRIB_ID (cs, attrib, idif);
322460 int ret = USB_RET_STALL;
323461
462+ // single channel or set all if cn == 0xFF
463+ if (cn < countof (s->f .vol ))
464+ {
465+ i_cn = cn;
466+ max_cn = cn + 1 ;
467+ }
468+ else if (cn == 0xFF )
469+ {
470+ i_cn = 0 ;
471+ max_cn = countof (s->f .vol );
472+ }
473+
324474 switch (aid) {
325475 case ATTRIB_ID (AUDIO_MUTE_CONTROL, AUDIO_REQUEST_GET_CUR, 0x0300 ):
326476 data[0 ] = s->f .mute ;
327477 ret = 1 ;
328478 break ;
329479 case ATTRIB_ID (AUDIO_VOLUME_CONTROL, AUDIO_REQUEST_GET_CUR, 0x0300 ):
330- if (cn < 2 ) {
331- // uint16_t vol = (s->f.vol[cn] * 0x8800 + 127) / 255 + 0x8000;
332- uint16_t vol = (s->f .vol [cn] * 0x8800 + 127 ) / 255 + 0x8000 ;
333- data[0 ] = (uint8_t )(vol & 0xFF );
334- data[1 ] = vol >> 8 ;
335- ret = 2 ;
336- }
480+ for (uint8_t i = i_cn; i < max_cn; i++)
481+ {
482+ if (i >= length / sizeof (uint16_t ))
483+ break ;
484+ auto tmp = &data[i * sizeof (uint16_t )];
485+
486+ uint16_t vol = (s->f .vol [i] * 0x8800 + 127 ) / 255 + 0x8000 ;
487+ tmp[0 ] = (uint8_t )(vol & 0xFF );
488+ tmp[1 ] = vol >> 8 ;
489+ ret = 2 ;
490+ }
337491 break ;
338492 case ATTRIB_ID (AUDIO_VOLUME_CONTROL, AUDIO_REQUEST_GET_MIN, 0x0300 ):
339- if (cn < 2 ) {
340- data[0 ] = 0x01 ;
341- data[1 ] = 0x80 ;
342- // data[0] = 0x00;
343- // data[1] = 0xE1; //0xE100 -31dB
344- ret = 2 ;
345- }
493+ data[0 ] = 0x01 ;
494+ data[1 ] = 0x80 ;
495+ // data[0] = 0x00;
496+ // data[1] = 0xE1; //0xE100 -31dB
497+ ret = 2 ;
346498 break ;
347499 case ATTRIB_ID (AUDIO_VOLUME_CONTROL, AUDIO_REQUEST_GET_MAX, 0x0300 ):
348- if (cn < 2 ) {
349- data[0 ] = 0x00 ;
350- data[1 ] = 0x08 ;
351- // data[0] = 0x00;
352- // data[1] = 0x18; //0x1800 +24dB
353- ret = 2 ;
354- }
500+ data[0 ] = 0x00 ;
501+ data[1 ] = 0x08 ;
502+ // data[0] = 0x00;
503+ // data[1] = 0x18; //0x1800 +24dB
504+ ret = 2 ;
355505 break ;
356506 case ATTRIB_ID (AUDIO_VOLUME_CONTROL, AUDIO_REQUEST_GET_RES, 0x0300 ):
357- if (cn < 2 ) {
358- data[0 ] = 0x88 ;
359- data[1 ] = 0x00 ;
360- // data[0] = 0x00;
361- // data[1] = 0x01; //0x0100 1.0 dB
362- ret = 2 ;
363- }
507+ data[0 ] = 0x88 ;
508+ data[1 ] = 0x00 ;
509+ // data[0] = 0x00;
510+ // data[1] = 0x01; //0x0100 1.0 dB
511+ ret = 2 ;
364512 break ;
365513 }
366514
@@ -372,35 +520,57 @@ static int usb_audio_set_control(SINGSTARMICState *s, uint8_t attrib,
372520 int length, uint8_t *data)
373521{
374522 uint8_t cs = cscn >> 8 ;
375- uint8_t cn = cscn - 1 ; /* -1 for the non-present master control */
523+ uint8_t cn = cscn - 1 , i_cn = 0 , max_cn = 0 ; /* -1 for the non-present master control */
376524 uint32_t aid = ATTRIB_ID (cs, attrib, idif);
377525 int ret = USB_RET_STALL;
378526 bool set_vol = false ;
379527
528+ // TODO confusing, singstar gets sent cn == 1 or 2 but AK5370 cn == 0 (master control?)
529+ // single channel or set all if cn == 0xFF
530+ if (cn < countof (s->f .vol ))
531+ {
532+ i_cn = cn;
533+ max_cn = cn + 1 ;
534+ }
535+ else if (cn == 0xFF )
536+ {
537+ i_cn = 0 ;
538+ max_cn = countof (s->f .vol );
539+ }
540+
380541 switch (aid) {
381542 case ATTRIB_ID (AUDIO_MUTE_CONTROL, AUDIO_REQUEST_SET_CUR, 0x0300 ):
382543 s->f .mute = data[0 ] & 1 ;
383544 set_vol = true ;
384545 ret = 0 ;
385546 break ;
386547 case ATTRIB_ID (AUDIO_VOLUME_CONTROL, AUDIO_REQUEST_SET_CUR, 0x0300 ):
387- if (cn < 2 ) {
388- uint16_t vol = data[0 ] + (data[1 ] << 8 );
548+ for (uint8_t i = i_cn; i < max_cn; i++)
549+ {
550+ int offset = cn == 0xFF ? i * sizeof (uint16_t ) : 0 ;
551+
552+ // TODO actually check how many controls the device has
553+ if (offset >= length - 1 )
554+ offset = 0 ; // should bail instead
389555
390- // qemu usb audiocard formula, singstar has a bit different range
556+ uint16_t vol = data[offset + 0 ] + (data[offset + 1 ] << 8 );
557+
558+ // qemu usb audiocard formula, singstar has a bit different range
391559 vol -= 0x8000 ;
392560 vol = (vol * 255 + 0x4400 ) / 0x8800 ;
393- if (vol > 255 ) {
561+ if (vol > 255 )
562+ {
394563 vol = 255 ;
395564 }
396565
397- if (s->f .vol [cn] != vol) {
398- s->f .vol [cn] = (uint8_t )vol;
399- set_vol = true ;
400- }
566+ s->f .vol [i] = (uint8_t )vol;
401567 ret = 0 ;
402568 }
403569 break ;
570+ case ATTRIB_ID (AUDIO_AUTOMATIC_GAIN_CONTROL, AUDIO_REQUEST_SET_CUR, 0x0300 ):
571+ OSDebugOut (TEXT (" singstar: mic auto gain: %d\n " ), data[0 ]);
572+ ret = 0 ;
573+ break ;
404574 }
405575
406576 if (set_vol) {
@@ -565,6 +735,11 @@ static void singstar_mic_handle_data(USBDevice *dev, USBPacket *p)
565735
566736 // TODO
567737 int outChns = s->f .intf == 1 ? 1 : 2 ;
738+
739+ // TODO Add audio ep specific struct?
740+ // const USBDescOther& desc = p->ep->dev->ifaces[p->ep->ifnum]->descs[1];
741+ // OSDebugOut(TEXT("Intf. channels: %u\n"), desc.data[4]);
742+
568743 uint32_t frames, out_frames[2 ] = {0 }, chn;
569744 int16_t *src1, *src2;
570745 int16_t *dst = nullptr ;
@@ -753,7 +928,7 @@ USBDevice* SingstarDevice::CreateDevice(int port)
753928 LoadSetting (nullptr , port, SingstarDevice::TypeName (), N_DEVICE_API, api);
754929 return SingstarDevice::CreateDevice (port, api);
755930}
756- USBDevice* SingstarDevice::CreateDevice (int port, const std::string& api)
931+ USBDevice* SingstarDevice::CreateDevice (int port, const std::string& api, bool only_mono )
757932{
758933 SINGSTARMICState *s;
759934 AudioDeviceInfo info;
@@ -771,12 +946,14 @@ USBDevice* SingstarDevice::CreateDevice(int port, const std::string& api)
771946 s->audsrcproxy ->AudioInit ();
772947
773948 s->audsrc [0 ] = s->audsrcproxy ->CreateObject (port, TypeName (), 0 , AUDIODIR_SOURCE);
774- s->audsrc [1 ] = s->audsrcproxy ->CreateObject (port, TypeName (), 1 , AUDIODIR_SOURCE);
949+ s->audsrc [1 ] = only_mono ? nullptr : s->audsrcproxy ->CreateObject (port, TypeName (), 1 , AUDIODIR_SOURCE);
775950
776- if ( !s->audsrc [0 ] && !s->audsrc [1 ])
951+ if ((only_mono && !s->audsrc [0 ]) || (!s-> audsrc [ 0 ] && !s->audsrc [1 ]) )
777952 goto fail;
778953
779- if (s->audsrc [0 ] && s->audsrc [1 ] && s->audsrc [0 ]->Compare (s->audsrc [1 ]))
954+ if (only_mono)
955+ s->f .mode = MIC_MODE_SINGLE;
956+ else if (s->audsrc [0 ] && s->audsrc [1 ] && s->audsrc [0 ]->Compare (s->audsrc [1 ]))
780957 {
781958 s->f .mode = MIC_MODE_SHARED;
782959 // And don't capture the same source twice
@@ -861,4 +1038,37 @@ int SingstarDevice::Freeze(int mode, USBDevice *dev, void *data)
8611038 return 0 ;
8621039}
8631040
1041+ USBDevice* AK5370MicDevice::CreateDevice (int port)
1042+ {
1043+ SINGSTARMICState* s;
1044+ AudioDeviceInfo info;
1045+
1046+ std::string api;
1047+ LoadSetting (nullptr , port, TypeName (), N_DEVICE_API, api);
1048+
1049+ USBDevice* dev = SingstarDevice::CreateDevice (port, api, true );
1050+ if (!dev)
1051+ return nullptr ;
1052+
1053+ s = (SINGSTARMICState*)dev;
1054+ s->desc = {};
1055+ s->desc_dev = {};
1056+
1057+ s->desc .full = &s->desc_dev ;
1058+ s->desc .str = ak5370_desc_strings;
1059+ if (usb_desc_parse_dev (ak5370_mic_dev_desc, sizeof (ak5370_mic_dev_desc), s->desc , s->desc_dev ) < 0 )
1060+ goto fail;
1061+ if (usb_desc_parse_config (ak5370_mic_config_desc, sizeof (ak5370_mic_config_desc), s->desc_dev ) < 0 )
1062+ goto fail;
1063+
1064+ s->dev .klass .usb_desc = &s->desc ;
1065+ s->dev .klass .product_desc = ak5370_desc_strings[2 ];
1066+ usb_desc_init (&s->dev );
1067+ return (USBDevice*)s;
1068+
1069+ fail:
1070+ singstar_mic_handle_destroy ((USBDevice*)s);
1071+ return NULL ;
1072+ }
1073+
8641074}
0 commit comments