USB: Audio support for EyeToy

This commit is contained in:
Florin9doi 2024-08-16 23:09:00 +03:00 committed by lightningterror
parent d6507a945b
commit c2ea8c4eab
4 changed files with 74 additions and 40 deletions

View File

@ -6,6 +6,8 @@
#include "usb-eyetoy-webcam.h" #include "usb-eyetoy-webcam.h"
#include "ov519.h" #include "ov519.h"
#include "USB/qemu-usb/desc.h" #include "USB/qemu-usb/desc.h"
#include "USB/usb-mic/audio.h"
#include "USB/usb-mic/usb-mic.h"
#include "USB/USB.h" #include "USB/USB.h"
#include "StateWrapper.h" #include "StateWrapper.h"
@ -23,7 +25,7 @@ namespace usb_eyetoy
u32 subtype; u32 subtype;
std::unique_ptr<VideoDevice> videodev; std::unique_ptr<VideoDevice> videodev;
// struct freeze { USBDevice* mic;
uint8_t regs[0xFF]; //OV519 uint8_t regs[0xFF]; //OV519
uint8_t i2c_regs[0xFF]; //OV764x uint8_t i2c_regs[0xFF]; //OV764x
@ -32,7 +34,6 @@ namespace usb_eyetoy
std::unique_ptr<unsigned char[]> mpeg_frame_data; std::unique_ptr<unsigned char[]> mpeg_frame_data;
unsigned int mpeg_frame_size; unsigned int mpeg_frame_size;
unsigned int mpeg_frame_offset; unsigned int mpeg_frame_offset;
// } f;
} EYETOYState; } EYETOYState;
static const USBDescStrings desc_strings = { static const USBDescStrings desc_strings = {
@ -103,8 +104,11 @@ namespace usb_eyetoy
static void eyetoy_handle_reset(USBDevice* dev) static void eyetoy_handle_reset(USBDevice* dev)
{ {
reset_controller(USB_CONTAINER_OF(dev, EYETOYState, dev)); EYETOYState* s = USB_CONTAINER_OF(dev, EYETOYState, dev);
reset_sensor(USB_CONTAINER_OF(dev, EYETOYState, dev)); reset_controller(s);
reset_sensor(s);
if (s->mic)
s->mic->klass.handle_reset(s->mic);
} }
static void webcam_handle_control_eyetoy(USBDevice* dev, USBPacket* p, int request, int value, int index, int length, uint8_t* data) static void webcam_handle_control_eyetoy(USBDevice* dev, USBPacket* p, int request, int value, int index, int length, uint8_t* data)
@ -328,10 +332,8 @@ namespace usb_eyetoy
} }
else if (devep == 2) else if (devep == 2)
{ {
// get audio if (s->mic)
//Console.Warning("get audio %d\n", len); s->mic->klass.handle_data(s->mic, p);
memset(data, 0, std::min(p->buffer_size, max_ep_size));
usb_packet_copy(p, data, std::min(p->buffer_size, max_ep_size));
} }
break; break;
case USB_TOKEN_OUT: case USB_TOKEN_OUT:
@ -408,11 +410,18 @@ namespace usb_eyetoy
{ {
EYETOYState* s = USB_CONTAINER_OF(dev, EYETOYState, dev); EYETOYState* s = USB_CONTAINER_OF(dev, EYETOYState, dev);
close_camera(s); close_camera(s);
if (s->mic)
s->mic->klass.unrealize(s->mic);
delete s; delete s;
} }
USBDevice* EyeToyWebCamDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const USBDevice* EyeToyWebCamDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
{ {
const usb_mic::MicrophoneDevice* mic_proxy =
static_cast<usb_mic::MicrophoneDevice*>(RegisterDevice::instance().Device(DEVTYPE_MICROPHONE));
if (!mic_proxy)
return nullptr;
std::unique_ptr<VideoDevice> videodev(VideoDevice::CreateInstance()); std::unique_ptr<VideoDevice> videodev(VideoDevice::CreateInstance());
if (!videodev) if (!videodev)
{ {
@ -435,6 +444,8 @@ namespace usb_eyetoy
goto fail; goto fail;
s->dev.klass.handle_control = webcam_handle_control_eyetoy; s->dev.klass.handle_control = webcam_handle_control_eyetoy;
s->dev.klass.handle_data = webcam_handle_data_eyetoy; s->dev.klass.handle_data = webcam_handle_data_eyetoy;
s->mic = mic_proxy->CreateDevice(si, port, 0, false, 16000, TypeName());
} }
else if (subtype == TYPE_OV511P) else if (subtype == TYPE_OV511P)
{ {
@ -503,17 +514,42 @@ namespace usb_eyetoy
std::span<const char*> EyeToyWebCamDevice::SubTypes() const std::span<const char*> EyeToyWebCamDevice::SubTypes() const
{ {
static const char* subtypes[] = { static const char* subtypes[] = {
TRANSLATE_NOOP("USB", "Sony EyeToy"), TRANSLATE_NOOP("USB", "Konami Capture Eye")}; TRANSLATE_NOOP("USB", "Sony EyeToy"),
TRANSLATE_NOOP("USB", "Konami Capture Eye")
};
return subtypes; return subtypes;
} }
std::span<const SettingInfo> EyeToyWebCamDevice::Settings(u32 subtype) const std::span<const SettingInfo> EyeToyWebCamDevice::Settings(u32 subtype) const
{ {
static constexpr const SettingInfo info[] = { switch (subtype)
{SettingInfo::Type::StringList, "device_name", TRANSLATE_NOOP("USB", "Device Name"), {
TRANSLATE_NOOP("USB", "Selects the device to capture images from."), "", nullptr, nullptr, nullptr, case TYPE_EYETOY:
nullptr, nullptr, &VideoDevice::GetDeviceList}, {
}; static constexpr const SettingInfo info[] = {
return info; {SettingInfo::Type::StringList, "device_name", TRANSLATE_NOOP("USB", "Video Device"),
TRANSLATE_NOOP("USB", "Selects the device to capture images from."), "", nullptr, nullptr, nullptr,
nullptr, nullptr, &VideoDevice::GetDeviceList},
{SettingInfo::Type::StringList, "input_device_name", TRANSLATE_NOOP("USB", "Audio Device"),
TRANSLATE_NOOP("USB", "Selects the device to read audio from."), "", nullptr, nullptr, nullptr, nullptr,
nullptr, &AudioDevice::GetInputDeviceList},
{SettingInfo::Type::Integer, "input_latency", TRANSLATE_NOOP("USB", "Audio Latency"),
TRANSLATE_NOOP("USB", "Specifies the latency to the host input device."),
AudioDevice::DEFAULT_LATENCY_STR, "1", "1000", "1", TRANSLATE_NOOP("USB", "%dms"), nullptr, nullptr, 1.0f},
};
return info;
}
case TYPE_OV511P:
{
static constexpr const SettingInfo info[] = {
{SettingInfo::Type::StringList, "device_name", TRANSLATE_NOOP("USB", "Video Device"),
TRANSLATE_NOOP("USB", "Selects the device to capture images from."), "", nullptr, nullptr, nullptr,
nullptr, nullptr, &VideoDevice::GetDeviceList},
};
return info;
}
default:
return {};
}
} }
} // namespace usb_eyetoy } // namespace usb_eyetoy

View File

@ -55,13 +55,13 @@ namespace usb_mic
{ {
/* /*
* A USB audio device supports an arbitrary number of alternate * A USB audio device supports an arbitrary number of alternate
* interface settings for each interface. Each corresponds to a block * interface settings for each interface. Each corresponds to a block
* diagram of parameterized blocks. This can thus refer to things like * diagram of parameterized blocks. This can thus refer to things like
* number of channels, data rates, or in fact completely different * number of channels, data rates, or in fact completely different
* block diagrams. Alternative setting 0 is always the null block diagram, * block diagrams. Alternative setting 0 is always the null block diagram,
* which is used by a disabled device. * which is used by a disabled device.
*/ */
enum usb_audio_altset : int8_t enum usb_audio_altset : int8_t
{ {
ALTSET_OFF = 0x00, /* No endpoint */ ALTSET_OFF = 0x00, /* No endpoint */
@ -200,7 +200,7 @@ namespace usb_mic
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */ 0x00, /* iInterface */
/* Interface 1, Alternate Setting 1, Audio Streaming - Operational */ /* Interface 1, Alternate Setting 1, Audio Streaming - 1 channel */
USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */ 0x01, /* bInterfaceNumber */
@ -252,7 +252,7 @@ namespace usb_mic
0x00, /* bLockDelayUnits */ 0x00, /* bLockDelayUnits */
WBVAL(0x0000), /* wLockDelay */ WBVAL(0x0000), /* wLockDelay */
/* Interface 1, Alternate Setting 2, Audio Streaming - ? */ /* Interface 1, Alternate Setting 2, Audio Streaming - 2 channels */
USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */ 0x01, /* bInterfaceNumber */
@ -402,7 +402,7 @@ namespace usb_mic
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */ 0x00, /* iInterface */
/* Interface 1, Alternate Setting 1, Audio Streaming - Operational */ /* Interface 1, Alternate Setting 1, Audio Streaming - 1 channel */
USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */ 0x01, /* bInterfaceNumber */
@ -454,7 +454,7 @@ namespace usb_mic
0x00, /* bLockDelayUnits */ 0x00, /* bLockDelayUnits */
WBVAL(0x0000), /* wLockDelay */ WBVAL(0x0000), /* wLockDelay */
/* Interface 1, Alternate Setting 2, Audio Streaming - ? */ /* Interface 1, Alternate Setting 2, Audio Streaming - 2 channels */
USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */ 0x01, /* bInterfaceNumber */
@ -627,7 +627,7 @@ namespace usb_mic
Console.Warning("singstar: ep control cs %x, cn %X, %X %X data:", cs, cn, attrib, ep); Console.Warning("singstar: ep control cs %x, cn %X, %X %X data:", cs, cn, attrib, ep);
/*for(int i=0; i<length; i++) /*for(int i=0; i<length; i++)
Console.Warning("%02X ", data[i]); Console.Warning("%02X ", data[i]);
Console.Warning("\n");*/ Console.Warning("\n");*/
switch (aid) switch (aid)
{ {
@ -692,8 +692,8 @@ namespace usb_mic
switch (request) switch (request)
{ {
/* /*
* Audio device specific request * Audio device specific request
*/ */
case ClassInterfaceRequest | AUDIO_REQUEST_GET_CUR: case ClassInterfaceRequest | AUDIO_REQUEST_GET_CUR:
case ClassInterfaceRequest | AUDIO_REQUEST_GET_MIN: case ClassInterfaceRequest | AUDIO_REQUEST_GET_MIN:
case ClassInterfaceRequest | AUDIO_REQUEST_GET_MAX: case ClassInterfaceRequest | AUDIO_REQUEST_GET_MAX:
@ -749,24 +749,21 @@ namespace usb_mic
{ {
SINGSTARMICState* s = USB_CONTAINER_OF(dev, SINGSTARMICState, dev); SINGSTARMICState* s = USB_CONTAINER_OF(dev, SINGSTARMICState, dev);
int ret = 0; int ret = 0;
uint8_t devep = p->ep->nr;
switch (p->pid) switch (p->pid)
{ {
case USB_TOKEN_IN: case USB_TOKEN_IN:
//Console.Warning("token in ep: %d len: %zd\n", devep, p->iov.size); //Console.Warning("token in ep: %d len: %zd\n", devep, p->iov.size);
if (devep == 1)
{ {
//TODO //TODO
int outChns = s->f.intf == 1 ? 1 : 2; int outChns = s->f.intf == 2 ? 2 : 1;
uint32_t frames, out_frames[2] = {0}, chn; uint32_t frames, out_frames[2] = {0}, chn;
int16_t *src1, *src2; int16_t *src1, *src2;
int16_t* dst = (int16_t*)p->buffer_ptr; int16_t* dst = (int16_t*)p->buffer_ptr;
size_t len = p->buffer_size; size_t len = p->buffer_size;
// send only 1ms (bInterval) of samples // send only 1ms (bInterval) of samples
if (s->f.srate[0] == 48000 || s->f.srate[0] == 8000) if (s->f.srate[0] == 48000 || s->f.srate[0] == 8000 || s->f.srate[0] == 16000)
len = std::min<u32>(p->buffer_size, outChns * sizeof(int16_t) * s->f.srate[0] / 1000); len = std::min<u32>(p->buffer_size, outChns * sizeof(int16_t) * s->f.srate[0] / 1000);
//Divide 'len' bytes between 2 channels of 16 bits //Divide 'len' bytes between 2 channels of 16 bits
@ -912,10 +909,10 @@ namespace usb_mic
return nullptr; return nullptr;
static const bool dual_mic = subtype == MIC_SINGSTAR; static const bool dual_mic = subtype == MIC_SINGSTAR;
return CreateDevice(si, port, subtype, dual_mic, MicrophoneDevice::TypeName()); return CreateDevice(si, port, subtype, dual_mic, 48000, MicrophoneDevice::TypeName());
} }
USBDevice* MicrophoneDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype, bool dual_mic, const char* devtype) const USBDevice* MicrophoneDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype, bool dual_mic, const int samplerate, const char* devtype) const
{ {
if (subtype >= MIC_COUNT) if (subtype >= MIC_COUNT)
return nullptr; return nullptr;
@ -985,6 +982,7 @@ namespace usb_mic
Host::OSD_ERROR_DURATION); Host::OSD_ERROR_DURATION);
goto fail; goto fail;
} }
s->audsrc[i]->SetResampling(samplerate);
} }
} }
@ -1020,8 +1018,8 @@ namespace usb_mic
// set defaults // set defaults
s->f.vol[0] = 240; /* 0 dB */ s->f.vol[0] = 240; /* 0 dB */
s->f.vol[1] = 240; /* 0 dB */ s->f.vol[1] = 240; /* 0 dB */
s->f.srate[0] = 48000; s->f.srate[0] = samplerate;
s->f.srate[1] = 48000; s->f.srate[1] = samplerate;
usb_desc_init(&s->dev); usb_desc_init(&s->dev);
usb_ep_init(&s->dev); usb_ep_init(&s->dev);

View File

@ -17,7 +17,7 @@ namespace usb_mic
class MicrophoneDevice : public DeviceProxy class MicrophoneDevice : public DeviceProxy
{ {
public: public:
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype, bool dual_mic, const char* devtype) const; USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype, bool dual_mic, const int samplerate, const char* devtype) const;
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override; USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
const char* Name() const override; const char* Name() const override;
const char* TypeName() const override; const char* TypeName() const override;

View File

@ -393,7 +393,7 @@ namespace usb_pad
if (!mic_proxy) if (!mic_proxy)
return nullptr; return nullptr;
USBDevice* mic = mic_proxy->CreateDevice(si, port, 0, false, TypeName()); USBDevice* mic = mic_proxy->CreateDevice(si, port, 0, false, 48000, TypeName());
if (!mic) if (!mic)
return nullptr; return nullptr;