mirror of https://github.com/PCSX2/pcsx2.git
USB: backport fixes from develop branch
This commit is contained in:
parent
53b818ac3b
commit
f1d1acd487
|
@ -346,6 +346,7 @@ set(pcsx2USBSources
|
|||
USB/usb-pad/usb-pad.cpp
|
||||
USB/usb-pad/usb-pad-ff.cpp
|
||||
USB/usb-pad/lg/lg_ff.cpp
|
||||
USB/usb-pad/usb-seamic.cpp
|
||||
USB/usb-mic/usb-mic-singstar.cpp
|
||||
USB/usb-mic/usb-mic-logitech.cpp
|
||||
USB/usb-mic/usb-headset.cpp
|
||||
|
|
|
@ -300,13 +300,13 @@ void USBclose()
|
|||
|
||||
u8 USBread8(u32 addr)
|
||||
{
|
||||
USB_LOG("* Invalid 8bit read at address %lx\n", addr);
|
||||
USB_LOG("* Invalid 8bit read at address %08x\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 USBread16(u32 addr)
|
||||
{
|
||||
USB_LOG("* Invalid 16bit read at address %lx\n", addr);
|
||||
USB_LOG("* Invalid 16bit read at address %08x\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -316,24 +316,24 @@ u32 USBread32(u32 addr)
|
|||
|
||||
hard = ohci_mem_read(qemu_ohci, addr);
|
||||
|
||||
USB_LOG("* Known 32bit read at address %lx: %lx\n", addr, hard);
|
||||
USB_LOG("* Known 32bit read at address %08x: %08x\n", addr, hard);
|
||||
|
||||
return hard;
|
||||
}
|
||||
|
||||
void USBwrite8(u32 addr, u8 value)
|
||||
{
|
||||
USB_LOG("* Invalid 8bit write at address %lx value %x\n", addr, value);
|
||||
USB_LOG("* Invalid 8bit write at address %08x value %x\n", addr, value);
|
||||
}
|
||||
|
||||
void USBwrite16(u32 addr, u16 value)
|
||||
{
|
||||
USB_LOG("* Invalid 16bit write at address %lx value %x\n", addr, value);
|
||||
USB_LOG("* Invalid 16bit write at address %08x value %x\n", addr, value);
|
||||
}
|
||||
|
||||
void USBwrite32(u32 addr, u32 value)
|
||||
{
|
||||
USB_LOG("* Known 32bit write at address %lx value %lx\n", addr, value);
|
||||
USB_LOG("* Known 32bit write at address %08x value %08x\n", addr, value);
|
||||
ohci_mem_write(qemu_ohci, addr, value);
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,7 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
{
|
||||
if ((long unsigned int)data->size < sizeof(USBfreezeData))
|
||||
{
|
||||
Console.WriteLn(Color_Red, "USB: Unable to load freeze data! Got %d bytes, expected >= %d.\n", data->size, sizeof(USBfreezeData));
|
||||
Console.WriteLn(Color_Red, "USB: Unable to load freeze data! Got %d bytes, expected >= %zu.\n", data->size, sizeof(USBfreezeData));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -367,6 +367,11 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
return -1;
|
||||
}
|
||||
|
||||
s8* ptr = data->data + sizeof(USBfreezeData);
|
||||
// Load the state of the attached devices
|
||||
if (data->size != sizeof(USBfreezeData) + usbd.device[0].size + usbd.device[1].size + 8192)
|
||||
return -1;
|
||||
|
||||
//TODO Subsequent save state loadings make USB "stall" for n seconds since previous load
|
||||
//clocks = usbd.cycles;
|
||||
//remaining = usbd.remaining;
|
||||
|
@ -377,12 +382,11 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
usbd.t.rhport[i].port.ops = qemu_ohci->rhport[i].port.ops;
|
||||
usbd.t.rhport[i].port.dev = qemu_ohci->rhport[i].port.dev;
|
||||
}
|
||||
//if (qemu_ohci->usb_packet.iov.iov)
|
||||
usb_packet_cleanup(&qemu_ohci->usb_packet);
|
||||
*qemu_ohci = usbd.t;
|
||||
|
||||
s8* ptr = data->data + sizeof(USBfreezeData);
|
||||
// Load the state of the attached devices
|
||||
if ((long unsigned int)data->size != sizeof(USBfreezeData) + usbd.device[0].size + usbd.device[1].size + 8192)
|
||||
return -1;
|
||||
// restore USBPacket for OHCIState
|
||||
usb_packet_init(&qemu_ohci->usb_packet);
|
||||
|
||||
RegisterDevice& regInst = RegisterDevice::instance();
|
||||
for (int i = 0; i < 2; i++)
|
||||
|
@ -431,6 +435,21 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
usb_device[i]->setup_len = tmp.setup_len;
|
||||
usb_device[i]->setup_index = tmp.setup_index;
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "Loading save state:\nport: " << i
|
||||
<< "\naddr: " << (int)usb_device[i]->addr
|
||||
<< "\nattached: " << usb_device[i]->attached
|
||||
<< "\nauto_attach: " << usb_device[i]->auto_attach
|
||||
<< "\nconfig: " << usb_device[i]->configuration
|
||||
<< "\nninterf: " << usb_device[i]->ninterfaces
|
||||
<< "\nflags: " << usb_device[i]->flags
|
||||
<< "\nstate: " << usb_device[i]->state
|
||||
<< "\nremote_wakeup: " << usb_device[i]->remote_wakeup
|
||||
<< "\nsetup_state: " << usb_device[i]->setup_state
|
||||
<< "\nsetup_len: " << usb_device[i]->setup_len
|
||||
<< "\nsetup_index: " << usb_device[i]->setup_index
|
||||
<< std::endl;
|
||||
#endif
|
||||
memcpy(usb_device[i]->data_buf, tmp.data_buf, sizeof(tmp.data_buf));
|
||||
memcpy(usb_device[i]->setup_buf, tmp.setup_buf, sizeof(tmp.setup_buf));
|
||||
|
||||
|
@ -442,9 +461,14 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
}
|
||||
|
||||
proxy->Freeze(FREEZE_LOAD, usb_device[i], ptr);
|
||||
//TODO reset port if save state's and configured wheel types are different
|
||||
usb_detach(&qemu_ohci->rhport[i].port);
|
||||
usb_attach(&qemu_ohci->rhport[i].port);
|
||||
if (!usb_device[i]->attached)
|
||||
{ // FIXME FREEZE_SAVE fcked up
|
||||
usb_device[i]->attached = true;
|
||||
usb_device_reset(usb_device[i]);
|
||||
//TODO reset port if save state's and configured wheel types are different
|
||||
usb_detach(&qemu_ohci->rhport[i].port);
|
||||
usb_attach(&qemu_ohci->rhport[i].port);
|
||||
}
|
||||
}
|
||||
else if (!proxy && index != DEVTYPE_NONE)
|
||||
{
|
||||
|
@ -455,10 +479,6 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
}
|
||||
|
||||
int dev_index = usbd.usb_packet.dev_index;
|
||||
// restore USBPacket for OHCIState
|
||||
//if (qemu_ohci->usb_packet.iov.iov)
|
||||
usb_packet_cleanup(&qemu_ohci->usb_packet);
|
||||
usb_packet_init(&qemu_ohci->usb_packet);
|
||||
|
||||
if (usb_device[dev_index])
|
||||
{
|
||||
|
@ -511,7 +531,7 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
auto proxy = regInst.Device(index);
|
||||
usbd.device[i].index = index;
|
||||
|
||||
if (proxy)
|
||||
if (proxy && usb_device[i])
|
||||
usbd.device[i].size = proxy->Freeze(FREEZE_SIZE, usb_device[i], nullptr);
|
||||
else
|
||||
usbd.device[i].size = 0;
|
||||
|
@ -522,9 +542,10 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
|
||||
strncpy(usbd.freezeID, USBfreezeID, strlen(USBfreezeID));
|
||||
usbd.t = *qemu_ohci;
|
||||
usbd.usb_packet.ep = qemu_ohci->usb_packet.ep ? *qemu_ohci->usb_packet.ep : USBEndpoint{0};
|
||||
usbd.t.usb_packet.iov = {};
|
||||
usbd.t.usb_packet.ep = nullptr;
|
||||
if (qemu_ohci->usb_packet.ep)
|
||||
usbd.usb_packet.ep = *qemu_ohci->usb_packet.ep;
|
||||
|
||||
for (uint32_t i = 0; i < qemu_ohci->num_ports; i++)
|
||||
{
|
||||
|
@ -542,14 +563,13 @@ s32 USBfreeze(int mode, freezeData* data)
|
|||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
auto proxy = regInst.Device(conf.Port[i]);
|
||||
if (proxy && usbd.device[i].size)
|
||||
if (usb_device[i])
|
||||
{
|
||||
proxy->Freeze(FREEZE_SAVE, usb_device[i], ptr);
|
||||
if (usb_device[i])
|
||||
usbd.device[i].dev = *usb_device[i];
|
||||
|
||||
memset(&usbd.device[i].dev.klass, 0, sizeof(USBDeviceClass));
|
||||
usbd.device[i].dev = *usb_device[i];
|
||||
if (proxy && usbd.device[i].size)
|
||||
proxy->Freeze(FREEZE_SAVE, usb_device[i], ptr);
|
||||
}
|
||||
memset(&usbd.device[i].dev.klass, 0, sizeof(USBDeviceClass));
|
||||
|
||||
ptr += usbd.device[i].size;
|
||||
}
|
||||
|
|
|
@ -161,3 +161,17 @@ void ClearSection(const TCHAR* section)
|
|||
s->RemoveAllKeys();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveSection(const char* dev_type, int port, const std::string& key)
|
||||
{
|
||||
TSTDSTRING tkey;
|
||||
tkey.assign(key.begin(), key.end());
|
||||
|
||||
TSTDSTRINGSTREAM section;
|
||||
if (dev_type)
|
||||
section << dev_type << _T(" ");
|
||||
section << tkey << _T(" ") << port;
|
||||
TSTDSTRING str = section.str();
|
||||
|
||||
ciniFile.RemoveSection(str_to_wstr(section.str()));
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ extern Config conf;
|
|||
void SaveConfig();
|
||||
void LoadConfig();
|
||||
void ClearSection(const TCHAR* section);
|
||||
void RemoveSection(const char* dev_type, int port, const std::string& key);
|
||||
|
||||
extern TSTDSTRING IniPath;
|
||||
extern TSTDSTRING LogDir;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
void RegisterDevice::Register()
|
||||
{
|
||||
auto& inst = RegisterDevice::instance();
|
||||
if (inst.Map().size()) // FIXME Don't clear proxies, singstar keeps a copy to uninit audio
|
||||
return;
|
||||
inst.Add(DEVTYPE_PAD, new DeviceProxy<usb_pad::PadDevice>());
|
||||
inst.Add(DEVTYPE_MSD, new DeviceProxy<usb_msd::MsdDevice>());
|
||||
inst.Add(DEVTYPE_SINGSTAR, new DeviceProxy<usb_mic::SingstarDevice>());
|
||||
|
@ -34,6 +36,8 @@ void RegisterDevice::Register()
|
|||
inst.Add(DEVTYPE_RBKIT, new DeviceProxy<usb_pad::RBDrumKitDevice>());
|
||||
inst.Add(DEVTYPE_BUZZ, new DeviceProxy<usb_pad::BuzzDevice>());
|
||||
inst.Add(DEVTYPE_EYETOY, new DeviceProxy<usb_eyetoy::EyeToyWebCamDevice>());
|
||||
inst.Add(DEVTYPE_BEATMANIA_DADADA, new DeviceProxy<usb_hid::BeatManiaDevice>());
|
||||
inst.Add(DEVTYPE_SEGA_SEAMIC, new DeviceProxy<usb_pad::SeamicDevice>());
|
||||
|
||||
RegisterAPIs();
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ enum DeviceType
|
|||
DEVTYPE_RBKIT,
|
||||
DEVTYPE_BUZZ,
|
||||
DEVTYPE_EYETOY,
|
||||
DEVTYPE_BEATMANIA_DADADA,
|
||||
DEVTYPE_SEGA_SEAMIC,
|
||||
};
|
||||
|
||||
struct SelectDeviceName
|
||||
|
|
|
@ -173,7 +173,7 @@ static void configureApi(GtkWidget* widget, gpointer data)
|
|||
|
||||
GtkWidget* new_combobox(const char* label, GtkWidget* vbox)
|
||||
{
|
||||
GtkWidget *ro_label, *rs_hbox, *rs_label, *rs_cb;
|
||||
GtkWidget *rs_hbox, *rs_label, *rs_cb;
|
||||
|
||||
rs_hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), rs_hbox, FALSE, TRUE, 0);
|
||||
|
@ -218,7 +218,7 @@ void USBconfigure()
|
|||
const char* players[] = {"Player 1:", "Player 2:"};
|
||||
|
||||
GtkWidget *rs_cb, *vbox;
|
||||
uint32_t idx = 0, sel_idx = 0;
|
||||
uint32_t sel_idx = 0;
|
||||
|
||||
// Create the dialog window
|
||||
GtkWidget* dlg = gtk_dialog_new_with_buttons(
|
||||
|
@ -246,10 +246,15 @@ void USBconfigure()
|
|||
gtk_combo_box_set_active(GTK_COMBO_BOX(rs_cb), 0);
|
||||
|
||||
auto devices = RegisterDevice::instance().Names();
|
||||
int idx = 0, selected = 0;
|
||||
int idx = 0;
|
||||
for (auto& device : devices)
|
||||
{
|
||||
auto deviceProxy = RegisterDevice::instance().Device(device);
|
||||
if (!deviceProxy)
|
||||
{
|
||||
OSDebugOut(_T("Device '%" SFMTs "' is registered, but failed to get proxy!\n"), device.c_str());
|
||||
continue;
|
||||
}
|
||||
auto name = deviceProxy->Name();
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rs_cb), name);
|
||||
idx++;
|
||||
|
|
|
@ -27,15 +27,19 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
#define CALLBACK __stdcall
|
||||
#else
|
||||
#elif defined(__i386__)
|
||||
#define CALLBACK __attribute__((stdcall))
|
||||
#else
|
||||
#define CALLBACK
|
||||
#endif
|
||||
|
||||
#ifndef EXPORT_C_
|
||||
#ifdef _MSC_VER
|
||||
#define EXPORT_C_(type) extern "C" type CALLBACK
|
||||
#elif defined(__i386__)
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((stdcall, visibility("default"))) type
|
||||
#else
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((stdcall, externally_visible, visibility("default"))) type
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((visibility("default"))) type
|
||||
//#define EXPORT_C_(type) extern "C" __attribute__((stdcall,visibility("default"))) type
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#define HID_MOUSE 1
|
||||
#define HID_TABLET 2
|
||||
#define HID_KEYBOARD 3
|
||||
// idk
|
||||
#define HID_SUBKIND_BEATMANIA 1
|
||||
|
||||
/* scancode without modifiers */
|
||||
#define SCANCODE_KEYMASK 0xff
|
||||
|
@ -323,6 +325,7 @@ struct HIDState
|
|||
uint32_t head; /* index into circular queue */
|
||||
uint32_t n;
|
||||
int kind;
|
||||
int sub_kind;
|
||||
int32_t protocol;
|
||||
uint8_t idle;
|
||||
bool idle_pending;
|
||||
|
|
|
@ -461,7 +461,7 @@ struct USBPort
|
|||
USBPortOps* ops;
|
||||
void* opaque;
|
||||
int index; /* internal port index, may be used with the opaque */
|
||||
//QTAILQ_ENTRY(USBPort) next; /* Used internally by qemu. */
|
||||
//QTAILQ_ENTRY(USBPort) next; /* Used internally by qemu. */
|
||||
};
|
||||
|
||||
typedef void USBCallback(USBPacket* packet, void* opaque);
|
||||
|
|
|
@ -560,6 +560,11 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
|||
the next ISO TD of the same ED */
|
||||
//trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number,
|
||||
// frame_count);
|
||||
if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC))
|
||||
{
|
||||
/* avoid infinite loop */
|
||||
return 1;
|
||||
}
|
||||
OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
|
||||
ed->head &= ~OHCI_DPTR_MASK;
|
||||
ed->head |= (iso_td.next & OHCI_DPTR_MASK);
|
||||
|
@ -603,7 +608,14 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
|||
}
|
||||
|
||||
start_offset = iso_td.offset[relative_frame_number];
|
||||
next_offset = iso_td.offset[relative_frame_number + 1];
|
||||
if (relative_frame_number < frame_count)
|
||||
{
|
||||
next_offset = iso_td.offset[relative_frame_number + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
next_offset = iso_td.be;
|
||||
}
|
||||
|
||||
if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) ||
|
||||
((relative_frame_number < frame_count) &&
|
||||
|
@ -647,7 +659,13 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
|||
else
|
||||
{
|
||||
/* Last packet in the ISO TD */
|
||||
end_addr = iso_td.be;
|
||||
end_addr = next_offset;
|
||||
}
|
||||
|
||||
if (start_addr > end_addr)
|
||||
{
|
||||
//trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK))
|
||||
|
@ -658,6 +676,10 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
|||
{
|
||||
len = end_addr - start_addr + 1;
|
||||
}
|
||||
if (len > sizeof(ohci->usb_buf))
|
||||
{
|
||||
len = sizeof(ohci->usb_buf);
|
||||
}
|
||||
|
||||
if (len && dir != OHCI_TD_DIR_IN)
|
||||
{
|
||||
|
@ -674,6 +696,11 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
|||
bool int_req = relative_frame_number == frame_count &&
|
||||
OHCI_BM(iso_td.flags, TD_DI) == 0;
|
||||
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
|
||||
if (dev == NULL)
|
||||
{
|
||||
//trace_usb_ohci_td_dev_error();
|
||||
return 1;
|
||||
}
|
||||
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
|
||||
usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
|
||||
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
|
||||
|
@ -851,8 +878,18 @@ static int ohci_service_td(OHCIState* ohci, struct ohci_ed* ed)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (td.cbp > td.be)
|
||||
{
|
||||
//trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be);
|
||||
ohci_die(ohci);
|
||||
return 1;
|
||||
}
|
||||
len = (td.be - td.cbp) + 1;
|
||||
}
|
||||
if (len > sizeof(ohci->usb_buf))
|
||||
{
|
||||
len = sizeof(ohci->usb_buf);
|
||||
}
|
||||
|
||||
pktlen = len;
|
||||
if (len && dir != OHCI_TD_DIR_IN)
|
||||
|
@ -897,6 +934,11 @@ static int ohci_service_td(OHCIState* ohci, struct ohci_ed* ed)
|
|||
return 1;
|
||||
}
|
||||
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
|
||||
if (dev == NULL)
|
||||
{
|
||||
//trace_usb_ohci_td_dev_error();
|
||||
return 1;
|
||||
}
|
||||
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
|
||||
usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
|
||||
OHCI_BM(td.flags, TD_DI) == 0);
|
||||
|
@ -1042,7 +1084,7 @@ static int ohci_service_ed_list(OHCIState* ohci, uint32_t head, int completion)
|
|||
if (head == 0)
|
||||
return 0;
|
||||
|
||||
for (cur = head; cur; cur = next_ed)
|
||||
for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed)
|
||||
{
|
||||
if (!ohci_read_ed(ohci, cur, &ed))
|
||||
{
|
||||
|
@ -1053,12 +1095,6 @@ static int ohci_service_ed_list(OHCIState* ohci, uint32_t head, int completion)
|
|||
|
||||
next_ed = ed.next & OHCI_DPTR_MASK;
|
||||
|
||||
if (++link_cnt > ED_LINK_LIMIT)
|
||||
{
|
||||
ohci_die(ohci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K))
|
||||
{
|
||||
uint32_t addr;
|
||||
|
@ -1445,7 +1481,47 @@ static void ohci_port_set_status(OHCIState* ohci, int portnum, uint32_t val)
|
|||
ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OHCI
|
||||
static const char* reg_names[] = {
|
||||
"HcRevision",
|
||||
"HcControl",
|
||||
"HcCommandStatus",
|
||||
"HcInterruptStatus",
|
||||
"HcInterruptEnable",
|
||||
"HcInterruptDisable",
|
||||
"HcHCCA",
|
||||
"HcPeriodCurrentED",
|
||||
"HcControlHeadED",
|
||||
"HcControlCurrentED",
|
||||
"HcBulkHeadED",
|
||||
"HcBulkCurrentED",
|
||||
"HcDoneHead",
|
||||
"HcFmInterval",
|
||||
"HcFmRemaining",
|
||||
"HcFmNumber",
|
||||
"HcPeriodicStart",
|
||||
"HcLSThreshold",
|
||||
"HcRhDescriptorA",
|
||||
"HcRhDescriptorB",
|
||||
"HcRhStatus",
|
||||
};
|
||||
|
||||
uint32_t ohci_mem_read_impl(OHCIState* ptr, uint32_t addr);
|
||||
uint32_t ohci_mem_read(OHCIState* ptr, uint32_t addr)
|
||||
{
|
||||
auto val = ohci_mem_read_impl(ptr, addr);
|
||||
int idx = (addr - ptr->mem_base) >> 2;
|
||||
if (idx < countof(reg_names))
|
||||
{
|
||||
fprintf(stderr, "ohci_mem_read %s(%d): %08x\n", reg_names[idx], idx, val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t ohci_mem_read_impl(OHCIState* ptr, uint32_t addr)
|
||||
#else
|
||||
uint32_t ohci_mem_read(OHCIState* ptr, uint32_t addr)
|
||||
#endif
|
||||
{
|
||||
OHCIState* ohci = ptr;
|
||||
|
||||
|
@ -1463,9 +1539,6 @@ uint32_t ohci_mem_read(OHCIState* ptr, uint32_t addr)
|
|||
/* HcRhPortStatus */
|
||||
return ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
|
||||
}
|
||||
#ifdef DEBUG_OHCI
|
||||
OSDebugOut(TEXT("ohci_mem_read: addr %d\n"), addr >> 2);
|
||||
#endif
|
||||
switch (addr >> 2)
|
||||
{
|
||||
case 0: /* HcRevision */
|
||||
|
@ -1535,7 +1608,22 @@ uint32_t ohci_mem_read(OHCIState* ptr, uint32_t addr)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OHCI
|
||||
void ohci_mem_write_impl(OHCIState* ptr, uint32_t addr, uint32_t val);
|
||||
void ohci_mem_write(OHCIState* ptr, uint32_t addr, uint32_t val)
|
||||
{
|
||||
int idx = (addr - ptr->mem_base) >> 2;
|
||||
if (idx < countof(reg_names))
|
||||
{
|
||||
fprintf(stderr, "ohci_mem_write %s(%d): %08x\n", reg_names[idx], idx, val);
|
||||
}
|
||||
ohci_mem_write_impl(ptr, addr, val);
|
||||
}
|
||||
|
||||
void ohci_mem_write_impl(OHCIState* ptr, uint32_t addr, uint32_t val)
|
||||
#else
|
||||
void ohci_mem_write(OHCIState* ptr, uint32_t addr, uint32_t val)
|
||||
#endif
|
||||
{
|
||||
OHCIState* ohci = ptr;
|
||||
|
||||
|
@ -1555,9 +1643,6 @@ void ohci_mem_write(OHCIState* ptr, uint32_t addr, uint32_t val)
|
|||
ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG_OHCI
|
||||
OSDebugOut(TEXT("ohci_mem_write: addr %d = 0x%08x\n"), addr >> 2, val);
|
||||
#endif
|
||||
switch (addr >> 2)
|
||||
{
|
||||
case 1: /* HcControl */
|
||||
|
@ -1658,7 +1743,7 @@ static USBPortOps ohci_port_ops = {
|
|||
/*.detach =*/ohci_detach,
|
||||
//.child_detach = ohci_child_detach,
|
||||
/*.wakeup =*/ohci_wakeup,
|
||||
//.complete = ohci_async_complete_packet,
|
||||
/*.complete =*/ohci_async_complete_packet,
|
||||
};
|
||||
|
||||
static USBBusOps ohci_bus_ops = {};
|
||||
|
|
|
@ -44,14 +44,12 @@ namespace usb_eyetoy
|
|||
namespace linux_api
|
||||
{
|
||||
|
||||
static pthread_t _eyetoy_thread;
|
||||
static pthread_t* eyetoy_thread = &_eyetoy_thread;
|
||||
static pthread_t eyetoy_thread = 0;
|
||||
static unsigned char eyetoy_running = 0;
|
||||
|
||||
static int fd = -1;
|
||||
buffer_t* buffers;
|
||||
static unsigned int n_buffers;
|
||||
static int out_buf;
|
||||
static unsigned int pixelformat;
|
||||
|
||||
buffer_t mpeg_buffer;
|
||||
|
@ -384,6 +382,8 @@ namespace usb_eyetoy
|
|||
break;
|
||||
}
|
||||
}
|
||||
eyetoy_running = 0;
|
||||
fprintf(stderr, "V4L2 thread quit\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -448,15 +448,15 @@ namespace usb_eyetoy
|
|||
if (eyetoy_running)
|
||||
{
|
||||
eyetoy_running = 0;
|
||||
pthread_join(*eyetoy_thread, NULL);
|
||||
pthread_join(eyetoy_thread, NULL);
|
||||
v4l_close();
|
||||
}
|
||||
eyetoy_running = 1;
|
||||
std::string selectedDevice;
|
||||
LoadSetting(EyeToyWebCamDevice::TypeName(), mPort, APINAME, N_DEVICE, selectedDevice);
|
||||
if (v4l_open(selectedDevice) != 0)
|
||||
return -1;
|
||||
pthread_create(eyetoy_thread, NULL, &v4l_thread, NULL);
|
||||
pthread_create(&eyetoy_thread, NULL, &v4l_thread, NULL);
|
||||
eyetoy_running = 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
@ -465,7 +465,9 @@ namespace usb_eyetoy
|
|||
if (eyetoy_running)
|
||||
{
|
||||
eyetoy_running = 0;
|
||||
pthread_join(*eyetoy_thread, NULL);
|
||||
if (eyetoy_thread)
|
||||
pthread_join(eyetoy_thread, NULL);
|
||||
eyetoy_thread = 0;
|
||||
v4l_close();
|
||||
}
|
||||
return 0;
|
||||
|
@ -489,8 +491,6 @@ namespace usb_eyetoy
|
|||
|
||||
int GtkConfigure(int port, const char* dev_type, void* data)
|
||||
{
|
||||
GtkWidget *ro_frame, *ro_label, *rs_hbox, *rs_label;
|
||||
|
||||
std::string selectedDevice;
|
||||
LoadSetting(dev_type, port, APINAME, N_DEVICE, selectedDevice);
|
||||
|
||||
|
@ -532,7 +532,7 @@ namespace usb_eyetoy
|
|||
int ret = RESULT_OK;
|
||||
if (result == GTK_RESPONSE_OK)
|
||||
{
|
||||
if (sel_new != sel_idx)
|
||||
if (devList.size() && sel_new != sel_idx)
|
||||
{
|
||||
if (!SaveSetting(dev_type, port, APINAME, N_DEVICE, devList.at(sel_new)))
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,14 +28,14 @@ extern GUID CLSID_NullRenderer;
|
|||
}
|
||||
|
||||
#pragma region qedit.h
|
||||
struct __declspec(uuid("0579154a-2b53-4994-b0d0-e773148eff85"))
|
||||
struct //__declspec(uuid("0579154a-2b53-4994-b0d0-e773148eff85"))
|
||||
ISampleGrabberCB : IUnknown
|
||||
{
|
||||
virtual HRESULT __stdcall SampleCB(double SampleTime, struct IMediaSample* pSample) = 0;
|
||||
virtual HRESULT __stdcall BufferCB(double SampleTime, unsigned char* pBuffer, long BufferLen) = 0;
|
||||
};
|
||||
|
||||
struct __declspec(uuid("6b652fff-11fe-4fce-92ad-0266b5d7c78f"))
|
||||
struct //__declspec(uuid("6b652fff-11fe-4fce-92ad-0266b5d7c78f"))
|
||||
ISampleGrabber : IUnknown
|
||||
{
|
||||
virtual HRESULT __stdcall SetOneShot(long OneShot) = 0;
|
||||
|
@ -47,8 +47,8 @@ struct __declspec(uuid("6b652fff-11fe-4fce-92ad-0266b5d7c78f"))
|
|||
virtual HRESULT __stdcall SetCallback(struct ISampleGrabberCB* pCallback, long WhichMethodToCallback) = 0;
|
||||
};
|
||||
|
||||
struct __declspec(uuid("c1f400a0-3f08-11d3-9f0b-006008039e37"))
|
||||
SampleGrabber;
|
||||
//struct __declspec(uuid("c1f400a0-3f08-11d3-9f0b-006008039e37"))
|
||||
// SampleGrabber;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
@ -72,12 +72,6 @@ namespace usb_eyetoy
|
|||
|
||||
typedef void (*DShowVideoCaptureCallback)(unsigned char* data, int len, int bitsperpixel);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* start = NULL;
|
||||
size_t length = 0;
|
||||
} buffer_t;
|
||||
|
||||
static const char* APINAME = "DirectShow";
|
||||
|
||||
class DirectShow : public VideoDevice
|
||||
|
@ -100,10 +94,12 @@ namespace usb_eyetoy
|
|||
void Port(int port) { mPort = port; }
|
||||
|
||||
protected:
|
||||
void SetCallback(DShowVideoCaptureCallback cb) { callbackhandler->SetCallback(cb); }
|
||||
void Start();
|
||||
void Stop();
|
||||
int InitializeDevice(std::wstring selectedDevice);
|
||||
void store_mpeg_frame(const std::vector<unsigned char>& data);
|
||||
void create_dummy_frame();
|
||||
void dshow_callback(unsigned char* data, int len, int bitsperpixel);
|
||||
|
||||
private:
|
||||
int mPort;
|
||||
|
@ -118,10 +114,16 @@ namespace usb_eyetoy
|
|||
ISampleGrabber* samplegrabber;
|
||||
IBaseFilter* nullrenderer;
|
||||
|
||||
std::vector<unsigned char> mpeg_buffer{};
|
||||
std::mutex mpeg_mutex;
|
||||
|
||||
class CallbackHandler : public ISampleGrabberCB
|
||||
{
|
||||
public:
|
||||
CallbackHandler() { callback = 0; }
|
||||
CallbackHandler(DirectShow* parent_)
|
||||
: parent(parent_)
|
||||
{
|
||||
}
|
||||
~CallbackHandler() {}
|
||||
|
||||
void SetCallback(DShowVideoCaptureCallback cb) { callback = cb; }
|
||||
|
@ -133,7 +135,7 @@ namespace usb_eyetoy
|
|||
virtual ULONG __stdcall Release() { return 2; }
|
||||
|
||||
private:
|
||||
DShowVideoCaptureCallback callback;
|
||||
DirectShow* parent;
|
||||
|
||||
} * callbackhandler;
|
||||
};
|
||||
|
|
|
@ -454,7 +454,7 @@ namespace usb_eyetoy
|
|||
|
||||
s->frame_step++;
|
||||
}
|
||||
else if (s->frame_step < 10)
|
||||
else if (s->mpeg_frame_offset < s->mpeg_frame_size)
|
||||
{
|
||||
int data_pk = s->mpeg_frame_size - s->mpeg_frame_offset;
|
||||
if (data_pk > max_ep_size)
|
||||
|
@ -464,7 +464,7 @@ namespace usb_eyetoy
|
|||
|
||||
s->frame_step++;
|
||||
}
|
||||
else if (s->frame_step == 10)
|
||||
else
|
||||
{
|
||||
uint8_t footer[] = {
|
||||
0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
@ -518,7 +518,7 @@ namespace usb_eyetoy
|
|||
VideoDeviceProxyBase* proxy = RegisterVideoDevice::instance().Proxy(varApi);
|
||||
if (!proxy)
|
||||
{
|
||||
SysMessage(TEXT("Invalid video device API: " SFMTs "\n"), varApi.c_str());
|
||||
SysMessage(TEXT("Invalid video device API: %" SFMTs "\n"), varApi.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -597,7 +597,7 @@ namespace usb_eyetoy
|
|||
default:
|
||||
break;
|
||||
}*/
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace usb_eyetoy
|
||||
|
|
|
@ -109,8 +109,7 @@ namespace usb_hid
|
|||
|
||||
int GtkHidConfigure(int port, const char* dev_type, HIDType hid_type, GtkWindow* parent)
|
||||
{
|
||||
GtkWidget *ro_frame, *ro_label, *rs_hbox, *rs_label, *rs_cb;
|
||||
GtkWidget *main_hbox, *right_vbox, *left_vbox;
|
||||
GtkWidget *main_hbox, *right_vbox, *rs_cb;
|
||||
|
||||
assert((int)HIDTYPE_MOUSE == 1); //make sure there is atleast two types so we won't go beyond array length
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ namespace usb_hid
|
|||
bool FindHid(const std::string& evphys, std::string& hid_dev)
|
||||
{
|
||||
int fd;
|
||||
int res;
|
||||
char buf[256];
|
||||
|
||||
std::stringstream str;
|
||||
|
@ -100,18 +99,8 @@ namespace usb_hid
|
|||
{
|
||||
// Make sure there is atleast two types so we won't go beyond array length
|
||||
assert((int)HIDTYPE_MOUSE == 1);
|
||||
int t;
|
||||
std::stringstream name;
|
||||
char buf[1024];
|
||||
|
||||
unsigned long keybit[NBITS(KEY_MAX)] = {0};
|
||||
unsigned long absbit[NBITS(ABS_MAX)] = {0};
|
||||
|
||||
memset(mAxisMap, -1, sizeof(mAxisMap));
|
||||
memset(mBtnMap, -1, sizeof(mBtnMap));
|
||||
|
||||
mAxisCount = 0;
|
||||
mButtonCount = 0;
|
||||
mHandle = -1;
|
||||
|
||||
std::string path;
|
||||
|
@ -124,39 +113,12 @@ namespace usb_hid
|
|||
if (path.empty() || !file_exists(path))
|
||||
goto quit;
|
||||
|
||||
/*if (GetEvdevName(joypath, buf)) {
|
||||
name << buf;
|
||||
name << " (evdev)";
|
||||
}*/
|
||||
|
||||
if ((mHandle = open(path.c_str(), O_RDWR | O_NONBLOCK)) < 0)
|
||||
{
|
||||
OSDebugOut("Cannot open device: %s\n", path.c_str());
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* if ((ioctl(mHandle, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0) &&
|
||||
(ioctl(mHandle, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0)) {
|
||||
// Probably isn't a evdev joystick
|
||||
SysMessage(APINAME ": Getting atleast some of the bits failed: %s\n", strerror(errno));
|
||||
goto quit;
|
||||
}*/
|
||||
|
||||
/*unsigned int version;
|
||||
if (ioctl(mHandle, EVIOCGVERSION, &version) < 0)
|
||||
{
|
||||
SysMessage(APINAME ": Get version failed: %s\n", strerror(errno));
|
||||
return false;
|
||||
}*/
|
||||
|
||||
/* for (int i = 0; i < KEY_MAX; ++i) {
|
||||
if (test_bit(i, keybit)) {
|
||||
OSDebugOut("Joystick has button: 0x%x\n", i);
|
||||
mBtnMap[i] = mButtonCount;
|
||||
++mButtonCount;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!mReaderThreadIsRunning)
|
||||
{
|
||||
if (mReaderThread.joinable())
|
||||
|
@ -186,9 +148,6 @@ namespace usb_hid
|
|||
|
||||
EvDev* dev = static_cast<EvDev*>(ptr);
|
||||
HIDState* hs = dev->mHIDState;
|
||||
int32_t lastX = 0, lastY = 0;
|
||||
bool shift = false;
|
||||
bool grabbed = false;
|
||||
|
||||
dev->mReaderThreadIsRunning = true;
|
||||
|
||||
|
|
|
@ -57,10 +57,6 @@ namespace usb_hid
|
|||
static void ReaderThread(void* ptr);
|
||||
|
||||
int mHandle;
|
||||
uint16_t mAxisMap[ABS_MAX + 1];
|
||||
uint16_t mBtnMap[KEY_MAX + 1];
|
||||
int mAxisCount;
|
||||
int mButtonCount;
|
||||
|
||||
std::thread mReaderThread;
|
||||
std::atomic<bool> mReaderThreadIsRunning;
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace usb_hid
|
|||
UsbHIDProxyBase(const std::string& name);
|
||||
virtual UsbHID* CreateObject(int port, const char* dev_type) const = 0;
|
||||
// ProxyBase::Configure is ignored
|
||||
virtual int Configure(int port, const char* dev_type, void* data) { return RESULT_CANCELED; }
|
||||
virtual int Configure(int port, const char* dev_type, HIDType hid_type, void* data) = 0;
|
||||
};
|
||||
|
||||
|
@ -76,10 +77,6 @@ namespace usb_hid
|
|||
{
|
||||
return T::Name();
|
||||
}
|
||||
virtual int Configure(int port, const char* dev_type, void* data)
|
||||
{
|
||||
return RESULT_CANCELED;
|
||||
}
|
||||
virtual int Configure(int port, const char* dev_type, HIDType hid_type, void* data)
|
||||
{
|
||||
return T::Configure(port, dev_type, hid_type, data);
|
||||
|
|
|
@ -64,6 +64,18 @@ namespace usb_hid
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::list<std::string> BeatManiaDevice::ListAPIs()
|
||||
{
|
||||
return RegisterUsbHID::instance().Names();
|
||||
}
|
||||
|
||||
const TCHAR* BeatManiaDevice::LongAPIName(const std::string& name)
|
||||
{
|
||||
auto proxy = RegisterUsbHID::instance().Proxy(name);
|
||||
if (proxy)
|
||||
return proxy->Name();
|
||||
return nullptr;
|
||||
}
|
||||
std::list<std::string> HIDMouseDevice::ListAPIs()
|
||||
{
|
||||
return RegisterUsbHID::instance().Names();
|
||||
|
@ -100,6 +112,14 @@ namespace usb_hid
|
|||
"HID Keyboard",
|
||||
};
|
||||
|
||||
|
||||
static const USBDescStrings beatmania_dadada_desc_strings = {
|
||||
"",
|
||||
"KONAMI CPJ1",
|
||||
"USB JIS Mini Keyboard",
|
||||
};
|
||||
|
||||
|
||||
/* mostly the same values as the Bochs USB Keyboard device */
|
||||
static const uint8_t kbd_dev_desc[] = {
|
||||
0x12, /* u8 bLength; */
|
||||
|
@ -414,6 +434,105 @@ namespace usb_hid
|
|||
0xc0, /* End Collection */
|
||||
};
|
||||
|
||||
static const uint8_t beatmania_dev_desc[] = {
|
||||
0x12, /* u8 bLength; */
|
||||
0x01, /* u8 bDescriptorType; Device */
|
||||
WBVAL(0x110), /* u16 bcdUSB; v1.10 */
|
||||
|
||||
0x00, /* u8 bDeviceClass; */
|
||||
0x00, /* u8 bDeviceSubClass; */
|
||||
0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
|
||||
0x08, /* u8 bMaxPacketSize0; 8 Bytes */
|
||||
|
||||
// 0x27, 0x06, /* u16 idVendor; */
|
||||
WBVAL(0x0510),
|
||||
// 0x01, 0x00, /* u16 idProduct; */
|
||||
WBVAL(0x0002),
|
||||
WBVAL(0x0020), /* u16 bcdDevice */
|
||||
|
||||
1, /* u8 iManufacturer; */
|
||||
2, /* u8 iProduct; */
|
||||
0, /* u8 iSerialNumber; */
|
||||
0x01 /* u8 bNumConfigurations; */
|
||||
};
|
||||
|
||||
static const uint8_t beatmania_config_desc[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x22, 0x00, // wTotalLength 34
|
||||
0x01, // bNumInterfaces 1
|
||||
0x01, // bConfigurationValue
|
||||
0x02, // iConfiguration (String Index)
|
||||
0xA0, // bmAttributes Remote Wakeup
|
||||
0x14, // bMaxPower 40mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x01, // bNumEndpoints 1
|
||||
0x03, // bInterfaceClass
|
||||
0x01, // bInterfaceSubClass
|
||||
0x01, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x09, // bLength
|
||||
0x21, // bDescriptorType (HID)
|
||||
0x10, 0x01, // bcdHID 1.10
|
||||
0x0F, // bCountryCode
|
||||
0x01, // bNumDescriptors
|
||||
0x22, // bDescriptorType[0] (HID)
|
||||
0x44, 0x00, // wDescriptorLength[0] 68
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x08, 0x00, // wMaxPacketSize 8
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
|
||||
// 34 bytes
|
||||
};
|
||||
|
||||
static const uint8_t beatmania_dadada_hid_report_descriptor[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x06, // Usage (Keyboard)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x05, 0x07, // Usage Page (Kbrd/Keypad)
|
||||
0x19, 0xE0, // Usage Minimum (0xE0)
|
||||
0x29, 0xE7, // Usage Maximum (0xE7)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x07, // Usage Page (Kbrd/Keypad)
|
||||
0x19, 0x00, // Usage Minimum (0x00)
|
||||
0x29, 0xFF, // Usage Maximum (0xFF)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x08, // Usage Page (LEDs)
|
||||
0x19, 0x01, // Usage Minimum (Num Lock)
|
||||
0x29, 0x05, // Usage Maximum (Kana)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x05, // Report Count (5)
|
||||
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0x75, 0x03, // Report Size (3)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
|
||||
// 68 bytes
|
||||
};
|
||||
|
||||
static void usb_hid_changed(HIDState* hs)
|
||||
{
|
||||
UsbHIDState* us = CONTAINER_OF(hs, UsbHIDState, f.hid);
|
||||
|
@ -463,9 +582,16 @@ namespace usb_hid
|
|||
}
|
||||
else if (hs->kind == HID_KEYBOARD)
|
||||
{
|
||||
memcpy(data, qemu_keyboard_hid_report_descriptor,
|
||||
sizeof(qemu_keyboard_hid_report_descriptor));
|
||||
p->actual_length = sizeof(qemu_keyboard_hid_report_descriptor);
|
||||
if (hs->sub_kind == HID_SUBKIND_BEATMANIA)
|
||||
{
|
||||
p->actual_length = sizeof(beatmania_dadada_hid_report_descriptor);
|
||||
memcpy(data, beatmania_dadada_hid_report_descriptor, p->actual_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->actual_length = sizeof(qemu_keyboard_hid_report_descriptor);
|
||||
memcpy(data, qemu_keyboard_hid_report_descriptor, p->actual_length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -665,6 +791,8 @@ namespace usb_hid
|
|||
auto s = reinterpret_cast<UsbHIDState*>(dev);
|
||||
auto freezed = reinterpret_cast<UsbHIDState::freeze*>(data);
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
switch (mode)
|
||||
{
|
||||
case FREEZE_LOAD:
|
||||
|
@ -682,7 +810,7 @@ namespace usb_hid
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
USBDevice* HIDMouseDevice::CreateDevice(int port)
|
||||
|
@ -754,4 +882,77 @@ namespace usb_hid
|
|||
return HIDKbdDevice::Freeze(mode, dev, data);
|
||||
}
|
||||
|
||||
// ---- BeatMania Da Da Da!! ----
|
||||
|
||||
USBDevice* BeatManiaDevice::CreateDevice(int port)
|
||||
{
|
||||
OSDebugOut(_T("%s\n"), __func__);
|
||||
UsbHIDState* s;
|
||||
|
||||
std::string varApi;
|
||||
LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, varApi);
|
||||
UsbHIDProxyBase* proxy = RegisterUsbHID::instance().Proxy(varApi);
|
||||
if (!proxy)
|
||||
{
|
||||
SysMessage(TEXT("Invalid HID API: %" SFMTs "\n"), varApi.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UsbHID* usbhid = proxy->CreateObject(port, TypeName());
|
||||
|
||||
if (!usbhid)
|
||||
return nullptr;
|
||||
|
||||
s = new UsbHIDState();
|
||||
|
||||
s->desc.full = &s->desc_dev;
|
||||
s->desc.str = beatmania_dadada_desc_strings;
|
||||
|
||||
if (usb_desc_parse_dev(beatmania_dev_desc, sizeof(beatmania_dev_desc), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(beatmania_config_desc, sizeof(beatmania_config_desc), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
|
||||
s->usbhid = usbhid;
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.klass.handle_attach = usb_desc_attach;
|
||||
s->dev.klass.handle_reset = usb_hid_handle_reset;
|
||||
s->dev.klass.handle_control = usb_hid_handle_control;
|
||||
s->dev.klass.handle_data = usb_hid_handle_data;
|
||||
s->dev.klass.unrealize = usb_hid_unrealize;
|
||||
s->dev.klass.open = usb_hid_open;
|
||||
s->dev.klass.close = usb_hid_close;
|
||||
s->dev.klass.usb_desc = &s->desc;
|
||||
s->dev.klass.product_desc = s->desc.str[2];
|
||||
s->port = port;
|
||||
|
||||
usb_desc_init(&s->dev);
|
||||
usb_ep_init(&s->dev);
|
||||
s->intr = usb_ep_get(&s->dev, USB_TOKEN_IN, 1);
|
||||
hid_init(&s->f.hid, HID_KEYBOARD, usb_hid_changed);
|
||||
s->f.hid.sub_kind = HID_SUBKIND_BEATMANIA;
|
||||
s->usbhid->SetHIDState(&s->f.hid);
|
||||
s->usbhid->SetHIDType(HIDTYPE_KBD);
|
||||
|
||||
usb_hid_handle_reset((USBDevice*)s);
|
||||
|
||||
return (USBDevice*)s;
|
||||
fail:
|
||||
usb_hid_unrealize((USBDevice*)s);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int BeatManiaDevice::Configure(int port, const std::string& api, void* data)
|
||||
{
|
||||
auto proxy = RegisterUsbHID::instance().Proxy(api);
|
||||
if (proxy)
|
||||
return proxy->Configure(port, TypeName(), HIDTYPE_KBD, data);
|
||||
return RESULT_CANCELED;
|
||||
}
|
||||
|
||||
int BeatManiaDevice::Freeze(int mode, USBDevice* dev, void* data)
|
||||
{
|
||||
return HIDKbdDevice::Freeze(mode, dev, data);
|
||||
}
|
||||
|
||||
} // namespace usb_hid
|
||||
|
|
|
@ -93,4 +93,23 @@ namespace usb_hid
|
|||
static int Freeze(int mode, USBDevice* dev, void* data);
|
||||
};
|
||||
|
||||
class BeatManiaDevice
|
||||
{
|
||||
public:
|
||||
virtual ~BeatManiaDevice() {}
|
||||
static USBDevice* CreateDevice(int port);
|
||||
static const TCHAR* Name()
|
||||
{
|
||||
return TEXT("BeatMania Da Da Da!! Keyboard");
|
||||
}
|
||||
static const char* TypeName()
|
||||
{
|
||||
return "beatmania";
|
||||
}
|
||||
static std::list<std::string> ListAPIs();
|
||||
static const TCHAR* LongAPIName(const std::string& name);
|
||||
static int Configure(int port, const std::string& api, void* data);
|
||||
static int Freeze(int mode, USBDevice* dev, void* data);
|
||||
};
|
||||
|
||||
} // namespace usb_hid
|
||||
|
|
|
@ -177,7 +177,7 @@ namespace usb_mic
|
|||
|
||||
static int GtkConfigure(int port, const char* dev_type, void* data)
|
||||
{
|
||||
GtkWidget *ro_frame, *ro_label, *rs_hbox, *rs_label, *rs_cb, *vbox;
|
||||
GtkWidget* ro_frame;
|
||||
|
||||
int dev_idxs[] = {0, 0, 0, 0};
|
||||
|
||||
|
@ -763,7 +763,7 @@ namespace usb_mic
|
|||
if (ret != PA_OK)
|
||||
return;
|
||||
|
||||
auto dur = std::chrono::duration_cast<ms>(hrc::now() - padev->mLastGetBuffer).count();
|
||||
//auto dur = std::chrono::duration_cast<ms>(hrc::now() - padev->mLastGetBuffer).count();
|
||||
if (padev->mPaused /*|| dur > 5000*/ || (!padata && nbytes /* hole */))
|
||||
{
|
||||
ret = pa_stream_drop(p);
|
||||
|
@ -836,7 +836,7 @@ namespace usb_mic
|
|||
void PulseAudioDevice::stream_write_cb(pa_stream* p, size_t nbytes, void* userdata)
|
||||
{
|
||||
void* pa_buffer = NULL;
|
||||
size_t pa_bytes, old_size;
|
||||
size_t pa_bytes;
|
||||
// The length of the data to write in bytes, must be in multiples of the stream's sample spec frame size
|
||||
ssize_t remaining_bytes = nbytes;
|
||||
int ret = PA_OK;
|
||||
|
|
|
@ -926,12 +926,12 @@ namespace usb_mic
|
|||
switch (uMsg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
|
||||
SetWindowLongPtr(hW, GWLP_USERDATA, lParam);
|
||||
break;
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
s = (WASAPISettings*)lParam;
|
||||
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
|
||||
SetWindowLongPtr(hW, GWLP_USERDATA, lParam);
|
||||
int buffering = 50;
|
||||
LoadSetting(s->dev_type, s->port, APINAME, N_BUFFER_LEN_SRC, buffering);
|
||||
|
||||
|
|
|
@ -1062,11 +1062,11 @@ namespace usb_mic
|
|||
int HeadsetDevice::Freeze(int mode, USBDevice* dev, void* data)
|
||||
{
|
||||
HeadsetState* s = (HeadsetState*)dev;
|
||||
if (!s)
|
||||
return 0;
|
||||
switch (mode)
|
||||
{
|
||||
case FREEZE_LOAD:
|
||||
if (!s)
|
||||
return -1;
|
||||
s->f = *(HeadsetState::freeze*)data;
|
||||
if (s->audsrc)
|
||||
s->audsrc->SetResampling(s->f.in.srate);
|
||||
|
@ -1074,8 +1074,6 @@ namespace usb_mic
|
|||
s->audsink->SetResampling(s->f.out.srate);
|
||||
return sizeof(HeadsetState::freeze);
|
||||
case FREEZE_SAVE:
|
||||
if (!s)
|
||||
return -1;
|
||||
*(HeadsetState::freeze*)data = s->f;
|
||||
return sizeof(HeadsetState::freeze);
|
||||
case FREEZE_SIZE:
|
||||
|
@ -1083,7 +1081,7 @@ namespace usb_mic
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace usb_mic
|
||||
|
|
|
@ -624,7 +624,7 @@ namespace usb_mic
|
|||
return;
|
||||
}
|
||||
|
||||
OSDebugOut(TEXT("data len: %d bytes, src[0]: %d frames, src[1]: %d frames\n"), len, out_frames[0], out_frames[1]);
|
||||
OSDebugOut(TEXT("data len: %zu bytes, src[0]: %d frames, src[1]: %d frames\n"), len, out_frames[0], out_frames[1]);
|
||||
|
||||
//TODO well, it is 16bit interleaved, right?
|
||||
//Merge with MIC_MODE_SHARED case?
|
||||
|
@ -718,7 +718,7 @@ namespace usb_mic
|
|||
case USB_TOKEN_OUT:
|
||||
printf("token out ep: %d\n", devep);
|
||||
OSDebugOut(TEXT("token out ep: %d len: %d\n"), devep, p->actual_length);
|
||||
[[fallthrough]];
|
||||
break;
|
||||
default:
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
|
@ -866,11 +866,11 @@ namespace usb_mic
|
|||
int SingstarDevice::Freeze(int mode, USBDevice* dev, void* data)
|
||||
{
|
||||
SINGSTARMICState* s = (SINGSTARMICState*)dev;
|
||||
if (!s)
|
||||
return 0;
|
||||
switch (mode)
|
||||
{
|
||||
case FREEZE_LOAD:
|
||||
if (!s)
|
||||
return -1;
|
||||
s->f = *(SINGSTARMICState::freeze*)data;
|
||||
if (s->audsrc[0])
|
||||
s->audsrc[0]->SetResampling(s->f.srate[0]);
|
||||
|
@ -878,8 +878,6 @@ namespace usb_mic
|
|||
s->audsrc[1]->SetResampling(s->f.srate[1]);
|
||||
return sizeof(SINGSTARMICState::freeze);
|
||||
case FREEZE_SAVE:
|
||||
if (!s)
|
||||
return -1;
|
||||
*(SINGSTARMICState::freeze*)data = s->f;
|
||||
return sizeof(SINGSTARMICState::freeze);
|
||||
case FREEZE_SIZE:
|
||||
|
@ -887,7 +885,7 @@ namespace usb_mic
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace usb_mic
|
||||
|
|
|
@ -23,8 +23,10 @@ namespace usb_msd
|
|||
|
||||
static void entryChanged(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
const gchar* text = gtk_entry_get_text(GTK_ENTRY(widget));
|
||||
//fprintf(stderr, "Entry text:%s\n", text);
|
||||
fprintf(stderr, "Entry text:%s\n", text);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void fileChooser(GtkWidget* widget, gpointer data)
|
||||
|
@ -59,7 +61,7 @@ namespace usb_msd
|
|||
|
||||
int MsdDevice::Configure(int port, const std::string& api, void* data)
|
||||
{
|
||||
GtkWidget *ro_frame, *ro_label, *rs_hbox, *rs_label, *rs_cb, *vbox;
|
||||
GtkWidget *ro_frame, *ro_label, *rs_hbox, *vbox;
|
||||
|
||||
GtkWidget* dlg = gtk_dialog_new_with_buttons(
|
||||
"Mass Storage Settings", GTK_WINDOW(data), GTK_DIALOG_MODAL,
|
||||
|
|
|
@ -618,7 +618,7 @@ namespace usb_msd
|
|||
MSDState* s = (MSDState*)opaque;
|
||||
DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x\n", cbw->lun, cbw->tag, cbw->data_len, cbw->cmd[0]);
|
||||
|
||||
uint32_t lba;
|
||||
int64_t lba;
|
||||
uint32_t xfer_len;
|
||||
s->f.last_cmd = cbw->cmd[0];
|
||||
|
||||
|
@ -701,7 +701,7 @@ namespace usb_msd
|
|||
s->f.data_len = xfer_len * LBA_BLOCK_SIZE;
|
||||
s->f.file_op_tag = s->f.tag;
|
||||
|
||||
DPRINTF("read lba=0x%x, len=0x%x\n", lba, xfer_len * LBA_BLOCK_SIZE);
|
||||
DPRINTF("read lba=0x%llx, len=0x%x\n", lba, xfer_len * LBA_BLOCK_SIZE);
|
||||
|
||||
if (xfer_len == 0) // nothing to do
|
||||
break;
|
||||
|
@ -1088,11 +1088,11 @@ namespace usb_msd
|
|||
MSDState* s = (MSDState*)dev;
|
||||
MSDState::freeze* tmp;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
switch (mode)
|
||||
{
|
||||
case FREEZE_LOAD:
|
||||
if (!s)
|
||||
return -1;
|
||||
//if (s->f.req) free (s->f.req);
|
||||
|
||||
tmp = (MSDState::freeze*)data;
|
||||
|
@ -1107,8 +1107,6 @@ namespace usb_msd
|
|||
return sizeof(MSDState::freeze); // + sizeof(ReqState);
|
||||
|
||||
case FREEZE_SAVE:
|
||||
if (!s)
|
||||
return -1;
|
||||
tmp = (MSDState::freeze*)data;
|
||||
*tmp = s->f;
|
||||
return sizeof(MSDState::freeze);
|
||||
|
@ -1118,7 +1116,7 @@ namespace usb_msd
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef DPRINTF
|
||||
|
|
|
@ -46,14 +46,6 @@ namespace usb_pad
|
|||
std::vector<DIJOYSTATE2> jso; // DInput joystick old state, only for config
|
||||
std::vector<DIJOYSTATE2> jsi; // DInput joystick initial state, only for config
|
||||
|
||||
int32_t AXISID[2][CID_COUNT];
|
||||
int32_t BUTTON[2][CID_COUNT];
|
||||
int32_t INVERT[2][CID_COUNT];
|
||||
int32_t HALF[2][CID_COUNT];
|
||||
int32_t LINEAR[2][CID_COUNT];
|
||||
int32_t OFFSET[2][CID_COUNT];
|
||||
int32_t DEADZONE[2][CID_COUNT];
|
||||
|
||||
int32_t BYPASSCAL = 0;
|
||||
int32_t GAINZ[2][1];
|
||||
int32_t FFMULTI[2][1];
|
||||
|
@ -64,7 +56,7 @@ namespace usb_pad
|
|||
HWND hKey;
|
||||
HWND hWnd;
|
||||
TCHAR text[1024];
|
||||
ControlID CID = CID_COUNT;
|
||||
ControlID CID = CID_COUNT; //keep track of last assigned control
|
||||
|
||||
HFONT hFont;
|
||||
HDC hDC;
|
||||
|
@ -305,17 +297,18 @@ namespace usb_pad
|
|||
if (filtercontrol == -1)
|
||||
return;
|
||||
//slider
|
||||
LINEAR[port][filtercontrol] = SendMessage(GetDlgItem(hWnd, IDC_SLIDER1), TBM_GETPOS, 0, 0) - 50 * PRECMULTI;
|
||||
OFFSET[port][filtercontrol] = SendMessage(GetDlgItem(hWnd, IDC_SLIDER2), TBM_GETPOS, 0, 0) - 50 * PRECMULTI;
|
||||
DEADZONE[port][filtercontrol] = SendMessage(GetDlgItem(hWnd, IDC_SLIDER3), TBM_GETPOS, 0, 0) - 50 * PRECMULTI;
|
||||
auto& im = g_Controls[port][filtercontrol];
|
||||
im.LINEAR = SendMessage(GetDlgItem(hWnd, IDC_SLIDER1), TBM_GETPOS, 0, 0) - 50 * PRECMULTI;
|
||||
im.OFFSET = SendMessage(GetDlgItem(hWnd, IDC_SLIDER2), TBM_GETPOS, 0, 0) - 50 * PRECMULTI;
|
||||
im.DEADZONE = SendMessage(GetDlgItem(hWnd, IDC_SLIDER3), TBM_GETPOS, 0, 0) - 50 * PRECMULTI;
|
||||
GAINZ[port][0] = SendMessage(GetDlgItem(hWnd, IDC_SLIDER4), TBM_GETPOS, 0, 0);
|
||||
FFMULTI[port][0] = SendMessage(GetDlgItem(hWnd, IDC_SLIDER5), TBM_GETPOS, 0, 0);
|
||||
|
||||
swprintf_s(text, TEXT("LINEARITY: %0.02f"), float(LINEAR[port][filtercontrol]) / PRECMULTI);
|
||||
swprintf_s(text, TEXT("LINEARITY: %0.02f"), float(im.LINEAR) / PRECMULTI);
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_LINEAR), text);
|
||||
swprintf_s(text, TEXT("OFFSET: %0.02f"), float(OFFSET[port][filtercontrol]) / PRECMULTI);
|
||||
swprintf_s(text, TEXT("OFFSET: %0.02f"), float(im.OFFSET) / PRECMULTI);
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_OFFSET), text);
|
||||
swprintf_s(text, TEXT("DEAD-ZONE: %0.02f"), float(DEADZONE[port][filtercontrol]) / PRECMULTI);
|
||||
swprintf_s(text, TEXT("DEAD-ZONE: %0.02f"), float(im.DEADZONE) / PRECMULTI);
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_DEADZONE), text);
|
||||
|
||||
GetClientRect(GetDlgItem(hWnd, IDC_PICTURE), &rect);
|
||||
|
@ -328,12 +321,11 @@ namespace usb_pad
|
|||
filtercontrol = SendMessage(GetDlgItem(hWnd, IDC_COMBO1), CB_GETCURSEL, 0, 0);
|
||||
if (filtercontrol == -1)
|
||||
return;
|
||||
//InputMapped im = {};
|
||||
//GetInputMap(port, (ControlID)filtercontrol, im);
|
||||
auto& im = g_Controls[port][filtercontrol];
|
||||
//slider
|
||||
SendMessage(GetDlgItem(hWnd, IDC_SLIDER1), TBM_SETPOS, 1, LINEAR[port][filtercontrol] + 50 * PRECMULTI);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_SLIDER2), TBM_SETPOS, 1, OFFSET[port][filtercontrol] + 50 * PRECMULTI);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_SLIDER3), TBM_SETPOS, 1, DEADZONE[port][filtercontrol] + 50 * PRECMULTI);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_SLIDER1), TBM_SETPOS, 1, im.LINEAR + 50 * PRECMULTI);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_SLIDER2), TBM_SETPOS, 1, im.OFFSET + 50 * PRECMULTI);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_SLIDER3), TBM_SETPOS, 1, im.DEADZONE + 50 * PRECMULTI);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_SLIDER4), TBM_SETPOS, 1, GAINZ[port][0]);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_SLIDER5), TBM_SETPOS, 1, FFMULTI[port][0]);
|
||||
|
||||
|
@ -342,44 +334,47 @@ namespace usb_pad
|
|||
|
||||
void DefaultFilters(int port, LONG id)
|
||||
{
|
||||
auto& im_l = g_Controls[port][CID_STEERING];
|
||||
auto& im_r = g_Controls[port][CID_STEERING_R];
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
LINEAR[port][i] = 0;
|
||||
OFFSET[port][i] = 0;
|
||||
DEADZONE[port][i] = 0;
|
||||
auto& c = g_Controls[port][i];
|
||||
c.LINEAR = 0;
|
||||
c.OFFSET = 0;
|
||||
c.DEADZONE = 0;
|
||||
}
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case 0:
|
||||
LINEAR[port][0] = 0;
|
||||
OFFSET[port][0] = 0;
|
||||
LINEAR[port][1] = 0;
|
||||
OFFSET[port][1] = 0;
|
||||
im_l.LINEAR = 0;
|
||||
im_l.OFFSET = 0;
|
||||
im_r.LINEAR = 0;
|
||||
im_r.OFFSET = 0;
|
||||
break;
|
||||
case 1:
|
||||
LINEAR[port][0] = 6 * PRECMULTI;
|
||||
OFFSET[port][0] = 0;
|
||||
LINEAR[port][1] = 6 * PRECMULTI;
|
||||
OFFSET[port][1] = 0;
|
||||
im_l.LINEAR = 6 * PRECMULTI;
|
||||
im_l.OFFSET = 0;
|
||||
im_r.LINEAR = 6 * PRECMULTI;
|
||||
im_r.OFFSET = 0;
|
||||
break;
|
||||
case 2:
|
||||
LINEAR[port][0] = 12 * PRECMULTI;
|
||||
OFFSET[port][0] = 0;
|
||||
LINEAR[port][1] = 12 * PRECMULTI;
|
||||
OFFSET[port][1] = 0;
|
||||
im_l.LINEAR = 12 * PRECMULTI;
|
||||
im_l.OFFSET = 0;
|
||||
im_r.LINEAR = 12 * PRECMULTI;
|
||||
im_r.OFFSET = 0;
|
||||
break;
|
||||
case 3:
|
||||
LINEAR[port][0] = 18 * PRECMULTI;
|
||||
OFFSET[port][0] = 0;
|
||||
LINEAR[port][1] = 18 * PRECMULTI;
|
||||
OFFSET[port][1] = 0;
|
||||
im_l.LINEAR = 18 * PRECMULTI;
|
||||
im_l.OFFSET = 0;
|
||||
im_r.LINEAR = 18 * PRECMULTI;
|
||||
im_r.OFFSET = 0;
|
||||
break;
|
||||
case 4:
|
||||
LINEAR[port][0] = 25 * PRECMULTI;
|
||||
OFFSET[port][0] = 0;
|
||||
LINEAR[port][1] = 25 * PRECMULTI;
|
||||
OFFSET[port][1] = 0;
|
||||
im_l.LINEAR = 25 * PRECMULTI;
|
||||
im_l.OFFSET = 0;
|
||||
im_r.LINEAR = 25 * PRECMULTI;
|
||||
im_r.OFFSET = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -398,7 +393,7 @@ namespace usb_pad
|
|||
if (GetInputMap(port, (ControlID)filtercontrol, im))
|
||||
{
|
||||
TESTV = ReadAxis(im);
|
||||
TESTVF = FilterControl(ReadAxis(im), LINEAR[port][filtercontrol], OFFSET[port][filtercontrol], DEADZONE[port][filtercontrol]);
|
||||
TESTVF = FilterControl(ReadAxis(im), im.LINEAR, im.OFFSET, im.DEADZONE);
|
||||
GetClientRect(GetDlgItem(hWnd, IDC_PICTURE), &rect);
|
||||
MapWindowPoints(GetDlgItem(hWnd, IDC_PICTURE), hWnd, (POINT*)&rect, 2);
|
||||
InvalidateRect(hWnd, &rect, TRUE);
|
||||
|
@ -418,13 +413,6 @@ namespace usb_pad
|
|||
|
||||
if (FindControl(port, CID, im))
|
||||
{
|
||||
if (CID <= CID_BRAKE)
|
||||
{
|
||||
LINEAR[port][CID] = im.LINEAR;
|
||||
OFFSET[port][CID] = im.OFFSET;
|
||||
DEADZONE[port][CID] = im.DEADZONE;
|
||||
}
|
||||
|
||||
AddInputMap(port, CID, im);
|
||||
SetControlLabel(CID, im);
|
||||
}
|
||||
|
@ -501,13 +489,14 @@ namespace usb_pad
|
|||
filtercontrol = SendMessage(GetDlgItem(hWnd, IDC_COMBO1), CB_GETCURSEL, 0, 0);
|
||||
if (filtercontrol >= 0)
|
||||
{
|
||||
auto& im = g_Controls[port][filtercontrol];
|
||||
|
||||
//draw nonlinear line
|
||||
SelectObject(hDrawingDC, bluepen);
|
||||
MoveToEx(hDrawingDC, (px + 8) * scale, (pheight + py - 8) * scale, 0);
|
||||
for (float x = 0; x < 1.0f; x += 0.001f)
|
||||
{
|
||||
float y1 = FilterControl(x, LINEAR[port][filtercontrol], OFFSET[port][filtercontrol], DEADZONE[port][filtercontrol]);
|
||||
float y1 = FilterControl(x, im.LINEAR, im.OFFSET, im.DEADZONE);
|
||||
LineTo(hDrawingDC, (x * (pwidth - 16) + px + 8) * scale, (-y1 * (pheight - 16) + (pheight - 8) + py) * scale);
|
||||
}
|
||||
LineTo(hDrawingDC, (1.0f * (pwidth - 16) + px + 8) * scale, (-1.0f * (pheight - 16) + (pheight - 8) + py) * scale);
|
||||
|
@ -1340,13 +1329,6 @@ namespace usb_pad
|
|||
im.DEADZONE = std::stoi(value);
|
||||
}
|
||||
|
||||
//if (cid <= CID_BRAKE)
|
||||
{
|
||||
LINEAR[port][cid] = im.LINEAR;
|
||||
OFFSET[port][cid] = im.OFFSET;
|
||||
DEADZONE[port][cid] = im.DEADZONE;
|
||||
}
|
||||
|
||||
AddInputMap(port, (ControlID)cid, im);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,15 @@ namespace usb_pad
|
|||
(((x) + 8 * sizeof(unsigned char) - 1) / (8 * sizeof(unsigned char)))
|
||||
#define testBit(bit, array) ((((uint8_t*)(array))[(bit) / 8] >> ((bit) % 8)) & 1)
|
||||
|
||||
EvdevFF::EvdevFF(int fd)
|
||||
EvdevFF::EvdevFF(int fd, bool gain_enabled, int gain, bool ac_managed, int ac_strength)
|
||||
: mHandle(fd)
|
||||
, mUseRumble(false)
|
||||
, mLastValue(0)
|
||||
, m_gain_enabled(gain_enabled)
|
||||
, m_gain(gain)
|
||||
//, m_ac_managed(ac_enabled)
|
||||
, m_ac_managed(true)
|
||||
, m_ac_strength(ac_strength)
|
||||
{
|
||||
unsigned char features[BITS_TO_UCHAR(FF_MAX)];
|
||||
if (ioctl(mHandle, EVIOCGBIT(EV_FF, sizeof(features)), features) < 0)
|
||||
|
@ -80,17 +86,21 @@ namespace usb_pad
|
|||
// Logitech wheels' force vs turn direction: 255 - left, 127/128 - neutral, 0 - right
|
||||
// left direction
|
||||
mEffect.direction = 0x4000;
|
||||
mEffect.u.constant.envelope.attack_length = 0; //0x100;
|
||||
mEffect.u.constant.envelope.attack_level = 0;
|
||||
mEffect.u.constant.envelope.fade_length = 0; //0x100;
|
||||
mEffect.u.constant.envelope.fade_level = 0;
|
||||
mEffect.trigger.button = 0;
|
||||
mEffect.trigger.interval = 0;
|
||||
mEffect.replay.length = 0x7FFFUL; /* mseconds */
|
||||
mEffect.replay.delay = 0;
|
||||
|
||||
SetGain(100);
|
||||
SetAutoCenter(0);
|
||||
if (m_gain_enabled)
|
||||
SetGain(m_gain);
|
||||
|
||||
m_ac_strength = std::min(100, std::max(0, m_ac_strength));
|
||||
if (ac_managed)
|
||||
SetAutoCenter(0); // default to off
|
||||
else
|
||||
SetAutoCenter(m_ac_strength);
|
||||
|
||||
m_ac_managed = ac_managed;
|
||||
}
|
||||
|
||||
EvdevFF::~EvdevFF()
|
||||
|
@ -128,6 +138,10 @@ namespace usb_pad
|
|||
mEffect.type = FF_CONSTANT;
|
||||
mEffect.id = mEffIds[EFF_CONSTANT];
|
||||
mEffect.u.constant.level = /*ff.u.constant.*/ level;
|
||||
// mEffect.u.constant.envelope.attack_length = 0;//0x100;
|
||||
// mEffect.u.constant.envelope.attack_level = 0;
|
||||
// mEffect.u.constant.envelope.fade_length = 0;//0x100;
|
||||
// mEffect.u.constant.envelope.fade_level = 0;
|
||||
|
||||
OSDebugOut("Constant force: %d\n", level);
|
||||
if (ioctl(mHandle, EVIOCSFF, &(mEffect)) < 0)
|
||||
|
@ -277,7 +291,10 @@ namespace usb_pad
|
|||
|
||||
void EvdevFF::SetAutoCenter(int value)
|
||||
{
|
||||
if (!m_ac_managed)
|
||||
return;
|
||||
struct input_event ie;
|
||||
value = value * m_ac_strength / 100;
|
||||
|
||||
ie.type = EV_FF;
|
||||
ie.code = FF_AUTOCENTER;
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace usb_pad
|
|||
class EvdevFF : public FFDevice
|
||||
{
|
||||
public:
|
||||
EvdevFF(int fd);
|
||||
EvdevFF(int fd, bool gain_enabled, int gain, bool ac_managed, int ac_strength);
|
||||
~EvdevFF();
|
||||
|
||||
void SetConstantForce(int level);
|
||||
|
@ -45,6 +45,10 @@ namespace usb_pad
|
|||
|
||||
bool mUseRumble;
|
||||
int mLastValue;
|
||||
bool m_gain_enabled;
|
||||
int m_gain;
|
||||
bool m_ac_managed;
|
||||
int m_ac_strength;
|
||||
};
|
||||
|
||||
} // namespace evdev
|
||||
|
|
|
@ -584,7 +584,7 @@ namespace usb_pad
|
|||
|
||||
static bool PollInput(const std::vector<std::pair<std::string, ConfigMapping>>& fds, std::string& dev_name, bool isaxis, int& value, bool& inverted, int& initial)
|
||||
{
|
||||
int event_fd = -1, t;
|
||||
int event_fd = -1;
|
||||
ssize_t len;
|
||||
input_event event;
|
||||
struct AxisValue
|
||||
|
@ -749,9 +749,9 @@ namespace usb_pad
|
|||
ApiCallbacks apicbs{GetEventName, EnumerateDevices, PollInput};
|
||||
int ret = 0;
|
||||
if (!strcmp(dev_type, BuzzDevice::TypeName()))
|
||||
ret = GtkBuzzConfigure(port, dev_type, "Evdev Settings", "evdev", GTK_WINDOW(data), apicbs);
|
||||
ret = GtkBuzzConfigure(port, dev_type, "Evdev Settings", evdev::APINAME, GTK_WINDOW(data), apicbs);
|
||||
else
|
||||
ret = GtkPadConfigure(port, dev_type, "Evdev Settings", "evdev", GTK_WINDOW(data), apicbs);
|
||||
ret = GtkPadConfigure(port, dev_type, "Evdev Settings", evdev::APINAME, GTK_WINDOW(data), apicbs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace usb_pad
|
|||
}
|
||||
|
||||
#define EVDEV_DIR "/dev/input/by-id/"
|
||||
void EnumerateDevices(vstring& list)
|
||||
void EnumerateDevices(device_list& list)
|
||||
{
|
||||
int fd;
|
||||
int res;
|
||||
|
@ -128,7 +128,7 @@ namespace usb_pad
|
|||
struct dirent* dp;
|
||||
|
||||
//TODO do some caching? ioctl is "very" slow
|
||||
static vstring list_cache;
|
||||
static device_list list_cache;
|
||||
|
||||
DIR* dirp = opendir(EVDEV_DIR);
|
||||
if (!dirp)
|
||||
|
@ -140,7 +140,7 @@ namespace usb_pad
|
|||
// get rid of unplugged devices
|
||||
for (int i = 0; i < list_cache.size();)
|
||||
{
|
||||
if (!file_exists(list_cache[i].second))
|
||||
if (!file_exists(list_cache[i].path))
|
||||
list_cache.erase(list_cache.begin() + i);
|
||||
else
|
||||
i++;
|
||||
|
@ -159,8 +159,8 @@ namespace usb_pad
|
|||
std::string path = str.str();
|
||||
|
||||
auto it = std::find_if(list_cache.begin(), list_cache.end(),
|
||||
[&path](auto& pair) {
|
||||
return pair.second == path;
|
||||
[&path](evdev_device& dev) {
|
||||
return dev.path == path;
|
||||
});
|
||||
if (it != list_cache.end())
|
||||
continue;
|
||||
|
@ -173,16 +173,16 @@ namespace usb_pad
|
|||
continue;
|
||||
}
|
||||
|
||||
list_cache.push_back(std::make_pair(std::string(dp->d_name), path));
|
||||
//list_cache.push_back(std::make_pair(std::string(dp->d_name), path));
|
||||
|
||||
/*res = ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);
|
||||
if (res < 0)
|
||||
perror("EVIOCGNAME");
|
||||
else
|
||||
{
|
||||
OSDebugOut("Evdev device name: %s\n", buf);
|
||||
list_cache.push_back(std::make_pair(std::string(buf) + " (evdev)", path));
|
||||
}*/
|
||||
res = ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);
|
||||
if (res < 0)
|
||||
perror("EVIOCGNAME");
|
||||
else
|
||||
{
|
||||
OSDebugOut("Evdev device name: %s\n", buf);
|
||||
list_cache.push_back({buf, dp->d_name, path});
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
@ -368,6 +368,7 @@ namespace usb_pad
|
|||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
// Map to xbox360ish controller
|
||||
switch (code)
|
||||
{
|
||||
|
@ -408,16 +409,17 @@ namespace usb_pad
|
|||
case BTN_TL:
|
||||
button = PAD_L1;
|
||||
break;
|
||||
case BTN_THUMBR:
|
||||
case BTN_TR2:
|
||||
button = PAD_R2;
|
||||
break;
|
||||
case BTN_THUMBL:
|
||||
case BTN_TL2:
|
||||
button = PAD_L2;
|
||||
break;
|
||||
default:
|
||||
OSDebugOut("Unmapped Button: %d, %d\n", code, event.value);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//if (button != PAD_BUTTON_COUNT)
|
||||
|
@ -530,9 +532,10 @@ namespace usb_pad
|
|||
int EvDevPad::Open()
|
||||
{
|
||||
std::stringstream name;
|
||||
vstring device_list;
|
||||
device_list device_list;
|
||||
char buf[1024];
|
||||
mWheelData = {};
|
||||
int32_t b_gain, gain, b_ac, ac;
|
||||
|
||||
unsigned long keybit[NBITS(KEY_MAX)];
|
||||
unsigned long absbit[NBITS(ABS_MAX)];
|
||||
|
@ -563,7 +566,8 @@ namespace usb_pad
|
|||
case WT_DRIVING_FORCE_PRO:
|
||||
case WT_DRIVING_FORCE_PRO_1102:
|
||||
{
|
||||
LoadSetting(mDevType, mPort, APINAME, N_HIDRAW_FF_PT, mUseRawFF);
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_HIDRAW_FF_PT, mUseRawFF))
|
||||
mUseRawFF = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -614,7 +618,7 @@ namespace usb_pad
|
|||
{
|
||||
if (mWriterThread.joinable())
|
||||
mWriterThread.join();
|
||||
mWriterThread = std::thread(EvDevPad::WriterThread, this);
|
||||
mWriterThread = std::thread(&EvDevPad::WriterThread, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -633,11 +637,11 @@ namespace usb_pad
|
|||
mDevices.push_back({});
|
||||
|
||||
struct device_data& device = mDevices.back();
|
||||
device.name = it.first;
|
||||
device.name = it.name;
|
||||
|
||||
if ((device.cfg.fd = open(it.second.c_str(), O_RDWR | O_NONBLOCK)) < 0)
|
||||
if ((device.cfg.fd = open(it.path.c_str(), O_RDWR | O_NONBLOCK)) < 0)
|
||||
{
|
||||
OSDebugOut("Cannot open device: %s\n", it.second.c_str());
|
||||
OSDebugOut("Cannot open device: %s\n", it.path.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -664,11 +668,19 @@ namespace usb_pad
|
|||
switch (mType)
|
||||
{
|
||||
case WT_BUZZ_CONTROLLER:
|
||||
LoadBuzzMappings(mDevType, mPort, device.name, device.cfg);
|
||||
LoadBuzzMappings(mDevType, mPort, it.id, device.cfg);
|
||||
max_buttons = 20;
|
||||
break;
|
||||
default:
|
||||
LoadMappings(mDevType, mPort, device.name, device.cfg);
|
||||
LoadMappings(mDevType, mPort, it.id, device.cfg);
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_GAIN_ENABLED, b_gain))
|
||||
b_gain = 1;
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_GAIN, gain))
|
||||
gain = 100;
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_AUTOCENTER_MANAGED, b_ac))
|
||||
b_ac = 1;
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_AUTOCENTER, ac))
|
||||
ac = 100;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -716,7 +728,9 @@ namespace usb_pad
|
|||
// TODO Instead of single FF instance, create for every device with X-axis???
|
||||
// and then switch between them according to which device was used recently
|
||||
if (k == JOY_STEERING && !mFFdev && !mUseRawFF)
|
||||
mFFdev = new EvdevFF(device.cfg.fd);
|
||||
{
|
||||
mFFdev = new EvdevFF(device.cfg.fd, b_gain, gain, b_ac, ac);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -805,20 +819,19 @@ namespace usb_pad
|
|||
return 0;
|
||||
}
|
||||
|
||||
void EvDevPad::WriterThread(void* ptr)
|
||||
void EvDevPad::WriterThread()
|
||||
{
|
||||
std::array<uint8_t, 8> buf;
|
||||
int res;
|
||||
|
||||
EvDevPad* pad = static_cast<EvDevPad*>(ptr);
|
||||
pad->mWriterThreadIsRunning = true;
|
||||
mWriterThreadIsRunning = true;
|
||||
|
||||
while (pad->mHidHandle != -1)
|
||||
while (mHidHandle != -1)
|
||||
{
|
||||
//if (pad->mFFData.wait_dequeue_timed(buf, std::chrono::milliseconds(1000))) //FIXME SIGABORT :S
|
||||
if (pad->mFFData.try_dequeue(buf))
|
||||
//if (mFFData.wait_dequeue_timed(buf, std::chrono::milliseconds(1000))) //FIXME SIGABORT :S
|
||||
if (mFFData.try_dequeue(buf))
|
||||
{
|
||||
res = write(pad->mHidHandle, buf.data(), buf.size());
|
||||
res = write(mHidHandle, buf.data(), buf.size());
|
||||
if (res < 0)
|
||||
{
|
||||
printf("Error: %d\n", errno);
|
||||
|
@ -832,7 +845,7 @@ namespace usb_pad
|
|||
}
|
||||
OSDebugOut(TEXT("WriterThread exited.\n"));
|
||||
|
||||
pad->mWriterThreadIsRunning = false;
|
||||
mWriterThreadIsRunning = false;
|
||||
}
|
||||
|
||||
} // namespace evdev
|
||||
|
|
|
@ -32,17 +32,15 @@ namespace usb_pad
|
|||
(((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
|
||||
#define NBITS(x) ((((x)-1) / (sizeof(long) * 8)) + 1)
|
||||
|
||||
void EnumerateDevices(vstring& list);
|
||||
void EnumerateDevices(device_list& list);
|
||||
|
||||
static const char* APINAME = "evdev";
|
||||
static constexpr const char* APINAME = "evdev";
|
||||
|
||||
class EvDevPad : public Pad
|
||||
{
|
||||
public:
|
||||
EvDevPad(int port, const char* dev_type)
|
||||
: Pad(port, dev_type)
|
||||
, mUseRawFF(0)
|
||||
, mHidHandle(-1)
|
||||
, mWriterThreadIsRunning(false)
|
||||
{
|
||||
}
|
||||
|
@ -64,13 +62,15 @@ namespace usb_pad
|
|||
protected:
|
||||
void PollAxesValues(const device_data& device);
|
||||
void SetAxis(const device_data& device, int code, int value);
|
||||
static void WriterThread(void* ptr);
|
||||
void WriterThread();
|
||||
|
||||
int mHidHandle;
|
||||
EvdevFF* mEvdevFF;
|
||||
struct wheel_data_t mWheelData;
|
||||
int mHidHandle = -1;
|
||||
EvdevFF* mEvdevFF = nullptr;
|
||||
struct wheel_data_t mWheelData
|
||||
{
|
||||
};
|
||||
std::vector<device_data> mDevices;
|
||||
int32_t mUseRawFF;
|
||||
int32_t mUseRawFF = 0;
|
||||
std::thread mWriterThread;
|
||||
std::atomic<bool> mWriterThreadIsRunning;
|
||||
moodycamel::BlockingReaderWriterQueue<std::array<uint8_t, 8>, 32> mFFData;
|
||||
|
|
|
@ -85,6 +85,7 @@ namespace usb_pad
|
|||
if (joyname.empty() || cfg.controls.size() != JOY_MAPS_COUNT)
|
||||
return false;
|
||||
|
||||
RemoveSection(dev_type, port, joyname);
|
||||
std::stringstream str;
|
||||
for (int i = 0; i < JOY_MAPS_COUNT; i++)
|
||||
{
|
||||
|
@ -92,7 +93,7 @@ namespace usb_pad
|
|||
str.str("");
|
||||
str << "map_" << JoystickMapNames[i];
|
||||
const std::string& name = str.str();
|
||||
if (!SaveSetting(dev_type, port, joyname, name.c_str(), static_cast<int32_t>(cfg.controls[i])))
|
||||
if (cfg.controls[i] >= 0 && !SaveSetting(dev_type, port, joyname, name.c_str(), static_cast<int32_t>(cfg.controls[i])))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -150,6 +151,7 @@ namespace usb_pad
|
|||
if (joyname.empty())
|
||||
return false;
|
||||
|
||||
RemoveSection(dev_type, port, joyname);
|
||||
std::stringstream str;
|
||||
|
||||
const size_t c = countof(buzz_map_names);
|
||||
|
@ -159,7 +161,7 @@ namespace usb_pad
|
|||
str.clear();
|
||||
str << "map_" << buzz_map_names[i % c] << "_" << (i / c);
|
||||
const std::string& name = str.str();
|
||||
if (!SaveSetting(dev_type, port, joyname, name.c_str(), static_cast<int32_t>(cfg.controls[i])))
|
||||
if (cfg.controls[i] >= 0 && !SaveSetting(dev_type, port, joyname, name.c_str(), static_cast<int32_t>(cfg.controls[i])))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -174,7 +176,7 @@ namespace usb_pad
|
|||
{
|
||||
for (int i = 0; /*i < JOY_MAPS_COUNT && */ i < it.second.controls.size(); i++)
|
||||
{
|
||||
if (it.second.controls[i] == (uint16_t)-1)
|
||||
if (it.second.controls[i] < 0)
|
||||
continue;
|
||||
|
||||
const char* pc_name = "Unknown";
|
||||
|
@ -225,7 +227,7 @@ namespace usb_pad
|
|||
|
||||
if (idx > -1)
|
||||
{
|
||||
std::string name = (cfg->joysticks.begin() + idx)->first;
|
||||
std::string name = (cfg->joysticks.begin() + idx)->name;
|
||||
cfg->js_iter = (cfg->joysticks.begin() + idx);
|
||||
OSDebugOut("Selected player %d idx: %d dev: '%s'\n", 2 - port, idx, name.c_str());
|
||||
}
|
||||
|
@ -233,7 +235,6 @@ namespace usb_pad
|
|||
|
||||
static void button_clicked(GtkComboBox* widget, gpointer data)
|
||||
{
|
||||
int port = reinterpret_cast<uintptr_t>(data);
|
||||
int type = reinterpret_cast<uintptr_t>(g_object_get_data(G_OBJECT(widget), JOYTYPE));
|
||||
ConfigData* cfg = (ConfigData*)g_object_get_data(G_OBJECT(widget), CFG);
|
||||
|
||||
|
@ -254,7 +255,7 @@ namespace usb_pad
|
|||
if (cfg->cb->poll(cfg->jsconf, dev_name, is_axis, value, inverted, initial))
|
||||
{
|
||||
auto it = std::find_if(cfg->jsconf.begin(), cfg->jsconf.end(),
|
||||
[&dev_name](auto& i) -> bool {
|
||||
[&dev_name](MappingPair& i) -> bool {
|
||||
return i.first == dev_name;
|
||||
});
|
||||
|
||||
|
@ -275,7 +276,6 @@ namespace usb_pad
|
|||
|
||||
static void button_clicked_buzz(GtkComboBox* widget, gpointer data)
|
||||
{
|
||||
int port = reinterpret_cast<uintptr_t>(data);
|
||||
int type = reinterpret_cast<uintptr_t>(g_object_get_data(G_OBJECT(widget), JOYTYPE));
|
||||
ConfigData* cfg = (ConfigData*)g_object_get_data(G_OBJECT(widget), CFG);
|
||||
|
||||
|
@ -295,7 +295,7 @@ namespace usb_pad
|
|||
if (cfg->cb->poll(cfg->jsconf, dev_name, false, value, inverted, initial))
|
||||
{
|
||||
auto it = std::find_if(cfg->jsconf.begin(), cfg->jsconf.end(),
|
||||
[&dev_name](auto& i) -> bool {
|
||||
[&dev_name](MappingPair& i) -> bool {
|
||||
return i.first == dev_name;
|
||||
});
|
||||
|
||||
|
@ -333,7 +333,7 @@ namespace usb_pad
|
|||
|
||||
auto& js = cfg->jsconf;
|
||||
auto it = std::find_if(js.begin(), js.end(),
|
||||
[&dev_name](auto i) {
|
||||
[&dev_name](MappingPair i) {
|
||||
return i.first == dev_name;
|
||||
});
|
||||
if (it != js.end())
|
||||
|
@ -394,19 +394,18 @@ namespace usb_pad
|
|||
refresh_store(cfg);
|
||||
}
|
||||
|
||||
static void hidraw_toggled(GtkToggleButton* widget, gpointer data)
|
||||
static void checkbox_toggled(GtkToggleButton* widget, gpointer data)
|
||||
{
|
||||
int port = reinterpret_cast<uintptr_t>(data);
|
||||
ConfigData* cfg = (ConfigData*)g_object_get_data(G_OBJECT(widget), CFG);
|
||||
if (cfg)
|
||||
gboolean* val = reinterpret_cast<gboolean*>(data);
|
||||
if (val)
|
||||
{
|
||||
cfg->use_hidraw_ff_pt = (bool)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
|
||||
*val = (bool)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
|
||||
}
|
||||
}
|
||||
|
||||
int GtkPadConfigure(int port, const char* dev_type, const char* apititle, const char* apiname, GtkWindow* parent, ApiCallbacks& apicbs)
|
||||
{
|
||||
GtkWidget *ro_frame, *ro_label, *rs_hbox, *rs_label, *rs_cb;
|
||||
GtkWidget *ro_frame, *rs_cb;
|
||||
GtkWidget *main_hbox, *right_vbox, *left_vbox, *treeview;
|
||||
GtkWidget* button;
|
||||
|
||||
|
@ -424,17 +423,16 @@ namespace usb_pad
|
|||
|
||||
for (const auto& it : cfg.joysticks)
|
||||
{
|
||||
if ((fd = open(it.second.c_str(), O_RDONLY | O_NONBLOCK)) < 0)
|
||||
if ((fd = open(it.path.c_str(), O_RDONLY | O_NONBLOCK)) < 0)
|
||||
{
|
||||
OSDebugOut("Cannot open device: %s\n", it.second.c_str());
|
||||
OSDebugOut("Cannot open device: %s\n", it.path.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigMapping c;
|
||||
c.fd = fd;
|
||||
LoadMappings(cfg.dev_type, port, it.first, c);
|
||||
cfg.jsconf.push_back(std::make_pair(it.first, c));
|
||||
OSDebugOut("mappings for '%s': %zu\n", it.first.c_str(), c.controls.size());
|
||||
ConfigMapping c(fd);
|
||||
LoadMappings(cfg.dev_type, port, it.id, c);
|
||||
cfg.jsconf.push_back(std::make_pair(it.id, c));
|
||||
OSDebugOut("mappings for '%s': %zu\n", it.name.c_str(), c.controls.size());
|
||||
}
|
||||
|
||||
refresh_store(&cfg);
|
||||
|
@ -596,6 +594,62 @@ namespace usb_pad
|
|||
|
||||
gtk_box_pack_start(GTK_BOX(right_vbox), cfg.label, TRUE, TRUE, 5);
|
||||
}
|
||||
ro_frame = gtk_frame_new("Force feedback");
|
||||
gtk_box_pack_start(GTK_BOX(right_vbox), ro_frame, TRUE, FALSE, 5);
|
||||
|
||||
//GtkWidget *frame_vbox = gtk_vbox_new (FALSE, 5);
|
||||
//gtk_container_add (GTK_CONTAINER (ro_frame), frame_vbox);
|
||||
|
||||
const char* labels_buff[][2] = {{"Set gain", "Gain"}, {"Managed by game", "Autocenter strength"}};
|
||||
const char* ff_var_name[][2] = {{N_GAIN_ENABLED, N_GAIN}, {N_AUTOCENTER_MANAGED, N_AUTOCENTER}};
|
||||
GtkWidget* ff_scales[2];
|
||||
int32_t ff_enabled[2];
|
||||
|
||||
GtkWidget* table = gtk_table_new(3, 2, true);
|
||||
gtk_container_add(GTK_CONTAINER(ro_frame), table);
|
||||
gtk_table_set_homogeneous(GTK_TABLE(table), FALSE);
|
||||
GtkAttachOptions opt = (GtkAttachOptions)(GTK_EXPAND | GTK_FILL); // default
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (LoadSetting(dev_type, port, apiname, ff_var_name[i][0], ff_enabled[i]))
|
||||
ff_enabled[i] = !!ff_enabled[i];
|
||||
else
|
||||
ff_enabled[i] = 1;
|
||||
|
||||
GtkWidget* chk_btn = gtk_check_button_new_with_label(labels_buff[i][0]);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_btn), (gboolean)ff_enabled[i]);
|
||||
g_signal_connect(G_OBJECT(chk_btn), "toggled", G_CALLBACK(checkbox_toggled), reinterpret_cast<gboolean*>(&ff_enabled[i]));
|
||||
gtk_table_attach(GTK_TABLE(table), chk_btn,
|
||||
2, 3,
|
||||
0 + i, 1 + i,
|
||||
GTK_FILL, GTK_SHRINK, 5, 1);
|
||||
|
||||
GtkWidget* label = gtk_label_new(labels_buff[i][1]);
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
|
||||
gtk_table_attach(GTK_TABLE(table), label,
|
||||
0, 1,
|
||||
0 + i, 1 + i,
|
||||
GTK_FILL, GTK_SHRINK, 5, 1);
|
||||
|
||||
//ff_scales[i] = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 1, 100, 1);
|
||||
ff_scales[i] = gtk_hscale_new_with_range(0, 100, 1);
|
||||
for (int v = 0; v <= 100; v += 10)
|
||||
gtk_scale_add_mark(GTK_SCALE(ff_scales[i]), v, GTK_POS_BOTTOM, nullptr);
|
||||
gtk_table_attach(GTK_TABLE(table), ff_scales[i],
|
||||
1, 2,
|
||||
0 + i, 1 + i,
|
||||
opt, opt, 5, 1);
|
||||
|
||||
int32_t var;
|
||||
if (LoadSetting(dev_type, port, apiname, ff_var_name[i][1], var))
|
||||
{
|
||||
var = std::min(100, std::max(0, var));
|
||||
gtk_range_set_value(GTK_RANGE(ff_scales[i]), var);
|
||||
}
|
||||
else
|
||||
gtk_range_set_value(GTK_RANGE(ff_scales[i]), 100);
|
||||
}
|
||||
|
||||
if (is_evdev)
|
||||
{
|
||||
|
@ -607,8 +661,8 @@ namespace usb_pad
|
|||
|
||||
GtkWidget* chk_btn = gtk_check_button_new_with_label("Enable");
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_btn), (gboolean)cfg.use_hidraw_ff_pt);
|
||||
g_object_set_data(G_OBJECT(chk_btn), CFG, &cfg);
|
||||
g_signal_connect(G_OBJECT(chk_btn), "toggled", G_CALLBACK(hidraw_toggled), reinterpret_cast<gpointer>(port));
|
||||
//g_object_set_data(G_OBJECT(chk_btn), CFG, &cfg);
|
||||
g_signal_connect(G_OBJECT(chk_btn), "toggled", G_CALLBACK(checkbox_toggled), reinterpret_cast<gboolean*>(&cfg.use_hidraw_ff_pt));
|
||||
gtk_box_pack_start(GTK_BOX(frame_vbox), chk_btn, FALSE, FALSE, 5);
|
||||
|
||||
rs_cb = new_combobox("Device:", frame_vbox);
|
||||
|
@ -617,12 +671,12 @@ namespace usb_pad
|
|||
for (auto& it : cfg.joysticks)
|
||||
{
|
||||
std::stringstream str;
|
||||
str << it.first;
|
||||
if (strcmp(apiname, "evdev") && !it.second.empty())
|
||||
str << " [" << it.second << "]";
|
||||
str << it.name;
|
||||
if (!strcmp(apiname, "evdev") && !it.id.empty())
|
||||
str << " [" << it.id << "]";
|
||||
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rs_cb), str.str().c_str());
|
||||
if (path == it.second)
|
||||
if (path == it.path)
|
||||
sel_idx = idx;
|
||||
idx++;
|
||||
}
|
||||
|
@ -640,7 +694,7 @@ namespace usb_pad
|
|||
{
|
||||
if (cfg.js_iter != cfg.joysticks.end())
|
||||
{
|
||||
if (!SaveSetting(dev_type, port, apiname, N_JOYSTICK, cfg.js_iter->second))
|
||||
if (!SaveSetting(dev_type, port, apiname, N_JOYSTICK, cfg.js_iter->path))
|
||||
ret = RESULT_FAILED;
|
||||
}
|
||||
|
||||
|
@ -651,6 +705,12 @@ namespace usb_pad
|
|||
{
|
||||
SaveSetting(dev_type, port, apiname, N_HIDRAW_FF_PT, cfg.use_hidraw_ff_pt);
|
||||
}
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
SaveSetting(dev_type, port, apiname, ff_var_name[i][0], ff_enabled[i]);
|
||||
int val = gtk_range_get_value(GTK_RANGE(ff_scales[i]));
|
||||
SaveSetting(dev_type, port, apiname, ff_var_name[i][1], val);
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = RESULT_CANCELED;
|
||||
|
@ -699,17 +759,17 @@ namespace usb_pad
|
|||
|
||||
for (const auto& it : cfg.joysticks)
|
||||
{
|
||||
if ((fd = open(it.second.c_str(), O_RDONLY | O_NONBLOCK)) < 0)
|
||||
if ((fd = open(it.path.c_str(), O_RDONLY | O_NONBLOCK)) < 0)
|
||||
{
|
||||
OSDebugOut("Cannot open device: %s\n", it.second.c_str());
|
||||
OSDebugOut("Cannot open device: %s\n", it.path.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigMapping c;
|
||||
c.fd = fd;
|
||||
LoadBuzzMappings(cfg.dev_type, port, it.first, c);
|
||||
cfg.jsconf.push_back(std::make_pair(it.first, c));
|
||||
OSDebugOut("mappings for '%s': %lu\n", it.first.c_str(), c.controls.size());
|
||||
LoadBuzzMappings(cfg.dev_type, port, it.id, c);
|
||||
cfg.jsconf.push_back(std::make_pair(it.id, c));
|
||||
OSDebugOut("mappings for '%s': %lu\n", it.name.c_str(), c.controls.size());
|
||||
}
|
||||
|
||||
refresh_store(&cfg);
|
||||
|
@ -867,7 +927,7 @@ namespace usb_pad
|
|||
{
|
||||
if (cfg.js_iter != cfg.joysticks.end())
|
||||
{
|
||||
if (!SaveSetting(dev_type, port, apiname, N_JOYSTICK, cfg.js_iter->second))
|
||||
if (!SaveSetting(dev_type, port, apiname, N_JOYSTICK, cfg.js_iter->path))
|
||||
ret = RESULT_FAILED;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,19 @@
|
|||
#include "../../configuration.h"
|
||||
|
||||
#define N_HIDRAW_FF_PT "hidraw_ff_pt"
|
||||
#define N_GAIN_ENABLED "gain_enabled"
|
||||
#define N_GAIN "gain"
|
||||
#define N_AUTOCENTER "autocenter"
|
||||
#define N_AUTOCENTER_MANAGED "ac_managed"
|
||||
|
||||
typedef std::vector<std::pair<std::string, std::string>> vstring;
|
||||
struct evdev_device
|
||||
{
|
||||
std::string name;
|
||||
std::string id;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
typedef std::vector<evdev_device> device_list;
|
||||
GtkWidget* new_combobox(const char* label, GtkWidget* vbox);
|
||||
|
||||
namespace usb_pad
|
||||
|
@ -65,7 +76,7 @@ namespace usb_pad
|
|||
JOY_MAPS_COUNT
|
||||
};
|
||||
|
||||
static const char* JoystickMapNames[] = {
|
||||
static constexpr const char* JoystickMapNames[] = {
|
||||
"cross",
|
||||
"square",
|
||||
"circle",
|
||||
|
@ -86,7 +97,7 @@ namespace usb_pad
|
|||
"throttle",
|
||||
"brake"};
|
||||
|
||||
static const char* buzz_map_names[] = {
|
||||
static constexpr const char* buzz_map_names[] = {
|
||||
"red",
|
||||
"yellow",
|
||||
"green",
|
||||
|
@ -103,24 +114,31 @@ namespace usb_pad
|
|||
|
||||
struct ConfigMapping
|
||||
{
|
||||
std::vector<uint16_t> controls;
|
||||
std::vector<int16_t> controls;
|
||||
int inverted[3];
|
||||
int initial[3];
|
||||
int fd = -1;
|
||||
|
||||
ConfigMapping() = default;
|
||||
ConfigMapping(int fd_)
|
||||
: fd(fd_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct ApiCallbacks
|
||||
{
|
||||
bool (*get_event_name)(const char* dev_type, int map, int event, const char** name);
|
||||
void (*populate)(vstring& jsdata);
|
||||
void (*populate)(device_list& jsdata);
|
||||
bool (*poll)(const std::vector<std::pair<std::string, ConfigMapping>>& jsconf, std::string& dev_name, bool isaxis, int& value, bool& inverted, int& initial);
|
||||
};
|
||||
|
||||
typedef std::pair<std::string, ConfigMapping> MappingPair;
|
||||
struct ConfigData
|
||||
{
|
||||
std::vector<std::pair<std::string, ConfigMapping>> jsconf;
|
||||
vstring joysticks;
|
||||
vstring::const_iterator js_iter;
|
||||
std::vector<MappingPair> jsconf;
|
||||
device_list joysticks;
|
||||
device_list::const_iterator js_iter;
|
||||
GtkWidget* label;
|
||||
GtkListStore* store;
|
||||
GtkTreeView* treeview;
|
||||
|
|
|
@ -173,7 +173,7 @@ namespace usb_pad
|
|||
return RESULT_CANCELED;
|
||||
|
||||
evdev::ApiCallbacks apicbs{GetEventName, EnumerateDevices, PollInput};
|
||||
int ret = evdev::GtkPadConfigure(port, dev_type, "Joydev Settings", "joydev", GTK_WINDOW(data), apicbs);
|
||||
int ret = evdev::GtkPadConfigure(port, dev_type, "Joydev Settings", joydev::APINAME, GTK_WINDOW(data), apicbs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace usb_pad
|
|||
#define NORM(x, n) (((uint32_t)(32768 + x) * n) / 0xFFFF)
|
||||
#define NORM2(x, n) (((uint32_t)(32768 + x) * n) / 0x7FFF)
|
||||
|
||||
void EnumerateDevices(vstring& list)
|
||||
void EnumerateDevices(device_list& list)
|
||||
{
|
||||
int fd;
|
||||
int res;
|
||||
|
@ -69,7 +69,7 @@ namespace usb_pad
|
|||
else
|
||||
{
|
||||
OSDebugOut("Joydev device name: %s\n", buf);
|
||||
list.push_back(std::make_pair(std::string(buf), path));
|
||||
list.push_back({buf, buf, path});
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
@ -114,7 +114,6 @@ namespace usb_pad
|
|||
continue;
|
||||
}
|
||||
|
||||
const auto& mappings = device.cfg.controls;
|
||||
//Non-blocking read sets len to -1 and errno to EAGAIN if no new data
|
||||
while ((len = read(device.cfg.fd, &events, sizeof(events))) > -1)
|
||||
{
|
||||
|
@ -325,9 +324,10 @@ namespace usb_pad
|
|||
|
||||
int JoyDevPad::Open()
|
||||
{
|
||||
vstring device_list;
|
||||
device_list device_list;
|
||||
bool has_steering;
|
||||
int count;
|
||||
int32_t b_gain, gain, b_ac, ac;
|
||||
memset(&mWheelData, 0, sizeof(wheel_data_t));
|
||||
|
||||
// Setting to unpressed
|
||||
|
@ -350,17 +350,26 @@ namespace usb_pad
|
|||
|
||||
EnumerateDevices(device_list);
|
||||
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_GAIN_ENABLED, b_gain))
|
||||
b_gain = 1;
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_GAIN, gain))
|
||||
gain = 100;
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_AUTOCENTER_MANAGED, b_ac))
|
||||
b_ac = 1;
|
||||
if (!LoadSetting(mDevType, mPort, APINAME, N_AUTOCENTER, ac))
|
||||
ac = 100;
|
||||
|
||||
for (const auto& it : device_list)
|
||||
{
|
||||
has_steering = false;
|
||||
mDevices.push_back({});
|
||||
|
||||
struct device_data& device = mDevices.back();
|
||||
device.name = it.first;
|
||||
device.name = it.name;
|
||||
|
||||
if ((device.cfg.fd = open(it.second.c_str(), O_RDWR | O_NONBLOCK)) < 0)
|
||||
if ((device.cfg.fd = open(it.path.c_str(), O_RDWR | O_NONBLOCK)) < 0)
|
||||
{
|
||||
OSDebugOut("Cannot open device: %s\n", it.second.c_str());
|
||||
OSDebugOut("Cannot open device: %s\n", it.path.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -441,12 +450,12 @@ namespace usb_pad
|
|||
|
||||
std::stringstream event;
|
||||
int index = 0;
|
||||
const char* tmp = it.second.c_str();
|
||||
const char* tmp = it.path.c_str();
|
||||
while (*tmp && !isdigit(*tmp))
|
||||
tmp++;
|
||||
|
||||
sscanf(tmp, "%d", &index);
|
||||
OSDebugOut("input index: %d of '%s'\n", index, it.second.c_str());
|
||||
OSDebugOut("input index: %d of '%s'\n", index, it.path.c_str());
|
||||
|
||||
//TODO kernel limit is 32?
|
||||
for (int j = 0; j <= 99; j++)
|
||||
|
@ -472,15 +481,11 @@ namespace usb_pad
|
|||
OSDebugOut("%s: Cannot open '%s'\n", APINAME, event.str().c_str());
|
||||
}
|
||||
else
|
||||
mFFdev = new evdev::EvdevFF(mHandleFF);
|
||||
mFFdev = new evdev::EvdevFF(mHandleFF, b_gain, gain, b_ac, ac);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
quit:
|
||||
Close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int JoyDevPad::Close()
|
||||
|
|
|
@ -23,9 +23,9 @@ namespace usb_pad
|
|||
namespace joydev
|
||||
{
|
||||
|
||||
void EnumerateDevices(vstring& list);
|
||||
void EnumerateDevices(device_list& list);
|
||||
|
||||
static const char* APINAME = "joydev";
|
||||
static constexpr const char* APINAME = "joydev";
|
||||
|
||||
class JoyDevPad : public Pad
|
||||
{
|
||||
|
@ -50,8 +50,10 @@ namespace usb_pad
|
|||
static int Configure(int port, const char* dev_type, void* data);
|
||||
|
||||
protected:
|
||||
int mHandleFF;
|
||||
struct wheel_data_t mWheelData;
|
||||
int mHandleFF = -1;
|
||||
struct wheel_data_t mWheelData
|
||||
{
|
||||
};
|
||||
std::vector<evdev::device_data> mDevices;
|
||||
};
|
||||
|
||||
|
|
|
@ -695,7 +695,7 @@ namespace usb_pad
|
|||
if (!InitHid())
|
||||
return FALSE;
|
||||
dgHwnd = hW;
|
||||
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
|
||||
SetWindowLongPtr(hW, GWLP_USERDATA, lParam);
|
||||
//SendDlgItemMessage(hW, IDC_BUILD_DATE, WM_SETTEXT, 0, (LPARAM)__DATE__ " " __TIME__);
|
||||
ListView_SetExtendedListViewStyle(GetDlgItem(hW, IDC_LIST1), LVS_EX_FULLROWSELECT);
|
||||
|
||||
|
|
|
@ -88,6 +88,12 @@ namespace usb_pad
|
|||
ffdev->SetFrictionForce(ff);
|
||||
}
|
||||
|
||||
void SetAutoCenter(FFDevice* ffdev, const autocenter& effect)
|
||||
{
|
||||
OSDebugOut(_T("%s: k1 %d k2 %d clip %d\n"), __func__, effect.k1, effect.k2, effect.clip);
|
||||
ffdev->SetAutoCenter((effect.k1 * effect.clip / 255) * 100 / 255); // FIXME
|
||||
}
|
||||
|
||||
// Unless passing ff packets straight to a device, parse it here
|
||||
void Pad::ParseFFData(const ff_data* ffdata, bool isDFP)
|
||||
{
|
||||
|
@ -205,6 +211,9 @@ namespace usb_pad
|
|||
caps |= FF_LG_CAPS_DAMPER_CLIP;
|
||||
SetDamperForce(mFFdev, ffdata->u.damper, caps);
|
||||
break;
|
||||
case FTYPE_AUTO_CENTER_SPRING:
|
||||
SetAutoCenter(mFFdev, ffdata->u.autocenter);
|
||||
break;
|
||||
default:
|
||||
OSDebugOut(TEXT("CMD_DOWNLOAD_AND_PLAY: unhandled force type 0x%02X in slots 0x%02X\n"), ffdata->type, slots);
|
||||
break;
|
||||
|
@ -230,9 +239,9 @@ namespace usb_pad
|
|||
case FTYPE_HIGH_RESOLUTION_SPRING:
|
||||
mFFdev->DisableForce(EFF_SPRING);
|
||||
break;
|
||||
//case FTYPE_AUTO_CENTER_SPRING:
|
||||
//mFFdev->DisableSpring();
|
||||
//break;
|
||||
case FTYPE_AUTO_CENTER_SPRING:
|
||||
mFFdev->SetAutoCenter(0);
|
||||
break;
|
||||
case FTYPE_FRICTION:
|
||||
mFFdev->DisableForce(EFF_FRICTION);
|
||||
break;
|
||||
|
|
|
@ -420,6 +420,14 @@ namespace usb_pad
|
|||
buf[3] = (data.buttons >> 8) & 0xff;
|
||||
buf[4] = 0xf0 | ((data.buttons >> 16) & 0xf);
|
||||
break;
|
||||
case WT_SEGA_SEAMIC:
|
||||
buf[0] = data.steering & 0xFF;
|
||||
buf[1] = data.throttle & 0xFF;
|
||||
buf[2] = data.brake & 0xFF;
|
||||
buf[3] = data.hatswitch & 0x0F; // 4bits?
|
||||
buf[3] |= (data.buttons & 0x0F) << 4; // 4 bits // TODO Or does it start at buf[4]?
|
||||
buf[4] = (data.buttons >> 4) & 0x3F; // 10 - 4 = 6 bits
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -629,17 +637,15 @@ namespace usb_pad
|
|||
{
|
||||
PADState* s = (PADState*)dev;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
switch (mode)
|
||||
{
|
||||
case FREEZE_LOAD:
|
||||
if (!s)
|
||||
return -1;
|
||||
s->f = *(PADState::freeze*)data;
|
||||
s->pad->Type((PS2WheelTypes)s->f.wheel_type);
|
||||
return sizeof(PADState::freeze);
|
||||
case FREEZE_SAVE:
|
||||
if (!s)
|
||||
return -1;
|
||||
*(PADState::freeze*)data = s->f;
|
||||
return sizeof(PADState::freeze);
|
||||
case FREEZE_SIZE:
|
||||
|
@ -647,7 +653,7 @@ namespace usb_pad
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---- Rock Band drum kit ----
|
||||
|
|
|
@ -100,6 +100,25 @@ namespace usb_pad
|
|||
static void Initialize();
|
||||
};
|
||||
|
||||
class SeamicDevice
|
||||
{
|
||||
public:
|
||||
virtual ~SeamicDevice() {}
|
||||
static USBDevice* CreateDevice(int port);
|
||||
static const TCHAR* Name()
|
||||
{
|
||||
return TEXT("Sega Seamic");
|
||||
}
|
||||
static const char* TypeName()
|
||||
{
|
||||
return "seamic";
|
||||
}
|
||||
static std::list<std::string> ListAPIs();
|
||||
static const TCHAR* LongAPIName(const std::string& name);
|
||||
static int Configure(int port, const std::string& api, void* data);
|
||||
static int Freeze(int mode, USBDevice* dev, void* data);
|
||||
};
|
||||
|
||||
// Most likely as seen on https://github.com/matlo/GIMX
|
||||
#define CMD_DOWNLOAD 0x00
|
||||
#define CMD_DOWNLOAD_AND_PLAY 0x01
|
||||
|
@ -148,12 +167,15 @@ namespace usb_pad
|
|||
WT_GT_FORCE, //formula gp
|
||||
WT_ROCKBAND1_DRUMKIT,
|
||||
WT_BUZZ_CONTROLLER,
|
||||
WT_SEGA_SEAMIC,
|
||||
};
|
||||
|
||||
inline int range_max(PS2WheelTypes type)
|
||||
{
|
||||
if (type == WT_DRIVING_FORCE_PRO || type == WT_DRIVING_FORCE_PRO_1102)
|
||||
return 0x3FFF;
|
||||
if (type == WT_SEGA_SEAMIC)
|
||||
return 255;
|
||||
return 0x3FF;
|
||||
}
|
||||
|
||||
|
@ -296,7 +318,7 @@ namespace usb_pad
|
|||
virtual void SetSpringForce(const parsed_ff_data& ff) = 0;
|
||||
virtual void SetDamperForce(const parsed_ff_data& ff) = 0;
|
||||
virtual void SetFrictionForce(const parsed_ff_data& ff) = 0;
|
||||
//virtual void SetAutoCenter(int value) = 0;
|
||||
virtual void SetAutoCenter(int value) = 0;
|
||||
//virtual void SetGain(int gain) = 0;
|
||||
virtual void DisableForce(EffectID force) = 0;
|
||||
};
|
||||
|
@ -1083,7 +1105,7 @@ namespace usb_pad
|
|||
0x03, // bmAttributes (Interrupt)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
// 41 bytes
|
||||
// 41 bytes
|
||||
};
|
||||
|
||||
//Wii Rock Band drum kit
|
||||
|
|
|
@ -0,0 +1,467 @@
|
|||
#include "padproxy.h"
|
||||
#include "usb-pad.h"
|
||||
#include "../qemu-usb/desc.h"
|
||||
#include "../usb-mic/usb-mic-singstar.h"
|
||||
|
||||
namespace usb_pad
|
||||
{
|
||||
|
||||
static const USBDescStrings desc_strings = {
|
||||
"",
|
||||
"ASCII CORPORATION",
|
||||
"ASCII Mic/Joy-stick",
|
||||
};
|
||||
|
||||
static const uint8_t dev_descriptor[] = {
|
||||
/* bLength */ 0x12, //(18)
|
||||
/* bDescriptorType */ 0x01, //(1)
|
||||
/* bcdUSB */ WBVAL(0x0110),
|
||||
/* bDeviceClass */ 0x00, //(0)
|
||||
/* bDeviceSubClass */ 0x00, //(0)
|
||||
/* bDeviceProtocol */ 0x00, //(0)
|
||||
/* bMaxPacketSize0 */ 0x08, //(8)
|
||||
/* idVendor */ WBVAL(0x0B49),
|
||||
/* idProduct */ WBVAL(0x0644),
|
||||
/* bcdDevice */ WBVAL(0x0100),
|
||||
/* iManufacturer */ 0x01,
|
||||
/* iProduct */ 0x02,
|
||||
/* iSerialNumber */ 0x00,
|
||||
/* bNumConfigurations */ 0x01,
|
||||
};
|
||||
|
||||
static const uint8_t hid_report_descriptor[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x04, // Usage (Joystick)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0xA1, 0x00, // Collection (Physical)
|
||||
0x95, 0x03, // Report Count (3)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x66, 0x00, 0x00, // Unit (None)
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x75, 0x04, // Report Size (4)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x07, // Logical Maximum (7)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||
0x66, 0x14, 0x00, // Unit (System: English Rotation, Length: Centimeter)
|
||||
0x09, 0x39, // Usage (Hat switch)
|
||||
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
|
||||
0x95, 0x0A, // Report Count (10)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x45, 0x01, // Physical Maximum (1)
|
||||
0x66, 0x00, 0x00, // Unit (None)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x0A, // Usage Maximum (0x0A)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x05, 0x08, // Usage Page (LEDs)
|
||||
0x19, 0x01, // Usage Minimum (Num Lock)
|
||||
0x29, 0x08, // Usage Maximum (Do Not Disturb)
|
||||
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
||||
0xC0, // End Collection
|
||||
0xC0, // End Collection
|
||||
|
||||
// 98 bytes
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x86, 0x00, // wTotalLength 134
|
||||
0x03, // bNumInterfaces 3
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration (String Index)
|
||||
0x80, // bmAttributes
|
||||
0x31, // bMaxPower 98mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x00, // bNumEndpoints 0
|
||||
0x01, // bInterfaceClass (Audio)
|
||||
0x01, // bInterfaceSubClass (Audio Control)
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x09, // bLength
|
||||
0x24, // bDescriptorType (See Next Line)
|
||||
0x01, // bDescriptorSubtype (CS_INTERFACE -> HEADER)
|
||||
0x00, 0x01, // bcdADC 1.00
|
||||
WBVAL(38), // wTotalLength 38
|
||||
0x01, // binCollection 0x01
|
||||
0x01, // baInterfaceNr 1
|
||||
|
||||
0x0C, // bLength
|
||||
0x24, // bDescriptorType (See Next Line)
|
||||
0x02, // bDescriptorSubtype (CS_INTERFACE -> INPUT_TERMINAL)
|
||||
0x01, // bTerminalID
|
||||
0x01, 0x02, // wTerminalType (Microphone)
|
||||
0x02, // bAssocTerminal
|
||||
0x01, // bNrChannels 1
|
||||
0x00, 0x00, // wChannelConfig
|
||||
0x00, // iChannelNames
|
||||
0x00, // iTerminal
|
||||
|
||||
0x09, // bLength
|
||||
0x24, // bDescriptorType (See Next Line)
|
||||
0x03, // bDescriptorSubtype (CS_INTERFACE -> OUTPUT_TERMINAL)
|
||||
0x02, // bTerminalID
|
||||
0x01, 0x01, // wTerminalType (USB Streaming)
|
||||
0x01, // bAssocTerminal
|
||||
0x03, // bSourceID
|
||||
0x00, // iTerminal
|
||||
|
||||
0x08, // bLength
|
||||
0x24, // bDescriptorType (See Next Line)
|
||||
0x06, // bDescriptorSubtype (CS_INTERFACE -> FEATURE_UNIT)
|
||||
0x03, // bUnitID
|
||||
0x01, // bSourceID
|
||||
0x01, // bControlSize 1
|
||||
0x03, 0x00, // bmaControls[0] (Mute,Volume)
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x01, // bInterfaceNumber 1
|
||||
0x00, // bAlternateSetting
|
||||
0x00, // bNumEndpoints 0
|
||||
0x01, // bInterfaceClass (Audio)
|
||||
0x02, // bInterfaceSubClass (Audio Streaming)
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x01, // bInterfaceNumber 1
|
||||
0x01, // bAlternateSetting
|
||||
0x01, // bNumEndpoints 1
|
||||
0x01, // bInterfaceClass (Audio)
|
||||
0x02, // bInterfaceSubClass (Audio Streaming)
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x07, // bLength
|
||||
0x24, // bDescriptorType (See Next Line)
|
||||
0x01, // bDescriptorSubtype (CS_INTERFACE -> AS_GENERAL)
|
||||
0x02, // bTerminalLink
|
||||
0x01, // bDelay 1
|
||||
0x01, 0x00, // wFormatTag (PCM)
|
||||
|
||||
0x0E, // bLength
|
||||
0x24, // bDescriptorType (See Next Line)
|
||||
0x02, // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
|
||||
0x01, // bFormatType 1
|
||||
0x01, // bNrChannels (Mono)
|
||||
0x02, // bSubFrameSize 2
|
||||
0x10, // bBitResolution 16
|
||||
0x02, // bSamFreqType 2
|
||||
B3VAL(8000), // tSamFreq[1] 8000 Hz
|
||||
B3VAL(11025), // tSamFreq[2] 11025 Hz
|
||||
|
||||
0x07, // bLength
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType (See Next Line)
|
||||
USB_ENDPOINT_IN(1), // bEndpointAddress (IN/D2H)
|
||||
0x01, // bmAttributes (Isochronous, No Sync, Data EP)
|
||||
WBVAL(100), // wMaxPacketSize 100
|
||||
0x01, // bInterval 1 (unit depends on device speed)
|
||||
|
||||
0x07, // bLength
|
||||
0x25, // bDescriptorType (See Next Line)
|
||||
0x01, // bDescriptorSubtype (CS_ENDPOINT -> EP_GENERAL)
|
||||
0x01, // bmAttributes (Sampling Freq Control)
|
||||
0x00, // bLockDelayUnits
|
||||
0x00, 0x00, // wLockDelay 0
|
||||
|
||||
USB_INTERFACE_DESC_SIZE, // bLength
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType (Interface)
|
||||
0x02, // bInterfaceNumber 2
|
||||
0x00, // bAlternateSetting
|
||||
0x01, // bNumEndpoints 1
|
||||
USB_CLASS_HID, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x09, // bLength
|
||||
USB_DT_HID, // bDescriptorType (HID)
|
||||
WBVAL(0x0100), // bcdHID 1.00
|
||||
0x00, // bCountryCode
|
||||
0x01, // bNumDescriptors
|
||||
USB_DT_REPORT, // bDescriptorType[0] (HID)
|
||||
WBVAL(98), // wDescriptorLength[0] 98
|
||||
|
||||
0x07, // bLength
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType (Endpoint)
|
||||
USB_ENDPOINT_IN(2), // bEndpointAddress (IN/D2H)
|
||||
USB_ENDPOINT_TYPE_INTERRUPT, // bmAttributes (Interrupt)
|
||||
WBVAL(8), // wMaxPacketSize 8
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
|
||||
// 134 bytes
|
||||
};
|
||||
|
||||
std::list<std::string> SeamicDevice::ListAPIs()
|
||||
{
|
||||
return RegisterPad::instance().Names();
|
||||
}
|
||||
|
||||
const TCHAR* SeamicDevice::LongAPIName(const std::string& name)
|
||||
{
|
||||
auto proxy = RegisterPad::instance().Proxy(name);
|
||||
if (proxy)
|
||||
return proxy->Name();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
typedef struct SeamicState
|
||||
{
|
||||
USBDevice dev;
|
||||
USBDesc desc;
|
||||
USBDescDevice desc_dev;
|
||||
USBDevice* mic;
|
||||
Pad* pad;
|
||||
uint8_t port;
|
||||
struct freeze
|
||||
{
|
||||
int nothing;
|
||||
} f;
|
||||
} SeamicState;
|
||||
|
||||
static void pad_handle_data(USBDevice* dev, USBPacket* p)
|
||||
{
|
||||
SeamicState* s = (SeamicState*)dev;
|
||||
uint8_t data[64];
|
||||
|
||||
int ret = 0;
|
||||
uint8_t devep = p->ep->nr;
|
||||
|
||||
switch (p->pid)
|
||||
{
|
||||
case USB_TOKEN_IN:
|
||||
if (devep == 1 && s->mic)
|
||||
{
|
||||
s->mic->klass.handle_data(s->mic, p);
|
||||
}
|
||||
else if (devep == 2 && s->pad)
|
||||
{
|
||||
ret = s->pad->TokenIn(data, p->iov.size);
|
||||
if (ret > 0)
|
||||
usb_packet_copy(p, data, MIN(ret, sizeof(data)));
|
||||
else
|
||||
p->status = ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case USB_TOKEN_OUT:
|
||||
usb_packet_copy(p, data, MIN(p->iov.size, sizeof(data)));
|
||||
ret = s->pad->TokenOut(data, p->iov.size);
|
||||
break;
|
||||
default:
|
||||
fail:
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pad_handle_reset(USBDevice* dev)
|
||||
{
|
||||
/* XXX: do it */
|
||||
SeamicState* s = (SeamicState*)dev;
|
||||
s->pad->Reset();
|
||||
s->mic->klass.handle_reset(s->mic);
|
||||
return;
|
||||
}
|
||||
|
||||
static void pad_handle_control(USBDevice* dev, USBPacket* p, int request, int value,
|
||||
int index, int length, uint8_t* data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
break;
|
||||
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||
OSDebugOut(TEXT("InterfaceRequest | USB_REQ_GET_DESCRIPTOR 0x%04X\n"), value);
|
||||
switch (value >> 8)
|
||||
{
|
||||
case USB_DT_REPORT:
|
||||
OSDebugOut(TEXT("Sending hid report desc.\n"));
|
||||
ret = sizeof(hid_report_descriptor);
|
||||
memcpy(data, hid_report_descriptor, ret);
|
||||
p->actual_length = ret;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
/* hid specific requests */
|
||||
case SET_REPORT:
|
||||
if (length > 0)
|
||||
{
|
||||
OSDebugOut(TEXT("SET_REPORT: 0x%02X \n"), data[0]);
|
||||
p->actual_length = 0;
|
||||
//p->status = USB_RET_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case SET_IDLE:
|
||||
OSDebugOut(TEXT("SET_IDLE\n"));
|
||||
break;
|
||||
default:
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fail:
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pad_handle_destroy(USBDevice* dev)
|
||||
{
|
||||
SeamicState* s = (SeamicState*)dev;
|
||||
s->mic->klass.unrealize(s->mic);
|
||||
s->mic = nullptr;
|
||||
delete s;
|
||||
}
|
||||
|
||||
static int pad_open(USBDevice* dev)
|
||||
{
|
||||
SeamicState* s = (SeamicState*)dev;
|
||||
if (s)
|
||||
{
|
||||
s->mic->klass.open(s->mic);
|
||||
return s->pad->Open();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pad_close(USBDevice* dev)
|
||||
{
|
||||
SeamicState* s = (SeamicState*)dev;
|
||||
if (s)
|
||||
{
|
||||
s->mic->klass.close(s->mic);
|
||||
s->pad->Close();
|
||||
}
|
||||
}
|
||||
|
||||
USBDevice* SeamicDevice::CreateDevice(int port)
|
||||
{
|
||||
std::string varApi;
|
||||
LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, varApi);
|
||||
PadProxyBase* proxy = RegisterPad::instance().Proxy(varApi);
|
||||
if (!proxy)
|
||||
{
|
||||
SysMessage(TEXT("PAD: Invalid input API.\n"));
|
||||
USB_LOG("usb-pad: %s: Invalid input API.\n", TypeName());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
USB_LOG("usb-pad: creating device '%s' on port %d with %s\n", TypeName(), port, varApi.c_str());
|
||||
|
||||
std::string api;
|
||||
if (!LoadSetting(nullptr, port, usb_mic::SingstarDevice::TypeName(), N_DEVICE_API, api))
|
||||
return nullptr;
|
||||
|
||||
USBDevice* mic = usb_mic::SingstarDevice::CreateDevice(port, api);
|
||||
if (!mic)
|
||||
return nullptr;
|
||||
|
||||
Pad* pad = proxy->CreateObject(port, TypeName());
|
||||
|
||||
if (!pad)
|
||||
return NULL;
|
||||
|
||||
pad->Type(WT_SEGA_SEAMIC);
|
||||
SeamicState* s = new SeamicState();
|
||||
|
||||
s->mic = mic;
|
||||
s->desc.full = &s->desc_dev;
|
||||
s->desc.str = desc_strings;
|
||||
|
||||
if (usb_desc_parse_dev(dev_descriptor, sizeof(dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(config_descriptor, sizeof(config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
|
||||
s->pad = pad;
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.klass.handle_attach = usb_desc_attach;
|
||||
s->dev.klass.handle_reset = pad_handle_reset;
|
||||
s->dev.klass.handle_control = pad_handle_control;
|
||||
s->dev.klass.handle_data = pad_handle_data;
|
||||
s->dev.klass.unrealize = pad_handle_destroy;
|
||||
s->dev.klass.open = pad_open;
|
||||
s->dev.klass.close = pad_close;
|
||||
s->dev.klass.usb_desc = &s->desc;
|
||||
s->dev.klass.product_desc = s->desc.str[2]; //not really used
|
||||
s->port = port;
|
||||
|
||||
usb_desc_init(&s->dev);
|
||||
usb_ep_init(&s->dev);
|
||||
pad_handle_reset((USBDevice*)s);
|
||||
|
||||
return (USBDevice*)s;
|
||||
|
||||
fail:
|
||||
pad_handle_destroy((USBDevice*)s);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int SeamicDevice::Configure(int port, const std::string& api, void* data)
|
||||
{
|
||||
auto proxy = RegisterPad::instance().Proxy(api);
|
||||
if (proxy)
|
||||
return proxy->Configure(port, TypeName(), data);
|
||||
return RESULT_CANCELED;
|
||||
}
|
||||
|
||||
int SeamicDevice::Freeze(int mode, USBDevice* dev, void* data)
|
||||
{
|
||||
return 0;
|
||||
// SeamicState *s = (SeamicState *)dev;
|
||||
// switch (mode)
|
||||
// {
|
||||
// case FREEZE_LOAD:
|
||||
// if (!s) return -1;
|
||||
// s->f = *(SeamicState::freeze *)data;
|
||||
// return sizeof(SeamicState::freeze);
|
||||
// case FREEZE_SAVE:
|
||||
// if (!s) return -1;
|
||||
// return sizeof(SeamicState::freeze);
|
||||
// case FREEZE_SIZE:
|
||||
// return sizeof(SeamicState::freeze);
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// return -1;
|
||||
}
|
||||
|
||||
} // namespace usb_pad
|
Loading…
Reference in New Issue