Skip to content

Commit bb5a333

Browse files
committed
usb-mic: add Karaoke Revolution mic (RU042)
1 parent 271f5b2 commit bb5a333

File tree

4 files changed

+271
-43
lines changed

4 files changed

+271
-43
lines changed

src/device_init.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ void RegisterDevice::Register()
2424
inst.Add(DEVTYPE_BEATMANIA_DADADA, new DeviceProxy<usb_hid::BeatManiaDevice>());
2525
inst.Add(DEVTYPE_SEGA_SEAMIC, new DeviceProxy<usb_pad::SeamicDevice>());
2626
inst.Add(DEVTYPE_KEYBOARDMANIA, new DeviceProxy<usb_pad::KeyboardmaniaDevice>());
27+
inst.Add(DEVTYPE_AKM_AK5370, new DeviceProxy<usb_mic::AK5370MicDevice>());
2728

2829
RegisterAPIs();
2930
}

src/deviceproxy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum DeviceType
3232
DEVTYPE_BEATMANIA_DADADA,
3333
DEVTYPE_SEGA_SEAMIC,
3434
DEVTYPE_KEYBOARDMANIA,
35+
DEVTYPE_AKM_AK5370,
3536
};
3637

3738
struct SelectDeviceName {

src/usb-mic/usb-mic-singstar.cpp

Lines changed: 252 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -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

301439
static 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

Comments
 (0)