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 "ov519.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 "StateWrapper.h"
@ -23,7 +25,7 @@ namespace usb_eyetoy
u32 subtype;
std::unique_ptr<VideoDevice> videodev;
// struct freeze {
USBDevice* mic;
uint8_t regs[0xFF]; //OV519
uint8_t i2c_regs[0xFF]; //OV764x
@ -32,7 +34,6 @@ namespace usb_eyetoy
std::unique_ptr<unsigned char[]> mpeg_frame_data;
unsigned int mpeg_frame_size;
unsigned int mpeg_frame_offset;
// } f;
} EYETOYState;
static const USBDescStrings desc_strings = {
@ -103,8 +104,11 @@ namespace usb_eyetoy
static void eyetoy_handle_reset(USBDevice* dev)
{
reset_controller(USB_CONTAINER_OF(dev, EYETOYState, dev));
reset_sensor(USB_CONTAINER_OF(dev, EYETOYState, dev));
EYETOYState* s = 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)
@ -328,10 +332,8 @@ namespace usb_eyetoy
}
else if (devep == 2)
{
// get audio
//Console.Warning("get audio %d\n", len);
memset(data, 0, std::min(p->buffer_size, max_ep_size));
usb_packet_copy(p, data, std::min(p->buffer_size, max_ep_size));
if (s->mic)
s->mic->klass.handle_data(s->mic, p);
}
break;
case USB_TOKEN_OUT:
@ -408,11 +410,18 @@ namespace usb_eyetoy
{
EYETOYState* s = USB_CONTAINER_OF(dev, EYETOYState, dev);
close_camera(s);
if (s->mic)
s->mic->klass.unrealize(s->mic);
delete s;
}
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());
if (!videodev)
{
@ -435,6 +444,8 @@ namespace usb_eyetoy
goto fail;
s->dev.klass.handle_control = webcam_handle_control_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)
{
@ -503,17 +514,42 @@ namespace usb_eyetoy
std::span<const char*> EyeToyWebCamDevice::SubTypes() const
{
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;
}
std::span<const SettingInfo> EyeToyWebCamDevice::Settings(u32 subtype) const
{
static constexpr const SettingInfo info[] = {
{SettingInfo::Type::StringList, "device_name", TRANSLATE_NOOP("USB", "Device Name"),
TRANSLATE_NOOP("USB", "Selects the device to capture images from."), "", nullptr, nullptr, nullptr,
nullptr, nullptr, &VideoDevice::GetDeviceList},
};
return info;
switch (subtype)
{
case TYPE_EYETOY:
{
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},
{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

View File

@ -55,13 +55,13 @@ namespace usb_mic
{
/*
* A USB audio device supports an arbitrary number of alternate
* interface settings for each interface. Each corresponds to a block
* diagram of parameterized blocks. This can thus refer to things like
* number of channels, data rates, or in fact completely different
* block diagrams. Alternative setting 0 is always the null block diagram,
* which is used by a disabled device.
*/
* A USB audio device supports an arbitrary number of alternate
* interface settings for each interface. Each corresponds to a block
* diagram of parameterized blocks. This can thus refer to things like
* number of channels, data rates, or in fact completely different
* block diagrams. Alternative setting 0 is always the null block diagram,
* which is used by a disabled device.
*/
enum usb_audio_altset : int8_t
{
ALTSET_OFF = 0x00, /* No endpoint */
@ -200,7 +200,7 @@ namespace usb_mic
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
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_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
@ -252,7 +252,7 @@ namespace usb_mic
0x00, /* bLockDelayUnits */
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_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
@ -402,7 +402,7 @@ namespace usb_mic
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
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_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
@ -454,7 +454,7 @@ namespace usb_mic
0x00, /* bLockDelayUnits */
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_DESCRIPTOR_TYPE, /* bDescriptorType */
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);
/*for(int i=0; i<length; i++)
Console.Warning("%02X ", data[i]);
Console.Warning("\n");*/
Console.Warning("\n");*/
switch (aid)
{
@ -692,8 +692,8 @@ namespace usb_mic
switch (request)
{
/*
* Audio device specific request
*/
* Audio device specific request
*/
case ClassInterfaceRequest | AUDIO_REQUEST_GET_CUR:
case ClassInterfaceRequest | AUDIO_REQUEST_GET_MIN:
case ClassInterfaceRequest | AUDIO_REQUEST_GET_MAX:
@ -749,24 +749,21 @@ namespace usb_mic
{
SINGSTARMICState* s = USB_CONTAINER_OF(dev, SINGSTARMICState, dev);
int ret = 0;
uint8_t devep = p->ep->nr;
switch (p->pid)
{
case USB_TOKEN_IN:
//Console.Warning("token in ep: %d len: %zd\n", devep, p->iov.size);
if (devep == 1)
{
//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;
int16_t *src1, *src2;
int16_t* dst = (int16_t*)p->buffer_ptr;
size_t len = p->buffer_size;
// 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);
//Divide 'len' bytes between 2 channels of 16 bits
@ -912,10 +909,10 @@ namespace usb_mic
return nullptr;
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)
return nullptr;
@ -985,6 +982,7 @@ namespace usb_mic
Host::OSD_ERROR_DURATION);
goto fail;
}
s->audsrc[i]->SetResampling(samplerate);
}
}
@ -1020,8 +1018,8 @@ namespace usb_mic
// set defaults
s->f.vol[0] = 240; /* 0 dB */
s->f.vol[1] = 240; /* 0 dB */
s->f.srate[0] = 48000;
s->f.srate[1] = 48000;
s->f.srate[0] = samplerate;
s->f.srate[1] = samplerate;
usb_desc_init(&s->dev);
usb_ep_init(&s->dev);

View File

@ -17,7 +17,7 @@ namespace usb_mic
class MicrophoneDevice : public DeviceProxy
{
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;
const char* Name() const override;
const char* TypeName() const override;

View File

@ -393,7 +393,7 @@ namespace usb_pad
if (!mic_proxy)
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)
return nullptr;