USB: clang-format

This commit is contained in:
Gauvain 'GovanifY' Roussel-Tarbouriech 2020-11-02 23:42:03 +01:00 committed by refractionpcsx2
parent 56e96a8ff9
commit 0c43fa92e5
121 changed files with 30422 additions and 26655 deletions

View File

@ -26,34 +26,37 @@
#include "shared/shared.h"
#include "deviceproxy.h"
#define PSXCLK 36864000 /* 36.864 Mhz */
#define PSXCLK 36864000 /* 36.864 Mhz */
OHCIState *qemu_ohci = NULL;
USBDevice *usb_device[2] = { NULL };
OHCIState* qemu_ohci = NULL;
USBDevice* usb_device[2] = {NULL};
bool configChanged = false;
Config conf;
char USBfreezeID[] = "USBqemuW01";
typedef struct {
typedef struct
{
char freezeID[11];
s64 cycles;
s64 remaining;
OHCIState t;
struct {
struct
{
DeviceType index;
u32 size;
USBDevice dev;
} device[2];
struct usb_packet {
struct usb_packet
{
USBEndpoint ep; //usb packet endpoint
int dev_index;
int data_size;
} usb_packet;
} USBfreezeData;
u8 *ram = 0;
FILE *usbLog;
u8* ram = 0;
FILE* usbLog;
int64_t usb_frame_time;
int64_t usb_bit_time;
@ -66,11 +69,12 @@ HWND gsWnd = nullptr;
#include "gtk.h"
#include <gdk/gdkx.h>
#include <X11/X.h>
Display *g_GSdsp;
Display* g_GSdsp;
Window g_GSwin;
#endif
Config::Config(): Log(0)
Config::Config()
: Log(0)
{
memset(&WheelType, 0, sizeof(WheelType));
}
@ -78,19 +82,20 @@ Config::Config(): Log(0)
//Simpler to reset and reattach after USBclose/USBopen
void Reset()
{
if(qemu_ohci)
if (qemu_ohci)
ohci_hard_reset(qemu_ohci);
}
void DestroyDevices()
{
for (int i=0; i<2; i++)
for (int i = 0; i < 2; i++)
{
if(qemu_ohci && qemu_ohci->rhport[i].port.dev) {
if (qemu_ohci && qemu_ohci->rhport[i].port.dev)
{
qemu_ohci->rhport[i].port.dev->klass.unrealize(qemu_ohci->rhport[i].port.dev);
qemu_ohci->rhport[i].port.dev = nullptr;
}
else if(usb_device[i])
else if (usb_device[i])
usb_device[i]->klass.unrealize(usb_device[i]);
usb_device[i] = nullptr;
@ -99,7 +104,7 @@ void DestroyDevices()
USBDevice* CreateDevice(DeviceType index, int port)
{
DeviceProxyBase *devProxy;
DeviceProxyBase* devProxy;
USBDevice* device = nullptr;
if (index == DEVTYPE_NONE)
@ -111,22 +116,24 @@ USBDevice* CreateDevice(DeviceType index, int port)
else
SysMessage(TEXT("Device %d: Unknown device type"), 1 - port);
if (!device) {
if (!device)
{
USB_LOG("USBqemu: failed to create device type %d on port %d\n", index, port);
}
return device;
}
//TODO re-do sneaky attach
void USBAttach(int port, USBDevice *dev, bool sneaky = false)
void USBAttach(int port, USBDevice* dev, bool sneaky = false)
{
if (!qemu_ohci) return;
if (!qemu_ohci)
return;
USBDevice *tmp = qemu_ohci->rhport[port].port.dev;
USBDevice* tmp = qemu_ohci->rhport[port].port.dev;
if (tmp)
{
if (!sneaky)
usb_detach (&qemu_ohci->rhport[port].port);
usb_detach(&qemu_ohci->rhport[port].port);
tmp->klass.unrealize(tmp);
}
@ -134,13 +141,13 @@ void USBAttach(int port, USBDevice *dev, bool sneaky = false)
if (dev)
{
dev->attached = true;
usb_attach (&qemu_ohci->rhport[port].port); //.ops->attach(&(qemu_ohci->rhport[port].port));
usb_attach(&qemu_ohci->rhport[port].port); //.ops->attach(&(qemu_ohci->rhport[port].port));
}
}
USBDevice* CreateDevice(const std::string& name, int port)
{
DeviceProxyBase *devProxy;
DeviceProxyBase* devProxy;
USBDevice* device = nullptr;
if (!name.empty())
@ -152,7 +159,8 @@ USBDevice* CreateDevice(const std::string& name, int port)
SysMessage(TEXT("Port %d: Unknown device type"), port);
}
if (!device) {
if (!device)
{
USB_LOG("USBqemu: failed to create device '%s' on port %d\n", name.c_str(), port);
}
return device;
@ -160,17 +168,19 @@ USBDevice* CreateDevice(const std::string& name, int port)
void CreateDevices()
{
if(!qemu_ohci) return; //No USBinit yet ie. called from config. dialog
if (!qemu_ohci)
return; //No USBinit yet ie. called from config. dialog
DestroyDevices();
for (int i=0; i<2; i++)
for (int i = 0; i < 2; i++)
{
usb_device[i] = CreateDevice(conf.Port[i], i);
USBAttach(i, usb_device[i]);
}
}
s32 USBinit() {
s32 USBinit()
{
OSDebugOut(TEXT("USBinit\n"));
RegisterDevice::Register();
@ -178,13 +188,14 @@ s32 USBinit() {
if (conf.Log && !usbLog)
{
usbLog = wfopen(LogDir.c_str(), "wb");// L"wb,ccs=UNICODE");
usbLog = wfopen(LogDir.c_str(), "wb"); // L"wb,ccs=UNICODE");
//if(usbLog) setvbuf(usbLog, NULL, _IONBF, 0);
USB_LOG("USBinit\n");
}
qemu_ohci = ohci_create(0x1f801600,2);
if(!qemu_ohci) return 1;
qemu_ohci = ohci_create(0x1f801600, 2);
if (!qemu_ohci)
return 1;
clocks = 0;
remaining = 0;
@ -192,7 +203,8 @@ s32 USBinit() {
return 0;
}
void USBshutdown() {
void USBshutdown()
{
OSDebugOut(TEXT("USBshutdown\n"));
DestroyDevices();
@ -202,15 +214,17 @@ void USBshutdown() {
ram = 0;
//#ifdef _DEBUG
if (conf.Log && usbLog) {
//#ifdef _DEBUG
if (conf.Log && usbLog)
{
fclose(usbLog);
usbLog = nullptr;
}
//#endif
//#endif
}
s32 USBopen(void *pDsp) {
s32 USBopen(void* pDsp)
{
if (conf.Log && !usbLog)
{
@ -223,31 +237,34 @@ s32 USBopen(void *pDsp) {
#if _WIN32
HWND hWnd=(HWND)pDsp;
HWND hWnd = (HWND)pDsp;
//HWND hWnd=(HWND)((uptr*)pDsp)[0];
if (!IsWindow (hWnd))
if (!IsWindow(hWnd))
hWnd = *(HWND*)hWnd;
if (!IsWindow (hWnd))
if (!IsWindow(hWnd))
hWnd = NULL;
else
{
while (GetWindowLong (hWnd, GWL_STYLE) & WS_CHILD)
hWnd = GetParent (hWnd);
while (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
hWnd = GetParent(hWnd);
}
gsWnd = hWnd;
pDsp = gsWnd;
#else
g_GSdsp = (Display *)((uptr*)pDsp)[0];
g_GSdsp = (Display*)((uptr*)pDsp)[0];
g_GSwin = (Window)((uptr*)pDsp)[1];
OSDebugOut("X11 display %p Xwindow %lu\n", g_GSdsp, g_GSwin);
#endif
try {
try
{
shared::Initialize(pDsp);
} catch (std::runtime_error &e) {
}
catch (std::runtime_error& e)
{
SysMessage(TEXT("%" SFMTs "\n"), e.what());
}
@ -258,75 +275,83 @@ s32 USBopen(void *pDsp) {
}
//TODO Pass pDsp to open probably so dinput can bind to this HWND
if(usb_device[0] && usb_device[0]->klass.open)
usb_device[0]->klass.open(usb_device[0]/*, pDsp*/);
if (usb_device[0] && usb_device[0]->klass.open)
usb_device[0]->klass.open(usb_device[0] /*, pDsp*/);
if(usb_device[1] && usb_device[1]->klass.open)
usb_device[1]->klass.open(usb_device[1]/*, pDsp*/);
if (usb_device[1] && usb_device[1]->klass.open)
usb_device[1]->klass.open(usb_device[1] /*, pDsp*/);
return 0;
}
void USBclose() {
void USBclose()
{
OSDebugOut(TEXT("USBclose\n"));
if(usb_device[0] && usb_device[0]->klass.close)
if (usb_device[0] && usb_device[0]->klass.close)
usb_device[0]->klass.close(usb_device[0]);
if(usb_device[1] && usb_device[1]->klass.close)
if (usb_device[1] && usb_device[1]->klass.close)
usb_device[1]->klass.close(usb_device[1]);
shared::Uninitialize();
}
u8 USBread8(u32 addr) {
u8 USBread8(u32 addr)
{
USB_LOG("* Invalid 8bit read at address %lx\n", addr);
return 0;
}
u16 USBread16(u32 addr) {
u16 USBread16(u32 addr)
{
USB_LOG("* Invalid 16bit read at address %lx\n", addr);
return 0;
}
u32 USBread32(u32 addr) {
u32 USBread32(u32 addr)
{
u32 hard;
hard=ohci_mem_read(qemu_ohci,addr);
hard = ohci_mem_read(qemu_ohci, addr);
USB_LOG("* Known 32bit read at address %lx: %lx\n", addr, hard);
return hard;
}
void USBwrite8(u32 addr, u8 value) {
void USBwrite8(u32 addr, u8 value)
{
USB_LOG("* Invalid 8bit write at address %lx value %x\n", addr, value);
}
void USBwrite16(u32 addr, u16 value) {
void USBwrite16(u32 addr, u16 value)
{
USB_LOG("* Invalid 16bit write at address %lx value %x\n", addr, value);
}
void USBwrite32(u32 addr, u32 value) {
void USBwrite32(u32 addr, u32 value)
{
USB_LOG("* Known 32bit write at address %lx value %lx\n", addr, value);
ohci_mem_write(qemu_ohci,addr,value);
ohci_mem_write(qemu_ohci, addr, value);
}
extern u32 bits;
void USBsetRAM(void *mem) {
void USBsetRAM(void* mem)
{
ram = (u8*)mem;
Reset();
}
s32 USBfreeze(int mode, freezeData *data) {
USBfreezeData usbd = { 0 };
s32 USBfreeze(int mode, freezeData* data)
{
USBfreezeData usbd = {0};
//TODO FREEZE_SIZE mismatch causes loading to fail in PCSX2 beforehand
if (mode == FREEZE_LOAD)
{
if((long unsigned int)data->size < sizeof(USBfreezeData))
if ((long unsigned int)data->size < sizeof(USBfreezeData))
{
SysMessage(TEXT("ERROR: Unable to load freeze data! Got %d bytes, expected >= %d.\n"), data->size, sizeof(USBfreezeData));
return -1;
@ -335,7 +360,7 @@ s32 USBfreeze(int mode, freezeData *data) {
usbd = *(USBfreezeData*)data->data;
usbd.freezeID[10] = 0;
if( strcmp(usbd.freezeID, USBfreezeID) != 0)
if (strcmp(usbd.freezeID, USBfreezeID) != 0)
{
SysMessage(TEXT("ERROR: Unable to load freeze data! Found ID '%") TEXT(SFMTs) TEXT("', expected ID '%") TEXT(SFMTs) TEXT("'.\n"), usbd.freezeID, USBfreezeID);
return -1;
@ -345,7 +370,7 @@ s32 USBfreeze(int mode, freezeData *data) {
//clocks = usbd.cycles;
//remaining = usbd.remaining;
for(uint32_t i=0; i< qemu_ohci->num_ports; i++)
for (uint32_t i = 0; i < qemu_ohci->num_ports; i++)
{
usbd.t.rhport[i].port.opaque = qemu_ohci;
usbd.t.rhport[i].port.ops = qemu_ohci->rhport[i].port.ops;
@ -353,13 +378,13 @@ s32 USBfreeze(int mode, freezeData *data) {
}
*qemu_ohci = usbd.t;
s8 *ptr = data->data + sizeof(USBfreezeData);
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;
RegisterDevice& regInst = RegisterDevice::instance();
for (int i=0; i<2; i++)
for (int i = 0; i < 2; i++)
{
auto index = regInst.Index(conf.Port[i]);
auto proxy = regInst.Device(index);
@ -369,7 +394,7 @@ s32 USBfreeze(int mode, freezeData *data) {
if (usbd.device[i].index != index)
{
index = usbd.device[i].index;
USBDevice *dev = qemu_ohci->rhport[i].port.dev;
USBDevice* dev = qemu_ohci->rhport[i].port.dev;
qemu_ohci->rhport[i].port.dev = nullptr;
if (dev)
@ -387,7 +412,7 @@ s32 USBfreeze(int mode, freezeData *data) {
{
if (proxy->Freeze(FREEZE_SIZE, usb_device[i], nullptr) != (s32)usbd.device[i].size)
{
SysMessage(TEXT("Port %d: device's freeze size doesn't match.\n"), 1+(1-i));
SysMessage(TEXT("Port %d: device's freeze size doesn't match.\n"), 1 + (1 - i));
return -1;
}
@ -409,19 +434,20 @@ s32 USBfreeze(int mode, freezeData *data) {
memcpy(usb_device[i]->setup_buf, tmp.setup_buf, sizeof(tmp.setup_buf));
usb_desc_set_config(usb_device[i], tmp.configuration);
for (int k = 0; k < 16; k++) {
for (int k = 0; k < 16; k++)
{
usb_device[i]->altsetting[k] = tmp.altsetting[k];
usb_desc_set_interface(usb_device[i], k, tmp.altsetting[k]);
}
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);
usb_detach(&qemu_ohci->rhport[i].port);
usb_attach(&qemu_ohci->rhport[i].port);
}
else if (!proxy && index != DEVTYPE_NONE)
{
SysMessage(TEXT("Port %d: unknown device.\nPlugin is probably too old for this save.\n"), 1+(1-i));
SysMessage(TEXT("Port %d: unknown device.\nPlugin is probably too old for this save.\n"), 1 + (1 - i));
return -1;
}
ptr += usbd.device[i].size;
@ -435,10 +461,10 @@ s32 USBfreeze(int mode, freezeData *data) {
if (usb_device[dev_index])
{
USBPacket *p = &qemu_ohci->usb_packet;
USBPacket* p = &qemu_ohci->usb_packet;
p->actual_length = usbd.usb_packet.data_size;
QEMUIOVector *iov = p->combined ? &p->combined->iov : &p->iov;
QEMUIOVector* iov = p->combined ? &p->combined->iov : &p->iov;
iov_from_buf(iov->iov, iov->niov, 0, ptr, p->actual_length);
if (usbd.usb_packet.ep.pid == USB_TOKEN_SETUP)
@ -448,18 +474,16 @@ s32 USBfreeze(int mode, freezeData *data) {
}
else
{
USBEndpoint *eps = nullptr;
USBEndpoint* eps = nullptr;
if (usbd.usb_packet.ep.pid == USB_TOKEN_IN)
eps = usb_device[dev_index]->ep_in;
else //if (usbd.ep.pid == USB_TOKEN_OUT)
eps = usb_device[dev_index]->ep_out;
for (int k = 0; k < USB_MAX_ENDPOINTS; k++) {
for (int k = 0; k < USB_MAX_ENDPOINTS; k++)
{
if (usbd.usb_packet.ep.type == eps[k].type
&& usbd.usb_packet.ep.nr == eps[k].nr
&& usbd.usb_packet.ep.ifnum == eps[k].ifnum
&& usbd.usb_packet.ep.pid == eps[k].pid)
if (usbd.usb_packet.ep.type == eps[k].type && usbd.usb_packet.ep.nr == eps[k].nr && usbd.usb_packet.ep.ifnum == eps[k].ifnum && usbd.usb_packet.ep.pid == eps[k].pid)
{
qemu_ohci->usb_packet.ep = &eps[k];
break;
@ -476,11 +500,11 @@ s32 USBfreeze(int mode, freezeData *data) {
//TODO straight copying of structs can break cross-platform/cross-compiler save states 'cause padding 'n' stuff
else if (mode == FREEZE_SAVE)
{
memset(data->data, 0, data->size);//maybe it already is...
memset(data->data, 0, data->size); //maybe it already is...
RegisterDevice& regInst = RegisterDevice::instance();
usbd.usb_packet.dev_index = -1;
for (int i=0; i<2; i++)
for (int i = 0; i < 2; i++)
{
//TODO check that current created usb device and conf.Port[n] are the same
auto index = regInst.Index(conf.Port[i]);
@ -499,10 +523,10 @@ s32 USBfreeze(int mode, freezeData *data) {
strncpy(usbd.freezeID, USBfreezeID, strlen(usbd.freezeID));
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.iov = {};
usbd.t.usb_packet.ep = nullptr;
for(uint32_t i=0; i< qemu_ohci->num_ports; i++)
for (uint32_t i = 0; i < qemu_ohci->num_ports; i++)
{
usbd.t.rhport[i].port.opaque = nullptr;
usbd.t.rhport[i].port.ops = nullptr;
@ -512,10 +536,10 @@ s32 USBfreeze(int mode, freezeData *data) {
usbd.cycles = clocks;
usbd.remaining = remaining;
s8 *ptr = data->data + sizeof(USBfreezeData);
s8* ptr = data->data + sizeof(USBfreezeData);
// Save the state of the attached devices
for (int i=0; i<2; i++)
for (int i = 0; i < 2; i++)
{
auto proxy = regInst.Device(conf.Port[i]);
if (proxy && usbd.device[i].size)
@ -524,15 +548,15 @@ s32 USBfreeze(int mode, freezeData *data) {
if (usb_device[i])
usbd.device[i].dev = *usb_device[i];
memset (&usbd.device[i].dev.klass, 0, sizeof(USBDeviceClass));
memset(&usbd.device[i].dev.klass, 0, sizeof(USBDeviceClass));
}
ptr += usbd.device[i].size;
}
USBPacket *p = &qemu_ohci->usb_packet;
USBPacket* p = &qemu_ohci->usb_packet;
usbd.usb_packet.data_size = p->actual_length;
QEMUIOVector *iov = p->combined ? &p->combined->iov : &p->iov;
QEMUIOVector* iov = p->combined ? &p->combined->iov : &p->iov;
iov_to_buf(iov->iov, iov->niov, 0, ptr, p->actual_length);
*(USBfreezeData*)data->data = usbd;
@ -541,7 +565,7 @@ s32 USBfreeze(int mode, freezeData *data) {
{
RegisterDevice& regInst = RegisterDevice::instance();
data->size = sizeof(USBfreezeData);
for (int i=0; i<2; i++)
for (int i = 0; i < 2; i++)
{
//TODO check that current created usb device and conf.Port[n] are the same
auto proxy = regInst.Device(conf.Port[i]);
@ -551,8 +575,9 @@ s32 USBfreeze(int mode, freezeData *data) {
}
// PCSX2 queries size before load too, so can't use actual packet length which varies :(
data->size += 8192;// qemu_ohci->usb_packet.actual_length;
if (qemu_ohci->usb_packet.actual_length > 8192) {
data->size += 8192; // qemu_ohci->usb_packet.actual_length;
if (qemu_ohci->usb_packet.actual_length > 8192)
{
fprintf(stderr, "Saving failed! USB packet is larger than 8K, try again later.\n");
return -1;
}
@ -565,12 +590,12 @@ void USBasync(u32 cycles)
{
remaining += cycles;
clocks += remaining;
if(qemu_ohci->eof_timer>0)
if (qemu_ohci->eof_timer > 0)
{
while((uint64_t)remaining>=qemu_ohci->eof_timer)
while ((uint64_t)remaining >= qemu_ohci->eof_timer)
{
remaining-=qemu_ohci->eof_timer;
qemu_ohci->eof_timer=0;
remaining -= qemu_ohci->eof_timer;
qemu_ohci->eof_timer = 0;
ohci_frame_boundary(qemu_ohci);
/*
@ -581,10 +606,10 @@ void USBasync(u32 cycles)
if (!qemu_ohci->eof_timer)
break;
}
if((remaining>0)&&(qemu_ohci->eof_timer>0))
if ((remaining > 0) && (qemu_ohci->eof_timer > 0))
{
s64 m = qemu_ohci->eof_timer;
if(remaining < m)
if (remaining < m)
m = remaining;
qemu_ohci->eof_timer -= m;
remaining -= m;
@ -596,11 +621,11 @@ void USBasync(u32 cycles)
//}
}
int cpu_physical_memory_rw(u32 addr, u8 *buf, size_t len, int is_write)
int cpu_physical_memory_rw(u32 addr, u8* buf, size_t len, int is_write)
{
//OSDebugOut(TEXT("%s addr %08X, len %d\n"), is_write ? TEXT("write") : TEXT("read "), addr, len);
// invalid address, reset and try again
if (addr+len >= 0x200000)
if (addr + len >= 0x200000)
{
OSDebugOut(TEXT("invalid address, soft resetting ohci.\n"));
if (qemu_ohci)
@ -608,10 +633,10 @@ int cpu_physical_memory_rw(u32 addr, u8 *buf, size_t len, int is_write)
return 1;
}
if(is_write)
memcpy(&(ram[addr]),buf,len);
if (is_write)
memcpy(&(ram[addr]), buf, len);
else
memcpy(buf,&(ram[addr]),len);
memcpy(buf, &(ram[addr]), len);
return 0;
}

View File

@ -26,7 +26,7 @@
// ---------------------------------------------------------------------
#define USBdefs
extern u8 *ram;
extern u8* ram;
// ---------------------------------------------------------------------
@ -39,29 +39,28 @@ s32 USBinit();
void USBasync(u32 cycles);
void USBshutdown();
void USBclose();
s32 USBopen(void *pDsp);
s32 USBfreeze(int mode, freezeData *data);
s32 USBopen(void* pDsp);
s32 USBfreeze(int mode, freezeData* data);
u8 USBread8(u32 addr);
u16 USBread16(u32 addr);
u32 USBread32(u32 addr);
void USBwrite8(u32 addr, u8 value);
void USBwrite8(u32 addr, u8 value);
void USBwrite16(u32 addr, u16 value);
void USBwrite32(u32 addr, u32 value);
void USBsetRAM(void *mem);
void USBsetRAM(void* mem);
extern FILE *usbLog;
extern FILE* usbLog;
s64 get_clock();
/* usb-pad-raw.cpp */
#if _WIN32
extern HWND gsWnd;
# if defined(BUILD_RAW)
#if defined(BUILD_RAW)
extern HWND msgWindow;
int InitWindow(HWND);
void UninitWindow();
# endif
#endif
#endif

View File

@ -25,7 +25,8 @@
HINSTANCE hInst;
extern bool configChanged;
void SysMessageA(const char *fmt, ...) {
void SysMessageA(const char* fmt, ...)
{
va_list list;
char tmp[512];
@ -35,7 +36,8 @@ void SysMessageA(const char *fmt, ...) {
MessageBoxA(0, tmp, "Qemu USB Msg", 0);
}
void SysMessageW(const wchar_t *fmt, ...) {
void SysMessageW(const wchar_t* fmt, ...)
{
va_list list;
wchar_t tmp[512];
@ -101,17 +103,19 @@ void PopulateAPIs(HWND hW, int port)
SendDlgItemMessage(hW, port ? IDC_COMBO_API1 : IDC_COMBO_API2, CB_SETCURSEL, sel, 0);
}
BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) {
BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int port;
switch(uMsg) {
switch (uMsg)
{
case WM_INITDIALOG:
SendDlgItemMessageA(hW, IDC_BUILD_DATE, WM_SETTEXT, 0, (LPARAM)__DATE__ " " __TIME__);
LoadConfig();
CheckDlgButton(hW, IDC_LOGGING, conf.Log);
//Selected emulated devices.
SendDlgItemMessageA(hW, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM)"None");
SendDlgItemMessageA(hW, IDC_COMBO2, CB_ADDSTRING, 0, (LPARAM)"None");
SendDlgItemMessageA(hW, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM) "None");
SendDlgItemMessageA(hW, IDC_COMBO2, CB_ADDSTRING, 0, (LPARAM) "None");
{
auto& rd = RegisterDevice::instance();
@ -136,16 +140,16 @@ BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
PopulateAPIs(hW, 1);
}
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE1, CB_ADDSTRING, 0, (LPARAM)"Driving Force");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE1, CB_ADDSTRING, 0, (LPARAM)"Driving Force Pro");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE1, CB_ADDSTRING, 0, (LPARAM)"Driving Force Pro (rev11.02)");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE1, CB_ADDSTRING, 0, (LPARAM)"GT Force");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE1, CB_ADDSTRING, 0, (LPARAM) "Driving Force");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE1, CB_ADDSTRING, 0, (LPARAM) "Driving Force Pro");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE1, CB_ADDSTRING, 0, (LPARAM) "Driving Force Pro (rev11.02)");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE1, CB_ADDSTRING, 0, (LPARAM) "GT Force");
SendDlgItemMessage(hW, IDC_COMBO_WHEEL_TYPE1, CB_SETCURSEL, conf.WheelType[PLAYER_ONE_PORT], 0);
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE2, CB_ADDSTRING, 0, (LPARAM)"Driving Force");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE2, CB_ADDSTRING, 0, (LPARAM)"Driving Force Pro");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE2, CB_ADDSTRING, 0, (LPARAM)"Driving Force Pro (rev11.02)");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE2, CB_ADDSTRING, 0, (LPARAM)"GT Force");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE2, CB_ADDSTRING, 0, (LPARAM) "Driving Force");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE2, CB_ADDSTRING, 0, (LPARAM) "Driving Force Pro");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE2, CB_ADDSTRING, 0, (LPARAM) "Driving Force Pro (rev11.02)");
SendDlgItemMessageA(hW, IDC_COMBO_WHEEL_TYPE2, CB_ADDSTRING, 0, (LPARAM) "GT Force");
SendDlgItemMessage(hW, IDC_COMBO_WHEEL_TYPE2, CB_SETCURSEL, conf.WheelType[PLAYER_TWO_PORT], 0);
return TRUE;
@ -153,73 +157,75 @@ BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_COMMAND:
switch (HIWORD(wParam))
{
case CBN_SELCHANGE:
switch (LOWORD(wParam)) {
case IDC_COMBO_API1:
case IDC_COMBO_API2:
port = (LOWORD(wParam) == IDC_COMBO_API1) ? 1 : 0;
SelChangedAPI(hW, port);
break;
case IDC_COMBO1:
case IDC_COMBO2:
port = (LOWORD(wParam) == IDC_COMBO1) ? 1 : 0;
PopulateAPIs(hW, port);
break;
}
break;
case BN_CLICKED:
switch(LOWORD(wParam)) {
case IDC_CONFIGURE1:
case IDC_CONFIGURE2:
{
LRESULT devtype, apitype;
port = (LOWORD(wParam) == IDC_CONFIGURE1) ? 1 : 0;
devtype = SendDlgItemMessage(hW, port ? IDC_COMBO1 : IDC_COMBO2, CB_GETCURSEL, 0, 0);
apitype = SendDlgItemMessage(hW, port ? IDC_COMBO_API1 : IDC_COMBO_API2, CB_GETCURSEL, 0, 0);
if (devtype > 0)
case CBN_SELCHANGE:
switch (LOWORD(wParam))
{
devtype--;
auto device = RegisterDevice::instance().Device(devtype);
if (device)
case IDC_COMBO_API1:
case IDC_COMBO_API2:
port = (LOWORD(wParam) == IDC_COMBO_API1) ? 1 : 0;
SelChangedAPI(hW, port);
break;
case IDC_COMBO1:
case IDC_COMBO2:
port = (LOWORD(wParam) == IDC_COMBO1) ? 1 : 0;
PopulateAPIs(hW, port);
break;
}
break;
case BN_CLICKED:
switch (LOWORD(wParam))
{
case IDC_CONFIGURE1:
case IDC_CONFIGURE2:
{
auto list = device->ListAPIs();
auto it = list.begin();
std::advance(it, apitype);
if (it == list.end())
break;
std::string api = *it;
Win32Handles handles(hInst, hW);
if (device->Configure(port, api, &handles) == RESULT_FAILED)
SysMessage(TEXT("Some settings may not have been saved!\n"));
}
}
}
break;
case IDCANCEL:
EndDialog(hW, TRUE);
return TRUE;
case IDOK:
conf.Log = IsDlgButtonChecked(hW, IDC_LOGGING);
{
auto& regInst = RegisterDevice::instance();
int i;
//device type
i = SendDlgItemMessage(hW, IDC_COMBO1, CB_GETCURSEL, 0, 0);
conf.Port[1] = regInst.Name(i - 1);
i = SendDlgItemMessage(hW, IDC_COMBO2, CB_GETCURSEL, 0, 0);
conf.Port[0] = regInst.Name(i - 1);
}
//wheel type
conf.WheelType[PLAYER_ONE_PORT] = SendDlgItemMessage(hW, IDC_COMBO_WHEEL_TYPE1, CB_GETCURSEL, 0, 0);
conf.WheelType[PLAYER_TWO_PORT] = SendDlgItemMessage(hW, IDC_COMBO_WHEEL_TYPE2, CB_GETCURSEL, 0, 0);
LRESULT devtype, apitype;
port = (LOWORD(wParam) == IDC_CONFIGURE1) ? 1 : 0;
devtype = SendDlgItemMessage(hW, port ? IDC_COMBO1 : IDC_COMBO2, CB_GETCURSEL, 0, 0);
apitype = SendDlgItemMessage(hW, port ? IDC_COMBO_API1 : IDC_COMBO_API2, CB_GETCURSEL, 0, 0);
SaveConfig();
CreateDevices();
EndDialog(hW, RESULT_OK);
configChanged = true;
return TRUE;
}
if (devtype > 0)
{
devtype--;
auto device = RegisterDevice::instance().Device(devtype);
if (device)
{
auto list = device->ListAPIs();
auto it = list.begin();
std::advance(it, apitype);
if (it == list.end())
break;
std::string api = *it;
Win32Handles handles(hInst, hW);
if (device->Configure(port, api, &handles) == RESULT_FAILED)
SysMessage(TEXT("Some settings may not have been saved!\n"));
}
}
}
break;
case IDCANCEL:
EndDialog(hW, TRUE);
return TRUE;
case IDOK:
conf.Log = IsDlgButtonChecked(hW, IDC_LOGGING);
{
auto& regInst = RegisterDevice::instance();
int i;
//device type
i = SendDlgItemMessage(hW, IDC_COMBO1, CB_GETCURSEL, 0, 0);
conf.Port[1] = regInst.Name(i - 1);
i = SendDlgItemMessage(hW, IDC_COMBO2, CB_GETCURSEL, 0, 0);
conf.Port[0] = regInst.Name(i - 1);
}
//wheel type
conf.WheelType[PLAYER_ONE_PORT] = SendDlgItemMessage(hW, IDC_COMBO_WHEEL_TYPE1, CB_GETCURSEL, 0, 0);
conf.WheelType[PLAYER_TWO_PORT] = SendDlgItemMessage(hW, IDC_COMBO_WHEEL_TYPE2, CB_GETCURSEL, 0, 0);
SaveConfig();
CreateDevices();
EndDialog(hW, RESULT_OK);
configChanged = true;
return TRUE;
}
}
}
@ -227,13 +233,17 @@ BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
EXPORT_C_(BOOL) AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
EXPORT_C_(BOOL)
AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam)) {
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hW, FALSE);
return TRUE;
@ -242,26 +252,30 @@ EXPORT_C_(BOOL) AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) {
return FALSE;
}
void USBconfigure() {
void USBconfigure()
{
ScopedCoreThreadPause paused_core;
RegisterDevice::Register();
DialogBox(hInst,
MAKEINTRESOURCE(IDD_CONFIG),
GetActiveWindow(),
(DLGPROC)ConfigureDlgProc);
RegisterDevice::Register();
DialogBox(hInst,
MAKEINTRESOURCE(IDD_CONFIG),
GetActiveWindow(),
(DLGPROC)ConfigureDlgProc);
paused_core.AllowResume();
}
EXPORT_C_(void) USBabout() {
DialogBox(hInst,
MAKEINTRESOURCE(IDD_ABOUT),
GetActiveWindow(),
(DLGPROC)AboutDlgProc);
EXPORT_C_(void)
USBabout()
{
DialogBox(hInst,
MAKEINTRESOURCE(IDD_ABOUT),
GetActiveWindow(),
(DLGPROC)AboutDlgProc);
}
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved) {
DWORD dwReason,
LPVOID lpReserved)
{
hInst = (HINSTANCE)hModule;
return TRUE;
}

View File

@ -21,24 +21,25 @@ typedef struct Win32Handles
{
HINSTANCE hInst;
HWND hWnd;
Win32Handles(HINSTANCE i, HWND w):
hInst(i),
hWnd(w)
Win32Handles(HINSTANCE i, HWND w)
: hInst(i)
, hWnd(w)
{
}
} Win32Handles;
#define CHECKED_SET_MAX_INT(var, hDlg, nIDDlgItem, bSigned, min, max)\
do {\
/*CheckControlTextIsNumber(GetDlgItem(hDlg, nIDDlgItem), bSigned, 0);*/\
var = GetDlgItemInt(hDlg, nIDDlgItem, NULL, bSigned);\
if (var < min)\
var = min;\
else if (var > max)\
{\
var = max;\
SetDlgItemInt(hDlg, nIDDlgItem, var, bSigned);\
SendMessage(GetDlgItem(hDlg, nIDDlgItem), EM_SETSEL, -2, -2);\
}\
} while (0)
#define CHECKED_SET_MAX_INT(var, hDlg, nIDDlgItem, bSigned, min, max) \
do \
{ \
/*CheckControlTextIsNumber(GetDlgItem(hDlg, nIDDlgItem), bSigned, 0);*/ \
var = GetDlgItemInt(hDlg, nIDDlgItem, NULL, bSigned); \
if (var < min) \
var = min; \
else if (var > max) \
{ \
var = max; \
SetDlgItemInt(hDlg, nIDDlgItem, var, bSigned); \
SendMessage(GetDlgItem(hDlg, nIDDlgItem), EM_SETSEL, -2, -2); \
} \
} while (0)
#endif

View File

@ -2,43 +2,43 @@
// Microsoft Visual C++ generated include file.
// Used by USBlinuz.rc
//
#define IDC_STATIC -1
#define IDC_CONFIGURE1 3
#define IDC_CONFIGURE2 4
#define IDD_CONFDLG 101
#define IDD_CONFIG 101
#define IDD_ABOUT 103
#define IDD_DLGMSD 106
#define IDD_DLGWASAPI 107
#define IDD_DLG_EYETOY 108
#define IDC_NAME 1000
#define IDC_LOGGING 1007
#define IDC_COMBO1 1008
#define IDC_COMBO2 1009
#define IDC_LIST1 1010
#define IDC_COMBO_API1 1010
#define IDC_COMBO3 1010
#define IDC_COMBO_FFB 1011
#define IDC_COMBO_API2 1011
#define IDC_BUTTON1 1012
#define IDC_DFP_PASS 1013
#define IDC_BUILD_DATE 1014
#define IDC_EDIT1 1015
#define IDC_COMBO_WHEEL_TYPE1 1037
#define IDC_COMBO_WHEEL_TYPE2 1038
#define IDC_SLIDER1 1039
#define IDC_BUFFER1 1040
#define IDC_COMBOMICAPI 1041
#define IDC_SLIDER2 1041
#define IDC_BUFFER2 1042
#define IDC_STATIC -1
#define IDC_CONFIGURE1 3
#define IDC_CONFIGURE2 4
#define IDD_CONFDLG 101
#define IDD_CONFIG 101
#define IDD_ABOUT 103
#define IDD_DLGMSD 106
#define IDD_DLGWASAPI 107
#define IDD_DLG_EYETOY 108
#define IDC_NAME 1000
#define IDC_LOGGING 1007
#define IDC_COMBO1 1008
#define IDC_COMBO2 1009
#define IDC_LIST1 1010
#define IDC_COMBO_API1 1010
#define IDC_COMBO3 1010
#define IDC_COMBO_FFB 1011
#define IDC_COMBO_API2 1011
#define IDC_BUTTON1 1012
#define IDC_DFP_PASS 1013
#define IDC_BUILD_DATE 1014
#define IDC_EDIT1 1015
#define IDC_COMBO_WHEEL_TYPE1 1037
#define IDC_COMBO_WHEEL_TYPE2 1038
#define IDC_SLIDER1 1039
#define IDC_BUFFER1 1040
#define IDC_COMBOMICAPI 1041
#define IDC_SLIDER2 1041
#define IDC_BUFFER2 1042
// Next default values for new objects
//
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1042
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1042
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -28,13 +28,13 @@ TSTDSTRING IniPath = TSTDSTRING(TEXT("./inis/")) + iniFile; // default path, jus
TSTDSTRING LogDir;
CIniFile ciniFile;
void USBsetSettingsDir( const char* dir )
void USBsetSettingsDir(const char* dir)
{
IniPath = dir;
IniPath.append(iniFile);
}
void USBsetLogDir( const char* dir )
void USBsetLogDir(const char* dir)
{
LogDir = dir;
}
@ -49,9 +49,10 @@ std::string GetSelectedAPI(const std::pair<int, std::string>& pair)
bool LoadSettingValue(const TSTDSTRING& ini, const TSTDSTRING& section, const TCHAR* param, TSTDSTRING& value)
{
CIniKey *key;
CIniKey* key;
auto sect = ciniFile.GetSection(str_to_wstr(section));
if (sect && (key = sect->GetKey(str_to_wstr(param)))) {
if (sect && (key = sect->GetKey(str_to_wstr(param))))
{
value = wstr_to_str(key->GetValue());
return true;
}
@ -60,14 +61,17 @@ bool LoadSettingValue(const TSTDSTRING& ini, const TSTDSTRING& section, const TC
bool LoadSettingValue(const TSTDSTRING& ini, const TSTDSTRING& section, const TCHAR* param, int32_t& value)
{
CIniKey *key;
CIniKey* key;
auto sect = ciniFile.GetSection(str_to_wstr(section));
if (sect && (key = sect->GetKey(str_to_wstr(param)))) {
try {
if (sect && (key = sect->GetKey(str_to_wstr(param))))
{
try
{
value = std::stoi(key->GetValue());
return true;
}
catch (std::exception& err) {
catch (std::exception& err)
{
OSDebugOut(TEXT("%" SFMTs "\n"), err.what());
}
}
@ -86,7 +90,8 @@ bool SaveSettingValue(const TSTDSTRING& ini, const TSTDSTRING& section, const TC
return true;
}
void SaveConfig() {
void SaveConfig()
{
SaveSetting("MAIN", "log", conf.Log);
@ -105,8 +110,10 @@ void SaveConfig() {
OSDebugOut(_T("ciniFile.Save: %d [%s]\n"), ret, IniPath.c_str());
}
void LoadConfig() {
std::cerr << "USB load config\n" << std::endl;
void LoadConfig()
{
std::cerr << "USB load config\n"
<< std::endl;
ciniFile.Load(str_to_wstr(IniPath));
LoadSetting("MAIN", "log", conf.Log);
@ -119,7 +126,7 @@ void LoadConfig() {
auto& instance = RegisterDevice::instance();
for (int i=0; i<2; i++)
for (int i = 0; i < 2; i++)
{
std::string api;
LoadSetting(nullptr, i, conf.Port[i], N_DEVICE_API, api);
@ -141,7 +148,7 @@ void LoadConfig() {
OSDebugOut(_T("API OK\n"));
}
if(api.size())
if (api.size())
changedAPIs[std::make_pair(i, conf.Port[i])] = api;
}
}
@ -149,7 +156,8 @@ void LoadConfig() {
void ClearSection(const TCHAR* section)
{
auto s = ciniFile.GetSection(str_to_wstr(section));
if (s) {
if (s)
{
s->RemoveAllKeys();
}
}

View File

@ -23,43 +23,44 @@
#include "platcompat.h"
#define RESULT_CANCELED 0
#define RESULT_OK 1
#define RESULT_FAILED 2
#define RESULT_OK 1
#define RESULT_FAILED 2
// freeze modes:
#define FREEZE_LOAD 0
#define FREEZE_SAVE 1
#define FREEZE_SIZE 2
#define FREEZE_LOAD 0
#define FREEZE_SAVE 1
#define FREEZE_SIZE 2
// Device-level config related defines
#define S_DEVICE_API TEXT("Device API")
#define S_WHEEL_TYPE TEXT("Wheel type")
#define S_DEVICE_PORT0 TEXT("Port 0")
#define S_DEVICE_PORT1 TEXT("Port 1")
#define S_CONFIG_PATH TEXT("Path")
#define S_DEVICE_API TEXT("Device API")
#define S_WHEEL_TYPE TEXT("Wheel type")
#define S_DEVICE_PORT0 TEXT("Port 0")
#define S_DEVICE_PORT1 TEXT("Port 1")
#define S_CONFIG_PATH TEXT("Path")
#define N_DEVICE_API TEXT("device_api")
#define N_DEVICES TEXT("devices")
#define N_DEVICE TEXT("device")
#define N_WHEEL_PT TEXT("wheel_pt")
#define N_DEVICE_PORT0 TEXT("port_0")
#define N_DEVICE_PORT1 TEXT("port_1")
#define N_DEVICE_PORT "port"
#define N_WHEEL_TYPE0 TEXT("wheel_type_0")
#define N_WHEEL_TYPE1 TEXT("wheel_type_1")
#define N_WHEEL_TYPE TEXT("wheel_type")
#define N_CONFIG_PATH TEXT("path")
#define N_DEVICE_API TEXT("device_api")
#define N_DEVICES TEXT("devices")
#define N_DEVICE TEXT("device")
#define N_WHEEL_PT TEXT("wheel_pt")
#define N_DEVICE_PORT0 TEXT("port_0")
#define N_DEVICE_PORT1 TEXT("port_1")
#define N_DEVICE_PORT "port"
#define N_WHEEL_TYPE0 TEXT("wheel_type_0")
#define N_WHEEL_TYPE1 TEXT("wheel_type_1")
#define N_WHEEL_TYPE TEXT("wheel_type")
#define N_CONFIG_PATH TEXT("path")
#define PLAYER_TWO_PORT 0
#define PLAYER_ONE_PORT 1
#define USB_PORT PLAYER_ONE_PORT
struct Config {
int Log;
std::string Port[2];
int WheelType[2];
struct Config
{
int Log;
std::string Port[2];
int WheelType[2];
Config();
Config();
};
extern Config conf;
@ -84,10 +85,10 @@ bool LoadSettingValue(const TSTDSTRING& ini, const TSTDSTRING& section, const TC
bool SaveSettingValue(const TSTDSTRING& ini, const TSTDSTRING& section, const TCHAR* param, const std::string& value);
#endif
void USBsetSettingsDir( const char* dir );
void USBsetLogDir( const char* dir );
void USBsetSettingsDir(const char* dir);
void USBsetLogDir(const char* dir);
template<typename Type>
template <typename Type>
bool LoadSetting(const char* dev_type, int port, const std::string& key, const TCHAR* name, Type& var)
{
bool ret = false;
@ -115,7 +116,7 @@ bool LoadSetting(const char* dev_type, int port, const std::string& key, const T
return ret;
}
template<typename Type>
template <typename Type>
bool LoadSetting(const TCHAR* section, const TCHAR* key, Type& var)
{
bool ret = false;
@ -142,7 +143,7 @@ bool LoadSetting(const TCHAR* section, const TCHAR* key, Type& var)
* ...
*
* */
template<typename Type>
template <typename Type>
bool SaveSetting(const char* dev_type, int port, const std::string& key, const TCHAR* name, const Type var)
{
bool ret = false;
@ -168,7 +169,7 @@ bool SaveSetting(const char* dev_type, int port, const std::string& key, const T
return ret;
}
template<typename Type>
template <typename Type>
bool SaveSetting(const TCHAR* section, const TCHAR* key, const Type var)
{
bool ret = false;

View File

@ -19,7 +19,7 @@
#include "usb-hid/hidproxy.h"
#include "usb-eyetoy/videodeviceproxy.h"
RegisterDevice *RegisterDevice::registerDevice = nullptr;
RegisterDevice* RegisterDevice::registerDevice = nullptr;
void RegisterAPIs()
{

View File

@ -46,30 +46,37 @@ enum DeviceType
DEVTYPE_EYETOY,
};
struct SelectDeviceName {
struct SelectDeviceName
{
template <typename S>
std::string operator()(const std::pair<const DeviceType, S> &x) const { return x.second->TypeName(); }
std::string operator()(const std::pair<const DeviceType, S>& x) const
{
return x.second->TypeName();
}
};
class DeviceError : public std::runtime_error
{
public:
DeviceError(const char* msg) : std::runtime_error(msg) {}
public:
DeviceError(const char* msg)
: std::runtime_error(msg)
{
}
virtual ~DeviceError() {}
};
class DeviceProxyBase
{
public:
DeviceProxyBase() {};
public:
DeviceProxyBase(){};
virtual ~DeviceProxyBase() {}
virtual USBDevice* CreateDevice(int port) = 0;
virtual const TCHAR* Name() const = 0;
virtual const char* TypeName() const = 0;
virtual int Configure(int port, const std::string& api, void *data) = 0;
virtual int Configure(int port, const std::string& api, void* data) = 0;
virtual std::list<std::string> ListAPIs() = 0;
virtual const TCHAR* LongAPIName(const std::string& name) = 0;
virtual int Freeze(int mode, USBDevice *dev, void *data) = 0;
virtual int Freeze(int mode, USBDevice* dev, void* data) = 0;
virtual bool IsValidAPI(const std::string& api)
{
@ -84,7 +91,7 @@ class DeviceProxyBase
template <class T>
class DeviceProxy : public DeviceProxyBase
{
public:
public:
DeviceProxy() {}
virtual ~DeviceProxy()
{
@ -102,7 +109,7 @@ class DeviceProxy : public DeviceProxyBase
{
return T::TypeName();
}
virtual int Configure(int port, const std::string& api, void *data)
virtual int Configure(int port, const std::string& api, void* data)
{
return T::Configure(port, api, data);
}
@ -114,7 +121,7 @@ class DeviceProxy : public DeviceProxyBase
{
return T::LongAPIName(name);
}
virtual int Freeze(int mode, USBDevice *dev, void *data)
virtual int Freeze(int mode, USBDevice* dev, void* data)
{
return T::Freeze(mode, dev, data);
}
@ -126,14 +133,19 @@ class RegisterProxy
RegisterProxy(const RegisterProxy&) = delete;
RegisterProxy() {}
public:
typedef std::map<std::string, std::unique_ptr<T> > RegisterProxyMap;
static RegisterProxy& instance() {
public:
typedef std::map<std::string, std::unique_ptr<T>> RegisterProxyMap;
static RegisterProxy& instance()
{
static RegisterProxy registerProxy;
return registerProxy;
}
virtual ~RegisterProxy() { Clear(); OSDebugOut("%p\n", this); }
virtual ~RegisterProxy()
{
Clear();
OSDebugOut("%p\n", this);
}
void Clear()
{
@ -182,11 +194,12 @@ class RegisterDevice
{
RegisterDevice(const RegisterDevice&) = delete;
RegisterDevice() {}
static RegisterDevice *registerDevice;
static RegisterDevice* registerDevice;
public:
typedef std::map<DeviceType, std::unique_ptr<DeviceProxyBase> > RegisterDeviceMap;
static RegisterDevice& instance() {
public:
typedef std::map<DeviceType, std::unique_ptr<DeviceProxyBase>> RegisterDeviceMap;
static RegisterDevice& instance()
{
if (!registerDevice)
registerDevice = new RegisterDevice();
return *registerDevice;
@ -210,11 +223,10 @@ class RegisterDevice
return k.second;
return nullptr;*/
auto proxy = std::find_if(registerDeviceMap.begin(),
registerDeviceMap.end(),
[&name](const RegisterDeviceMap::value_type& val) -> bool
{
return val.second->TypeName() == name;
});
registerDeviceMap.end(),
[&name](const RegisterDeviceMap::value_type& val) -> bool {
return val.second->TypeName() == name;
});
if (proxy != registerDeviceMap.end())
return proxy->second.get();
return nullptr;
@ -232,11 +244,10 @@ class RegisterDevice
DeviceType Index(const std::string& name)
{
auto proxy = std::find_if(registerDeviceMap.begin(),
registerDeviceMap.end(),
[&name](RegisterDeviceMap::value_type& val) -> bool
{
return val.second->TypeName() == name;
});
registerDeviceMap.end(),
[&name](RegisterDeviceMap::value_type& val) -> bool {
return val.second->TypeName() == name;
});
if (proxy != registerDeviceMap.end())
return proxy->first;
return DEVTYPE_NONE;
@ -266,7 +277,7 @@ class RegisterDevice
return registerDeviceMap;
}
private:
private:
RegisterDeviceMap registerDeviceMap;
};

View File

@ -15,4 +15,3 @@
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include <gtk/gtk.h>

View File

@ -16,9 +16,13 @@
#ifndef HELPERS_H
#define HELPERS_H
struct SelectKey {
struct SelectKey
{
template <typename F, typename S>
F operator()(const std::pair<const F, S> &x) const { return x.first; }
F operator()(const std::pair<const F, S>& x) const
{
return x.first;
}
};
#endif

View File

@ -14,69 +14,581 @@
*/
#include "icon_buzz_24.h"
const unsigned char icon_buzz_24[] {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xa6, 0xf5,
0xfd, 0xff, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xfd,
0xfd, 0xff, 0xfd, 0xf6, 0xa6, 0x39, 0x00, 0x00, 0x00,
0x00, 0x00, 0x50, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xd6, 0x50, 0x00, 0x00, 0x00, 0x1e, 0xce,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xce, 0x1e, 0x00, 0x00, 0x8b, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8b, 0x00,
0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x5e, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x5e, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x5e, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x5e, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11,
0x00, 0x8b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x8b, 0x00, 0x00, 0x1e, 0xce,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xce, 0x1e, 0x00, 0x00, 0x00, 0x50, 0xd6, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0x50, 0x00, 0x00,
0x00, 0x00, 0x00, 0x39, 0xa6, 0xf0, 0xfd, 0xff, 0xfe,
0xfe, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xfd,
0xf0, 0xa6, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
const unsigned char icon_buzz_24[]{
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x39,
0xa6,
0xf5,
0xfd,
0xff,
0xfd,
0xfe,
0xfe,
0xff,
0xff,
0xff,
0xfd,
0xfd,
0xff,
0xfd,
0xf6,
0xa6,
0x39,
0x00,
0x00,
0x00,
0x00,
0x00,
0x50,
0xd6,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xd6,
0x50,
0x00,
0x00,
0x00,
0x1e,
0xce,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xce,
0x1e,
0x00,
0x00,
0x8b,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0x8b,
0x00,
0x11,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0x11,
0x5e,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0x5e,
0xe4,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xe4,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xe4,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xe4,
0x5e,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0x5e,
0x11,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0x11,
0x00,
0x8b,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0x8b,
0x00,
0x00,
0x1e,
0xce,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xce,
0x1e,
0x00,
0x00,
0x00,
0x50,
0xd6,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xd6,
0x50,
0x00,
0x00,
0x00,
0x00,
0x00,
0x39,
0xa6,
0xf0,
0xfd,
0xff,
0xfe,
0xfe,
0xff,
0xff,
0xff,
0xff,
0xfe,
0xfe,
0xff,
0xfd,
0xf0,
0xa6,
0x39,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
};

View File

@ -25,18 +25,18 @@
// #define VERBOSE_FUNCTION_ACTUALFILE
// #define VERBOSE_WARNING_ACTUALFILE
extern int IsActualFile(const char *filename);
extern void ActualFileDelete(const char *filename);
extern void ActualFileRename(const char *origname, const char *newname);
extern int IsActualFile(const char* filename);
extern void ActualFileDelete(const char* filename);
extern void ActualFileRename(const char* origname, const char* newname);
extern ACTUALHANDLE ActualFileOpenForRead(const char *filename);
extern ACTUALHANDLE ActualFileOpenForRead(const char* filename);
extern off64_t ActualFileSize(ACTUALHANDLE handle);
extern int ActualFileSeek(ACTUALHANDLE handle, off64_t position);
extern int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer);
extern int ActualFileRead(ACTUALHANDLE handle, int bytes, char* buffer);
extern void ActualFileClose(ACTUALHANDLE handle);
extern ACTUALHANDLE ActualFileOpenForWrite(const char *filename);
extern int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer);
extern ACTUALHANDLE ActualFileOpenForWrite(const char* filename);
extern int ActualFileWrite(ACTUALHANDLE handle, int bytes, char* buffer);
#endif /* ACTUALFILE_H */

View File

@ -45,14 +45,14 @@ struct SettingsCB
gboolean run_msg_dialog(gpointer data)
{
GtkWidget *dialog = (GtkWidget *)data;
gtk_widget_show_all (dialog);
gtk_dialog_run (GTK_DIALOG(dialog));
gtk_widget_destroy (dialog);
GtkWidget* dialog = (GtkWidget*)data;
gtk_widget_show_all(dialog);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return FALSE;
}
static void wheeltypeChanged (GtkComboBox *widget, gpointer data)
static void wheeltypeChanged(GtkComboBox* widget, gpointer data)
{
gint idx = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
//if(data)
@ -64,13 +64,13 @@ static void wheeltypeChanged (GtkComboBox *widget, gpointer data)
}
}
static void populateApiWidget(SettingsCB *settingsCB, const std::string& device)
static void populateApiWidget(SettingsCB* settingsCB, const std::string& device)
{
gtk_list_store_clear (GTK_LIST_STORE (gtk_combo_box_get_model (settingsCB->combo)));
gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(settingsCB->combo)));
auto dev = RegisterDevice::instance().Device( device );
auto dev = RegisterDevice::instance().Device(device);
int port = 1 - settingsCB->player;
GtkComboBox *widget = settingsCB->combo;
GtkComboBox* widget = settingsCB->combo;
if (dev)
{
std::string api;
@ -88,22 +88,22 @@ static void populateApiWidget(SettingsCB *settingsCB, const std::string& device)
OSDebugOut("Current api: %s\n", api.c_str());
settingsCB->api = api;
int i = 0;
for(auto& it : dev->ListAPIs())
for (auto& it : dev->ListAPIs())
{
auto name = dev->LongAPIName(it);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), name);
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(widget), name);
if (api.size() && api == it)
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), i);
gtk_combo_box_set_active(GTK_COMBO_BOX(widget), i);
else
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0);
i++;
}
}
}
static void deviceChanged (GtkComboBox *widget, gpointer data)
static void deviceChanged(GtkComboBox* widget, gpointer data)
{
SettingsCB *settingsCB = (SettingsCB *)data;
SettingsCB* settingsCB = (SettingsCB*)data;
gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
int player = settingsCB->player;
std::string s;
@ -114,7 +114,7 @@ static void deviceChanged (GtkComboBox *widget, gpointer data)
settingsCB->device = s;
populateApiWidget(settingsCB, s);
if(player == 0)
if (player == 0)
conf.Port[1] = s;
else
conf.Port[0] = s;
@ -122,15 +122,15 @@ static void deviceChanged (GtkComboBox *widget, gpointer data)
OSDebugOut("Selected player %d idx: %d [%s]\n", player, active, s.c_str());
}
static void apiChanged (GtkComboBox *widget, gpointer data)
static void apiChanged(GtkComboBox* widget, gpointer data)
{
SettingsCB *settingsCB = (SettingsCB *)data;
SettingsCB* settingsCB = (SettingsCB*)data;
int player = settingsCB->player;
gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
int port = 1 - player;
auto& name = settingsCB->device;
auto dev = RegisterDevice::instance().Device( name );
auto dev = RegisterDevice::instance().Device(name);
if (dev)
{
auto apis = dev->ListAPIs();
@ -152,130 +152,131 @@ static void apiChanged (GtkComboBox *widget, gpointer data)
}
}
static void configureApi (GtkWidget *widget, gpointer data)
static void configureApi(GtkWidget* widget, gpointer data)
{
SettingsCB *settingsCB = (SettingsCB *)data;
SettingsCB* settingsCB = (SettingsCB*)data;
int player = settingsCB->player;
int port = 1 - player;
auto& name = settingsCB->device;
auto& api = settingsCB->api;
auto dev = RegisterDevice::instance().Device( name );
auto dev = RegisterDevice::instance().Device(name);
OSDebugOut("configure api %s [%s] for player %d\n", api.c_str(), name.c_str(), player);
if (dev)
{
GtkWidget *dlg = GTK_WIDGET (g_object_get_data (G_OBJECT(widget), "dlg"));
GtkWidget* dlg = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "dlg"));
int res = dev->Configure(port, api, dlg);
OSDebugOut("Configure returned %d\n", res);
}
}
GtkWidget *new_combobox(const char* label, GtkWidget *vbox)
GtkWidget* new_combobox(const char* label, GtkWidget* vbox)
{
GtkWidget *ro_label, *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);
rs_hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), rs_hbox, FALSE, TRUE, 0);
rs_label = gtk_label_new (label);
gtk_box_pack_start (GTK_BOX (rs_hbox), rs_label, FALSE, TRUE, 5);
gtk_label_set_justify (GTK_LABEL (rs_label), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment (GTK_MISC (rs_label), 1, 0.5);
rs_label = gtk_label_new(label);
gtk_box_pack_start(GTK_BOX(rs_hbox), rs_label, FALSE, TRUE, 5);
gtk_label_set_justify(GTK_LABEL(rs_label), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment(GTK_MISC(rs_label), 1, 0.5);
rs_cb = gtk_combo_box_text_new ();
gtk_box_pack_start (GTK_BOX (rs_hbox), rs_cb, TRUE, TRUE, 5);
rs_cb = gtk_combo_box_text_new();
gtk_box_pack_start(GTK_BOX(rs_hbox), rs_cb, TRUE, TRUE, 5);
return rs_cb;
}
static GtkWidget* new_frame(const char *label, GtkWidget *box)
static GtkWidget* new_frame(const char* label, GtkWidget* box)
{
GtkWidget *ro_frame = gtk_frame_new (NULL);
gtk_box_pack_start (GTK_BOX (box), ro_frame, TRUE, FALSE, 0);
GtkWidget* ro_frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(box), ro_frame, TRUE, FALSE, 0);
GtkWidget *ro_label = gtk_label_new (label);
gtk_frame_set_label_widget (GTK_FRAME (ro_frame), ro_label);
gtk_label_set_use_markup (GTK_LABEL (ro_label), TRUE);
GtkWidget* ro_label = gtk_label_new(label);
gtk_frame_set_label_widget(GTK_FRAME(ro_frame), ro_label);
gtk_label_set_use_markup(GTK_LABEL(ro_label), TRUE);
GtkWidget *vbox = gtk_vbox_new (FALSE, 5);
gtk_container_add (GTK_CONTAINER (ro_frame), vbox);
GtkWidget* vbox = gtk_vbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(ro_frame), vbox);
return vbox;
}
void USBconfigure() {
ScopedCoreThreadPause paused_core;
void USBconfigure()
{
ScopedCoreThreadPause paused_core;
RegisterDevice::Register();
LoadConfig();
void * that = NULL;
void* that = NULL;
SettingsCB settingsCB[2];
settingsCB[0].player = 0;
settingsCB[1].player = 1;
const char* wt[] = {"Driving Force", "Driving Force Pro", "Driving Force Pro (rev11.02)", "GT Force"};
const char *players[] = {"Player 1:", "Player 2:"};
const char* players[] = {"Player 1:", "Player 2:"};
GtkWidget *rs_cb, *vbox;
uint32_t idx = 0, sel_idx = 0;
// Create the dialog window
GtkWidget *dlg = gtk_dialog_new_with_buttons (
GtkWidget* dlg = gtk_dialog_new_with_buttons(
"Qemu USB Settings", NULL, GTK_DIALOG_MODAL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (dlg), TRUE);
GtkWidget *dlg_area_box = gtk_dialog_get_content_area (GTK_DIALOG (dlg));
GtkWidget *main_vbox = gtk_vbox_new (FALSE, 5);
gtk_container_add (GTK_CONTAINER (dlg_area_box), main_vbox);
gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
gtk_window_set_resizable(GTK_WINDOW(dlg), TRUE);
GtkWidget* dlg_area_box = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
GtkWidget* main_vbox = gtk_vbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(dlg_area_box), main_vbox);
/*** Device type ***/
vbox = new_frame("Select device type:", main_vbox);
std::string devs[2] = { conf.Port[1], conf.Port[0] };
std::string devs[2] = {conf.Port[1], conf.Port[0]};
/*** Devices' Comboboxes ***/
for(int ply = 0; ply < 2; ply++)
for (int ply = 0; ply < 2; ply++)
{
settingsCB[ply].device = devs[ply];
rs_cb = new_combobox(players[ply], vbox);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (rs_cb), "None");
gtk_combo_box_set_active (GTK_COMBO_BOX (rs_cb), 0);
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rs_cb), "None");
gtk_combo_box_set_active(GTK_COMBO_BOX(rs_cb), 0);
auto devices = RegisterDevice::instance().Names();
int idx = 0, selected = 0;
for(auto& device : devices)
for (auto& device : devices)
{
auto deviceProxy = RegisterDevice::instance().Device(device);
auto name = deviceProxy->Name();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (rs_cb), name );
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rs_cb), name);
idx++;
if (devs[ply] == device)
gtk_combo_box_set_active (GTK_COMBO_BOX (rs_cb), idx);
gtk_combo_box_set_active(GTK_COMBO_BOX(rs_cb), idx);
}
g_signal_connect (G_OBJECT (rs_cb), "changed", G_CALLBACK (deviceChanged), (gpointer)&settingsCB[ply]);
g_signal_connect(G_OBJECT(rs_cb), "changed", G_CALLBACK(deviceChanged), (gpointer)&settingsCB[ply]);
}
/*** APIs ***/
vbox = new_frame("Select device API:", main_vbox);
/*** API Comboboxes ***/
for(int ply = 0; ply < 2; ply++)
for (int ply = 0; ply < 2; ply++)
{
rs_cb = new_combobox (players[ply], vbox);
settingsCB[ply].combo = GTK_COMBO_BOX (rs_cb);
rs_cb = new_combobox(players[ply], vbox);
settingsCB[ply].combo = GTK_COMBO_BOX(rs_cb);
//gtk_combo_box_set_active (GTK_COMBO_BOX (rs_cb), sel_idx);
g_signal_connect (G_OBJECT (rs_cb), "changed", G_CALLBACK (apiChanged), (gpointer)&settingsCB[ply]);
g_signal_connect(G_OBJECT(rs_cb), "changed", G_CALLBACK(apiChanged), (gpointer)&settingsCB[ply]);
GtkWidget *hbox = gtk_widget_get_parent (rs_cb);
GtkWidget *button = gtk_button_new_with_label ("Configure");
gtk_button_set_image(GTK_BUTTON (button), gtk_image_new_from_icon_name ("gtk-preferences", GTK_ICON_SIZE_BUTTON));
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 5);
GtkWidget* hbox = gtk_widget_get_parent(rs_cb);
GtkWidget* button = gtk_button_new_with_label("Configure");
gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_icon_name("gtk-preferences", GTK_ICON_SIZE_BUTTON));
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
g_signal_connect (button, "clicked", G_CALLBACK (configureApi), (gpointer)&settingsCB[ply]);
g_object_set_data (G_OBJECT (button), "dlg", dlg);
g_signal_connect(button, "clicked", G_CALLBACK(configureApi), (gpointer)&settingsCB[ply]);
g_object_set_data(G_OBJECT(button), "dlg", dlg);
populateApiWidget(&settingsCB[ply], devs[ply]);
}
@ -283,41 +284,42 @@ void USBconfigure() {
/** Wheel type **/
vbox = new_frame("Emulated wheel model:", main_vbox);
for(int ply = 0; ply < 2; ply++)
for (int ply = 0; ply < 2; ply++)
{
int port = 1 - ply;
rs_cb = new_combobox (players[ply], vbox);
rs_cb = new_combobox(players[ply], vbox);
sel_idx = 0;
for (int i = 0; i < countof(wt); i++)
{
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (rs_cb), wt[i]);
if(conf.WheelType[port] == i)
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rs_cb), wt[i]);
if (conf.WheelType[port] == i)
sel_idx = i;
}
gtk_combo_box_set_active (GTK_COMBO_BOX (rs_cb), sel_idx);
g_signal_connect (G_OBJECT (rs_cb), "changed", G_CALLBACK (wheeltypeChanged), reinterpret_cast<gpointer> (port));
gtk_combo_box_set_active(GTK_COMBO_BOX(rs_cb), sel_idx);
g_signal_connect(G_OBJECT(rs_cb), "changed", G_CALLBACK(wheeltypeChanged), reinterpret_cast<gpointer>(port));
}
gtk_widget_show_all (dlg);
gtk_widget_show_all(dlg);
// Modal loop
gint result = gtk_dialog_run (GTK_DIALOG (dlg));
gtk_widget_destroy (dlg);
gint result = gtk_dialog_run(GTK_DIALOG(dlg));
gtk_widget_destroy(dlg);
// Wait for all gtk events to be consumed ...
while (gtk_events_pending ())
gtk_main_iteration_do (FALSE);
while (gtk_events_pending())
gtk_main_iteration_do(FALSE);
if (result == GTK_RESPONSE_OK)
{
SaveConfig();
configChanged = true;
}
// ClearAPIs();
// ClearAPIs();
paused_core.AllowResume();
}
void CALLBACK USBabout() {
void CALLBACK USBabout()
{
}

View File

@ -21,7 +21,7 @@
#include "config.h"
void SysMessage_stderr(const char *fmt, ...)
void SysMessage_stderr(const char* fmt, ...)
{
va_list arglist;

View File

@ -46,14 +46,14 @@
#if __cplusplus
extern "C" {
#endif
extern int INISaveString(const char *file, const char *section, const char *keyword, const char *value);
extern int INILoadString(const char *file, const char *section, const char *keyword, char *buffer);
extern int INISaveString(const char* file, const char* section, const char* keyword, const char* value);
extern int INILoadString(const char* file, const char* section, const char* keyword, char* buffer);
extern int INISaveUInt(const char *file, const char *section, const char *keyword, unsigned int value);
extern int INILoadUInt(const char *file, const char *section, const char *keyword, unsigned int *buffer);
extern int INISaveUInt(const char* file, const char* section, const char* keyword, unsigned int value);
extern int INILoadUInt(const char* file, const char* section, const char* keyword, unsigned int* buffer);
// NULL in the keyword below removes the whole section.
extern int INIRemove(const char *file, const char *section, const char *keyword);
extern int INIRemove(const char* file, const char* section, const char* keyword);
#if __cplusplus
}

View File

@ -15,7 +15,8 @@
#include "osdebugout.h"
std::wostream& operator<<(std::wostream& os, const std::string& s) {
std::wostream& operator<<(std::wostream& os, const std::string& s)
{
std::wstring ws;
ws.assign(s.begin(), s.end());
return os << ws;
@ -23,9 +24,9 @@ std::wostream& operator<<(std::wostream& os, const std::string& s) {
#ifdef _WIN32
static int rateLimit = 0;
void _OSDebugOut(const TCHAR *psz_fmt, ...)
void _OSDebugOut(const TCHAR* psz_fmt, ...)
{
if(rateLimit > 0 && rateLimit < 100)
if (rateLimit > 0 && rateLimit < 100)
{
rateLimit++;
return;

View File

@ -25,29 +25,65 @@ void __Log(const char* fmt, ...);
#ifdef _WIN32
#include <vector>
void _OSDebugOut(const TCHAR *psz_fmt, ...);
void _OSDebugOut(const TCHAR* psz_fmt, ...);
std::wostream& operator<<(std::wostream& os, const std::string& s);
#ifdef _DEBUG
#define OSDebugOut(psz_fmt, ...) _OSDebugOut(TEXT("[USBqemu] [%" SFMTs "]:%d\t") psz_fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define OSDebugOut_noprfx(psz_fmt, ...) _OSDebugOut(TEXT(psz_fmt), ##__VA_ARGS__)
#define OSDebugOutStream_noprfx(psz_str) do{ TSTDSTRINGSTREAM ss; ss << psz_str; _OSDebugOut(_T("%s\n"), ss.str().c_str()); }while(0)
#define OSDebugOutStream_noprfx(psz_str) \
do \
{ \
TSTDSTRINGSTREAM ss; \
ss << psz_str; \
_OSDebugOut(_T("%s\n"), ss.str().c_str()); \
} while (0)
#else
#define OSDebugOut(psz_fmt, ...) do{}while(0)
#define OSDebugOut_noprfx(psz_fmt, ...) do{}while(0)
#define OSDebugOutStream_noprfx(str) do{}while(0)
#define OSDebugOut(psz_fmt, ...) \
do \
{ \
} while (0)
#define OSDebugOut_noprfx(psz_fmt, ...) \
do \
{ \
} while (0)
#define OSDebugOutStream_noprfx(str) \
do \
{ \
} while (0)
#endif
#else //_WIN32
#ifdef _DEBUG
#define OSDebugOut(psz_fmt, ...) do{ fprintf(stderr, "[USBqemu] [%s]:%d\t" psz_fmt, __func__, __LINE__, ##__VA_ARGS__); }while(0)
#define OSDebugOut_noprfx(psz_fmt, ...) do{ fprintf(stderr, psz_fmt, ##__VA_ARGS__); }while(0)
#define OSDebugOutStream_noprfx(str) do{ std::cerr << str << std::endl; }while(0)
#define OSDebugOut(psz_fmt, ...) \
do \
{ \
fprintf(stderr, "[USBqemu] [%s]:%d\t" psz_fmt, __func__, __LINE__, ##__VA_ARGS__); \
} while (0)
#define OSDebugOut_noprfx(psz_fmt, ...) \
do \
{ \
fprintf(stderr, psz_fmt, ##__VA_ARGS__); \
} while (0)
#define OSDebugOutStream_noprfx(str) \
do \
{ \
std::cerr << str << std::endl; \
} while (0)
#else
#define OSDebugOut(psz_fmt, ...) do{}while(0)
#define OSDebugOut_noprfx(psz_fmt, ...) do{}while(0)
#define OSDebugOutStream_noprfx(str) do{}while(0)
#define OSDebugOut(psz_fmt, ...) \
do \
{ \
} while (0)
#define OSDebugOut_noprfx(psz_fmt, ...) \
do \
{ \
} while (0)
#define OSDebugOutStream_noprfx(str) \
do \
{ \
} while (0)
#endif
#endif //_WIN32

View File

@ -26,16 +26,16 @@
#endif
#ifdef _WIN32
# define CALLBACK __stdcall
#define CALLBACK __stdcall
#else
# define CALLBACK __attribute__((stdcall))
#define CALLBACK __attribute__((stdcall))
#endif
#ifndef EXPORT_C_
#ifdef _MSC_VER
#define EXPORT_C_(type) extern "C" type CALLBACK
#else
#define EXPORT_C_(type) extern "C" __attribute__((stdcall,externally_visible,visibility("default"))) type
#define EXPORT_C_(type) extern "C" __attribute__((stdcall, externally_visible, visibility("default"))) type
//#define EXPORT_C_(type) extern "C" __attribute__((stdcall,visibility("default"))) type
#endif
#endif
@ -61,7 +61,7 @@ typedef SSIZE_T ssize_t;
#define __builtin_constant_p(p) false
void SysMessageW(const wchar_t *fmt, ...);
void SysMessageW(const wchar_t* fmt, ...);
#define SysMessage SysMessageW
#ifndef _T
@ -85,7 +85,7 @@ void SysMessageW(const wchar_t *fmt, ...);
#define TSTDSTRINGSTREAM std::stringstream
#define TSTDTOSTRING std::to_string
void SysMessage(const char *fmt, ...);
void SysMessage(const char* fmt, ...);
#endif //_WIN32
@ -96,22 +96,20 @@ void SysMessage(const char *fmt, ...);
template <size_t size>
errno_t mbstowcs_s(
size_t *pReturnValue,
size_t* pReturnValue,
wchar_t (&wcstr)[size],
const char *mbstr,
size_t count
)
const char* mbstr,
size_t count)
{
return mbstowcs_s(pReturnValue, wcstr, size, mbstr, count);
}
template <size_t size>
errno_t wcstombs_s(
size_t *pReturnValue,
size_t* pReturnValue,
char (&mbstr)[size],
const wchar_t *wcstr,
size_t count
)
const wchar_t* wcstr,
size_t count)
{
return wcstombs_s(pReturnValue, mbstr, size, wcstr, count);
}
@ -127,20 +125,20 @@ errno_t wcstombs_s(
template <class T, std::size_t N>
constexpr std::size_t countof(const T (&)[N]) noexcept
{
return N;
return N;
}
template <class T>
constexpr std::size_t countof(const T N)
{
return N.size();
return N.size();
}
//TODO Idk, used only in desc.h and struct USBDescriptor should be already packed anyway
#if defined(_WIN32) && !defined(__MINGW32__)
#define PACK(def,name) __pragma( pack(push, 1) ) def name __pragma( pack(pop) )
#define PACK(def, name) __pragma(pack(push, 1)) def name __pragma(pack(pop))
#elif defined(__clang__)
#define PACK(def,name) def __attribute__((packed)) name
#define PACK(def, name) def __attribute__((packed)) name
#else
#define PACK(def,name) def __attribute__((gcc_struct, packed)) name
#define PACK(def, name) def __attribute__((gcc_struct, packed)) name
#endif

View File

@ -17,9 +17,9 @@
//TODO Maybe too much inheritance?
class ProxyBase
{
public:
public:
ProxyBase() {}
virtual ~ProxyBase() {}
virtual const TCHAR* Name() const = 0;
virtual int Configure(int port, const char* dev_type, void *data) = 0;
virtual int Configure(int port, const char* dev_type, void* data) = 0;
};

View File

@ -25,76 +25,79 @@
/* Number of Downstream Ports on the root hub. */
#define OHCI_MAX_PORTS 15 // status regs from 0x0c54 but usb snooping
// reg is at 0x0c80, so only 11 ports?
#define OHCI_MAX_PORTS 15 // status regs from 0x0c54 but usb snooping \
// reg is at 0x0c80, so only 11 ports?
extern int64_t usb_frame_time;
extern int64_t usb_bit_time;
typedef struct OHCIPort {
USBPort port;
uint32_t ctrl;
typedef struct OHCIPort
{
USBPort port;
uint32_t ctrl;
} OHCIPort;
typedef uint32_t target_phys_addr_t;
typedef struct OHCIState {
target_phys_addr_t mem_base;
int mem;
uint32_t num_ports;
typedef struct OHCIState
{
target_phys_addr_t mem_base;
int mem;
uint32_t num_ports;
uint64_t eof_timer;
int64_t sof_time;
uint64_t eof_timer;
int64_t sof_time;
/* OHCI state */
/* Control partition */
uint32_t ctl, status;
uint32_t intr_status;
uint32_t intr;
/* OHCI state */
/* Control partition */
uint32_t ctl, status;
uint32_t intr_status;
uint32_t intr;
/* memory pointer partition */
uint32_t hcca;
uint32_t ctrl_head, ctrl_cur;
uint32_t bulk_head, bulk_cur;
uint32_t per_cur;
uint32_t done;
int32_t done_count;
/* memory pointer partition */
uint32_t hcca;
uint32_t ctrl_head, ctrl_cur;
uint32_t bulk_head, bulk_cur;
uint32_t per_cur;
uint32_t done;
int32_t done_count;
/* Frame counter partition */
uint32_t fsmps:15;
uint32_t fit:1;
uint32_t fi:14;
uint32_t frt:1;
uint16_t frame_number;
uint16_t padding;
uint32_t pstart;
uint32_t lst;
/* Frame counter partition */
uint32_t fsmps : 15;
uint32_t fit : 1;
uint32_t fi : 14;
uint32_t frt : 1;
uint16_t frame_number;
uint16_t padding;
uint32_t pstart;
uint32_t lst;
/* Root Hub partition */
uint32_t rhdesc_a, rhdesc_b;
uint32_t rhstatus;
OHCIPort rhport[OHCI_MAX_PORTS];
/* Active packets. */
uint32_t old_ctl;
USBPacket usb_packet;
uint8_t usb_buf[8192];
uint32_t async_td;
bool async_complete;
/* Root Hub partition */
uint32_t rhdesc_a, rhdesc_b;
uint32_t rhstatus;
OHCIPort rhport[OHCI_MAX_PORTS];
/* Active packets. */
uint32_t old_ctl;
USBPacket usb_packet;
uint8_t usb_buf[8192];
uint32_t async_td;
bool async_complete;
} OHCIState;
/* Host Controller Communications Area */
struct ohci_hcca {
uint32_t intr[32];
uint16_t frame, pad;
uint32_t done;
struct ohci_hcca
{
uint32_t intr[32];
uint16_t frame, pad;
uint32_t done;
};
// No offsetof in C++.
#ifndef offsetof
#define offsetof_(x,z) (intptr_t(&((x)->z)) - intptr_t(x))
#define offsetof(x,z) offsetof_((x*)0,z)
#define offsetof_(x, z) (intptr_t(&((x)->z)) - intptr_t(x))
#define offsetof(x, z) offsetof_((x*)0, z)
#endif
//ISO C++ forbids declaration of typeof with no type
@ -103,200 +106,204 @@ struct ohci_hcca {
const typeof(((type *) 0)->member) *__mptr = (ptr); \
(type *) ((char *) __mptr - offsetof(type, member));})
*/
#define CONTAINER_OF(p, type, field) ((type*) ((char*)p - ((ptrdiff_t)&((type*)0)->field)))
#define CONTAINER_OF(p, type, field) ((type*)((char*)p - ((ptrdiff_t) & ((type*)0)->field)))
#define HCCA_WRITEBACK_OFFSET 128 //offsetof(struct ohci_hcca, frame)
#define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */
#define HCCA_WRITEBACK_OFFSET 128 //offsetof(struct ohci_hcca, frame)
#define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */
#define ED_WBACK_OFFSET 8 //offsetof(struct ohci_ed, head)
#define ED_WBACK_SIZE 4
#define ED_WBACK_SIZE 4
/* Bitfields for the first word of an Endpoint Descriptor. */
#define OHCI_ED_FA_SHIFT 0 //device address
#define OHCI_ED_FA_MASK (0x7f<<OHCI_ED_FA_SHIFT)
#define OHCI_ED_EN_SHIFT 7 //endpoint number
#define OHCI_ED_EN_MASK (0xf<<OHCI_ED_EN_SHIFT)
#define OHCI_ED_D_SHIFT 11 //direction
#define OHCI_ED_D_MASK (3<<OHCI_ED_D_SHIFT)
#define OHCI_ED_S (1<<13) //speed 0 - full, 1 - low
#define OHCI_ED_K (1<<14) //skip ED if 1
#define OHCI_ED_F (1<<15) //format 0 - inter, bulk or setup, 1 - isoch
#define OHCI_ED_FA_SHIFT 0 //device address
#define OHCI_ED_FA_MASK (0x7f << OHCI_ED_FA_SHIFT)
#define OHCI_ED_EN_SHIFT 7 //endpoint number
#define OHCI_ED_EN_MASK (0xf << OHCI_ED_EN_SHIFT)
#define OHCI_ED_D_SHIFT 11 //direction
#define OHCI_ED_D_MASK (3 << OHCI_ED_D_SHIFT)
#define OHCI_ED_S (1 << 13) //speed 0 - full, 1 - low
#define OHCI_ED_K (1 << 14) //skip ED if 1
#define OHCI_ED_F (1 << 15) //format 0 - inter, bulk or setup, 1 - isoch
//#define OHCI_ED_MPS_SHIFT 7
//#define OHCI_ED_MPS_MASK (0xf<<OHCI_ED_FA_SHIFT)
#define OHCI_ED_MPS_SHIFT 16 //max packet size
#define OHCI_ED_MPS_MASK (0x7ff<<OHCI_ED_MPS_SHIFT)
#define OHCI_ED_MPS_MASK (0x7ff << OHCI_ED_MPS_SHIFT)
/* Flags in the head field of an Endpoint Descriptor. */
#define OHCI_ED_H 1 //halted
#define OHCI_ED_C 2
#define OHCI_ED_H 1 //halted
#define OHCI_ED_C 2
/* Bitfields for the first word of a Transfer Descriptor. */
#define OHCI_TD_R (1<<18)
#define OHCI_TD_DP_SHIFT 19
#define OHCI_TD_DP_MASK (3<<OHCI_TD_DP_SHIFT)
#define OHCI_TD_DI_SHIFT 21
#define OHCI_TD_DI_MASK (7<<OHCI_TD_DI_SHIFT)
#define OHCI_TD_T0 (1<<24)
#define OHCI_TD_T1 (1<<24)
#define OHCI_TD_EC_SHIFT 26
#define OHCI_TD_EC_MASK (3<<OHCI_TD_EC_SHIFT)
#define OHCI_TD_CC_SHIFT 28
#define OHCI_TD_CC_MASK (0xf<<OHCI_TD_CC_SHIFT)
#define OHCI_TD_R (1 << 18)
#define OHCI_TD_DP_SHIFT 19
#define OHCI_TD_DP_MASK (3 << OHCI_TD_DP_SHIFT)
#define OHCI_TD_DI_SHIFT 21
#define OHCI_TD_DI_MASK (7 << OHCI_TD_DI_SHIFT)
#define OHCI_TD_T0 (1 << 24)
#define OHCI_TD_T1 (1 << 24)
#define OHCI_TD_EC_SHIFT 26
#define OHCI_TD_EC_MASK (3 << OHCI_TD_EC_SHIFT)
#define OHCI_TD_CC_SHIFT 28
#define OHCI_TD_CC_MASK (0xf << OHCI_TD_CC_SHIFT)
/* Bitfields for the first word of an Isochronous Transfer Descriptor. */
/* CC & DI - same as in the General Transfer Descriptor */
#define OHCI_TD_SF_SHIFT 0
#define OHCI_TD_SF_MASK (0xffff<<OHCI_TD_SF_SHIFT)
#define OHCI_TD_FC_SHIFT 24
#define OHCI_TD_FC_MASK (7<<OHCI_TD_FC_SHIFT)
#define OHCI_TD_SF_SHIFT 0
#define OHCI_TD_SF_MASK (0xffff << OHCI_TD_SF_SHIFT)
#define OHCI_TD_FC_SHIFT 24
#define OHCI_TD_FC_MASK (7 << OHCI_TD_FC_SHIFT)
/* Isochronous Transfer Descriptor - Offset / PacketStatusWord */
#define OHCI_TD_PSW_CC_SHIFT 12
#define OHCI_TD_PSW_CC_MASK (0xf<<OHCI_TD_PSW_CC_SHIFT)
#define OHCI_TD_PSW_CC_MASK (0xf << OHCI_TD_PSW_CC_SHIFT)
#define OHCI_TD_PSW_SIZE_SHIFT 0
#define OHCI_TD_PSW_SIZE_MASK (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
#define OHCI_TD_PSW_SIZE_MASK (0xfff << OHCI_TD_PSW_SIZE_SHIFT)
#define OHCI_PAGE_MASK 0xfffff000
#define OHCI_OFFSET_MASK 0xfff
#define OHCI_PAGE_MASK 0xfffff000
#define OHCI_OFFSET_MASK 0xfff
#define OHCI_DPTR_MASK 0xfffffff0
#define OHCI_DPTR_MASK 0xfffffff0
#define OHCI_BM(val, field) \
(((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
(((val)&OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
#define OHCI_SET_BM(val, field, newval) do { \
val &= ~OHCI_##field##_MASK; \
val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
} while(0)
#define OHCI_SET_BM(val, field, newval) \
do \
{ \
val &= ~OHCI_##field##_MASK; \
val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
} while (0)
/* endpoint descriptor */
struct ohci_ed {
uint32_t flags;
uint32_t tail;
uint32_t head;
uint32_t next;
struct ohci_ed
{
uint32_t flags;
uint32_t tail;
uint32_t head;
uint32_t next;
};
/* General transfer descriptor */
struct ohci_td {
uint32_t flags;
uint32_t cbp;
uint32_t next;
uint32_t be;
struct ohci_td
{
uint32_t flags;
uint32_t cbp;
uint32_t next;
uint32_t be;
};
/* Isochronous transfer descriptor */
struct ohci_iso_td {
uint32_t flags;
uint32_t bp;
uint32_t next;
uint32_t be;
uint16_t offset[8];
struct ohci_iso_td
{
uint32_t flags;
uint32_t bp;
uint32_t next;
uint32_t be;
uint16_t offset[8];
};
#define USB_HZ 12000000
#define USB_HZ 12000000
/* OHCI Local stuff */
#define OHCI_CTL_CBSR ((1<<0)|(1<<1))
#define OHCI_CTL_PLE (1<<2)
#define OHCI_CTL_IE (1<<3)
#define OHCI_CTL_CLE (1<<4)
#define OHCI_CTL_BLE (1<<5)
#define OHCI_CTL_HCFS ((1<<6)|(1<<7))
#define OHCI_USB_RESET 0x00
#define OHCI_USB_RESUME 0x40
#define OHCI_USB_OPERATIONAL 0x80
#define OHCI_USB_SUSPEND 0xc0
#define OHCI_CTL_IR (1<<8)
#define OHCI_CTL_RWC (1<<9)
#define OHCI_CTL_RWE (1<<10)
#define OHCI_CTL_CBSR ((1 << 0) | (1 << 1))
#define OHCI_CTL_PLE (1 << 2)
#define OHCI_CTL_IE (1 << 3)
#define OHCI_CTL_CLE (1 << 4)
#define OHCI_CTL_BLE (1 << 5)
#define OHCI_CTL_HCFS ((1 << 6) | (1 << 7))
#define OHCI_USB_RESET 0x00
#define OHCI_USB_RESUME 0x40
#define OHCI_USB_OPERATIONAL 0x80
#define OHCI_USB_SUSPEND 0xc0
#define OHCI_CTL_IR (1 << 8)
#define OHCI_CTL_RWC (1 << 9)
#define OHCI_CTL_RWE (1 << 10)
#define OHCI_STATUS_HCR (1<<0)
#define OHCI_STATUS_CLF (1<<1)
#define OHCI_STATUS_BLF (1<<2)
#define OHCI_STATUS_OCR (1<<3)
#define OHCI_STATUS_SOC ((1<<6)|(1<<7)) //TODO LSI has SOC at bits 16,17?
#define OHCI_STATUS_HCR (1 << 0)
#define OHCI_STATUS_CLF (1 << 1)
#define OHCI_STATUS_BLF (1 << 2)
#define OHCI_STATUS_OCR (1 << 3)
#define OHCI_STATUS_SOC ((1 << 6) | (1 << 7)) //TODO LSI has SOC at bits 16,17?
#define OHCI_INTR_SO (1U<<0) /* Scheduling overrun */
#define OHCI_INTR_WD (1U<<1) /* HcDoneHead writeback */
#define OHCI_INTR_SF (1U<<2) /* Start of frame */
#define OHCI_INTR_RD (1U<<3) /* Resume detect */
#define OHCI_INTR_UE (1U<<4) /* Unrecoverable error */
#define OHCI_INTR_FNO (1U<<5) /* Frame number overflow */
#define OHCI_INTR_RHSC (1U<<6) /* Root hub status change */
#define OHCI_INTR_OC (1U<<30) /* Ownership change */
#define OHCI_INTR_MIE (1U<<31) /* Master Interrupt Enable */
#define OHCI_INTR_SO (1U << 0) /* Scheduling overrun */
#define OHCI_INTR_WD (1U << 1) /* HcDoneHead writeback */
#define OHCI_INTR_SF (1U << 2) /* Start of frame */
#define OHCI_INTR_RD (1U << 3) /* Resume detect */
#define OHCI_INTR_UE (1U << 4) /* Unrecoverable error */
#define OHCI_INTR_FNO (1U << 5) /* Frame number overflow */
#define OHCI_INTR_RHSC (1U << 6) /* Root hub status change */
#define OHCI_INTR_OC (1U << 30) /* Ownership change */
#define OHCI_INTR_MIE (1U << 31) /* Master Interrupt Enable */
#define OHCI_HCCA_SIZE 0x100
#define OHCI_HCCA_MASK 0xffffff00
#define OHCI_HCCA_SIZE 0x100
#define OHCI_HCCA_MASK 0xffffff00
#define OHCI_EDPTR_MASK 0xfffffff0
#define OHCI_EDPTR_MASK 0xfffffff0
#define OHCI_FMI_FI 0x00003fff
#define OHCI_FMI_FSMPS 0xffff0000
#define OHCI_FMI_FIT 0x80000000
#define OHCI_FMI_FI 0x00003fff
#define OHCI_FMI_FSMPS 0xffff0000
#define OHCI_FMI_FIT 0x80000000
#define OHCI_FR_RT (1U<<31)
#define OHCI_FR_RT (1U << 31)
#define OHCI_LS_THRESH 0x628
#define OHCI_LS_THRESH 0x628
#define OHCI_RHA_RW_MASK 0x00000000 /* Mask of supported features. */
#define OHCI_RHA_PSM (1<<8)
#define OHCI_RHA_NPS (1<<9)
#define OHCI_RHA_DT (1<<10)
#define OHCI_RHA_OCPM (1<<11)
#define OHCI_RHA_NOCP (1<<12)
#define OHCI_RHA_POTPGT_MASK 0xff000000
#define OHCI_RHA_RW_MASK 0x00000000 /* Mask of supported features. */
#define OHCI_RHA_PSM (1 << 8)
#define OHCI_RHA_NPS (1 << 9)
#define OHCI_RHA_DT (1 << 10)
#define OHCI_RHA_OCPM (1 << 11)
#define OHCI_RHA_NOCP (1 << 12)
#define OHCI_RHA_POTPGT_MASK 0xff000000
#define OHCI_RHS_LPS (1U<<0)
#define OHCI_RHS_OCI (1U<<1)
#define OHCI_RHS_DRWE (1U<<15)
#define OHCI_RHS_LPSC (1U<<16)
#define OHCI_RHS_OCIC (1U<<17)
#define OHCI_RHS_CRWE (1U<<31)
#define OHCI_RHS_LPS (1U << 0)
#define OHCI_RHS_OCI (1U << 1)
#define OHCI_RHS_DRWE (1U << 15)
#define OHCI_RHS_LPSC (1U << 16)
#define OHCI_RHS_OCIC (1U << 17)
#define OHCI_RHS_CRWE (1U << 31)
#define OHCI_PORT_CCS (1<<0)
#define OHCI_PORT_PES (1<<1)
#define OHCI_PORT_PSS (1<<2)
#define OHCI_PORT_POCI (1<<3)
#define OHCI_PORT_PRS (1<<4)
#define OHCI_PORT_PPS (1<<8)
#define OHCI_PORT_LSDA (1<<9)
#define OHCI_PORT_CSC (1<<16)
#define OHCI_PORT_PESC (1<<17)
#define OHCI_PORT_PSSC (1<<18)
#define OHCI_PORT_OCIC (1<<19)
#define OHCI_PORT_PRSC (1<<20)
#define OHCI_PORT_WTC (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
|OHCI_PORT_OCIC|OHCI_PORT_PRSC)
#define OHCI_PORT_CCS (1 << 0)
#define OHCI_PORT_PES (1 << 1)
#define OHCI_PORT_PSS (1 << 2)
#define OHCI_PORT_POCI (1 << 3)
#define OHCI_PORT_PRS (1 << 4)
#define OHCI_PORT_PPS (1 << 8)
#define OHCI_PORT_LSDA (1 << 9)
#define OHCI_PORT_CSC (1 << 16)
#define OHCI_PORT_PESC (1 << 17)
#define OHCI_PORT_PSSC (1 << 18)
#define OHCI_PORT_OCIC (1 << 19)
#define OHCI_PORT_PRSC (1 << 20)
#define OHCI_PORT_WTC (OHCI_PORT_CSC | OHCI_PORT_PESC | OHCI_PORT_PSSC | OHCI_PORT_OCIC | OHCI_PORT_PRSC)
#define OHCI_TD_DIR_SETUP 0x0
#define OHCI_TD_DIR_OUT 0x1
#define OHCI_TD_DIR_IN 0x2
#define OHCI_TD_DIR_RESERVED 0x3
#define OHCI_TD_DIR_SETUP 0x0
#define OHCI_TD_DIR_OUT 0x1
#define OHCI_TD_DIR_IN 0x2
#define OHCI_TD_DIR_RESERVED 0x3
#define OHCI_CC_NOERROR 0x0
#define OHCI_CC_CRC 0x1
#define OHCI_CC_BITSTUFFING 0x2
#define OHCI_CC_DATATOGGLEMISMATCH 0x3
#define OHCI_CC_STALL 0x4
#define OHCI_CC_NOERROR 0x0
#define OHCI_CC_CRC 0x1
#define OHCI_CC_BITSTUFFING 0x2
#define OHCI_CC_DATATOGGLEMISMATCH 0x3
#define OHCI_CC_STALL 0x4
#define OHCI_CC_DEVICENOTRESPONDING 0x5
#define OHCI_CC_PIDCHECKFAILURE 0x6
#define OHCI_CC_UNDEXPETEDPID 0x7 // the what?
#define OHCI_CC_DATAOVERRUN 0x8
#define OHCI_CC_DATAUNDERRUN 0x9
#define OHCI_CC_BUFFEROVERRUN 0xc
#define OHCI_CC_BUFFERUNDERRUN 0xd
#define OHCI_CC_PIDCHECKFAILURE 0x6
#define OHCI_CC_UNDEXPETEDPID 0x7 // the what?
#define OHCI_CC_DATAOVERRUN 0x8
#define OHCI_CC_DATAUNDERRUN 0x9
#define OHCI_CC_BUFFEROVERRUN 0xc
#define OHCI_CC_BUFFERUNDERRUN 0xd
OHCIState *ohci_create(uint32_t base, int ports);
OHCIState* ohci_create(uint32_t base, int ports);
uint32_t ohci_mem_read(OHCIState *ohci, uint32_t addr );
void ohci_mem_write(OHCIState *ohci, uint32_t addr, uint32_t value );
void ohci_frame_boundary(void *opaque);
uint32_t ohci_mem_read(OHCIState* ohci, uint32_t addr);
void ohci_mem_write(OHCIState* ohci, uint32_t addr, uint32_t value);
void ohci_frame_boundary(void* opaque);
void ohci_hard_reset(OHCIState *ohci);
void ohci_soft_reset(OHCIState *ohci);
int ohci_bus_start(OHCIState *ohci);
void ohci_bus_stop(OHCIState *ohci);
void ohci_hard_reset(OHCIState* ohci);
void ohci_soft_reset(OHCIState* ohci);
int ohci_bus_start(OHCIState* ohci);
void ohci_bus_stop(OHCIState* ohci);
#endif

View File

@ -18,72 +18,80 @@
#define USB_DEVICE_GET_CLASS(p) (&p->klass)
static void usb_device_realize(USBDevice *dev/*, Error **errp*/)
static void usb_device_realize(USBDevice* dev /*, Error **errp*/)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->realize) {
klass->realize(dev/*, errp*/);
}
if (klass->realize)
{
klass->realize(dev /*, errp*/);
}
}
USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
USBDevice* usb_device_find_device(USBDevice* dev, uint8_t addr)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->find_device) {
return klass->find_device(dev, addr);
}
return NULL;
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->find_device)
{
return klass->find_device(dev, addr);
}
return NULL;
}
static void usb_device_unrealize(USBDevice *dev/*, Error **errp*/)
static void usb_device_unrealize(USBDevice* dev /*, Error **errp*/)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->unrealize) {
klass->unrealize(dev/*, errp*/);
}
if (klass->unrealize)
{
klass->unrealize(dev /*, errp*/);
}
}
void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
void usb_device_cancel_packet(USBDevice* dev, USBPacket* p)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->cancel_packet) {
klass->cancel_packet(dev, p);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->cancel_packet)
{
klass->cancel_packet(dev, p);
}
}
void usb_device_handle_attach(USBDevice *dev)
void usb_device_handle_attach(USBDevice* dev)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_attach) {
klass->handle_attach(dev);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_attach)
{
klass->handle_attach(dev);
}
}
void usb_device_handle_reset(USBDevice *dev)
void usb_device_handle_reset(USBDevice* dev)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_reset) {
klass->handle_reset(dev);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_reset)
{
klass->handle_reset(dev);
}
}
void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
int value, int index, int length, uint8_t *data)
void usb_device_handle_control(USBDevice* dev, USBPacket* p, int request,
int value, int index, int length, uint8_t* data)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_control) {
klass->handle_control(dev, p, request, value, index, length, data);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_control)
{
klass->handle_control(dev, p, request, value, index, length, data);
}
}
void usb_device_handle_data(USBDevice *dev, USBPacket *p)
void usb_device_handle_data(USBDevice* dev, USBPacket* p)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_data) {
klass->handle_data(dev, p);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_data)
{
klass->handle_data(dev, p);
}
}
/*const char *usb_device_get_product_desc(USBDevice *dev)
@ -92,54 +100,60 @@ void usb_device_handle_data(USBDevice *dev, USBPacket *p)
return klass->product_desc;
}*/
const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
const USBDesc* usb_device_get_usb_desc(USBDevice* dev)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (dev->usb_desc) {
return dev->usb_desc;
}
return klass->usb_desc;
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (dev->usb_desc)
{
return dev->usb_desc;
}
return klass->usb_desc;
}
void usb_device_set_interface(USBDevice *dev, int intf,
int alt_old, int alt_new)
void usb_device_set_interface(USBDevice* dev, int intf,
int alt_old, int alt_new)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->set_interface) {
klass->set_interface(dev, intf, alt_old, alt_new);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->set_interface)
{
klass->set_interface(dev, intf, alt_old, alt_new);
}
}
void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep)
void usb_device_flush_ep_queue(USBDevice* dev, USBEndpoint* ep)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->flush_ep_queue) {
klass->flush_ep_queue(dev, ep);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->flush_ep_queue)
{
klass->flush_ep_queue(dev, ep);
}
}
void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep)
void usb_device_ep_stopped(USBDevice* dev, USBEndpoint* ep)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->ep_stopped) {
klass->ep_stopped(dev, ep);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->ep_stopped)
{
klass->ep_stopped(dev, ep);
}
}
int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps,
int streams)
int usb_device_alloc_streams(USBDevice* dev, USBEndpoint** eps, int nr_eps,
int streams)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->alloc_streams) {
return klass->alloc_streams(dev, eps, nr_eps, streams);
}
return 0;
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->alloc_streams)
{
return klass->alloc_streams(dev, eps, nr_eps, streams);
}
return 0;
}
void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps)
void usb_device_free_streams(USBDevice* dev, USBEndpoint** eps, int nr_eps)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->free_streams) {
klass->free_streams(dev, eps, nr_eps);
}
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
if (klass->free_streams)
{
klass->free_streams(dev, eps, nr_eps);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -20,199 +20,222 @@
#include "../platcompat.h"
/* binary representation */
PACK(typedef struct USBDescriptor {
uint8_t bLength;
uint8_t bDescriptorType;
union {
struct {
uint8_t bcdUSB_lo;
uint8_t bcdUSB_hi;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t idVendor_lo;
uint8_t idVendor_hi;
uint8_t idProduct_lo;
uint8_t idProduct_hi;
uint8_t bcdDevice_lo;
uint8_t bcdDevice_hi;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} device;
struct {
uint8_t bcdUSB_lo;
uint8_t bcdUSB_hi;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
uint8_t bReserved;
} device_qualifier;
struct {
uint8_t wTotalLength_lo;
uint8_t wTotalLength_hi;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} config;
struct {
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} intf;
struct {
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint8_t wMaxPacketSize_lo;
uint8_t wMaxPacketSize_hi;
uint8_t bInterval;
uint8_t bRefresh; /* only audio ep */
uint8_t bSynchAddress; /* only audio ep */
} endpoint;
struct {
uint8_t bMaxBurst;
uint8_t bmAttributes;
uint8_t wBytesPerInterval_lo;
uint8_t wBytesPerInterval_hi;
} super_endpoint;
struct {
uint8_t wTotalLength_lo;
uint8_t wTotalLength_hi;
uint8_t bNumDeviceCaps;
} bos;
struct {
uint8_t bDevCapabilityType;
union {
struct {
uint8_t bmAttributes_1;
uint8_t bmAttributes_2;
uint8_t bmAttributes_3;
uint8_t bmAttributes_4;
} usb2_ext;
struct {
uint8_t bmAttributes;
uint8_t wSpeedsSupported_lo;
uint8_t wSpeedsSupported_hi;
uint8_t bFunctionalitySupport;
uint8_t bU1DevExitLat;
uint8_t wU2DevExitLat_lo;
uint8_t wU2DevExitLat_hi;
} super;
} u;
} cap;
} u;
}, USBDescriptor);
PACK(
typedef struct USBDescriptor {
uint8_t bLength;
uint8_t bDescriptorType;
union
{
struct
{
uint8_t bcdUSB_lo;
uint8_t bcdUSB_hi;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t idVendor_lo;
uint8_t idVendor_hi;
uint8_t idProduct_lo;
uint8_t idProduct_hi;
uint8_t bcdDevice_lo;
uint8_t bcdDevice_hi;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} device;
struct
{
uint8_t bcdUSB_lo;
uint8_t bcdUSB_hi;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
uint8_t bReserved;
} device_qualifier;
struct
{
uint8_t wTotalLength_lo;
uint8_t wTotalLength_hi;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} config;
struct
{
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} intf;
struct
{
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint8_t wMaxPacketSize_lo;
uint8_t wMaxPacketSize_hi;
uint8_t bInterval;
uint8_t bRefresh; /* only audio ep */
uint8_t bSynchAddress; /* only audio ep */
} endpoint;
struct
{
uint8_t bMaxBurst;
uint8_t bmAttributes;
uint8_t wBytesPerInterval_lo;
uint8_t wBytesPerInterval_hi;
} super_endpoint;
struct
{
uint8_t wTotalLength_lo;
uint8_t wTotalLength_hi;
uint8_t bNumDeviceCaps;
} bos;
struct
{
uint8_t bDevCapabilityType;
union
{
struct
{
uint8_t bmAttributes_1;
uint8_t bmAttributes_2;
uint8_t bmAttributes_3;
uint8_t bmAttributes_4;
} usb2_ext;
struct
{
uint8_t bmAttributes;
uint8_t wSpeedsSupported_lo;
uint8_t wSpeedsSupported_hi;
uint8_t bFunctionalitySupport;
uint8_t bU1DevExitLat;
uint8_t wU2DevExitLat_lo;
uint8_t wU2DevExitLat_hi;
} super;
} u;
} cap;
} u;
},
USBDescriptor);
struct USBDescID {
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
struct USBDescID
{
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
};
struct USBDescDevice {
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
struct USBDescDevice
{
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint8_t bNumConfigurations;
std::vector<USBDescConfig> confs;
std::vector<USBDescConfig> confs;
};
struct USBDescConfig {
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
struct USBDescConfig
{
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
/* grouped interfaces */
//uint8_t nif_groups;
std::vector<USBDescIfaceAssoc> if_groups;
std::vector<USBDescIfaceAssoc> if_groups;
/* "normal" interfaces */
//uint8_t nif;
std::vector<USBDescIface> ifs;
std::vector<USBDescIface> ifs;
};
/* conceptually an Interface Association Descriptor, and releated interfaces */
struct USBDescIfaceAssoc {
uint8_t bFirstInterface;
uint8_t bInterfaceCount;
uint8_t bFunctionClass;
uint8_t bFunctionSubClass;
uint8_t bFunctionProtocol;
uint8_t iFunction;
struct USBDescIfaceAssoc
{
uint8_t bFirstInterface;
uint8_t bInterfaceCount;
uint8_t bFunctionClass;
uint8_t bFunctionSubClass;
uint8_t bFunctionProtocol;
uint8_t iFunction;
//uint8_t nif;
std::vector<USBDescIface> ifs;
std::vector<USBDescIface> ifs;
};
struct USBDescIface {
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
struct USBDescIface
{
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
//uint8_t ndesc;
std::vector<USBDescOther> descs;
std::vector<USBDescEndpoint> eps;
std::vector<USBDescOther> descs;
std::vector<USBDescEndpoint> eps;
};
struct USBDescEndpoint {
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
uint8_t bRefresh;
uint8_t bSynchAddress;
struct USBDescEndpoint
{
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
uint8_t bRefresh;
uint8_t bSynchAddress;
uint8_t is_audio; /* has bRefresh + bSynchAddress */
const uint8_t *extra;
uint8_t is_audio; /* has bRefresh + bSynchAddress */
const uint8_t* extra;
/* superspeed endpoint companion */
uint8_t bMaxBurst;
uint8_t bmAttributes_super;
uint16_t wBytesPerInterval;
uint8_t bMaxBurst;
uint8_t bmAttributes_super;
uint16_t wBytesPerInterval;
};
struct USBDescOther {
uint8_t length;
const uint8_t *data;
struct USBDescOther
{
uint8_t length;
const uint8_t* data;
};
struct USBDescMSOS {
const char *CompatibleID;
const wchar_t *Label;
bool SelectiveSuspendEnabled;
struct USBDescMSOS
{
const char* CompatibleID;
const wchar_t* Label;
bool SelectiveSuspendEnabled;
};
typedef const char *USBDescStrings[256];
typedef const char* USBDescStrings[256];
struct USBDesc {
USBDescID id;
const USBDescDevice *full;
const USBDescDevice *high;
const USBDescDevice *super;
const char* const *str;
const USBDescMSOS *msos;
struct USBDesc
{
USBDescID id;
const USBDescDevice* full;
const USBDescDevice* high;
const USBDescDevice* super;
const char* const* str;
const USBDescMSOS* msos;
};
#define USB_DESC_FLAG_SUPER (1 << 1)
@ -229,32 +252,32 @@ static inline uint8_t usb_hi(uint16_t val)
}
/* generate usb packages from structs */
int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
bool msos, uint8_t *dest, size_t len);
int usb_desc_device_qualifier(const USBDescDevice *dev,
uint8_t *dest, size_t len);
int usb_desc_device(const USBDescID* id, const USBDescDevice* dev,
bool msos, uint8_t* dest, size_t len);
int usb_desc_device_qualifier(const USBDescDevice* dev,
uint8_t* dest, size_t len);
int usb_desc_config(const USBDescConfig& conf, int flags,
uint8_t *dest, size_t len);
uint8_t* dest, size_t len);
int usb_desc_iface_group(const USBDescIfaceAssoc& iad, int flags,
uint8_t *dest, size_t len);
uint8_t* dest, size_t len);
int usb_desc_iface(const USBDescIface& iface, int flags,
uint8_t *dest, size_t len);
uint8_t* dest, size_t len);
int usb_desc_endpoint(const USBDescEndpoint& ep, int flags,
uint8_t *dest, size_t len);
int usb_desc_other(const USBDescOther& desc, uint8_t *dest, size_t len);
uint8_t* dest, size_t len);
int usb_desc_other(const USBDescOther& desc, uint8_t* dest, size_t len);
//int usb_desc_msos(const USBDesc *desc, USBPacket *p,
// int index, uint8_t *dest, size_t len);
int usb_desc_parse_dev (const uint8_t *data, int len, USBDesc& desc, USBDescDevice& dev);
int usb_desc_parse_config (const uint8_t *data, int len, USBDescDevice& dev);
int usb_desc_parse_dev(const uint8_t* data, int len, USBDesc& desc, USBDescDevice& dev);
int usb_desc_parse_config(const uint8_t* data, int len, USBDescDevice& dev);
/* control message emulation helpers */
void usb_desc_init(USBDevice *dev);
void usb_desc_attach(USBDevice *dev);
int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
int value, uint8_t *dest, size_t len);
int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data);
void usb_desc_init(USBDevice* dev);
void usb_desc_attach(USBDevice* dev);
int usb_desc_string(USBDevice* dev, int index, uint8_t* dest, size_t len);
int usb_desc_get_descriptor(USBDevice* dev, USBPacket* p,
int value, uint8_t* dest, size_t len);
int usb_desc_handle_control(USBDevice* dev, USBPacket* p,
int request, int value, int index, int length, uint8_t* data);
int usb_desc_set_config(USBDevice *dev, int value);
int usb_desc_set_interface(USBDevice *dev, int index, int value);
int usb_desc_set_config(USBDevice* dev, int value);
int usb_desc_set_interface(USBDevice* dev, int index, int value);

View File

@ -17,7 +17,7 @@
#include <cstdlib>
#include <cstring>
#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((b) > 0 && (a) > G_MAXSIZE / (b)))
#define SIZE_OVERFLOWS(a, b) (G_UNLIKELY((b) > 0 && (a) > G_MAXSIZE / (b)))
/**
* g_malloc:
@ -28,25 +28,24 @@
*
* Returns: a pointer to the allocated memory
*/
void*
my_g_malloc (size_t n_bytes)
void* my_g_malloc(size_t n_bytes)
{
if (G_LIKELY (n_bytes))
{
void* mem;
if (G_LIKELY(n_bytes))
{
void* mem;
mem = malloc (n_bytes);
//TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 0));
if (mem)
return mem;
mem = malloc(n_bytes);
//TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 0, 0));
if (mem)
return mem;
//g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_bytes);
}
//g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_bytes);
}
//TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 0, 0));
//TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 0, 0));
return NULL;
return NULL;
}
/**
* g_malloc0:
@ -57,25 +56,24 @@ my_g_malloc (size_t n_bytes)
*
* Returns: a pointer to the allocated memory
*/
void*
my_g_malloc0 (size_t n_bytes)
void* my_g_malloc0(size_t n_bytes)
{
if (G_LIKELY (n_bytes))
{
void* mem;
if (G_LIKELY(n_bytes))
{
void* mem;
mem = calloc (1, n_bytes);
//TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 1, 0));
if (mem)
return mem;
mem = calloc(1, n_bytes);
//TRACE (GLIB_MEM_ALLOC((void*) mem, (unsigned int) n_bytes, 1, 0));
if (mem)
return mem;
//g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_bytes);
}
//g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_bytes);
}
//TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 1, 0));
//TRACE(GLIB_MEM_ALLOC((void*) NULL, (int) n_bytes, 1, 0));
return NULL;
return NULL;
}
/**
* g_malloc_n:
@ -88,17 +86,16 @@ my_g_malloc0 (size_t n_bytes)
* Since: 2.24
* Returns: a pointer to the allocated memory
*/
void*
my_g_malloc_n (size_t n_blocks,
size_t n_block_bytes)
void* my_g_malloc_n(size_t n_blocks,
size_t n_block_bytes)
{
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
{
//g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_blocks, n_block_bytes);
}
if (SIZE_OVERFLOWS(n_blocks, n_block_bytes))
{
//g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_blocks, n_block_bytes);
}
return my_g_malloc (n_blocks * n_block_bytes);
return my_g_malloc(n_blocks * n_block_bytes);
}
/**
@ -114,29 +111,28 @@ my_g_malloc_n (size_t n_blocks,
*
* Returns: the new address of the allocated memory
*/
void*
my_g_realloc (void* mem,
size_t n_bytes)
void* my_g_realloc(void* mem,
size_t n_bytes)
{
void* newmem;
void* newmem;
if (G_LIKELY (n_bytes))
{
newmem = realloc (mem, n_bytes);
//TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 0));
if (newmem)
return newmem;
if (G_LIKELY(n_bytes))
{
newmem = realloc(mem, n_bytes);
//TRACE (GLIB_MEM_REALLOC((void*) newmem, (void*)mem, (unsigned int) n_bytes, 0));
if (newmem)
return newmem;
//g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_bytes);
}
//g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_bytes);
}
if (mem)
free (mem);
if (mem)
free(mem);
//TRACE (GLIB_MEM_REALLOC((void*) NULL, (void*)mem, 0, 0));
//TRACE (GLIB_MEM_REALLOC((void*) NULL, (void*)mem, 0, 0));
return NULL;
return NULL;
}
/**
@ -151,16 +147,15 @@ my_g_realloc (void* mem,
* Since: 2.24
* Returns: the new address of the allocated memory
*/
void*
my_g_realloc_n (void* mem,
size_t n_blocks,
size_t n_block_bytes)
void* my_g_realloc_n(void* mem,
size_t n_blocks,
size_t n_block_bytes)
{
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
{
//g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_blocks, n_block_bytes);
}
if (SIZE_OVERFLOWS(n_blocks, n_block_bytes))
{
//g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
// G_STRLOC, n_blocks, n_block_bytes);
}
return my_g_realloc (mem, n_blocks * n_block_bytes);
return my_g_realloc(mem, n_blocks * n_block_bytes);
}

View File

@ -24,16 +24,16 @@
#define G_MAXSIZE G_MAXUINT32
#endif
#define G_MAXUINT64 0xffffffffffffffffUL
#define G_MAXUINT32 ((uint32_t)0xffffffff)
#define G_MAXUINT64 0xffffffffffffffffUL
#define G_MAXUINT32 ((uint32_t)0xffffffff)
void* my_g_malloc0 (size_t n_bytes);
void* my_g_malloc (size_t n_bytes);
void* my_g_malloc_n (size_t n_blocks,
size_t n_block_bytes);
void* my_g_realloc_n (void* mem,
size_t n_blocks,
size_t n_block_bytes);
void* my_g_malloc0(size_t n_bytes);
void* my_g_malloc(size_t n_bytes);
void* my_g_malloc_n(size_t n_blocks,
size_t n_block_bytes);
void* my_g_realloc_n(void* mem,
size_t n_blocks,
size_t n_block_bytes);
#define my_g_free free
@ -41,11 +41,11 @@ void* my_g_realloc_n (void* mem,
#define G_UNLIKELY(expr) (expr)
#define my_G_NEW(struct_type, n_structs, func) \
((struct_type *) my_g_##func##_n ((n_structs), sizeof (struct_type)))
((struct_type*)my_g_##func##_n((n_structs), sizeof(struct_type)))
#define my_G_RENEW(struct_type, mem, n_structs, func) \
((struct_type *) my_g_##func##_n (mem, (n_structs), sizeof (struct_type)))
((struct_type*)my_g_##func##_n(mem, (n_structs), sizeof(struct_type)))
#define my_g_new(struct_type, n_structs) my_G_NEW (struct_type, n_structs, malloc)
#define my_g_renew(struct_type, mem, n_structs) my_G_RENEW (struct_type, mem, n_structs, realloc)
#define my_g_new(struct_type, n_structs) my_G_NEW(struct_type, n_structs, malloc)
#define my_g_renew(struct_type, mem, n_structs) my_G_RENEW(struct_type, mem, n_structs, realloc)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -25,12 +25,12 @@
#define MOUSE_EVENT_MBUTTON 0x04
/* identical to the ps/2 keyboard bits */
#define QEMU_SCROLL_LOCK_LED (1 << 0)
#define QEMU_NUM_LOCK_LED (1 << 1)
#define QEMU_CAPS_LOCK_LED (1 << 2)
#define QEMU_NUM_LOCK_LED (1 << 1)
#define QEMU_CAPS_LOCK_LED (1 << 2)
#define HID_MOUSE 1
#define HID_TABLET 2
#define HID_KEYBOARD 3
#define HID_MOUSE 1
#define HID_TABLET 2
#define HID_KEYBOARD 3
/* scancode without modifiers */
#define SCANCODE_KEYMASK 0xff
@ -38,171 +38,173 @@
#define SCANCODE_KEYCODEMASK 0x7f
/* "grey" keys will usually need a 0xe0 prefix */
#define SCANCODE_GREY 0x80
#define SCANCODE_EMUL0 0xE0
#define SCANCODE_EMUL1 0xE1
#define SCANCODE_GREY 0x80
#define SCANCODE_EMUL0 0xE0
#define SCANCODE_EMUL1 0xE1
/* "up" flag */
#define SCANCODE_UP 0x80
#define SCANCODE_UP 0x80
/* Additional modifiers to use if not catched another way. */
#define SCANCODE_SHIFT 0x100
#define SCANCODE_CTRL 0x200
#define SCANCODE_ALT 0x400
#define SCANCODE_ALTGR 0x800
#define SCANCODE_SHIFT 0x100
#define SCANCODE_CTRL 0x200
#define SCANCODE_ALT 0x400
#define SCANCODE_ALTGR 0x800
typedef enum QKeyCode {
Q_KEY_CODE_UNMAPPED = 0,
Q_KEY_CODE_SHIFT = 1,
Q_KEY_CODE_SHIFT_R = 2,
Q_KEY_CODE_ALT = 3,
Q_KEY_CODE_ALT_R = 4,
Q_KEY_CODE_CTRL = 5,
Q_KEY_CODE_CTRL_R = 6,
Q_KEY_CODE_MENU = 7,
Q_KEY_CODE_ESC = 8,
Q_KEY_CODE_1 = 9,
Q_KEY_CODE_2 = 10,
Q_KEY_CODE_3 = 11,
Q_KEY_CODE_4 = 12,
Q_KEY_CODE_5 = 13,
Q_KEY_CODE_6 = 14,
Q_KEY_CODE_7 = 15,
Q_KEY_CODE_8 = 16,
Q_KEY_CODE_9 = 17,
Q_KEY_CODE_0 = 18,
Q_KEY_CODE_MINUS = 19,
Q_KEY_CODE_EQUAL = 20,
Q_KEY_CODE_BACKSPACE = 21,
Q_KEY_CODE_TAB = 22,
Q_KEY_CODE_Q = 23,
Q_KEY_CODE_W = 24,
Q_KEY_CODE_E = 25,
Q_KEY_CODE_R = 26,
Q_KEY_CODE_T = 27,
Q_KEY_CODE_Y = 28,
Q_KEY_CODE_U = 29,
Q_KEY_CODE_I = 30,
Q_KEY_CODE_O = 31,
Q_KEY_CODE_P = 32,
Q_KEY_CODE_BRACKET_LEFT = 33,
Q_KEY_CODE_BRACKET_RIGHT = 34,
Q_KEY_CODE_RET = 35,
Q_KEY_CODE_A = 36,
Q_KEY_CODE_S = 37,
Q_KEY_CODE_D = 38,
Q_KEY_CODE_F = 39,
Q_KEY_CODE_G = 40,
Q_KEY_CODE_H = 41,
Q_KEY_CODE_J = 42,
Q_KEY_CODE_K = 43,
Q_KEY_CODE_L = 44,
Q_KEY_CODE_SEMICOLON = 45,
Q_KEY_CODE_APOSTROPHE = 46,
Q_KEY_CODE_GRAVE_ACCENT = 47,
Q_KEY_CODE_BACKSLASH = 48,
Q_KEY_CODE_Z = 49,
Q_KEY_CODE_X = 50,
Q_KEY_CODE_C = 51,
Q_KEY_CODE_V = 52,
Q_KEY_CODE_B = 53,
Q_KEY_CODE_N = 54,
Q_KEY_CODE_M = 55,
Q_KEY_CODE_COMMA = 56,
Q_KEY_CODE_DOT = 57,
Q_KEY_CODE_SLASH = 58,
Q_KEY_CODE_ASTERISK = 59,
Q_KEY_CODE_SPC = 60,
Q_KEY_CODE_CAPS_LOCK = 61,
Q_KEY_CODE_F1 = 62,
Q_KEY_CODE_F2 = 63,
Q_KEY_CODE_F3 = 64,
Q_KEY_CODE_F4 = 65,
Q_KEY_CODE_F5 = 66,
Q_KEY_CODE_F6 = 67,
Q_KEY_CODE_F7 = 68,
Q_KEY_CODE_F8 = 69,
Q_KEY_CODE_F9 = 70,
Q_KEY_CODE_F10 = 71,
Q_KEY_CODE_NUM_LOCK = 72,
Q_KEY_CODE_SCROLL_LOCK = 73,
Q_KEY_CODE_KP_DIVIDE = 74,
Q_KEY_CODE_KP_MULTIPLY = 75,
Q_KEY_CODE_KP_SUBTRACT = 76,
Q_KEY_CODE_KP_ADD = 77,
Q_KEY_CODE_KP_ENTER = 78,
Q_KEY_CODE_KP_DECIMAL = 79,
Q_KEY_CODE_SYSRQ = 80,
Q_KEY_CODE_KP_0 = 81,
Q_KEY_CODE_KP_1 = 82,
Q_KEY_CODE_KP_2 = 83,
Q_KEY_CODE_KP_3 = 84,
Q_KEY_CODE_KP_4 = 85,
Q_KEY_CODE_KP_5 = 86,
Q_KEY_CODE_KP_6 = 87,
Q_KEY_CODE_KP_7 = 88,
Q_KEY_CODE_KP_8 = 89,
Q_KEY_CODE_KP_9 = 90,
Q_KEY_CODE_LESS = 91,
Q_KEY_CODE_F11 = 92,
Q_KEY_CODE_F12 = 93,
Q_KEY_CODE_PRINT = 94,
Q_KEY_CODE_HOME = 95,
Q_KEY_CODE_PGUP = 96,
Q_KEY_CODE_PGDN = 97,
Q_KEY_CODE_END = 98,
Q_KEY_CODE_LEFT = 99,
Q_KEY_CODE_UP = 100,
Q_KEY_CODE_DOWN = 101,
Q_KEY_CODE_RIGHT = 102,
Q_KEY_CODE_INSERT = 103,
Q_KEY_CODE_DELETE = 104,
Q_KEY_CODE_STOP = 105,
Q_KEY_CODE_AGAIN = 106,
Q_KEY_CODE_PROPS = 107,
Q_KEY_CODE_UNDO = 108,
Q_KEY_CODE_FRONT = 109,
Q_KEY_CODE_COPY = 110,
Q_KEY_CODE_OPEN = 111,
Q_KEY_CODE_PASTE = 112,
Q_KEY_CODE_FIND = 113,
Q_KEY_CODE_CUT = 114,
Q_KEY_CODE_LF = 115,
Q_KEY_CODE_HELP = 116,
Q_KEY_CODE_META_L = 117,
Q_KEY_CODE_META_R = 118,
Q_KEY_CODE_COMPOSE = 119,
Q_KEY_CODE_PAUSE = 120,
Q_KEY_CODE_RO = 121,
Q_KEY_CODE_HIRAGANA = 122,
Q_KEY_CODE_HENKAN = 123,
Q_KEY_CODE_YEN = 124,
Q_KEY_CODE_MUHENKAN = 125,
Q_KEY_CODE_KATAKANAHIRAGANA = 126,
Q_KEY_CODE_KP_COMMA = 127,
Q_KEY_CODE_KP_EQUALS = 128,
Q_KEY_CODE_POWER = 129,
Q_KEY_CODE_SLEEP = 130,
Q_KEY_CODE_WAKE = 131,
Q_KEY_CODE_AUDIONEXT = 132,
Q_KEY_CODE_AUDIOPREV = 133,
Q_KEY_CODE_AUDIOSTOP = 134,
Q_KEY_CODE_AUDIOPLAY = 135,
Q_KEY_CODE_AUDIOMUTE = 136,
Q_KEY_CODE_VOLUMEUP = 137,
Q_KEY_CODE_VOLUMEDOWN = 138,
Q_KEY_CODE_MEDIASELECT = 139,
Q_KEY_CODE_MAIL = 140,
Q_KEY_CODE_CALCULATOR = 141,
Q_KEY_CODE_COMPUTER = 142,
Q_KEY_CODE_AC_HOME = 143,
Q_KEY_CODE_AC_BACK = 144,
Q_KEY_CODE_AC_FORWARD = 145,
Q_KEY_CODE_AC_REFRESH = 146,
Q_KEY_CODE_AC_BOOKMARKS = 147,
Q_KEY_CODE__MAX = 148,
typedef enum QKeyCode
{
Q_KEY_CODE_UNMAPPED = 0,
Q_KEY_CODE_SHIFT = 1,
Q_KEY_CODE_SHIFT_R = 2,
Q_KEY_CODE_ALT = 3,
Q_KEY_CODE_ALT_R = 4,
Q_KEY_CODE_CTRL = 5,
Q_KEY_CODE_CTRL_R = 6,
Q_KEY_CODE_MENU = 7,
Q_KEY_CODE_ESC = 8,
Q_KEY_CODE_1 = 9,
Q_KEY_CODE_2 = 10,
Q_KEY_CODE_3 = 11,
Q_KEY_CODE_4 = 12,
Q_KEY_CODE_5 = 13,
Q_KEY_CODE_6 = 14,
Q_KEY_CODE_7 = 15,
Q_KEY_CODE_8 = 16,
Q_KEY_CODE_9 = 17,
Q_KEY_CODE_0 = 18,
Q_KEY_CODE_MINUS = 19,
Q_KEY_CODE_EQUAL = 20,
Q_KEY_CODE_BACKSPACE = 21,
Q_KEY_CODE_TAB = 22,
Q_KEY_CODE_Q = 23,
Q_KEY_CODE_W = 24,
Q_KEY_CODE_E = 25,
Q_KEY_CODE_R = 26,
Q_KEY_CODE_T = 27,
Q_KEY_CODE_Y = 28,
Q_KEY_CODE_U = 29,
Q_KEY_CODE_I = 30,
Q_KEY_CODE_O = 31,
Q_KEY_CODE_P = 32,
Q_KEY_CODE_BRACKET_LEFT = 33,
Q_KEY_CODE_BRACKET_RIGHT = 34,
Q_KEY_CODE_RET = 35,
Q_KEY_CODE_A = 36,
Q_KEY_CODE_S = 37,
Q_KEY_CODE_D = 38,
Q_KEY_CODE_F = 39,
Q_KEY_CODE_G = 40,
Q_KEY_CODE_H = 41,
Q_KEY_CODE_J = 42,
Q_KEY_CODE_K = 43,
Q_KEY_CODE_L = 44,
Q_KEY_CODE_SEMICOLON = 45,
Q_KEY_CODE_APOSTROPHE = 46,
Q_KEY_CODE_GRAVE_ACCENT = 47,
Q_KEY_CODE_BACKSLASH = 48,
Q_KEY_CODE_Z = 49,
Q_KEY_CODE_X = 50,
Q_KEY_CODE_C = 51,
Q_KEY_CODE_V = 52,
Q_KEY_CODE_B = 53,
Q_KEY_CODE_N = 54,
Q_KEY_CODE_M = 55,
Q_KEY_CODE_COMMA = 56,
Q_KEY_CODE_DOT = 57,
Q_KEY_CODE_SLASH = 58,
Q_KEY_CODE_ASTERISK = 59,
Q_KEY_CODE_SPC = 60,
Q_KEY_CODE_CAPS_LOCK = 61,
Q_KEY_CODE_F1 = 62,
Q_KEY_CODE_F2 = 63,
Q_KEY_CODE_F3 = 64,
Q_KEY_CODE_F4 = 65,
Q_KEY_CODE_F5 = 66,
Q_KEY_CODE_F6 = 67,
Q_KEY_CODE_F7 = 68,
Q_KEY_CODE_F8 = 69,
Q_KEY_CODE_F9 = 70,
Q_KEY_CODE_F10 = 71,
Q_KEY_CODE_NUM_LOCK = 72,
Q_KEY_CODE_SCROLL_LOCK = 73,
Q_KEY_CODE_KP_DIVIDE = 74,
Q_KEY_CODE_KP_MULTIPLY = 75,
Q_KEY_CODE_KP_SUBTRACT = 76,
Q_KEY_CODE_KP_ADD = 77,
Q_KEY_CODE_KP_ENTER = 78,
Q_KEY_CODE_KP_DECIMAL = 79,
Q_KEY_CODE_SYSRQ = 80,
Q_KEY_CODE_KP_0 = 81,
Q_KEY_CODE_KP_1 = 82,
Q_KEY_CODE_KP_2 = 83,
Q_KEY_CODE_KP_3 = 84,
Q_KEY_CODE_KP_4 = 85,
Q_KEY_CODE_KP_5 = 86,
Q_KEY_CODE_KP_6 = 87,
Q_KEY_CODE_KP_7 = 88,
Q_KEY_CODE_KP_8 = 89,
Q_KEY_CODE_KP_9 = 90,
Q_KEY_CODE_LESS = 91,
Q_KEY_CODE_F11 = 92,
Q_KEY_CODE_F12 = 93,
Q_KEY_CODE_PRINT = 94,
Q_KEY_CODE_HOME = 95,
Q_KEY_CODE_PGUP = 96,
Q_KEY_CODE_PGDN = 97,
Q_KEY_CODE_END = 98,
Q_KEY_CODE_LEFT = 99,
Q_KEY_CODE_UP = 100,
Q_KEY_CODE_DOWN = 101,
Q_KEY_CODE_RIGHT = 102,
Q_KEY_CODE_INSERT = 103,
Q_KEY_CODE_DELETE = 104,
Q_KEY_CODE_STOP = 105,
Q_KEY_CODE_AGAIN = 106,
Q_KEY_CODE_PROPS = 107,
Q_KEY_CODE_UNDO = 108,
Q_KEY_CODE_FRONT = 109,
Q_KEY_CODE_COPY = 110,
Q_KEY_CODE_OPEN = 111,
Q_KEY_CODE_PASTE = 112,
Q_KEY_CODE_FIND = 113,
Q_KEY_CODE_CUT = 114,
Q_KEY_CODE_LF = 115,
Q_KEY_CODE_HELP = 116,
Q_KEY_CODE_META_L = 117,
Q_KEY_CODE_META_R = 118,
Q_KEY_CODE_COMPOSE = 119,
Q_KEY_CODE_PAUSE = 120,
Q_KEY_CODE_RO = 121,
Q_KEY_CODE_HIRAGANA = 122,
Q_KEY_CODE_HENKAN = 123,
Q_KEY_CODE_YEN = 124,
Q_KEY_CODE_MUHENKAN = 125,
Q_KEY_CODE_KATAKANAHIRAGANA = 126,
Q_KEY_CODE_KP_COMMA = 127,
Q_KEY_CODE_KP_EQUALS = 128,
Q_KEY_CODE_POWER = 129,
Q_KEY_CODE_SLEEP = 130,
Q_KEY_CODE_WAKE = 131,
Q_KEY_CODE_AUDIONEXT = 132,
Q_KEY_CODE_AUDIOPREV = 133,
Q_KEY_CODE_AUDIOSTOP = 134,
Q_KEY_CODE_AUDIOPLAY = 135,
Q_KEY_CODE_AUDIOMUTE = 136,
Q_KEY_CODE_VOLUMEUP = 137,
Q_KEY_CODE_VOLUMEDOWN = 138,
Q_KEY_CODE_MEDIASELECT = 139,
Q_KEY_CODE_MAIL = 140,
Q_KEY_CODE_CALCULATOR = 141,
Q_KEY_CODE_COMPUTER = 142,
Q_KEY_CODE_AC_HOME = 143,
Q_KEY_CODE_AC_BACK = 144,
Q_KEY_CODE_AC_FORWARD = 145,
Q_KEY_CODE_AC_REFRESH = 146,
Q_KEY_CODE_AC_BOOKMARKS = 147,
Q_KEY_CODE__MAX = 148,
} QKeyCode;
typedef enum InputEventKind {
typedef enum InputEventKind
{
INPUT_EVENT_KIND_KEY = 0,
INPUT_EVENT_KIND_BTN = 1,
INPUT_EVENT_KIND_REL = 2,
@ -210,19 +212,22 @@ typedef enum InputEventKind {
INPUT_EVENT_KIND__MAX = 4,
} InputEventKind;
typedef enum KeyValueKind {
typedef enum KeyValueKind
{
KEY_VALUE_KIND_NUMBER = 0,
KEY_VALUE_KIND_QCODE = 1,
KEY_VALUE_KIND__MAX = 2,
} KeyValueKind;
typedef enum InputAxis {
typedef enum InputAxis
{
INPUT_AXIS_X = 0,
INPUT_AXIS_Y = 1,
INPUT_AXIS__MAX = 2,
} InputAxis;
typedef enum InputButton {
typedef enum InputButton
{
INPUT_BUTTON_LEFT = 0,
INPUT_BUTTON_MIDDLE = 1,
INPUT_BUTTON_RIGHT = 2,
@ -233,32 +238,39 @@ typedef enum InputButton {
INPUT_BUTTON__MAX = 7,
} InputButton;
struct KeyValue {
struct KeyValue
{
KeyValueKind type;
union {
union
{
int number;
QKeyCode qcode;
} u;
};
struct InputKeyEvent {
struct InputKeyEvent
{
KeyValue key;
bool down;
};
struct InputBtnEvent {
struct InputBtnEvent
{
InputButton button;
bool down;
};
struct InputMoveEvent {
struct InputMoveEvent
{
InputAxis axis;
int64_t value;
};
struct InputEvent {
struct InputEvent
{
InputEventKind type;
union {
union
{
InputKeyEvent key;
InputBtnEvent btn;
InputMoveEvent rel;
@ -267,61 +279,66 @@ struct InputEvent {
};
typedef struct HIDState HIDState;
typedef void(*HIDEventFunc)(HIDState *s);
typedef void (*HIDEventFunc)(HIDState* s);
typedef void QEMUPutKBDEvent(HIDState *hs, InputEvent *evt);
typedef void QEMUPutLEDEvent(void *opaque, int ledstate);
typedef void QEMUPutMouseEvent(HIDState *hs, InputEvent *evt);
typedef void QEMUPutKBDEvent(HIDState* hs, InputEvent* evt);
typedef void QEMUPutLEDEvent(void* opaque, int ledstate);
typedef void QEMUPutMouseEvent(HIDState* hs, InputEvent* evt);
typedef struct HIDPointerEvent {
int32_t xdx, ydy; /* relative if it's a mouse, otherwise absolute */
int32_t dz, buttons_state;
typedef struct HIDPointerEvent
{
int32_t xdx, ydy; /* relative if it's a mouse, otherwise absolute */
int32_t dz, buttons_state;
} HIDPointerEvent;
#define QUEUE_LENGTH 16 /* should be enough for a triple-click */
#define QUEUE_MASK (QUEUE_LENGTH-1u)
#define QUEUE_INCR(v) ((v)++, (v) &= QUEUE_MASK)
#define QUEUE_LENGTH 16 /* should be enough for a triple-click */
#define QUEUE_MASK (QUEUE_LENGTH - 1u)
#define QUEUE_INCR(v) ((v)++, (v) &= QUEUE_MASK)
typedef struct HIDMouseState {
HIDPointerEvent queue[QUEUE_LENGTH];
int mouse_grabbed;
QEMUPutMouseEvent *eh_entry;
HIDEventFunc eh_sync;
typedef struct HIDMouseState
{
HIDPointerEvent queue[QUEUE_LENGTH];
int mouse_grabbed;
QEMUPutMouseEvent* eh_entry;
HIDEventFunc eh_sync;
} HIDMouseState;
typedef struct HIDKeyboardState {
uint32_t keycodes[QUEUE_LENGTH];
uint16_t modifiers;
uint8_t leds;
uint8_t key[16];
int32_t keys;
QEMUPutKBDEvent *eh_entry;
typedef struct HIDKeyboardState
{
uint32_t keycodes[QUEUE_LENGTH];
uint16_t modifiers;
uint8_t leds;
uint8_t key[16];
int32_t keys;
QEMUPutKBDEvent* eh_entry;
} HIDKeyboardState;
struct HIDState {
union {
HIDMouseState ptr;
HIDKeyboardState kbd;
};
uint32_t head; /* index into circular queue */
uint32_t n;
int kind;
int32_t protocol;
uint8_t idle;
bool idle_pending;
//QEMUTimer *idle_timer;
HIDEventFunc event;
struct HIDState
{
union
{
HIDMouseState ptr;
HIDKeyboardState kbd;
};
uint32_t head; /* index into circular queue */
uint32_t n;
int kind;
int32_t protocol;
uint8_t idle;
bool idle_pending;
//QEMUTimer *idle_timer;
HIDEventFunc event;
};
void hid_init(HIDState *hs, int kind, HIDEventFunc event);
void hid_reset(HIDState *hs);
void hid_free(HIDState *hs);
void hid_init(HIDState* hs, int kind, HIDEventFunc event);
void hid_reset(HIDState* hs);
void hid_free(HIDState* hs);
bool hid_has_events(HIDState *hs);
void hid_set_next_idle(HIDState *hs);
void hid_pointer_activate(HIDState *hs);
int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len);
int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len);
int hid_keyboard_write(HIDState *hs, uint8_t *buf, int len);
bool hid_has_events(HIDState* hs);
void hid_set_next_idle(HIDState* hs);
void hid_pointer_activate(HIDState* hs);
int hid_pointer_poll(HIDState* hs, uint8_t* buf, int len);
int hid_keyboard_poll(HIDState* hs, uint8_t* buf, int len);
int hid_keyboard_write(HIDState* hs, uint8_t* buf, int len);
#endif /* QEMU_HID_H */

File diff suppressed because it is too large Load Diff

View File

@ -17,197 +17,202 @@
//TODO how much does std::map kill perf if any?
const std::map<const QKeyCode, unsigned short> qemu_input_map_qcode_to_qnum = {
{Q_KEY_CODE_0, 0xb}, /* qcode:Q_KEY_CODE_0 (0) -> linux:11 (KEY_0) -> qnum:11 */
{Q_KEY_CODE_1, 0x2}, /* qcode:Q_KEY_CODE_1 (1) -> linux:2 (KEY_1) -> qnum:2 */
{Q_KEY_CODE_2, 0x3}, /* qcode:Q_KEY_CODE_2 (2) -> linux:3 (KEY_2) -> qnum:3 */
{Q_KEY_CODE_3, 0x4}, /* qcode:Q_KEY_CODE_3 (3) -> linux:4 (KEY_3) -> qnum:4 */
{Q_KEY_CODE_4, 0x5}, /* qcode:Q_KEY_CODE_4 (4) -> linux:5 (KEY_4) -> qnum:5 */
{Q_KEY_CODE_5, 0x6}, /* qcode:Q_KEY_CODE_5 (5) -> linux:6 (KEY_5) -> qnum:6 */
{Q_KEY_CODE_6, 0x7}, /* qcode:Q_KEY_CODE_6 (6) -> linux:7 (KEY_6) -> qnum:7 */
{Q_KEY_CODE_7, 0x8}, /* qcode:Q_KEY_CODE_7 (7) -> linux:8 (KEY_7) -> qnum:8 */
{Q_KEY_CODE_8, 0x9}, /* qcode:Q_KEY_CODE_8 (8) -> linux:9 (KEY_8) -> qnum:9 */
{Q_KEY_CODE_9, 0xa}, /* qcode:Q_KEY_CODE_9 (9) -> linux:10 (KEY_9) -> qnum:10 */
{Q_KEY_CODE_A, 0x1e}, /* qcode:Q_KEY_CODE_A (a) -> linux:30 (KEY_A) -> qnum:30 */
{Q_KEY_CODE_AC_BACK, 0xea}, /* qcode:Q_KEY_CODE_AC_BACK (ac_back) -> linux:158 (KEY_BACK) -> qnum:234 */
{Q_KEY_CODE_AC_BOOKMARKS, 0xe6}, /* qcode:Q_KEY_CODE_AC_BOOKMARKS (ac_bookmarks) -> linux:156 (KEY_BOOKMARKS) -> qnum:230 */
{Q_KEY_CODE_AC_FORWARD, 0xe9}, /* qcode:Q_KEY_CODE_AC_FORWARD (ac_forward) -> linux:159 (KEY_FORWARD) -> qnum:233 */
{Q_KEY_CODE_AC_HOME, 0xb2}, /* qcode:Q_KEY_CODE_AC_HOME (ac_home) -> linux:172 (KEY_HOMEPAGE) -> qnum:178 */
{Q_KEY_CODE_AC_REFRESH, 0xe7}, /* qcode:Q_KEY_CODE_AC_REFRESH (ac_refresh) -> linux:173 (KEY_REFRESH) -> qnum:231 */
{Q_KEY_CODE_AGAIN, 0x85}, /* qcode:Q_KEY_CODE_AGAIN (again) -> linux:129 (KEY_AGAIN) -> qnum:133 */
{Q_KEY_CODE_ALT, 0x38}, /* qcode:Q_KEY_CODE_ALT (alt) -> linux:56 (KEY_LEFTALT) -> qnum:56 */
{Q_KEY_CODE_ALT_R, 0xb8}, /* qcode:Q_KEY_CODE_ALT_R (alt_r) -> linux:100 (KEY_RIGHTALT) -> qnum:184 */
{Q_KEY_CODE_APOSTROPHE, 0x28}, /* qcode:Q_KEY_CODE_APOSTROPHE (apostrophe) -> linux:40 (KEY_APOSTROPHE) -> qnum:40 */
{Q_KEY_CODE_ASTERISK, 0x37}, /* qcode:Q_KEY_CODE_ASTERISK (kp_multiply) -> linux:55 (KEY_KPASTERISK) -> qnum:55 */
{Q_KEY_CODE_AUDIOMUTE, 0xa0}, /* qcode:Q_KEY_CODE_AUDIOMUTE (audiomute) -> linux:113 (KEY_MUTE) -> qnum:160 */
{Q_KEY_CODE_AUDIONEXT, 0x99}, /* qcode:Q_KEY_CODE_AUDIONEXT (audionext) -> linux:163 (KEY_NEXTSONG) -> qnum:153 */
{Q_KEY_CODE_AUDIOPLAY, 0xa2}, /* qcode:Q_KEY_CODE_AUDIOPLAY (audioplay) -> linux:164 (KEY_PLAYPAUSE) -> qnum:162 */
{Q_KEY_CODE_AUDIOPREV, 0x90}, /* qcode:Q_KEY_CODE_AUDIOPREV (audioprev) -> linux:165 (KEY_PREVIOUSSONG) -> qnum:144 */
{Q_KEY_CODE_AUDIOSTOP, 0xa4}, /* qcode:Q_KEY_CODE_AUDIOSTOP (audiostop) -> linux:166 (KEY_STOPCD) -> qnum:164 */
{Q_KEY_CODE_B, 0x30}, /* qcode:Q_KEY_CODE_B (b) -> linux:48 (KEY_B) -> qnum:48 */
{Q_KEY_CODE_BACKSLASH, 0x2b}, /* qcode:Q_KEY_CODE_BACKSLASH (backslash) -> linux:43 (KEY_BACKSLASH) -> qnum:43 */
{Q_KEY_CODE_BACKSPACE, 0xe}, /* qcode:Q_KEY_CODE_BACKSPACE (backspace) -> linux:14 (KEY_BACKSPACE) -> qnum:14 */
{Q_KEY_CODE_BRACKET_LEFT, 0x1a}, /* qcode:Q_KEY_CODE_BRACKET_LEFT (bracket_left) -> linux:26 (KEY_LEFTBRACE) -> qnum:26 */
{Q_KEY_CODE_BRACKET_RIGHT, 0x1b}, /* qcode:Q_KEY_CODE_BRACKET_RIGHT (bracket_right) -> linux:27 (KEY_RIGHTBRACE) -> qnum:27 */
{Q_KEY_CODE_C, 0x2e}, /* qcode:Q_KEY_CODE_C (c) -> linux:46 (KEY_C) -> qnum:46 */
{Q_KEY_CODE_CALCULATOR, 0xa1}, /* qcode:Q_KEY_CODE_CALCULATOR (calculator) -> linux:140 (KEY_CALC) -> qnum:161 */
{Q_KEY_CODE_CAPS_LOCK, 0x3a}, /* qcode:Q_KEY_CODE_CAPS_LOCK (caps_lock) -> linux:58 (KEY_CAPSLOCK) -> qnum:58 */
{Q_KEY_CODE_COMMA, 0x33}, /* qcode:Q_KEY_CODE_COMMA (comma) -> linux:51 (KEY_COMMA) -> qnum:51 */
{Q_KEY_CODE_COMPOSE, 0xdd}, /* qcode:Q_KEY_CODE_COMPOSE (compose) -> linux:127 (KEY_COMPOSE) -> qnum:221 */
{Q_KEY_CODE_COMPUTER, 0xeb}, /* qcode:Q_KEY_CODE_COMPUTER (computer) -> linux:157 (KEY_COMPUTER) -> qnum:235 */
{Q_KEY_CODE_COPY, 0xf8}, /* qcode:Q_KEY_CODE_COPY (copy) -> linux:133 (KEY_COPY) -> qnum:248 */
{Q_KEY_CODE_CTRL, 0x1d}, /* qcode:Q_KEY_CODE_CTRL (ctrl) -> linux:29 (KEY_LEFTCTRL) -> qnum:29 */
{Q_KEY_CODE_CTRL_R, 0x9d}, /* qcode:Q_KEY_CODE_CTRL_R (ctrl_r) -> linux:97 (KEY_RIGHTCTRL) -> qnum:157 */
{Q_KEY_CODE_CUT, 0xbc}, /* qcode:Q_KEY_CODE_CUT (cut) -> linux:137 (KEY_CUT) -> qnum:188 */
{Q_KEY_CODE_D, 0x20}, /* qcode:Q_KEY_CODE_D (d) -> linux:32 (KEY_D) -> qnum:32 */
{Q_KEY_CODE_DELETE, 0xd3}, /* qcode:Q_KEY_CODE_DELETE (delete) -> linux:111 (KEY_DELETE) -> qnum:211 */
{Q_KEY_CODE_DOT, 0x34}, /* qcode:Q_KEY_CODE_DOT (dot) -> linux:52 (KEY_DOT) -> qnum:52 */
{Q_KEY_CODE_DOWN, 0xd0}, /* qcode:Q_KEY_CODE_DOWN (down) -> linux:108 (KEY_DOWN) -> qnum:208 */
{Q_KEY_CODE_E, 0x12}, /* qcode:Q_KEY_CODE_E (e) -> linux:18 (KEY_E) -> qnum:18 */
{Q_KEY_CODE_END, 0xcf}, /* qcode:Q_KEY_CODE_END (end) -> linux:107 (KEY_END) -> qnum:207 */
{Q_KEY_CODE_EQUAL, 0xd}, /* qcode:Q_KEY_CODE_EQUAL (equal) -> linux:13 (KEY_EQUAL) -> qnum:13 */
{Q_KEY_CODE_ESC, 0x1}, /* qcode:Q_KEY_CODE_ESC (esc) -> linux:1 (KEY_ESC) -> qnum:1 */
{Q_KEY_CODE_F, 0x21}, /* qcode:Q_KEY_CODE_F (f) -> linux:33 (KEY_F) -> qnum:33 */
{Q_KEY_CODE_F1, 0x3b}, /* qcode:Q_KEY_CODE_F1 (f1) -> linux:59 (KEY_F1) -> qnum:59 */
{Q_KEY_CODE_F10, 0x44}, /* qcode:Q_KEY_CODE_F10 (f10) -> linux:68 (KEY_F10) -> qnum:68 */
{Q_KEY_CODE_F11, 0x57}, /* qcode:Q_KEY_CODE_F11 (f11) -> linux:87 (KEY_F11) -> qnum:87 */
{Q_KEY_CODE_F12, 0x58}, /* qcode:Q_KEY_CODE_F12 (f12) -> linux:88 (KEY_F12) -> qnum:88 */
{Q_KEY_CODE_F2, 0x3c}, /* qcode:Q_KEY_CODE_F2 (f2) -> linux:60 (KEY_F2) -> qnum:60 */
{Q_KEY_CODE_F3, 0x3d}, /* qcode:Q_KEY_CODE_F3 (f3) -> linux:61 (KEY_F3) -> qnum:61 */
{Q_KEY_CODE_F4, 0x3e}, /* qcode:Q_KEY_CODE_F4 (f4) -> linux:62 (KEY_F4) -> qnum:62 */
{Q_KEY_CODE_F5, 0x3f}, /* qcode:Q_KEY_CODE_F5 (f5) -> linux:63 (KEY_F5) -> qnum:63 */
{Q_KEY_CODE_F6, 0x40}, /* qcode:Q_KEY_CODE_F6 (f6) -> linux:64 (KEY_F6) -> qnum:64 */
{Q_KEY_CODE_F7, 0x41}, /* qcode:Q_KEY_CODE_F7 (f7) -> linux:65 (KEY_F7) -> qnum:65 */
{Q_KEY_CODE_F8, 0x42}, /* qcode:Q_KEY_CODE_F8 (f8) -> linux:66 (KEY_F8) -> qnum:66 */
{Q_KEY_CODE_F9, 0x43}, /* qcode:Q_KEY_CODE_F9 (f9) -> linux:67 (KEY_F9) -> qnum:67 */
{Q_KEY_CODE_FIND, 0xc1}, /* qcode:Q_KEY_CODE_FIND (find) -> linux:136 (KEY_FIND) -> qnum:193 */
{Q_KEY_CODE_FRONT, 0x8c}, /* qcode:Q_KEY_CODE_FRONT (front) -> linux:132 (KEY_FRONT) -> qnum:140 */
{Q_KEY_CODE_G, 0x22}, /* qcode:Q_KEY_CODE_G (g) -> linux:34 (KEY_G) -> qnum:34 */
{Q_KEY_CODE_GRAVE_ACCENT, 0x29}, /* qcode:Q_KEY_CODE_GRAVE_ACCENT (grave_accent) -> linux:41 (KEY_GRAVE) -> qnum:41 */
{Q_KEY_CODE_H, 0x23}, /* qcode:Q_KEY_CODE_H (h) -> linux:35 (KEY_H) -> qnum:35 */
{Q_KEY_CODE_HELP, 0xf5}, /* qcode:Q_KEY_CODE_HELP (help) -> linux:138 (KEY_HELP) -> qnum:245 */
{Q_KEY_CODE_HENKAN, 0x79}, /* qcode:Q_KEY_CODE_HENKAN (henkan) -> linux:92 (KEY_HENKAN) -> qnum:121 */
{Q_KEY_CODE_HIRAGANA, 0x77}, /* qcode:Q_KEY_CODE_HIRAGANA (hiragana) -> linux:91 (KEY_HIRAGANA) -> qnum:119 */
{Q_KEY_CODE_HOME, 0xc7}, /* qcode:Q_KEY_CODE_HOME (home) -> linux:102 (KEY_HOME) -> qnum:199 */
{Q_KEY_CODE_I, 0x17}, /* qcode:Q_KEY_CODE_I (i) -> linux:23 (KEY_I) -> qnum:23 */
{Q_KEY_CODE_INSERT, 0xd2}, /* qcode:Q_KEY_CODE_INSERT (insert) -> linux:110 (KEY_INSERT) -> qnum:210 */
{Q_KEY_CODE_J, 0x24}, /* qcode:Q_KEY_CODE_J (j) -> linux:36 (KEY_J) -> qnum:36 */
{Q_KEY_CODE_K, 0x25}, /* qcode:Q_KEY_CODE_K (k) -> linux:37 (KEY_K) -> qnum:37 */
{Q_KEY_CODE_KATAKANAHIRAGANA, 0x70}, /* qcode:Q_KEY_CODE_KATAKANAHIRAGANA (katakanahiragana) -> linux:93 (KEY_KATAKANAHIRAGANA) -> qnum:112 */
{Q_KEY_CODE_KP_0, 0x52}, /* qcode:Q_KEY_CODE_KP_0 (kp_0) -> linux:82 (KEY_KP0) -> qnum:82 */
{Q_KEY_CODE_KP_1, 0x4f}, /* qcode:Q_KEY_CODE_KP_1 (kp_1) -> linux:79 (KEY_KP1) -> qnum:79 */
{Q_KEY_CODE_KP_2, 0x50}, /* qcode:Q_KEY_CODE_KP_2 (kp_2) -> linux:80 (KEY_KP2) -> qnum:80 */
{Q_KEY_CODE_KP_3, 0x51}, /* qcode:Q_KEY_CODE_KP_3 (kp_3) -> linux:81 (KEY_KP3) -> qnum:81 */
{Q_KEY_CODE_KP_4, 0x4b}, /* qcode:Q_KEY_CODE_KP_4 (kp_4) -> linux:75 (KEY_KP4) -> qnum:75 */
{Q_KEY_CODE_KP_5, 0x4c}, /* qcode:Q_KEY_CODE_KP_5 (kp_5) -> linux:76 (KEY_KP5) -> qnum:76 */
{Q_KEY_CODE_KP_6, 0x4d}, /* qcode:Q_KEY_CODE_KP_6 (kp_6) -> linux:77 (KEY_KP6) -> qnum:77 */
{Q_KEY_CODE_KP_7, 0x47}, /* qcode:Q_KEY_CODE_KP_7 (kp_7) -> linux:71 (KEY_KP7) -> qnum:71 */
{Q_KEY_CODE_KP_8, 0x48}, /* qcode:Q_KEY_CODE_KP_8 (kp_8) -> linux:72 (KEY_KP8) -> qnum:72 */
{Q_KEY_CODE_KP_9, 0x49}, /* qcode:Q_KEY_CODE_KP_9 (kp_9) -> linux:73 (KEY_KP9) -> qnum:73 */
{Q_KEY_CODE_KP_ADD, 0x4e}, /* qcode:Q_KEY_CODE_KP_ADD (kp_add) -> linux:78 (KEY_KPPLUS) -> qnum:78 */
{Q_KEY_CODE_KP_COMMA, 0x7e}, /* qcode:Q_KEY_CODE_KP_COMMA (kp_comma) -> linux:121 (KEY_KPCOMMA) -> qnum:126 */
{Q_KEY_CODE_KP_DECIMAL, 0x53}, /* qcode:Q_KEY_CODE_KP_DECIMAL (kp_decimal) -> linux:83 (KEY_KPDOT) -> qnum:83 */
{Q_KEY_CODE_KP_DIVIDE, 0xb5}, /* qcode:Q_KEY_CODE_KP_DIVIDE (kp_divide) -> linux:98 (KEY_KPSLASH) -> qnum:181 */
{Q_KEY_CODE_KP_ENTER, 0x9c}, /* qcode:Q_KEY_CODE_KP_ENTER (kp_enter) -> linux:96 (KEY_KPENTER) -> qnum:156 */
{Q_KEY_CODE_KP_EQUALS, 0x59}, /* qcode:Q_KEY_CODE_KP_EQUALS (kp_equals) -> linux:117 (KEY_KPEQUAL) -> qnum:89 */
{Q_KEY_CODE_KP_MULTIPLY, 0x37}, /* qcode:Q_KEY_CODE_KP_MULTIPLY (kp_multiply) -> linux:55 (KEY_KPASTERISK) -> qnum:55 */
{Q_KEY_CODE_KP_SUBTRACT, 0x4a}, /* qcode:Q_KEY_CODE_KP_SUBTRACT (kp_subtract) -> linux:74 (KEY_KPMINUS) -> qnum:74 */
{Q_KEY_CODE_L, 0x26}, /* qcode:Q_KEY_CODE_L (l) -> linux:38 (KEY_L) -> qnum:38 */
{Q_KEY_CODE_LEFT, 0xcb}, /* qcode:Q_KEY_CODE_LEFT (left) -> linux:105 (KEY_LEFT) -> qnum:203 */
{Q_KEY_CODE_LESS, 0x56}, /* qcode:Q_KEY_CODE_LESS (less) -> linux:86 (KEY_102ND) -> qnum:86 */
{Q_KEY_CODE_LF, 0x5b}, /* qcode:Q_KEY_CODE_LF (lf) -> linux:101 (KEY_LINEFEED) -> qnum:91 */
{Q_KEY_CODE_M, 0x32}, /* qcode:Q_KEY_CODE_M (m) -> linux:50 (KEY_M) -> qnum:50 */
{Q_KEY_CODE_MAIL, 0xec}, /* qcode:Q_KEY_CODE_MAIL (mail) -> linux:155 (KEY_MAIL) -> qnum:236 */
{Q_KEY_CODE_MEDIASELECT, 0xed}, /* qcode:Q_KEY_CODE_MEDIASELECT (mediaselect) -> linux:226 (KEY_MEDIA) -> qnum:237 */
{Q_KEY_CODE_MENU, 0x9e}, /* qcode:Q_KEY_CODE_MENU (menu) -> linux:139 (KEY_MENU) -> qnum:158 */
{Q_KEY_CODE_META_L, 0xdb}, /* qcode:Q_KEY_CODE_META_L (meta_l) -> linux:125 (KEY_LEFTMETA) -> qnum:219 */
{Q_KEY_CODE_META_R, 0xdc}, /* qcode:Q_KEY_CODE_META_R (meta_r) -> linux:126 (KEY_RIGHTMETA) -> qnum:220 */
{Q_KEY_CODE_MINUS, 0xc}, /* qcode:Q_KEY_CODE_MINUS (minus) -> linux:12 (KEY_MINUS) -> qnum:12 */
{Q_KEY_CODE_MUHENKAN, 0x7b}, /* qcode:Q_KEY_CODE_MUHENKAN (muhenkan) -> linux:94 (KEY_MUHENKAN) -> qnum:123 */
{Q_KEY_CODE_N, 0x31}, /* qcode:Q_KEY_CODE_N (n) -> linux:49 (KEY_N) -> qnum:49 */
{Q_KEY_CODE_NUM_LOCK, 0x45}, /* qcode:Q_KEY_CODE_NUM_LOCK (num_lock) -> linux:69 (KEY_NUMLOCK) -> qnum:69 */
{Q_KEY_CODE_O, 0x18}, /* qcode:Q_KEY_CODE_O (o) -> linux:24 (KEY_O) -> qnum:24 */
{Q_KEY_CODE_OPEN, 0x64}, /* qcode:Q_KEY_CODE_OPEN (open) -> linux:134 (KEY_OPEN) -> qnum:100 */
{Q_KEY_CODE_P, 0x19}, /* qcode:Q_KEY_CODE_P (p) -> linux:25 (KEY_P) -> qnum:25 */
{Q_KEY_CODE_PASTE, 0x65}, /* qcode:Q_KEY_CODE_PASTE (paste) -> linux:135 (KEY_PASTE) -> qnum:101 */
{Q_KEY_CODE_PAUSE, 0xc6}, /* qcode:Q_KEY_CODE_PAUSE (pause) -> linux:119 (KEY_PAUSE) -> qnum:198 */
{Q_KEY_CODE_PGDN, 0xd1}, /* qcode:Q_KEY_CODE_PGDN (pgdn) -> linux:109 (KEY_PAGEDOWN) -> qnum:209 */
{Q_KEY_CODE_PGUP, 0xc9}, /* qcode:Q_KEY_CODE_PGUP (pgup) -> linux:104 (KEY_PAGEUP) -> qnum:201 */
{Q_KEY_CODE_POWER, 0xde}, /* qcode:Q_KEY_CODE_POWER (power) -> linux:116 (KEY_POWER) -> qnum:222 */
{Q_KEY_CODE_PRINT, 0x54}, /* qcode:Q_KEY_CODE_PRINT (sysrq) -> linux:99 (KEY_SYSRQ) -> qnum:84 */
{Q_KEY_CODE_PROPS, 0x86}, /* qcode:Q_KEY_CODE_PROPS (props) -> linux:130 (KEY_PROPS) -> qnum:134 */
{Q_KEY_CODE_Q, 0x10}, /* qcode:Q_KEY_CODE_Q (q) -> linux:16 (KEY_Q) -> qnum:16 */
{Q_KEY_CODE_R, 0x13}, /* qcode:Q_KEY_CODE_R (r) -> linux:19 (KEY_R) -> qnum:19 */
{Q_KEY_CODE_RET, 0x1c}, /* qcode:Q_KEY_CODE_RET (ret) -> linux:28 (KEY_ENTER) -> qnum:28 */
{Q_KEY_CODE_RIGHT, 0xcd}, /* qcode:Q_KEY_CODE_RIGHT (right) -> linux:106 (KEY_RIGHT) -> qnum:205 */
{Q_KEY_CODE_RO, 0x73}, /* qcode:Q_KEY_CODE_RO (ro) -> linux:89 (KEY_RO) -> qnum:115 */
{Q_KEY_CODE_S, 0x1f}, /* qcode:Q_KEY_CODE_S (s) -> linux:31 (KEY_S) -> qnum:31 */
{Q_KEY_CODE_SCROLL_LOCK, 0x46}, /* qcode:Q_KEY_CODE_SCROLL_LOCK (scroll_lock) -> linux:70 (KEY_SCROLLLOCK) -> qnum:70 */
{Q_KEY_CODE_SEMICOLON, 0x27}, /* qcode:Q_KEY_CODE_SEMICOLON (semicolon) -> linux:39 (KEY_SEMICOLON) -> qnum:39 */
{Q_KEY_CODE_SHIFT, 0x2a}, /* qcode:Q_KEY_CODE_SHIFT (shift) -> linux:42 (KEY_LEFTSHIFT) -> qnum:42 */
{Q_KEY_CODE_SHIFT_R, 0x36}, /* qcode:Q_KEY_CODE_SHIFT_R (shift_r) -> linux:54 (KEY_RIGHTSHIFT) -> qnum:54 */
{Q_KEY_CODE_SLASH, 0x35}, /* qcode:Q_KEY_CODE_SLASH (slash) -> linux:53 (KEY_SLASH) -> qnum:53 */
{Q_KEY_CODE_SLEEP, 0xdf}, /* qcode:Q_KEY_CODE_SLEEP (sleep) -> linux:142 (KEY_SLEEP) -> qnum:223 */
{Q_KEY_CODE_SPC, 0x39}, /* qcode:Q_KEY_CODE_SPC (spc) -> linux:57 (KEY_SPACE) -> qnum:57 */
{Q_KEY_CODE_STOP, 0xe8}, /* qcode:Q_KEY_CODE_STOP (stop) -> linux:128 (KEY_STOP) -> qnum:232 */
{Q_KEY_CODE_SYSRQ, 0x54}, /* qcode:Q_KEY_CODE_SYSRQ (sysrq) -> linux:99 (KEY_SYSRQ) -> qnum:84 */
{Q_KEY_CODE_T, 0x14}, /* qcode:Q_KEY_CODE_T (t) -> linux:20 (KEY_T) -> qnum:20 */
{Q_KEY_CODE_TAB, 0xf}, /* qcode:Q_KEY_CODE_TAB (tab) -> linux:15 (KEY_TAB) -> qnum:15 */
{Q_KEY_CODE_U, 0x16}, /* qcode:Q_KEY_CODE_U (u) -> linux:22 (KEY_U) -> qnum:22 */
{Q_KEY_CODE_UNDO, 0x87}, /* qcode:Q_KEY_CODE_UNDO (undo) -> linux:131 (KEY_UNDO) -> qnum:135 */
{Q_KEY_CODE_UP, 0xc8}, /* qcode:Q_KEY_CODE_UP (up) -> linux:103 (KEY_UP) -> qnum:200 */
{Q_KEY_CODE_V, 0x2f}, /* qcode:Q_KEY_CODE_V (v) -> linux:47 (KEY_V) -> qnum:47 */
{Q_KEY_CODE_VOLUMEDOWN, 0xae}, /* qcode:Q_KEY_CODE_VOLUMEDOWN (volumedown) -> linux:114 (KEY_VOLUMEDOWN) -> qnum:174 */
{Q_KEY_CODE_VOLUMEUP, 0xb0}, /* qcode:Q_KEY_CODE_VOLUMEUP (volumeup) -> linux:115 (KEY_VOLUMEUP) -> qnum:176 */
{Q_KEY_CODE_W, 0x11}, /* qcode:Q_KEY_CODE_W (w) -> linux:17 (KEY_W) -> qnum:17 */
{Q_KEY_CODE_WAKE, 0xe3}, /* qcode:Q_KEY_CODE_WAKE (wake) -> linux:143 (KEY_WAKEUP) -> qnum:227 */
{Q_KEY_CODE_X, 0x2d}, /* qcode:Q_KEY_CODE_X (x) -> linux:45 (KEY_X) -> qnum:45 */
{Q_KEY_CODE_Y, 0x15}, /* qcode:Q_KEY_CODE_Y (y) -> linux:21 (KEY_Y) -> qnum:21 */
{Q_KEY_CODE_YEN, 0x7d}, /* qcode:Q_KEY_CODE_YEN (yen) -> linux:124 (KEY_YEN) -> qnum:125 */
{Q_KEY_CODE_Z, 0x2c}, /* qcode:Q_KEY_CODE_Z (z) -> linux:44 (KEY_Z) -> qnum:44 */
{Q_KEY_CODE_0, 0xb}, /* qcode:Q_KEY_CODE_0 (0) -> linux:11 (KEY_0) -> qnum:11 */
{Q_KEY_CODE_1, 0x2}, /* qcode:Q_KEY_CODE_1 (1) -> linux:2 (KEY_1) -> qnum:2 */
{Q_KEY_CODE_2, 0x3}, /* qcode:Q_KEY_CODE_2 (2) -> linux:3 (KEY_2) -> qnum:3 */
{Q_KEY_CODE_3, 0x4}, /* qcode:Q_KEY_CODE_3 (3) -> linux:4 (KEY_3) -> qnum:4 */
{Q_KEY_CODE_4, 0x5}, /* qcode:Q_KEY_CODE_4 (4) -> linux:5 (KEY_4) -> qnum:5 */
{Q_KEY_CODE_5, 0x6}, /* qcode:Q_KEY_CODE_5 (5) -> linux:6 (KEY_5) -> qnum:6 */
{Q_KEY_CODE_6, 0x7}, /* qcode:Q_KEY_CODE_6 (6) -> linux:7 (KEY_6) -> qnum:7 */
{Q_KEY_CODE_7, 0x8}, /* qcode:Q_KEY_CODE_7 (7) -> linux:8 (KEY_7) -> qnum:8 */
{Q_KEY_CODE_8, 0x9}, /* qcode:Q_KEY_CODE_8 (8) -> linux:9 (KEY_8) -> qnum:9 */
{Q_KEY_CODE_9, 0xa}, /* qcode:Q_KEY_CODE_9 (9) -> linux:10 (KEY_9) -> qnum:10 */
{Q_KEY_CODE_A, 0x1e}, /* qcode:Q_KEY_CODE_A (a) -> linux:30 (KEY_A) -> qnum:30 */
{Q_KEY_CODE_AC_BACK, 0xea}, /* qcode:Q_KEY_CODE_AC_BACK (ac_back) -> linux:158 (KEY_BACK) -> qnum:234 */
{Q_KEY_CODE_AC_BOOKMARKS, 0xe6}, /* qcode:Q_KEY_CODE_AC_BOOKMARKS (ac_bookmarks) -> linux:156 (KEY_BOOKMARKS) -> qnum:230 */
{Q_KEY_CODE_AC_FORWARD, 0xe9}, /* qcode:Q_KEY_CODE_AC_FORWARD (ac_forward) -> linux:159 (KEY_FORWARD) -> qnum:233 */
{Q_KEY_CODE_AC_HOME, 0xb2}, /* qcode:Q_KEY_CODE_AC_HOME (ac_home) -> linux:172 (KEY_HOMEPAGE) -> qnum:178 */
{Q_KEY_CODE_AC_REFRESH, 0xe7}, /* qcode:Q_KEY_CODE_AC_REFRESH (ac_refresh) -> linux:173 (KEY_REFRESH) -> qnum:231 */
{Q_KEY_CODE_AGAIN, 0x85}, /* qcode:Q_KEY_CODE_AGAIN (again) -> linux:129 (KEY_AGAIN) -> qnum:133 */
{Q_KEY_CODE_ALT, 0x38}, /* qcode:Q_KEY_CODE_ALT (alt) -> linux:56 (KEY_LEFTALT) -> qnum:56 */
{Q_KEY_CODE_ALT_R, 0xb8}, /* qcode:Q_KEY_CODE_ALT_R (alt_r) -> linux:100 (KEY_RIGHTALT) -> qnum:184 */
{Q_KEY_CODE_APOSTROPHE, 0x28}, /* qcode:Q_KEY_CODE_APOSTROPHE (apostrophe) -> linux:40 (KEY_APOSTROPHE) -> qnum:40 */
{Q_KEY_CODE_ASTERISK, 0x37}, /* qcode:Q_KEY_CODE_ASTERISK (kp_multiply) -> linux:55 (KEY_KPASTERISK) -> qnum:55 */
{Q_KEY_CODE_AUDIOMUTE, 0xa0}, /* qcode:Q_KEY_CODE_AUDIOMUTE (audiomute) -> linux:113 (KEY_MUTE) -> qnum:160 */
{Q_KEY_CODE_AUDIONEXT, 0x99}, /* qcode:Q_KEY_CODE_AUDIONEXT (audionext) -> linux:163 (KEY_NEXTSONG) -> qnum:153 */
{Q_KEY_CODE_AUDIOPLAY, 0xa2}, /* qcode:Q_KEY_CODE_AUDIOPLAY (audioplay) -> linux:164 (KEY_PLAYPAUSE) -> qnum:162 */
{Q_KEY_CODE_AUDIOPREV, 0x90}, /* qcode:Q_KEY_CODE_AUDIOPREV (audioprev) -> linux:165 (KEY_PREVIOUSSONG) -> qnum:144 */
{Q_KEY_CODE_AUDIOSTOP, 0xa4}, /* qcode:Q_KEY_CODE_AUDIOSTOP (audiostop) -> linux:166 (KEY_STOPCD) -> qnum:164 */
{Q_KEY_CODE_B, 0x30}, /* qcode:Q_KEY_CODE_B (b) -> linux:48 (KEY_B) -> qnum:48 */
{Q_KEY_CODE_BACKSLASH, 0x2b}, /* qcode:Q_KEY_CODE_BACKSLASH (backslash) -> linux:43 (KEY_BACKSLASH) -> qnum:43 */
{Q_KEY_CODE_BACKSPACE, 0xe}, /* qcode:Q_KEY_CODE_BACKSPACE (backspace) -> linux:14 (KEY_BACKSPACE) -> qnum:14 */
{Q_KEY_CODE_BRACKET_LEFT, 0x1a}, /* qcode:Q_KEY_CODE_BRACKET_LEFT (bracket_left) -> linux:26 (KEY_LEFTBRACE) -> qnum:26 */
{Q_KEY_CODE_BRACKET_RIGHT, 0x1b}, /* qcode:Q_KEY_CODE_BRACKET_RIGHT (bracket_right) -> linux:27 (KEY_RIGHTBRACE) -> qnum:27 */
{Q_KEY_CODE_C, 0x2e}, /* qcode:Q_KEY_CODE_C (c) -> linux:46 (KEY_C) -> qnum:46 */
{Q_KEY_CODE_CALCULATOR, 0xa1}, /* qcode:Q_KEY_CODE_CALCULATOR (calculator) -> linux:140 (KEY_CALC) -> qnum:161 */
{Q_KEY_CODE_CAPS_LOCK, 0x3a}, /* qcode:Q_KEY_CODE_CAPS_LOCK (caps_lock) -> linux:58 (KEY_CAPSLOCK) -> qnum:58 */
{Q_KEY_CODE_COMMA, 0x33}, /* qcode:Q_KEY_CODE_COMMA (comma) -> linux:51 (KEY_COMMA) -> qnum:51 */
{Q_KEY_CODE_COMPOSE, 0xdd}, /* qcode:Q_KEY_CODE_COMPOSE (compose) -> linux:127 (KEY_COMPOSE) -> qnum:221 */
{Q_KEY_CODE_COMPUTER, 0xeb}, /* qcode:Q_KEY_CODE_COMPUTER (computer) -> linux:157 (KEY_COMPUTER) -> qnum:235 */
{Q_KEY_CODE_COPY, 0xf8}, /* qcode:Q_KEY_CODE_COPY (copy) -> linux:133 (KEY_COPY) -> qnum:248 */
{Q_KEY_CODE_CTRL, 0x1d}, /* qcode:Q_KEY_CODE_CTRL (ctrl) -> linux:29 (KEY_LEFTCTRL) -> qnum:29 */
{Q_KEY_CODE_CTRL_R, 0x9d}, /* qcode:Q_KEY_CODE_CTRL_R (ctrl_r) -> linux:97 (KEY_RIGHTCTRL) -> qnum:157 */
{Q_KEY_CODE_CUT, 0xbc}, /* qcode:Q_KEY_CODE_CUT (cut) -> linux:137 (KEY_CUT) -> qnum:188 */
{Q_KEY_CODE_D, 0x20}, /* qcode:Q_KEY_CODE_D (d) -> linux:32 (KEY_D) -> qnum:32 */
{Q_KEY_CODE_DELETE, 0xd3}, /* qcode:Q_KEY_CODE_DELETE (delete) -> linux:111 (KEY_DELETE) -> qnum:211 */
{Q_KEY_CODE_DOT, 0x34}, /* qcode:Q_KEY_CODE_DOT (dot) -> linux:52 (KEY_DOT) -> qnum:52 */
{Q_KEY_CODE_DOWN, 0xd0}, /* qcode:Q_KEY_CODE_DOWN (down) -> linux:108 (KEY_DOWN) -> qnum:208 */
{Q_KEY_CODE_E, 0x12}, /* qcode:Q_KEY_CODE_E (e) -> linux:18 (KEY_E) -> qnum:18 */
{Q_KEY_CODE_END, 0xcf}, /* qcode:Q_KEY_CODE_END (end) -> linux:107 (KEY_END) -> qnum:207 */
{Q_KEY_CODE_EQUAL, 0xd}, /* qcode:Q_KEY_CODE_EQUAL (equal) -> linux:13 (KEY_EQUAL) -> qnum:13 */
{Q_KEY_CODE_ESC, 0x1}, /* qcode:Q_KEY_CODE_ESC (esc) -> linux:1 (KEY_ESC) -> qnum:1 */
{Q_KEY_CODE_F, 0x21}, /* qcode:Q_KEY_CODE_F (f) -> linux:33 (KEY_F) -> qnum:33 */
{Q_KEY_CODE_F1, 0x3b}, /* qcode:Q_KEY_CODE_F1 (f1) -> linux:59 (KEY_F1) -> qnum:59 */
{Q_KEY_CODE_F10, 0x44}, /* qcode:Q_KEY_CODE_F10 (f10) -> linux:68 (KEY_F10) -> qnum:68 */
{Q_KEY_CODE_F11, 0x57}, /* qcode:Q_KEY_CODE_F11 (f11) -> linux:87 (KEY_F11) -> qnum:87 */
{Q_KEY_CODE_F12, 0x58}, /* qcode:Q_KEY_CODE_F12 (f12) -> linux:88 (KEY_F12) -> qnum:88 */
{Q_KEY_CODE_F2, 0x3c}, /* qcode:Q_KEY_CODE_F2 (f2) -> linux:60 (KEY_F2) -> qnum:60 */
{Q_KEY_CODE_F3, 0x3d}, /* qcode:Q_KEY_CODE_F3 (f3) -> linux:61 (KEY_F3) -> qnum:61 */
{Q_KEY_CODE_F4, 0x3e}, /* qcode:Q_KEY_CODE_F4 (f4) -> linux:62 (KEY_F4) -> qnum:62 */
{Q_KEY_CODE_F5, 0x3f}, /* qcode:Q_KEY_CODE_F5 (f5) -> linux:63 (KEY_F5) -> qnum:63 */
{Q_KEY_CODE_F6, 0x40}, /* qcode:Q_KEY_CODE_F6 (f6) -> linux:64 (KEY_F6) -> qnum:64 */
{Q_KEY_CODE_F7, 0x41}, /* qcode:Q_KEY_CODE_F7 (f7) -> linux:65 (KEY_F7) -> qnum:65 */
{Q_KEY_CODE_F8, 0x42}, /* qcode:Q_KEY_CODE_F8 (f8) -> linux:66 (KEY_F8) -> qnum:66 */
{Q_KEY_CODE_F9, 0x43}, /* qcode:Q_KEY_CODE_F9 (f9) -> linux:67 (KEY_F9) -> qnum:67 */
{Q_KEY_CODE_FIND, 0xc1}, /* qcode:Q_KEY_CODE_FIND (find) -> linux:136 (KEY_FIND) -> qnum:193 */
{Q_KEY_CODE_FRONT, 0x8c}, /* qcode:Q_KEY_CODE_FRONT (front) -> linux:132 (KEY_FRONT) -> qnum:140 */
{Q_KEY_CODE_G, 0x22}, /* qcode:Q_KEY_CODE_G (g) -> linux:34 (KEY_G) -> qnum:34 */
{Q_KEY_CODE_GRAVE_ACCENT, 0x29}, /* qcode:Q_KEY_CODE_GRAVE_ACCENT (grave_accent) -> linux:41 (KEY_GRAVE) -> qnum:41 */
{Q_KEY_CODE_H, 0x23}, /* qcode:Q_KEY_CODE_H (h) -> linux:35 (KEY_H) -> qnum:35 */
{Q_KEY_CODE_HELP, 0xf5}, /* qcode:Q_KEY_CODE_HELP (help) -> linux:138 (KEY_HELP) -> qnum:245 */
{Q_KEY_CODE_HENKAN, 0x79}, /* qcode:Q_KEY_CODE_HENKAN (henkan) -> linux:92 (KEY_HENKAN) -> qnum:121 */
{Q_KEY_CODE_HIRAGANA, 0x77}, /* qcode:Q_KEY_CODE_HIRAGANA (hiragana) -> linux:91 (KEY_HIRAGANA) -> qnum:119 */
{Q_KEY_CODE_HOME, 0xc7}, /* qcode:Q_KEY_CODE_HOME (home) -> linux:102 (KEY_HOME) -> qnum:199 */
{Q_KEY_CODE_I, 0x17}, /* qcode:Q_KEY_CODE_I (i) -> linux:23 (KEY_I) -> qnum:23 */
{Q_KEY_CODE_INSERT, 0xd2}, /* qcode:Q_KEY_CODE_INSERT (insert) -> linux:110 (KEY_INSERT) -> qnum:210 */
{Q_KEY_CODE_J, 0x24}, /* qcode:Q_KEY_CODE_J (j) -> linux:36 (KEY_J) -> qnum:36 */
{Q_KEY_CODE_K, 0x25}, /* qcode:Q_KEY_CODE_K (k) -> linux:37 (KEY_K) -> qnum:37 */
{Q_KEY_CODE_KATAKANAHIRAGANA, 0x70}, /* qcode:Q_KEY_CODE_KATAKANAHIRAGANA (katakanahiragana) -> linux:93 (KEY_KATAKANAHIRAGANA) -> qnum:112 */
{Q_KEY_CODE_KP_0, 0x52}, /* qcode:Q_KEY_CODE_KP_0 (kp_0) -> linux:82 (KEY_KP0) -> qnum:82 */
{Q_KEY_CODE_KP_1, 0x4f}, /* qcode:Q_KEY_CODE_KP_1 (kp_1) -> linux:79 (KEY_KP1) -> qnum:79 */
{Q_KEY_CODE_KP_2, 0x50}, /* qcode:Q_KEY_CODE_KP_2 (kp_2) -> linux:80 (KEY_KP2) -> qnum:80 */
{Q_KEY_CODE_KP_3, 0x51}, /* qcode:Q_KEY_CODE_KP_3 (kp_3) -> linux:81 (KEY_KP3) -> qnum:81 */
{Q_KEY_CODE_KP_4, 0x4b}, /* qcode:Q_KEY_CODE_KP_4 (kp_4) -> linux:75 (KEY_KP4) -> qnum:75 */
{Q_KEY_CODE_KP_5, 0x4c}, /* qcode:Q_KEY_CODE_KP_5 (kp_5) -> linux:76 (KEY_KP5) -> qnum:76 */
{Q_KEY_CODE_KP_6, 0x4d}, /* qcode:Q_KEY_CODE_KP_6 (kp_6) -> linux:77 (KEY_KP6) -> qnum:77 */
{Q_KEY_CODE_KP_7, 0x47}, /* qcode:Q_KEY_CODE_KP_7 (kp_7) -> linux:71 (KEY_KP7) -> qnum:71 */
{Q_KEY_CODE_KP_8, 0x48}, /* qcode:Q_KEY_CODE_KP_8 (kp_8) -> linux:72 (KEY_KP8) -> qnum:72 */
{Q_KEY_CODE_KP_9, 0x49}, /* qcode:Q_KEY_CODE_KP_9 (kp_9) -> linux:73 (KEY_KP9) -> qnum:73 */
{Q_KEY_CODE_KP_ADD, 0x4e}, /* qcode:Q_KEY_CODE_KP_ADD (kp_add) -> linux:78 (KEY_KPPLUS) -> qnum:78 */
{Q_KEY_CODE_KP_COMMA, 0x7e}, /* qcode:Q_KEY_CODE_KP_COMMA (kp_comma) -> linux:121 (KEY_KPCOMMA) -> qnum:126 */
{Q_KEY_CODE_KP_DECIMAL, 0x53}, /* qcode:Q_KEY_CODE_KP_DECIMAL (kp_decimal) -> linux:83 (KEY_KPDOT) -> qnum:83 */
{Q_KEY_CODE_KP_DIVIDE, 0xb5}, /* qcode:Q_KEY_CODE_KP_DIVIDE (kp_divide) -> linux:98 (KEY_KPSLASH) -> qnum:181 */
{Q_KEY_CODE_KP_ENTER, 0x9c}, /* qcode:Q_KEY_CODE_KP_ENTER (kp_enter) -> linux:96 (KEY_KPENTER) -> qnum:156 */
{Q_KEY_CODE_KP_EQUALS, 0x59}, /* qcode:Q_KEY_CODE_KP_EQUALS (kp_equals) -> linux:117 (KEY_KPEQUAL) -> qnum:89 */
{Q_KEY_CODE_KP_MULTIPLY, 0x37}, /* qcode:Q_KEY_CODE_KP_MULTIPLY (kp_multiply) -> linux:55 (KEY_KPASTERISK) -> qnum:55 */
{Q_KEY_CODE_KP_SUBTRACT, 0x4a}, /* qcode:Q_KEY_CODE_KP_SUBTRACT (kp_subtract) -> linux:74 (KEY_KPMINUS) -> qnum:74 */
{Q_KEY_CODE_L, 0x26}, /* qcode:Q_KEY_CODE_L (l) -> linux:38 (KEY_L) -> qnum:38 */
{Q_KEY_CODE_LEFT, 0xcb}, /* qcode:Q_KEY_CODE_LEFT (left) -> linux:105 (KEY_LEFT) -> qnum:203 */
{Q_KEY_CODE_LESS, 0x56}, /* qcode:Q_KEY_CODE_LESS (less) -> linux:86 (KEY_102ND) -> qnum:86 */
{Q_KEY_CODE_LF, 0x5b}, /* qcode:Q_KEY_CODE_LF (lf) -> linux:101 (KEY_LINEFEED) -> qnum:91 */
{Q_KEY_CODE_M, 0x32}, /* qcode:Q_KEY_CODE_M (m) -> linux:50 (KEY_M) -> qnum:50 */
{Q_KEY_CODE_MAIL, 0xec}, /* qcode:Q_KEY_CODE_MAIL (mail) -> linux:155 (KEY_MAIL) -> qnum:236 */
{Q_KEY_CODE_MEDIASELECT, 0xed}, /* qcode:Q_KEY_CODE_MEDIASELECT (mediaselect) -> linux:226 (KEY_MEDIA) -> qnum:237 */
{Q_KEY_CODE_MENU, 0x9e}, /* qcode:Q_KEY_CODE_MENU (menu) -> linux:139 (KEY_MENU) -> qnum:158 */
{Q_KEY_CODE_META_L, 0xdb}, /* qcode:Q_KEY_CODE_META_L (meta_l) -> linux:125 (KEY_LEFTMETA) -> qnum:219 */
{Q_KEY_CODE_META_R, 0xdc}, /* qcode:Q_KEY_CODE_META_R (meta_r) -> linux:126 (KEY_RIGHTMETA) -> qnum:220 */
{Q_KEY_CODE_MINUS, 0xc}, /* qcode:Q_KEY_CODE_MINUS (minus) -> linux:12 (KEY_MINUS) -> qnum:12 */
{Q_KEY_CODE_MUHENKAN, 0x7b}, /* qcode:Q_KEY_CODE_MUHENKAN (muhenkan) -> linux:94 (KEY_MUHENKAN) -> qnum:123 */
{Q_KEY_CODE_N, 0x31}, /* qcode:Q_KEY_CODE_N (n) -> linux:49 (KEY_N) -> qnum:49 */
{Q_KEY_CODE_NUM_LOCK, 0x45}, /* qcode:Q_KEY_CODE_NUM_LOCK (num_lock) -> linux:69 (KEY_NUMLOCK) -> qnum:69 */
{Q_KEY_CODE_O, 0x18}, /* qcode:Q_KEY_CODE_O (o) -> linux:24 (KEY_O) -> qnum:24 */
{Q_KEY_CODE_OPEN, 0x64}, /* qcode:Q_KEY_CODE_OPEN (open) -> linux:134 (KEY_OPEN) -> qnum:100 */
{Q_KEY_CODE_P, 0x19}, /* qcode:Q_KEY_CODE_P (p) -> linux:25 (KEY_P) -> qnum:25 */
{Q_KEY_CODE_PASTE, 0x65}, /* qcode:Q_KEY_CODE_PASTE (paste) -> linux:135 (KEY_PASTE) -> qnum:101 */
{Q_KEY_CODE_PAUSE, 0xc6}, /* qcode:Q_KEY_CODE_PAUSE (pause) -> linux:119 (KEY_PAUSE) -> qnum:198 */
{Q_KEY_CODE_PGDN, 0xd1}, /* qcode:Q_KEY_CODE_PGDN (pgdn) -> linux:109 (KEY_PAGEDOWN) -> qnum:209 */
{Q_KEY_CODE_PGUP, 0xc9}, /* qcode:Q_KEY_CODE_PGUP (pgup) -> linux:104 (KEY_PAGEUP) -> qnum:201 */
{Q_KEY_CODE_POWER, 0xde}, /* qcode:Q_KEY_CODE_POWER (power) -> linux:116 (KEY_POWER) -> qnum:222 */
{Q_KEY_CODE_PRINT, 0x54}, /* qcode:Q_KEY_CODE_PRINT (sysrq) -> linux:99 (KEY_SYSRQ) -> qnum:84 */
{Q_KEY_CODE_PROPS, 0x86}, /* qcode:Q_KEY_CODE_PROPS (props) -> linux:130 (KEY_PROPS) -> qnum:134 */
{Q_KEY_CODE_Q, 0x10}, /* qcode:Q_KEY_CODE_Q (q) -> linux:16 (KEY_Q) -> qnum:16 */
{Q_KEY_CODE_R, 0x13}, /* qcode:Q_KEY_CODE_R (r) -> linux:19 (KEY_R) -> qnum:19 */
{Q_KEY_CODE_RET, 0x1c}, /* qcode:Q_KEY_CODE_RET (ret) -> linux:28 (KEY_ENTER) -> qnum:28 */
{Q_KEY_CODE_RIGHT, 0xcd}, /* qcode:Q_KEY_CODE_RIGHT (right) -> linux:106 (KEY_RIGHT) -> qnum:205 */
{Q_KEY_CODE_RO, 0x73}, /* qcode:Q_KEY_CODE_RO (ro) -> linux:89 (KEY_RO) -> qnum:115 */
{Q_KEY_CODE_S, 0x1f}, /* qcode:Q_KEY_CODE_S (s) -> linux:31 (KEY_S) -> qnum:31 */
{Q_KEY_CODE_SCROLL_LOCK, 0x46}, /* qcode:Q_KEY_CODE_SCROLL_LOCK (scroll_lock) -> linux:70 (KEY_SCROLLLOCK) -> qnum:70 */
{Q_KEY_CODE_SEMICOLON, 0x27}, /* qcode:Q_KEY_CODE_SEMICOLON (semicolon) -> linux:39 (KEY_SEMICOLON) -> qnum:39 */
{Q_KEY_CODE_SHIFT, 0x2a}, /* qcode:Q_KEY_CODE_SHIFT (shift) -> linux:42 (KEY_LEFTSHIFT) -> qnum:42 */
{Q_KEY_CODE_SHIFT_R, 0x36}, /* qcode:Q_KEY_CODE_SHIFT_R (shift_r) -> linux:54 (KEY_RIGHTSHIFT) -> qnum:54 */
{Q_KEY_CODE_SLASH, 0x35}, /* qcode:Q_KEY_CODE_SLASH (slash) -> linux:53 (KEY_SLASH) -> qnum:53 */
{Q_KEY_CODE_SLEEP, 0xdf}, /* qcode:Q_KEY_CODE_SLEEP (sleep) -> linux:142 (KEY_SLEEP) -> qnum:223 */
{Q_KEY_CODE_SPC, 0x39}, /* qcode:Q_KEY_CODE_SPC (spc) -> linux:57 (KEY_SPACE) -> qnum:57 */
{Q_KEY_CODE_STOP, 0xe8}, /* qcode:Q_KEY_CODE_STOP (stop) -> linux:128 (KEY_STOP) -> qnum:232 */
{Q_KEY_CODE_SYSRQ, 0x54}, /* qcode:Q_KEY_CODE_SYSRQ (sysrq) -> linux:99 (KEY_SYSRQ) -> qnum:84 */
{Q_KEY_CODE_T, 0x14}, /* qcode:Q_KEY_CODE_T (t) -> linux:20 (KEY_T) -> qnum:20 */
{Q_KEY_CODE_TAB, 0xf}, /* qcode:Q_KEY_CODE_TAB (tab) -> linux:15 (KEY_TAB) -> qnum:15 */
{Q_KEY_CODE_U, 0x16}, /* qcode:Q_KEY_CODE_U (u) -> linux:22 (KEY_U) -> qnum:22 */
{Q_KEY_CODE_UNDO, 0x87}, /* qcode:Q_KEY_CODE_UNDO (undo) -> linux:131 (KEY_UNDO) -> qnum:135 */
{Q_KEY_CODE_UP, 0xc8}, /* qcode:Q_KEY_CODE_UP (up) -> linux:103 (KEY_UP) -> qnum:200 */
{Q_KEY_CODE_V, 0x2f}, /* qcode:Q_KEY_CODE_V (v) -> linux:47 (KEY_V) -> qnum:47 */
{Q_KEY_CODE_VOLUMEDOWN, 0xae}, /* qcode:Q_KEY_CODE_VOLUMEDOWN (volumedown) -> linux:114 (KEY_VOLUMEDOWN) -> qnum:174 */
{Q_KEY_CODE_VOLUMEUP, 0xb0}, /* qcode:Q_KEY_CODE_VOLUMEUP (volumeup) -> linux:115 (KEY_VOLUMEUP) -> qnum:176 */
{Q_KEY_CODE_W, 0x11}, /* qcode:Q_KEY_CODE_W (w) -> linux:17 (KEY_W) -> qnum:17 */
{Q_KEY_CODE_WAKE, 0xe3}, /* qcode:Q_KEY_CODE_WAKE (wake) -> linux:143 (KEY_WAKEUP) -> qnum:227 */
{Q_KEY_CODE_X, 0x2d}, /* qcode:Q_KEY_CODE_X (x) -> linux:45 (KEY_X) -> qnum:45 */
{Q_KEY_CODE_Y, 0x15}, /* qcode:Q_KEY_CODE_Y (y) -> linux:21 (KEY_Y) -> qnum:21 */
{Q_KEY_CODE_YEN, 0x7d}, /* qcode:Q_KEY_CODE_YEN (yen) -> linux:124 (KEY_YEN) -> qnum:125 */
{Q_KEY_CODE_Z, 0x2c}, /* qcode:Q_KEY_CODE_Z (z) -> linux:44 (KEY_Z) -> qnum:44 */
};
int qemu_input_qcode_to_number(const QKeyCode value)
{
auto it = qemu_input_map_qcode_to_qnum.find(value);
if (it == qemu_input_map_qcode_to_qnum.end())
return 0;
return it->second;
auto it = qemu_input_map_qcode_to_qnum.find(value);
if (it == qemu_input_map_qcode_to_qnum.end())
return 0;
return it->second;
}
int qemu_input_key_value_to_number(const KeyValue *value)
int qemu_input_key_value_to_number(const KeyValue* value)
{
if (value->type == KEY_VALUE_KIND_QCODE) {
return qemu_input_qcode_to_number(value->u.qcode);
}
else {
assert(value->type == KEY_VALUE_KIND_NUMBER);
return value->u.number;
}
if (value->type == KEY_VALUE_KIND_QCODE)
{
return qemu_input_qcode_to_number(value->u.qcode);
}
else
{
assert(value->type == KEY_VALUE_KIND_NUMBER);
return value->u.number;
}
}
int qemu_input_key_value_to_scancode(const KeyValue *value, bool down,
int *codes)
int qemu_input_key_value_to_scancode(const KeyValue* value, bool down,
int* codes)
{
int keycode = qemu_input_key_value_to_number(value);
int count = 0;
int keycode = qemu_input_key_value_to_number(value);
int count = 0;
if (value->type == KEY_VALUE_KIND_QCODE &&
value->u.qcode == Q_KEY_CODE_PAUSE) {
/* specific case */
int v = down ? 0 : 0x80;
codes[count++] = 0xe1;
codes[count++] = 0x1d | v;
codes[count++] = 0x45 | v;
return count;
}
if (keycode & SCANCODE_GREY) {
codes[count++] = SCANCODE_EMUL0;
keycode &= ~SCANCODE_GREY;
}
if (!down) {
keycode |= SCANCODE_UP;
}
codes[count++] = keycode;
if (value->type == KEY_VALUE_KIND_QCODE &&
value->u.qcode == Q_KEY_CODE_PAUSE)
{
/* specific case */
int v = down ? 0 : 0x80;
codes[count++] = 0xe1;
codes[count++] = 0x1d | v;
codes[count++] = 0x45 | v;
return count;
}
if (keycode & SCANCODE_GREY)
{
codes[count++] = SCANCODE_EMUL0;
keycode &= ~SCANCODE_GREY;
}
if (!down)
{
keycode |= SCANCODE_UP;
}
codes[count++] = keycode;
return count;
return count;
}

View File

@ -20,256 +20,256 @@
*/
#include "input-keymap-win32-to-qcode.h"
const std::array<QKeyCode, 252> qemu_input_map_win32_to_qcode = {
Q_KEY_CODE_UNMAPPED, /* win32:0 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:1 (VK_LBUTTON) -> linux:256 (BTN_0) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:2 (VK_RBUTTON) -> linux:257 (BTN_1) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:3 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:4 (VK_MBUTTON) -> linux:258 (BTN_2) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:5 (VK_XBUTTON1) -> linux:259 (BTN_3) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:6 (VK_XBUTTON2) -> linux:260 (BTN_4) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:7 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_BACKSPACE, /* win32:8 (VK_BACK) -> linux:14 (KEY_BACKSPACE) -> qcode:Q_KEY_CODE_BACKSPACE (backspace) */
Q_KEY_CODE_TAB, /* win32:9 (VK_TAB) -> linux:15 (KEY_TAB) -> qcode:Q_KEY_CODE_TAB (tab) */
Q_KEY_CODE_UNMAPPED, /* win32:10 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:11 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:12 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_RET, /* win32:13 (VK_RETURN) -> linux:28 (KEY_ENTER) -> qcode:Q_KEY_CODE_RET (ret) */
Q_KEY_CODE_UNMAPPED, /* win32:14 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:15 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SHIFT, /* win32:16 (VK_LSHIFT) -> linux:42 (KEY_LEFTSHIFT) -> qcode:Q_KEY_CODE_SHIFT (shift) */
Q_KEY_CODE_CTRL, /* win32:17 (VK_CONTROL) -> linux:29 (KEY_LEFTCTRL) -> qcode:Q_KEY_CODE_CTRL (ctrl) */
Q_KEY_CODE_ALT, /* win32:18 (VK_MENU) -> linux:56 (KEY_LEFTALT) -> qcode:Q_KEY_CODE_ALT (alt) */
Q_KEY_CODE_PAUSE, /* win32:19 (VK_PAUSE) -> linux:119 (KEY_PAUSE) -> qcode:Q_KEY_CODE_PAUSE (pause) */
Q_KEY_CODE_CAPS_LOCK, /* win32:20 (VK_CAPITAL) -> linux:58 (KEY_CAPSLOCK) -> qcode:Q_KEY_CODE_CAPS_LOCK (caps_lock) */
Q_KEY_CODE_UNMAPPED, /* win32:21 (VK_HANGEUL) -> linux:122 (KEY_HANGEUL) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:22 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:23 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:24 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:25 (VK_HANJA) -> linux:123 (KEY_HANJA) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:26 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_ESC, /* win32:27 (VK_ESCAPE) -> linux:1 (KEY_ESC) -> qcode:Q_KEY_CODE_ESC (esc) */
Q_KEY_CODE_UNMAPPED, /* win32:28 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:29 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:30 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:31 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SPC, /* win32:32 (VK_SPACE) -> linux:57 (KEY_SPACE) -> qcode:Q_KEY_CODE_SPC (spc) */
Q_KEY_CODE_PGUP, /* win32:33 (VK_PRIOR) -> linux:104 (KEY_PAGEUP) -> qcode:Q_KEY_CODE_PGUP (pgup) */
Q_KEY_CODE_PGDN, /* win32:34 (VK_NEXT) -> linux:109 (KEY_PAGEDOWN) -> qcode:Q_KEY_CODE_PGDN (pgdn) */
Q_KEY_CODE_END, /* win32:35 (VK_END) -> linux:107 (KEY_END) -> qcode:Q_KEY_CODE_END (end) */
Q_KEY_CODE_HOME, /* win32:36 (VK_HOME) -> linux:102 (KEY_HOME) -> qcode:Q_KEY_CODE_HOME (home) */
Q_KEY_CODE_LEFT, /* win32:37 (VK_LEFT) -> linux:105 (KEY_LEFT) -> qcode:Q_KEY_CODE_LEFT (left) */
Q_KEY_CODE_UP, /* win32:38 (VK_UP) -> linux:103 (KEY_UP) -> qcode:Q_KEY_CODE_UP (up) */
Q_KEY_CODE_RIGHT, /* win32:39 (VK_RIGHT) -> linux:106 (KEY_RIGHT) -> qcode:Q_KEY_CODE_RIGHT (right) */
Q_KEY_CODE_DOWN, /* win32:40 (VK_DOWN) -> linux:108 (KEY_DOWN) -> qcode:Q_KEY_CODE_DOWN (down) */
Q_KEY_CODE_UNMAPPED, /* win32:41 (VK_SELECT) -> linux:353 (KEY_SELECT) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:42 (VK_PRINT) -> linux:210 (KEY_PRINT) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:43 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SYSRQ, /* win32:44 (VK_SNAPSHOT) -> linux:99 (KEY_SYSRQ) -> qcode:Q_KEY_CODE_SYSRQ (sysrq) */
Q_KEY_CODE_INSERT, /* win32:45 (VK_INSERT) -> linux:110 (KEY_INSERT) -> qcode:Q_KEY_CODE_INSERT (insert) */
Q_KEY_CODE_DELETE, /* win32:46 (VK_DELETE) -> linux:111 (KEY_DELETE) -> qcode:Q_KEY_CODE_DELETE (delete) */
Q_KEY_CODE_HELP, /* win32:47 (VK_HELP) -> linux:138 (KEY_HELP) -> qcode:Q_KEY_CODE_HELP (help) */
Q_KEY_CODE_0, /* win32:48 (VK_0) -> linux:11 (KEY_0) -> qcode:Q_KEY_CODE_0 (0) */
Q_KEY_CODE_1, /* win32:49 (VK_1) -> linux:2 (KEY_1) -> qcode:Q_KEY_CODE_1 (1) */
Q_KEY_CODE_2, /* win32:50 (VK_2) -> linux:3 (KEY_2) -> qcode:Q_KEY_CODE_2 (2) */
Q_KEY_CODE_3, /* win32:51 (VK_3) -> linux:4 (KEY_3) -> qcode:Q_KEY_CODE_3 (3) */
Q_KEY_CODE_4, /* win32:52 (VK_4) -> linux:5 (KEY_4) -> qcode:Q_KEY_CODE_4 (4) */
Q_KEY_CODE_5, /* win32:53 (VK_5) -> linux:6 (KEY_5) -> qcode:Q_KEY_CODE_5 (5) */
Q_KEY_CODE_6, /* win32:54 (VK_6) -> linux:7 (KEY_6) -> qcode:Q_KEY_CODE_6 (6) */
Q_KEY_CODE_7, /* win32:55 (VK_7) -> linux:8 (KEY_7) -> qcode:Q_KEY_CODE_7 (7) */
Q_KEY_CODE_8, /* win32:56 (VK_8) -> linux:9 (KEY_8) -> qcode:Q_KEY_CODE_8 (8) */
Q_KEY_CODE_9, /* win32:57 (VK_9) -> linux:10 (KEY_9) -> qcode:Q_KEY_CODE_9 (9) */
Q_KEY_CODE_UNMAPPED, /* win32:58 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:59 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:60 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:61 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:62 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:63 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:64 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_A, /* win32:65 (VK_A) -> linux:30 (KEY_A) -> qcode:Q_KEY_CODE_A (a) */
Q_KEY_CODE_B, /* win32:66 (VK_B) -> linux:48 (KEY_B) -> qcode:Q_KEY_CODE_B (b) */
Q_KEY_CODE_C, /* win32:67 (VK_C) -> linux:46 (KEY_C) -> qcode:Q_KEY_CODE_C (c) */
Q_KEY_CODE_D, /* win32:68 (VK_D) -> linux:32 (KEY_D) -> qcode:Q_KEY_CODE_D (d) */
Q_KEY_CODE_E, /* win32:69 (VK_E) -> linux:18 (KEY_E) -> qcode:Q_KEY_CODE_E (e) */
Q_KEY_CODE_F, /* win32:70 (VK_F) -> linux:33 (KEY_F) -> qcode:Q_KEY_CODE_F (f) */
Q_KEY_CODE_G, /* win32:71 (VK_G) -> linux:34 (KEY_G) -> qcode:Q_KEY_CODE_G (g) */
Q_KEY_CODE_H, /* win32:72 (VK_H) -> linux:35 (KEY_H) -> qcode:Q_KEY_CODE_H (h) */
Q_KEY_CODE_I, /* win32:73 (VK_I) -> linux:23 (KEY_I) -> qcode:Q_KEY_CODE_I (i) */
Q_KEY_CODE_J, /* win32:74 (VK_J) -> linux:36 (KEY_J) -> qcode:Q_KEY_CODE_J (j) */
Q_KEY_CODE_K, /* win32:75 (VK_K) -> linux:37 (KEY_K) -> qcode:Q_KEY_CODE_K (k) */
Q_KEY_CODE_L, /* win32:76 (VK_L) -> linux:38 (KEY_L) -> qcode:Q_KEY_CODE_L (l) */
Q_KEY_CODE_M, /* win32:77 (VK_M) -> linux:50 (KEY_M) -> qcode:Q_KEY_CODE_M (m) */
Q_KEY_CODE_N, /* win32:78 (VK_N) -> linux:49 (KEY_N) -> qcode:Q_KEY_CODE_N (n) */
Q_KEY_CODE_O, /* win32:79 (VK_O) -> linux:24 (KEY_O) -> qcode:Q_KEY_CODE_O (o) */
Q_KEY_CODE_P, /* win32:80 (VK_P) -> linux:25 (KEY_P) -> qcode:Q_KEY_CODE_P (p) */
Q_KEY_CODE_Q, /* win32:81 (VK_Q) -> linux:16 (KEY_Q) -> qcode:Q_KEY_CODE_Q (q) */
Q_KEY_CODE_R, /* win32:82 (VK_R) -> linux:19 (KEY_R) -> qcode:Q_KEY_CODE_R (r) */
Q_KEY_CODE_S, /* win32:83 (VK_S) -> linux:31 (KEY_S) -> qcode:Q_KEY_CODE_S (s) */
Q_KEY_CODE_T, /* win32:84 (VK_T) -> linux:20 (KEY_T) -> qcode:Q_KEY_CODE_T (t) */
Q_KEY_CODE_U, /* win32:85 (VK_U) -> linux:22 (KEY_U) -> qcode:Q_KEY_CODE_U (u) */
Q_KEY_CODE_V, /* win32:86 (VK_V) -> linux:47 (KEY_V) -> qcode:Q_KEY_CODE_V (v) */
Q_KEY_CODE_W, /* win32:87 (VK_W) -> linux:17 (KEY_W) -> qcode:Q_KEY_CODE_W (w) */
Q_KEY_CODE_X, /* win32:88 (VK_X) -> linux:45 (KEY_X) -> qcode:Q_KEY_CODE_X (x) */
Q_KEY_CODE_Y, /* win32:89 (VK_Y) -> linux:21 (KEY_Y) -> qcode:Q_KEY_CODE_Y (y) */
Q_KEY_CODE_Z, /* win32:90 (VK_Z) -> linux:44 (KEY_Z) -> qcode:Q_KEY_CODE_Z (z) */
Q_KEY_CODE_META_L, /* win32:91 (VK_LWIN) -> linux:125 (KEY_LEFTMETA) -> qcode:Q_KEY_CODE_META_L (meta_l) */
Q_KEY_CODE_META_R, /* win32:92 (VK_RWIN) -> linux:126 (KEY_RIGHTMETA) -> qcode:Q_KEY_CODE_META_R (meta_r) */
Q_KEY_CODE_COMPOSE, /* win32:93 (VK_APPS) -> linux:127 (KEY_COMPOSE) -> qcode:Q_KEY_CODE_COMPOSE (compose) */
Q_KEY_CODE_UNMAPPED, /* win32:94 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SLEEP, /* win32:95 (VK_SLEEP) -> linux:142 (KEY_SLEEP) -> qcode:Q_KEY_CODE_SLEEP (sleep) */
Q_KEY_CODE_KP_0, /* win32:96 (VK_NUMPAD0) -> linux:82 (KEY_KP0) -> qcode:Q_KEY_CODE_KP_0 (kp_0) */
Q_KEY_CODE_KP_1, /* win32:97 (VK_NUMPAD1) -> linux:79 (KEY_KP1) -> qcode:Q_KEY_CODE_KP_1 (kp_1) */
Q_KEY_CODE_KP_2, /* win32:98 (VK_NUMPAD2) -> linux:80 (KEY_KP2) -> qcode:Q_KEY_CODE_KP_2 (kp_2) */
Q_KEY_CODE_KP_3, /* win32:99 (VK_NUMPAD3) -> linux:81 (KEY_KP3) -> qcode:Q_KEY_CODE_KP_3 (kp_3) */
Q_KEY_CODE_KP_4, /* win32:100 (VK_NUMPAD4) -> linux:75 (KEY_KP4) -> qcode:Q_KEY_CODE_KP_4 (kp_4) */
Q_KEY_CODE_KP_5, /* win32:101 (VK_NUMPAD5) -> linux:76 (KEY_KP5) -> qcode:Q_KEY_CODE_KP_5 (kp_5) */
Q_KEY_CODE_KP_6, /* win32:102 (VK_NUMPAD6) -> linux:77 (KEY_KP6) -> qcode:Q_KEY_CODE_KP_6 (kp_6) */
Q_KEY_CODE_KP_7, /* win32:103 (VK_NUMPAD7) -> linux:71 (KEY_KP7) -> qcode:Q_KEY_CODE_KP_7 (kp_7) */
Q_KEY_CODE_KP_8, /* win32:104 (VK_NUMPAD8) -> linux:72 (KEY_KP8) -> qcode:Q_KEY_CODE_KP_8 (kp_8) */
Q_KEY_CODE_KP_9, /* win32:105 (VK_NUMPAD9) -> linux:73 (KEY_KP9) -> qcode:Q_KEY_CODE_KP_9 (kp_9) */
Q_KEY_CODE_KP_MULTIPLY, /* win32:106 (VK_MULTIPLY) -> linux:55 (KEY_KPASTERISK) -> qcode:Q_KEY_CODE_KP_MULTIPLY (kp_multiply) */
Q_KEY_CODE_KP_ADD, /* win32:107 (VK_ADD) -> linux:78 (KEY_KPPLUS) -> qcode:Q_KEY_CODE_KP_ADD (kp_add) */
Q_KEY_CODE_KP_COMMA, /* win32:108 (VK_SEPARATOR??) -> linux:121 (KEY_KPCOMMA) -> qcode:Q_KEY_CODE_KP_COMMA (kp_comma) */
Q_KEY_CODE_KP_SUBTRACT, /* win32:109 (VK_SUBTRACT) -> linux:74 (KEY_KPMINUS) -> qcode:Q_KEY_CODE_KP_SUBTRACT (kp_subtract) */
Q_KEY_CODE_KP_DECIMAL, /* win32:110 (VK_DECIMAL) -> linux:83 (KEY_KPDOT) -> qcode:Q_KEY_CODE_KP_DECIMAL (kp_decimal) */
Q_KEY_CODE_KP_DIVIDE, /* win32:111 (VK_DIVIDE) -> linux:98 (KEY_KPSLASH) -> qcode:Q_KEY_CODE_KP_DIVIDE (kp_divide) */
Q_KEY_CODE_F1, /* win32:112 (VK_F1) -> linux:59 (KEY_F1) -> qcode:Q_KEY_CODE_F1 (f1) */
Q_KEY_CODE_F2, /* win32:113 (VK_F2) -> linux:60 (KEY_F2) -> qcode:Q_KEY_CODE_F2 (f2) */
Q_KEY_CODE_F3, /* win32:114 (VK_F3) -> linux:61 (KEY_F3) -> qcode:Q_KEY_CODE_F3 (f3) */
Q_KEY_CODE_F4, /* win32:115 (VK_F4) -> linux:62 (KEY_F4) -> qcode:Q_KEY_CODE_F4 (f4) */
Q_KEY_CODE_F5, /* win32:116 (VK_F5) -> linux:63 (KEY_F5) -> qcode:Q_KEY_CODE_F5 (f5) */
Q_KEY_CODE_F6, /* win32:117 (VK_F6) -> linux:64 (KEY_F6) -> qcode:Q_KEY_CODE_F6 (f6) */
Q_KEY_CODE_F7, /* win32:118 (VK_F7) -> linux:65 (KEY_F7) -> qcode:Q_KEY_CODE_F7 (f7) */
Q_KEY_CODE_F8, /* win32:119 (VK_F8) -> linux:66 (KEY_F8) -> qcode:Q_KEY_CODE_F8 (f8) */
Q_KEY_CODE_F9, /* win32:120 (VK_F9) -> linux:67 (KEY_F9) -> qcode:Q_KEY_CODE_F9 (f9) */
Q_KEY_CODE_F10, /* win32:121 (VK_F10) -> linux:68 (KEY_F10) -> qcode:Q_KEY_CODE_F10 (f10) */
Q_KEY_CODE_F11, /* win32:122 (VK_F11) -> linux:87 (KEY_F11) -> qcode:Q_KEY_CODE_F11 (f11) */
Q_KEY_CODE_F12, /* win32:123 (VK_F12) -> linux:88 (KEY_F12) -> qcode:Q_KEY_CODE_F12 (f12) */
Q_KEY_CODE_UNMAPPED, /* win32:124 (VK_F13) -> linux:183 (KEY_F13) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:125 (VK_F14) -> linux:184 (KEY_F14) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:126 (VK_F15) -> linux:185 (KEY_F15) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:127 (VK_F16) -> linux:186 (KEY_F16) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:128 (VK_F17) -> linux:187 (KEY_F17) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:129 (VK_F18) -> linux:188 (KEY_F18) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:130 (VK_F19) -> linux:189 (KEY_F19) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:131 (VK_F20) -> linux:190 (KEY_F20) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:132 (VK_F21) -> linux:191 (KEY_F21) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:133 (VK_F22) -> linux:192 (KEY_F22) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:134 (VK_F23) -> linux:193 (KEY_F23) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:135 (VK_F24) -> linux:194 (KEY_F24) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:136 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:137 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:138 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:139 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:140 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:141 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:142 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:143 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_NUM_LOCK, /* win32:144 (VK_NUMLOCK) -> linux:69 (KEY_NUMLOCK) -> qcode:Q_KEY_CODE_NUM_LOCK (num_lock) */
Q_KEY_CODE_SCROLL_LOCK, /* win32:145 (VK_SCROLL) -> linux:70 (KEY_SCROLLLOCK) -> qcode:Q_KEY_CODE_SCROLL_LOCK (scroll_lock) */
Q_KEY_CODE_UNMAPPED, /* win32:146 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:147 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:148 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:149 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:150 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:151 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:152 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:153 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:154 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:155 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:156 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:157 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:158 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:159 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SHIFT, /* win32:160 (VK_LSHIFT) -> linux:42 (KEY_LEFTSHIFT) -> qcode:Q_KEY_CODE_SHIFT (shift) */
Q_KEY_CODE_SHIFT_R, /* win32:161 (VK_RSHIFT) -> linux:54 (KEY_RIGHTSHIFT) -> qcode:Q_KEY_CODE_SHIFT_R (shift_r) */
Q_KEY_CODE_CTRL, /* win32:162 (VK_CONTROL) -> linux:29 (KEY_LEFTCTRL) -> qcode:Q_KEY_CODE_CTRL (ctrl) */
Q_KEY_CODE_CTRL_R, /* win32:163 (VK_RCONTROL) -> linux:97 (KEY_RIGHTCTRL) -> qcode:Q_KEY_CODE_CTRL_R (ctrl_r) */
Q_KEY_CODE_ALT, /* win32:164 (VK_MENU) -> linux:56 (KEY_LEFTALT) -> qcode:Q_KEY_CODE_ALT (alt) */
Q_KEY_CODE_ALT_R, /* win32:165 (VK_RMENU) -> linux:100 (KEY_RIGHTALT) -> qcode:Q_KEY_CODE_ALT_R (alt_r) */
Q_KEY_CODE_AC_BACK, /* win32:166 (VK_BROWSER_BACK) -> linux:158 (KEY_BACK) -> qcode:Q_KEY_CODE_AC_BACK (ac_back) */
Q_KEY_CODE_AC_FORWARD, /* win32:167 (VK_BROWSER_FORWARD) -> linux:159 (KEY_FORWARD) -> qcode:Q_KEY_CODE_AC_FORWARD (ac_forward) */
Q_KEY_CODE_AC_REFRESH, /* win32:168 (VK_BROWSER_REFRESH) -> linux:173 (KEY_REFRESH) -> qcode:Q_KEY_CODE_AC_REFRESH (ac_refresh) */
Q_KEY_CODE_STOP, /* win32:169 (VK_BROWSER_STOP) -> linux:128 (KEY_STOP) -> qcode:Q_KEY_CODE_STOP (stop) */
Q_KEY_CODE_UNMAPPED, /* win32:170 (VK_BROWSER_SEARCH) -> linux:217 (KEY_SEARCH) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:171 (VK_BROWSER_FAVOURITES) -> linux:364 (KEY_FAVORITES) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_AC_HOME, /* win32:172 (VK_BROWSER_HOME) -> linux:172 (KEY_HOMEPAGE) -> qcode:Q_KEY_CODE_AC_HOME (ac_home) */
Q_KEY_CODE_AUDIOMUTE, /* win32:173 (VK_VOLUME_MUTE) -> linux:113 (KEY_MUTE) -> qcode:Q_KEY_CODE_AUDIOMUTE (audiomute) */
Q_KEY_CODE_VOLUMEDOWN, /* win32:174 (VK_VOLUME_DOWN) -> linux:114 (KEY_VOLUMEDOWN) -> qcode:Q_KEY_CODE_VOLUMEDOWN (volumedown) */
Q_KEY_CODE_VOLUMEUP, /* win32:175 (VK_VOLUME_UP) -> linux:115 (KEY_VOLUMEUP) -> qcode:Q_KEY_CODE_VOLUMEUP (volumeup) */
Q_KEY_CODE_AUDIONEXT, /* win32:176 (VK_MEDIA_NEXT_TRACK) -> linux:163 (KEY_NEXTSONG) -> qcode:Q_KEY_CODE_AUDIONEXT (audionext) */
Q_KEY_CODE_AUDIOPREV, /* win32:177 (VK_MEDIA_PREV_TRACK) -> linux:165 (KEY_PREVIOUSSONG) -> qcode:Q_KEY_CODE_AUDIOPREV (audioprev) */
Q_KEY_CODE_AUDIOSTOP, /* win32:178 (VK_MEDIA_STOP) -> linux:166 (KEY_STOPCD) -> qcode:Q_KEY_CODE_AUDIOSTOP (audiostop) */
Q_KEY_CODE_AUDIOPLAY, /* win32:179 (VK_MEDIA_PLAY_PAUSE) -> linux:164 (KEY_PLAYPAUSE) -> qcode:Q_KEY_CODE_AUDIOPLAY (audioplay) */
Q_KEY_CODE_UNMAPPED, /* win32:180 (VK_LAUNCH_MAIL) -> linux:215 (KEY_EMAIL) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:181 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:182 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:183 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:184 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:185 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SEMICOLON, /* win32:186 (VK_OEM_1) -> linux:39 (KEY_SEMICOLON) -> qcode:Q_KEY_CODE_SEMICOLON (semicolon) */
Q_KEY_CODE_EQUAL, /* win32:187 (VK_OEM_PLUS) -> linux:13 (KEY_EQUAL) -> qcode:Q_KEY_CODE_EQUAL (equal) */
Q_KEY_CODE_COMMA, /* win32:188 (VK_OEM_COMMA) -> linux:51 (KEY_COMMA) -> qcode:Q_KEY_CODE_COMMA (comma) */
Q_KEY_CODE_MINUS, /* win32:189 (VK_OEM_MINUS) -> linux:12 (KEY_MINUS) -> qcode:Q_KEY_CODE_MINUS (minus) */
Q_KEY_CODE_DOT, /* win32:190 (VK_OEM_PERIOD) -> linux:52 (KEY_DOT) -> qcode:Q_KEY_CODE_DOT (dot) */
Q_KEY_CODE_SLASH, /* win32:191 (VK_OEM_2) -> linux:53 (KEY_SLASH) -> qcode:Q_KEY_CODE_SLASH (slash) */
Q_KEY_CODE_GRAVE_ACCENT, /* win32:192 (VK_OEM_3) -> linux:41 (KEY_GRAVE) -> qcode:Q_KEY_CODE_GRAVE_ACCENT (grave_accent) */
Q_KEY_CODE_UNMAPPED, /* win32:193 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:194 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:195 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:196 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:197 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:198 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:199 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:200 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:201 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:202 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:203 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:204 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:205 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:206 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:207 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:208 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:209 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:210 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:211 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:212 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:213 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:214 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:215 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:216 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:217 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:218 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_BRACKET_LEFT, /* win32:219 (VK_OEM_4) -> linux:26 (KEY_LEFTBRACE) -> qcode:Q_KEY_CODE_BRACKET_LEFT (bracket_left) */
Q_KEY_CODE_BACKSLASH, /* win32:220 (VK_OEM_5) -> linux:43 (KEY_BACKSLASH) -> qcode:Q_KEY_CODE_BACKSLASH (backslash) */
Q_KEY_CODE_BRACKET_RIGHT, /* win32:221 (VK_OEM_6) -> linux:27 (KEY_RIGHTBRACE) -> qcode:Q_KEY_CODE_BRACKET_RIGHT (bracket_right) */
Q_KEY_CODE_APOSTROPHE, /* win32:222 (VK_OEM_7) -> linux:40 (KEY_APOSTROPHE) -> qcode:Q_KEY_CODE_APOSTROPHE (apostrophe) */
Q_KEY_CODE_UNMAPPED, /* win32:223 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:224 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_LESS, /* win32:225 (VK_OEM_102) -> linux:86 (KEY_102ND) -> qcode:Q_KEY_CODE_LESS (less) */
Q_KEY_CODE_UNMAPPED, /* win32:226 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:227 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:228 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:229 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:230 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:231 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:232 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:233 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:234 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:235 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:236 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:237 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:238 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:239 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:240 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:241 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:242 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:243 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:244 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:245 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:246 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:247 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:248 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:249 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:250 (VK_PLAY) -> linux:207 (KEY_PLAY) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:251 (VK_ZOOM) -> linux:372 (KEY_ZOOM) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:0 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:1 (VK_LBUTTON) -> linux:256 (BTN_0) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:2 (VK_RBUTTON) -> linux:257 (BTN_1) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:3 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:4 (VK_MBUTTON) -> linux:258 (BTN_2) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:5 (VK_XBUTTON1) -> linux:259 (BTN_3) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:6 (VK_XBUTTON2) -> linux:260 (BTN_4) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:7 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_BACKSPACE, /* win32:8 (VK_BACK) -> linux:14 (KEY_BACKSPACE) -> qcode:Q_KEY_CODE_BACKSPACE (backspace) */
Q_KEY_CODE_TAB, /* win32:9 (VK_TAB) -> linux:15 (KEY_TAB) -> qcode:Q_KEY_CODE_TAB (tab) */
Q_KEY_CODE_UNMAPPED, /* win32:10 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:11 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:12 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_RET, /* win32:13 (VK_RETURN) -> linux:28 (KEY_ENTER) -> qcode:Q_KEY_CODE_RET (ret) */
Q_KEY_CODE_UNMAPPED, /* win32:14 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:15 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SHIFT, /* win32:16 (VK_LSHIFT) -> linux:42 (KEY_LEFTSHIFT) -> qcode:Q_KEY_CODE_SHIFT (shift) */
Q_KEY_CODE_CTRL, /* win32:17 (VK_CONTROL) -> linux:29 (KEY_LEFTCTRL) -> qcode:Q_KEY_CODE_CTRL (ctrl) */
Q_KEY_CODE_ALT, /* win32:18 (VK_MENU) -> linux:56 (KEY_LEFTALT) -> qcode:Q_KEY_CODE_ALT (alt) */
Q_KEY_CODE_PAUSE, /* win32:19 (VK_PAUSE) -> linux:119 (KEY_PAUSE) -> qcode:Q_KEY_CODE_PAUSE (pause) */
Q_KEY_CODE_CAPS_LOCK, /* win32:20 (VK_CAPITAL) -> linux:58 (KEY_CAPSLOCK) -> qcode:Q_KEY_CODE_CAPS_LOCK (caps_lock) */
Q_KEY_CODE_UNMAPPED, /* win32:21 (VK_HANGEUL) -> linux:122 (KEY_HANGEUL) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:22 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:23 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:24 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:25 (VK_HANJA) -> linux:123 (KEY_HANJA) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:26 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_ESC, /* win32:27 (VK_ESCAPE) -> linux:1 (KEY_ESC) -> qcode:Q_KEY_CODE_ESC (esc) */
Q_KEY_CODE_UNMAPPED, /* win32:28 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:29 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:30 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:31 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SPC, /* win32:32 (VK_SPACE) -> linux:57 (KEY_SPACE) -> qcode:Q_KEY_CODE_SPC (spc) */
Q_KEY_CODE_PGUP, /* win32:33 (VK_PRIOR) -> linux:104 (KEY_PAGEUP) -> qcode:Q_KEY_CODE_PGUP (pgup) */
Q_KEY_CODE_PGDN, /* win32:34 (VK_NEXT) -> linux:109 (KEY_PAGEDOWN) -> qcode:Q_KEY_CODE_PGDN (pgdn) */
Q_KEY_CODE_END, /* win32:35 (VK_END) -> linux:107 (KEY_END) -> qcode:Q_KEY_CODE_END (end) */
Q_KEY_CODE_HOME, /* win32:36 (VK_HOME) -> linux:102 (KEY_HOME) -> qcode:Q_KEY_CODE_HOME (home) */
Q_KEY_CODE_LEFT, /* win32:37 (VK_LEFT) -> linux:105 (KEY_LEFT) -> qcode:Q_KEY_CODE_LEFT (left) */
Q_KEY_CODE_UP, /* win32:38 (VK_UP) -> linux:103 (KEY_UP) -> qcode:Q_KEY_CODE_UP (up) */
Q_KEY_CODE_RIGHT, /* win32:39 (VK_RIGHT) -> linux:106 (KEY_RIGHT) -> qcode:Q_KEY_CODE_RIGHT (right) */
Q_KEY_CODE_DOWN, /* win32:40 (VK_DOWN) -> linux:108 (KEY_DOWN) -> qcode:Q_KEY_CODE_DOWN (down) */
Q_KEY_CODE_UNMAPPED, /* win32:41 (VK_SELECT) -> linux:353 (KEY_SELECT) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:42 (VK_PRINT) -> linux:210 (KEY_PRINT) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:43 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SYSRQ, /* win32:44 (VK_SNAPSHOT) -> linux:99 (KEY_SYSRQ) -> qcode:Q_KEY_CODE_SYSRQ (sysrq) */
Q_KEY_CODE_INSERT, /* win32:45 (VK_INSERT) -> linux:110 (KEY_INSERT) -> qcode:Q_KEY_CODE_INSERT (insert) */
Q_KEY_CODE_DELETE, /* win32:46 (VK_DELETE) -> linux:111 (KEY_DELETE) -> qcode:Q_KEY_CODE_DELETE (delete) */
Q_KEY_CODE_HELP, /* win32:47 (VK_HELP) -> linux:138 (KEY_HELP) -> qcode:Q_KEY_CODE_HELP (help) */
Q_KEY_CODE_0, /* win32:48 (VK_0) -> linux:11 (KEY_0) -> qcode:Q_KEY_CODE_0 (0) */
Q_KEY_CODE_1, /* win32:49 (VK_1) -> linux:2 (KEY_1) -> qcode:Q_KEY_CODE_1 (1) */
Q_KEY_CODE_2, /* win32:50 (VK_2) -> linux:3 (KEY_2) -> qcode:Q_KEY_CODE_2 (2) */
Q_KEY_CODE_3, /* win32:51 (VK_3) -> linux:4 (KEY_3) -> qcode:Q_KEY_CODE_3 (3) */
Q_KEY_CODE_4, /* win32:52 (VK_4) -> linux:5 (KEY_4) -> qcode:Q_KEY_CODE_4 (4) */
Q_KEY_CODE_5, /* win32:53 (VK_5) -> linux:6 (KEY_5) -> qcode:Q_KEY_CODE_5 (5) */
Q_KEY_CODE_6, /* win32:54 (VK_6) -> linux:7 (KEY_6) -> qcode:Q_KEY_CODE_6 (6) */
Q_KEY_CODE_7, /* win32:55 (VK_7) -> linux:8 (KEY_7) -> qcode:Q_KEY_CODE_7 (7) */
Q_KEY_CODE_8, /* win32:56 (VK_8) -> linux:9 (KEY_8) -> qcode:Q_KEY_CODE_8 (8) */
Q_KEY_CODE_9, /* win32:57 (VK_9) -> linux:10 (KEY_9) -> qcode:Q_KEY_CODE_9 (9) */
Q_KEY_CODE_UNMAPPED, /* win32:58 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:59 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:60 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:61 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:62 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:63 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:64 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_A, /* win32:65 (VK_A) -> linux:30 (KEY_A) -> qcode:Q_KEY_CODE_A (a) */
Q_KEY_CODE_B, /* win32:66 (VK_B) -> linux:48 (KEY_B) -> qcode:Q_KEY_CODE_B (b) */
Q_KEY_CODE_C, /* win32:67 (VK_C) -> linux:46 (KEY_C) -> qcode:Q_KEY_CODE_C (c) */
Q_KEY_CODE_D, /* win32:68 (VK_D) -> linux:32 (KEY_D) -> qcode:Q_KEY_CODE_D (d) */
Q_KEY_CODE_E, /* win32:69 (VK_E) -> linux:18 (KEY_E) -> qcode:Q_KEY_CODE_E (e) */
Q_KEY_CODE_F, /* win32:70 (VK_F) -> linux:33 (KEY_F) -> qcode:Q_KEY_CODE_F (f) */
Q_KEY_CODE_G, /* win32:71 (VK_G) -> linux:34 (KEY_G) -> qcode:Q_KEY_CODE_G (g) */
Q_KEY_CODE_H, /* win32:72 (VK_H) -> linux:35 (KEY_H) -> qcode:Q_KEY_CODE_H (h) */
Q_KEY_CODE_I, /* win32:73 (VK_I) -> linux:23 (KEY_I) -> qcode:Q_KEY_CODE_I (i) */
Q_KEY_CODE_J, /* win32:74 (VK_J) -> linux:36 (KEY_J) -> qcode:Q_KEY_CODE_J (j) */
Q_KEY_CODE_K, /* win32:75 (VK_K) -> linux:37 (KEY_K) -> qcode:Q_KEY_CODE_K (k) */
Q_KEY_CODE_L, /* win32:76 (VK_L) -> linux:38 (KEY_L) -> qcode:Q_KEY_CODE_L (l) */
Q_KEY_CODE_M, /* win32:77 (VK_M) -> linux:50 (KEY_M) -> qcode:Q_KEY_CODE_M (m) */
Q_KEY_CODE_N, /* win32:78 (VK_N) -> linux:49 (KEY_N) -> qcode:Q_KEY_CODE_N (n) */
Q_KEY_CODE_O, /* win32:79 (VK_O) -> linux:24 (KEY_O) -> qcode:Q_KEY_CODE_O (o) */
Q_KEY_CODE_P, /* win32:80 (VK_P) -> linux:25 (KEY_P) -> qcode:Q_KEY_CODE_P (p) */
Q_KEY_CODE_Q, /* win32:81 (VK_Q) -> linux:16 (KEY_Q) -> qcode:Q_KEY_CODE_Q (q) */
Q_KEY_CODE_R, /* win32:82 (VK_R) -> linux:19 (KEY_R) -> qcode:Q_KEY_CODE_R (r) */
Q_KEY_CODE_S, /* win32:83 (VK_S) -> linux:31 (KEY_S) -> qcode:Q_KEY_CODE_S (s) */
Q_KEY_CODE_T, /* win32:84 (VK_T) -> linux:20 (KEY_T) -> qcode:Q_KEY_CODE_T (t) */
Q_KEY_CODE_U, /* win32:85 (VK_U) -> linux:22 (KEY_U) -> qcode:Q_KEY_CODE_U (u) */
Q_KEY_CODE_V, /* win32:86 (VK_V) -> linux:47 (KEY_V) -> qcode:Q_KEY_CODE_V (v) */
Q_KEY_CODE_W, /* win32:87 (VK_W) -> linux:17 (KEY_W) -> qcode:Q_KEY_CODE_W (w) */
Q_KEY_CODE_X, /* win32:88 (VK_X) -> linux:45 (KEY_X) -> qcode:Q_KEY_CODE_X (x) */
Q_KEY_CODE_Y, /* win32:89 (VK_Y) -> linux:21 (KEY_Y) -> qcode:Q_KEY_CODE_Y (y) */
Q_KEY_CODE_Z, /* win32:90 (VK_Z) -> linux:44 (KEY_Z) -> qcode:Q_KEY_CODE_Z (z) */
Q_KEY_CODE_META_L, /* win32:91 (VK_LWIN) -> linux:125 (KEY_LEFTMETA) -> qcode:Q_KEY_CODE_META_L (meta_l) */
Q_KEY_CODE_META_R, /* win32:92 (VK_RWIN) -> linux:126 (KEY_RIGHTMETA) -> qcode:Q_KEY_CODE_META_R (meta_r) */
Q_KEY_CODE_COMPOSE, /* win32:93 (VK_APPS) -> linux:127 (KEY_COMPOSE) -> qcode:Q_KEY_CODE_COMPOSE (compose) */
Q_KEY_CODE_UNMAPPED, /* win32:94 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SLEEP, /* win32:95 (VK_SLEEP) -> linux:142 (KEY_SLEEP) -> qcode:Q_KEY_CODE_SLEEP (sleep) */
Q_KEY_CODE_KP_0, /* win32:96 (VK_NUMPAD0) -> linux:82 (KEY_KP0) -> qcode:Q_KEY_CODE_KP_0 (kp_0) */
Q_KEY_CODE_KP_1, /* win32:97 (VK_NUMPAD1) -> linux:79 (KEY_KP1) -> qcode:Q_KEY_CODE_KP_1 (kp_1) */
Q_KEY_CODE_KP_2, /* win32:98 (VK_NUMPAD2) -> linux:80 (KEY_KP2) -> qcode:Q_KEY_CODE_KP_2 (kp_2) */
Q_KEY_CODE_KP_3, /* win32:99 (VK_NUMPAD3) -> linux:81 (KEY_KP3) -> qcode:Q_KEY_CODE_KP_3 (kp_3) */
Q_KEY_CODE_KP_4, /* win32:100 (VK_NUMPAD4) -> linux:75 (KEY_KP4) -> qcode:Q_KEY_CODE_KP_4 (kp_4) */
Q_KEY_CODE_KP_5, /* win32:101 (VK_NUMPAD5) -> linux:76 (KEY_KP5) -> qcode:Q_KEY_CODE_KP_5 (kp_5) */
Q_KEY_CODE_KP_6, /* win32:102 (VK_NUMPAD6) -> linux:77 (KEY_KP6) -> qcode:Q_KEY_CODE_KP_6 (kp_6) */
Q_KEY_CODE_KP_7, /* win32:103 (VK_NUMPAD7) -> linux:71 (KEY_KP7) -> qcode:Q_KEY_CODE_KP_7 (kp_7) */
Q_KEY_CODE_KP_8, /* win32:104 (VK_NUMPAD8) -> linux:72 (KEY_KP8) -> qcode:Q_KEY_CODE_KP_8 (kp_8) */
Q_KEY_CODE_KP_9, /* win32:105 (VK_NUMPAD9) -> linux:73 (KEY_KP9) -> qcode:Q_KEY_CODE_KP_9 (kp_9) */
Q_KEY_CODE_KP_MULTIPLY, /* win32:106 (VK_MULTIPLY) -> linux:55 (KEY_KPASTERISK) -> qcode:Q_KEY_CODE_KP_MULTIPLY (kp_multiply) */
Q_KEY_CODE_KP_ADD, /* win32:107 (VK_ADD) -> linux:78 (KEY_KPPLUS) -> qcode:Q_KEY_CODE_KP_ADD (kp_add) */
Q_KEY_CODE_KP_COMMA, /* win32:108 (VK_SEPARATOR??) -> linux:121 (KEY_KPCOMMA) -> qcode:Q_KEY_CODE_KP_COMMA (kp_comma) */
Q_KEY_CODE_KP_SUBTRACT, /* win32:109 (VK_SUBTRACT) -> linux:74 (KEY_KPMINUS) -> qcode:Q_KEY_CODE_KP_SUBTRACT (kp_subtract) */
Q_KEY_CODE_KP_DECIMAL, /* win32:110 (VK_DECIMAL) -> linux:83 (KEY_KPDOT) -> qcode:Q_KEY_CODE_KP_DECIMAL (kp_decimal) */
Q_KEY_CODE_KP_DIVIDE, /* win32:111 (VK_DIVIDE) -> linux:98 (KEY_KPSLASH) -> qcode:Q_KEY_CODE_KP_DIVIDE (kp_divide) */
Q_KEY_CODE_F1, /* win32:112 (VK_F1) -> linux:59 (KEY_F1) -> qcode:Q_KEY_CODE_F1 (f1) */
Q_KEY_CODE_F2, /* win32:113 (VK_F2) -> linux:60 (KEY_F2) -> qcode:Q_KEY_CODE_F2 (f2) */
Q_KEY_CODE_F3, /* win32:114 (VK_F3) -> linux:61 (KEY_F3) -> qcode:Q_KEY_CODE_F3 (f3) */
Q_KEY_CODE_F4, /* win32:115 (VK_F4) -> linux:62 (KEY_F4) -> qcode:Q_KEY_CODE_F4 (f4) */
Q_KEY_CODE_F5, /* win32:116 (VK_F5) -> linux:63 (KEY_F5) -> qcode:Q_KEY_CODE_F5 (f5) */
Q_KEY_CODE_F6, /* win32:117 (VK_F6) -> linux:64 (KEY_F6) -> qcode:Q_KEY_CODE_F6 (f6) */
Q_KEY_CODE_F7, /* win32:118 (VK_F7) -> linux:65 (KEY_F7) -> qcode:Q_KEY_CODE_F7 (f7) */
Q_KEY_CODE_F8, /* win32:119 (VK_F8) -> linux:66 (KEY_F8) -> qcode:Q_KEY_CODE_F8 (f8) */
Q_KEY_CODE_F9, /* win32:120 (VK_F9) -> linux:67 (KEY_F9) -> qcode:Q_KEY_CODE_F9 (f9) */
Q_KEY_CODE_F10, /* win32:121 (VK_F10) -> linux:68 (KEY_F10) -> qcode:Q_KEY_CODE_F10 (f10) */
Q_KEY_CODE_F11, /* win32:122 (VK_F11) -> linux:87 (KEY_F11) -> qcode:Q_KEY_CODE_F11 (f11) */
Q_KEY_CODE_F12, /* win32:123 (VK_F12) -> linux:88 (KEY_F12) -> qcode:Q_KEY_CODE_F12 (f12) */
Q_KEY_CODE_UNMAPPED, /* win32:124 (VK_F13) -> linux:183 (KEY_F13) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:125 (VK_F14) -> linux:184 (KEY_F14) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:126 (VK_F15) -> linux:185 (KEY_F15) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:127 (VK_F16) -> linux:186 (KEY_F16) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:128 (VK_F17) -> linux:187 (KEY_F17) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:129 (VK_F18) -> linux:188 (KEY_F18) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:130 (VK_F19) -> linux:189 (KEY_F19) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:131 (VK_F20) -> linux:190 (KEY_F20) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:132 (VK_F21) -> linux:191 (KEY_F21) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:133 (VK_F22) -> linux:192 (KEY_F22) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:134 (VK_F23) -> linux:193 (KEY_F23) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:135 (VK_F24) -> linux:194 (KEY_F24) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:136 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:137 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:138 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:139 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:140 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:141 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:142 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:143 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_NUM_LOCK, /* win32:144 (VK_NUMLOCK) -> linux:69 (KEY_NUMLOCK) -> qcode:Q_KEY_CODE_NUM_LOCK (num_lock) */
Q_KEY_CODE_SCROLL_LOCK, /* win32:145 (VK_SCROLL) -> linux:70 (KEY_SCROLLLOCK) -> qcode:Q_KEY_CODE_SCROLL_LOCK (scroll_lock) */
Q_KEY_CODE_UNMAPPED, /* win32:146 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:147 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:148 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:149 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:150 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:151 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:152 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:153 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:154 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:155 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:156 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:157 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:158 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:159 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SHIFT, /* win32:160 (VK_LSHIFT) -> linux:42 (KEY_LEFTSHIFT) -> qcode:Q_KEY_CODE_SHIFT (shift) */
Q_KEY_CODE_SHIFT_R, /* win32:161 (VK_RSHIFT) -> linux:54 (KEY_RIGHTSHIFT) -> qcode:Q_KEY_CODE_SHIFT_R (shift_r) */
Q_KEY_CODE_CTRL, /* win32:162 (VK_CONTROL) -> linux:29 (KEY_LEFTCTRL) -> qcode:Q_KEY_CODE_CTRL (ctrl) */
Q_KEY_CODE_CTRL_R, /* win32:163 (VK_RCONTROL) -> linux:97 (KEY_RIGHTCTRL) -> qcode:Q_KEY_CODE_CTRL_R (ctrl_r) */
Q_KEY_CODE_ALT, /* win32:164 (VK_MENU) -> linux:56 (KEY_LEFTALT) -> qcode:Q_KEY_CODE_ALT (alt) */
Q_KEY_CODE_ALT_R, /* win32:165 (VK_RMENU) -> linux:100 (KEY_RIGHTALT) -> qcode:Q_KEY_CODE_ALT_R (alt_r) */
Q_KEY_CODE_AC_BACK, /* win32:166 (VK_BROWSER_BACK) -> linux:158 (KEY_BACK) -> qcode:Q_KEY_CODE_AC_BACK (ac_back) */
Q_KEY_CODE_AC_FORWARD, /* win32:167 (VK_BROWSER_FORWARD) -> linux:159 (KEY_FORWARD) -> qcode:Q_KEY_CODE_AC_FORWARD (ac_forward) */
Q_KEY_CODE_AC_REFRESH, /* win32:168 (VK_BROWSER_REFRESH) -> linux:173 (KEY_REFRESH) -> qcode:Q_KEY_CODE_AC_REFRESH (ac_refresh) */
Q_KEY_CODE_STOP, /* win32:169 (VK_BROWSER_STOP) -> linux:128 (KEY_STOP) -> qcode:Q_KEY_CODE_STOP (stop) */
Q_KEY_CODE_UNMAPPED, /* win32:170 (VK_BROWSER_SEARCH) -> linux:217 (KEY_SEARCH) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:171 (VK_BROWSER_FAVOURITES) -> linux:364 (KEY_FAVORITES) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_AC_HOME, /* win32:172 (VK_BROWSER_HOME) -> linux:172 (KEY_HOMEPAGE) -> qcode:Q_KEY_CODE_AC_HOME (ac_home) */
Q_KEY_CODE_AUDIOMUTE, /* win32:173 (VK_VOLUME_MUTE) -> linux:113 (KEY_MUTE) -> qcode:Q_KEY_CODE_AUDIOMUTE (audiomute) */
Q_KEY_CODE_VOLUMEDOWN, /* win32:174 (VK_VOLUME_DOWN) -> linux:114 (KEY_VOLUMEDOWN) -> qcode:Q_KEY_CODE_VOLUMEDOWN (volumedown) */
Q_KEY_CODE_VOLUMEUP, /* win32:175 (VK_VOLUME_UP) -> linux:115 (KEY_VOLUMEUP) -> qcode:Q_KEY_CODE_VOLUMEUP (volumeup) */
Q_KEY_CODE_AUDIONEXT, /* win32:176 (VK_MEDIA_NEXT_TRACK) -> linux:163 (KEY_NEXTSONG) -> qcode:Q_KEY_CODE_AUDIONEXT (audionext) */
Q_KEY_CODE_AUDIOPREV, /* win32:177 (VK_MEDIA_PREV_TRACK) -> linux:165 (KEY_PREVIOUSSONG) -> qcode:Q_KEY_CODE_AUDIOPREV (audioprev) */
Q_KEY_CODE_AUDIOSTOP, /* win32:178 (VK_MEDIA_STOP) -> linux:166 (KEY_STOPCD) -> qcode:Q_KEY_CODE_AUDIOSTOP (audiostop) */
Q_KEY_CODE_AUDIOPLAY, /* win32:179 (VK_MEDIA_PLAY_PAUSE) -> linux:164 (KEY_PLAYPAUSE) -> qcode:Q_KEY_CODE_AUDIOPLAY (audioplay) */
Q_KEY_CODE_UNMAPPED, /* win32:180 (VK_LAUNCH_MAIL) -> linux:215 (KEY_EMAIL) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:181 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:182 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:183 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:184 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:185 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_SEMICOLON, /* win32:186 (VK_OEM_1) -> linux:39 (KEY_SEMICOLON) -> qcode:Q_KEY_CODE_SEMICOLON (semicolon) */
Q_KEY_CODE_EQUAL, /* win32:187 (VK_OEM_PLUS) -> linux:13 (KEY_EQUAL) -> qcode:Q_KEY_CODE_EQUAL (equal) */
Q_KEY_CODE_COMMA, /* win32:188 (VK_OEM_COMMA) -> linux:51 (KEY_COMMA) -> qcode:Q_KEY_CODE_COMMA (comma) */
Q_KEY_CODE_MINUS, /* win32:189 (VK_OEM_MINUS) -> linux:12 (KEY_MINUS) -> qcode:Q_KEY_CODE_MINUS (minus) */
Q_KEY_CODE_DOT, /* win32:190 (VK_OEM_PERIOD) -> linux:52 (KEY_DOT) -> qcode:Q_KEY_CODE_DOT (dot) */
Q_KEY_CODE_SLASH, /* win32:191 (VK_OEM_2) -> linux:53 (KEY_SLASH) -> qcode:Q_KEY_CODE_SLASH (slash) */
Q_KEY_CODE_GRAVE_ACCENT, /* win32:192 (VK_OEM_3) -> linux:41 (KEY_GRAVE) -> qcode:Q_KEY_CODE_GRAVE_ACCENT (grave_accent) */
Q_KEY_CODE_UNMAPPED, /* win32:193 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:194 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:195 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:196 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:197 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:198 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:199 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:200 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:201 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:202 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:203 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:204 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:205 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:206 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:207 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:208 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:209 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:210 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:211 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:212 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:213 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:214 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:215 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:216 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:217 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:218 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_BRACKET_LEFT, /* win32:219 (VK_OEM_4) -> linux:26 (KEY_LEFTBRACE) -> qcode:Q_KEY_CODE_BRACKET_LEFT (bracket_left) */
Q_KEY_CODE_BACKSLASH, /* win32:220 (VK_OEM_5) -> linux:43 (KEY_BACKSLASH) -> qcode:Q_KEY_CODE_BACKSLASH (backslash) */
Q_KEY_CODE_BRACKET_RIGHT, /* win32:221 (VK_OEM_6) -> linux:27 (KEY_RIGHTBRACE) -> qcode:Q_KEY_CODE_BRACKET_RIGHT (bracket_right) */
Q_KEY_CODE_APOSTROPHE, /* win32:222 (VK_OEM_7) -> linux:40 (KEY_APOSTROPHE) -> qcode:Q_KEY_CODE_APOSTROPHE (apostrophe) */
Q_KEY_CODE_UNMAPPED, /* win32:223 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:224 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_LESS, /* win32:225 (VK_OEM_102) -> linux:86 (KEY_102ND) -> qcode:Q_KEY_CODE_LESS (less) */
Q_KEY_CODE_UNMAPPED, /* win32:226 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:227 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:228 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:229 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:230 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:231 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:232 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:233 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:234 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:235 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:236 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:237 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:238 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:239 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:240 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:241 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:242 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:243 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:244 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:245 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:246 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:247 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:248 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:249 (unnamed) -> linux:None (unnamed) -> qcode:None (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:250 (VK_PLAY) -> linux:207 (KEY_PLAY) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
Q_KEY_CODE_UNMAPPED, /* win32:251 (VK_ZOOM) -> linux:372 (KEY_ZOOM) -> qcode:Q_KEY_CODE_UNMAPPED (unnamed) */
};

View File

@ -18,5 +18,5 @@
extern const std::map<const QKeyCode, unsigned short> qemu_input_map_qcode_to_qnum;
int qemu_input_qcode_to_number(const QKeyCode value);
int qemu_input_key_value_to_number(const KeyValue *value);
int qemu_input_key_value_to_scancode(const KeyValue *value, bool down, int *codes);
int qemu_input_key_value_to_number(const KeyValue* value);
int qemu_input_key_value_to_scancode(const KeyValue* value, bool down, int* codes);

View File

@ -24,133 +24,149 @@
//#include "qemu/cutils.h"
#include <cassert>
size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt,
size_t offset, const void *buf, size_t bytes)
size_t iov_from_buf_full(const struct iovec* iov, unsigned int iov_cnt,
size_t offset, const void* buf, size_t bytes)
{
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
if (offset < iov[i].iov_len) {
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memcpy((char *)iov[i].iov_base + offset, (char *)buf + done, len);
done += len;
offset = 0;
} else {
offset -= iov[i].iov_len;
}
}
assert(offset == 0);
return done;
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++)
{
if (offset < iov[i].iov_len)
{
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memcpy((char*)iov[i].iov_base + offset, (char*)buf + done, len);
done += len;
offset = 0;
}
else
{
offset -= iov[i].iov_len;
}
}
assert(offset == 0);
return done;
}
size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt,
size_t offset, void *buf, size_t bytes)
size_t iov_to_buf_full(const struct iovec* iov, const unsigned int iov_cnt,
size_t offset, void* buf, size_t bytes)
{
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
if (offset < iov[i].iov_len) {
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memcpy((char *)buf + done, (char *)iov[i].iov_base + offset, len);
done += len;
offset = 0;
} else {
offset -= iov[i].iov_len;
}
}
assert(offset == 0);
return done;
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++)
{
if (offset < iov[i].iov_len)
{
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memcpy((char*)buf + done, (char*)iov[i].iov_base + offset, len);
done += len;
offset = 0;
}
else
{
offset -= iov[i].iov_len;
}
}
assert(offset == 0);
return done;
}
size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
size_t offset, int fillc, size_t bytes)
size_t iov_memset(const struct iovec* iov, const unsigned int iov_cnt,
size_t offset, int fillc, size_t bytes)
{
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
if (offset < iov[i].iov_len) {
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memset((char *)iov[i].iov_base + offset, fillc, len);
done += len;
offset = 0;
} else {
offset -= iov[i].iov_len;
}
}
assert(offset == 0);
return done;
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++)
{
if (offset < iov[i].iov_len)
{
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memset((char*)iov[i].iov_base + offset, fillc, len);
done += len;
offset = 0;
}
else
{
offset -= iov[i].iov_len;
}
}
assert(offset == 0);
return done;
}
size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt)
size_t iov_size(const struct iovec* iov, const unsigned int iov_cnt)
{
size_t len;
unsigned int i;
size_t len;
unsigned int i;
len = 0;
for (i = 0; i < iov_cnt; i++) {
len += iov[i].iov_len;
}
return len;
len = 0;
for (i = 0; i < iov_cnt; i++)
{
len += iov[i].iov_len;
}
return len;
}
unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
const struct iovec *iov, unsigned int iov_cnt,
size_t offset, size_t bytes)
unsigned iov_copy(struct iovec* dst_iov, unsigned int dst_iov_cnt,
const struct iovec* iov, unsigned int iov_cnt,
size_t offset, size_t bytes)
{
size_t len;
unsigned int i, j;
for (i = 0, j = 0;
i < iov_cnt && j < dst_iov_cnt && (offset || bytes); i++) {
if (offset >= iov[i].iov_len) {
offset -= iov[i].iov_len;
continue;
}
len = MIN(bytes, iov[i].iov_len - offset);
size_t len;
unsigned int i, j;
for (i = 0, j = 0;
i < iov_cnt && j < dst_iov_cnt && (offset || bytes); i++)
{
if (offset >= iov[i].iov_len)
{
offset -= iov[i].iov_len;
continue;
}
len = MIN(bytes, iov[i].iov_len - offset);
dst_iov[j].iov_base = (char *)iov[i].iov_base + offset;
dst_iov[j].iov_len = len;
j++;
bytes -= len;
offset = 0;
}
assert(offset == 0);
return j;
dst_iov[j].iov_base = (char*)iov[i].iov_base + offset;
dst_iov[j].iov_len = len;
j++;
bytes -= len;
offset = 0;
}
assert(offset == 0);
return j;
}
/* io vectors */
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
void qemu_iovec_init(QEMUIOVector* qiov, int alloc_hint)
{
qiov->iov = my_g_new(struct iovec, alloc_hint);
qiov->niov = 0;
qiov->nalloc = alloc_hint;
qiov->size = 0;
qiov->iov = my_g_new(struct iovec, alloc_hint);
qiov->niov = 0;
qiov->nalloc = alloc_hint;
qiov->size = 0;
}
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
void qemu_iovec_init_external(QEMUIOVector* qiov, struct iovec* iov, int niov)
{
int i;
int i;
qiov->iov = iov;
qiov->niov = niov;
qiov->nalloc = -1;
qiov->size = 0;
for (i = 0; i < niov; i++)
qiov->size += iov[i].iov_len;
qiov->iov = iov;
qiov->niov = niov;
qiov->nalloc = -1;
qiov->size = 0;
for (i = 0; i < niov; i++)
qiov->size += iov[i].iov_len;
}
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
void qemu_iovec_add(QEMUIOVector* qiov, void* base, size_t len)
{
assert(qiov->nalloc != -1);
assert(qiov->nalloc != -1);
if (qiov->niov == qiov->nalloc) {
qiov->nalloc = 2 * qiov->nalloc + 1;
qiov->iov = my_g_renew(struct iovec, qiov->iov, qiov->nalloc);
}
qiov->iov[qiov->niov].iov_base = base;
qiov->iov[qiov->niov].iov_len = len;
qiov->size += len;
++qiov->niov;
if (qiov->niov == qiov->nalloc)
{
qiov->nalloc = 2 * qiov->nalloc + 1;
qiov->iov = my_g_renew(struct iovec, qiov->iov, qiov->nalloc);
}
qiov->iov[qiov->niov].iov_base = base;
qiov->iov[qiov->niov].iov_len = len;
qiov->size += len;
++qiov->niov;
}
/*
@ -163,30 +179,35 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
* of src".
* Only vector pointers are processed, not the actual data buffers.
*/
size_t qemu_iovec_concat_iov(QEMUIOVector *dst,
struct iovec *src_iov, unsigned int src_cnt,
size_t soffset, size_t sbytes)
size_t qemu_iovec_concat_iov(QEMUIOVector* dst,
struct iovec* src_iov, unsigned int src_cnt,
size_t soffset, size_t sbytes)
{
unsigned int i;
size_t done;
unsigned int i;
size_t done;
if (!sbytes) {
return 0;
}
assert(dst->nalloc != -1);
for (i = 0, done = 0; done < sbytes && i < src_cnt; i++) {
if (soffset < src_iov[i].iov_len) {
size_t len = MIN(src_iov[i].iov_len - soffset, sbytes - done);
qemu_iovec_add(dst, (char *)src_iov[i].iov_base + soffset, len);
done += len;
soffset = 0;
} else {
soffset -= src_iov[i].iov_len;
}
}
assert(soffset == 0); /* offset beyond end of src */
if (!sbytes)
{
return 0;
}
assert(dst->nalloc != -1);
for (i = 0, done = 0; done < sbytes && i < src_cnt; i++)
{
if (soffset < src_iov[i].iov_len)
{
size_t len = MIN(src_iov[i].iov_len - soffset, sbytes - done);
qemu_iovec_add(dst, (char*)src_iov[i].iov_base + soffset, len);
done += len;
soffset = 0;
}
else
{
soffset -= src_iov[i].iov_len;
}
}
assert(soffset == 0); /* offset beyond end of src */
return done;
return done;
}
/*
@ -199,10 +220,10 @@ size_t qemu_iovec_concat_iov(QEMUIOVector *dst,
* of src".
* Only vector pointers are processed, not the actual data buffers.
*/
void qemu_iovec_concat(QEMUIOVector *dst,
QEMUIOVector *src, size_t soffset, size_t sbytes)
void qemu_iovec_concat(QEMUIOVector* dst,
QEMUIOVector* src, size_t soffset, size_t sbytes)
{
qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes);
qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes);
}
/*
@ -226,40 +247,40 @@ void qemu_iovec_concat(QEMUIOVector *dst,
return true;
}*/
void qemu_iovec_destroy(QEMUIOVector *qiov)
void qemu_iovec_destroy(QEMUIOVector* qiov)
{
assert(qiov->nalloc != -1);
assert(qiov->nalloc != -1);
qemu_iovec_reset(qiov);
my_g_free(qiov->iov);
qiov->nalloc = 0;
qiov->iov = NULL;
qemu_iovec_reset(qiov);
my_g_free(qiov->iov);
qiov->nalloc = 0;
qiov->iov = NULL;
}
void qemu_iovec_reset(QEMUIOVector *qiov)
void qemu_iovec_reset(QEMUIOVector* qiov)
{
assert(qiov->nalloc != -1);
assert(qiov->nalloc != -1);
qiov->niov = 0;
qiov->size = 0;
qiov->niov = 0;
qiov->size = 0;
}
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
void *buf, size_t bytes)
size_t qemu_iovec_to_buf(QEMUIOVector* qiov, size_t offset,
void* buf, size_t bytes)
{
return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
}
size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
const void *buf, size_t bytes)
size_t qemu_iovec_from_buf(QEMUIOVector* qiov, size_t offset,
const void* buf, size_t bytes)
{
return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
}
size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
int fillc, size_t bytes)
size_t qemu_iovec_memset(QEMUIOVector* qiov, size_t offset,
int fillc, size_t bytes)
{
return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
}
/**
@ -272,118 +293,132 @@ size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
* @b: I/O vector
* @ret: Offset to first mismatching byte or -1 if match
*/
ssize_t qemu_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
ssize_t qemu_iovec_compare(QEMUIOVector* a, QEMUIOVector* b)
{
int i;
ssize_t offset = 0;
int i;
ssize_t offset = 0;
assert(a->niov == b->niov);
for (i = 0; i < a->niov; i++) {
size_t len = 0;
uint8_t *p = (uint8_t *)a->iov[i].iov_base;
uint8_t *q = (uint8_t *)b->iov[i].iov_base;
assert(a->niov == b->niov);
for (i = 0; i < a->niov; i++)
{
size_t len = 0;
uint8_t* p = (uint8_t*)a->iov[i].iov_base;
uint8_t* q = (uint8_t*)b->iov[i].iov_base;
assert(a->iov[i].iov_len == b->iov[i].iov_len);
while (len < a->iov[i].iov_len && *p++ == *q++) {
len++;
}
assert(a->iov[i].iov_len == b->iov[i].iov_len);
while (len < a->iov[i].iov_len && *p++ == *q++)
{
len++;
}
offset += len;
offset += len;
if (len != a->iov[i].iov_len) {
return offset;
}
}
return -1;
if (len != a->iov[i].iov_len)
{
return offset;
}
}
return -1;
}
typedef struct {
int src_index;
struct iovec *src_iov;
void *dest_base;
typedef struct
{
int src_index;
struct iovec* src_iov;
void* dest_base;
} IOVectorSortElem;
static int sortelem_cmp_src_base(const void *a, const void *b)
static int sortelem_cmp_src_base(const void* a, const void* b)
{
const IOVectorSortElem *elem_a = (const IOVectorSortElem *)a;
const IOVectorSortElem *elem_b = (const IOVectorSortElem *)b;
const IOVectorSortElem* elem_a = (const IOVectorSortElem*)a;
const IOVectorSortElem* elem_b = (const IOVectorSortElem*)b;
/* Don't overflow */
if (elem_a->src_iov->iov_base < elem_b->src_iov->iov_base) {
return -1;
} else if (elem_a->src_iov->iov_base > elem_b->src_iov->iov_base) {
return 1;
} else {
return 0;
}
/* Don't overflow */
if (elem_a->src_iov->iov_base < elem_b->src_iov->iov_base)
{
return -1;
}
else if (elem_a->src_iov->iov_base > elem_b->src_iov->iov_base)
{
return 1;
}
else
{
return 0;
}
}
static int sortelem_cmp_src_index(const void *a, const void *b)
static int sortelem_cmp_src_index(const void* a, const void* b)
{
const IOVectorSortElem *elem_a = (const IOVectorSortElem *)a;
const IOVectorSortElem *elem_b = (const IOVectorSortElem *)b;
const IOVectorSortElem* elem_a = (const IOVectorSortElem*)a;
const IOVectorSortElem* elem_b = (const IOVectorSortElem*)b;
return elem_a->src_index - elem_b->src_index;
return elem_a->src_index - elem_b->src_index;
}
size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt,
size_t bytes)
size_t iov_discard_front(struct iovec** iov, unsigned int* iov_cnt,
size_t bytes)
{
size_t total = 0;
struct iovec *cur;
size_t total = 0;
struct iovec* cur;
for (cur = *iov; *iov_cnt > 0; cur++) {
if (cur->iov_len > bytes) {
cur->iov_base = (uint8_t *)cur->iov_base + bytes;
cur->iov_len -= bytes;
total += bytes;
break;
}
for (cur = *iov; *iov_cnt > 0; cur++)
{
if (cur->iov_len > bytes)
{
cur->iov_base = (uint8_t*)cur->iov_base + bytes;
cur->iov_len -= bytes;
total += bytes;
break;
}
bytes -= cur->iov_len;
total += cur->iov_len;
*iov_cnt -= 1;
}
bytes -= cur->iov_len;
total += cur->iov_len;
*iov_cnt -= 1;
}
*iov = cur;
return total;
*iov = cur;
return total;
}
size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt,
size_t bytes)
size_t iov_discard_back(struct iovec* iov, unsigned int* iov_cnt,
size_t bytes)
{
size_t total = 0;
struct iovec *cur;
size_t total = 0;
struct iovec* cur;
if (*iov_cnt == 0) {
return 0;
}
if (*iov_cnt == 0)
{
return 0;
}
cur = iov + (*iov_cnt - 1);
cur = iov + (*iov_cnt - 1);
while (*iov_cnt > 0) {
if (cur->iov_len > bytes) {
cur->iov_len -= bytes;
total += bytes;
break;
}
while (*iov_cnt > 0)
{
if (cur->iov_len > bytes)
{
cur->iov_len -= bytes;
total += bytes;
break;
}
bytes -= cur->iov_len;
total += cur->iov_len;
cur--;
*iov_cnt -= 1;
}
bytes -= cur->iov_len;
total += cur->iov_len;
cur--;
*iov_cnt -= 1;
}
return total;
return total;
}
void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes)
void qemu_iovec_discard_back(QEMUIOVector* qiov, size_t bytes)
{
unsigned int niov = qiov->niov;
unsigned int niov = qiov->niov;
assert(qiov->size >= bytes);
assert(iov_discard_back(qiov->iov, &niov, bytes) == bytes);
assert(qiov->size >= bytes);
assert(iov_discard_back(qiov->iov, &niov, bytes) == bytes);
qiov->niov = niov;
qiov->size -= bytes;
qiov->niov = niov;
qiov->size -= bytes;
}

View File

@ -15,9 +15,10 @@
#define IOV_H
#if !defined(_BITS_UIO_H) && !defined(__iovec_defined) /* /usr/include/bits/uio.h */
struct iovec {
void *iov_base;
size_t iov_len;
struct iovec
{
void* iov_base;
size_t iov_len;
};
#endif
@ -25,7 +26,7 @@ struct iovec {
* count and return data size, in bytes, of an iovec
* starting at `iov' of `iov_cnt' number of elements.
*/
size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt);
size_t iov_size(const struct iovec* iov, const unsigned int iov_cnt);
/**
* Copy from single continuous buffer to scatter-gather vector of buffers
@ -44,35 +45,41 @@ size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt);
* such "large" value is -1 (sinice size_t is unsigned),
* so specifying `-1' as `bytes' means 'up to the end of iovec'.
*/
size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt,
size_t offset, const void *buf, size_t bytes);
size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt,
size_t offset, void *buf, size_t bytes);
size_t iov_from_buf_full(const struct iovec* iov, unsigned int iov_cnt,
size_t offset, const void* buf, size_t bytes);
size_t iov_to_buf_full(const struct iovec* iov, const unsigned int iov_cnt,
size_t offset, void* buf, size_t bytes);
static inline size_t
iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
size_t offset, const void *buf, size_t bytes)
iov_from_buf(const struct iovec* iov, unsigned int iov_cnt,
size_t offset, const void* buf, size_t bytes)
{
if (__builtin_constant_p(bytes) && iov_cnt &&
offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) {
memcpy((char *)iov[0].iov_base + offset, buf, bytes);
return bytes;
} else {
return iov_from_buf_full(iov, iov_cnt, offset, buf, bytes);
}
if (__builtin_constant_p(bytes) && iov_cnt &&
offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset)
{
memcpy((char*)iov[0].iov_base + offset, buf, bytes);
return bytes;
}
else
{
return iov_from_buf_full(iov, iov_cnt, offset, buf, bytes);
}
}
static inline size_t
iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
size_t offset, void *buf, size_t bytes)
iov_to_buf(const struct iovec* iov, const unsigned int iov_cnt,
size_t offset, void* buf, size_t bytes)
{
if (__builtin_constant_p(bytes) && iov_cnt &&
offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) {
memcpy(buf, (char *)iov[0].iov_base + offset, bytes);
return bytes;
} else {
return iov_to_buf_full(iov, iov_cnt, offset, buf, bytes);
}
if (__builtin_constant_p(bytes) && iov_cnt &&
offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset)
{
memcpy(buf, (char*)iov[0].iov_base + offset, bytes);
return bytes;
}
else
{
return iov_to_buf_full(iov, iov_cnt, offset, buf, bytes);
}
}
/**
@ -85,8 +92,8 @@ iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
* min(size, iov_size(iov) - offset).
* Again, it is okay to use large value for `bytes' to mean "up to the end".
*/
size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
size_t offset, int fillc, size_t bytes);
size_t iov_memset(const struct iovec* iov, const unsigned int iov_cnt,
size_t offset, int fillc, size_t bytes);
/*
* Send/recv data from/to iovec buffers directly
@ -106,29 +113,29 @@ size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
* For iov_send_recv() _whole_ area being sent or received
* should be within the iovec, not only beginning of it.
*/
ssize_t iov_send_recv(int sockfd, const struct iovec *iov, unsigned iov_cnt,
size_t offset, size_t bytes, bool do_send);
ssize_t iov_send_recv(int sockfd, const struct iovec* iov, unsigned iov_cnt,
size_t offset, size_t bytes, bool do_send);
#define iov_recv(sockfd, iov, iov_cnt, offset, bytes) \
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, false)
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, false)
#define iov_send(sockfd, iov, iov_cnt, offset, bytes) \
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, true)
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, true)
/**
* Produce a text hexdump of iovec `iov' with `iov_cnt' number of elements
* in file `fp', prefixing each line with `prefix' and processing not more
* than `limit' data bytes.
*/
void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
FILE *fp, const char *prefix, size_t limit);
void iov_hexdump(const struct iovec* iov, const unsigned int iov_cnt,
FILE* fp, const char* prefix, size_t limit);
/*
* Partial copy of vector from iov to dst_iov (data is not copied).
* dst_iov overlaps iov at a specified offset.
* size of dst_iov is at most bytes. dst vector count is returned.
*/
unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
const struct iovec *iov, unsigned int iov_cnt,
size_t offset, size_t bytes);
unsigned iov_copy(struct iovec* dst_iov, unsigned int dst_iov_cnt,
const struct iovec* iov, unsigned int iov_cnt,
size_t offset, size_t bytes);
/*
* Remove a given number of bytes from the front or back of a vector.
@ -138,37 +145,38 @@ unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
* The number of bytes actually discarded is returned. This number may be
* smaller than requested if the vector is too small.
*/
size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt,
size_t bytes);
size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt,
size_t bytes);
size_t iov_discard_front(struct iovec** iov, unsigned int* iov_cnt,
size_t bytes);
size_t iov_discard_back(struct iovec* iov, unsigned int* iov_cnt,
size_t bytes);
typedef struct QEMUIOVector {
struct iovec *iov;
int niov;
int nalloc;
size_t size;
typedef struct QEMUIOVector
{
struct iovec* iov;
int niov;
int nalloc;
size_t size;
} QEMUIOVector;
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
void qemu_iovec_concat(QEMUIOVector *dst,
QEMUIOVector *src, size_t soffset, size_t sbytes);
size_t qemu_iovec_concat_iov(QEMUIOVector *dst,
struct iovec *src_iov, unsigned int src_cnt,
size_t soffset, size_t sbytes);
bool qemu_iovec_is_zero(QEMUIOVector *qiov);
void qemu_iovec_destroy(QEMUIOVector *qiov);
void qemu_iovec_reset(QEMUIOVector *qiov);
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
void *buf, size_t bytes);
size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
const void *buf, size_t bytes);
size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
int fillc, size_t bytes);
ssize_t qemu_iovec_compare(QEMUIOVector *a, QEMUIOVector *b);
void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf);
void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes);
void qemu_iovec_init(QEMUIOVector* qiov, int alloc_hint);
void qemu_iovec_init_external(QEMUIOVector* qiov, struct iovec* iov, int niov);
void qemu_iovec_add(QEMUIOVector* qiov, void* base, size_t len);
void qemu_iovec_concat(QEMUIOVector* dst,
QEMUIOVector* src, size_t soffset, size_t sbytes);
size_t qemu_iovec_concat_iov(QEMUIOVector* dst,
struct iovec* src_iov, unsigned int src_cnt,
size_t soffset, size_t sbytes);
bool qemu_iovec_is_zero(QEMUIOVector* qiov);
void qemu_iovec_destroy(QEMUIOVector* qiov);
void qemu_iovec_reset(QEMUIOVector* qiov);
size_t qemu_iovec_to_buf(QEMUIOVector* qiov, size_t offset,
void* buf, size_t bytes);
size_t qemu_iovec_from_buf(QEMUIOVector* qiov, size_t offset,
const void* buf, size_t bytes);
size_t qemu_iovec_memset(QEMUIOVector* qiov, size_t offset,
int fillc, size_t bytes);
ssize_t qemu_iovec_compare(QEMUIOVector* a, QEMUIOVector* b);
void qemu_iovec_clone(QEMUIOVector* dest, const QEMUIOVector* src, void* buf);
void qemu_iovec_discard_back(QEMUIOVector* qiov, size_t bytes);
#endif

View File

@ -83,390 +83,472 @@
/*
* List definitions.
*/
#define QLIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define QLIST_HEAD(name, type) \
struct name \
{ \
struct type* lh_first; /* first element */ \
}
#define QLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define QLIST_HEAD_INITIALIZER(head) \
{ \
NULL \
}
#define QLIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
#define QLIST_ENTRY(type) \
struct \
{ \
struct type* le_next; /* next element */ \
struct type** le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#define QLIST_INIT(head) do { \
(head)->lh_first = NULL; \
} while (/*CONSTCOND*/0)
#define QLIST_INIT(head) \
do \
{ \
(head)->lh_first = NULL; \
} while (/*CONSTCOND*/ 0)
#define QLIST_SWAP(dstlist, srclist, field) do { \
void *tmplist; \
tmplist = (srclist)->lh_first; \
(srclist)->lh_first = (dstlist)->lh_first; \
if ((srclist)->lh_first != NULL) { \
(srclist)->lh_first->field.le_prev = &(srclist)->lh_first; \
} \
(dstlist)->lh_first = tmplist; \
if ((dstlist)->lh_first != NULL) { \
(dstlist)->lh_first->field.le_prev = &(dstlist)->lh_first; \
} \
} while (/*CONSTCOND*/0)
#define QLIST_SWAP(dstlist, srclist, field) \
do \
{ \
void* tmplist; \
tmplist = (srclist)->lh_first; \
(srclist)->lh_first = (dstlist)->lh_first; \
if ((srclist)->lh_first != NULL) \
{ \
(srclist)->lh_first->field.le_prev = &(srclist)->lh_first; \
} \
(dstlist)->lh_first = tmplist; \
if ((dstlist)->lh_first != NULL) \
{ \
(dstlist)->lh_first->field.le_prev = &(dstlist)->lh_first; \
} \
} while (/*CONSTCOND*/ 0)
#define QLIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (/*CONSTCOND*/0)
#define QLIST_INSERT_AFTER(listelm, elm, field) \
do \
{ \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (/*CONSTCOND*/ 0)
#define QLIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (/*CONSTCOND*/0)
#define QLIST_INSERT_BEFORE(listelm, elm, field) \
do \
{ \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (/*CONSTCOND*/ 0)
#define QLIST_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (/*CONSTCOND*/0)
#define QLIST_INSERT_HEAD(head, elm, field) \
do \
{ \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next; \
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (/*CONSTCOND*/ 0)
#define QLIST_REMOVE(elm, field) do { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
} while (/*CONSTCOND*/0)
#define QLIST_REMOVE(elm, field) \
do \
{ \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
} while (/*CONSTCOND*/ 0)
#define QLIST_FOREACH(var, head, field) \
for ((var) = ((head)->lh_first); \
(var); \
(var) = ((var)->field.le_next))
#define QLIST_FOREACH(var, head, field) \
for ((var) = ((head)->lh_first); \
(var); \
(var) = ((var)->field.le_next))
#define QLIST_FOREACH_SAFE(var, head, field, next_var) \
for ((var) = ((head)->lh_first); \
(var) && ((next_var) = ((var)->field.le_next), 1); \
(var) = (next_var))
#define QLIST_FOREACH_SAFE(var, head, field, next_var) \
for ((var) = ((head)->lh_first); \
(var) && ((next_var) = ((var)->field.le_next), 1); \
(var) = (next_var))
/*
* List access methods.
*/
#define QLIST_EMPTY(head) ((head)->lh_first == NULL)
#define QLIST_FIRST(head) ((head)->lh_first)
#define QLIST_NEXT(elm, field) ((elm)->field.le_next)
#define QLIST_EMPTY(head) ((head)->lh_first == NULL)
#define QLIST_FIRST(head) ((head)->lh_first)
#define QLIST_NEXT(elm, field) ((elm)->field.le_next)
/*
* Singly-linked List definitions.
*/
#define QSLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define QSLIST_HEAD(name, type) \
struct name \
{ \
struct type* slh_first; /* first element */ \
}
#define QSLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define QSLIST_HEAD_INITIALIZER(head) \
{ \
NULL \
}
#define QSLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
#define QSLIST_ENTRY(type) \
struct \
{ \
struct type* sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#define QSLIST_INIT(head) do { \
(head)->slh_first = NULL; \
} while (/*CONSTCOND*/0)
#define QSLIST_INIT(head) \
do \
{ \
(head)->slh_first = NULL; \
} while (/*CONSTCOND*/ 0)
#define QSLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (/*CONSTCOND*/0)
#define QSLIST_INSERT_AFTER(slistelm, elm, field) \
do \
{ \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (/*CONSTCOND*/ 0)
#define QSLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (/*CONSTCOND*/0)
#define QSLIST_INSERT_HEAD(head, elm, field) \
do \
{ \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (/*CONSTCOND*/ 0)
#define QSLIST_INSERT_HEAD_ATOMIC(head, elm, field) do { \
typeof(elm) save_sle_next; \
do { \
save_sle_next = (elm)->field.sle_next = (head)->slh_first; \
} while (atomic_cmpxchg(&(head)->slh_first, save_sle_next, (elm)) != \
save_sle_next); \
} while (/*CONSTCOND*/0)
#define QSLIST_INSERT_HEAD_ATOMIC(head, elm, field) \
do \
{ \
typeof(elm) save_sle_next; \
do \
{ \
save_sle_next = (elm)->field.sle_next = (head)->slh_first; \
} while (atomic_cmpxchg(&(head)->slh_first, save_sle_next, (elm)) != \
save_sle_next); \
} while (/*CONSTCOND*/ 0)
#define QSLIST_MOVE_ATOMIC(dest, src) do { \
(dest)->slh_first = atomic_xchg(&(src)->slh_first, NULL); \
} while (/*CONSTCOND*/0)
#define QSLIST_MOVE_ATOMIC(dest, src) \
do \
{ \
(dest)->slh_first = atomic_xchg(&(src)->slh_first, NULL); \
} while (/*CONSTCOND*/ 0)
#define QSLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (/*CONSTCOND*/0)
#define QSLIST_REMOVE_HEAD(head, field) \
do \
{ \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (/*CONSTCOND*/ 0)
#define QSLIST_REMOVE_AFTER(slistelm, field) do { \
(slistelm)->field.sle_next = \
QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \
} while (/*CONSTCOND*/0)
#define QSLIST_REMOVE_AFTER(slistelm, field) \
do \
{ \
(slistelm)->field.sle_next = \
QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \
} while (/*CONSTCOND*/ 0)
#define QSLIST_FOREACH(var, head, field) \
for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
#define QSLIST_FOREACH(var, head, field) \
for ((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
#define QSLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = QSLIST_FIRST((head)); \
(var) && ((tvar) = QSLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define QSLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = QSLIST_FIRST((head)); \
(var) && ((tvar) = QSLIST_NEXT((var), field), 1); \
(var) = (tvar))
/*
* Singly-linked List access methods.
*/
#define QSLIST_EMPTY(head) ((head)->slh_first == NULL)
#define QSLIST_FIRST(head) ((head)->slh_first)
#define QSLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define QSLIST_EMPTY(head) ((head)->slh_first == NULL)
#define QSLIST_FIRST(head) ((head)->slh_first)
#define QSLIST_NEXT(elm, field) ((elm)->field.sle_next)
/*
* Simple queue definitions.
*/
#define QSIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
#define QSIMPLEQ_HEAD(name, type) \
struct name \
{ \
struct type* sqh_first; /* first element */ \
struct type** sqh_last; /* addr of last next element */ \
}
#define QSIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#define QSIMPLEQ_HEAD_INITIALIZER(head) \
{ \
NULL, &(head).sqh_first \
}
#define QSIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; /* next element */ \
}
#define QSIMPLEQ_ENTRY(type) \
struct \
{ \
struct type* sqe_next; /* next element */ \
}
/*
* Simple queue functions.
*/
#define QSIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (/*CONSTCOND*/0)
#define QSIMPLEQ_INIT(head) \
do \
{ \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (/*CONSTCOND*/ 0)
#define QSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (/*CONSTCOND*/0)
#define QSIMPLEQ_INSERT_HEAD(head, elm, field) \
do \
{ \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (/*CONSTCOND*/ 0)
#define QSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (/*CONSTCOND*/0)
#define QSIMPLEQ_INSERT_TAIL(head, elm, field) \
do \
{ \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (/*CONSTCOND*/ 0)
#define QSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (/*CONSTCOND*/0)
#define QSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) \
do \
{ \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (/*CONSTCOND*/ 0)
#define QSIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL)\
(head)->sqh_last = &(head)->sqh_first; \
} while (/*CONSTCOND*/0)
#define QSIMPLEQ_REMOVE_HEAD(head, field) \
do \
{ \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (/*CONSTCOND*/ 0)
#define QSIMPLEQ_SPLIT_AFTER(head, elm, field, removed) do { \
QSIMPLEQ_INIT(removed); \
if (((removed)->sqh_first = (head)->sqh_first) != NULL) { \
if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) { \
(head)->sqh_last = &(head)->sqh_first; \
} \
(removed)->sqh_last = &(elm)->field.sqe_next; \
(elm)->field.sqe_next = NULL; \
} \
} while (/*CONSTCOND*/0)
#define QSIMPLEQ_SPLIT_AFTER(head, elm, field, removed) \
do \
{ \
QSIMPLEQ_INIT(removed); \
if (((removed)->sqh_first = (head)->sqh_first) != NULL) \
{ \
if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \
{ \
(head)->sqh_last = &(head)->sqh_first; \
} \
(removed)->sqh_last = &(elm)->field.sqe_next; \
(elm)->field.sqe_next = NULL; \
} \
} while (/*CONSTCOND*/ 0)
#define QSIMPLEQ_REMOVE(head, elm, type, field) do { \
if ((head)->sqh_first == (elm)) { \
QSIMPLEQ_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->sqh_first; \
while (curelm->field.sqe_next != (elm)) \
curelm = curelm->field.sqe_next; \
if ((curelm->field.sqe_next = \
curelm->field.sqe_next->field.sqe_next) == NULL) \
(head)->sqh_last = &(curelm)->field.sqe_next; \
} \
} while (/*CONSTCOND*/0)
#define QSIMPLEQ_REMOVE(head, elm, type, field) \
do \
{ \
if ((head)->sqh_first == (elm)) \
{ \
QSIMPLEQ_REMOVE_HEAD((head), field); \
} \
else \
{ \
struct type* curelm = (head)->sqh_first; \
while (curelm->field.sqe_next != (elm)) \
curelm = curelm->field.sqe_next; \
if ((curelm->field.sqe_next = \
curelm->field.sqe_next->field.sqe_next) == NULL) \
(head)->sqh_last = &(curelm)->field.sqe_next; \
} \
} while (/*CONSTCOND*/ 0)
#define QSIMPLEQ_FOREACH(var, head, field) \
for ((var) = ((head)->sqh_first); \
(var); \
(var) = ((var)->field.sqe_next))
#define QSIMPLEQ_FOREACH(var, head, field) \
for ((var) = ((head)->sqh_first); \
(var); \
(var) = ((var)->field.sqe_next))
#define QSIMPLEQ_FOREACH_SAFE(var, head, field, next) \
for ((var) = ((head)->sqh_first); \
(var) && ((next = ((var)->field.sqe_next)), 1); \
(var) = (next))
#define QSIMPLEQ_FOREACH_SAFE(var, head, field, next) \
for ((var) = ((head)->sqh_first); \
(var) && ((next = ((var)->field.sqe_next)), 1); \
(var) = (next))
#define QSIMPLEQ_CONCAT(head1, head2) do { \
if (!QSIMPLEQ_EMPTY((head2))) { \
*(head1)->sqh_last = (head2)->sqh_first; \
(head1)->sqh_last = (head2)->sqh_last; \
QSIMPLEQ_INIT((head2)); \
} \
} while (/*CONSTCOND*/0)
#define QSIMPLEQ_CONCAT(head1, head2) \
do \
{ \
if (!QSIMPLEQ_EMPTY((head2))) \
{ \
*(head1)->sqh_last = (head2)->sqh_first; \
(head1)->sqh_last = (head2)->sqh_last; \
QSIMPLEQ_INIT((head2)); \
} \
} while (/*CONSTCOND*/ 0)
#define QSIMPLEQ_LAST(head, type, field) \
(QSIMPLEQ_EMPTY((head)) ? \
NULL : \
((struct type *)(void *) \
((char *)((head)->sqh_last) - offsetof(struct type, field))))
#define QSIMPLEQ_LAST(head, type, field) \
(QSIMPLEQ_EMPTY((head)) ? \
NULL : \
((struct type*)(void*)((char*)((head)->sqh_last) - offsetof(struct type, field))))
/*
* Simple queue access methods.
*/
#define QSIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
#define QSIMPLEQ_FIRST(head) ((head)->sqh_first)
#define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
#define QSIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
#define QSIMPLEQ_FIRST(head) ((head)->sqh_first)
#define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
/*
* Tail queue definitions.
*/
#define Q_TAILQ_HEAD(name, type, qual) \
struct name { \
qual type *tqh_first; /* first element */ \
qual type *qual *tqh_last; /* addr of last next element */ \
}
#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type,)
#define Q_TAILQ_HEAD(name, type, qual) \
struct name \
{ \
qual type* tqh_first; /* first element */ \
qual type* qual* tqh_last; /* addr of last next element */ \
}
#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type, )
#define QTAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define QTAILQ_HEAD_INITIALIZER(head) \
{ \
NULL, &(head).tqh_first \
}
#define Q_TAILQ_ENTRY(type, qual) \
struct { \
qual type *tqe_next; /* next element */ \
qual type *qual *tqe_prev; /* address of previous next element */\
}
#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type,)
#define Q_TAILQ_ENTRY(type, qual) \
struct \
{ \
qual type* tqe_next; /* next element */ \
qual type* qual* tqe_prev; /* address of previous next element */ \
}
#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type, )
/*
* Tail queue functions.
*/
#define QTAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INIT(head) \
do \
{ \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (/*CONSTCOND*/ 0)
#define QTAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INSERT_HEAD(head, elm, field) \
do \
{ \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (/*CONSTCOND*/ 0)
#define QTAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INSERT_TAIL(head, elm, field) \
do \
{ \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (/*CONSTCOND*/ 0)
#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) \
do \
{ \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (/*CONSTCOND*/ 0)
#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INSERT_BEFORE(listelm, elm, field) \
do \
{ \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (/*CONSTCOND*/ 0)
#define QTAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
(elm)->field.tqe_prev = NULL; \
} while (/*CONSTCOND*/0)
#define QTAILQ_REMOVE(head, elm, field) \
do \
{ \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
(elm)->field.tqe_prev = NULL; \
} while (/*CONSTCOND*/ 0)
#define QTAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->tqh_first); \
(var); \
(var) = ((var)->field.tqe_next))
#define QTAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->tqh_first); \
(var); \
(var) = ((var)->field.tqe_next))
#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \
for ((var) = ((head)->tqh_first); \
(var) && ((next_var) = ((var)->field.tqe_next), 1); \
(var) = (next_var))
#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \
for ((var) = ((head)->tqh_first); \
(var) && ((next_var) = ((var)->field.tqe_next), 1); \
(var) = (next_var))
#define QTAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
(var); \
(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
for ((var) = (*(((struct headname*)((head)->tqh_last))->tqh_last)); \
(var); \
(var) = (*(((struct headname*)((var)->field.tqe_prev))->tqh_last)))
/*
* Tail queue access methods.
*/
#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define QTAILQ_FIRST(head) ((head)->tqh_first)
#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define QTAILQ_IN_USE(elm, field) ((elm)->field.tqe_prev != NULL)
#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define QTAILQ_FIRST(head) ((head)->tqh_first)
#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define QTAILQ_IN_USE(elm, field) ((elm)->field.tqe_prev != NULL)
#define QTAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
(*(((struct headname*)((head)->tqh_last))->tqh_last))
#define QTAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
(*(((struct headname*)((elm)->field.tqe_prev))->tqh_last))
#define field_at_offset(base, offset, type) \
((type) (((char *) (base)) + (offset)))
#define field_at_offset(base, offset, type) \
((type)(((char*)(base)) + (offset)))
typedef struct DUMMY_Q_ENTRY DUMMY_Q_ENTRY;
typedef struct DUMMY_Q DUMMY_Q;
struct DUMMY_Q_ENTRY {
QTAILQ_ENTRY(DUMMY_Q_ENTRY) next;
struct DUMMY_Q_ENTRY
{
QTAILQ_ENTRY(DUMMY_Q_ENTRY)
next;
};
struct DUMMY_Q {
QTAILQ_HEAD(DUMMY_Q_HEAD, DUMMY_Q_ENTRY) head;
struct DUMMY_Q
{
QTAILQ_HEAD(DUMMY_Q_HEAD, DUMMY_Q_ENTRY)
head;
};
#define dummy_q ((DUMMY_Q *) 0)
#define dummy_qe ((DUMMY_Q_ENTRY *) 0)
#define dummy_q ((DUMMY_Q*)0)
#define dummy_qe ((DUMMY_Q_ENTRY*)0)
/*
* Offsets of layout of a tail queue head.
*/
#define QTAILQ_FIRST_OFFSET (offsetof(typeof(dummy_q->head), tqh_first))
#define QTAILQ_LAST_OFFSET (offsetof(typeof(dummy_q->head), tqh_last))
#define QTAILQ_LAST_OFFSET (offsetof(typeof(dummy_q->head), tqh_last))
/*
* Raw access of elements of a tail queue
*/
#define QTAILQ_RAW_FIRST(head) \
(*field_at_offset(head, QTAILQ_FIRST_OFFSET, void **))
#define QTAILQ_RAW_TQH_LAST(head) \
(*field_at_offset(head, QTAILQ_LAST_OFFSET, void ***))
#define QTAILQ_RAW_FIRST(head) \
(*field_at_offset(head, QTAILQ_FIRST_OFFSET, void**))
#define QTAILQ_RAW_TQH_LAST(head) \
(*field_at_offset(head, QTAILQ_LAST_OFFSET, void***))
/*
* Offsets of layout of a tail queue element.
@ -477,25 +559,27 @@ struct DUMMY_Q {
/*
* Raw access of elements of a tail entry
*/
#define QTAILQ_RAW_NEXT(elm, entry) \
(*field_at_offset(elm, entry + QTAILQ_NEXT_OFFSET, void **))
#define QTAILQ_RAW_TQE_PREV(elm, entry) \
(*field_at_offset(elm, entry + QTAILQ_PREV_OFFSET, void ***))
#define QTAILQ_RAW_NEXT(elm, entry) \
(*field_at_offset(elm, entry + QTAILQ_NEXT_OFFSET, void**))
#define QTAILQ_RAW_TQE_PREV(elm, entry) \
(*field_at_offset(elm, entry + QTAILQ_PREV_OFFSET, void***))
/*
* Tail queue tranversal using pointer arithmetic.
*/
#define QTAILQ_RAW_FOREACH(elm, head, entry) \
for ((elm) = QTAILQ_RAW_FIRST(head); \
(elm); \
(elm) = QTAILQ_RAW_NEXT(elm, entry))
#define QTAILQ_RAW_FOREACH(elm, head, entry) \
for ((elm) = QTAILQ_RAW_FIRST(head); \
(elm); \
(elm) = QTAILQ_RAW_NEXT(elm, entry))
/*
* Tail queue insertion using pointer arithmetic.
*/
#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do { \
QTAILQ_RAW_NEXT(elm, entry) = NULL; \
QTAILQ_RAW_TQE_PREV(elm, entry) = QTAILQ_RAW_TQH_LAST(head); \
*QTAILQ_RAW_TQH_LAST(head) = (elm); \
QTAILQ_RAW_TQH_LAST(head) = &QTAILQ_RAW_NEXT(elm, entry); \
} while (/*CONSTCOND*/0)
#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) \
do \
{ \
QTAILQ_RAW_NEXT(elm, entry) = NULL; \
QTAILQ_RAW_TQE_PREV(elm, entry) = QTAILQ_RAW_TQH_LAST(head); \
*QTAILQ_RAW_TQH_LAST(head) = (elm); \
QTAILQ_RAW_TQH_LAST(head) = &QTAILQ_RAW_NEXT(elm, entry); \
} while (/*CONSTCOND*/ 0)
#endif /* QEMU_SYS_QUEUE_H */

View File

@ -26,241 +26,241 @@
#include "queue.h"
#define USB_TOKEN_SETUP 0x2d
#define USB_TOKEN_IN 0x69 /* device -> host */
#define USB_TOKEN_OUT 0xe1 /* host -> device */
#define USB_TOKEN_IN 0x69 /* device -> host */
#define USB_TOKEN_OUT 0xe1 /* host -> device */
/* specific usb messages, also sent in the 'pid' parameter */
#define USB_MSG_ATTACH 0x100
#define USB_MSG_DETACH 0x101
#define USB_MSG_RESET 0x102
#define USB_MSG_ATTACH 0x100
#define USB_MSG_DETACH 0x101
#define USB_MSG_RESET 0x102
#define USB_RET_SUCCESS (0)
#define USB_RET_NODEV (-1)
#define USB_RET_NAK (-2)
#define USB_RET_STALL (-3)
#define USB_RET_BABBLE (-4)
#define USB_RET_IOERROR (-5)
#define USB_RET_ASYNC (-6)
#define USB_RET_ADD_TO_QUEUE (-7)
#define USB_RET_SUCCESS (0)
#define USB_RET_NODEV (-1)
#define USB_RET_NAK (-2)
#define USB_RET_STALL (-3)
#define USB_RET_BABBLE (-4)
#define USB_RET_IOERROR (-5)
#define USB_RET_ASYNC (-6)
#define USB_RET_ADD_TO_QUEUE (-7)
#define USB_RET_REMOVE_FROM_QUEUE (-8)
#define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1
#define USB_SPEED_HIGH 2
#define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1
#define USB_SPEED_HIGH 2
#define USB_SPEED_MASK_LOW (1 << USB_SPEED_LOW)
#define USB_SPEED_MASK_FULL (1 << USB_SPEED_FULL)
#define USB_SPEED_MASK_LOW (1 << USB_SPEED_LOW)
#define USB_SPEED_MASK_FULL (1 << USB_SPEED_FULL)
#define USB_STATE_NOTATTACHED 0
#define USB_STATE_ATTACHED 1
#define USB_STATE_ATTACHED 1
//#define USB_STATE_POWERED 2
#define USB_STATE_DEFAULT 3
#define USB_STATE_DEFAULT 3
//#define USB_STATE_ADDRESS 4
//#define USB_STATE_CONFIGURED 5
#define USB_STATE_SUSPENDED 6
#define USB_STATE_SUSPENDED 6
#define USB_CLASS_RESERVED 0
#define USB_CLASS_AUDIO 1
#define USB_CLASS_COMM 2
#define USB_CLASS_HID 3
#define USB_CLASS_PHYSICAL 5
#define USB_CLASS_STILL_IMAGE 6
#define USB_CLASS_PRINTER 7
#define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9
#define USB_CLASS_CDC_DATA 0x0a
#define USB_CLASS_CSCID 0x0b
#define USB_CLASS_CONTENT_SEC 0x0d
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
#define USB_CLASS_RESERVED 0
#define USB_CLASS_AUDIO 1
#define USB_CLASS_COMM 2
#define USB_CLASS_HID 3
#define USB_CLASS_PHYSICAL 5
#define USB_CLASS_STILL_IMAGE 6
#define USB_CLASS_PRINTER 7
#define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9
#define USB_CLASS_CDC_DATA 0x0a
#define USB_CLASS_CSCID 0x0b
#define USB_CLASS_CONTENT_SEC 0x0d
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
#define USB_DIR_OUT 0
#define USB_DIR_IN 0x80
#define USB_DIR_OUT 0
#define USB_DIR_IN 0x80
#define USB_TYPE_MASK (0x03 << 5)
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
#define USB_TYPE_MASK (0x03 << 5)
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
#define USB_RECIP_MASK 0x1f
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
#define USB_RECIP_MASK 0x1f
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
#define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) //0x8000
#define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) // 0x0000
#define VendorDeviceRequest ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) // 0xC000
#define DeviceRequest ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8) //0x8000
#define DeviceOutRequest ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8) // 0x0000
#define VendorDeviceRequest ((USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE) << 8) // 0xC000
#define VendorDeviceOutRequest \
((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) //0x4000
((USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) << 8) //0x4000
#define InterfaceRequest \
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) // 0x8100
((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8) // 0x8100
#define InterfaceOutRequest \
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) //0x0100
#define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) //0x8200
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8) //0x0100
#define EndpointRequest ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT) << 8) //0x8200
#define EndpointOutRequest \
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) //0x0200
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT) << 8) //0x0200
#define ClassInterfaceRequest \
((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) //0xA100
((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) //0xA100
#define ClassInterfaceOutRequest \
((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) //0x2100
((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) //0x2100
#define ClassEndpointRequest \
((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_ENDPOINT)<<8) //0xA200
((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT) << 8) //0xA200
#define ClassEndpointOutRequest \
((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_ENDPOINT)<<8) //0x2200
((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT) << 8) //0x2200
#define VendorInterfaceRequest \
((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8)
((USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE) << 8)
#define VendorInterfaceOutRequest \
((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8)
((USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE) << 8)
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_DEVICE_SELF_POWERED 0
#define USB_DEVICE_REMOTE_WAKEUP 1
#define USB_DEVICE_SELF_POWERED 0
#define USB_DEVICE_REMOTE_WAKEUP 1
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
#define USB_DT_DEVICE_QUALIFIER 0x06
#define USB_DT_OTHER_SPEED_CONFIG 0x07
#define USB_DT_DEBUG 0x0A
#define USB_DT_INTERFACE_ASSOC 0x0B
#define USB_DT_BOS 0x0F
#define USB_DT_DEVICE_CAPABILITY 0x10
#define USB_DT_HID 0x21
#define USB_DT_REPORT 0x22
#define USB_DT_PHYSICAL 0x23
#define USB_DT_CS_INTERFACE 0x24
#define USB_DT_CS_ENDPOINT 0x25
#define USB_DT_ENDPOINT_COMPANION 0x30
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
#define USB_DT_DEVICE_QUALIFIER 0x06
#define USB_DT_OTHER_SPEED_CONFIG 0x07
#define USB_DT_DEBUG 0x0A
#define USB_DT_INTERFACE_ASSOC 0x0B
#define USB_DT_BOS 0x0F
#define USB_DT_DEVICE_CAPABILITY 0x10
#define USB_DT_HID 0x21
#define USB_DT_REPORT 0x22
#define USB_DT_PHYSICAL 0x23
#define USB_DT_CS_INTERFACE 0x24
#define USB_DT_CS_ENDPOINT 0x25
#define USB_DT_ENDPOINT_COMPANION 0x30
#define USB_DEV_CAP_WIRELESS 0x01
#define USB_DEV_CAP_USB2_EXT 0x02
#define USB_DEV_CAP_SUPERSPEED 0x03
#define USB_DEV_CAP_WIRELESS 0x01
#define USB_DEV_CAP_USB2_EXT 0x02
#define USB_DEV_CAP_SUPERSPEED 0x03
#define USB_CFG_ATT_ONE (1 << 7) /* should always be set */
#define USB_CFG_ATT_SELFPOWER (1 << 6)
#define USB_CFG_ATT_WAKEUP (1 << 5)
#define USB_CFG_ATT_BATTERY (1 << 4)
#define USB_CFG_ATT_ONE (1 << 7) /* should always be set */
#define USB_CFG_ATT_SELFPOWER (1 << 6)
#define USB_CFG_ATT_WAKEUP (1 << 5)
#define USB_CFG_ATT_BATTERY (1 << 4)
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
#define USB_ENDPOINT_XFER_BULK 2
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_XFER_INVALID 255
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
#define USB_ENDPOINT_XFER_BULK 2
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_XFER_INVALID 255
#define USB_INTERFACE_INVALID 255
#define USB_INTERFACE_INVALID 255
/* HID interface requests */
#define GET_REPORT 0xa101
#define GET_IDLE 0xa102
#define GET_REPORT 0xa101
#define GET_IDLE 0xa102
#define GET_PROTOCOL 0xa103
#define SET_REPORT 0x2109
#define SET_IDLE 0x210a
#define SET_REPORT 0x2109
#define SET_IDLE 0x210a
#define SET_PROTOCOL 0x210b
#define USB_DEVICE_DESC_SIZE 18
#define USB_DEVICE_DESC_SIZE 18
#define USB_CONFIGURATION_DESC_SIZE 9
#define USB_INTERFACE_DESC_SIZE 9
#define USB_ENDPOINT_DESC_SIZE 7
#define USB_INTERFACE_DESC_SIZE 9
#define USB_ENDPOINT_DESC_SIZE 7
#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
#define B3VAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF),(((x) >> 16) & 0xFF)
#define WBVAL(x) ((x)&0xFF), (((x) >> 8) & 0xFF)
#define B3VAL(x) ((x)&0xFF), (((x) >> 8) & 0xFF), (((x) >> 16) & 0xFF)
/* bmRequestType.Dir */
#define REQUEST_HOST_TO_DEVICE 0
#define REQUEST_DEVICE_TO_HOST 1
#define REQUEST_HOST_TO_DEVICE 0
#define REQUEST_DEVICE_TO_HOST 1
/* bmRequestType.Type */
#define REQUEST_STANDARD 0
#define REQUEST_CLASS 1
#define REQUEST_VENDOR 2
#define REQUEST_RESERVED 3
#define REQUEST_STANDARD 0
#define REQUEST_CLASS 1
#define REQUEST_VENDOR 2
#define REQUEST_RESERVED 3
/* bmRequestType.Recipient */
#define REQUEST_TO_DEVICE 0
#define REQUEST_TO_INTERFACE 1
#define REQUEST_TO_ENDPOINT 2
#define REQUEST_TO_OTHER 3
#define REQUEST_TO_DEVICE 0
#define REQUEST_TO_INTERFACE 1
#define REQUEST_TO_ENDPOINT 2
#define REQUEST_TO_OTHER 3
/* USB Standard Request Codes */
#define USB_REQUEST_GET_STATUS 0
#define USB_REQUEST_CLEAR_FEATURE 1
#define USB_REQUEST_SET_FEATURE 3
#define USB_REQUEST_SET_ADDRESS 5
#define USB_REQUEST_GET_DESCRIPTOR 6
#define USB_REQUEST_SET_DESCRIPTOR 7
#define USB_REQUEST_GET_CONFIGURATION 8
#define USB_REQUEST_SET_CONFIGURATION 9
#define USB_REQUEST_GET_INTERFACE 10
#define USB_REQUEST_SET_INTERFACE 11
#define USB_REQUEST_SYNC_FRAME 12
#define USB_REQUEST_GET_STATUS 0
#define USB_REQUEST_CLEAR_FEATURE 1
#define USB_REQUEST_SET_FEATURE 3
#define USB_REQUEST_SET_ADDRESS 5
#define USB_REQUEST_GET_DESCRIPTOR 6
#define USB_REQUEST_SET_DESCRIPTOR 7
#define USB_REQUEST_GET_CONFIGURATION 8
#define USB_REQUEST_SET_CONFIGURATION 9
#define USB_REQUEST_GET_INTERFACE 10
#define USB_REQUEST_SET_INTERFACE 11
#define USB_REQUEST_SYNC_FRAME 12
/* USB GET_STATUS Bit Values */
#define USB_GETSTATUS_SELF_POWERED 0x01
#define USB_GETSTATUS_REMOTE_WAKEUP 0x02
#define USB_GETSTATUS_ENDPOINT_STALL 0x01
#define USB_GETSTATUS_SELF_POWERED 0x01
#define USB_GETSTATUS_REMOTE_WAKEUP 0x02
#define USB_GETSTATUS_ENDPOINT_STALL 0x01
/* USB Standard Feature selectors */
#define USB_FEATURE_ENDPOINT_STALL 0
#define USB_FEATURE_REMOTE_WAKEUP 1
#define USB_FEATURE_ENDPOINT_STALL 0
#define USB_FEATURE_REMOTE_WAKEUP 1
/* USB Descriptor Types */
#define USB_DEVICE_DESCRIPTOR_TYPE 1
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
#define USB_STRING_DESCRIPTOR_TYPE 3
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 6
#define USB_DEVICE_DESCRIPTOR_TYPE 1
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
#define USB_STRING_DESCRIPTOR_TYPE 3
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 6
#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE 7
#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8
#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8
/* bmAttributes in Configuration Descriptor */
#define USB_CONFIG_POWERED_MASK 0xC0
#define USB_CONFIG_BUS_POWERED 0x80
#define USB_CONFIG_SELF_POWERED 0x40
#define USB_CONFIG_REMOTE_WAKEUP 0x20
#define USB_CONFIG_POWERED_MASK 0xC0
#define USB_CONFIG_BUS_POWERED 0x80
#define USB_CONFIG_SELF_POWERED 0x40
#define USB_CONFIG_REMOTE_WAKEUP 0x20
/* bMaxPower in Configuration Descriptor */
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
#define USB_CONFIG_POWER_MA(mA) ((mA) / 2)
/* bEndpointAddress in Endpoint Descriptor */
#define USB_ENDPOINT_DIRECTION_MASK 0x80
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
#define USB_ENDPOINT_DIRECTION_MASK 0x80
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
/* bmAttributes in Endpoint Descriptor */
#define USB_ENDPOINT_TYPE_MASK 0x03
#define USB_ENDPOINT_TYPE_CONTROL 0x00
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
#define USB_ENDPOINT_TYPE_BULK 0x02
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
#define USB_ENDPOINT_SYNC_MASK 0x0C
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00
#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04
#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08
#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C
#define USB_ENDPOINT_USAGE_MASK 0x30
#define USB_ENDPOINT_USAGE_DATA 0x00
#define USB_ENDPOINT_USAGE_FEEDBACK 0x10
#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20
#define USB_ENDPOINT_USAGE_RESERVED 0x30
#define USB_ENDPOINT_TYPE_MASK 0x03
#define USB_ENDPOINT_TYPE_CONTROL 0x00
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
#define USB_ENDPOINT_TYPE_BULK 0x02
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
#define USB_ENDPOINT_SYNC_MASK 0x0C
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00
#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04
#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08
#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C
#define USB_ENDPOINT_USAGE_MASK 0x30
#define USB_ENDPOINT_USAGE_DATA 0x00
#define USB_ENDPOINT_USAGE_FEEDBACK 0x10
#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20
#define USB_ENDPOINT_USAGE_RESERVED 0x30
typedef struct USBBus USBBus;
typedef struct USBBusOps USBBusOps;
@ -281,323 +281,344 @@ typedef struct USBDescOther USBDescOther;
typedef struct USBDescString USBDescString;
typedef struct USBDescMSOS USBDescMSOS;
struct USBDescString {
uint8_t index;
char *str;
QLIST_ENTRY(USBDescString) next;
struct USBDescString
{
uint8_t index;
char* str;
QLIST_ENTRY(USBDescString)
next;
};
#define USB_MAX_ENDPOINTS 15
#define USB_MAX_ENDPOINTS 15
#define USB_MAX_INTERFACES 16
struct USBEndpoint {
uint8_t nr;
uint8_t pid;
uint8_t type;
uint8_t ifnum;
int max_packet_size;
int max_streams;
bool pipeline;
bool halted;
USBDevice *dev;
QTAILQ_HEAD(, USBPacket) queue;
struct USBEndpoint
{
uint8_t nr;
uint8_t pid;
uint8_t type;
uint8_t ifnum;
int max_packet_size;
int max_streams;
bool pipeline;
bool halted;
USBDevice* dev;
QTAILQ_HEAD(, USBPacket)
queue;
};
enum USBDeviceFlags {
USB_DEV_FLAG_FULL_PATH,
USB_DEV_FLAG_IS_HOST,
USB_DEV_FLAG_MSOS_DESC_ENABLE,
USB_DEV_FLAG_MSOS_DESC_IN_USE,
enum USBDeviceFlags
{
USB_DEV_FLAG_FULL_PATH,
USB_DEV_FLAG_IS_HOST,
USB_DEV_FLAG_MSOS_DESC_ENABLE,
USB_DEV_FLAG_MSOS_DESC_IN_USE,
};
typedef void (*USBDeviceRealize)(USBDevice *dev/*, Error **errp*/);
typedef void (*USBDeviceUnrealize)(USBDevice *dev/*, Error **errp*/);
typedef void (*USBDeviceRealize)(USBDevice* dev /*, Error **errp*/);
typedef void (*USBDeviceUnrealize)(USBDevice* dev /*, Error **errp*/);
typedef struct USBDeviceClass {
//DeviceClass parent_class;
typedef struct USBDeviceClass
{
//DeviceClass parent_class;
USBDeviceRealize realize;
USBDeviceUnrealize unrealize;
USBDeviceRealize realize;
USBDeviceUnrealize unrealize;
/*
/*
* Walk (enabled) downstream ports, check for a matching device.
* Only hubs implement this.
*/
USBDevice *(*find_device)(USBDevice *dev, uint8_t addr);
USBDevice* (*find_device)(USBDevice* dev, uint8_t addr);
/*
/*
* Called when a packet is canceled.
*/
void (*cancel_packet)(USBDevice *dev, USBPacket *p);
void (*cancel_packet)(USBDevice* dev, USBPacket* p);
/*
/*
* Attach the device
*/
void (*handle_attach)(USBDevice *dev);
void (*handle_attach)(USBDevice* dev);
/*
/*
* Reset the device
*/
void (*handle_reset)(USBDevice *dev);
void (*handle_reset)(USBDevice* dev);
/*
/*
* Process control request.
* Called from handle_packet().
*
* Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
* then the number of bytes transferred is stored in p->actual_length
*/
void (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value,
int index, int length, uint8_t *data);
void (*handle_control)(USBDevice* dev, USBPacket* p, int request, int value,
int index, int length, uint8_t* data);
/*
/*
* Process data transfers (both BULK and ISOC).
* Called from handle_packet().
*
* Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
* then the number of bytes transferred is stored in p->actual_length
*/
void (*handle_data)(USBDevice *dev, USBPacket *p);
void (*handle_data)(USBDevice* dev, USBPacket* p);
void (*set_interface)(USBDevice *dev, int intf,
int alt_old, int alt_new);
void (*set_interface)(USBDevice* dev, int intf,
int alt_old, int alt_new);
/*
/*
* Called when the hcd is done queuing packets for an endpoint, only
* necessary for devices which can return USB_RET_ADD_TO_QUEUE.
*/
void (*flush_ep_queue)(USBDevice *dev, USBEndpoint *ep);
void (*flush_ep_queue)(USBDevice* dev, USBEndpoint* ep);
/*
/*
* Called by the hcd to let the device know the queue for an endpoint
* has been unlinked / stopped. Optional may be NULL.
*/
void (*ep_stopped)(USBDevice *dev, USBEndpoint *ep);
void (*ep_stopped)(USBDevice* dev, USBEndpoint* ep);
/*
/*
* Called by the hcd to alloc / free streams on a bulk endpoint.
* Optional may be NULL.
*/
int (*alloc_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps,
int streams);
void (*free_streams)(USBDevice *dev, USBEndpoint **eps, int nr_eps);
int (*open)(USBDevice *dev);
void (*close)(USBDevice *dev);
int (*alloc_streams)(USBDevice* dev, USBEndpoint** eps, int nr_eps,
int streams);
void (*free_streams)(USBDevice* dev, USBEndpoint** eps, int nr_eps);
const char *product_desc;
const USBDesc *usb_desc;
bool attached_settable;
int (*open)(USBDevice* dev);
void (*close)(USBDevice* dev);
const char* product_desc;
const USBDesc* usb_desc;
bool attached_settable;
} USBDeviceClass;
/* definition of a USB device */
struct USBDevice {
USBDeviceClass klass;
USBPort *port;
USBBus *bus;
void *opaque;
uint32_t flags;
struct USBDevice
{
USBDeviceClass klass;
USBPort* port;
USBBus* bus;
void* opaque;
uint32_t flags;
/* Actual connected speed */
int speed;
/* Supported speeds, not in info because it may be variable (hostdevs) */
int speedmask;
uint8_t addr;
char product_desc[32];
int auto_attach;
bool attached;
/* Actual connected speed */
int speed;
/* Supported speeds, not in info because it may be variable (hostdevs) */
int speedmask;
uint8_t addr;
char product_desc[32];
int auto_attach;
bool attached;
int32_t state;
uint8_t setup_buf[8];
uint8_t data_buf[4096];
int32_t remote_wakeup;
int32_t setup_state;
int32_t setup_len;
int32_t setup_index;
int32_t state;
uint8_t setup_buf[8];
uint8_t data_buf[4096];
int32_t remote_wakeup;
int32_t setup_state;
int32_t setup_len;
int32_t setup_index;
USBEndpoint ep_ctl;
USBEndpoint ep_in[USB_MAX_ENDPOINTS];
USBEndpoint ep_out[USB_MAX_ENDPOINTS];
USBEndpoint ep_ctl;
USBEndpoint ep_in[USB_MAX_ENDPOINTS];
USBEndpoint ep_out[USB_MAX_ENDPOINTS];
const USBDesc *usb_desc; /* Overrides class usb_desc if not NULL */
const USBDescDevice *device;
const USBDesc* usb_desc; /* Overrides class usb_desc if not NULL */
const USBDescDevice* device;
int configuration;
int ninterfaces;
int altsetting[USB_MAX_INTERFACES];
const USBDescConfig *config;
const USBDescIface *ifaces[USB_MAX_INTERFACES];
int configuration;
int ninterfaces;
int altsetting[USB_MAX_INTERFACES];
const USBDescConfig* config;
const USBDescIface* ifaces[USB_MAX_INTERFACES];
};
typedef struct USBPortOps {
void (*attach)(USBPort *port);
void (*detach)(USBPort *port);
/*
typedef struct USBPortOps
{
void (*attach)(USBPort* port);
void (*detach)(USBPort* port);
/*
* This gets called when a device downstream from the device attached to
* the port (iow attached through a hub) gets detached.
*/
//void (*child_detach)(USBPort *port, USBDevice *child);
void (*wakeup)(USBPort *port);
/*
//void (*child_detach)(USBPort *port, USBDevice *child);
void (*wakeup)(USBPort* port);
/*
* Note that port->dev will be different then the device from which
* the packet originated when a hub is involved.
*/
void (*complete)(USBPort *port, USBPacket *p);
void (*complete)(USBPort* port, USBPacket* p);
} USBPortOps;
/* USB port on which a device can be connected */
struct USBPort {
USBDevice *dev;
int speedmask;
USBPortOps *ops;
void *opaque;
int index; /* internal port index, may be used with the opaque */
//QTAILQ_ENTRY(USBPort) next; /* Used internally by qemu. */
struct USBPort
{
USBDevice* dev;
int speedmask;
USBPortOps* ops;
void* opaque;
int index; /* internal port index, may be used with the opaque */
//QTAILQ_ENTRY(USBPort) next; /* Used internally by qemu. */
};
typedef void USBCallback(USBPacket * packet, void *opaque);
typedef void USBCallback(USBPacket* packet, void* opaque);
typedef enum USBPacketState {
USB_PACKET_UNDEFINED = 0,
USB_PACKET_SETUP,
USB_PACKET_QUEUED,
USB_PACKET_ASYNC,
USB_PACKET_COMPLETE,
USB_PACKET_CANCELED,
typedef enum USBPacketState
{
USB_PACKET_UNDEFINED = 0,
USB_PACKET_SETUP,
USB_PACKET_QUEUED,
USB_PACKET_ASYNC,
USB_PACKET_COMPLETE,
USB_PACKET_CANCELED,
} USBPacketState;
/* Structure used to hold information about an active USB packet. */
struct USBPacket {
/* Data fields for use by the driver. */
int pid;
uint64_t id;
USBEndpoint *ep;
unsigned int stream;
QEMUIOVector iov;
uint64_t parameter; /* control transfers */
bool short_not_ok;
bool int_req;
int status; /* USB_RET_* status code */
int actual_length; /* Number of bytes actually transferred */
/* Internal use by the USB layer. */
USBPacketState state;
USBCombinedPacket *combined;
QTAILQ_ENTRY(USBPacket) queue;
QTAILQ_ENTRY(USBPacket) combined_entry;
struct USBPacket
{
/* Data fields for use by the driver. */
int pid;
uint64_t id;
USBEndpoint* ep;
unsigned int stream;
QEMUIOVector iov;
uint64_t parameter; /* control transfers */
bool short_not_ok;
bool int_req;
int status; /* USB_RET_* status code */
int actual_length; /* Number of bytes actually transferred */
/* Internal use by the USB layer. */
USBPacketState state;
USBCombinedPacket* combined;
QTAILQ_ENTRY(USBPacket)
queue;
QTAILQ_ENTRY(USBPacket)
combined_entry;
};
struct USBCombinedPacket {
USBPacket *first;
QTAILQ_HEAD(packets_head, USBPacket) packets;
QEMUIOVector iov;
struct USBCombinedPacket
{
USBPacket* first;
QTAILQ_HEAD(packets_head, USBPacket)
packets;
QEMUIOVector iov;
};
void usb_packet_init(USBPacket *p);
void usb_packet_set_state(USBPacket *p, USBPacketState state);
void usb_packet_check_state(USBPacket *p, USBPacketState expected);
void usb_packet_setup(USBPacket *p, int pid,
USBEndpoint *ep, unsigned int stream,
uint64_t id, bool short_not_ok, bool int_req);
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len);
void usb_packet_init(USBPacket* p);
void usb_packet_set_state(USBPacket* p, USBPacketState state);
void usb_packet_check_state(USBPacket* p, USBPacketState expected);
void usb_packet_setup(USBPacket* p, int pid,
USBEndpoint* ep, unsigned int stream,
uint64_t id, bool short_not_ok, bool int_req);
void usb_packet_addbuf(USBPacket* p, void* ptr, size_t len);
//int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
//void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl);
void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes);
void usb_packet_skip(USBPacket *p, size_t bytes);
size_t usb_packet_size(USBPacket *p);
void usb_packet_cleanup(USBPacket *p);
void usb_packet_copy(USBPacket* p, void* ptr, size_t bytes);
void usb_packet_skip(USBPacket* p, size_t bytes);
size_t usb_packet_size(USBPacket* p);
void usb_packet_cleanup(USBPacket* p);
static inline bool usb_packet_is_inflight(USBPacket *p)
static inline bool usb_packet_is_inflight(USBPacket* p)
{
return (p->state == USB_PACKET_QUEUED ||
p->state == USB_PACKET_ASYNC);
return (p->state == USB_PACKET_QUEUED ||
p->state == USB_PACKET_ASYNC);
}
struct USBBus {
//BusState qbus;
USBBusOps *ops;
int busnr;
int nfree;
int nused;
QTAILQ_HEAD(, USBPort) free;
QTAILQ_HEAD(, USBPort) used;
QTAILQ_ENTRY(USBBus) next;
struct USBBus
{
//BusState qbus;
USBBusOps* ops;
int busnr;
int nfree;
int nused;
QTAILQ_HEAD(, USBPort)
free;
QTAILQ_HEAD(, USBPort)
used;
QTAILQ_ENTRY(USBBus)
next;
};
struct USBBusOps {
void (*register_companion)(USBBus *bus, USBPort *ports[],
uint32_t portcount, uint32_t firstport/*,
Error **errp*/);
void (*wakeup_endpoint)(USBBus *bus, USBEndpoint *ep, unsigned int stream);
struct USBBusOps
{
void (*register_companion)(USBBus* bus, USBPort* ports[],
uint32_t portcount, uint32_t firstport /*,
Error **errp*/
);
void (*wakeup_endpoint)(USBBus* bus, USBEndpoint* ep, unsigned int stream);
};
USBDevice *usb_find_device(USBPort *port, uint8_t addr);
USBDevice* usb_find_device(USBPort* port, uint8_t addr);
void usb_handle_packet(USBDevice *dev, USBPacket *p);
void usb_packet_complete(USBDevice *dev, USBPacket *p);
void usb_packet_complete_one(USBDevice *dev, USBPacket *p);
void usb_cancel_packet(USBPacket * p);
void usb_handle_packet(USBDevice* dev, USBPacket* p);
void usb_packet_complete(USBDevice* dev, USBPacket* p);
void usb_packet_complete_one(USBDevice* dev, USBPacket* p);
void usb_cancel_packet(USBPacket* p);
void usb_ep_init(USBDevice *dev);
void usb_ep_reset(USBDevice *dev);
void usb_ep_dump(USBDevice *dev);
struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep);
uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep);
void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type);
void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum);
void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
uint16_t raw);
void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw);
void usb_ep_set_halted(USBDevice *dev, int pid, int ep, bool halted);
USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
uint64_t id);
void usb_ep_init(USBDevice* dev);
void usb_ep_reset(USBDevice* dev);
void usb_ep_dump(USBDevice* dev);
struct USBEndpoint* usb_ep_get(USBDevice* dev, int pid, int ep);
uint8_t usb_ep_get_type(USBDevice* dev, int pid, int ep);
void usb_ep_set_type(USBDevice* dev, int pid, int ep, uint8_t type);
void usb_ep_set_ifnum(USBDevice* dev, int pid, int ep, uint8_t ifnum);
void usb_ep_set_max_packet_size(USBDevice* dev, int pid, int ep,
uint16_t raw);
void usb_ep_set_max_streams(USBDevice* dev, int pid, int ep, uint8_t raw);
void usb_ep_set_halted(USBDevice* dev, int pid, int ep, bool halted);
USBPacket* usb_ep_find_packet_by_id(USBDevice* dev, int pid, int ep,
uint64_t id);
void usb_ep_combine_input_packets(USBEndpoint *ep);
void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p);
void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p);
void usb_ep_combine_input_packets(USBEndpoint* ep);
void usb_combined_input_packet_complete(USBDevice* dev, USBPacket* p);
void usb_combined_packet_cancel(USBDevice* dev, USBPacket* p);
void usb_pick_speed(USBPort *port);
void usb_attach(USBPort *port);
void usb_detach(USBPort *port);
void usb_port_reset(USBPort *port);
void usb_device_reset(USBDevice *dev);
void usb_wakeup(USBEndpoint *ep, unsigned int stream);
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
void usb_pick_speed(USBPort* port);
void usb_attach(USBPort* port);
void usb_detach(USBPort* port);
void usb_port_reset(USBPort* port);
void usb_device_reset(USBDevice* dev);
void usb_wakeup(USBEndpoint* ep, unsigned int stream);
void usb_generic_async_ctrl_complete(USBDevice* s, USBPacket* p);
int usb_generic_handle_packet(USBDevice *s, int pid,
uint8_t devaddr, uint8_t devep,
uint8_t *data, int len);
void usb_reattach(USBPort *port);
void usb_send_msg(USBDevice *dev, int msg);
int usb_generic_handle_packet(USBDevice* s, int pid,
uint8_t devaddr, uint8_t devep,
uint8_t* data, int len);
void usb_reattach(USBPort* port);
void usb_send_msg(USBDevice* dev, int msg);
/* usb hub */
USBDevice *usb_hub_init(int nb_ports);
USBDevice* usb_hub_init(int nb_ports);
USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr);
USBDevice* usb_device_find_device(USBDevice* dev, uint8_t addr);
void usb_device_cancel_packet(USBDevice *dev, USBPacket *p);
void usb_device_cancel_packet(USBDevice* dev, USBPacket* p);
void usb_device_handle_attach(USBDevice *dev);
void usb_device_handle_attach(USBDevice* dev);
void usb_device_handle_reset(USBDevice *dev);
void usb_device_handle_reset(USBDevice* dev);
void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
int val, int index, int length, uint8_t *data);
void usb_device_handle_control(USBDevice* dev, USBPacket* p, int request,
int val, int index, int length, uint8_t* data);
void usb_device_handle_data(USBDevice *dev, USBPacket *p);
void usb_device_handle_data(USBDevice* dev, USBPacket* p);
void usb_device_set_interface(USBDevice *dev, int intf,
int alt_old, int alt_new);
void usb_device_set_interface(USBDevice* dev, int intf,
int alt_old, int alt_new);
void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep);
void usb_device_flush_ep_queue(USBDevice* dev, USBEndpoint* ep);
void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep);
void usb_device_ep_stopped(USBDevice* dev, USBEndpoint* ep);
int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps,
int streams);
void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps);
int usb_device_alloc_streams(USBDevice* dev, USBEndpoint** eps, int nr_eps,
int streams);
void usb_device_free_streams(USBDevice* dev, USBEndpoint** eps, int nr_eps);
const char *usb_device_get_product_desc(USBDevice *dev);
const char* usb_device_get_product_desc(USBDevice* dev);
const USBDesc *usb_device_get_usb_desc(USBDevice *dev);
const USBDesc* usb_device_get_usb_desc(USBDevice* dev);

View File

@ -27,58 +27,60 @@
#define MAX_PORTS 8
typedef struct USBHubPort {
USBPort port;
uint16_t wPortStatus;
uint16_t wPortChange;
typedef struct USBHubPort
{
USBPort port;
uint16_t wPortStatus;
uint16_t wPortChange;
} USBHubPort;
typedef struct USBHubState {
USBDevice dev;
int nb_ports;
USBHubPort ports[MAX_PORTS];
typedef struct USBHubState
{
USBDevice dev;
int nb_ports;
USBHubPort ports[MAX_PORTS];
} USBHubState;
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
#define PORT_STAT_CONNECTION 0x0001
#define PORT_STAT_ENABLE 0x0002
#define PORT_STAT_SUSPEND 0x0004
#define PORT_STAT_OVERCURRENT 0x0008
#define PORT_STAT_RESET 0x0010
#define PORT_STAT_POWER 0x0100
#define PORT_STAT_LOW_SPEED 0x0200
#define PORT_STAT_HIGH_SPEED 0x0400
#define PORT_STAT_TEST 0x0800
#define PORT_STAT_INDICATOR 0x1000
#define PORT_STAT_CONNECTION 0x0001
#define PORT_STAT_ENABLE 0x0002
#define PORT_STAT_SUSPEND 0x0004
#define PORT_STAT_OVERCURRENT 0x0008
#define PORT_STAT_RESET 0x0010
#define PORT_STAT_POWER 0x0100
#define PORT_STAT_LOW_SPEED 0x0200
#define PORT_STAT_HIGH_SPEED 0x0400
#define PORT_STAT_TEST 0x0800
#define PORT_STAT_INDICATOR 0x1000
#define PORT_STAT_C_CONNECTION 0x0001
#define PORT_STAT_C_ENABLE 0x0002
#define PORT_STAT_C_SUSPEND 0x0004
#define PORT_STAT_C_OVERCURRENT 0x0008
#define PORT_STAT_C_RESET 0x0010
#define PORT_STAT_C_CONNECTION 0x0001
#define PORT_STAT_C_ENABLE 0x0002
#define PORT_STAT_C_SUSPEND 0x0004
#define PORT_STAT_C_OVERCURRENT 0x0008
#define PORT_STAT_C_RESET 0x0010
#define PORT_CONNECTION 0
#define PORT_ENABLE 1
#define PORT_SUSPEND 2
#define PORT_OVERCURRENT 3
#define PORT_RESET 4
#define PORT_POWER 8
#define PORT_LOWSPEED 9
#define PORT_HIGHSPEED 10
#define PORT_C_CONNECTION 16
#define PORT_C_ENABLE 17
#define PORT_C_SUSPEND 18
#define PORT_C_OVERCURRENT 19
#define PORT_C_RESET 20
#define PORT_TEST 21
#define PORT_INDICATOR 22
#define PORT_CONNECTION 0
#define PORT_ENABLE 1
#define PORT_SUSPEND 2
#define PORT_OVERCURRENT 3
#define PORT_RESET 4
#define PORT_POWER 8
#define PORT_LOWSPEED 9
#define PORT_HIGHSPEED 10
#define PORT_C_CONNECTION 16
#define PORT_C_ENABLE 17
#define PORT_C_SUSPEND 18
#define PORT_C_OVERCURRENT 19
#define PORT_C_RESET 20
#define PORT_TEST 21
#define PORT_INDICATOR 22
/* same as Linux kernel root hubs */
@ -87,19 +89,19 @@ static const uint8_t qemu_hub_dev_descriptor[] = {
0x01, /* u8 bDescriptorType; Device */
0x10, 0x01, /* u16 bcdUSB; v1.1 */
0x09, /* u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* u8 bDeviceSubClass; */
0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
0x08, /* u8 bMaxPacketSize0; 8 Bytes */
0x09, /* u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* u8 bDeviceSubClass; */
0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
0x08, /* u8 bMaxPacketSize0; 8 Bytes */
0x00, 0x00, /* u16 idVendor; */
0x00, 0x00, /* u16 idProduct; */
0x00, 0x00, /* u16 idProduct; */
0x01, 0x01, /* u16 bcdDevice */
0x03, /* u8 iManufacturer; */
0x02, /* u8 iProduct; */
0x01, /* u8 iSerialNumber; */
0x01 /* u8 bNumConfigurations; */
0x03, /* u8 iManufacturer; */
0x02, /* u8 iProduct; */
0x01, /* u8 iSerialNumber; */
0x01 /* u8 bNumConfigurations; */
};
/* XXX: patch interrupt size */
@ -118,7 +120,7 @@ static const uint8_t qemu_hub_config_descriptor[] = {
5: Remote wakeup,
4..0: resvd */
0x00, /* u8 MaxPower; */
/* USB 1.1:
* USB 2.0, single TT organization (mandatory):
* one interface, protocol 0
@ -131,435 +133,475 @@ static const uint8_t qemu_hub_config_descriptor[] = {
*/
/* one interface */
0x09, /* u8 if_bLength; */
0x04, /* u8 if_bDescriptorType; Interface */
0x00, /* u8 if_bInterfaceNumber; */
0x00, /* u8 if_bAlternateSetting; */
0x01, /* u8 if_bNumEndpoints; */
0x09, /* u8 if_bInterfaceClass; HUB_CLASSCODE */
0x00, /* u8 if_bInterfaceSubClass; */
0x00, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
0x00, /* u8 if_iInterface; */
0x09, /* u8 if_bLength; */
0x04, /* u8 if_bDescriptorType; Interface */
0x00, /* u8 if_bInterfaceNumber; */
0x00, /* u8 if_bAlternateSetting; */
0x01, /* u8 if_bNumEndpoints; */
0x09, /* u8 if_bInterfaceClass; HUB_CLASSCODE */
0x00, /* u8 if_bInterfaceSubClass; */
0x00, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
0x00, /* u8 if_iInterface; */
/* one endpoint (status change endpoint) */
0x07, /* u8 ep_bLength; */
0x05, /* u8 ep_bDescriptorType; Endpoint */
0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* u8 ep_bmAttributes; Interrupt */
0x02, 0x00, /* u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
0x03, /* u8 ep_bmAttributes; Interrupt */
0x02, 0x00, /* u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
0xff /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
};
static const uint8_t qemu_hub_hub_descriptor[] =
{
0x00, /* u8 bLength; patched in later */
0x29, /* u8 bDescriptorType; Hub-descriptor */
0x00, /* u8 bNbrPorts; (patched later) */
0x0a, /* u16 wHubCharacteristics; */
0x00, /* (per-port OC, no power switching) */
0x01, /* u8 bPwrOn2pwrGood; 2ms */
0x00 /* u8 bHubContrCurrent; 0 mA */
{
0x00, /* u8 bLength; patched in later */
0x29, /* u8 bDescriptorType; Hub-descriptor */
0x00, /* u8 bNbrPorts; (patched later) */
0x0a, /* u16 wHubCharacteristics; */
0x00, /* (per-port OC, no power switching) */
0x01, /* u8 bPwrOn2pwrGood; 2ms */
0x00 /* u8 bHubContrCurrent; 0 mA */
/* DeviceRemovable and PortPwrCtrlMask patched in later */
/* DeviceRemovable and PortPwrCtrlMask patched in later */
};
static void usb_hub_attach(USBPort *port1, USBDevice *dev)
static void usb_hub_attach(USBPort* port1, USBDevice* dev)
{
USBHubState *s =(USBHubState *) port1->opaque;
USBHubPort *port = (USBHubPort *)&s->ports[port1->index];
if (dev) {
if (port->port.dev)
usb_attach(port1, NULL);
port->wPortStatus |= PORT_STAT_CONNECTION;
port->wPortChange |= PORT_STAT_C_CONNECTION;
if (dev->speed == USB_SPEED_LOW)
port->wPortStatus |= PORT_STAT_LOW_SPEED;
else
port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
port->port.dev = dev;
/* send the attach message */
dev->handle_packet(dev,
USB_MSG_ATTACH, 0, 0, NULL, 0);
} else {
dev = port->port.dev;
if (dev) {
port->wPortStatus &= ~PORT_STAT_CONNECTION;
port->wPortChange |= PORT_STAT_C_CONNECTION;
if (port->wPortStatus & PORT_STAT_ENABLE) {
port->wPortStatus &= ~PORT_STAT_ENABLE;
port->wPortChange |= PORT_STAT_C_ENABLE;
}
/* send the detach message */
dev->handle_packet(dev,
USB_MSG_DETACH, 0, 0, NULL, 0);
port->port.dev = NULL;
}
}
USBHubState* s = (USBHubState*)port1->opaque;
USBHubPort* port = (USBHubPort*)&s->ports[port1->index];
if (dev)
{
if (port->port.dev)
usb_attach(port1, NULL);
port->wPortStatus |= PORT_STAT_CONNECTION;
port->wPortChange |= PORT_STAT_C_CONNECTION;
if (dev->speed == USB_SPEED_LOW)
port->wPortStatus |= PORT_STAT_LOW_SPEED;
else
port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
port->port.dev = dev;
/* send the attach message */
dev->handle_packet(dev,
USB_MSG_ATTACH, 0, 0, NULL, 0);
}
else
{
dev = port->port.dev;
if (dev)
{
port->wPortStatus &= ~PORT_STAT_CONNECTION;
port->wPortChange |= PORT_STAT_C_CONNECTION;
if (port->wPortStatus & PORT_STAT_ENABLE)
{
port->wPortStatus &= ~PORT_STAT_ENABLE;
port->wPortChange |= PORT_STAT_C_ENABLE;
}
/* send the detach message */
dev->handle_packet(dev,
USB_MSG_DETACH, 0, 0, NULL, 0);
port->port.dev = NULL;
}
}
}
static void usb_hub_handle_reset(USBDevice *dev)
static void usb_hub_handle_reset(USBDevice* dev)
{
/* XXX: do it */
/* XXX: do it */
}
static int usb_hub_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
static int usb_hub_handle_control(USBDevice* dev, int request, int value,
int index, int length, uint8_t* data)
{
USBHubState *s = (USBHubState *)dev;
int ret;
USBHubState* s = (USBHubState*)dev;
int ret;
switch(request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
(dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
data[1] = 0x00;
ret = 2;
break;
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
if (value == USB_DEVICE_REMOTE_WAKEUP) {
dev->remote_wakeup = 0;
} else {
goto fail;
}
ret = 0;
break;
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
if (value == 0 && index != 0x81) { /* clear ep halt */
goto fail;
}
ret = 0;
break;
case DeviceOutRequest | USB_REQ_SET_FEATURE:
if (value == USB_DEVICE_REMOTE_WAKEUP) {
dev->remote_wakeup = 1;
} else {
goto fail;
}
ret = 0;
break;
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
dev->addr = value;
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
switch(value >> 8) {
case USB_DT_DEVICE:
memcpy(data, qemu_hub_dev_descriptor,
sizeof(qemu_hub_dev_descriptor));
ret = sizeof(qemu_hub_dev_descriptor);
break;
case USB_DT_CONFIG:
memcpy(data, qemu_hub_config_descriptor,
sizeof(qemu_hub_config_descriptor));
switch (request)
{
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
(dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
data[1] = 0x00;
ret = 2;
break;
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
if (value == USB_DEVICE_REMOTE_WAKEUP)
{
dev->remote_wakeup = 0;
}
else
{
goto fail;
}
ret = 0;
break;
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
if (value == 0 && index != 0x81)
{ /* clear ep halt */
goto fail;
}
ret = 0;
break;
case DeviceOutRequest | USB_REQ_SET_FEATURE:
if (value == USB_DEVICE_REMOTE_WAKEUP)
{
dev->remote_wakeup = 1;
}
else
{
goto fail;
}
ret = 0;
break;
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
dev->addr = value;
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
switch (value >> 8)
{
case USB_DT_DEVICE:
memcpy(data, qemu_hub_dev_descriptor,
sizeof(qemu_hub_dev_descriptor));
ret = sizeof(qemu_hub_dev_descriptor);
break;
case USB_DT_CONFIG:
memcpy(data, qemu_hub_config_descriptor,
sizeof(qemu_hub_config_descriptor));
/* status change endpoint size based on number
/* status change endpoint size based on number
* of ports */
data[22] = (s->nb_ports + 1 + 7) / 8;
data[22] = (s->nb_ports + 1 + 7) / 8;
ret = sizeof(qemu_hub_config_descriptor);
break;
case USB_DT_STRING:
switch(value & 0xff) {
case 0:
/* language ids */
data[0] = 4;
data[1] = 3;
data[2] = 0x09;
data[3] = 0x04;
ret = 4;
break;
case 1:
/* serial number */
ret = set_usb_string(data, "314159");
break;
case 2:
/* product description */
ret = set_usb_string(data, "QEMU USB Hub");
break;
case 3:
/* vendor description */
ret = set_usb_string(data, "PCSX2/QEMU");
break;
default:
goto fail;
}
break;
default:
goto fail;
}
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
ret = 0;
break;
/* usb specific requests */
case GetHubStatus:
data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 0;
ret = 4;
break;
case GetPortStatus:
{
unsigned int n = index - 1;
USBHubPort *port;
if (n >= s->nb_ports)
goto fail;
port = &s->ports[n];
data[0] = port->wPortStatus;
data[1] = port->wPortStatus >> 8;
data[2] = port->wPortChange;
data[3] = port->wPortChange >> 8;
ret = 4;
}
break;
case SetHubFeature:
case ClearHubFeature:
if (value == 0 || value == 1) {
} else {
goto fail;
}
ret = 0;
break;
case SetPortFeature:
{
unsigned int n = index - 1;
USBHubPort *port;
USBDevice *dev;
if (n >= s->nb_ports)
goto fail;
port = &s->ports[n];
dev = port->port.dev;
switch(value) {
case PORT_SUSPEND:
port->wPortStatus |= PORT_STAT_SUSPEND;
break;
case PORT_RESET:
if (dev) {
dev->handle_packet(dev,
USB_MSG_RESET, 0, 0, NULL, 0);
port->wPortChange |= PORT_STAT_C_RESET;
/* set enable bit */
port->wPortStatus |= PORT_STAT_ENABLE;
}
break;
case PORT_POWER:
break;
default:
goto fail;
}
ret = 0;
}
break;
case ClearPortFeature:
{
unsigned int n = index - 1;
USBHubPort *port;
USBDevice *dev;
if (n >= s->nb_ports)
goto fail;
port = &s->ports[n];
dev = port->port.dev;
switch(value) {
case PORT_ENABLE:
port->wPortStatus &= ~PORT_STAT_ENABLE;
break;
case PORT_C_ENABLE:
port->wPortChange &= ~PORT_STAT_C_ENABLE;
break;
case PORT_SUSPEND:
port->wPortStatus &= ~PORT_STAT_SUSPEND;
break;
case PORT_C_SUSPEND:
port->wPortChange &= ~PORT_STAT_C_SUSPEND;
break;
case PORT_C_CONNECTION:
port->wPortChange &= ~PORT_STAT_C_CONNECTION;
break;
case PORT_C_OVERCURRENT:
port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
break;
case PORT_C_RESET:
port->wPortChange &= ~PORT_STAT_C_RESET;
break;
default:
goto fail;
}
ret = 0;
}
break;
case GetHubDescriptor:
{
unsigned int n, limit, var_hub_size = 0;
memcpy(data, qemu_hub_hub_descriptor,
sizeof(qemu_hub_hub_descriptor));
data[2] = s->nb_ports;
ret = sizeof(qemu_hub_config_descriptor);
break;
case USB_DT_STRING:
switch (value & 0xff)
{
case 0:
/* language ids */
data[0] = 4;
data[1] = 3;
data[2] = 0x09;
data[3] = 0x04;
ret = 4;
break;
case 1:
/* serial number */
ret = set_usb_string(data, "314159");
break;
case 2:
/* product description */
ret = set_usb_string(data, "QEMU USB Hub");
break;
case 3:
/* vendor description */
ret = set_usb_string(data, "PCSX2/QEMU");
break;
default:
goto fail;
}
break;
default:
goto fail;
}
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
ret = 0;
break;
/* usb specific requests */
case GetHubStatus:
data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 0;
ret = 4;
break;
case GetPortStatus:
{
unsigned int n = index - 1;
USBHubPort* port;
if (n >= s->nb_ports)
goto fail;
port = &s->ports[n];
data[0] = port->wPortStatus;
data[1] = port->wPortStatus >> 8;
data[2] = port->wPortChange;
data[3] = port->wPortChange >> 8;
ret = 4;
}
break;
case SetHubFeature:
case ClearHubFeature:
if (value == 0 || value == 1)
{
}
else
{
goto fail;
}
ret = 0;
break;
case SetPortFeature:
{
unsigned int n = index - 1;
USBHubPort* port;
USBDevice* dev;
if (n >= s->nb_ports)
goto fail;
port = &s->ports[n];
dev = port->port.dev;
switch (value)
{
case PORT_SUSPEND:
port->wPortStatus |= PORT_STAT_SUSPEND;
break;
case PORT_RESET:
if (dev)
{
dev->handle_packet(dev,
USB_MSG_RESET, 0, 0, NULL, 0);
port->wPortChange |= PORT_STAT_C_RESET;
/* set enable bit */
port->wPortStatus |= PORT_STAT_ENABLE;
}
break;
case PORT_POWER:
break;
default:
goto fail;
}
ret = 0;
}
break;
case ClearPortFeature:
{
unsigned int n = index - 1;
USBHubPort* port;
USBDevice* dev;
if (n >= s->nb_ports)
goto fail;
port = &s->ports[n];
dev = port->port.dev;
switch (value)
{
case PORT_ENABLE:
port->wPortStatus &= ~PORT_STAT_ENABLE;
break;
case PORT_C_ENABLE:
port->wPortChange &= ~PORT_STAT_C_ENABLE;
break;
case PORT_SUSPEND:
port->wPortStatus &= ~PORT_STAT_SUSPEND;
break;
case PORT_C_SUSPEND:
port->wPortChange &= ~PORT_STAT_C_SUSPEND;
break;
case PORT_C_CONNECTION:
port->wPortChange &= ~PORT_STAT_C_CONNECTION;
break;
case PORT_C_OVERCURRENT:
port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
break;
case PORT_C_RESET:
port->wPortChange &= ~PORT_STAT_C_RESET;
break;
default:
goto fail;
}
ret = 0;
}
break;
case GetHubDescriptor:
{
unsigned int n, limit, var_hub_size = 0;
memcpy(data, qemu_hub_hub_descriptor,
sizeof(qemu_hub_hub_descriptor));
data[2] = s->nb_ports;
/* fill DeviceRemovable bits */
limit = ((s->nb_ports + 1 + 7) / 8) + 7;
for (n = 7; n < limit; n++) {
data[n] = 0x00;
var_hub_size++;
}
/* fill DeviceRemovable bits */
limit = ((s->nb_ports + 1 + 7) / 8) + 7;
for (n = 7; n < limit; n++)
{
data[n] = 0x00;
var_hub_size++;
}
/* fill PortPwrCtrlMask bits */
limit = limit + ((s->nb_ports + 7) / 8);
for (;n < limit; n++) {
data[n] = 0xff;
var_hub_size++;
}
/* fill PortPwrCtrlMask bits */
limit = limit + ((s->nb_ports + 7) / 8);
for (; n < limit; n++)
{
data[n] = 0xff;
var_hub_size++;
}
ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
data[0] = ret;
break;
}
default:
fail:
ret = USB_RET_STALL;
break;
}
return ret;
ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
data[0] = ret;
break;
}
default:
fail:
ret = USB_RET_STALL;
break;
}
return ret;
}
static int usb_hub_handle_data(USBDevice *dev, int pid,
uint8_t devep, uint8_t *data, int len)
static int usb_hub_handle_data(USBDevice* dev, int pid,
uint8_t devep, uint8_t* data, int len)
{
USBHubState *s = (USBHubState *)dev;
int ret;
USBHubState* s = (USBHubState*)dev;
int ret;
switch(pid) {
case USB_TOKEN_IN:
if (devep == 1) {
USBHubPort *port;
unsigned int status;
int i, n;
n = (s->nb_ports + 1 + 7) / 8;
if (len == 1) { /* FreeBSD workaround */
n = 1;
} else if (n > len) {
return USB_RET_BABBLE;
}
status = 0;
for(i = 0; i < s->nb_ports; i++) {
port = &s->ports[i];
if (port->wPortChange)
status |= (1 << (i + 1));
}
if (status != 0) {
for(i = 0; i < n; i++) {
data[i] = status >> (8 * i);
}
ret = n;
} else {
ret = USB_RET_NAK; /* usb11 11.13.1 */
}
} else {
goto fail;
}
break;
case USB_TOKEN_OUT:
default:
fail:
ret = USB_RET_STALL;
break;
}
return ret;
switch (pid)
{
case USB_TOKEN_IN:
if (devep == 1)
{
USBHubPort* port;
unsigned int status;
int i, n;
n = (s->nb_ports + 1 + 7) / 8;
if (len == 1)
{ /* FreeBSD workaround */
n = 1;
}
else if (n > len)
{
return USB_RET_BABBLE;
}
status = 0;
for (i = 0; i < s->nb_ports; i++)
{
port = &s->ports[i];
if (port->wPortChange)
status |= (1 << (i + 1));
}
if (status != 0)
{
for (i = 0; i < n; i++)
{
data[i] = status >> (8 * i);
}
ret = n;
}
else
{
ret = USB_RET_NAK; /* usb11 11.13.1 */
}
}
else
{
goto fail;
}
break;
case USB_TOKEN_OUT:
default:
fail:
ret = USB_RET_STALL;
break;
}
return ret;
}
static int usb_hub_broadcast_packet(USBHubState *s, int pid,
uint8_t devaddr, uint8_t devep,
uint8_t *data, int len)
static int usb_hub_broadcast_packet(USBHubState* s, int pid,
uint8_t devaddr, uint8_t devep,
uint8_t* data, int len)
{
USBHubPort *port;
USBDevice *dev;
int i, ret;
USBHubPort* port;
USBDevice* dev;
int i, ret;
for(i = 0; i < s->nb_ports; i++) {
port = &s->ports[i];
dev = port->port.dev;
if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
ret = dev->handle_packet(dev, pid,
devaddr, devep,
data, len);
if (ret != USB_RET_NODEV) {
return ret;
}
}
}
return USB_RET_NODEV;
for (i = 0; i < s->nb_ports; i++)
{
port = &s->ports[i];
dev = port->port.dev;
if (dev && (port->wPortStatus & PORT_STAT_ENABLE))
{
ret = dev->handle_packet(dev, pid,
devaddr, devep,
data, len);
if (ret != USB_RET_NODEV)
{
return ret;
}
}
}
return USB_RET_NODEV;
}
static int usb_hub_handle_packet(USBDevice *dev, int pid,
uint8_t devaddr, uint8_t devep,
uint8_t *data, int len)
static int usb_hub_handle_packet(USBDevice* dev, int pid,
uint8_t devaddr, uint8_t devep,
uint8_t* data, int len)
{
USBHubState *s = (USBHubState *)dev;
USBHubState* s = (USBHubState*)dev;
#if defined(DEBUG) && 0
printf("usb_hub: pid=0x%x\n", pid);
printf("usb_hub: pid=0x%x\n", pid);
#endif
if (dev->state == USB_STATE_DEFAULT &&
dev->addr != 0 &&
devaddr != dev->addr &&
(pid == USB_TOKEN_SETUP ||
pid == USB_TOKEN_OUT ||
pid == USB_TOKEN_IN)) {
/* broadcast the packet to the devices */
return usb_hub_broadcast_packet(s, pid, devaddr, devep, data, len);
}
return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
if (dev->state == USB_STATE_DEFAULT &&
dev->addr != 0 &&
devaddr != dev->addr &&
(pid == USB_TOKEN_SETUP ||
pid == USB_TOKEN_OUT ||
pid == USB_TOKEN_IN))
{
/* broadcast the packet to the devices */
return usb_hub_broadcast_packet(s, pid, devaddr, devep, data, len);
}
return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
}
static void usb_hub_handle_destroy(USBDevice *dev)
static void usb_hub_handle_destroy(USBDevice* dev)
{
USBHubState *s = (USBHubState *)dev;
USBHubState* s = (USBHubState*)dev;
free(s);
free(s);
}
USBDevice *usb_hub_init(int nb_ports)
USBDevice* usb_hub_init(int nb_ports)
{
USBHubState *s;
USBHubPort *port;
int i;
USBHubState* s;
USBHubPort* port;
int i;
if (nb_ports > MAX_PORTS)
return NULL;
s = (USBHubState *)qemu_mallocz(sizeof(USBHubState));
if (!s)
return NULL;
s->dev.speed = USB_SPEED_FULL;
s->dev.handle_packet = usb_hub_handle_packet;
if (nb_ports > MAX_PORTS)
return NULL;
s = (USBHubState*)qemu_mallocz(sizeof(USBHubState));
if (!s)
return NULL;
s->dev.speed = USB_SPEED_FULL;
s->dev.handle_packet = usb_hub_handle_packet;
/* generic USB device init */
s->dev.handle_reset = usb_hub_handle_reset;
s->dev.handle_control = usb_hub_handle_control;
s->dev.handle_data = usb_hub_handle_data;
s->dev.handle_destroy = usb_hub_handle_destroy;
/* generic USB device init */
s->dev.handle_reset = usb_hub_handle_reset;
s->dev.handle_control = usb_hub_handle_control;
s->dev.handle_data = usb_hub_handle_data;
s->dev.handle_destroy = usb_hub_handle_destroy;
strncpy(s->dev.devname, "QEMU USB Hub", sizeof(s->dev.devname));
strncpy(s->dev.devname, "QEMU USB Hub", sizeof(s->dev.devname));
s->nb_ports = nb_ports;
for(i = 0; i < s->nb_ports; i++) {
port = &s->ports[i];
s->nb_ports = nb_ports;
for (i = 0; i < s->nb_ports; i++)
{
port = &s->ports[i];
port->port.opaque = s;
port->port.index = i;
port->port.attach = usb_hub_attach;
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
}
return (USBDevice *)s;
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
}
return (USBDevice*)s;
}

File diff suppressed because it is too large Load Diff

View File

@ -18,23 +18,25 @@
/* compute with 96 bit intermediate result: (a*b)/c */
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
{
union {
uint64_t ll;
struct {
union
{
uint64_t ll;
struct
{
#ifdef WORDS_BIGENDIAN
uint32_t high, low;
uint32_t high, low;
#else
uint32_t low, high;
#endif
} l;
} u, res;
uint64_t rl, rh;
uint32_t low, high;
#endif
} l;
} u, res;
uint64_t rl, rh;
u.ll = a;
rl = (uint64_t)u.l.low * (uint64_t)b;
rh = (uint64_t)u.l.high * (uint64_t)b;
rh += (rl >> 32);
res.l.high = rh / c;
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
return res.ll;
u.ll = a;
rl = (uint64_t)u.l.low * (uint64_t)b;
rh = (uint64_t)u.l.high * (uint64_t)b;
rh += (rl >> 32);
res.l.high = rh / c;
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
return res.ll;
}

View File

@ -53,10 +53,10 @@
#include "qusb.h"
#ifndef glue
#define xglue(x, y) x ## y
#define xglue(x, y) x##y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#define stringify(s) tostring(s)
#define tostring(s) #s
#endif
#ifndef MIN
@ -68,19 +68,19 @@
/* vl.c */
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
int cpu_physical_memory_rw(uint32_t addr, uint8_t *buf,
size_t len, int is_write);
int cpu_physical_memory_rw(uint32_t addr, uint8_t* buf,
size_t len, int is_write);
inline int cpu_physical_memory_read(uint32_t addr,
uint8_t *buf, size_t len)
uint8_t* buf, size_t len)
{
return cpu_physical_memory_rw(addr, buf, len, 0);
}
inline int cpu_physical_memory_write(uint32_t addr,
const uint8_t *buf, size_t len)
const uint8_t* buf, size_t len)
{
return cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
return cpu_physical_memory_rw(addr, (uint8_t*)buf, len, 1);
}
#endif /* VL_H */

View File

@ -47,7 +47,7 @@
#if defined(AE_VCPP) || defined(AE_ICC)
#define AE_FORCEINLINE __forceinline
#elif defined(AE_GCC)
//#define AE_FORCEINLINE __attribute__((always_inline))
//#define AE_FORCEINLINE __attribute__((always_inline))
#define AE_FORCEINLINE inline
#else
#define AE_FORCEINLINE inline
@ -67,21 +67,23 @@
// Portable atomic fences implemented below:
namespace moodycamel {
namespace moodycamel
{
enum memory_order {
memory_order_relaxed,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst,
enum memory_order
{
memory_order_relaxed,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst,
// memory_order_sync: Forces a full sync:
// #LoadLoad, #LoadStore, #StoreStore, and most significantly, #StoreLoad
memory_order_sync = memory_order_seq_cst
};
// memory_order_sync: Forces a full sync:
// #LoadLoad, #LoadStore, #StoreStore, and most significantly, #StoreLoad
memory_order_sync = memory_order_seq_cst
};
} // end namespace moodycamel
} // end namespace moodycamel
#if (defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))) || (defined(AE_ICC) && __INTEL_COMPILER < 1600)
// VS2010 and ICC13 don't support std::atomic_*_fence, implement our own fences
@ -103,108 +105,154 @@ enum memory_order {
#ifdef AE_VCPP
#pragma warning(push)
#pragma warning(disable: 4365) // Disable erroneous 'conversion from long to unsigned int, signed/unsigned mismatch' error when using `assert`
#pragma warning(disable : 4365) // Disable erroneous 'conversion from long to unsigned int, signed/unsigned mismatch' error when using `assert`
#ifdef __cplusplus_cli
#pragma managed(push, off)
#endif
#endif
namespace moodycamel {
AE_FORCEINLINE void compiler_fence(memory_order order)
namespace moodycamel
{
switch (order) {
case memory_order_relaxed: break;
case memory_order_acquire: _ReadBarrier(); break;
case memory_order_release: _WriteBarrier(); break;
case memory_order_acq_rel: _ReadWriteBarrier(); break;
case memory_order_seq_cst: _ReadWriteBarrier(); break;
default: assert(false);
AE_FORCEINLINE void compiler_fence(memory_order order)
{
switch (order)
{
case memory_order_relaxed:
break;
case memory_order_acquire:
_ReadBarrier();
break;
case memory_order_release:
_WriteBarrier();
break;
case memory_order_acq_rel:
_ReadWriteBarrier();
break;
case memory_order_seq_cst:
_ReadWriteBarrier();
break;
default:
assert(false);
}
}
}
// x86/x64 have a strong memory model -- all loads and stores have
// acquire and release semantics automatically (so only need compiler
// barriers for those).
#if defined(AE_ARCH_X86) || defined(AE_ARCH_X64)
AE_FORCEINLINE void fence(memory_order order)
{
switch (order) {
case memory_order_relaxed: break;
case memory_order_acquire: _ReadBarrier(); break;
case memory_order_release: _WriteBarrier(); break;
case memory_order_acq_rel: _ReadWriteBarrier(); break;
case memory_order_seq_cst:
_ReadWriteBarrier();
AeFullSync();
_ReadWriteBarrier();
break;
default: assert(false);
AE_FORCEINLINE void fence(memory_order order)
{
switch (order)
{
case memory_order_relaxed:
break;
case memory_order_acquire:
_ReadBarrier();
break;
case memory_order_release:
_WriteBarrier();
break;
case memory_order_acq_rel:
_ReadWriteBarrier();
break;
case memory_order_seq_cst:
_ReadWriteBarrier();
AeFullSync();
_ReadWriteBarrier();
break;
default:
assert(false);
}
}
}
#else
AE_FORCEINLINE void fence(memory_order order)
{
// Non-specialized arch, use heavier memory barriers everywhere just in case :-(
switch (order) {
case memory_order_relaxed:
break;
case memory_order_acquire:
_ReadBarrier();
AeLiteSync();
_ReadBarrier();
break;
case memory_order_release:
_WriteBarrier();
AeLiteSync();
_WriteBarrier();
break;
case memory_order_acq_rel:
_ReadWriteBarrier();
AeLiteSync();
_ReadWriteBarrier();
break;
case memory_order_seq_cst:
_ReadWriteBarrier();
AeFullSync();
_ReadWriteBarrier();
break;
default: assert(false);
AE_FORCEINLINE void fence(memory_order order)
{
// Non-specialized arch, use heavier memory barriers everywhere just in case :-(
switch (order)
{
case memory_order_relaxed:
break;
case memory_order_acquire:
_ReadBarrier();
AeLiteSync();
_ReadBarrier();
break;
case memory_order_release:
_WriteBarrier();
AeLiteSync();
_WriteBarrier();
break;
case memory_order_acq_rel:
_ReadWriteBarrier();
AeLiteSync();
_ReadWriteBarrier();
break;
case memory_order_seq_cst:
_ReadWriteBarrier();
AeFullSync();
_ReadWriteBarrier();
break;
default:
assert(false);
}
}
}
#endif
} // end namespace moodycamel
} // end namespace moodycamel
#else
// Use standard library of atomics
#include <atomic>
namespace moodycamel {
AE_FORCEINLINE void compiler_fence(memory_order order)
namespace moodycamel
{
switch (order) {
case memory_order_relaxed: break;
case memory_order_acquire: std::atomic_signal_fence(std::memory_order_acquire); break;
case memory_order_release: std::atomic_signal_fence(std::memory_order_release); break;
case memory_order_acq_rel: std::atomic_signal_fence(std::memory_order_acq_rel); break;
case memory_order_seq_cst: std::atomic_signal_fence(std::memory_order_seq_cst); break;
default: assert(false);
}
}
AE_FORCEINLINE void fence(memory_order order)
{
switch (order) {
case memory_order_relaxed: break;
case memory_order_acquire: std::atomic_thread_fence(std::memory_order_acquire); break;
case memory_order_release: std::atomic_thread_fence(std::memory_order_release); break;
case memory_order_acq_rel: std::atomic_thread_fence(std::memory_order_acq_rel); break;
case memory_order_seq_cst: std::atomic_thread_fence(std::memory_order_seq_cst); break;
default: assert(false);
AE_FORCEINLINE void compiler_fence(memory_order order)
{
switch (order)
{
case memory_order_relaxed:
break;
case memory_order_acquire:
std::atomic_signal_fence(std::memory_order_acquire);
break;
case memory_order_release:
std::atomic_signal_fence(std::memory_order_release);
break;
case memory_order_acq_rel:
std::atomic_signal_fence(std::memory_order_acq_rel);
break;
case memory_order_seq_cst:
std::atomic_signal_fence(std::memory_order_seq_cst);
break;
default:
assert(false);
}
}
}
} // end namespace moodycamel
AE_FORCEINLINE void fence(memory_order order)
{
switch (order)
{
case memory_order_relaxed:
break;
case memory_order_acquire:
std::atomic_thread_fence(std::memory_order_acquire);
break;
case memory_order_release:
std::atomic_thread_fence(std::memory_order_release);
break;
case memory_order_acq_rel:
std::atomic_thread_fence(std::memory_order_acq_rel);
break;
case memory_order_seq_cst:
std::atomic_thread_fence(std::memory_order_seq_cst);
break;
default:
assert(false);
}
}
} // end namespace moodycamel
#endif
@ -222,102 +270,132 @@ AE_FORCEINLINE void fence(memory_order order)
// Provides basic support for atomic variables -- no memory ordering guarantees are provided.
// The guarantee of atomicity is only made for types that already have atomic load and store guarantees
// at the hardware level -- on most platforms this generally means aligned pointers and integers (only).
namespace moodycamel {
template<typename T>
class weak_atomic
namespace moodycamel
{
public:
weak_atomic() { }
template <typename T>
class weak_atomic
{
public:
weak_atomic() {}
#ifdef AE_VCPP
#pragma warning(push)
#pragma warning(disable: 4100) // Get rid of (erroneous) 'unreferenced formal parameter' warning
#pragma warning(disable : 4100) // Get rid of (erroneous) 'unreferenced formal parameter' warning
#endif
template<typename U> weak_atomic(U&& x) : value(std::forward<U>(x)) { }
template <typename U>
weak_atomic(U&& x)
: value(std::forward<U>(x))
{
}
#ifdef __cplusplus_cli
// Work around bug with universal reference/nullptr combination that only appears when /clr is on
weak_atomic(nullptr_t) : value(nullptr) { }
// Work around bug with universal reference/nullptr combination that only appears when /clr is on
weak_atomic(nullptr_t)
: value(nullptr)
{
}
#endif
weak_atomic(weak_atomic const& other) : value(other.value) { }
weak_atomic(weak_atomic&& other) : value(std::move(other.value)) { }
weak_atomic(weak_atomic const& other)
: value(other.value)
{
}
weak_atomic(weak_atomic&& other)
: value(std::move(other.value))
{
}
#ifdef AE_VCPP
#pragma warning(pop)
#endif
AE_FORCEINLINE operator T() const { return load(); }
AE_FORCEINLINE operator T() const
{
return load();
}
#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC
template<typename U> AE_FORCEINLINE weak_atomic const& operator=(U&& x) { value = std::forward<U>(x); return *this; }
AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other) { value = other.value; return *this; }
AE_FORCEINLINE T load() const { return value; }
AE_FORCEINLINE T fetch_add_acquire(T increment)
{
template <typename U>
AE_FORCEINLINE weak_atomic const& operator=(U&& x)
{
value = std::forward<U>(x);
return *this;
}
AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other)
{
value = other.value;
return *this;
}
AE_FORCEINLINE T load() const { return value; }
AE_FORCEINLINE T fetch_add_acquire(T increment)
{
#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86)
if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment);
if (sizeof(T) == 4)
return _InterlockedExchangeAdd((long volatile*)&value, (long)increment);
#if defined(_M_AMD64)
else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment);
else if (sizeof(T) == 8)
return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment);
#endif
#else
#error Unsupported platform
#endif
assert(false && "T must be either a 32 or 64 bit type");
return value;
}
AE_FORCEINLINE T fetch_add_release(T increment)
{
assert(false && "T must be either a 32 or 64 bit type");
return value;
}
AE_FORCEINLINE T fetch_add_release(T increment)
{
#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86)
if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment);
if (sizeof(T) == 4)
return _InterlockedExchangeAdd((long volatile*)&value, (long)increment);
#if defined(_M_AMD64)
else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment);
else if (sizeof(T) == 8)
return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment);
#endif
#else
#error Unsupported platform
#endif
assert(false && "T must be either a 32 or 64 bit type");
return value;
}
assert(false && "T must be either a 32 or 64 bit type");
return value;
}
#else
template<typename U>
AE_FORCEINLINE weak_atomic const& operator=(U&& x)
{
value.store(std::forward<U>(x), std::memory_order_relaxed);
return *this;
}
AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other)
{
value.store(other.value.load(std::memory_order_relaxed), std::memory_order_relaxed);
return *this;
}
template <typename U>
AE_FORCEINLINE weak_atomic const& operator=(U&& x)
{
value.store(std::forward<U>(x), std::memory_order_relaxed);
return *this;
}
AE_FORCEINLINE T load() const { return value.load(std::memory_order_relaxed); }
AE_FORCEINLINE T fetch_add_acquire(T increment)
{
return value.fetch_add(increment, std::memory_order_acquire);
}
AE_FORCEINLINE T fetch_add_release(T increment)
{
return value.fetch_add(increment, std::memory_order_release);
}
AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other)
{
value.store(other.value.load(std::memory_order_relaxed), std::memory_order_relaxed);
return *this;
}
AE_FORCEINLINE T load() const { return value.load(std::memory_order_relaxed); }
AE_FORCEINLINE T fetch_add_acquire(T increment)
{
return value.fetch_add(increment, std::memory_order_acquire);
}
AE_FORCEINLINE T fetch_add_release(T increment)
{
return value.fetch_add(increment, std::memory_order_release);
}
#endif
private:
private:
#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC
// No std::atomic support, but still need to circumvent compiler optimizations.
// `volatile` will make memory access slow, but is guaranteed to be reliable.
volatile T value;
// No std::atomic support, but still need to circumvent compiler optimizations.
// `volatile` will make memory access slow, but is guaranteed to be reliable.
volatile T value;
#else
std::atomic<T> value;
std::atomic<T> value;
#endif
};
};
} // end namespace moodycamel
} // end namespace moodycamel
@ -330,11 +408,11 @@ private:
// I know this is an ugly hack but it still beats polluting the global
// namespace with thousands of generic names or adding a .cpp for nothing.
extern "C" {
struct _SECURITY_ATTRIBUTES;
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName);
__declspec(dllimport) int __stdcall CloseHandle(void* hObject);
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount);
struct _SECURITY_ATTRIBUTES;
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName);
__declspec(dllimport) int __stdcall CloseHandle(void* hObject);
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount);
}
#elif defined(__MACH__)
#include <mach/mach.h>
@ -371,29 +449,29 @@ namespace moodycamel
class Semaphore
{
private:
void* m_hSema;
Semaphore(const Semaphore& other);
Semaphore& operator=(const Semaphore& other);
void* m_hSema;
Semaphore(const Semaphore& other);
Semaphore& operator=(const Semaphore& other);
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
const long maxLong = 0x7fffffff;
m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr);
}
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
const long maxLong = 0x7fffffff;
m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr);
}
~Semaphore()
{
CloseHandle(m_hSema);
}
~Semaphore()
{
CloseHandle(m_hSema);
}
void wait()
{
const unsigned long infinite = 0xffffffff;
WaitForSingleObject(m_hSema, infinite);
}
void wait()
{
const unsigned long infinite = 0xffffffff;
WaitForSingleObject(m_hSema, infinite);
}
bool try_wait()
{
@ -407,10 +485,10 @@ namespace moodycamel
return WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) != RC_WAIT_TIMEOUT;
}
void signal(int count = 1)
{
ReleaseSemaphore(m_hSema, count, nullptr);
}
void signal(int count = 1)
{
ReleaseSemaphore(m_hSema, count, nullptr);
}
};
#elif defined(__MACH__)
//---------------------------------------------------------
@ -420,27 +498,27 @@ namespace moodycamel
class Semaphore
{
private:
semaphore_t m_sema;
semaphore_t m_sema;
Semaphore(const Semaphore& other);
Semaphore& operator=(const Semaphore& other);
Semaphore(const Semaphore& other);
Semaphore& operator=(const Semaphore& other);
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
}
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
}
~Semaphore()
{
semaphore_destroy(mach_task_self(), m_sema);
}
~Semaphore()
{
semaphore_destroy(mach_task_self(), m_sema);
}
void wait()
{
semaphore_wait(m_sema);
}
void wait()
{
semaphore_wait(m_sema);
}
bool try_wait()
{
@ -459,18 +537,18 @@ namespace moodycamel
return rc != KERN_OPERATION_TIMED_OUT && rc != KERN_ABORTED;
}
void signal()
{
semaphore_signal(m_sema);
}
void signal()
{
semaphore_signal(m_sema);
}
void signal(int count)
{
while (count-- > 0)
{
semaphore_signal(m_sema);
}
}
void signal(int count)
{
while (count-- > 0)
{
semaphore_signal(m_sema);
}
}
};
#elif defined(__unix__)
//---------------------------------------------------------
@ -479,38 +557,38 @@ namespace moodycamel
class Semaphore
{
private:
sem_t m_sema;
sem_t m_sema;
Semaphore(const Semaphore& other);
Semaphore& operator=(const Semaphore& other);
Semaphore(const Semaphore& other);
Semaphore& operator=(const Semaphore& other);
public:
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
sem_init(&m_sema, 0, initialCount);
}
Semaphore(int initialCount = 0)
{
assert(initialCount >= 0);
sem_init(&m_sema, 0, initialCount);
}
~Semaphore()
{
sem_destroy(&m_sema);
}
~Semaphore()
{
sem_destroy(&m_sema);
}
void wait()
{
// http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error
int rc;
do
{
rc = sem_wait(&m_sema);
}
while (rc == -1 && errno == EINTR);
}
void wait()
{
// http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error
int rc;
do
{
rc = sem_wait(&m_sema);
} while (rc == -1 && errno == EINTR);
}
bool try_wait()
{
int rc;
do {
do
{
rc = sem_trywait(&m_sema);
} while (rc == -1 && errno == EINTR);
return !(rc == -1 && errno == EAGAIN);
@ -526,30 +604,32 @@ namespace moodycamel
ts.tv_nsec += (usecs % usecs_in_1_sec) * 1000;
// sem_timedwait bombs if you have more than 1e9 in tv_nsec
// so we have to clean things up before passing it in
if (ts.tv_nsec >= nsecs_in_1_sec) {
if (ts.tv_nsec >= nsecs_in_1_sec)
{
ts.tv_nsec -= nsecs_in_1_sec;
++ts.tv_sec;
}
int rc;
do {
do
{
rc = sem_timedwait(&m_sema, &ts);
} while (rc == -1 && errno == EINTR);
return !(rc == -1 && errno == ETIMEDOUT);
}
void signal()
{
sem_post(&m_sema);
}
void signal()
{
sem_post(&m_sema);
}
void signal(int count)
{
while (count-- > 0)
{
sem_post(&m_sema);
}
}
void signal(int count)
{
while (count-- > 0)
{
sem_post(&m_sema);
}
}
};
#else
#error Unsupported platform! (No semaphore wrapper available)
@ -562,31 +642,31 @@ namespace moodycamel
{
public:
typedef std::make_signed<std::size_t>::type ssize_t;
private:
weak_atomic<ssize_t> m_count;
Semaphore m_sema;
bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1)
{
ssize_t oldCount;
// Is there a better way to set the initial spin count?
// If we lower it to 1000, testBenaphore becomes 15x slower on my Core i7-5930K Windows PC,
// as threads start hitting the kernel semaphore.
int spin = 10000;
while (--spin >= 0)
{
if (m_count.load() > 0)
{
m_count.fetch_add_acquire(-1);
return true;
}
compiler_fence(memory_order_acquire); // Prevent the compiler from collapsing the loop.
}
oldCount = m_count.fetch_add_acquire(-1);
private:
weak_atomic<ssize_t> m_count;
Semaphore m_sema;
bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1)
{
ssize_t oldCount;
// Is there a better way to set the initial spin count?
// If we lower it to 1000, testBenaphore becomes 15x slower on my Core i7-5930K Windows PC,
// as threads start hitting the kernel semaphore.
int spin = 10000;
while (--spin >= 0)
{
if (m_count.load() > 0)
{
m_count.fetch_add_acquire(-1);
return true;
}
compiler_fence(memory_order_acquire); // Prevent the compiler from collapsing the loop.
}
oldCount = m_count.fetch_add_acquire(-1);
if (oldCount > 0)
return true;
if (timeout_usecs < 0)
if (timeout_usecs < 0)
{
m_sema.wait();
return true;
@ -602,60 +682,61 @@ namespace moodycamel
{
oldCount = m_count.fetch_add_release(1);
if (oldCount < 0)
return false; // successfully restored things to the way they were
return false; // successfully restored things to the way they were
// Oh, the producer thread just signaled the semaphore after all. Try again:
oldCount = m_count.fetch_add_acquire(-1);
if (oldCount > 0 && m_sema.try_wait())
return true;
}
}
}
public:
LightweightSemaphore(ssize_t initialCount = 0) : m_count(initialCount)
{
assert(initialCount >= 0);
}
LightweightSemaphore(ssize_t initialCount = 0)
: m_count(initialCount)
{
assert(initialCount >= 0);
}
bool tryWait()
{
if (m_count.load() > 0)
{
m_count.fetch_add_acquire(-1);
return true;
}
return false;
}
bool tryWait()
{
if (m_count.load() > 0)
{
m_count.fetch_add_acquire(-1);
return true;
}
return false;
}
void wait()
{
if (!tryWait())
waitWithPartialSpinning();
}
void wait()
{
if (!tryWait())
waitWithPartialSpinning();
}
bool wait(std::int64_t timeout_usecs)
{
return tryWait() || waitWithPartialSpinning(timeout_usecs);
}
void signal(ssize_t count = 1)
{
assert(count >= 0);
ssize_t oldCount = m_count.fetch_add_release(count);
assert(oldCount >= -1);
if (oldCount < 0)
{
m_sema.signal(1);
}
}
ssize_t availableApprox() const
{
ssize_t count = m_count.load();
return count > 0 ? count : 0;
}
void signal(ssize_t count = 1)
{
assert(count >= 0);
ssize_t oldCount = m_count.fetch_add_release(count);
assert(oldCount >= -1);
if (oldCount < 0)
{
m_sema.signal(1);
}
}
ssize_t availableApprox() const
{
ssize_t count = m_count.load();
return count > 0 ? count : 0;
}
};
} // end namespace spsc_sema
} // end namespace moodycamel
} // end namespace spsc_sema
} // end namespace moodycamel
#if defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))
#pragma warning(pop)

File diff suppressed because it is too large Load Diff

View File

@ -33,36 +33,42 @@ _HidD_GetProductString HidD_GetProductString = NULL;
static HMODULE hModHid = 0;
int InitHid() {
if (hModHid) {
return 1;
}
hModHid = LoadLibraryA("hid.dll");
if (hModHid) {
if ((HidD_GetHidGuid = (_HidD_GetHidGuid)GetProcAddress(hModHid, "HidD_GetHidGuid")) &&
(HidD_GetAttributes = (_HidD_GetAttributes)GetProcAddress(hModHid, "HidD_GetAttributes")) &&
(HidD_GetPreparsedData = (_HidD_GetPreparsedData)GetProcAddress(hModHid, "HidD_GetPreparsedData")) &&
(HidP_GetCaps = (_HidP_GetCaps)GetProcAddress(hModHid, "HidP_GetCaps")) &&
(HidD_FreePreparsedData = (_HidD_FreePreparsedData)GetProcAddress(hModHid, "HidD_FreePreparsedData")) &&
(HidP_GetSpecificButtonCaps = (_HidP_GetSpecificButtonCaps)GetProcAddress(hModHid, "HidP_GetSpecificButtonCaps")) &&
(HidP_GetButtonCaps = (_HidP_GetButtonCaps)GetProcAddress(hModHid, "HidP_GetButtonCaps")) &&
(HidP_GetUsages = (_HidP_GetUsages)GetProcAddress(hModHid, "HidP_GetUsages")) &&
(HidP_GetValueCaps = (_HidP_GetValueCaps)GetProcAddress(hModHid, "HidP_GetValueCaps")) &&
(HidP_GetUsageValue = (_HidP_GetUsageValue)GetProcAddress(hModHid, "HidP_GetUsageValue")) &&
(HidD_GetProductString = (_HidD_GetProductString)GetProcAddress(hModHid, "HidD_GetProductString")) &&
(HidD_GetFeature = (_HidD_GetFeature)GetProcAddress(hModHid, "HidD_GetFeature")) &&
(HidD_SetFeature = (_HidD_SetFeature)GetProcAddress(hModHid, "HidD_SetFeature"))) {
//pHidD_GetHidGuid(&GUID_DEVINTERFACE_HID);
return 1;
}
UninitHid();
}
return 0;
int InitHid()
{
if (hModHid)
{
return 1;
}
hModHid = LoadLibraryA("hid.dll");
if (hModHid)
{
if ((HidD_GetHidGuid = (_HidD_GetHidGuid)GetProcAddress(hModHid, "HidD_GetHidGuid")) &&
(HidD_GetAttributes = (_HidD_GetAttributes)GetProcAddress(hModHid, "HidD_GetAttributes")) &&
(HidD_GetPreparsedData = (_HidD_GetPreparsedData)GetProcAddress(hModHid, "HidD_GetPreparsedData")) &&
(HidP_GetCaps = (_HidP_GetCaps)GetProcAddress(hModHid, "HidP_GetCaps")) &&
(HidD_FreePreparsedData = (_HidD_FreePreparsedData)GetProcAddress(hModHid, "HidD_FreePreparsedData")) &&
(HidP_GetSpecificButtonCaps = (_HidP_GetSpecificButtonCaps)GetProcAddress(hModHid, "HidP_GetSpecificButtonCaps")) &&
(HidP_GetButtonCaps = (_HidP_GetButtonCaps)GetProcAddress(hModHid, "HidP_GetButtonCaps")) &&
(HidP_GetUsages = (_HidP_GetUsages)GetProcAddress(hModHid, "HidP_GetUsages")) &&
(HidP_GetValueCaps = (_HidP_GetValueCaps)GetProcAddress(hModHid, "HidP_GetValueCaps")) &&
(HidP_GetUsageValue = (_HidP_GetUsageValue)GetProcAddress(hModHid, "HidP_GetUsageValue")) &&
(HidD_GetProductString = (_HidD_GetProductString)GetProcAddress(hModHid, "HidD_GetProductString")) &&
(HidD_GetFeature = (_HidD_GetFeature)GetProcAddress(hModHid, "HidD_GetFeature")) &&
(HidD_SetFeature = (_HidD_SetFeature)GetProcAddress(hModHid, "HidD_SetFeature")))
{
//pHidD_GetHidGuid(&GUID_DEVINTERFACE_HID);
return 1;
}
UninitHid();
}
return 0;
}
void UninitHid() {
if (hModHid) {
FreeLibrary(hModHid);
hModHid = 0;
}
void UninitHid()
{
if (hModHid)
{
FreeLibrary(hModHid);
hModHid = 0;
}
}

View File

@ -20,74 +20,74 @@
typedef USHORT USAGE, *PUSAGE;
#define HID_USAGE_PAGE_GENERIC ((USAGE) 0x01)
#define HID_USAGE_PAGE_SIMULATION ((USAGE) 0x02)
#define HID_USAGE_PAGE_VR ((USAGE) 0x03)
#define HID_USAGE_PAGE_SPORT ((USAGE) 0x04)
#define HID_USAGE_PAGE_GAME ((USAGE) 0x05)
#define HID_USAGE_PAGE_KEYBOARD ((USAGE) 0x07)
#define HID_USAGE_PAGE_LED ((USAGE) 0x08)
#define HID_USAGE_PAGE_BUTTON ((USAGE) 0x09)
#define HID_USAGE_PAGE_ORDINAL ((USAGE) 0x0A)
#define HID_USAGE_PAGE_TELEPHONY ((USAGE) 0x0B)
#define HID_USAGE_PAGE_CONSUMER ((USAGE) 0x0C)
#define HID_USAGE_PAGE_DIGITIZER ((USAGE) 0x0D)
#define HID_USAGE_PAGE_UNICODE ((USAGE) 0x10)
#define HID_USAGE_PAGE_ALPHANUMERIC ((USAGE) 0x14)
#define HID_USAGE_PAGE_GENERIC ((USAGE)0x01)
#define HID_USAGE_PAGE_SIMULATION ((USAGE)0x02)
#define HID_USAGE_PAGE_VR ((USAGE)0x03)
#define HID_USAGE_PAGE_SPORT ((USAGE)0x04)
#define HID_USAGE_PAGE_GAME ((USAGE)0x05)
#define HID_USAGE_PAGE_KEYBOARD ((USAGE)0x07)
#define HID_USAGE_PAGE_LED ((USAGE)0x08)
#define HID_USAGE_PAGE_BUTTON ((USAGE)0x09)
#define HID_USAGE_PAGE_ORDINAL ((USAGE)0x0A)
#define HID_USAGE_PAGE_TELEPHONY ((USAGE)0x0B)
#define HID_USAGE_PAGE_CONSUMER ((USAGE)0x0C)
#define HID_USAGE_PAGE_DIGITIZER ((USAGE)0x0D)
#define HID_USAGE_PAGE_UNICODE ((USAGE)0x10)
#define HID_USAGE_PAGE_ALPHANUMERIC ((USAGE)0x14)
//
// Usages from Generic Desktop Page (0x01)
//
#define HID_USAGE_GENERIC_POINTER ((USAGE) 0x01)
#define HID_USAGE_GENERIC_MOUSE ((USAGE) 0x02)
#define HID_USAGE_GENERIC_JOYSTICK ((USAGE) 0x04)
#define HID_USAGE_GENERIC_GAMEPAD ((USAGE) 0x05)
#define HID_USAGE_GENERIC_KEYBOARD ((USAGE) 0x06)
#define HID_USAGE_GENERIC_KEYPAD ((USAGE) 0x07)
#define HID_USAGE_GENERIC_SYSTEM_CTL ((USAGE) 0x80)
#define HID_USAGE_GENERIC_POINTER ((USAGE)0x01)
#define HID_USAGE_GENERIC_MOUSE ((USAGE)0x02)
#define HID_USAGE_GENERIC_JOYSTICK ((USAGE)0x04)
#define HID_USAGE_GENERIC_GAMEPAD ((USAGE)0x05)
#define HID_USAGE_GENERIC_KEYBOARD ((USAGE)0x06)
#define HID_USAGE_GENERIC_KEYPAD ((USAGE)0x07)
#define HID_USAGE_GENERIC_SYSTEM_CTL ((USAGE)0x80)
#define HID_USAGE_GENERIC_X ((USAGE) 0x30)
#define HID_USAGE_GENERIC_Y ((USAGE) 0x31)
#define HID_USAGE_GENERIC_Z ((USAGE) 0x32)
#define HID_USAGE_GENERIC_RX ((USAGE) 0x33)
#define HID_USAGE_GENERIC_RY ((USAGE) 0x34)
#define HID_USAGE_GENERIC_RZ ((USAGE) 0x35)
#define HID_USAGE_GENERIC_SLIDER ((USAGE) 0x36)
#define HID_USAGE_GENERIC_DIAL ((USAGE) 0x37)
#define HID_USAGE_GENERIC_WHEEL ((USAGE) 0x38)
#define HID_USAGE_GENERIC_HATSWITCH ((USAGE) 0x39)
#define HID_USAGE_GENERIC_COUNTED_BUFFER ((USAGE) 0x3A)
#define HID_USAGE_GENERIC_BYTE_COUNT ((USAGE) 0x3B)
#define HID_USAGE_GENERIC_MOTION_WAKEUP ((USAGE) 0x3C)
#define HID_USAGE_GENERIC_VX ((USAGE) 0x40)
#define HID_USAGE_GENERIC_VY ((USAGE) 0x41)
#define HID_USAGE_GENERIC_VZ ((USAGE) 0x42)
#define HID_USAGE_GENERIC_VBRX ((USAGE) 0x43)
#define HID_USAGE_GENERIC_VBRY ((USAGE) 0x44)
#define HID_USAGE_GENERIC_VBRZ ((USAGE) 0x45)
#define HID_USAGE_GENERIC_VNO ((USAGE) 0x46)
#define HID_USAGE_GENERIC_SYSCTL_POWER ((USAGE) 0x81)
#define HID_USAGE_GENERIC_SYSCTL_SLEEP ((USAGE) 0x82)
#define HID_USAGE_GENERIC_SYSCTL_WAKE ((USAGE) 0x83)
#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU ((USAGE) 0x84)
#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU ((USAGE) 0x85)
#define HID_USAGE_GENERIC_SYSCTL_APP_MENU ((USAGE) 0x86)
#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU ((USAGE) 0x87)
#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT ((USAGE) 0x88)
#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT ((USAGE) 0x89)
#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT ((USAGE) 0x8A)
#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT ((USAGE) 0x8B)
#define HID_USAGE_GENERIC_SYSCTL_MENU_UP ((USAGE) 0x8C)
#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN ((USAGE) 0x8D)
#define HID_USAGE_GENERIC_X ((USAGE)0x30)
#define HID_USAGE_GENERIC_Y ((USAGE)0x31)
#define HID_USAGE_GENERIC_Z ((USAGE)0x32)
#define HID_USAGE_GENERIC_RX ((USAGE)0x33)
#define HID_USAGE_GENERIC_RY ((USAGE)0x34)
#define HID_USAGE_GENERIC_RZ ((USAGE)0x35)
#define HID_USAGE_GENERIC_SLIDER ((USAGE)0x36)
#define HID_USAGE_GENERIC_DIAL ((USAGE)0x37)
#define HID_USAGE_GENERIC_WHEEL ((USAGE)0x38)
#define HID_USAGE_GENERIC_HATSWITCH ((USAGE)0x39)
#define HID_USAGE_GENERIC_COUNTED_BUFFER ((USAGE)0x3A)
#define HID_USAGE_GENERIC_BYTE_COUNT ((USAGE)0x3B)
#define HID_USAGE_GENERIC_MOTION_WAKEUP ((USAGE)0x3C)
#define HID_USAGE_GENERIC_VX ((USAGE)0x40)
#define HID_USAGE_GENERIC_VY ((USAGE)0x41)
#define HID_USAGE_GENERIC_VZ ((USAGE)0x42)
#define HID_USAGE_GENERIC_VBRX ((USAGE)0x43)
#define HID_USAGE_GENERIC_VBRY ((USAGE)0x44)
#define HID_USAGE_GENERIC_VBRZ ((USAGE)0x45)
#define HID_USAGE_GENERIC_VNO ((USAGE)0x46)
#define HID_USAGE_GENERIC_SYSCTL_POWER ((USAGE)0x81)
#define HID_USAGE_GENERIC_SYSCTL_SLEEP ((USAGE)0x82)
#define HID_USAGE_GENERIC_SYSCTL_WAKE ((USAGE)0x83)
#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU ((USAGE)0x84)
#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU ((USAGE)0x85)
#define HID_USAGE_GENERIC_SYSCTL_APP_MENU ((USAGE)0x86)
#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU ((USAGE)0x87)
#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT ((USAGE)0x88)
#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT ((USAGE)0x89)
#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT ((USAGE)0x8A)
#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT ((USAGE)0x8B)
#define HID_USAGE_GENERIC_SYSCTL_MENU_UP ((USAGE)0x8C)
#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN ((USAGE)0x8D)
//
// Usages from Simulation Controls Page (0x02)
//
#define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA)
#define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB)
#define HID_USAGE_SIMULATION_RUDDER ((USAGE)0xBA)
#define HID_USAGE_SIMULATION_THROTTLE ((USAGE)0xBB)
//
// Virtual Reality Controls Page (0x03)
@ -109,38 +109,38 @@ typedef USHORT USAGE, *PUSAGE;
//
// Error "keys"
#define HID_USAGE_KEYBOARD_NOEVENT ((USAGE) 0x00)
#define HID_USAGE_KEYBOARD_ROLLOVER ((USAGE) 0x01)
#define HID_USAGE_KEYBOARD_POSTFAIL ((USAGE) 0x02)
#define HID_USAGE_KEYBOARD_UNDEFINED ((USAGE) 0x03)
#define HID_USAGE_KEYBOARD_NOEVENT ((USAGE)0x00)
#define HID_USAGE_KEYBOARD_ROLLOVER ((USAGE)0x01)
#define HID_USAGE_KEYBOARD_POSTFAIL ((USAGE)0x02)
#define HID_USAGE_KEYBOARD_UNDEFINED ((USAGE)0x03)
// Letters
#define HID_USAGE_KEYBOARD_aA ((USAGE) 0x04)
#define HID_USAGE_KEYBOARD_zZ ((USAGE) 0x1D)
#define HID_USAGE_KEYBOARD_aA ((USAGE)0x04)
#define HID_USAGE_KEYBOARD_zZ ((USAGE)0x1D)
// Numbers
#define HID_USAGE_KEYBOARD_ONE ((USAGE) 0x1E)
#define HID_USAGE_KEYBOARD_ZERO ((USAGE) 0x27)
#define HID_USAGE_KEYBOARD_ONE ((USAGE)0x1E)
#define HID_USAGE_KEYBOARD_ZERO ((USAGE)0x27)
// Modifier Keys
#define HID_USAGE_KEYBOARD_LCTRL ((USAGE) 0xE0)
#define HID_USAGE_KEYBOARD_LSHFT ((USAGE) 0xE1)
#define HID_USAGE_KEYBOARD_LALT ((USAGE) 0xE2)
#define HID_USAGE_KEYBOARD_LGUI ((USAGE) 0xE3)
#define HID_USAGE_KEYBOARD_RCTRL ((USAGE) 0xE4)
#define HID_USAGE_KEYBOARD_RSHFT ((USAGE) 0xE5)
#define HID_USAGE_KEYBOARD_RALT ((USAGE) 0xE6)
#define HID_USAGE_KEYBOARD_RGUI ((USAGE) 0xE7)
#define HID_USAGE_KEYBOARD_SCROLL_LOCK ((USAGE) 0x47)
#define HID_USAGE_KEYBOARD_NUM_LOCK ((USAGE) 0x53)
#define HID_USAGE_KEYBOARD_CAPS_LOCK ((USAGE) 0x39)
#define HID_USAGE_KEYBOARD_LCTRL ((USAGE)0xE0)
#define HID_USAGE_KEYBOARD_LSHFT ((USAGE)0xE1)
#define HID_USAGE_KEYBOARD_LALT ((USAGE)0xE2)
#define HID_USAGE_KEYBOARD_LGUI ((USAGE)0xE3)
#define HID_USAGE_KEYBOARD_RCTRL ((USAGE)0xE4)
#define HID_USAGE_KEYBOARD_RSHFT ((USAGE)0xE5)
#define HID_USAGE_KEYBOARD_RALT ((USAGE)0xE6)
#define HID_USAGE_KEYBOARD_RGUI ((USAGE)0xE7)
#define HID_USAGE_KEYBOARD_SCROLL_LOCK ((USAGE)0x47)
#define HID_USAGE_KEYBOARD_NUM_LOCK ((USAGE)0x53)
#define HID_USAGE_KEYBOARD_CAPS_LOCK ((USAGE)0x39)
// Funtion keys
#define HID_USAGE_KEYBOARD_F1 ((USAGE) 0x3A)
#define HID_USAGE_KEYBOARD_F12 ((USAGE) 0x45)
#define HID_USAGE_KEYBOARD_F1 ((USAGE)0x3A)
#define HID_USAGE_KEYBOARD_F12 ((USAGE)0x45)
#define HID_USAGE_KEYBOARD_RETURN ((USAGE) 0x28)
#define HID_USAGE_KEYBOARD_ESCAPE ((USAGE) 0x29)
#define HID_USAGE_KEYBOARD_DELETE ((USAGE) 0x2A)
#define HID_USAGE_KEYBOARD_RETURN ((USAGE)0x28)
#define HID_USAGE_KEYBOARD_ESCAPE ((USAGE)0x29)
#define HID_USAGE_KEYBOARD_DELETE ((USAGE)0x2A)
#define HID_USAGE_KEYBOARD_PRINT_SCREEN ((USAGE) 0x46)
#define HID_USAGE_KEYBOARD_PRINT_SCREEN ((USAGE)0x46)
// and hundreds more...
@ -148,81 +148,81 @@ typedef USHORT USAGE, *PUSAGE;
// LED Page (0x08)
//
#define HID_USAGE_LED_NUM_LOCK ((USAGE) 0x01)
#define HID_USAGE_LED_CAPS_LOCK ((USAGE) 0x02)
#define HID_USAGE_LED_SCROLL_LOCK ((USAGE) 0x03)
#define HID_USAGE_LED_COMPOSE ((USAGE) 0x04)
#define HID_USAGE_LED_KANA ((USAGE) 0x05)
#define HID_USAGE_LED_POWER ((USAGE) 0x06)
#define HID_USAGE_LED_SHIFT ((USAGE) 0x07)
#define HID_USAGE_LED_DO_NOT_DISTURB ((USAGE) 0x08)
#define HID_USAGE_LED_MUTE ((USAGE) 0x09)
#define HID_USAGE_LED_TONE_ENABLE ((USAGE) 0x0A)
#define HID_USAGE_LED_HIGH_CUT_FILTER ((USAGE) 0x0B)
#define HID_USAGE_LED_LOW_CUT_FILTER ((USAGE) 0x0C)
#define HID_USAGE_LED_EQUALIZER_ENABLE ((USAGE) 0x0D)
#define HID_USAGE_LED_SOUND_FIELD_ON ((USAGE) 0x0E)
#define HID_USAGE_LED_SURROUND_FIELD_ON ((USAGE) 0x0F)
#define HID_USAGE_LED_REPEAT ((USAGE) 0x10)
#define HID_USAGE_LED_STEREO ((USAGE) 0x11)
#define HID_USAGE_LED_SAMPLING_RATE_DETECT ((USAGE) 0x12)
#define HID_USAGE_LED_SPINNING ((USAGE) 0x13)
#define HID_USAGE_LED_CAV ((USAGE) 0x14)
#define HID_USAGE_LED_CLV ((USAGE) 0x15)
#define HID_USAGE_LED_RECORDING_FORMAT_DET ((USAGE) 0x16)
#define HID_USAGE_LED_OFF_HOOK ((USAGE) 0x17)
#define HID_USAGE_LED_RING ((USAGE) 0x18)
#define HID_USAGE_LED_MESSAGE_WAITING ((USAGE) 0x19)
#define HID_USAGE_LED_DATA_MODE ((USAGE) 0x1A)
#define HID_USAGE_LED_BATTERY_OPERATION ((USAGE) 0x1B)
#define HID_USAGE_LED_BATTERY_OK ((USAGE) 0x1C)
#define HID_USAGE_LED_BATTERY_LOW ((USAGE) 0x1D)
#define HID_USAGE_LED_SPEAKER ((USAGE) 0x1E)
#define HID_USAGE_LED_HEAD_SET ((USAGE) 0x1F)
#define HID_USAGE_LED_HOLD ((USAGE) 0x20)
#define HID_USAGE_LED_MICROPHONE ((USAGE) 0x21)
#define HID_USAGE_LED_COVERAGE ((USAGE) 0x22)
#define HID_USAGE_LED_NIGHT_MODE ((USAGE) 0x23)
#define HID_USAGE_LED_SEND_CALLS ((USAGE) 0x24)
#define HID_USAGE_LED_CALL_PICKUP ((USAGE) 0x25)
#define HID_USAGE_LED_CONFERENCE ((USAGE) 0x26)
#define HID_USAGE_LED_STAND_BY ((USAGE) 0x27)
#define HID_USAGE_LED_CAMERA_ON ((USAGE) 0x28)
#define HID_USAGE_LED_CAMERA_OFF ((USAGE) 0x29)
#define HID_USAGE_LED_ON_LINE ((USAGE) 0x2A)
#define HID_USAGE_LED_OFF_LINE ((USAGE) 0x2B)
#define HID_USAGE_LED_BUSY ((USAGE) 0x2C)
#define HID_USAGE_LED_READY ((USAGE) 0x2D)
#define HID_USAGE_LED_PAPER_OUT ((USAGE) 0x2E)
#define HID_USAGE_LED_PAPER_JAM ((USAGE) 0x2F)
#define HID_USAGE_LED_REMOTE ((USAGE) 0x30)
#define HID_USAGE_LED_FORWARD ((USAGE) 0x31)
#define HID_USAGE_LED_REVERSE ((USAGE) 0x32)
#define HID_USAGE_LED_STOP ((USAGE) 0x33)
#define HID_USAGE_LED_REWIND ((USAGE) 0x34)
#define HID_USAGE_LED_FAST_FORWARD ((USAGE) 0x35)
#define HID_USAGE_LED_PLAY ((USAGE) 0x36)
#define HID_USAGE_LED_PAUSE ((USAGE) 0x37)
#define HID_USAGE_LED_RECORD ((USAGE) 0x38)
#define HID_USAGE_LED_ERROR ((USAGE) 0x39)
#define HID_USAGE_LED_SELECTED_INDICATOR ((USAGE) 0x3A)
#define HID_USAGE_LED_IN_USE_INDICATOR ((USAGE) 0x3B)
#define HID_USAGE_LED_MULTI_MODE_INDICATOR ((USAGE) 0x3C)
#define HID_USAGE_LED_INDICATOR_ON ((USAGE) 0x3D)
#define HID_USAGE_LED_INDICATOR_FLASH ((USAGE) 0x3E)
#define HID_USAGE_LED_INDICATOR_SLOW_BLINK ((USAGE) 0x3F)
#define HID_USAGE_LED_INDICATOR_FAST_BLINK ((USAGE) 0x40)
#define HID_USAGE_LED_INDICATOR_OFF ((USAGE) 0x41)
#define HID_USAGE_LED_FLASH_ON_TIME ((USAGE) 0x42)
#define HID_USAGE_LED_SLOW_BLINK_ON_TIME ((USAGE) 0x43)
#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME ((USAGE) 0x44)
#define HID_USAGE_LED_FAST_BLINK_ON_TIME ((USAGE) 0x45)
#define HID_USAGE_LED_FAST_BLINK_OFF_TIME ((USAGE) 0x46)
#define HID_USAGE_LED_INDICATOR_COLOR ((USAGE) 0x47)
#define HID_USAGE_LED_RED ((USAGE) 0x48)
#define HID_USAGE_LED_GREEN ((USAGE) 0x49)
#define HID_USAGE_LED_AMBER ((USAGE) 0x4A)
#define HID_USAGE_LED_GENERIC_INDICATOR ((USAGE) 0x3B)
#define HID_USAGE_LED_NUM_LOCK ((USAGE)0x01)
#define HID_USAGE_LED_CAPS_LOCK ((USAGE)0x02)
#define HID_USAGE_LED_SCROLL_LOCK ((USAGE)0x03)
#define HID_USAGE_LED_COMPOSE ((USAGE)0x04)
#define HID_USAGE_LED_KANA ((USAGE)0x05)
#define HID_USAGE_LED_POWER ((USAGE)0x06)
#define HID_USAGE_LED_SHIFT ((USAGE)0x07)
#define HID_USAGE_LED_DO_NOT_DISTURB ((USAGE)0x08)
#define HID_USAGE_LED_MUTE ((USAGE)0x09)
#define HID_USAGE_LED_TONE_ENABLE ((USAGE)0x0A)
#define HID_USAGE_LED_HIGH_CUT_FILTER ((USAGE)0x0B)
#define HID_USAGE_LED_LOW_CUT_FILTER ((USAGE)0x0C)
#define HID_USAGE_LED_EQUALIZER_ENABLE ((USAGE)0x0D)
#define HID_USAGE_LED_SOUND_FIELD_ON ((USAGE)0x0E)
#define HID_USAGE_LED_SURROUND_FIELD_ON ((USAGE)0x0F)
#define HID_USAGE_LED_REPEAT ((USAGE)0x10)
#define HID_USAGE_LED_STEREO ((USAGE)0x11)
#define HID_USAGE_LED_SAMPLING_RATE_DETECT ((USAGE)0x12)
#define HID_USAGE_LED_SPINNING ((USAGE)0x13)
#define HID_USAGE_LED_CAV ((USAGE)0x14)
#define HID_USAGE_LED_CLV ((USAGE)0x15)
#define HID_USAGE_LED_RECORDING_FORMAT_DET ((USAGE)0x16)
#define HID_USAGE_LED_OFF_HOOK ((USAGE)0x17)
#define HID_USAGE_LED_RING ((USAGE)0x18)
#define HID_USAGE_LED_MESSAGE_WAITING ((USAGE)0x19)
#define HID_USAGE_LED_DATA_MODE ((USAGE)0x1A)
#define HID_USAGE_LED_BATTERY_OPERATION ((USAGE)0x1B)
#define HID_USAGE_LED_BATTERY_OK ((USAGE)0x1C)
#define HID_USAGE_LED_BATTERY_LOW ((USAGE)0x1D)
#define HID_USAGE_LED_SPEAKER ((USAGE)0x1E)
#define HID_USAGE_LED_HEAD_SET ((USAGE)0x1F)
#define HID_USAGE_LED_HOLD ((USAGE)0x20)
#define HID_USAGE_LED_MICROPHONE ((USAGE)0x21)
#define HID_USAGE_LED_COVERAGE ((USAGE)0x22)
#define HID_USAGE_LED_NIGHT_MODE ((USAGE)0x23)
#define HID_USAGE_LED_SEND_CALLS ((USAGE)0x24)
#define HID_USAGE_LED_CALL_PICKUP ((USAGE)0x25)
#define HID_USAGE_LED_CONFERENCE ((USAGE)0x26)
#define HID_USAGE_LED_STAND_BY ((USAGE)0x27)
#define HID_USAGE_LED_CAMERA_ON ((USAGE)0x28)
#define HID_USAGE_LED_CAMERA_OFF ((USAGE)0x29)
#define HID_USAGE_LED_ON_LINE ((USAGE)0x2A)
#define HID_USAGE_LED_OFF_LINE ((USAGE)0x2B)
#define HID_USAGE_LED_BUSY ((USAGE)0x2C)
#define HID_USAGE_LED_READY ((USAGE)0x2D)
#define HID_USAGE_LED_PAPER_OUT ((USAGE)0x2E)
#define HID_USAGE_LED_PAPER_JAM ((USAGE)0x2F)
#define HID_USAGE_LED_REMOTE ((USAGE)0x30)
#define HID_USAGE_LED_FORWARD ((USAGE)0x31)
#define HID_USAGE_LED_REVERSE ((USAGE)0x32)
#define HID_USAGE_LED_STOP ((USAGE)0x33)
#define HID_USAGE_LED_REWIND ((USAGE)0x34)
#define HID_USAGE_LED_FAST_FORWARD ((USAGE)0x35)
#define HID_USAGE_LED_PLAY ((USAGE)0x36)
#define HID_USAGE_LED_PAUSE ((USAGE)0x37)
#define HID_USAGE_LED_RECORD ((USAGE)0x38)
#define HID_USAGE_LED_ERROR ((USAGE)0x39)
#define HID_USAGE_LED_SELECTED_INDICATOR ((USAGE)0x3A)
#define HID_USAGE_LED_IN_USE_INDICATOR ((USAGE)0x3B)
#define HID_USAGE_LED_MULTI_MODE_INDICATOR ((USAGE)0x3C)
#define HID_USAGE_LED_INDICATOR_ON ((USAGE)0x3D)
#define HID_USAGE_LED_INDICATOR_FLASH ((USAGE)0x3E)
#define HID_USAGE_LED_INDICATOR_SLOW_BLINK ((USAGE)0x3F)
#define HID_USAGE_LED_INDICATOR_FAST_BLINK ((USAGE)0x40)
#define HID_USAGE_LED_INDICATOR_OFF ((USAGE)0x41)
#define HID_USAGE_LED_FLASH_ON_TIME ((USAGE)0x42)
#define HID_USAGE_LED_SLOW_BLINK_ON_TIME ((USAGE)0x43)
#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME ((USAGE)0x44)
#define HID_USAGE_LED_FAST_BLINK_ON_TIME ((USAGE)0x45)
#define HID_USAGE_LED_FAST_BLINK_OFF_TIME ((USAGE)0x46)
#define HID_USAGE_LED_INDICATOR_COLOR ((USAGE)0x47)
#define HID_USAGE_LED_RED ((USAGE)0x48)
#define HID_USAGE_LED_GREEN ((USAGE)0x49)
#define HID_USAGE_LED_AMBER ((USAGE)0x4A)
#define HID_USAGE_LED_GENERIC_INDICATOR ((USAGE)0x3B)
//
// Button Page (0x09)
@ -242,13 +242,13 @@ typedef USHORT USAGE, *PUSAGE;
// Telephony Device Page (0x0B)
//
#define HID_USAGE_TELEPHONY_PHONE ((USAGE) 0x01)
#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE ((USAGE) 0x02)
#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS ((USAGE) 0x03)
#define HID_USAGE_TELEPHONY_HANDSET ((USAGE) 0x04)
#define HID_USAGE_TELEPHONY_HEADSET ((USAGE) 0x05)
#define HID_USAGE_TELEPHONY_KEYPAD ((USAGE) 0x06)
#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON ((USAGE) 0x07)
#define HID_USAGE_TELEPHONY_PHONE ((USAGE)0x01)
#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE ((USAGE)0x02)
#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS ((USAGE)0x03)
#define HID_USAGE_TELEPHONY_HANDSET ((USAGE)0x04)
#define HID_USAGE_TELEPHONY_HEADSET ((USAGE)0x05)
#define HID_USAGE_TELEPHONY_KEYPAD ((USAGE)0x06)
#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON ((USAGE)0x07)
// BUGBUG defined in ntstatus.h
#ifndef FACILITY_HID_ERROR_CODE
@ -256,190 +256,198 @@ typedef USHORT USAGE, *PUSAGE;
#endif
#define HIDP_ERROR_CODES(SEV, CODE) \
((NTSTATUS)(((SEV) << 28) | (FACILITY_HID_ERROR_CODE << 16) | (CODE)))
((NTSTATUS)(((SEV) << 28) | (FACILITY_HID_ERROR_CODE << 16) | (CODE)))
#define HIDP_STATUS_SUCCESS (HIDP_ERROR_CODES(0x0,0))
#define HIDP_STATUS_NULL (HIDP_ERROR_CODES(0x8,1))
#define HIDP_STATUS_INVALID_PREPARSED_DATA (HIDP_ERROR_CODES(0xC,1))
#define HIDP_STATUS_INVALID_REPORT_TYPE (HIDP_ERROR_CODES(0xC,2))
#define HIDP_STATUS_INVALID_REPORT_LENGTH (HIDP_ERROR_CODES(0xC,3))
#define HIDP_STATUS_USAGE_NOT_FOUND (HIDP_ERROR_CODES(0xC,4))
#define HIDP_STATUS_VALUE_OUT_OF_RANGE (HIDP_ERROR_CODES(0xC,5))
#define HIDP_STATUS_BAD_LOG_PHY_VALUES (HIDP_ERROR_CODES(0xC,6))
#define HIDP_STATUS_BUFFER_TOO_SMALL (HIDP_ERROR_CODES(0xC,7))
#define HIDP_STATUS_INTERNAL_ERROR (HIDP_ERROR_CODES(0xC,8))
#define HIDP_STATUS_I8242_TRANS_UNKNOWN (HIDP_ERROR_CODES(0xC,9))
#define HIDP_STATUS_INCOMPATIBLE_REPORT_ID (HIDP_ERROR_CODES(0xC,0xA))
#define HIDP_STATUS_NOT_VALUE_ARRAY (HIDP_ERROR_CODES(0xC,0xB))
#define HIDP_STATUS_IS_VALUE_ARRAY (HIDP_ERROR_CODES(0xC,0xC))
#define HIDP_STATUS_DATA_INDEX_NOT_FOUND (HIDP_ERROR_CODES(0xC,0xD))
#define HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE (HIDP_ERROR_CODES(0xC,0xE))
#define HIDP_STATUS_BUTTON_NOT_PRESSED (HIDP_ERROR_CODES(0xC,0xF))
#define HIDP_STATUS_REPORT_DOES_NOT_EXIST (HIDP_ERROR_CODES(0xC,0x10))
#define HIDP_STATUS_NOT_IMPLEMENTED (HIDP_ERROR_CODES(0xC,0x20))
#define HIDP_STATUS_SUCCESS (HIDP_ERROR_CODES(0x0, 0))
#define HIDP_STATUS_NULL (HIDP_ERROR_CODES(0x8, 1))
#define HIDP_STATUS_INVALID_PREPARSED_DATA (HIDP_ERROR_CODES(0xC, 1))
#define HIDP_STATUS_INVALID_REPORT_TYPE (HIDP_ERROR_CODES(0xC, 2))
#define HIDP_STATUS_INVALID_REPORT_LENGTH (HIDP_ERROR_CODES(0xC, 3))
#define HIDP_STATUS_USAGE_NOT_FOUND (HIDP_ERROR_CODES(0xC, 4))
#define HIDP_STATUS_VALUE_OUT_OF_RANGE (HIDP_ERROR_CODES(0xC, 5))
#define HIDP_STATUS_BAD_LOG_PHY_VALUES (HIDP_ERROR_CODES(0xC, 6))
#define HIDP_STATUS_BUFFER_TOO_SMALL (HIDP_ERROR_CODES(0xC, 7))
#define HIDP_STATUS_INTERNAL_ERROR (HIDP_ERROR_CODES(0xC, 8))
#define HIDP_STATUS_I8242_TRANS_UNKNOWN (HIDP_ERROR_CODES(0xC, 9))
#define HIDP_STATUS_INCOMPATIBLE_REPORT_ID (HIDP_ERROR_CODES(0xC, 0xA))
#define HIDP_STATUS_NOT_VALUE_ARRAY (HIDP_ERROR_CODES(0xC, 0xB))
#define HIDP_STATUS_IS_VALUE_ARRAY (HIDP_ERROR_CODES(0xC, 0xC))
#define HIDP_STATUS_DATA_INDEX_NOT_FOUND (HIDP_ERROR_CODES(0xC, 0xD))
#define HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE (HIDP_ERROR_CODES(0xC, 0xE))
#define HIDP_STATUS_BUTTON_NOT_PRESSED (HIDP_ERROR_CODES(0xC, 0xF))
#define HIDP_STATUS_REPORT_DOES_NOT_EXIST (HIDP_ERROR_CODES(0xC, 0x10))
#define HIDP_STATUS_NOT_IMPLEMENTED (HIDP_ERROR_CODES(0xC, 0x20))
typedef enum _HIDP_REPORT_TYPE
{
HidP_Input,
HidP_Output,
HidP_Feature
HidP_Input,
HidP_Output,
HidP_Feature
} HIDP_REPORT_TYPE;
typedef struct _USAGE_AND_PAGE
{
USAGE Usage;
USAGE UsagePage;
USAGE Usage;
USAGE UsagePage;
} USAGE_AND_PAGE, *PUSAGE_AND_PAGE;
typedef struct _HIDP_BUTTON_CAPS
{
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USHORT BitField;
USHORT LinkCollection; // A unique internal index pointer
USHORT BitField;
USHORT LinkCollection; // A unique internal index pointer
USAGE LinkUsage;
USAGE LinkUsagePage;
USAGE LinkUsage;
USAGE LinkUsagePage;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
ULONG Reserved[10];
union {
struct {
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
struct {
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
};
ULONG Reserved[10];
union
{
struct
{
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
struct
{
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
};
} HIDP_BUTTON_CAPS, *PHIDP_BUTTON_CAPS;
typedef struct _HIDP_VALUE_CAPS
{
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USHORT BitField;
USHORT LinkCollection; // A unique internal index pointer
USHORT BitField;
USHORT LinkCollection; // A unique internal index pointer
USAGE LinkUsage;
USAGE LinkUsagePage;
USAGE LinkUsage;
USAGE LinkUsagePage;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
BOOLEAN HasNull; // Does this channel have a null report union
UCHAR Reserved;
USHORT BitSize; // How many bits are devoted to this value?
BOOLEAN HasNull; // Does this channel have a null report union
UCHAR Reserved;
USHORT BitSize; // How many bits are devoted to this value?
USHORT ReportCount; // See Note below. Usually set to 1.
USHORT Reserved2[5];
USHORT ReportCount; // See Note below. Usually set to 1.
USHORT Reserved2[5];
ULONG UnitsExp;
ULONG Units;
ULONG UnitsExp;
ULONG Units;
LONG LogicalMin, LogicalMax;
LONG PhysicalMin, PhysicalMax;
LONG LogicalMin, LogicalMax;
LONG PhysicalMin, PhysicalMax;
union {
struct {
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
union
{
struct
{
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
struct {
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
};
struct
{
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
};
} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
typedef struct _HIDD_ATTRIBUTES {
ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES)
typedef struct _HIDD_ATTRIBUTES
{
ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES)
//
// Vendor ids of this hid device
//
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
//
// Vendor ids of this hid device
//
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
//
// Additional fields will be added to the end of this structure.
//
//
// Additional fields will be added to the end of this structure.
//
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
typedef PUCHAR PHIDP_REPORT_DESCRIPTOR;
typedef struct _HIDP_PREPARSED_DATA * PHIDP_PREPARSED_DATA;
typedef PUCHAR PHIDP_REPORT_DESCRIPTOR;
typedef struct _HIDP_PREPARSED_DATA* PHIDP_PREPARSED_DATA;
typedef struct _HIDP_CAPS
{
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT NumberLinkCollectionNodes;
USHORT NumberLinkCollectionNodes;
USHORT NumberInputButtonCaps;
USHORT NumberInputValueCaps;
USHORT NumberInputDataIndices;
USHORT NumberInputButtonCaps;
USHORT NumberInputValueCaps;
USHORT NumberInputDataIndices;
USHORT NumberOutputButtonCaps;
USHORT NumberOutputValueCaps;
USHORT NumberOutputDataIndices;
USHORT NumberOutputButtonCaps;
USHORT NumberOutputValueCaps;
USHORT NumberOutputDataIndices;
USHORT NumberFeatureButtonCaps;
USHORT NumberFeatureValueCaps;
USHORT NumberFeatureDataIndices;
USHORT NumberFeatureButtonCaps;
USHORT NumberFeatureValueCaps;
USHORT NumberFeatureDataIndices;
} HIDP_CAPS, *PHIDP_CAPS;
typedef struct _HIDP_DATA
{
USHORT DataIndex;
USHORT Reserved;
union {
ULONG RawValue; // for values
BOOLEAN On; // for buttons MUST BE TRUE for buttons.
};
USHORT DataIndex;
USHORT Reserved;
union
{
ULONG RawValue; // for values
BOOLEAN On; // for buttons MUST BE TRUE for buttons.
};
} HIDP_DATA, *PHIDP_DATA;
typedef BOOLEAN(__stdcall *_HidD_GetAttributes) (HANDLE HidDeviceObject, HIDD_ATTRIBUTES *Attributes);
typedef void(__stdcall *_HidD_GetHidGuid) (GUID* HidGuid);
typedef BOOLEAN(__stdcall *_HidD_GetPreparsedData) (HANDLE HidDeviceObject, PHIDP_PREPARSED_DATA *PreparsedData);
typedef NTSTATUS(__stdcall *_HidP_GetCaps) (PHIDP_PREPARSED_DATA PreparsedData, HIDP_CAPS *caps);
typedef BOOLEAN(__stdcall *_HidD_FreePreparsedData) (PHIDP_PREPARSED_DATA PreparsedData);
typedef BOOLEAN(__stdcall *_HidD_GetFeature) (HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength);
typedef BOOLEAN(__stdcall *_HidD_SetFeature) (HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength);
typedef NTSTATUS(__stdcall *_HidP_GetSpecificButtonCaps) (HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PHIDP_BUTTON_CAPS ButtonCaps, PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall *_HidP_GetButtonCaps)(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps, PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall *_HidP_GetUsages)(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE *UsageList, ULONG *UsageLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
typedef NTSTATUS(__stdcall *_HidP_GetValueCaps)(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall *_HidP_GetUsageValue)(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
typedef BOOLEAN (__stdcall *_HidD_GetProductString)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength);
typedef BOOLEAN(__stdcall* _HidD_GetAttributes)(HANDLE HidDeviceObject, HIDD_ATTRIBUTES* Attributes);
typedef void(__stdcall* _HidD_GetHidGuid)(GUID* HidGuid);
typedef BOOLEAN(__stdcall* _HidD_GetPreparsedData)(HANDLE HidDeviceObject, PHIDP_PREPARSED_DATA* PreparsedData);
typedef NTSTATUS(__stdcall* _HidP_GetCaps)(PHIDP_PREPARSED_DATA PreparsedData, HIDP_CAPS* caps);
typedef BOOLEAN(__stdcall* _HidD_FreePreparsedData)(PHIDP_PREPARSED_DATA PreparsedData);
typedef BOOLEAN(__stdcall* _HidD_GetFeature)(HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength);
typedef BOOLEAN(__stdcall* _HidD_SetFeature)(HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength);
typedef NTSTATUS(__stdcall* _HidP_GetSpecificButtonCaps)(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PHIDP_BUTTON_CAPS ButtonCaps, PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall* _HidP_GetButtonCaps)(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps, PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall* _HidP_GetUsages)(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE* UsageList, ULONG* UsageLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
typedef NTSTATUS(__stdcall* _HidP_GetValueCaps)(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall* _HidP_GetUsageValue)(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
typedef BOOLEAN(__stdcall* _HidD_GetProductString)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength);
//#define HidP_GetButtonCaps(_Type_, _Caps_, _Len_, _Data_) \
// HidP_GetSpecificButtonCaps(_Type_, 0, 0, 0, _Caps_, _Len_, _Data_)

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,7 @@
#ifdef _WIN32
// VC6 "identifier was truncated to '255' characters in the debug information"
#if defined(_MSC_VER) && (_MSC_VER >= 1200) && (_MSC_VER < 1300)
#pragma warning(disable: 4786)
#pragma warning(disable : 4786)
#endif
// Prevent compile time warnings for deprecation
#define _CRT_SECURE_NO_DEPRECATE
@ -63,208 +63,221 @@
#include <wchar.h>
#include <algorithm>
#define INI_TOKEN_A_ANSI "\a" // I.E. Item1;Item2;Item3 - '\a' used in place of ';'
#define INI_TOKEN_B_ANSI "\b" // I.E. Item1,Item1b;Item2,Item2b;Item3,Item3b - '\b' used in place of ','
#define INI_EMPTY_ANSI "*" // Used to indicate empty value in token string. I.E. *;Item2;*;Item3;
#define INI_TOKEN_A_ANSI "\a" // I.E. Item1;Item2;Item3 - '\a' used in place of ';'
#define INI_TOKEN_B_ANSI "\b" // I.E. Item1,Item1b;Item2,Item2b;Item3,Item3b - '\b' used in place of ','
#define INI_EMPTY_ANSI "*" // Used to indicate empty value in token string. I.E. *;Item2;*;Item3;
class CIniFileA
{
public:
static const char* const LF;
public:
CIniFileA();
~CIniFileA();
// Used to save the data back to the file or your choice
bool Save( const std::string& fileName );
// Save data to an output stream
void Save( std::ostream& output );
// Loads the Reads the data in the ini file into the IniFile object
bool Load( const std::string& fileName , bool bMerge = false );
// Load data from an input stream
void Load( std::istream& input , bool bMerge = false );
static const char* const LF;
public:
class CIniMergeA
{
public:
explicit CIniMergeA(CIniFileA& ini):_ini(ini) {}
std::istream &operator()(std::istream& input) const
{
_ini.Load( input , true );
return input;
}
private:
CIniFileA& _ini;
};
CIniFileA();
~CIniFileA();
// Used to save the data back to the file or your choice
bool Save(const std::string& fileName);
// Save data to an output stream
void Save(std::ostream& output);
// Loads the Reads the data in the ini file into the IniFile object
bool Load(const std::string& fileName, bool bMerge = false);
// Load data from an input stream
void Load(std::istream& input, bool bMerge = false);
public:
class CIniMergeA
{
public:
explicit CIniMergeA(CIniFileA& ini)
: _ini(ini)
{
}
std::istream& operator()(std::istream& input) const
{
_ini.Load(input, true);
return input;
}
private:
CIniFileA& _ini;
};
public:
#ifdef _WIN32
// Added for versions earlier than VS2008
// Added for versions earlier than VS2008
#if defined(_MSC_VER) && (_MSC_VER <= 1400)
struct ci_less_a;
struct ci_less_a;
#endif
#endif
class CIniSectionA
{
friend class CIniFileA; // Allow CIniFileA to create sections
class CIniSectionA
{
friend class CIniFileA; // Allow CIniFileA to create sections
#ifdef _WIN32
// Added for versions earlier than VS2008
// Added for versions earlier than VS2008
#if defined(_MSC_VER) && (_MSC_VER <= 1400)
friend struct ci_less_a;
friend struct ci_less_a;
#endif
#endif
public:
public:
#ifdef _WIN32
// Added for versions earlier than VS2008
// Added for versions earlier than VS2008
#if defined(_MSC_VER) && (_MSC_VER <= 1400)
struct ci_less_a;
struct ci_less_a;
#endif
#endif
class CIniKeyA
{
friend class CIniSectionA; // Allow CIniSectionA to create keys
class CIniKeyA
{
friend class CIniSectionA; // Allow CIniSectionA to create keys
#ifdef _WIN32
// Added for versions earlier than VS2008
// Added for versions earlier than VS2008
#if defined(_MSC_VER) && (_MSC_VER <= 1400)
friend struct ci_less_a;
friend struct ci_less_a;
#endif
#endif
private: // CIniFileA acts as a class factory for CIniSectionA Objects
CIniKeyA( CIniSectionA* pSection , const std::string& sKeyName );
CIniKeyA( const CIniKeyA& ); // No Copy
CIniKeyA& operator=(const CIniKeyA&); // No Copy
~CIniKeyA( );
public:
// Sets the value of the key
void SetValue( const std::string& sValue );
// Returns the value of the key
std::string GetValue() const;
// Sets the key name, returns true on success, fails if the section
// name sKeyName already exists
bool SetKeyName( std::string sKeyName );
// Returns the name of the Key
std::string GetKeyName() const;
private:
// Pointer to the parent CIniSectionA
CIniSectionA* m_pSection;
// Name of the Key
std::string m_sKeyName;
// Value associated
std::string m_sValue;
}; // End of CIniKeyA
// Typedef of set of CIniKeyA pointers
struct ci_less_a
{
bool operator() (const CIniKeyA* s1, const CIniKeyA* s2) const
{
private: // CIniFileA acts as a class factory for CIniSectionA Objects
CIniKeyA(CIniSectionA* pSection, const std::string& sKeyName);
CIniKeyA(const CIniKeyA&); // No Copy
CIniKeyA& operator=(const CIniKeyA&); // No Copy
~CIniKeyA();
public:
// Sets the value of the key
void SetValue(const std::string& sValue);
// Returns the value of the key
std::string GetValue() const;
// Sets the key name, returns true on success, fails if the section
// name sKeyName already exists
bool SetKeyName(std::string sKeyName);
// Returns the name of the Key
std::string GetKeyName() const;
private:
// Pointer to the parent CIniSectionA
CIniSectionA* m_pSection;
// Name of the Key
std::string m_sKeyName;
// Value associated
std::string m_sValue;
}; // End of CIniKeyA
// Typedef of set of CIniKeyA pointers
struct ci_less_a
{
bool operator()(const CIniKeyA* s1, const CIniKeyA* s2) const
{
#ifndef _WIN32
return strcasecmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
return strcasecmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
#else
return _stricmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
return _stricmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
#endif
}
};
}
};
typedef std::set<CIniKeyA*,ci_less_a> KeyIndexA;
typedef std::set<CIniKeyA*, ci_less_a> KeyIndexA;
#ifdef _WIN32
// Added for VC6 Support
// Added for VC6 Support
#if defined(_MSC_VER) && (_MSC_VER >= 1200) && (_MSC_VER < 1300)
friend class CIniKeyA;
friend class CIniKeyA;
#endif
#endif
private: // CIniSectionA acts as a class factory for CIniKeyA Objects
CIniSectionA( CIniFileA* pIniFile , const std::string& sSectionName );
CIniSectionA( const CIniSectionA& ); // No Copy
CIniSectionA& operator=(const CIniSectionA&); // No Copy
~CIniSectionA( );
public:
// Adds a key to the CIniSectionA object, returns a CIniKeyA pointer to the new or existing object
CIniKeyA* AddKey( std::string sKeyName );
// Removes a single key by pointer
void RemoveKey( CIniKeyA* pKey );
// Removes a single key by string
void RemoveKey( std::string sKey );
// Removes all the keys in the section
void RemoveAllKeys( );
// Returns a CIniKeyA pointer to the key by name, NULL if it was not found
CIniKeyA* GetKey( std::string sKeyName ) const;
// Returns all keys in the section by KeyIndex only to be used for enumeration
const KeyIndexA& GetKeys() const;
// Returns a KeyValue at a certain section
std::string GetKeyValue( std::string sKey ) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue( std::string sKey, const std::string& sValue );
// Sets the section name, returns true on success, fails if the section
// name sSectionName already exists
bool SetSectionName( std::string sSectionName );
// Returns the section name
std::string GetSectionName() const;
private:
KeyIndexA::const_iterator _find_key( const std::string& sKeyName ) const;
KeyIndexA::iterator _find_key( const std::string& sKeyName );
private:
// CIniFileA pointer back to the object that instanciated the section
CIniFileA* m_pIniFile;
// Name of the section
std::string m_sSectionName;
// List of CIniKeyA pointers ( Keys in the section )
KeyIndexA m_keys;
}; // End of CIniSectionA
// Typedef of a List of CIniSectionA pointers
struct ci_less_a
{
bool operator() (const CIniSectionA* s1, const CIniSectionA* s2) const
{
private: // CIniSectionA acts as a class factory for CIniKeyA Objects
CIniSectionA(CIniFileA* pIniFile, const std::string& sSectionName);
CIniSectionA(const CIniSectionA&); // No Copy
CIniSectionA& operator=(const CIniSectionA&); // No Copy
~CIniSectionA();
public:
// Adds a key to the CIniSectionA object, returns a CIniKeyA pointer to the new or existing object
CIniKeyA* AddKey(std::string sKeyName);
// Removes a single key by pointer
void RemoveKey(CIniKeyA* pKey);
// Removes a single key by string
void RemoveKey(std::string sKey);
// Removes all the keys in the section
void RemoveAllKeys();
// Returns a CIniKeyA pointer to the key by name, NULL if it was not found
CIniKeyA* GetKey(std::string sKeyName) const;
// Returns all keys in the section by KeyIndex only to be used for enumeration
const KeyIndexA& GetKeys() const;
// Returns a KeyValue at a certain section
std::string GetKeyValue(std::string sKey) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue(std::string sKey, const std::string& sValue);
// Sets the section name, returns true on success, fails if the section
// name sSectionName already exists
bool SetSectionName(std::string sSectionName);
// Returns the section name
std::string GetSectionName() const;
private:
KeyIndexA::const_iterator _find_key(const std::string& sKeyName) const;
KeyIndexA::iterator _find_key(const std::string& sKeyName);
private:
// CIniFileA pointer back to the object that instanciated the section
CIniFileA* m_pIniFile;
// Name of the section
std::string m_sSectionName;
// List of CIniKeyA pointers ( Keys in the section )
KeyIndexA m_keys;
}; // End of CIniSectionA
// Typedef of a List of CIniSectionA pointers
struct ci_less_a
{
bool operator()(const CIniSectionA* s1, const CIniSectionA* s2) const
{
#ifndef _WIN32
return strcasecmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
return strcasecmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
#else
return _stricmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
return _stricmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
#endif
}
};
}
};
typedef std::set<CIniSectionA*,ci_less_a> SecIndexA;
typedef std::set<CIniSectionA*, ci_less_a> SecIndexA;
#ifdef _WIN32
// Added for VC6 Support
// Added for VC6 Support
#if defined(_MSC_VER) && (_MSC_VER >= 1200) && (_MSC_VER < 1300)
friend class CIniSectionA;
friend class CIniSectionA;
#endif
#endif
public:
// Adds a section to the CIniFileA object, returns a CIniFileA pointer to the new or existing object
CIniSectionA* AddSection( std::string sSection );
// Removes section by pointer
void RemoveSection( CIniSectionA* pSection );
// Removes a section by its name sSection
void RemoveSection( std::string sSection );
// Removes all existing sections
void RemoveAllSections( );
// Returns a CIniSectionA* to the section by name, NULL if it was not found
CIniSectionA* GetSection( std::string sSection ) const;
// Returns all sections in the inifile by SecIndex, only to be used for enumeration (DO NOT KEEP THE REF OR TRY TO DELETE STUFF!)
const SecIndexA& GetSections() const;
// Returns a KeyValue at a certain section
std::string GetKeyValue( const std::string& sSection, const std::string& sKey ) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue( const std::string& sSection, const std::string& sKey, const std::string& sValue );
// Renames an existing section returns true on success, false if the section didn't exist or there was another section with the same sNewSectionName
bool RenameSection( const std::string& sSectionName , const std::string& sNewSectionName );
// Renames an existing key returns true on success, false if the key didn't exist or there was another section with the same sNewSectionName
bool RenameKey( const std::string& sSectionName , const std::string& sKeyName , const std::string& sNewKeyName);
// Adds a section to the CIniFileA object, returns a CIniFileA pointer to the new or existing object
CIniSectionA* AddSection(std::string sSection);
// Removes section by pointer
void RemoveSection(CIniSectionA* pSection);
// Removes a section by its name sSection
void RemoveSection(std::string sSection);
// Removes all existing sections
void RemoveAllSections();
// Returns a CIniSectionA* to the section by name, NULL if it was not found
CIniSectionA* GetSection(std::string sSection) const;
// Returns all sections in the inifile by SecIndex, only to be used for enumeration (DO NOT KEEP THE REF OR TRY TO DELETE STUFF!)
const SecIndexA& GetSections() const;
// Returns a KeyValue at a certain section
std::string GetKeyValue(const std::string& sSection, const std::string& sKey) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue(const std::string& sSection, const std::string& sKey, const std::string& sValue);
// Renames an existing section returns true on success, false if the section didn't exist or there was another section with the same sNewSectionName
bool RenameSection(const std::string& sSectionName, const std::string& sNewSectionName);
// Renames an existing key returns true on success, false if the key didn't exist or there was another section with the same sNewSectionName
bool RenameKey(const std::string& sSectionName, const std::string& sKeyName, const std::string& sNewKeyName);
private:
SecIndexA::const_iterator _find_sec( const std::string& sSection ) const;
SecIndexA::iterator _find_sec( const std::string& sSection );
SecIndexA::const_iterator _find_sec(const std::string& sSection) const;
SecIndexA::iterator _find_sec(const std::string& sSection);
private:
CIniFileA( const CIniFileA&); // No Copy
CIniFileA& operator=(const CIniFileA&); // No Copy
// List of CIniSectionA pointers ( List of sections in the class )
SecIndexA m_sections;
CIniFileA(const CIniFileA&); // No Copy
CIniFileA& operator=(const CIniFileA&); // No Copy
// List of CIniSectionA pointers ( List of sections in the class )
SecIndexA m_sections;
}; // End of CIniFileA
// Basic typedefs for ease of use
@ -287,207 +300,220 @@ std::istream& operator>>(std::istream& input, CIniMergeA merger);
// Unicode Class Definition
#define INI_TOKEN_A_UNICODE L"\a" // I.E. Item1;Item2;Item3 - '\a' used in place of ';'
#define INI_TOKEN_B_UNICODE L"\b" // I.E. Item1,Item1b;Item2,Item2b;Item3,Item3b - '\b' used in place of ','
#define INI_EMPTY_UNICODE L"*" // Used to indicate empty value in token string. I.E. *;Item2;*;Item3;
#define INI_TOKEN_A_UNICODE L"\a" // I.E. Item1;Item2;Item3 - '\a' used in place of ';'
#define INI_TOKEN_B_UNICODE L"\b" // I.E. Item1,Item1b;Item2,Item2b;Item3,Item3b - '\b' used in place of ','
#define INI_EMPTY_UNICODE L"*" // Used to indicate empty value in token string. I.E. *;Item2;*;Item3;
class CIniFileW
{
public:
static const wchar_t* const LF;
public:
CIniFileW();
~CIniFileW();
// Used to save the data back to the file or your choice
bool Save( const std::wstring& fileName );
// Save data to an output stream
void Save( std::wostream& output );
// Loads the Reads the data in the ini file into the IniFile object
bool Load( const std::wstring& fileName , bool bMerge = false );
// Load data from an input stream
void Load( std::wistream& input , bool bMerge = false );
static const wchar_t* const LF;
public:
class CIniMergeW
{
public:
explicit CIniMergeW(CIniFileW& ini):_ini(ini) {}
std::wistream &operator()(std::wistream& input) const
{
_ini.Load( input , true );
return input;
}
private:
CIniFileW& _ini;
};
CIniFileW();
~CIniFileW();
// Used to save the data back to the file or your choice
bool Save(const std::wstring& fileName);
// Save data to an output stream
void Save(std::wostream& output);
// Loads the Reads the data in the ini file into the IniFile object
bool Load(const std::wstring& fileName, bool bMerge = false);
// Load data from an input stream
void Load(std::wistream& input, bool bMerge = false);
public:
class CIniMergeW
{
public:
explicit CIniMergeW(CIniFileW& ini)
: _ini(ini)
{
}
std::wistream& operator()(std::wistream& input) const
{
_ini.Load(input, true);
return input;
}
private:
CIniFileW& _ini;
};
public:
#ifdef _WIN32
// Added for versions earlier than VS2008
// Added for versions earlier than VS2008
#if defined(_MSC_VER) && (_MSC_VER <= 1400)
struct ci_less_w;
struct ci_less_w;
#endif
#endif
class CIniSectionW
{
friend class CIniFileW; // Allow CIniFileW to create sections
class CIniSectionW
{
friend class CIniFileW; // Allow CIniFileW to create sections
#ifdef _WIN32
// Added for versions earlier than VS2008
// Added for versions earlier than VS2008
#if defined(_MSC_VER) && (_MSC_VER <= 1400)
friend struct ci_less_w;
friend struct ci_less_w;
#endif
#endif
public:
public:
#ifdef _WIN32
// Added for versions earlier than VS2008
// Added for versions earlier than VS2008
#if defined(_MSC_VER) && (_MSC_VER <= 1400)
struct ci_less_w;
struct ci_less_w;
#endif
#endif
class CIniKeyW
{
friend class CIniSectionW; // Allow CIniSectionW to create keys
class CIniKeyW
{
friend class CIniSectionW; // Allow CIniSectionW to create keys
#ifdef _WIN32
// Added for versions earlier than VS2008
// Added for versions earlier than VS2008
#if defined(_MSC_VER) && (_MSC_VER <= 1400)
friend struct ci_less_w;
friend struct ci_less_w;
#endif
#endif
private: // CIniFileW acts as a class factory for CIniSectionW Objects
CIniKeyW( CIniSectionW* pSection , const std::wstring& sKeyName );
CIniKeyW( const CIniKeyW& ); // No Copy
CIniKeyW& operator=(const CIniKeyW&); // No Copy
~CIniKeyW( );
public:
// Sets the value of the key
void SetValue( const std::wstring& sValue );
// Returns the value of the key
std::wstring GetValue() const;
// Sets the key name, returns true on success, fails if the section
// name sKeyName already exists
bool SetKeyName( std::wstring sKeyName );
// Returns the name of the Key
std::wstring GetKeyName() const;
private:
// Pointer to the parent CIniSectionW
CIniSectionW* m_pSection;
// Name of the Key
std::wstring m_sKeyName;
// Value associated
std::wstring m_sValue;
}; // End of CIniKeyW
// Typedef of set of CIniKeyW pointers
struct ci_less_w
{
bool operator() (const CIniKeyW* s1, const CIniKeyW* s2) const
{
private: // CIniFileW acts as a class factory for CIniSectionW Objects
CIniKeyW(CIniSectionW* pSection, const std::wstring& sKeyName);
CIniKeyW(const CIniKeyW&); // No Copy
CIniKeyW& operator=(const CIniKeyW&); // No Copy
~CIniKeyW();
public:
// Sets the value of the key
void SetValue(const std::wstring& sValue);
// Returns the value of the key
std::wstring GetValue() const;
// Sets the key name, returns true on success, fails if the section
// name sKeyName already exists
bool SetKeyName(std::wstring sKeyName);
// Returns the name of the Key
std::wstring GetKeyName() const;
private:
// Pointer to the parent CIniSectionW
CIniSectionW* m_pSection;
// Name of the Key
std::wstring m_sKeyName;
// Value associated
std::wstring m_sValue;
}; // End of CIniKeyW
// Typedef of set of CIniKeyW pointers
struct ci_less_w
{
bool operator()(const CIniKeyW* s1, const CIniKeyW* s2) const
{
#ifndef _WIN32
return wcscasecmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
return wcscasecmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
#else
return _wcsicmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
return _wcsicmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
#endif
}
};
}
};
typedef std::set<CIniKeyW*,ci_less_w> KeyIndexW;
typedef std::set<CIniKeyW*, ci_less_w> KeyIndexW;
#ifdef _WIN32
// Added for VC6 Support
// Added for VC6 Support
#if defined(_MSC_VER) && (_MSC_VER >= 1200) && (_MSC_VER < 1300)
friend class CIniKeyW;
friend class CIniKeyW;
#endif
#endif
private: // CIniSectionW acts as a class factory for CIniKeyW Objects
CIniSectionW( CIniFileW* pIniFile , const std::wstring& sSectionName );
CIniSectionW( const CIniSectionW& ); // No Copy
CIniSectionW& operator=(const CIniSectionW&); // No Copy
~CIniSectionW( );
public:
// Adds a key to the CIniSectionW object, returns a CIniKeyW pointer to the new or existing object
CIniKeyW* AddKey( std::wstring sKeyName );
// Removes a single key by pointer
void RemoveKey( CIniKeyW* pKey );
// Removes a single key by string
void RemoveKey( std::wstring sKey );
// Removes all the keys in the section
void RemoveAllKeys( );
// Returns a CIniKeyW pointer to the key by name, NULL if it was not found
CIniKeyW* GetKey( std::wstring sKeyName ) const;
// Returns all keys in the section by KeyIndex only to be used for enumeration
const KeyIndexW& GetKeys() const;
// Returns a KeyValue at a certain section
std::wstring GetKeyValue( std::wstring sKey ) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue( std::wstring sKey, const std::wstring& sValue );
// Sets the section name, returns true on success, fails if the section
// name sSectionName already exists
bool SetSectionName( std::wstring sSectionName );
// Returns the section name
std::wstring GetSectionName() const;
private:
KeyIndexW::const_iterator _find_key( const std::wstring& sKeyName ) const;
KeyIndexW::iterator _find_key( const std::wstring& sKeyName );
private:
// CIniFileW pointer back to the object that instanciated the section
CIniFileW* m_pIniFile;
// Name of the section
std::wstring m_sSectionName;
// List of CIniKeyW pointers ( Keys in the section )
KeyIndexW m_keys;
}; // End of CIniSectionW
// Typedef of a List of CIniSectionW pointers
struct ci_less_w
{
bool operator() (const CIniSectionW* s1, const CIniSectionW* s2) const
{
private: // CIniSectionW acts as a class factory for CIniKeyW Objects
CIniSectionW(CIniFileW* pIniFile, const std::wstring& sSectionName);
CIniSectionW(const CIniSectionW&); // No Copy
CIniSectionW& operator=(const CIniSectionW&); // No Copy
~CIniSectionW();
public:
// Adds a key to the CIniSectionW object, returns a CIniKeyW pointer to the new or existing object
CIniKeyW* AddKey(std::wstring sKeyName);
// Removes a single key by pointer
void RemoveKey(CIniKeyW* pKey);
// Removes a single key by string
void RemoveKey(std::wstring sKey);
// Removes all the keys in the section
void RemoveAllKeys();
// Returns a CIniKeyW pointer to the key by name, NULL if it was not found
CIniKeyW* GetKey(std::wstring sKeyName) const;
// Returns all keys in the section by KeyIndex only to be used for enumeration
const KeyIndexW& GetKeys() const;
// Returns a KeyValue at a certain section
std::wstring GetKeyValue(std::wstring sKey) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue(std::wstring sKey, const std::wstring& sValue);
// Sets the section name, returns true on success, fails if the section
// name sSectionName already exists
bool SetSectionName(std::wstring sSectionName);
// Returns the section name
std::wstring GetSectionName() const;
private:
KeyIndexW::const_iterator _find_key(const std::wstring& sKeyName) const;
KeyIndexW::iterator _find_key(const std::wstring& sKeyName);
private:
// CIniFileW pointer back to the object that instanciated the section
CIniFileW* m_pIniFile;
// Name of the section
std::wstring m_sSectionName;
// List of CIniKeyW pointers ( Keys in the section )
KeyIndexW m_keys;
}; // End of CIniSectionW
// Typedef of a List of CIniSectionW pointers
struct ci_less_w
{
bool operator()(const CIniSectionW* s1, const CIniSectionW* s2) const
{
#ifndef _WIN32
return wcscasecmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
return wcscasecmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
#else
return _wcsicmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
return _wcsicmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
#endif
}
};
}
};
typedef std::set<CIniSectionW*,ci_less_w> SecIndexW;
typedef std::set<CIniSectionW*, ci_less_w> SecIndexW;
#ifdef _WIN32
// Added for VC6 Support
// Added for VC6 Support
#if defined(_MSC_VER) && (_MSC_VER >= 1200) && (_MSC_VER < 1300)
friend class CIniSectionW;
friend class CIniSectionW;
#endif
#endif
public:
// Adds a section to the CIniFileW object, returns a CIniFileW pointer to the new or existing object
CIniSectionW* AddSection( std::wstring sSection );
// Removes section by pointer
void RemoveSection( CIniSectionW* pSection );
// Removes a section by its name sSection
void RemoveSection( std::wstring sSection );
// Removes all existing sections
void RemoveAllSections( );
// Returns a CIniSectionW* to the section by name, NULL if it was not found
CIniSectionW* GetSection( std::wstring sSection ) const;
// Returns all sections in the inifile by SecIndex, only to be used for enumeration (DO NOT KEEP THE REF OR TRY TO DELETE STUFF!)
const SecIndexW& GetSections() const;
// Returns a KeyValue at a certain section
std::wstring GetKeyValue( const std::wstring& sSection, const std::wstring& sKey ) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue( const std::wstring& sSection, const std::wstring& sKey, const std::wstring& sValue );
// Renames an existing section returns true on success, false if the section didn't exist or there was another section with the same sNewSectionName
bool RenameSection( const std::wstring& sSectionName , const std::wstring& sNewSectionName );
// Renames an existing key returns true on success, false if the key didn't exist or there was another section with the same sNewSectionName
bool RenameKey( const std::wstring& sSectionName , const std::wstring& sKeyName , const std::wstring& sNewKeyName);
// Adds a section to the CIniFileW object, returns a CIniFileW pointer to the new or existing object
CIniSectionW* AddSection(std::wstring sSection);
// Removes section by pointer
void RemoveSection(CIniSectionW* pSection);
// Removes a section by its name sSection
void RemoveSection(std::wstring sSection);
// Removes all existing sections
void RemoveAllSections();
// Returns a CIniSectionW* to the section by name, NULL if it was not found
CIniSectionW* GetSection(std::wstring sSection) const;
// Returns all sections in the inifile by SecIndex, only to be used for enumeration (DO NOT KEEP THE REF OR TRY TO DELETE STUFF!)
const SecIndexW& GetSections() const;
// Returns a KeyValue at a certain section
std::wstring GetKeyValue(const std::wstring& sSection, const std::wstring& sKey) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue(const std::wstring& sSection, const std::wstring& sKey, const std::wstring& sValue);
// Renames an existing section returns true on success, false if the section didn't exist or there was another section with the same sNewSectionName
bool RenameSection(const std::wstring& sSectionName, const std::wstring& sNewSectionName);
// Renames an existing key returns true on success, false if the key didn't exist or there was another section with the same sNewSectionName
bool RenameKey(const std::wstring& sSectionName, const std::wstring& sKeyName, const std::wstring& sNewKeyName);
private:
SecIndexW::const_iterator _find_sec( const std::wstring& sSection ) const;
SecIndexW::iterator _find_sec( const std::wstring& sSection );
SecIndexW::const_iterator _find_sec(const std::wstring& sSection) const;
SecIndexW::iterator _find_sec(const std::wstring& sSection);
private:
CIniFileW( const CIniFileW&); // No Copy
CIniFileW& operator=(const CIniFileW&); // No Copy
// List of CIniSectionW pointers ( List of sections in the class )
SecIndexW m_sections;
CIniFileW(const CIniFileW&); // No Copy
CIniFileW& operator=(const CIniFileW&); // No Copy
// List of CIniSectionW pointers ( List of sections in the class )
SecIndexW m_sections;
}; // End of CIniFileW
// Basic typedefs for ease of use
@ -542,4 +568,3 @@ std::wstring str_to_wstr(const std::string& arg);
std::string wstr_to_str(const std::wstring& arg);
#endif

View File

@ -21,237 +21,246 @@
extern HINSTANCE hInst;
namespace shared{ namespace rawinput{
static std::vector<ParseRawInputCB *> callbacks;
HWND msgWindow = nullptr;
WNDPROC eatenWndProc = nullptr;
HWND eatenWnd = nullptr;
HHOOK hHook = nullptr, hHookWnd = nullptr, hHookKB = nullptr;
bool skipInput = false;
void RegisterCallback(ParseRawInputCB *cb)
namespace shared
{
if (cb && std::find(callbacks.begin(), callbacks.end(), cb) == callbacks.end())
callbacks.push_back(cb);
}
void UnregisterCallback(ParseRawInputCB *cb)
{
auto it = std::find(callbacks.begin(), callbacks.end(), cb);
if (it != callbacks.end())
callbacks.erase(it);
}
static POINT origCursorPos;
static POINT center;
static bool cursorCaptured = false;
static void WindowResized(HWND hWnd)
{
RECT r;
GetWindowRect(hWnd, &r);
ClipCursor(&r);
center.x = (r.left + r.right) / 2;
center.y = (r.top + r.bottom) / 2;
SetCursorPos(center.x, center.y);
}
static void CursorCapture(HWND hWnd)
{
OSDebugOut(TEXT("Capture cursor\n"));
SetCapture(hWnd);
ShowCursor(0);
GetCursorPos(&origCursorPos);
RECT r;
GetWindowRect(hWnd, &r);
ClipCursor(&r);
center.x = (r.left + r.right) / 2;
center.y = (r.top + r.bottom) / 2;
SetCursorPos(center.x, center.y);
cursorCaptured = true;
}
static void CursorRelease()
{
OSDebugOut(TEXT("Release cursor\n"));
if (cursorCaptured)
namespace rawinput
{
ClipCursor(0);
ReleaseCapture();
ShowCursor(1);
SetCursorPos(origCursorPos.x, origCursorPos.y);
cursorCaptured = false;
}
}
static void ToggleCursor(HWND hWnd, RAWKEYBOARD &k)
{
static bool shiftDown = false;
static std::vector<ParseRawInputCB*> callbacks;
if (k.VKey == VK_SHIFT || k.VKey == VK_LSHIFT || k.VKey == VK_RSHIFT)
shiftDown = !(k.Flags & RI_KEY_BREAK);
HWND msgWindow = nullptr;
WNDPROC eatenWndProc = nullptr;
HWND eatenWnd = nullptr;
HHOOK hHook = nullptr, hHookWnd = nullptr, hHookKB = nullptr;
bool skipInput = false;
if (shiftDown && k.VKey == VK_F11 && !k.Flags)
{
if (!cursorCaptured)
CursorCapture(hWnd);
else
CursorRelease();
}
}
static int RegisterRaw(HWND hWnd)
{
msgWindow = hWnd;
RAWINPUTDEVICE Rid[4];
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = HID_USAGE_GENERIC_GAMEPAD;
Rid[0].dwFlags = hWnd ? RIDEV_INPUTSINK : RIDEV_REMOVE; // adds game pad
Rid[0].hwndTarget = hWnd;
Rid[1].usUsagePage = 0x01;
Rid[1].usUsage = HID_USAGE_GENERIC_JOYSTICK;
Rid[1].dwFlags = hWnd ? RIDEV_INPUTSINK : RIDEV_REMOVE; // adds joystick
Rid[1].hwndTarget = hWnd;
Rid[2].usUsagePage = 0x01;
Rid[2].usUsage = HID_USAGE_GENERIC_KEYBOARD;
Rid[2].dwFlags = hWnd ? RIDEV_INPUTSINK : RIDEV_REMOVE;// | RIDEV_NOLEGACY; // adds HID keyboard //and also !ignores legacy keyboard messages
Rid[2].hwndTarget = hWnd;
Rid[3].usUsagePage = 0x01;
Rid[3].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[3].dwFlags = hWnd ? RIDEV_INPUTSINK : RIDEV_REMOVE;
Rid[3].hwndTarget = hWnd;
if (RegisterRawInputDevices(Rid, countof(Rid), sizeof(Rid[0])) == FALSE) {
//registration failed. Call GetLastError for the cause of the error.
fprintf(stderr, "Could not (de)register raw input devices.\n");
return 0;
}
return 1;
}
static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_ACTIVATE:
OSDebugOut(TEXT("****** WM_ACTIVATE ****** %p %d\n"), hWnd, LOWORD(wParam) != WA_INACTIVE);
skipInput = LOWORD(wParam) == WA_INACTIVE;
break;
case WM_SETFOCUS:
OSDebugOut(TEXT("****** WM_SETFOCUS ****** %p\n"), hWnd);
skipInput = false;
break;
case WM_KILLFOCUS:
OSDebugOut(TEXT("****** WM_KILLFOCUS ****** %p\n"), hWnd);
skipInput = true;
break;
}
return 0;
}
static LRESULT CALLBACK RawInputProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PRAWINPUT pRawInput;
UINT bufferSize=0;
switch(uMsg) {
case WM_CREATE:
if (eatenWnd == nullptr)
RegisterRaw(hWnd);
break;
case WM_INPUT: {
if (skipInput) break;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER));
pRawInput = (PRAWINPUT)malloc(bufferSize);
if (!pRawInput)
break;
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, pRawInput, &bufferSize, sizeof(RAWINPUTHEADER)) > 0) {
if (pRawInput->header.dwType == RIM_TYPEKEYBOARD)
ToggleCursor(hWnd, pRawInput->data.keyboard);
for (auto cb : callbacks)
cb->ParseRawInput(pRawInput);
void RegisterCallback(ParseRawInputCB* cb)
{
if (cb && std::find(callbacks.begin(), callbacks.end(), cb) == callbacks.end())
callbacks.push_back(cb);
}
free(pRawInput);
break;
}
case WM_ACTIVATE:
OSDebugOut(TEXT("****** WM_ACTIVATE ****** %p %d\n"), hWnd, LOWORD(wParam) != WA_INACTIVE);
skipInput = LOWORD(wParam) == WA_INACTIVE;
if (LOWORD(wParam) == WA_INACTIVE)
CursorRelease();
break;
case WM_SETFOCUS:
OSDebugOut(TEXT("****** WM_SETFOCUS ****** %p\n"), hWnd);
//skipInput = false; //TODO when the hell is WM_SETFOCUS sent? seems like only when mouse is capped
break;
case WM_KILLFOCUS:
OSDebugOut(TEXT("****** WM_KILLFOCUS ****** %p\n"), hWnd);
//skipInput = true;
break;
case WM_SIZE:
if (cursorCaptured)
WindowResized(hWnd);
break;
case WM_DESTROY:
if (eatenWnd == nullptr)
RegisterRaw(nullptr);
Uninitialize();
break;
}
void UnregisterCallback(ParseRawInputCB* cb)
{
auto it = std::find(callbacks.begin(), callbacks.end(), cb);
if (it != callbacks.end())
callbacks.erase(it);
}
if(eatenWndProc)
return CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
//else
// return DefWindowProc(hWnd, uMsg, wParam, lParam);
return 0;
}
static POINT origCursorPos;
static POINT center;
static bool cursorCaptured = false;
static LRESULT CALLBACK HookProc(INT code, WPARAM wParam, LPARAM lParam)
{
MSG *msg = reinterpret_cast<MSG*> (lParam);
static void WindowResized(HWND hWnd)
{
RECT r;
GetWindowRect(hWnd, &r);
ClipCursor(&r);
center.x = (r.left + r.right) / 2;
center.y = (r.top + r.bottom) / 2;
SetCursorPos(center.x, center.y);
}
//fprintf(stderr, "hook: %d, %d, %d\n", code, wParam, lParam);
if(code == HC_ACTION)
RawInputProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
return CallNextHookEx(hHook, code, wParam, lParam);
}
static void CursorCapture(HWND hWnd)
{
OSDebugOut(TEXT("Capture cursor\n"));
SetCapture(hWnd);
ShowCursor(0);
static LRESULT CALLBACK HookWndProc(INT code, WPARAM wParam, LPARAM lParam)
{
MSG *msg = reinterpret_cast<MSG*> (lParam);
GetCursorPos(&origCursorPos);
//fprintf(stderr, "hook: %d, %d, %d\n", code, wParam, lParam);
if (code == HC_ACTION)
MyWndProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
return CallNextHookEx(hHookWnd, code, wParam, lParam);
}
RECT r;
GetWindowRect(hWnd, &r);
ClipCursor(&r);
center.x = (r.left + r.right) / 2;
center.y = (r.top + r.bottom) / 2;
SetCursorPos(center.x, center.y);
cursorCaptured = true;
}
static LRESULT CALLBACK KBHookProc(INT code, WPARAM wParam, LPARAM lParam)
{
fprintf(stderr, "kb hook: %d, %zd, %zd\n", code, wParam, lParam);
KBDLLHOOKSTRUCT *kb = reinterpret_cast<KBDLLHOOKSTRUCT*> (lParam);
//if(code == HC_ACTION)
// RawInputProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
return CallNextHookEx(0, code, wParam, lParam);
}
static void CursorRelease()
{
OSDebugOut(TEXT("Release cursor\n"));
if (cursorCaptured)
{
ClipCursor(0);
ReleaseCapture();
ShowCursor(1);
SetCursorPos(origCursorPos.x, origCursorPos.y);
cursorCaptured = false;
}
}
int Initialize(void *ptr)
{
HWND hWnd = reinterpret_cast<HWND> (ptr);
if (!InitHid())
return 0;
static void ToggleCursor(HWND hWnd, RAWKEYBOARD& k)
{
static bool shiftDown = false;
if (k.VKey == VK_SHIFT || k.VKey == VK_LSHIFT || k.VKey == VK_RSHIFT)
shiftDown = !(k.Flags & RI_KEY_BREAK);
if (shiftDown && k.VKey == VK_F11 && !k.Flags)
{
if (!cursorCaptured)
CursorCapture(hWnd);
else
CursorRelease();
}
}
static int RegisterRaw(HWND hWnd)
{
msgWindow = hWnd;
RAWINPUTDEVICE Rid[4];
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = HID_USAGE_GENERIC_GAMEPAD;
Rid[0].dwFlags = hWnd ? RIDEV_INPUTSINK : RIDEV_REMOVE; // adds game pad
Rid[0].hwndTarget = hWnd;
Rid[1].usUsagePage = 0x01;
Rid[1].usUsage = HID_USAGE_GENERIC_JOYSTICK;
Rid[1].dwFlags = hWnd ? RIDEV_INPUTSINK : RIDEV_REMOVE; // adds joystick
Rid[1].hwndTarget = hWnd;
Rid[2].usUsagePage = 0x01;
Rid[2].usUsage = HID_USAGE_GENERIC_KEYBOARD;
Rid[2].dwFlags = hWnd ? RIDEV_INPUTSINK : RIDEV_REMOVE; // | RIDEV_NOLEGACY; // adds HID keyboard //and also !ignores legacy keyboard messages
Rid[2].hwndTarget = hWnd;
Rid[3].usUsagePage = 0x01;
Rid[3].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[3].dwFlags = hWnd ? RIDEV_INPUTSINK : RIDEV_REMOVE;
Rid[3].hwndTarget = hWnd;
if (RegisterRawInputDevices(Rid, countof(Rid), sizeof(Rid[0])) == FALSE)
{
//registration failed. Call GetLastError for the cause of the error.
fprintf(stderr, "Could not (de)register raw input devices.\n");
return 0;
}
return 1;
}
static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_ACTIVATE:
OSDebugOut(TEXT("****** WM_ACTIVATE ****** %p %d\n"), hWnd, LOWORD(wParam) != WA_INACTIVE);
skipInput = LOWORD(wParam) == WA_INACTIVE;
break;
case WM_SETFOCUS:
OSDebugOut(TEXT("****** WM_SETFOCUS ****** %p\n"), hWnd);
skipInput = false;
break;
case WM_KILLFOCUS:
OSDebugOut(TEXT("****** WM_KILLFOCUS ****** %p\n"), hWnd);
skipInput = true;
break;
}
return 0;
}
static LRESULT CALLBACK RawInputProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PRAWINPUT pRawInput;
UINT bufferSize = 0;
switch (uMsg)
{
case WM_CREATE:
if (eatenWnd == nullptr)
RegisterRaw(hWnd);
break;
case WM_INPUT:
{
if (skipInput)
break;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER));
pRawInput = (PRAWINPUT)malloc(bufferSize);
if (!pRawInput)
break;
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, pRawInput, &bufferSize, sizeof(RAWINPUTHEADER)) > 0)
{
if (pRawInput->header.dwType == RIM_TYPEKEYBOARD)
ToggleCursor(hWnd, pRawInput->data.keyboard);
for (auto cb : callbacks)
cb->ParseRawInput(pRawInput);
}
free(pRawInput);
break;
}
case WM_ACTIVATE:
OSDebugOut(TEXT("****** WM_ACTIVATE ****** %p %d\n"), hWnd, LOWORD(wParam) != WA_INACTIVE);
skipInput = LOWORD(wParam) == WA_INACTIVE;
if (LOWORD(wParam) == WA_INACTIVE)
CursorRelease();
break;
case WM_SETFOCUS:
OSDebugOut(TEXT("****** WM_SETFOCUS ****** %p\n"), hWnd);
//skipInput = false; //TODO when the hell is WM_SETFOCUS sent? seems like only when mouse is capped
break;
case WM_KILLFOCUS:
OSDebugOut(TEXT("****** WM_KILLFOCUS ****** %p\n"), hWnd);
//skipInput = true;
break;
case WM_SIZE:
if (cursorCaptured)
WindowResized(hWnd);
break;
case WM_DESTROY:
if (eatenWnd == nullptr)
RegisterRaw(nullptr);
Uninitialize();
break;
}
if (eatenWndProc)
return CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
//else
// return DefWindowProc(hWnd, uMsg, wParam, lParam);
return 0;
}
static LRESULT CALLBACK HookProc(INT code, WPARAM wParam, LPARAM lParam)
{
MSG* msg = reinterpret_cast<MSG*>(lParam);
//fprintf(stderr, "hook: %d, %d, %d\n", code, wParam, lParam);
if (code == HC_ACTION)
RawInputProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
return CallNextHookEx(hHook, code, wParam, lParam);
}
static LRESULT CALLBACK HookWndProc(INT code, WPARAM wParam, LPARAM lParam)
{
MSG* msg = reinterpret_cast<MSG*>(lParam);
//fprintf(stderr, "hook: %d, %d, %d\n", code, wParam, lParam);
if (code == HC_ACTION)
MyWndProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
return CallNextHookEx(hHookWnd, code, wParam, lParam);
}
static LRESULT CALLBACK KBHookProc(INT code, WPARAM wParam, LPARAM lParam)
{
fprintf(stderr, "kb hook: %d, %zd, %zd\n", code, wParam, lParam);
KBDLLHOOKSTRUCT* kb = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
//if(code == HC_ACTION)
// RawInputProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
return CallNextHookEx(0, code, wParam, lParam);
}
int Initialize(void* ptr)
{
HWND hWnd = reinterpret_cast<HWND>(ptr);
if (!InitHid())
return 0;
#if 0
if (!RegisterRaw(hWnd))
@ -261,27 +270,28 @@ int Initialize(void *ptr)
//hHookKB = SetWindowsHookEx(WH_KEYBOARD_LL, KBHookProc, hInst, 0);
//int err = GetLastError();
#else
eatenWnd = hWnd;
eatenWndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)RawInputProc);
RegisterRaw(hWnd);
eatenWnd = hWnd;
eatenWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)RawInputProc);
RegisterRaw(hWnd);
#endif
return 1;
}
return 1;
}
void Uninitialize()
{
if(hHook)
{
UnhookWindowsHookEx(hHook);
//UnhookWindowsHookEx(hHookKB);
hHook = 0;
}
if(eatenWnd)
RegisterRaw(nullptr);
if(eatenWnd && eatenWndProc)
SetWindowLongPtr(eatenWnd, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
eatenWndProc = nullptr;
eatenWnd = nullptr;
}
void Uninitialize()
{
if (hHook)
{
UnhookWindowsHookEx(hHook);
//UnhookWindowsHookEx(hHookKB);
hHook = 0;
}
if (eatenWnd)
RegisterRaw(nullptr);
if (eatenWnd && eatenWndProc)
SetWindowLongPtr(eatenWnd, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
eatenWndProc = nullptr;
eatenWnd = nullptr;
}
}} //namespace
} // namespace rawinput
} // namespace shared

View File

@ -18,17 +18,21 @@
#include <setupapi.h>
#include "hidapi.h"
namespace shared{ namespace rawinput{
class ParseRawInputCB
namespace shared
{
namespace rawinput
{
class ParseRawInputCB
{
public:
virtual void ParseRawInput(PRAWINPUT pRawInput) = 0;
};
virtual void ParseRawInput(PRAWINPUT pRawInput) = 0;
};
int Initialize(void *hWnd);
void Uninitialize();
int Initialize(void* hWnd);
void Uninitialize();
void RegisterCallback(ParseRawInputCB *cb);
void UnregisterCallback(ParseRawInputCB *cb);
}}
void RegisterCallback(ParseRawInputCB* cb);
void UnregisterCallback(ParseRawInputCB* cb);
} // namespace rawinput
} // namespace shared

View File

@ -21,7 +21,10 @@
#if 0
#define DPRINTF OSDebugOut
#else
#define DPRINTF(...) do{}while(0)
#define DPRINTF(...) \
do \
{ \
} while (0)
#endif
RingBuffer::RingBuffer()
@ -33,19 +36,20 @@ RingBuffer::RingBuffer()
{
}
RingBuffer::RingBuffer(size_t capacity) : RingBuffer()
RingBuffer::RingBuffer(size_t capacity)
: RingBuffer()
{
reserve(capacity);
}
RingBuffer::~RingBuffer()
{
delete [] m_data;
delete[] m_data;
}
void RingBuffer::reserve(size_t capacity)
{
delete [] m_data;
delete[] m_data;
m_data = new char[capacity];
memset(m_data, 0, capacity);
m_capacity = capacity;
@ -63,7 +67,7 @@ size_t RingBuffer::size() const
size = 0;
}
else if (m_begin < m_end)
size = m_end - m_begin; // [ b...e ]
size = m_end - m_begin; // [ b...e ]
else
size = m_capacity - m_begin + m_end; // [...e b...]
@ -71,7 +75,7 @@ size_t RingBuffer::size() const
return size;
}
size_t RingBuffer::read(uint8_t *dst, size_t nbytes)
size_t RingBuffer::read(uint8_t* dst, size_t nbytes)
{
size_t to_read = nbytes;
while (to_read > 0 && size() > 0)
@ -85,12 +89,12 @@ size_t RingBuffer::read(uint8_t *dst, size_t nbytes)
return nbytes - to_read;
}
void RingBuffer::write(uint8_t *src, size_t nbytes)
void RingBuffer::write(uint8_t* src, size_t nbytes)
{
size_t bytes;
while (nbytes > 0)
{
bytes = std::min(nbytes, m_capacity - m_end);
bytes = std::min(nbytes, m_capacity - m_end);
memcpy(back(), src, bytes);
write(bytes);
src += bytes;
@ -105,12 +109,12 @@ size_t RingBuffer::peek_write(bool overwrite) const
if (overwrite)
return m_capacity - m_end;
if (m_end < m_begin) // [...e b...]
if (m_end < m_begin) // [...e b...]
peek = m_begin - m_end;
else if (m_end < m_capacity) // [ b...e ]
peek = m_capacity - m_end;
else
peek = m_begin; // [ b.......e]
peek = m_begin; // [ b.......e]
DPRINTF(TEXT("peek_write %zu\n"), peek);
return peek;
@ -126,12 +130,12 @@ size_t RingBuffer::peek_read() const
else
peek = 0;
}
else if (m_begin < m_end) // [ b...e ]
else if (m_begin < m_end) // [ b...e ]
peek = m_end - m_begin;
else if (m_begin < m_capacity) // [...e b...]
else if (m_begin < m_capacity) // [...e b...]
peek = m_capacity - m_begin;
else
peek = m_end; // [...e b]
peek = m_end; // [...e b]
DPRINTF(TEXT("peek_read %zu\n"), peek);
return peek;
@ -171,11 +175,11 @@ void RingBuffer::write(size_t bytes)
// push m_begin forward if m_end overlaps it
if ((m_end < m_begin && m_end + bytes > m_begin) ||
m_end + bytes > m_begin + m_capacity)
m_end + bytes > m_begin + m_capacity)
{
m_overrun = true;
m_begin = (m_end + bytes) % m_capacity;
m_end = m_begin;
m_end = m_begin;
}
else
m_end = (m_end + bytes) % m_capacity;
@ -186,7 +190,7 @@ void RingBuffer::write(size_t bytes)
void RingBuffer::read(size_t bytes)
{
assert( bytes <= size() );
assert(bytes <= size());
m_overrun = false;
if ((m_begin < m_end && m_begin + bytes > m_end) ||

View File

@ -28,6 +28,7 @@ using sec = std::chrono::seconds;
class RingBuffer
{
RingBuffer(RingBuffer&) = delete;
public:
RingBuffer();
RingBuffer(size_t capacity);
@ -37,18 +38,24 @@ public:
//size_t read(char *data, size_t bytes);
// Overwrites old data if nbytes > size()
void write(uint8_t *src, size_t nbytes);
size_t read(uint8_t *dst, size_t nbytes);
void write(uint8_t* src, size_t nbytes);
size_t read(uint8_t* dst, size_t nbytes);
// just move pointers around
void write(size_t bytes);
void read(size_t bytes);
template<typename T>
void write(size_t samples) { write(samples * sizeof(T)); }
template <typename T>
void write(size_t samples)
{
write(samples * sizeof(T));
}
template<typename T>
void read(size_t samples) { read (samples * sizeof(T)); }
template <typename T>
void read(size_t samples)
{
read(samples * sizeof(T));
}
void reserve(size_t size);
// if you care about old data, check how much can be written
@ -56,13 +63,13 @@ public:
size_t peek_write(bool overwrite = false) const;
size_t peek_read() const;
template<typename T>
template <typename T>
size_t peek_write(bool overwrite = false) const
{
return peek_write(overwrite) / sizeof(T);
}
template<typename T>
template <typename T>
size_t peek_read() const
{
return peek_read() / sizeof(T);
@ -70,33 +77,39 @@ public:
// amount of valid data, may need to read twice
size_t size() const;
template<typename T>
template <typename T>
size_t size() const
{
return size() / sizeof(T);
}
size_t capacity() const { return m_capacity; }
char* front(){ return m_data + m_begin; }
char* back(){ return m_data + m_end; }
char* front() { return m_data + m_begin; }
char* back() { return m_data + m_end; }
template<typename T>
T* front() { return (T*)(m_data + m_begin); }
template <typename T>
T* front()
{
return (T*)(m_data + m_begin);
}
template<typename T>
T* back() { return (T*)(m_data + m_end); }
template <typename T>
T* back()
{
return (T*)(m_data + m_end);
}
long long MilliSecsSinceLastWrite()
{
return std::chrono::duration_cast<ms>(hrc::now()-mLastWrite).count();
return std::chrono::duration_cast<ms>(hrc::now() - mLastWrite).count();
}
private:
size_t m_capacity;
char *m_data;
size_t m_capacity;
char* m_data;
size_t m_begin;
bool m_overrun;
size_t m_end;
size_t m_end;
hrc::time_point mLastWrite = hrc::time_point(ns(0));
};
#endif

View File

@ -20,22 +20,23 @@
#include "rawinput.h"
#endif
namespace shared {
namespace shared
{
void Initialize(void *ptr)
void Initialize(void* ptr)
{
// Keeping it simple, for now
#if defined(BUILD_RAW)
if (!shared::rawinput::Initialize(ptr))
throw std::runtime_error("Failed to initialize raw input!");
#endif
// Keeping it simple, for now
#if defined(BUILD_RAW)
if (!shared::rawinput::Initialize(ptr))
throw std::runtime_error("Failed to initialize raw input!");
#endif
}
void Uninitialize(/*void *ptr*/)
{
#if defined(BUILD_RAW)
shared::rawinput::Uninitialize(/*ptr*/);
#endif
#if defined(BUILD_RAW)
shared::rawinput::Uninitialize(/*ptr*/);
#endif
}
};
}; // namespace shared

View File

@ -14,7 +14,8 @@
*/
#pragma once
namespace shared {
void Initialize(void *ptr);
namespace shared
{
void Initialize(void* ptr);
void Uninitialize(/*void *ptr*/);
};
}; // namespace shared

View File

@ -35,450 +35,524 @@
#include "jpgd/jpgd.h"
#include "jo_mpeg.h"
GtkWidget *new_combobox(const char* label, GtkWidget *vbox); // src/linux/config-gtk.cpp
GtkWidget* new_combobox(const char* label, GtkWidget* vbox); // src/linux/config-gtk.cpp
#define CLEAR(x) memset(&(x), 0, sizeof(x))
namespace usb_eyetoy
{
namespace linux_api
{
namespace linux_api
{
static pthread_t _eyetoy_thread;
static pthread_t *eyetoy_thread = &_eyetoy_thread;
static unsigned char eyetoy_running = 0;
static pthread_t _eyetoy_thread;
static pthread_t* eyetoy_thread = &_eyetoy_thread;
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;
static int fd = -1;
buffer_t* buffers;
static unsigned int n_buffers;
static int out_buf;
static unsigned int pixelformat;
buffer_t mpeg_buffer;
std::mutex mpeg_mutex;
buffer_t mpeg_buffer;
std::mutex mpeg_mutex;
static int xioctl(int fh, unsigned long int request, void *arg) {
int r;
do {
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
static void store_mpeg_frame(unsigned char *data, unsigned int len) {
mpeg_mutex.lock();
memcpy(mpeg_buffer.start, data, len);
mpeg_buffer.length = len;
mpeg_mutex.unlock();
}
static void process_image(const unsigned char *ptr, int size) {
if (pixelformat == V4L2_PIX_FMT_YUYV) {
unsigned char *mpegData = (unsigned char*) calloc(1, 320 * 240 * 2);
int mpegLen = jo_write_mpeg(mpegData, ptr, 320, 240, JO_YUYV, JO_FLIP_X, JO_NONE);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
} else if (pixelformat == V4L2_PIX_FMT_JPEG) {
int width, height, actual_comps;
unsigned char *rgbData = jpgd::decompress_jpeg_image_from_memory(ptr, size, &width, &height, &actual_comps, 3);
unsigned char *mpegData = (unsigned char*) calloc(1, 320 * 240 * 2);
int mpegLen = jo_write_mpeg(mpegData, rgbData, 320, 240, JO_RGB24, JO_FLIP_X, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
} else {
fprintf(stderr, "unk format %c%c%c%c\n", pixelformat, pixelformat>>8, pixelformat>>16, pixelformat>>24);
}
}
static int read_frame() {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
default:
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_DQBUF", errno, strerror(errno));
return -1;
}
}
assert(buf.index < n_buffers);
process_image((const unsigned char*) buffers[buf.index].start, buf.bytesused);
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) {
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_QBUF", errno, strerror(errno));
return -1;
}
return 1;
}
std::vector<std::string> getDevList() {
std::vector<std::string> devList;
char dev_name[64];
int fd;
struct v4l2_capability cap;
for (int index = 0; index < 64; index++) {
snprintf(dev_name, sizeof(dev_name), "/dev/video%d", index);
if ((fd = open(dev_name, O_RDONLY)) < 0) {
continue;
static int xioctl(int fh, unsigned long int request, void* arg)
{
int r;
do
{
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
if(ioctl(fd, VIDIOC_QUERYCAP, &cap) >= 0) {
devList.push_back((char*)cap.card);
static void store_mpeg_frame(unsigned char* data, unsigned int len)
{
mpeg_mutex.lock();
memcpy(mpeg_buffer.start, data, len);
mpeg_buffer.length = len;
mpeg_mutex.unlock();
}
close(fd);
}
return devList;
}
static int v4l_open(std::string selectedDevice) {
char dev_name[64];
struct v4l2_capability cap;
fd = -1;
for (int index = 0; index < 64; index++) {
snprintf(dev_name, sizeof(dev_name), "/dev/video%d", index);
if ((fd = open(dev_name, O_RDWR | O_NONBLOCK, 0)) < 0) {
continue;
}
CLEAR(cap);
if(ioctl(fd, VIDIOC_QUERYCAP, &cap) >= 0) {
fprintf(stderr, "Camera: %s / %s\n", dev_name, (char*)cap.card);
if (!selectedDevice.empty() && strcmp(selectedDevice.c_str(), (char*)cap.card) == 0) {
goto cont;
static void process_image(const unsigned char* ptr, int size)
{
if (pixelformat == V4L2_PIX_FMT_YUYV)
{
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
int mpegLen = jo_write_mpeg(mpegData, ptr, 320, 240, JO_YUYV, JO_FLIP_X, JO_NONE);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
}
else if (pixelformat == V4L2_PIX_FMT_JPEG)
{
int width, height, actual_comps;
unsigned char* rgbData = jpgd::decompress_jpeg_image_from_memory(ptr, size, &width, &height, &actual_comps, 3);
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
int mpegLen = jo_write_mpeg(mpegData, rgbData, 320, 240, JO_RGB24, JO_FLIP_X, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
}
else
{
fprintf(stderr, "unk format %c%c%c%c\n", pixelformat, pixelformat >> 8, pixelformat >> 16, pixelformat >> 24);
}
}
close(fd);
fd = -1;
}
static int read_frame()
{
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (fd < 0) {
snprintf(dev_name, sizeof(dev_name), "/dev/video0");
fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
if (-1 == fd) {
fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_name, errno, strerror(errno));
return -1;
}
}
if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
switch (errno)
{
case EAGAIN:
return 0;
cont:
CLEAR(cap);
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
if (EINVAL == errno) {
fprintf(stderr, "%s is no V4L2 device\n", dev_name);
return -1;
} else {
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_QUERYCAP", errno, strerror(errno));
return -1;
}
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf(stderr, "%s is no video capture device\n", dev_name);
return -1;
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
fprintf(stderr, "%s does not support streaming i/o\n", dev_name);
return -1;
}
struct v4l2_cropcap cropcap;
CLEAR(cropcap);
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
struct v4l2_crop crop;
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap.defrect;
if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
switch (errno) {
case EINVAL:
break;
default:
break;
case EIO:
default:
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_DQBUF", errno, strerror(errno));
return -1;
}
}
}
}
struct v4l2_format fmt;
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
assert(buf.index < n_buffers);
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)) {
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_S_FMT", errno, strerror(errno));
return -1;
}
pixelformat = fmt.fmt.pix.pixelformat;
fprintf(stderr, "VIDIOC_S_FMT res=%dx%d, fmt=%c%c%c%c\n", fmt.fmt.pix.width, fmt.fmt.pix.height,
pixelformat, pixelformat>>8, pixelformat>>16, pixelformat>>24
);
process_image((const unsigned char*)buffers[buf.index].start, buf.bytesused);
struct v4l2_requestbuffers req;
CLEAR(req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_QBUF", errno, strerror(errno));
return -1;
}
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
fprintf(stderr, "%s does not support memory mapping\n", dev_name);
return -1;
} else {
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_REQBUFS", errno, strerror(errno));
return -1;
}
}
if (req.count < 2) {
fprintf(stderr, "Insufficient buffer memory on %s\n", dev_name);
return -1;
}
buffers = (buffer_t*) calloc(req.count, sizeof(*buffers));
if (!buffers) {
fprintf(stderr, "Out of memory\n");
return -1;
}
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)) {
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_QUERYBUF", errno, strerror(errno));
return -1;
return 1;
}
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
std::vector<std::string> getDevList()
{
std::vector<std::string> devList;
char dev_name[64];
int fd;
struct v4l2_capability cap;
if (MAP_FAILED == buffers[n_buffers].start) {
fprintf(stderr, "%s error %d, %s\n", "mmap", errno, strerror(errno));
return -1;
}
}
for (int index = 0; index < 64; index++)
{
snprintf(dev_name, sizeof(dev_name), "/dev/video%d", index);
for (unsigned int i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) {
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_QBUF", errno, strerror(errno));
return -1;
}
}
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type)) {
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_STREAMON", errno, strerror(errno));
return -1;
}
return 0;
}
static void* v4l_thread(void *arg) {
while(eyetoy_running) {
for (;;) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval timeout = {2, 0}; // 2sec
int ret = select(fd + 1, &fds, NULL, NULL, &timeout);
if (ret < 0) {
if (errno == EINTR)
if ((fd = open(dev_name, O_RDONLY)) < 0)
{
continue;
fprintf(stderr, "%s error %d, %s\n", "select", errno, strerror(errno));
break;
}
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) >= 0)
{
devList.push_back((char*)cap.card);
}
close(fd);
}
return devList;
}
static int v4l_open(std::string selectedDevice)
{
char dev_name[64];
struct v4l2_capability cap;
fd = -1;
for (int index = 0; index < 64; index++)
{
snprintf(dev_name, sizeof(dev_name), "/dev/video%d", index);
if ((fd = open(dev_name, O_RDWR | O_NONBLOCK, 0)) < 0)
{
continue;
}
CLEAR(cap);
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) >= 0)
{
fprintf(stderr, "Camera: %s / %s\n", dev_name, (char*)cap.card);
if (!selectedDevice.empty() && strcmp(selectedDevice.c_str(), (char*)cap.card) == 0)
{
goto cont;
}
}
close(fd);
fd = -1;
}
if (ret == 0) {
fprintf(stderr, "select timeout\n");
break;
if (fd < 0)
{
snprintf(dev_name, sizeof(dev_name), "/dev/video0");
fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
if (-1 == fd)
{
fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_name, errno, strerror(errno));
return -1;
}
}
if (read_frame())
break;
}
}
return NULL;
}
cont:
static int v4l_close() {
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type)) {
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_STREAMOFF", errno, strerror(errno));
return -1;
}
for (unsigned int i = 0; i < n_buffers; ++i) {
if (-1 == munmap(buffers[i].start, buffers[i].length)) {
fprintf(stderr, "%s error %d, %s\n", "munmap", errno, strerror(errno));
return -1;
}
}
free(buffers);
if (-1 == close(fd)) {
fprintf(stderr, "%s error %d, %s\n", "close", errno, strerror(errno));
return -1;
}
fd = -1;
return 0;
}
void create_dummy_frame() {
const int width = 320;
const int height = 240;
const int bytesPerPixel = 3;
unsigned char *rgbData = (unsigned char*) calloc(1, width * height * bytesPerPixel);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned char *ptr = rgbData + (y*width+x) * bytesPerPixel;
ptr[0] = 255-y;
ptr[1] = y;
ptr[2] = 255-y;
}
}
unsigned char *mpegData = (unsigned char*) calloc(1, width * height * bytesPerPixel);
int mpegLen = jo_write_mpeg(mpegData, rgbData, width, height, JO_RGB24, JO_NONE, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
}
int V4L2::Open() {
mpeg_buffer.start = calloc(1, 320 * 240 * 2);
create_dummy_frame();
if (eyetoy_running) {
eyetoy_running = 0;
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);
return 0;
};
int V4L2::Close() {
if (eyetoy_running) {
eyetoy_running = 0;
pthread_join(*eyetoy_thread, NULL);
v4l_close();
}
return 0;
};
int V4L2::GetImage(uint8_t *buf, int len) {
mpeg_mutex.lock();
int len2 = mpeg_buffer.length;
if (len < mpeg_buffer.length) len2 = len;
memcpy(buf, mpeg_buffer.start, len2);
mpeg_mutex.unlock();
return len2;
};
static void deviceChanged(GtkComboBox *widget, gpointer data) {
*(int*) data = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
}
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);
GtkWidget *dlg = gtk_dialog_new_with_buttons(
"V4L2 Settings", GTK_WINDOW(data), GTK_DIALOG_MODAL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
gtk_window_set_resizable(GTK_WINDOW(dlg), TRUE);
gtk_window_set_default_size(GTK_WINDOW(dlg), 320, 75);
GtkWidget *dlg_area_box = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
GtkWidget *main_hbox = gtk_hbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(dlg_area_box), main_hbox);
GtkWidget *right_vbox = gtk_vbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(main_hbox), right_vbox, TRUE, TRUE, 5);
GtkWidget *rs_cb = new_combobox("Device:", right_vbox);
std::vector<std::string> devList = getDevList();
int sel_idx = 0;
for (auto idx = 0; idx < devList.size(); idx++) {
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rs_cb), devList.at(idx).c_str());
if (!selectedDevice.empty() && selectedDevice == devList.at(idx)) {
gtk_combo_box_set_active(GTK_COMBO_BOX(rs_cb), idx);
sel_idx = idx;
}
}
int sel_new;
g_signal_connect(G_OBJECT(rs_cb), "changed", G_CALLBACK(deviceChanged), (gpointer)&sel_new);
gtk_widget_show_all(dlg);
gint result = gtk_dialog_run(GTK_DIALOG(dlg));
int ret = RESULT_OK;
if (result == GTK_RESPONSE_OK) {
if (sel_new != sel_idx) {
if (!SaveSetting(dev_type, port, APINAME, N_DEVICE, devList.at(sel_new))) {
ret = RESULT_FAILED;
CLEAR(cap);
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap))
{
if (EINVAL == errno)
{
fprintf(stderr, "%s is no V4L2 device\n", dev_name);
return -1;
}
else
{
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_QUERYCAP", errno, strerror(errno));
return -1;
}
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
{
fprintf(stderr, "%s is no video capture device\n", dev_name);
return -1;
}
if (!(cap.capabilities & V4L2_CAP_STREAMING))
{
fprintf(stderr, "%s does not support streaming i/o\n", dev_name);
return -1;
}
struct v4l2_cropcap cropcap;
CLEAR(cropcap);
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap))
{
struct v4l2_crop crop;
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap.defrect;
if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop))
{
switch (errno)
{
case EINVAL:
break;
default:
break;
}
}
}
struct v4l2_format fmt;
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
{
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_S_FMT", errno, strerror(errno));
return -1;
}
pixelformat = fmt.fmt.pix.pixelformat;
fprintf(stderr, "VIDIOC_S_FMT res=%dx%d, fmt=%c%c%c%c\n", fmt.fmt.pix.width, fmt.fmt.pix.height,
pixelformat, pixelformat >> 8, pixelformat >> 16, pixelformat >> 24);
struct v4l2_requestbuffers req;
CLEAR(req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req))
{
if (EINVAL == errno)
{
fprintf(stderr, "%s does not support memory mapping\n", dev_name);
return -1;
}
else
{
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_REQBUFS", errno, strerror(errno));
return -1;
}
}
if (req.count < 2)
{
fprintf(stderr, "Insufficient buffer memory on %s\n", dev_name);
return -1;
}
buffers = (buffer_t*)calloc(req.count, sizeof(*buffers));
if (!buffers)
{
fprintf(stderr, "Out of memory\n");
return -1;
}
for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
{
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
{
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_QUERYBUF", errno, strerror(errno));
return -1;
}
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start)
{
fprintf(stderr, "%s error %d, %s\n", "mmap", errno, strerror(errno));
return -1;
}
}
for (unsigned int i = 0; i < n_buffers; ++i)
{
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_QBUF", errno, strerror(errno));
return -1;
}
}
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
{
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_STREAMON", errno, strerror(errno));
return -1;
}
return 0;
}
} else {
ret = RESULT_CANCELED;
}
gtk_widget_destroy(dlg);
return ret;
}
int V4L2::Configure(int port, const char *dev_type, void *data) {
return GtkConfigure(port, dev_type, data);
};
static void* v4l_thread(void* arg)
{
while (eyetoy_running)
{
for (;;)
{
fd_set fds;
} // namespace linux_api
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval timeout = {2, 0}; // 2sec
int ret = select(fd + 1, &fds, NULL, NULL, &timeout);
if (ret < 0)
{
if (errno == EINTR)
continue;
fprintf(stderr, "%s error %d, %s\n", "select", errno, strerror(errno));
break;
}
if (ret == 0)
{
fprintf(stderr, "select timeout\n");
break;
}
if (read_frame())
break;
}
}
return NULL;
}
static int v4l_close()
{
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
{
fprintf(stderr, "%s error %d, %s\n", "VIDIOC_STREAMOFF", errno, strerror(errno));
return -1;
}
for (unsigned int i = 0; i < n_buffers; ++i)
{
if (-1 == munmap(buffers[i].start, buffers[i].length))
{
fprintf(stderr, "%s error %d, %s\n", "munmap", errno, strerror(errno));
return -1;
}
}
free(buffers);
if (-1 == close(fd))
{
fprintf(stderr, "%s error %d, %s\n", "close", errno, strerror(errno));
return -1;
}
fd = -1;
return 0;
}
void create_dummy_frame()
{
const int width = 320;
const int height = 240;
const int bytesPerPixel = 3;
unsigned char* rgbData = (unsigned char*)calloc(1, width * height * bytesPerPixel);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
unsigned char* ptr = rgbData + (y * width + x) * bytesPerPixel;
ptr[0] = 255 - y;
ptr[1] = y;
ptr[2] = 255 - y;
}
}
unsigned char* mpegData = (unsigned char*)calloc(1, width * height * bytesPerPixel);
int mpegLen = jo_write_mpeg(mpegData, rgbData, width, height, JO_RGB24, JO_NONE, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
}
int V4L2::Open()
{
mpeg_buffer.start = calloc(1, 320 * 240 * 2);
create_dummy_frame();
if (eyetoy_running)
{
eyetoy_running = 0;
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);
return 0;
};
int V4L2::Close()
{
if (eyetoy_running)
{
eyetoy_running = 0;
pthread_join(*eyetoy_thread, NULL);
v4l_close();
}
return 0;
};
int V4L2::GetImage(uint8_t* buf, int len)
{
mpeg_mutex.lock();
int len2 = mpeg_buffer.length;
if (len < mpeg_buffer.length)
len2 = len;
memcpy(buf, mpeg_buffer.start, len2);
mpeg_mutex.unlock();
return len2;
};
static void deviceChanged(GtkComboBox* widget, gpointer data)
{
*(int*)data = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
}
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);
GtkWidget* dlg = gtk_dialog_new_with_buttons(
"V4L2 Settings", GTK_WINDOW(data), GTK_DIALOG_MODAL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
gtk_window_set_resizable(GTK_WINDOW(dlg), TRUE);
gtk_window_set_default_size(GTK_WINDOW(dlg), 320, 75);
GtkWidget* dlg_area_box = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
GtkWidget* main_hbox = gtk_hbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(dlg_area_box), main_hbox);
GtkWidget* right_vbox = gtk_vbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(main_hbox), right_vbox, TRUE, TRUE, 5);
GtkWidget* rs_cb = new_combobox("Device:", right_vbox);
std::vector<std::string> devList = getDevList();
int sel_idx = 0;
for (auto idx = 0; idx < devList.size(); idx++)
{
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rs_cb), devList.at(idx).c_str());
if (!selectedDevice.empty() && selectedDevice == devList.at(idx))
{
gtk_combo_box_set_active(GTK_COMBO_BOX(rs_cb), idx);
sel_idx = idx;
}
}
int sel_new;
g_signal_connect(G_OBJECT(rs_cb), "changed", G_CALLBACK(deviceChanged), (gpointer)&sel_new);
gtk_widget_show_all(dlg);
gint result = gtk_dialog_run(GTK_DIALOG(dlg));
int ret = RESULT_OK;
if (result == GTK_RESPONSE_OK)
{
if (sel_new != sel_idx)
{
if (!SaveSetting(dev_type, port, APINAME, N_DEVICE, devList.at(sel_new)))
{
ret = RESULT_FAILED;
}
}
}
else
{
ret = RESULT_CANCELED;
}
gtk_widget_destroy(dlg);
return ret;
}
int V4L2::Configure(int port, const char* dev_type, void* data)
{
return GtkConfigure(port, dev_type, data);
};
} // namespace linux_api
} // namespace usb_eyetoy

View File

@ -17,37 +17,40 @@
namespace usb_eyetoy
{
namespace linux_api
{
namespace linux_api
{
typedef struct {
void *start;
size_t length;
} buffer_t;
typedef struct
{
void* start;
size_t length;
} buffer_t;
static const char *APINAME = "V4L2";
static const char* APINAME = "V4L2";
class V4L2 : public VideoDevice
{
public:
V4L2(int port) : mPort(port) {};
~V4L2(){};
int Open();
int Close();
int GetImage(uint8_t *buf, int len);
int Reset() { return 0; };
class V4L2 : public VideoDevice
{
public:
V4L2(int port)
: mPort(port){};
~V4L2(){};
int Open();
int Close();
int GetImage(uint8_t* buf, int len);
int Reset() { return 0; };
static const TCHAR *Name() {
return TEXT("V4L2");
}
static int Configure(int port, const char *dev_type, void *data);
static const TCHAR* Name()
{
return TEXT("V4L2");
}
static int Configure(int port, const char* dev_type, void* data);
int Port() { return mPort; }
void Port(int port) { mPort = port; }
int Port() { return mPort; }
void Port(int port) { mPort = port; }
private:
int mPort;
};
private:
int mPort;
};
} // namespace linux_api
} // namespace linux_api
} // namespace usb_eyetoy

View File

@ -23,452 +23,526 @@
namespace usb_eyetoy
{
namespace windows_api
{
namespace windows_api
{
HRESULT DirectShow::CallbackHandler::SampleCB(double time, IMediaSample *sample) {
HRESULT hr;
unsigned char* buffer;
HRESULT DirectShow::CallbackHandler::SampleCB(double time, IMediaSample* sample)
{
HRESULT hr;
unsigned char* buffer;
hr = sample->GetPointer((BYTE**)&buffer);
if (hr != S_OK) return S_OK;
hr = sample->GetPointer((BYTE**)&buffer);
if (hr != S_OK)
return S_OK;
if (callback) callback(buffer, sample->GetActualDataLength(), BITS_PER_PIXEL);
return S_OK;
}
HRESULT DirectShow::CallbackHandler::QueryInterface(REFIID iid, LPVOID *ppv) {
if( iid == IID_ISampleGrabberCB || iid == IID_IUnknown ) {
*ppv = (void *) static_cast<ISampleGrabberCB*>( this );
return S_OK;
}
return E_NOINTERFACE;
}
std::vector<std::wstring> getDevList() {
std::vector<std::wstring> devList;
ICreateDevEnum *pCreateDevEnum = 0;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pCreateDevEnum));
if (FAILED(hr)) {
fprintf(stderr, "Error Creating Device Enumerator");
return devList;
}
IEnumMoniker *pEnum = 0;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, NULL);
if (FAILED(hr)) {
fprintf(stderr, "You have no video capture hardware");
return devList;
};
IMoniker *pMoniker = NULL;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
IPropertyBag *pPropBag;
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr)) {
pMoniker->Release();
continue;
if (callback)
callback(buffer, sample->GetActualDataLength(), BITS_PER_PIXEL);
return S_OK;
}
VARIANT var;
VariantInit(&var);
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr)) {
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
if (SUCCEEDED(hr)) {
devList.push_back(var.bstrVal);
VariantClear(&var);
HRESULT DirectShow::CallbackHandler::QueryInterface(REFIID iid, LPVOID* ppv)
{
if (iid == IID_ISampleGrabberCB || iid == IID_IUnknown)
{
*ppv = (void*)static_cast<ISampleGrabberCB*>(this);
return S_OK;
}
return E_NOINTERFACE;
}
pPropBag->Release();
pMoniker->Release();
}
std::vector<std::wstring> getDevList()
{
std::vector<std::wstring> devList;
pEnum->Release();
CoUninitialize();
ICreateDevEnum* pCreateDevEnum = 0;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pCreateDevEnum));
if (FAILED(hr))
{
fprintf(stderr, "Error Creating Device Enumerator");
return devList;
}
return devList;
}
IEnumMoniker* pEnum = 0;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, NULL);
if (FAILED(hr))
{
fprintf(stderr, "You have no video capture hardware");
return devList;
};
int DirectShow::InitializeDevice(std::wstring selectedDevice) {
IMoniker* pMoniker = NULL;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
IPropertyBag* pPropBag;
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
pMoniker->Release();
continue;
}
// Create the Capture Graph Builder.
HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraphBuilder));
if (FAILED(hr)) {
fprintf(stderr, "CoCreateInstance CLSID_CaptureGraphBuilder2 err : %x\n", hr);
return -1;
}
VARIANT var;
VariantInit(&var);
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
if (SUCCEEDED(hr))
{
devList.push_back(var.bstrVal);
VariantClear(&var);
}
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraph));
if (FAILED(hr)) {
fprintf(stderr, "CoCreateInstance CLSID_FilterGraph err : %x\n", hr);
return -1;
}
pPropBag->Release();
pMoniker->Release();
}
hr = pGraphBuilder->SetFiltergraph(pGraph);
if (FAILED(hr)) {
fprintf(stderr, "SetFiltergraph err : %x\n", hr);
return -1;
}
pEnum->Release();
CoUninitialize();
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
if (FAILED(hr)) {
fprintf(stderr, "QueryInterface IID_IMediaControl err : %x\n", hr);
return -1;
}
// enumerate all video capture devices
ICreateDevEnum *pCreateDevEnum = 0;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pCreateDevEnum));
if (FAILED(hr)) {
fprintf(stderr, "Error Creating Device Enumerator");
return -1;
}
IEnumMoniker *pEnum = 0;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, NULL);
if (FAILED(hr)) {
fprintf(stderr, "You have no video capture hardware");
return -1;
};
pEnum->Reset();
IMoniker *pMoniker;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK && sourcefilter == NULL) {
IPropertyBag *pPropBag = 0;
hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr)) {
fprintf(stderr, "BindToStorage err : %x\n", hr);
goto freeMoniker;
return devList;
}
VARIANT var;
VariantInit(&var);
int DirectShow::InitializeDevice(std::wstring selectedDevice)
{
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr)) {
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
if (FAILED(hr)) {
fprintf(stderr, "Read name err : %x\n", hr);
goto freeVar;
}
fprintf(stderr, "Camera: '%ls'\n", var.bstrVal);
if (!selectedDevice.empty() && selectedDevice != var.bstrVal) {
goto freeVar;
}
// Create the Capture Graph Builder.
HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraphBuilder));
if (FAILED(hr))
{
fprintf(stderr, "CoCreateInstance CLSID_CaptureGraphBuilder2 err : %x\n", hr);
return -1;
}
//add a filter for the device
hr = pGraph->AddSourceFilterForMoniker(pMoniker, NULL, L"sourcefilter", &sourcefilter);
if (FAILED(hr)) {
fprintf(stderr, "AddSourceFilterForMoniker err : %x\n", hr);
goto freeVar;
}
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraph));
if (FAILED(hr))
{
fprintf(stderr, "CoCreateInstance CLSID_FilterGraph err : %x\n", hr);
return -1;
}
hr = pGraphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, sourcefilter, IID_IAMStreamConfig, (void **)&pSourceConfig);
if (SUCCEEDED(hr)) {
int iCount = 0, iSize = 0;
hr = pSourceConfig->GetNumberOfCapabilities(&iCount, &iSize);
hr = pGraphBuilder->SetFiltergraph(pGraph);
if (FAILED(hr))
{
fprintf(stderr, "SetFiltergraph err : %x\n", hr);
return -1;
}
// Check the size to make sure we pass in the correct structure.
if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
// Use the video capabilities structure.
for (int iFormat = 0; iFormat < iCount; iFormat++) {
VIDEO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE *pmtConfig;
hr = pSourceConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE *)&scc);
fprintf(stderr, "GetStreamCaps min=%dx%d max=%dx%d, fmt=%x\n",
scc.MinOutputSize.cx, scc.MinOutputSize.cy,
scc.MaxOutputSize.cx, scc.MaxOutputSize.cy,
pmtConfig->subtype);
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
if (FAILED(hr))
{
fprintf(stderr, "QueryInterface IID_IMediaControl err : %x\n", hr);
return -1;
}
if (SUCCEEDED(hr)) {
if ((pmtConfig->majortype == MEDIATYPE_Video) &&
(pmtConfig->formattype == FORMAT_VideoInfo) &&
(pmtConfig->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
(pmtConfig->pbFormat != NULL)) {
// enumerate all video capture devices
ICreateDevEnum* pCreateDevEnum = 0;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pCreateDevEnum));
if (FAILED(hr))
{
fprintf(stderr, "Error Creating Device Enumerator");
return -1;
}
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER *)pmtConfig->pbFormat;
pVih->bmiHeader.biWidth = 320;
pVih->bmiHeader.biHeight = 240;
pVih->bmiHeader.biSizeImage = DIBSIZE(pVih->bmiHeader);
hr = pSourceConfig->SetFormat(pmtConfig);
IEnumMoniker* pEnum = 0;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, NULL);
if (FAILED(hr))
{
fprintf(stderr, "You have no video capture hardware");
return -1;
};
pEnum->Reset();
IMoniker* pMoniker;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK && sourcefilter == NULL)
{
IPropertyBag* pPropBag = 0;
hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
fprintf(stderr, "BindToStorage err : %x\n", hr);
goto freeMoniker;
}
VARIANT var;
VariantInit(&var);
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
if (FAILED(hr))
{
fprintf(stderr, "Read name err : %x\n", hr);
goto freeVar;
}
fprintf(stderr, "Camera: '%ls'\n", var.bstrVal);
if (!selectedDevice.empty() && selectedDevice != var.bstrVal)
{
goto freeVar;
}
//add a filter for the device
hr = pGraph->AddSourceFilterForMoniker(pMoniker, NULL, L"sourcefilter", &sourcefilter);
if (FAILED(hr))
{
fprintf(stderr, "AddSourceFilterForMoniker err : %x\n", hr);
goto freeVar;
}
hr = pGraphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, sourcefilter, IID_IAMStreamConfig, (void**)&pSourceConfig);
if (SUCCEEDED(hr))
{
int iCount = 0, iSize = 0;
hr = pSourceConfig->GetNumberOfCapabilities(&iCount, &iSize);
// Check the size to make sure we pass in the correct structure.
if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
{
// Use the video capabilities structure.
for (int iFormat = 0; iFormat < iCount; iFormat++)
{
VIDEO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE* pmtConfig;
hr = pSourceConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
fprintf(stderr, "GetStreamCaps min=%dx%d max=%dx%d, fmt=%x\n",
scc.MinOutputSize.cx, scc.MinOutputSize.cy,
scc.MaxOutputSize.cx, scc.MaxOutputSize.cy,
pmtConfig->subtype);
if (SUCCEEDED(hr))
{
if ((pmtConfig->majortype == MEDIATYPE_Video) &&
(pmtConfig->formattype == FORMAT_VideoInfo) &&
(pmtConfig->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
(pmtConfig->pbFormat != NULL))
{
VIDEOINFOHEADER* pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
pVih->bmiHeader.biWidth = 320;
pVih->bmiHeader.biHeight = 240;
pVih->bmiHeader.biSizeImage = DIBSIZE(pVih->bmiHeader);
hr = pSourceConfig->SetFormat(pmtConfig);
}
//DeleteMediaType(pmtConfig);
}
}
//DeleteMediaType(pmtConfig);
}
}
// Create the Sample Grabber filter.
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&samplegrabberfilter));
if (FAILED(hr))
{
fprintf(stderr, "CoCreateInstance CLSID_SampleGrabber err : %x\n", hr);
goto freeVar;
}
hr = pGraph->AddFilter(samplegrabberfilter, L"samplegrabberfilter");
if (FAILED(hr))
{
fprintf(stderr, "AddFilter samplegrabberfilter err : %x\n", hr);
goto freeVar;
}
//set mediatype on the samplegrabber
hr = samplegrabberfilter->QueryInterface(IID_PPV_ARGS(&samplegrabber));
if (FAILED(hr))
{
fprintf(stderr, "QueryInterface err : %x\n", hr);
goto freeVar;
}
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(mt));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
hr = samplegrabber->SetMediaType(&mt);
if (FAILED(hr))
{
fprintf(stderr, "SetMediaType err : %x\n", hr);
goto freeVar;
}
//add the callback to the samplegrabber
hr = samplegrabber->SetCallback(callbackhandler, 0);
if (hr != S_OK)
{
fprintf(stderr, "SetCallback err : %x\n", hr);
goto freeVar;
}
//set the null renderer
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&nullrenderer));
if (FAILED(hr))
{
fprintf(stderr, "CoCreateInstance CLSID_NullRenderer err : %x\n", hr);
goto freeVar;
}
hr = pGraph->AddFilter(nullrenderer, L"nullrenderer");
if (FAILED(hr))
{
fprintf(stderr, "AddFilter nullrenderer err : %x\n", hr);
goto freeVar;
}
//set the render path
hr = pGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, sourcefilter, samplegrabberfilter, nullrenderer);
if (FAILED(hr))
{
fprintf(stderr, "RenderStream err : %x\n", hr);
goto freeVar;
}
// if the stream is started, start capturing immediatly
LONGLONG start = 0, stop = MAXLONGLONG;
hr = pGraphBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, sourcefilter, &start, &stop, 1, 2);
if (FAILED(hr))
{
fprintf(stderr, "ControlStream err : %x\n", hr);
goto freeVar;
}
freeVar:
VariantClear(&var);
pPropBag->Release();
freeMoniker:
pMoniker->Release();
}
pEnum->Release();
if (sourcefilter == NULL)
{
return -1;
}
return 0;
}
void DirectShow::Start()
{
HRESULT hr = nullrenderer->Run(0);
if (FAILED(hr))
throw hr;
hr = samplegrabberfilter->Run(0);
if (FAILED(hr))
throw hr;
hr = sourcefilter->Run(0);
if (FAILED(hr))
throw hr;
}
void DirectShow::Stop()
{
HRESULT hr = sourcefilter->Stop();
if (FAILED(hr))
throw hr;
hr = samplegrabberfilter->Stop();
if (FAILED(hr))
throw hr;
hr = nullrenderer->Stop();
if (FAILED(hr))
throw hr;
}
buffer_t mpeg_buffer{};
std::mutex mpeg_mutex;
void store_mpeg_frame(unsigned char* data, unsigned int len)
{
mpeg_mutex.lock();
memcpy(mpeg_buffer.start, data, len);
mpeg_buffer.length = len;
mpeg_mutex.unlock();
}
void dshow_callback(unsigned char* data, int len, int bitsperpixel)
{
if (bitsperpixel == 24)
{
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
int mpegLen = jo_write_mpeg(mpegData, data, 320, 240, JO_RGB24, JO_FLIP_X, JO_FLIP_Y);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
}
else
{
fprintf(stderr, "dshow_callback: unk format: len=%d bpp=%d\n", len, bitsperpixel);
}
}
// Create the Sample Grabber filter.
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&samplegrabberfilter));
if (FAILED(hr)) {
fprintf(stderr, "CoCreateInstance CLSID_SampleGrabber err : %x\n", hr);
goto freeVar;
void create_dummy_frame()
{
const int width = 320;
const int height = 240;
const int bytesPerPixel = 3;
unsigned char* rgbData = (unsigned char*)calloc(1, width * height * bytesPerPixel);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
unsigned char* ptr = rgbData + (y * width + x) * bytesPerPixel;
ptr[0] = 255 - y;
ptr[1] = y;
ptr[2] = 255 - y;
}
}
unsigned char* mpegData = (unsigned char*)calloc(1, width * height * bytesPerPixel);
int mpegLen = jo_write_mpeg(mpegData, rgbData, width, height, JO_RGB24, JO_NONE, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
}
hr = pGraph->AddFilter(samplegrabberfilter, L"samplegrabberfilter");
if (FAILED(hr)) {
fprintf(stderr, "AddFilter samplegrabberfilter err : %x\n", hr);
goto freeVar;
DirectShow::DirectShow(int port)
{
mPort = port;
pGraphBuilder = NULL;
pGraph = NULL;
pControl = NULL;
sourcefilter = NULL;
samplegrabberfilter = NULL;
nullrenderer = NULL;
pSourceConfig = NULL;
samplegrabber = NULL;
callbackhandler = new CallbackHandler();
CoInitialize(NULL);
}
//set mediatype on the samplegrabber
hr = samplegrabberfilter->QueryInterface(IID_PPV_ARGS(&samplegrabber));
if (FAILED(hr)) {
fprintf(stderr, "QueryInterface err : %x\n", hr);
goto freeVar;
}
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(mt));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
hr = samplegrabber->SetMediaType(&mt);
if (FAILED(hr)) {
fprintf(stderr, "SetMediaType err : %x\n", hr);
goto freeVar;
}
//add the callback to the samplegrabber
hr = samplegrabber->SetCallback(callbackhandler, 0);
if (hr != S_OK) {
fprintf(stderr, "SetCallback err : %x\n", hr);
goto freeVar;
}
//set the null renderer
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&nullrenderer));
if (FAILED(hr)) {
fprintf(stderr, "CoCreateInstance CLSID_NullRenderer err : %x\n", hr);
goto freeVar;
}
hr = pGraph->AddFilter(nullrenderer, L"nullrenderer");
if (FAILED(hr)) {
fprintf(stderr, "AddFilter nullrenderer err : %x\n", hr);
goto freeVar;
}
//set the render path
hr = pGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, sourcefilter, samplegrabberfilter, nullrenderer);
if (FAILED(hr)) {
fprintf(stderr, "RenderStream err : %x\n", hr);
goto freeVar;
}
// if the stream is started, start capturing immediatly
LONGLONG start = 0, stop = MAXLONGLONG;
hr = pGraphBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, sourcefilter, &start, &stop, 1, 2);
if (FAILED(hr)) {
fprintf(stderr, "ControlStream err : %x\n", hr);
goto freeVar;
}
freeVar:
VariantClear(&var);
pPropBag->Release();
freeMoniker:
pMoniker->Release();
}
pEnum->Release();
if (sourcefilter == NULL) {
return -1;
}
return 0;
}
void DirectShow::Start() {
HRESULT hr = nullrenderer->Run(0);
if (FAILED(hr)) throw hr;
hr = samplegrabberfilter->Run(0);
if (FAILED(hr)) throw hr;
hr = sourcefilter->Run(0);
if (FAILED(hr)) throw hr;
}
void DirectShow::Stop() {
HRESULT hr = sourcefilter->Stop();
if (FAILED(hr)) throw hr;
hr = samplegrabberfilter->Stop();
if (FAILED(hr)) throw hr;
hr = nullrenderer->Stop();
if (FAILED(hr)) throw hr;
}
buffer_t mpeg_buffer {};
std::mutex mpeg_mutex;
void store_mpeg_frame(unsigned char *data, unsigned int len) {
mpeg_mutex.lock();
memcpy(mpeg_buffer.start, data, len);
mpeg_buffer.length = len;
mpeg_mutex.unlock();
}
void dshow_callback(unsigned char *data, int len, int bitsperpixel) {
if (bitsperpixel == 24) {
unsigned char *mpegData = (unsigned char *)calloc(1, 320 * 240 * 2);
int mpegLen = jo_write_mpeg(mpegData, data, 320, 240, JO_RGB24, JO_FLIP_X, JO_FLIP_Y);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
} else {
fprintf(stderr, "dshow_callback: unk format: len=%d bpp=%d\n", len, bitsperpixel);
}
}
void create_dummy_frame() {
const int width = 320;
const int height = 240;
const int bytesPerPixel = 3;
unsigned char *rgbData = (unsigned char*) calloc(1, width * height * bytesPerPixel);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned char *ptr = rgbData + (y*width+x) * bytesPerPixel;
ptr[0] = 255-y;
ptr[1] = y;
ptr[2] = 255-y;
}
}
unsigned char *mpegData = (unsigned char*) calloc(1, width * height * bytesPerPixel);
int mpegLen = jo_write_mpeg(mpegData, rgbData, width, height, JO_RGB24, JO_NONE, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
}
DirectShow::DirectShow(int port) {
mPort = port;
pGraphBuilder = NULL;
pGraph = NULL;
pControl = NULL;
sourcefilter = NULL;
samplegrabberfilter = NULL;
nullrenderer = NULL;
pSourceConfig = NULL;
samplegrabber = NULL;
callbackhandler = new CallbackHandler();
CoInitialize(NULL);
}
int DirectShow::Open() {
mpeg_buffer.start = calloc(1, 320 * 240 * 2);
create_dummy_frame();
std::wstring selectedDevice;
LoadSetting(EyeToyWebCamDevice::TypeName(), Port(), APINAME, N_DEVICE, selectedDevice);
int ret = InitializeDevice(selectedDevice);
if (ret < 0) {
fprintf(stderr, "Camera: cannot find '%ls'\n", selectedDevice.c_str());
return -1;
}
pControl->Run();
this->Stop();
this->SetCallback(dshow_callback);
this->Start();
return 0;
};
int DirectShow::Close() {
if (sourcefilter != NULL) {
this->Stop();
pControl->Stop();
sourcefilter->Release();
pSourceConfig->Release();
samplegrabberfilter->Release();
samplegrabber->Release();
nullrenderer->Release();
}
pGraphBuilder->Release();
pGraph->Release();
pControl->Release();
if (mpeg_buffer.start != NULL) {
free(mpeg_buffer.start);
mpeg_buffer.start = NULL;
}
return 0;
};
int DirectShow::GetImage(uint8_t *buf, int len) {
mpeg_mutex.lock();
int len2 = mpeg_buffer.length;
if (len < mpeg_buffer.length) len2 = len;
memcpy(buf, mpeg_buffer.start, len2);
mpeg_mutex.unlock();
return len2;
};
BOOL CALLBACK DirectShowDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) {
int port;
switch (uMsg) {
case WM_CREATE:
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
break;
case WM_INITDIALOG: {
port = (int)lParam;
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
int DirectShow::Open()
{
mpeg_buffer.start = calloc(1, 320 * 240 * 2);
create_dummy_frame();
std::wstring selectedDevice;
LoadSetting(EyeToyWebCamDevice::TypeName(), port, APINAME, N_DEVICE, selectedDevice);
SendDlgItemMessage(hW, IDC_COMBO1, CB_RESETCONTENT, 0, 0);
LoadSetting(EyeToyWebCamDevice::TypeName(), Port(), APINAME, N_DEVICE, selectedDevice);
std::vector<std::wstring> devList = getDevList();
for (auto i = 0; i != devList.size(); i++) {
SendDlgItemMessageW(hW, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM)devList[i].c_str());
if (selectedDevice == devList.at(i)) {
SendDlgItemMessage(hW, IDC_COMBO1, CB_SETCURSEL, i, i);
}
int ret = InitializeDevice(selectedDevice);
if (ret < 0)
{
fprintf(stderr, "Camera: cannot find '%ls'\n", selectedDevice.c_str());
return -1;
}
return TRUE;
}
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED) {
switch (LOWORD(wParam)) {
case IDOK: {
INT_PTR res = RESULT_OK;
static wchar_t selectedDevice[500] = {0};
GetWindowTextW(GetDlgItem(hW, IDC_COMBO1), selectedDevice, countof(selectedDevice));
port = (int)GetWindowLongPtr(hW, GWLP_USERDATA);
if (!SaveSetting<std::wstring>(EyeToyWebCamDevice::TypeName(), port, APINAME, N_DEVICE, selectedDevice)) {
res = RESULT_FAILED;
pControl->Run();
this->Stop();
this->SetCallback(dshow_callback);
this->Start();
return 0;
};
int DirectShow::Close()
{
if (sourcefilter != NULL)
{
this->Stop();
pControl->Stop();
sourcefilter->Release();
pSourceConfig->Release();
samplegrabberfilter->Release();
samplegrabber->Release();
nullrenderer->Release();
}
pGraphBuilder->Release();
pGraph->Release();
pControl->Release();
if (mpeg_buffer.start != NULL)
{
free(mpeg_buffer.start);
mpeg_buffer.start = NULL;
}
return 0;
};
int DirectShow::GetImage(uint8_t* buf, int len)
{
mpeg_mutex.lock();
int len2 = mpeg_buffer.length;
if (len < mpeg_buffer.length)
len2 = len;
memcpy(buf, mpeg_buffer.start, len2);
mpeg_mutex.unlock();
return len2;
};
BOOL CALLBACK DirectShowDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int port;
switch (uMsg)
{
case WM_CREATE:
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
break;
case WM_INITDIALOG:
{
port = (int)lParam;
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
std::wstring selectedDevice;
LoadSetting(EyeToyWebCamDevice::TypeName(), port, APINAME, N_DEVICE, selectedDevice);
SendDlgItemMessage(hW, IDC_COMBO1, CB_RESETCONTENT, 0, 0);
std::vector<std::wstring> devList = getDevList();
for (auto i = 0; i != devList.size(); i++)
{
SendDlgItemMessageW(hW, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM)devList[i].c_str());
if (selectedDevice == devList.at(i))
{
SendDlgItemMessage(hW, IDC_COMBO1, CB_SETCURSEL, i, i);
}
EndDialog(hW, res);
return TRUE;
}
case IDCANCEL:
EndDialog(hW, RESULT_CANCELED);
return TRUE;
return TRUE;
}
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case IDOK:
{
INT_PTR res = RESULT_OK;
static wchar_t selectedDevice[500] = {0};
GetWindowTextW(GetDlgItem(hW, IDC_COMBO1), selectedDevice, countof(selectedDevice));
port = (int)GetWindowLongPtr(hW, GWLP_USERDATA);
if (!SaveSetting<std::wstring>(EyeToyWebCamDevice::TypeName(), port, APINAME, N_DEVICE, selectedDevice))
{
res = RESULT_FAILED;
}
EndDialog(hW, res);
return TRUE;
}
case IDCANCEL:
EndDialog(hW, RESULT_CANCELED);
return TRUE;
}
}
}
}
return FALSE;
}
return FALSE;
}
int DirectShow::Configure(int port, const char *dev_type, void *data) {
Win32Handles handles = *(Win32Handles *)data;
return DialogBoxParam(handles.hInst,
MAKEINTRESOURCE(IDD_DLG_EYETOY),
handles.hWnd,
(DLGPROC)DirectShowDlgProc, port);
};
int DirectShow::Configure(int port, const char* dev_type, void* data)
{
Win32Handles handles = *(Win32Handles*)data;
return DialogBoxParam(handles.hInst,
MAKEINTRESOURCE(IDD_DLG_EYETOY),
handles.hWnd,
(DLGPROC)DirectShowDlgProc, port);
};
} // namespace windows_api
} // namespace windows_api
} // namespace usb_eyetoy

View File

@ -22,31 +22,33 @@
#include <dshow.h>
extern "C" {
extern GUID IID_ISampleGrabberCB;
extern GUID CLSID_SampleGrabber;
extern GUID CLSID_NullRenderer;
extern GUID IID_ISampleGrabberCB;
extern GUID CLSID_SampleGrabber;
extern GUID CLSID_NullRenderer;
}
#pragma region qedit.h
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;
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"))
ISampleGrabber : IUnknown {
virtual HRESULT __stdcall SetOneShot (long OneShot) = 0;
virtual HRESULT __stdcall SetMediaType (struct _AMMediaType *pType) = 0;
virtual HRESULT __stdcall GetConnectedMediaType (struct _AMMediaType *pType) = 0;
virtual HRESULT __stdcall SetBufferSamples (long BufferThem) = 0;
virtual HRESULT __stdcall GetCurrentBuffer (long *pBufferSize, long *pBuffer) = 0;
virtual HRESULT __stdcall GetCurrentSample (struct IMediaSample **ppSample) = 0;
virtual HRESULT __stdcall SetCallback (struct ISampleGrabberCB *pCallback, long WhichMethodToCallback) = 0;
ISampleGrabber : IUnknown
{
virtual HRESULT __stdcall SetOneShot(long OneShot) = 0;
virtual HRESULT __stdcall SetMediaType(struct _AMMediaType* pType) = 0;
virtual HRESULT __stdcall GetConnectedMediaType(struct _AMMediaType* pType) = 0;
virtual HRESULT __stdcall SetBufferSamples(long BufferThem) = 0;
virtual HRESULT __stdcall GetCurrentBuffer(long* pBufferSize, long* pBuffer) = 0;
virtual HRESULT __stdcall GetCurrentSample(struct IMediaSample** ppSample) = 0;
virtual HRESULT __stdcall SetCallback(struct ISampleGrabberCB* pCallback, long WhichMethodToCallback) = 0;
};
struct __declspec(uuid("c1f400a0-3f08-11d3-9f0b-006008039e37"))
SampleGrabber;
SampleGrabber;
#pragma endregion
@ -65,73 +67,76 @@ SampleGrabber;
namespace usb_eyetoy
{
namespace windows_api
{
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 {
public:
DirectShow(int port);
~DirectShow() {}
int Open();
int Close();
int GetImage(uint8_t *buf, int len);
int Reset() { return 0; };
static const TCHAR *Name() {
return TEXT("DirectShow");
}
static int Configure(int port, const char *dev_type, void *data);
int Port() { return mPort; }
void Port(int port) { mPort = port; }
protected:
void SetCallback(DShowVideoCaptureCallback cb) { callbackhandler->SetCallback(cb); }
void Start();
void Stop();
int InitializeDevice(std::wstring selectedDevice);
private:
int mPort;
ICaptureGraphBuilder2 *pGraphBuilder;
IFilterGraph2 *pGraph;
IMediaControl *pControl;
IBaseFilter *sourcefilter;
IAMStreamConfig *pSourceConfig;
IBaseFilter *samplegrabberfilter;
ISampleGrabber *samplegrabber;
IBaseFilter *nullrenderer;
class CallbackHandler : public ISampleGrabberCB
namespace windows_api
{
public:
CallbackHandler() { callback = 0; }
~CallbackHandler() {}
void SetCallback(DShowVideoCaptureCallback cb) { callback = cb; }
typedef void (*DShowVideoCaptureCallback)(unsigned char* data, int len, int bitsperpixel);
virtual HRESULT __stdcall SampleCB(double time, IMediaSample *sample);
virtual HRESULT __stdcall BufferCB(double time, BYTE *buffer, long len) { return S_OK; }
virtual HRESULT __stdcall QueryInterface(REFIID iid, LPVOID *ppv);
virtual ULONG __stdcall AddRef() { return 1; }
virtual ULONG __stdcall Release() { return 2; }
typedef struct
{
void* start = NULL;
size_t length = 0;
} buffer_t;
private:
DShowVideoCaptureCallback callback;
static const char* APINAME = "DirectShow";
} * callbackhandler;
};
class DirectShow : public VideoDevice
{
public:
DirectShow(int port);
~DirectShow() {}
int Open();
int Close();
int GetImage(uint8_t* buf, int len);
int Reset() { return 0; };
} // namespace windows_api
static const TCHAR* Name()
{
return TEXT("DirectShow");
}
static int Configure(int port, const char* dev_type, void* data);
int Port() { return mPort; }
void Port(int port) { mPort = port; }
protected:
void SetCallback(DShowVideoCaptureCallback cb) { callbackhandler->SetCallback(cb); }
void Start();
void Stop();
int InitializeDevice(std::wstring selectedDevice);
private:
int mPort;
ICaptureGraphBuilder2* pGraphBuilder;
IFilterGraph2* pGraph;
IMediaControl* pControl;
IBaseFilter* sourcefilter;
IAMStreamConfig* pSourceConfig;
IBaseFilter* samplegrabberfilter;
ISampleGrabber* samplegrabber;
IBaseFilter* nullrenderer;
class CallbackHandler : public ISampleGrabberCB
{
public:
CallbackHandler() { callback = 0; }
~CallbackHandler() {}
void SetCallback(DShowVideoCaptureCallback cb) { callback = cb; }
virtual HRESULT __stdcall SampleCB(double time, IMediaSample* sample);
virtual HRESULT __stdcall BufferCB(double time, BYTE* buffer, long len) { return S_OK; }
virtual HRESULT __stdcall QueryInterface(REFIID iid, LPVOID* ppv);
virtual ULONG __stdcall AddRef() { return 1; }
virtual ULONG __stdcall Release() { return 2; }
private:
DShowVideoCaptureCallback callback;
} * callbackhandler;
};
} // namespace windows_api
} // namespace usb_eyetoy

View File

@ -34,38 +34,163 @@
#include "jo_mpeg.h"
// Huffman tables
static const unsigned char s_jo_HTDC_Y[9][2] = {{4,3}, {0,2}, {1,2}, {5,3}, {6,3}, {14,4}, {30,5}, {62,6}, {126,7}};
static const unsigned char s_jo_HTDC_C[9][2] = {{0,2}, {1,2}, {2,2}, {6,3}, {14,4}, {30,5}, {62,6}, {126,7}, {254,8}};
static const unsigned char s_jo_HTDC_Y[9][2] = {{4, 3}, {0, 2}, {1, 2}, {5, 3}, {6, 3}, {14, 4}, {30, 5}, {62, 6}, {126, 7}};
static const unsigned char s_jo_HTDC_C[9][2] = {{0, 2}, {1, 2}, {2, 2}, {6, 3}, {14, 4}, {30, 5}, {62, 6}, {126, 7}, {254, 8}};
static const unsigned char s_jo_HTAC[32][40][2] = {
{{6,3},{8,5},{10,6},{12,8},{76,9},{66,9},{20,11},{58,13},{48,13},{38,13},{32,13},{52,14},{50,14},{48,14},{46,14},{62,15},{62,15},{58,15},{56,15},{54,15},{52,15},{50,15},{48,15},{46,15},{44,15},{42,15},{40,15},{38,15},{36,15},{34,15},{32,15},{48,16},{46,16},{44,16},{42,16},{40,16},{38,16},{36,16},{34,16},{32,16},},
{{6,4},{12,7},{74,9},{24,11},{54,13},{44,14},{42,14},{62,16},{60,16},{58,16},{56,16},{54,16},{52,16},{50,16},{38,17},{36,17},{34,17},{32,17}},
{{10,5},{8,8},{22,11},{40,13},{40,14}},
{{14,6},{72,9},{56,13},{38,14}},
{{12,6},{30,11},{36,13}}, {{14,7},{18,11},{36,14}}, {{10,7},{60,13},{40,17}},
{{8,7},{42,13}}, {{14,8},{34,13}}, {{10,8},{34,14}}, {{78,9},{32,14}}, {{70,9},{52,17}}, {{68,9},{50,17}}, {{64,9},{48,17}}, {{28,11},{46,17}}, {{26,11},{44,17}}, {{16,11},{42,17}},
{{62,13}}, {{52,13}}, {{50,13}}, {{46,13}}, {{44,13}}, {{62,14}}, {{60,14}}, {{58,14}}, {{56,14}}, {{54,14}}, {{62,17}}, {{60,17}}, {{58,17}}, {{56,17}}, {{54,17}},
{
{6, 3},
{8, 5},
{10, 6},
{12, 8},
{76, 9},
{66, 9},
{20, 11},
{58, 13},
{48, 13},
{38, 13},
{32, 13},
{52, 14},
{50, 14},
{48, 14},
{46, 14},
{62, 15},
{62, 15},
{58, 15},
{56, 15},
{54, 15},
{52, 15},
{50, 15},
{48, 15},
{46, 15},
{44, 15},
{42, 15},
{40, 15},
{38, 15},
{36, 15},
{34, 15},
{32, 15},
{48, 16},
{46, 16},
{44, 16},
{42, 16},
{40, 16},
{38, 16},
{36, 16},
{34, 16},
{32, 16},
},
{{6, 4}, {12, 7}, {74, 9}, {24, 11}, {54, 13}, {44, 14}, {42, 14}, {62, 16}, {60, 16}, {58, 16}, {56, 16}, {54, 16}, {52, 16}, {50, 16}, {38, 17}, {36, 17}, {34, 17}, {32, 17}},
{{10, 5}, {8, 8}, {22, 11}, {40, 13}, {40, 14}},
{{14, 6}, {72, 9}, {56, 13}, {38, 14}},
{{12, 6}, {30, 11}, {36, 13}},
{{14, 7}, {18, 11}, {36, 14}},
{{10, 7}, {60, 13}, {40, 17}},
{{8, 7}, {42, 13}},
{{14, 8}, {34, 13}},
{{10, 8}, {34, 14}},
{{78, 9}, {32, 14}},
{{70, 9}, {52, 17}},
{{68, 9}, {50, 17}},
{{64, 9}, {48, 17}},
{{28, 11}, {46, 17}},
{{26, 11}, {44, 17}},
{{16, 11}, {42, 17}},
{{62, 13}},
{{52, 13}},
{{50, 13}},
{{46, 13}},
{{44, 13}},
{{62, 14}},
{{60, 14}},
{{58, 14}},
{{56, 14}},
{{54, 14}},
{{62, 17}},
{{60, 17}},
{{58, 17}},
{{56, 17}},
{{54, 17}},
};
static const float s_jo_quantTbl[64] = {
0.015625f,0.005632f,0.005035f,0.004832f,0.004808f,0.005892f,0.007964f,0.013325f,
0.005632f,0.004061f,0.003135f,0.003193f,0.003338f,0.003955f,0.004898f,0.008828f,
0.005035f,0.003135f,0.002816f,0.003013f,0.003299f,0.003581f,0.005199f,0.009125f,
0.004832f,0.003484f,0.003129f,0.003348f,0.003666f,0.003979f,0.005309f,0.009632f,
0.005682f,0.003466f,0.003543f,0.003666f,0.003906f,0.004546f,0.005774f,0.009439f,
0.006119f,0.004248f,0.004199f,0.004228f,0.004546f,0.005062f,0.006124f,0.009942f,
0.008883f,0.006167f,0.006096f,0.005777f,0.006078f,0.006391f,0.007621f,0.012133f,
0.016780f,0.011263f,0.009907f,0.010139f,0.009849f,0.010297f,0.012133f,0.019785f,
0.015625f,
0.005632f,
0.005035f,
0.004832f,
0.004808f,
0.005892f,
0.007964f,
0.013325f,
0.005632f,
0.004061f,
0.003135f,
0.003193f,
0.003338f,
0.003955f,
0.004898f,
0.008828f,
0.005035f,
0.003135f,
0.002816f,
0.003013f,
0.003299f,
0.003581f,
0.005199f,
0.009125f,
0.004832f,
0.003484f,
0.003129f,
0.003348f,
0.003666f,
0.003979f,
0.005309f,
0.009632f,
0.005682f,
0.003466f,
0.003543f,
0.003666f,
0.003906f,
0.004546f,
0.005774f,
0.009439f,
0.006119f,
0.004248f,
0.004199f,
0.004228f,
0.004546f,
0.005062f,
0.006124f,
0.009942f,
0.008883f,
0.006167f,
0.006096f,
0.005777f,
0.006078f,
0.006391f,
0.007621f,
0.012133f,
0.016780f,
0.011263f,
0.009907f,
0.010139f,
0.009849f,
0.010297f,
0.012133f,
0.019785f,
};
static const unsigned char s_jo_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
static const unsigned char s_jo_ZigZag[] = {0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63};
typedef struct {
unsigned char *buf_ptr;
typedef struct
{
unsigned char* buf_ptr;
int buf, cnt;
} jo_bits_t;
static void jo_writeBits(jo_bits_t *b, int value, int count) {
static void jo_writeBits(jo_bits_t* b, int value, int count)
{
b->cnt += count;
b->buf |= value << (24 - b->cnt);
while(b->cnt >= 8) {
while (b->cnt >= 8)
{
unsigned char c = (b->buf >> 16) & 255;
//putc(c, b->fp);
*(b->buf_ptr) = c & 0xff;
@ -75,7 +200,8 @@ static void jo_writeBits(jo_bits_t *b, int value, int count) {
}
}
static void jo_DCT(float *d0, float *d1, float *d2, float *d3, float *d4, float *d5, float *d6, float *d7) {
static void jo_DCT(float* d0, float* d1, float* d2, float* d3, float* d4, float* d5, float* d6, float* d7)
{
float tmp0 = *d0 + *d7;
float tmp7 = *d0 - *d7;
float tmp1 = *d1 + *d6;
@ -86,48 +212,52 @@ static void jo_DCT(float *d0, float *d1, float *d2, float *d3, float *d4, float
float tmp4 = *d3 - *d4;
// Even part
float tmp10 = tmp0 + tmp3; // phase 2
float tmp10 = tmp0 + tmp3; // phase 2
float tmp13 = tmp0 - tmp3;
float tmp11 = tmp1 + tmp2;
float tmp12 = tmp1 - tmp2;
*d0 = tmp10 + tmp11; // phase 3
*d0 = tmp10 + tmp11; // phase 3
*d4 = tmp10 - tmp11;
float z1 = (tmp12 + tmp13) * 0.707106781f; // c4
*d2 = tmp13 + z1; // phase 5
*d2 = tmp13 + z1; // phase 5
*d6 = tmp13 - z1;
// Odd part
tmp10 = tmp4 + tmp5; // phase 2
tmp10 = tmp4 + tmp5; // phase 2
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
// The rotator is modified from fig 4-8 to avoid extra negations.
float z5 = (tmp10 - tmp12) * 0.382683433f; // c6
float z2 = tmp10 * 0.541196100f + z5; // c2-c6
float z4 = tmp12 * 1.306562965f + z5; // c2+c6
float z3 = tmp11 * 0.707106781f; // c4
float z2 = tmp10 * 0.541196100f + z5; // c2-c6
float z4 = tmp12 * 1.306562965f + z5; // c2+c6
float z3 = tmp11 * 0.707106781f; // c4
float z11 = tmp7 + z3; // phase 5
float z11 = tmp7 + z3; // phase 5
float z13 = tmp7 - z3;
*d5 = z13 + z2; // phase 6
*d5 = z13 + z2; // phase 6
*d3 = z13 - z2;
*d1 = z11 + z4;
*d7 = z11 - z4;
}
static int jo_processDU(jo_bits_t *bits, float A[64], const unsigned char htdc[9][2], int DC) {
for(int dataOff=0; dataOff<64; dataOff+=8) {
jo_DCT(&A[dataOff], &A[dataOff+1], &A[dataOff+2], &A[dataOff+3], &A[dataOff+4], &A[dataOff+5], &A[dataOff+6], &A[dataOff+7]);
static int jo_processDU(jo_bits_t* bits, float A[64], const unsigned char htdc[9][2], int DC)
{
for (int dataOff = 0; dataOff < 64; dataOff += 8)
{
jo_DCT(&A[dataOff], &A[dataOff + 1], &A[dataOff + 2], &A[dataOff + 3], &A[dataOff + 4], &A[dataOff + 5], &A[dataOff + 6], &A[dataOff + 7]);
}
for(int dataOff=0; dataOff<8; ++dataOff) {
jo_DCT(&A[dataOff], &A[dataOff+8], &A[dataOff+16], &A[dataOff+24], &A[dataOff+32], &A[dataOff+40], &A[dataOff+48], &A[dataOff+56]);
for (int dataOff = 0; dataOff < 8; ++dataOff)
{
jo_DCT(&A[dataOff], &A[dataOff + 8], &A[dataOff + 16], &A[dataOff + 24], &A[dataOff + 32], &A[dataOff + 40], &A[dataOff + 48], &A[dataOff + 56]);
}
int Q[64];
for(int i=0; i<64; ++i) {
float v = A[i]*s_jo_quantTbl[i];
for (int i = 0; i < 64; ++i)
{
float v = A[i] * s_jo_quantTbl[i];
Q[s_jo_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
}
@ -135,36 +265,48 @@ static int jo_processDU(jo_bits_t *bits, float A[64], const unsigned char htdc[9
int aDC = DC < 0 ? -DC : DC;
int size = 0;
int tempval = aDC;
while(tempval) {
while (tempval)
{
size++;
tempval >>= 1;
}
jo_writeBits(bits, htdc[size][0], htdc[size][1]);
if(DC < 0) aDC ^= (1 << size) - 1;
if (DC < 0)
aDC ^= (1 << size) - 1;
jo_writeBits(bits, aDC, size);
int endpos = 63;
for(; (endpos>0)&&(Q[endpos]==0); --endpos) { /* do nothing */ }
for(int i = 1; i <= endpos;) {
for (; (endpos > 0) && (Q[endpos] == 0); --endpos)
{ /* do nothing */
}
for (int i = 1; i <= endpos;)
{
int run = 0;
while (Q[i]==0 && i<endpos) {
while (Q[i] == 0 && i < endpos)
{
++run;
++i;
}
int AC = Q[i++];
int aAC = AC < 0 ? -AC : AC;
int code = 0, size = 0;
if (run<32 && aAC<=40) {
code = s_jo_HTAC[run][aAC-1][0];
size = s_jo_HTAC[run][aAC-1][1];
if (AC < 0) code += 1;
if (run < 32 && aAC <= 40)
{
code = s_jo_HTAC[run][aAC - 1][0];
size = s_jo_HTAC[run][aAC - 1][1];
if (AC < 0)
code += 1;
}
if(!size) {
if (!size)
{
jo_writeBits(bits, 1, 6);
jo_writeBits(bits, run, 6);
if (AC < -127) {
if (AC < -127)
{
jo_writeBits(bits, 128, 12);
} else if(AC > 127) {
}
else if (AC > 127)
{
jo_writeBits(bits, 0, 12);
}
code = AC & 0xFFF;
@ -177,17 +319,23 @@ static int jo_processDU(jo_bits_t *bits, float A[64], const unsigned char htdc[9
return Q[0];
}
unsigned long jo_write_mpeg(unsigned char *mpeg_buf, const unsigned char *raw, int width, int height, int format, int flipx, int flipy) {
unsigned long jo_write_mpeg(unsigned char* mpeg_buf, const unsigned char* raw, int width, int height, int format, int flipx, int flipy)
{
int lastDCY = 128, lastDCCR = 128, lastDCCB = 128;
unsigned char *head = mpeg_buf;
unsigned char* head = mpeg_buf;
jo_bits_t bits = {mpeg_buf};
for (int vblock = 0; vblock < (height+15)/16; vblock++) {
for (int hblock = 0; hblock < (width+15)/16; hblock++) {
if (vblock == 0 && hblock == 0) {
for (int vblock = 0; vblock < (height + 15) / 16; vblock++)
{
for (int hblock = 0; hblock < (width + 15) / 16; hblock++)
{
if (vblock == 0 && hblock == 0)
{
jo_writeBits(&bits, 0b01, 2); // macroblock_type = intra+quant
jo_writeBits(&bits, 8, 5); // quantiser_scale_code = 8
} else {
jo_writeBits(&bits, 8, 5); // quantiser_scale_code = 8
}
else
{
jo_writeBits(&bits, 0b1, 1); // macroblock_address_increment
jo_writeBits(&bits, 0b1, 1); // macroblock_type = intra
}
@ -195,87 +343,113 @@ unsigned long jo_write_mpeg(unsigned char *mpeg_buf, const unsigned char *raw, i
float Y[256], CBx[256], CRx[256];
float CB[64], CR[64];
if (format == JO_RGBX) {
for (int i=0; i<256; ++i) {
int y = vblock*16+(i/16);
int x = hblock*16+(i&15);
x = x >= width ? width-1 : x;
y = y >= height ? height-1 : y;
if (flipx) x = width - 1 - x;
if (flipy) y = height - 1 - y;
const unsigned char *c = raw + y*width*4+x*4;
if (format == JO_RGBX)
{
for (int i = 0; i < 256; ++i)
{
int y = vblock * 16 + (i / 16);
int x = hblock * 16 + (i & 15);
x = x >= width ? width - 1 : x;
y = y >= height ? height - 1 : y;
if (flipx)
x = width - 1 - x;
if (flipy)
y = height - 1 - y;
const unsigned char* c = raw + y * width * 4 + x * 4;
float r, g, b;
if (flipx && flipy) {
if (flipx && flipy)
{
r = c[2], g = c[1], b = c[0];
} else {
}
else
{
r = c[0], g = c[1], b = c[2];
}
Y[i] = (0.299f*r + 0.587f*g + 0.114f*b) * (219.f/255) + 16;
CBx[i] = (-0.299f*r - 0.587f*g + 0.886f*b) * (224.f/255) + 128;
CRx[i] = (0.701f*r - 0.587f*g - 0.114f*b) * (224.f/255) + 128;
Y[i] = (0.299f * r + 0.587f * g + 0.114f * b) * (219.f / 255) + 16;
CBx[i] = (-0.299f * r - 0.587f * g + 0.886f * b) * (224.f / 255) + 128;
CRx[i] = (0.701f * r - 0.587f * g - 0.114f * b) * (224.f / 255) + 128;
}
// Downsample Cb,Cr (420 format)
for (int i=0; i<64; ++i) {
int j =(i&7)*2 + (i&56)*4;
CB[i] = (CBx[j] + CBx[j+1] + CBx[j+16] + CBx[j+17]) * 0.25f;
CR[i] = (CRx[j] + CRx[j+1] + CRx[j+16] + CRx[j+17]) * 0.25f;
for (int i = 0; i < 64; ++i)
{
int j = (i & 7) * 2 + (i & 56) * 4;
CB[i] = (CBx[j] + CBx[j + 1] + CBx[j + 16] + CBx[j + 17]) * 0.25f;
CR[i] = (CRx[j] + CRx[j + 1] + CRx[j + 16] + CRx[j + 17]) * 0.25f;
}
} else
if (format == JO_RGB24) {
for (int i=0; i<256; ++i) {
int y = vblock*16+(i/16);
int x = hblock*16+(i&15);
x = x >= width ? width-1 : x;
y = y >= height ? height-1 : y;
if (flipx) x = width - 1 - x;
if (flipy) y = height - 1 - y;
const unsigned char *c = raw + y*width*3+x*3;
}
else if (format == JO_RGB24)
{
for (int i = 0; i < 256; ++i)
{
int y = vblock * 16 + (i / 16);
int x = hblock * 16 + (i & 15);
x = x >= width ? width - 1 : x;
y = y >= height ? height - 1 : y;
if (flipx)
x = width - 1 - x;
if (flipy)
y = height - 1 - y;
const unsigned char* c = raw + y * width * 3 + x * 3;
float r, g, b;
if (flipx && flipy) {
if (flipx && flipy)
{
r = c[2], g = c[1], b = c[0];
} else {
}
else
{
r = c[0], g = c[1], b = c[2];
}
Y[i] = (0.299f*r + 0.587f*g + 0.114f*b) * (219.f/255) + 16;
CBx[i] = (-0.299f*r - 0.587f*g + 0.886f*b) * (224.f/255) + 128;
CRx[i] = (0.701f*r - 0.587f*g - 0.114f*b) * (224.f/255) + 128;
Y[i] = (0.299f * r + 0.587f * g + 0.114f * b) * (219.f / 255) + 16;
CBx[i] = (-0.299f * r - 0.587f * g + 0.886f * b) * (224.f / 255) + 128;
CRx[i] = (0.701f * r - 0.587f * g - 0.114f * b) * (224.f / 255) + 128;
}
// Downsample Cb,Cr (420 format)
for (int i=0; i<64; ++i) {
int j =(i&7)*2 + (i&56)*4;
CB[i] = (CBx[j] + CBx[j+1] + CBx[j+16] + CBx[j+17]) * 0.25f;
CR[i] = (CRx[j] + CRx[j+1] + CRx[j+16] + CRx[j+17]) * 0.25f;
for (int i = 0; i < 64; ++i)
{
int j = (i & 7) * 2 + (i & 56) * 4;
CB[i] = (CBx[j] + CBx[j + 1] + CBx[j + 16] + CBx[j + 17]) * 0.25f;
CR[i] = (CRx[j] + CRx[j + 1] + CRx[j + 16] + CRx[j + 17]) * 0.25f;
}
} else
if (format == JO_YUYV) {
for (int i=0; i<256; i+=2) {
int y = vblock*16+(i/16);
int x = hblock*16+(i&15);
x = x >= width ? width-1 : x;
y = y >= height ? height-1 : y;
if (flipx) x = width - 1 - x;
if (flipy) y = height - 1 - y;
const unsigned char *c = raw + y*width*2+x*2-2;
if (flipx) {
Y[i+1] = c[0];
CB[i/4] = c[1];
Y[i] = c[2];
CR[i/4] = c[3];
} else {
Y[i] = c[2];
CB[i/4] = c[3];
Y[i+1] = c[4];
CR[i/4] = c[5];
}
else if (format == JO_YUYV)
{
for (int i = 0; i < 256; i += 2)
{
int y = vblock * 16 + (i / 16);
int x = hblock * 16 + (i & 15);
x = x >= width ? width - 1 : x;
y = y >= height ? height - 1 : y;
if (flipx)
x = width - 1 - x;
if (flipy)
y = height - 1 - y;
const unsigned char* c = raw + y * width * 2 + x * 2 - 2;
if (flipx)
{
Y[i + 1] = c[0];
CB[i / 4] = c[1];
Y[i] = c[2];
CR[i / 4] = c[3];
}
else
{
Y[i] = c[2];
CB[i / 4] = c[3];
Y[i + 1] = c[4];
CR[i / 4] = c[5];
}
}
}
for (int k1=0; k1<2; ++k1) {
for (int k2=0; k2<2; ++k2) {
for (int k1 = 0; k1 < 2; ++k1)
{
for (int k2 = 0; k2 < 2; ++k2)
{
float block[64];
for (int i=0; i<64; i+=8) {
int j = (i&7)+(i&56)*2 + k1*8*16 + k2*8;
memcpy(block+i, Y+j, 8*sizeof(Y[0]));
for (int i = 0; i < 64; i += 8)
{
int j = (i & 7) + (i & 56) * 2 + k1 * 8 * 16 + k2 * 8;
memcpy(block + i, Y + j, 8 * sizeof(Y[0]));
}
lastDCY = jo_processDU(&bits, block, s_jo_HTDC_Y, lastDCY);
}

View File

@ -17,19 +17,21 @@
extern "C" {
#endif
typedef enum {
typedef enum
{
JO_RGBX,
JO_RGB24,
JO_YUYV,
} jo_mpeg_format_t;
typedef enum {
typedef enum
{
JO_NONE,
JO_FLIP_X,
JO_FLIP_Y,
} jo_mpeg_flip_t;
unsigned long jo_write_mpeg(unsigned char *mpeg_buf, const unsigned char *rgbx, int width, int height, int format, int flipx, int flipy);
unsigned long jo_write_mpeg(unsigned char* mpeg_buf, const unsigned char* rgbx, int width, int height, int format, int flipx, int flipy);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -11,9 +11,9 @@
#include <stdint.h>
#ifdef _MSC_VER
#define JPGD_NORETURN __declspec(noreturn)
#define JPGD_NORETURN __declspec(noreturn)
#elif defined(__GNUC__)
#define JPGD_NORETURN __attribute__ ((noreturn))
#define JPGD_NORETURN __attribute__((noreturn))
#else
#define JPGD_NORETURN
#endif
@ -23,11 +23,11 @@
namespace jpgd
{
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef unsigned int uint;
typedef signed int int32;
typedef unsigned int uint;
typedef signed int int32;
// Loads a JPEG image from a memory buffer or a file.
// req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA).
@ -40,15 +40,42 @@ namespace jpgd
// Success/failure error codes.
enum jpgd_status
{
JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1,
JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE,
JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS,
JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH,
JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER,
JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS,
JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE,
JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER,
JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM, JPGD_TOO_MANY_SCANS
JPGD_SUCCESS = 0,
JPGD_FAILED = -1,
JPGD_DONE = 1,
JPGD_BAD_DHT_COUNTS = -256,
JPGD_BAD_DHT_INDEX,
JPGD_BAD_DHT_MARKER,
JPGD_BAD_DQT_MARKER,
JPGD_BAD_DQT_TABLE,
JPGD_BAD_PRECISION,
JPGD_BAD_HEIGHT,
JPGD_BAD_WIDTH,
JPGD_TOO_MANY_COMPONENTS,
JPGD_BAD_SOF_LENGTH,
JPGD_BAD_VARIABLE_MARKER,
JPGD_BAD_DRI_LENGTH,
JPGD_BAD_SOS_LENGTH,
JPGD_BAD_SOS_COMP_ID,
JPGD_W_EXTRA_BYTES_BEFORE_MARKER,
JPGD_NO_ARITHMITIC_SUPPORT,
JPGD_UNEXPECTED_MARKER,
JPGD_NOT_JPEG,
JPGD_UNSUPPORTED_MARKER,
JPGD_BAD_DQT_LENGTH,
JPGD_TOO_MANY_BLOCKS,
JPGD_UNDEFINED_QUANT_TABLE,
JPGD_UNDEFINED_HUFF_TABLE,
JPGD_NOT_SINGLE_SCAN,
JPGD_UNSUPPORTED_COLORSPACE,
JPGD_UNSUPPORTED_SAMP_FACTORS,
JPGD_DECODE_ERROR,
JPGD_BAD_RESTART_MARKER,
JPGD_BAD_SOS_SPECTRAL,
JPGD_BAD_SOS_SUCCESSIVE,
JPGD_STREAM_READ,
JPGD_NOTENOUGHMEM,
JPGD_TOO_MANY_SCANS
};
// Input stream interface.
@ -59,8 +86,8 @@ namespace jpgd
class jpeg_decoder_stream
{
public:
jpeg_decoder_stream() { }
virtual ~jpeg_decoder_stream() { }
jpeg_decoder_stream() {}
virtual ~jpeg_decoder_stream() {}
// The read() method is called when the internal input buffer is empty.
// Parameters:
@ -76,7 +103,7 @@ namespace jpgd
class jpeg_decoder_file_stream : public jpeg_decoder_stream
{
jpeg_decoder_file_stream(const jpeg_decoder_file_stream&);
jpeg_decoder_file_stream& operator =(const jpeg_decoder_file_stream&);
jpeg_decoder_file_stream& operator=(const jpeg_decoder_file_stream&);
FILE* m_pFile;
bool m_eof_flag, m_error_flag;
@ -98,13 +125,28 @@ namespace jpgd
uint m_ofs, m_size;
public:
jpeg_decoder_mem_stream() : m_pSrc_data(NULL), m_ofs(0), m_size(0) { }
jpeg_decoder_mem_stream(const uint8* pSrc_data, uint size) : m_pSrc_data(pSrc_data), m_ofs(0), m_size(size) { }
jpeg_decoder_mem_stream()
: m_pSrc_data(NULL)
, m_ofs(0)
, m_size(0)
{
}
jpeg_decoder_mem_stream(const uint8* pSrc_data, uint size)
: m_pSrc_data(pSrc_data)
, m_ofs(0)
, m_size(size)
{
}
virtual ~jpeg_decoder_mem_stream() { }
virtual ~jpeg_decoder_mem_stream() {}
bool open(const uint8* pSrc_data, uint size);
void close() { m_pSrc_data = NULL; m_ofs = 0; m_size = 0; }
void close()
{
m_pSrc_data = NULL;
m_ofs = 0;
m_size = 0;
}
virtual int read(uint8* pBuf, int max_bytes_to_read, bool* pEOF_flag);
};
@ -114,8 +156,15 @@ namespace jpgd
enum
{
JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4,
JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 16384, JPGD_MAX_HEIGHT = 32768, JPGD_MAX_WIDTH = 32768
JPGD_IN_BUF_SIZE = 8192,
JPGD_MAX_BLOCKS_PER_MCU = 10,
JPGD_MAX_HUFF_TABLES = 8,
JPGD_MAX_QUANT_TABLES = 4,
JPGD_MAX_COMPONENTS = 4,
JPGD_MAX_COMPS_IN_SCAN = 4,
JPGD_MAX_BLOCKS_PER_ROW = 16384,
JPGD_MAX_HEIGHT = 32768,
JPGD_MAX_WIDTH = 32768
};
typedef int16 jpgd_quant_t;
@ -142,7 +191,7 @@ namespace jpgd
int begin_decoding();
// Returns the next scan line.
// For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1).
// For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1).
// Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4).
// Returns JPGD_SUCCESS if a scan line has been returned.
// Returns JPGD_DONE if all scan lines have been returned.
@ -164,17 +213,17 @@ namespace jpgd
private:
jpeg_decoder(const jpeg_decoder&);
jpeg_decoder& operator =(const jpeg_decoder&);
jpeg_decoder& operator=(const jpeg_decoder&);
typedef void (*pDecode_block_func)(jpeg_decoder*, int, int, int);
struct huff_tables
{
bool ac_table;
uint look_up[256];
uint look_up2[256];
uint look_up[256];
uint look_up2[256];
uint8 code_size[JPGD_HUFF_CODE_SIZE_MAX_LENGTH];
uint tree[JPGD_HUFF_TREE_MAX_LENGTH];
uint tree[JPGD_HUFF_TREE_MAX_LENGTH];
};
struct coeff_buf
@ -214,26 +263,26 @@ namespace jpgd
int m_comp_ident[JPGD_MAX_COMPONENTS]; // component's ID
int m_comp_h_blocks[JPGD_MAX_COMPONENTS];
int m_comp_v_blocks[JPGD_MAX_COMPONENTS];
int m_comps_in_scan; // # of components in scan
int m_comp_list[JPGD_MAX_COMPS_IN_SCAN]; // components in this scan
int m_comp_dc_tab[JPGD_MAX_COMPONENTS]; // component's DC Huffman coding table selector
int m_comp_ac_tab[JPGD_MAX_COMPONENTS]; // component's AC Huffman coding table selector
int m_spectral_start; // spectral selection start
int m_spectral_end; // spectral selection end
int m_successive_low; // successive approximation low
int m_successive_high; // successive approximation high
int m_max_mcu_x_size; // MCU's max. X size in pixels
int m_max_mcu_y_size; // MCU's max. Y size in pixels
int m_comps_in_scan; // # of components in scan
int m_comp_list[JPGD_MAX_COMPS_IN_SCAN]; // components in this scan
int m_comp_dc_tab[JPGD_MAX_COMPONENTS]; // component's DC Huffman coding table selector
int m_comp_ac_tab[JPGD_MAX_COMPONENTS]; // component's AC Huffman coding table selector
int m_spectral_start; // spectral selection start
int m_spectral_end; // spectral selection end
int m_successive_low; // successive approximation low
int m_successive_high; // successive approximation high
int m_max_mcu_x_size; // MCU's max. X size in pixels
int m_max_mcu_y_size; // MCU's max. Y size in pixels
int m_blocks_per_mcu;
int m_max_blocks_per_row;
int m_mcus_per_row, m_mcus_per_col;
int m_mcu_org[JPGD_MAX_BLOCKS_PER_MCU];
int m_total_lines_left; // total # lines left in image
int m_mcu_lines_left; // total # lines left in this MCU
int m_total_lines_left; // total # lines left in image
int m_mcu_lines_left; // total # lines left in this MCU
int m_num_buffered_scanlines;
int m_real_dest_bytes_per_scan_line;
int m_dest_bytes_per_scan_line; // rounded up
int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y)
int m_dest_bytes_per_scan_line; // rounded up
int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y)
huff_tables* m_pHuff_tabs[JPGD_MAX_HUFF_TABLES];
coeff_buf* m_dc_coeffs[JPGD_MAX_COMPONENTS];
coeff_buf* m_ac_coeffs[JPGD_MAX_COMPONENTS];
@ -275,7 +324,12 @@ namespace jpgd
bool m_sample_buf_prev_valid;
bool m_has_sse2;
inline int check_sample_buf_ofs(int ofs) const { assert(ofs >= 0); assert(ofs < m_max_blocks_per_row * 64); return ofs; }
inline int check_sample_buf_ofs(int ofs) const
{
assert(ofs >= 0);
assert(ofs < m_max_blocks_per_row * 64);
return ofs;
}
void free_all_blocks();
JPGD_NORETURN void stop_decoding(jpgd_status status);
void* alloc(size_t n, bool zero = false);

View File

@ -24,26 +24,26 @@
#include <immintrin.h>
#ifdef _MSC_VER
#define JPGD_SIMD_ALIGN(type, name) __declspec(align(16)) type name
#define JPGD_SIMD_ALIGN(type, name) __declspec(align(16)) type name
#else
#define JPGD_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
#define JPGD_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
#endif
#define BITS_INV_ACC 4
#define SHIFT_INV_ROW 16 - BITS_INV_ACC
#define SHIFT_INV_COL 1 + BITS_INV_ACC
const short IRND_INV_ROW = 1024 * (6 - BITS_INV_ACC); //1 << (SHIFT_INV_ROW-1)
const short IRND_INV_COL = 16 * (BITS_INV_ACC - 3); // 1 << (SHIFT_INV_COL-1)
const short IRND_INV_CORR = IRND_INV_COL - 1; // correction -1.0 and round
const short IRND_INV_ROW = 1024 * (6 - BITS_INV_ACC); //1 << (SHIFT_INV_ROW-1)
const short IRND_INV_COL = 16 * (BITS_INV_ACC - 3); // 1 << (SHIFT_INV_COL-1)
const short IRND_INV_CORR = IRND_INV_COL - 1; // correction -1.0 and round
JPGD_SIMD_ALIGN(short, shortM128_one_corr[8]) = {1, 1, 1, 1, 1, 1, 1, 1};
JPGD_SIMD_ALIGN(short, shortM128_round_inv_row[8]) = {IRND_INV_ROW, 0, IRND_INV_ROW, 0, IRND_INV_ROW, 0, IRND_INV_ROW, 0};
JPGD_SIMD_ALIGN(short, shortM128_round_inv_col[8]) = {IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL};
JPGD_SIMD_ALIGN(short, shortM128_round_inv_corr[8])= {IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR};
JPGD_SIMD_ALIGN(short, shortM128_tg_1_16[8]) = {13036, 13036, 13036, 13036, 13036, 13036, 13036, 13036}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_tg_2_16[8]) = {27146, 27146, 27146, 27146, 27146, 27146, 27146, 27146}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_tg_3_16[8]) = {-21746, -21746, -21746, -21746, -21746, -21746, -21746, -21746}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_cos_4_16[8]) = {-19195, -19195, -19195, -19195, -19195, -19195, -19195, -19195};// cos * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_round_inv_corr[8]) = {IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR};
JPGD_SIMD_ALIGN(short, shortM128_tg_1_16[8]) = {13036, 13036, 13036, 13036, 13036, 13036, 13036, 13036}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_tg_2_16[8]) = {27146, 27146, 27146, 27146, 27146, 27146, 27146, 27146}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_tg_3_16[8]) = {-21746, -21746, -21746, -21746, -21746, -21746, -21746, -21746}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_cos_4_16[8]) = {-19195, -19195, -19195, -19195, -19195, -19195, -19195, -19195}; // cos * (2<<16) + 0.5
//-----------------------------------------------------------------------------
// Table for rows 0,4 - constants are multiplied on cos_4_16
@ -56,22 +56,22 @@ JPGD_SIMD_ALIGN(short, shortM128_tab_i_04[]) = {
16384, -8867, 16384, -21407, // w13 w12 w09 w08
16384, 8867, -16384, -21407, // w07 w06 w03 w02
-16384, 21407, 16384, -8867, // w15 w14 w11 w10
22725, 19266, 19266, -4520, // w21 w20 w17 w16
22725, 19266, 19266, -4520, // w21 w20 w17 w16
12873, -22725, 4520, -12873, // w29 w28 w25 w24
12873, 4520, -22725, -12873, // w23 w22 w19 w18
4520, 19266, 19266, -22725}; // w31 w30 w27 w26
// Table for rows 1,7 - constants are multiplied on cos_1_16
// Table for rows 1,7 - constants are multiplied on cos_1_16
//movq -> w05 w04 w01 w00
JPGD_SIMD_ALIGN(short, shortM128_tab_i_17[]) = {
22725, 29692, 22725, 12299,
22725, -12299, 22725, -29692, // w13 w12 w09 w08
22725, 12299, -22725, -29692, // w07 w06 w03 w02
-22725, 29692, 22725, -12299, // w15 w14 w11 w10
31521, 26722, 26722, -6270, // w21 w20 w17 w16
17855, -31521, 6270, -17855, // w29 w28 w25 w24
17855, 6270, -31521, -17855, // w23 w22 w19 w18
6270, 26722, 26722, -31521}; // w31 w30 w27 w26
31521, 26722, 26722, -6270, // w21 w20 w17 w16
17855, -31521, 6270, -17855, // w29 w28 w25 w24
17855, 6270, -31521, -17855, // w23 w22 w19 w18
6270, 26722, 26722, -31521}; // w31 w30 w27 w26
// Table for rows 2,6 - constants are multiplied on cos_2_16
//movq -> w05 w04 w01 w00
@ -80,10 +80,10 @@ JPGD_SIMD_ALIGN(short, shortM128_tab_i_26[]) = {
21407, -11585, 21407, -27969, // w13 w12 w09 w08
21407, 11585, -21407, -27969, // w07 w06 w03 w02
-21407, 27969, 21407, -11585, // w15 w14 w11 w10
29692, 25172, 25172, -5906, // w21 w20 w17 w16
16819, -29692, 5906, -16819, // w29 w28 w25 w24
16819, 5906, -29692, -16819, // w23 w22 w19 w18
5906, 25172, 25172, -29692}; // w31 w30 w27 w26
29692, 25172, 25172, -5906, // w21 w20 w17 w16
16819, -29692, 5906, -16819, // w29 w28 w25 w24
16819, 5906, -29692, -16819, // w23 w22 w19 w18
5906, 25172, 25172, -29692}; // w31 w30 w27 w26
// Table for rows 3,5 - constants are multiplied on cos_3_16
//movq -> w05 w04 w01 w00
JPGD_SIMD_ALIGN(short, shortM128_tab_i_35[]) = {
@ -91,28 +91,28 @@ JPGD_SIMD_ALIGN(short, shortM128_tab_i_35[]) = {
19266, -10426, 19266, -25172, // w13 w12 w09 w08
19266, 10426, -19266, -25172, // w07 w06 w03 w02
-19266, 25172, 19266, -10426, // w15 w14 w11 w10
26722, 22654, 22654, -5315, // w21 w20 w17 w16
15137, -26722, 5315, -15137, // w29 w28 w25 w24
15137, 5315, -26722, -15137, // w23 w22 w19 w18
5315, 22654, 22654, -26722}; // w31 w30 w27 w26
26722, 22654, 22654, -5315, // w21 w20 w17 w16
15137, -26722, 5315, -15137, // w29 w28 w25 w24
15137, 5315, -26722, -15137, // w23 w22 w19 w18
5315, 22654, 22654, -26722}; // w31 w30 w27 w26
JPGD_SIMD_ALIGN(short, shortM128_128[8]) = { 128, 128, 128, 128, 128, 128, 128, 128 };
JPGD_SIMD_ALIGN(short, shortM128_128[8]) = {128, 128, 128, 128, 128, 128, 128, 128};
void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
void idctSSEShortU8(const short* pInput, uint8_t* pOutputUB)
{
__m128i r_xmm0, r_xmm4;
__m128i r_xmm1, r_xmm2, r_xmm3, r_xmm5, r_xmm6, r_xmm7;
__m128i row0, row1, row2, row3, row4, row5, row6, row7;
short * pTab_i_04 = shortM128_tab_i_04;
short * pTab_i_26 = shortM128_tab_i_26;
short* pTab_i_04 = shortM128_tab_i_04;
short* pTab_i_26 = shortM128_tab_i_26;
//Get pointers for this input and output
pTab_i_04 = shortM128_tab_i_04;
pTab_i_26 = shortM128_tab_i_26;
//Row 1 and Row 3
r_xmm0 = _mm_load_si128((__m128i *) pInput);
r_xmm4 = _mm_load_si128((__m128i *) (&pInput[2*8]));
r_xmm0 = _mm_load_si128((__m128i*)pInput);
r_xmm4 = _mm_load_si128((__m128i*)(&pInput[2 * 8]));
// *** Work on the data in xmm0
//low shuffle mask = 0xd8 = 11 01 10 00
@ -121,58 +121,58 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
// copy short 2 and short 0 to all locations
r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
// add to those copies
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *) pTab_i_04));
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i*)pTab_i_04));
// shuffle mask = 0x55 = 01 01 01 01
// copy short 3 and short 1 to all locations
r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
// high shuffle mask = 0xd8 = 11 01 10 00
// get short 6 and short 4 into bit positions 64-95
// get short 7 and short 5 into bit positions 96-127
r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
// add to short 3 and short 1
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *) &pTab_i_04[16]));
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i*)&pTab_i_04[16]));
// shuffle mask = 0xaa = 10 10 10 10
// copy short 6 and short 4 to all locations
r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
// shuffle mask = 0xaa = 11 11 11 11
// copy short 7 and short 5 to all locations
r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
// add to short 6 and short 4
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *) &pTab_i_04[8]));
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i*)&pTab_i_04[8]));
// *** Work on the data in xmm4
// high shuffle mask = 0xd8 11 01 10 00
// get short 6 and short 4 into bit positions 64-95
// get short 7 and short 5 into bit positions 96-127
r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
// (xmm0 short 2 and short 0 plus pSi) + some constants
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *) shortM128_round_inv_row));
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i*)shortM128_round_inv_row));
r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *) &pTab_i_04[24]));
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i*)&pTab_i_04[24]));
r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *) &shortM128_tab_i_26[0]));
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i*)&shortM128_tab_i_26[0]));
r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
r_xmm2 = r_xmm1;
r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *) &shortM128_tab_i_26[8]));
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i*)&shortM128_tab_i_26[8]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *) &shortM128_tab_i_26[16]));
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i*)&shortM128_tab_i_26[16]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *) shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *) &shortM128_tab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i*)shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i*)&shortM128_tab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
r_xmm6 = r_xmm5;
r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
@ -187,37 +187,37 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
row2 = _mm_packs_epi32(r_xmm4, r_xmm6);
//Row 5 and row 7
r_xmm0 = _mm_load_si128((__m128i *) (&pInput[4*8]));
r_xmm4 = _mm_load_si128((__m128i *) (&pInput[6*8]));
r_xmm0 = _mm_load_si128((__m128i*)(&pInput[4 * 8]));
r_xmm4 = _mm_load_si128((__m128i*)(&pInput[6 * 8]));
r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *) pTab_i_04));
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i*)pTab_i_04));
r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *) &pTab_i_04[16]));
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i*)&pTab_i_04[16]));
r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *) &pTab_i_04[8]));
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i*)&pTab_i_04[8]));
r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *) shortM128_round_inv_row));
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i*)shortM128_round_inv_row));
r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *) &pTab_i_04[24]));
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i*)&pTab_i_04[24]));
r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *) &shortM128_tab_i_26[0]));
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i*)&shortM128_tab_i_26[0]));
r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
r_xmm2 = r_xmm1;
r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *) &shortM128_tab_i_26[8]));
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i*)&shortM128_tab_i_26[8]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *) &shortM128_tab_i_26[16]));
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i*)&shortM128_tab_i_26[16]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *) shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *) &shortM128_tab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i*)shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i*)&shortM128_tab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
r_xmm6 = r_xmm5;
r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
@ -234,37 +234,37 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
//Row 4 and row 2
pTab_i_04 = shortM128_tab_i_35;
pTab_i_26 = shortM128_tab_i_17;
r_xmm0 = _mm_load_si128((__m128i *) (&pInput[3*8]));
r_xmm4 = _mm_load_si128((__m128i *) (&pInput[1*8]));
r_xmm0 = _mm_load_si128((__m128i*)(&pInput[3 * 8]));
r_xmm4 = _mm_load_si128((__m128i*)(&pInput[1 * 8]));
r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *) pTab_i_04));
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i*)pTab_i_04));
r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *) &pTab_i_04[16]));
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i*)&pTab_i_04[16]));
r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *) &pTab_i_04[8]));
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i*)&pTab_i_04[8]));
r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *) shortM128_round_inv_row));
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i*)shortM128_round_inv_row));
r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *) &pTab_i_04[24]));
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i*)&pTab_i_04[24]));
r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *) &pTab_i_26[0]));
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i*)&pTab_i_26[0]));
r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
r_xmm2 = r_xmm1;
r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *) &pTab_i_26[8]));
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i*)&pTab_i_26[8]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *) &pTab_i_26[16]));
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i*)&pTab_i_26[16]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *) shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *) &pTab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i*)shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i*)&pTab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
r_xmm6 = r_xmm5;
r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
@ -279,37 +279,37 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
row1 = _mm_packs_epi32(r_xmm4, r_xmm6);
//Row 6 and row 8
r_xmm0 = _mm_load_si128((__m128i *) (&pInput[5*8]));
r_xmm4 = _mm_load_si128((__m128i *) (&pInput[7*8]));
r_xmm0 = _mm_load_si128((__m128i*)(&pInput[5 * 8]));
r_xmm4 = _mm_load_si128((__m128i*)(&pInput[7 * 8]));
r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *) pTab_i_04));
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i*)pTab_i_04));
r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *) &pTab_i_04[16]));
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i*)&pTab_i_04[16]));
r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *) &pTab_i_04[8]));
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i*)&pTab_i_04[8]));
r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *) shortM128_round_inv_row));
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i*)shortM128_round_inv_row));
r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *) &pTab_i_04[24]));
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i*)&pTab_i_04[24]));
r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *) &pTab_i_26[0]));
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i*)&pTab_i_26[0]));
r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
r_xmm2 = r_xmm1;
r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *) &pTab_i_26[8]));
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i*)&pTab_i_26[8]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *) &pTab_i_26[16]));
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i*)&pTab_i_26[16]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *) shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *) &pTab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i*)shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i*)&pTab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
r_xmm6 = r_xmm5;
r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
@ -323,13 +323,13 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
row7 = _mm_packs_epi32(r_xmm4, r_xmm6);
r_xmm1 = _mm_load_si128((__m128i *) shortM128_tg_3_16);
r_xmm1 = _mm_load_si128((__m128i*)shortM128_tg_3_16);
r_xmm2 = row5;
r_xmm3 = row3;
r_xmm0 = _mm_mulhi_epi16(row5, r_xmm1);
r_xmm1 = _mm_mulhi_epi16(r_xmm1, r_xmm3);
r_xmm5 = _mm_load_si128((__m128i *) shortM128_tg_1_16);
r_xmm5 = _mm_load_si128((__m128i*)shortM128_tg_1_16);
r_xmm6 = row7;
r_xmm4 = _mm_mulhi_epi16(row7, r_xmm5);
@ -339,7 +339,7 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
r_xmm7 = row6;
r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm3);
r_xmm3 = _mm_load_si128((__m128i *) shortM128_tg_2_16);
r_xmm3 = _mm_load_si128((__m128i*)shortM128_tg_2_16);
r_xmm2 = _mm_subs_epi16(r_xmm2, r_xmm1);
r_xmm7 = _mm_mulhi_epi16(r_xmm7, r_xmm3);
r_xmm1 = r_xmm0;
@ -347,11 +347,11 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
r_xmm5 = _mm_subs_epi16(r_xmm5, r_xmm6);
r_xmm4 = _mm_adds_epi16(r_xmm4, row1);
r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm4);
r_xmm0 = _mm_adds_epi16(r_xmm0, *((__m128i *) shortM128_one_corr));
r_xmm0 = _mm_adds_epi16(r_xmm0, *((__m128i*)shortM128_one_corr));
r_xmm4 = _mm_subs_epi16(r_xmm4, r_xmm1);
r_xmm6 = r_xmm5;
r_xmm5 = _mm_subs_epi16(r_xmm5, r_xmm2);
r_xmm5 = _mm_adds_epi16(r_xmm5, *((__m128i *) shortM128_one_corr));
r_xmm5 = _mm_adds_epi16(r_xmm5, *((__m128i*)shortM128_one_corr));
r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm2);
//Intermediate results, needed later
@ -359,9 +359,9 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
temp7 = r_xmm0;
r_xmm1 = r_xmm4;
r_xmm0 = _mm_load_si128((__m128i *) shortM128_cos_4_16);
r_xmm0 = _mm_load_si128((__m128i*)shortM128_cos_4_16);
r_xmm4 = _mm_adds_epi16(r_xmm4, r_xmm5);
r_xmm2 = _mm_load_si128((__m128i *) shortM128_cos_4_16);
r_xmm2 = _mm_load_si128((__m128i*)shortM128_cos_4_16);
r_xmm2 = _mm_mulhi_epi16(r_xmm2, r_xmm4);
//Intermediate results, needed later
@ -377,24 +377,24 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
r_xmm6 = _mm_subs_epi16(r_xmm6, row4);
r_xmm4 = _mm_adds_epi16(r_xmm4, r_xmm2);
r_xmm4 = _mm_or_si128(r_xmm4, *((__m128i *) shortM128_one_corr));
r_xmm4 = _mm_or_si128(r_xmm4, *((__m128i*)shortM128_one_corr));
r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm1);
r_xmm0 = _mm_or_si128(r_xmm0, *((__m128i *) shortM128_one_corr));
r_xmm0 = _mm_or_si128(r_xmm0, *((__m128i*)shortM128_one_corr));
r_xmm2 = r_xmm5;
r_xmm5 = _mm_adds_epi16(r_xmm5, r_xmm7);
r_xmm1 = r_xmm6;
r_xmm5 = _mm_adds_epi16(r_xmm5, *((__m128i *) shortM128_round_inv_col));
r_xmm5 = _mm_adds_epi16(r_xmm5, *((__m128i*)shortM128_round_inv_col));
r_xmm2 = _mm_subs_epi16(r_xmm2, r_xmm7);
r_xmm7 = temp7;
r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm3);
r_xmm6 = _mm_adds_epi16(r_xmm6, *((__m128i *) shortM128_round_inv_col));
r_xmm6 = _mm_adds_epi16(r_xmm6, *((__m128i*)shortM128_round_inv_col));
r_xmm7 = _mm_adds_epi16(r_xmm7, r_xmm5);
r_xmm7 = _mm_srai_epi16(r_xmm7, SHIFT_INV_COL);
r_xmm1 = _mm_subs_epi16(r_xmm1, r_xmm3);
r_xmm1 = _mm_adds_epi16(r_xmm1, *((__m128i *) shortM128_round_inv_corr));
r_xmm1 = _mm_adds_epi16(r_xmm1, *((__m128i*)shortM128_round_inv_corr));
r_xmm3 = r_xmm6;
r_xmm2 = _mm_adds_epi16(r_xmm2, *((__m128i *) shortM128_round_inv_corr));
r_xmm2 = _mm_adds_epi16(r_xmm2, *((__m128i*)shortM128_round_inv_corr));
r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm4);
//Store results for row 0
@ -406,7 +406,7 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
r_xmm1 = _mm_adds_epi16(r_xmm1, r_xmm0);
//Store results for row 1
//_mm_store_si128((__m128i *) (&pOutput[1*8]), r_xmm6);
//_mm_store_si128((__m128i *) (&pOutput[1*8]), r_xmm6);
__m128i r1 = r_xmm6;
r_xmm1 = _mm_srai_epi16(r_xmm1, SHIFT_INV_COL);
@ -415,24 +415,24 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
r_xmm7 = _mm_srai_epi16(r_xmm7, SHIFT_INV_COL);
//Store results for row 2
//_mm_store_si128((__m128i *) (&pOutput[2*8]), r_xmm1);
//_mm_store_si128((__m128i *) (&pOutput[2*8]), r_xmm1);
__m128i r2 = r_xmm1;
r_xmm5 = _mm_subs_epi16(r_xmm5, temp7);
r_xmm5 = _mm_subs_epi16(r_xmm5, temp7);
r_xmm5 = _mm_srai_epi16(r_xmm5, SHIFT_INV_COL);
//Store results for row 7
//_mm_store_si128((__m128i *) (&pOutput[7*8]), r_xmm5);
//_mm_store_si128((__m128i *) (&pOutput[7*8]), r_xmm5);
__m128i r7 = r_xmm5;
r_xmm3 = _mm_subs_epi16(r_xmm3, r_xmm4);
r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm2);
r_xmm2 = _mm_subs_epi16(r_xmm2, temp3);
r_xmm2 = _mm_subs_epi16(r_xmm2, temp3);
r_xmm6 = _mm_srai_epi16(r_xmm6, SHIFT_INV_COL);
r_xmm2 = _mm_srai_epi16(r_xmm2, SHIFT_INV_COL);
//Store results for row 3
//_mm_store_si128((__m128i *) (&pOutput[3*8]), r_xmm6);
//_mm_store_si128((__m128i *) (&pOutput[3*8]), r_xmm6);
__m128i r3 = r_xmm6;
r_xmm3 = _mm_srai_epi16(r_xmm3, SHIFT_INV_COL);
@ -446,17 +446,17 @@ void idctSSEShortU8(const short *pInput, uint8_t * pOutputUB)
__m128i r5 = r_xmm7;
__m128i r6 = r_xmm3;
r0 = _mm_add_epi16(*(const __m128i *)shortM128_128, r0);
r1 = _mm_add_epi16(*(const __m128i *)shortM128_128, r1);
r2 = _mm_add_epi16(*(const __m128i *)shortM128_128, r2);
r3 = _mm_add_epi16(*(const __m128i *)shortM128_128, r3);
r4 = _mm_add_epi16(*(const __m128i *)shortM128_128, r4);
r5 = _mm_add_epi16(*(const __m128i *)shortM128_128, r5);
r6 = _mm_add_epi16(*(const __m128i *)shortM128_128, r6);
r7 = _mm_add_epi16(*(const __m128i *)shortM128_128, r7);
r0 = _mm_add_epi16(*(const __m128i*)shortM128_128, r0);
r1 = _mm_add_epi16(*(const __m128i*)shortM128_128, r1);
r2 = _mm_add_epi16(*(const __m128i*)shortM128_128, r2);
r3 = _mm_add_epi16(*(const __m128i*)shortM128_128, r3);
r4 = _mm_add_epi16(*(const __m128i*)shortM128_128, r4);
r5 = _mm_add_epi16(*(const __m128i*)shortM128_128, r5);
r6 = _mm_add_epi16(*(const __m128i*)shortM128_128, r6);
r7 = _mm_add_epi16(*(const __m128i*)shortM128_128, r7);
((__m128i *)pOutputUB)[0] = _mm_packus_epi16(r0, r1);
((__m128i *)pOutputUB)[1] = _mm_packus_epi16(r2, r3);
((__m128i *)pOutputUB)[2] = _mm_packus_epi16(r4, r5);
((__m128i *)pOutputUB)[3] = _mm_packus_epi16(r6, r7);
((__m128i*)pOutputUB)[0] = _mm_packus_epi16(r0, r1);
((__m128i*)pOutputUB)[1] = _mm_packus_epi16(r2, r3);
((__m128i*)pOutputUB)[2] = _mm_packus_epi16(r4, r5);
((__m128i*)pOutputUB)[3] = _mm_packus_epi16(r6, r7);
}

View File

@ -14,43 +14,42 @@
*/
/* I2C registers */
#define R51x_I2C_W_SID 0x41
#define R51x_I2C_SADDR_3 0x42
#define R51x_I2C_SADDR_2 0x43
#define R51x_I2C_R_SID 0x44
#define R51x_I2C_DATA 0x45
#define R518_I2C_CTL 0x47 /* OV518(+) only */
#define OVFX2_I2C_ADDR 0x00
#define R51x_I2C_W_SID 0x41
#define R51x_I2C_SADDR_3 0x42
#define R51x_I2C_SADDR_2 0x43
#define R51x_I2C_R_SID 0x44
#define R51x_I2C_DATA 0x45
#define R518_I2C_CTL 0x47 /* OV518(+) only */
#define OVFX2_I2C_ADDR 0x00
/* OV519 Camera interface register numbers */
#define OV519_R10_H_SIZE 0x10
#define OV519_R11_V_SIZE 0x11
#define OV519_R12_X_OFFSETL 0x12
#define OV519_R13_X_OFFSETH 0x13
#define OV519_R14_Y_OFFSETL 0x14
#define OV519_R15_Y_OFFSETH 0x15
#define OV519_R16_DIVIDER 0x16
#define OV519_R20_DFR 0x20
#define OV519_R25_FORMAT 0x25
#define OV519_R10_H_SIZE 0x10
#define OV519_R11_V_SIZE 0x11
#define OV519_R12_X_OFFSETL 0x12
#define OV519_R13_X_OFFSETH 0x13
#define OV519_R14_Y_OFFSETL 0x14
#define OV519_R15_Y_OFFSETH 0x15
#define OV519_R16_DIVIDER 0x16
#define OV519_R20_DFR 0x20
#define OV519_R25_FORMAT 0x25
/* OV519 System Controller register numbers */
#define OV519_R51_RESET1 0x51
#define OV519_R54_EN_CLK1 0x54
#define OV519_R57_SNAPSHOT 0x57
#define OV519_R51_RESET1 0x51
#define OV519_R54_EN_CLK1 0x54
#define OV519_R57_SNAPSHOT 0x57
#define OV519_GPIO_DATA_OUT0 0x71
#define OV519_GPIO_IO_CTRL0 0x72
#define OV519_GPIO_DATA_OUT0 0x71
#define OV519_GPIO_IO_CTRL0 0x72
/* OV7610 registers */
#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
#define OV7610_REG_BLUE 0x01 /* blue channel balance */
#define OV7610_REG_RED 0x02 /* red channel balance */
#define OV7610_REG_SAT 0x03 /* saturation */
#define OV8610_REG_HUE 0x04 /* 04 reserved */
#define OV7610_REG_CNT 0x05 /* Y contrast */
#define OV7610_REG_BRT 0x06 /* Y brightness */
#define OV7610_REG_COM_C 0x14 /* misc common regs */
#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */
#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */
#define OV7610_REG_COM_I 0x29 /* misc settings */
#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
#define OV7610_REG_BLUE 0x01 /* blue channel balance */
#define OV7610_REG_RED 0x02 /* red channel balance */
#define OV7610_REG_SAT 0x03 /* saturation */
#define OV8610_REG_HUE 0x04 /* 04 reserved */
#define OV7610_REG_CNT 0x05 /* Y contrast */
#define OV7610_REG_BRT 0x06 /* Y brightness */
#define OV7610_REG_COM_C 0x14 /* misc common regs */
#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */
#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */
#define OV7610_REG_COM_I 0x29 /* misc settings */

File diff suppressed because it is too large Load Diff

View File

@ -23,36 +23,37 @@
#include <mutex>
namespace usb_eyetoy {
class EyeToyWebCamDevice
namespace usb_eyetoy
{
public:
virtual ~EyeToyWebCamDevice() {}
static USBDevice* CreateDevice(int port);
static const TCHAR* Name()
{
return TEXT("EyeToy");
}
static const char* TypeName()
{
return "eyetoy";
}
static std::list<std::string> ListAPIs()
{
return RegisterVideoDevice::instance().Names();
}
static const TCHAR* LongAPIName(const std::string& name)
{
auto proxy = RegisterVideoDevice::instance().Proxy(name);
if (proxy)
return proxy->Name();
return nullptr;
}
static int Configure(int port, const std::string& api, void *data);
static int Freeze(int mode, USBDevice *dev, void *data);
};
} //namespace
class EyeToyWebCamDevice
{
public:
virtual ~EyeToyWebCamDevice() {}
static USBDevice* CreateDevice(int port);
static const TCHAR* Name()
{
return TEXT("EyeToy");
}
static const char* TypeName()
{
return "eyetoy";
}
static std::list<std::string> ListAPIs()
{
return RegisterVideoDevice::instance().Names();
}
static const TCHAR* LongAPIName(const std::string& name)
{
auto proxy = RegisterVideoDevice::instance().Proxy(name);
if (proxy)
return proxy->Name();
return nullptr;
}
static int Configure(int port, const std::string& api, void* data);
static int Freeze(int mode, USBDevice* dev, void* data);
};
} // namespace usb_eyetoy
#endif

View File

@ -18,23 +18,24 @@
#include "../qemu-usb/vl.h"
#include "../configuration.h"
namespace usb_eyetoy {
class VideoDevice
namespace usb_eyetoy
{
public:
virtual ~VideoDevice() {}
virtual int Open() = 0;
virtual int Close() = 0;
virtual int GetImage(uint8_t *buf, int len) = 0;
virtual int Reset() = 0;
virtual int Port() { return mPort; }
virtual void Port(int port) { mPort = port; }
class VideoDevice
{
public:
virtual ~VideoDevice() {}
virtual int Open() = 0;
virtual int Close() = 0;
virtual int GetImage(uint8_t* buf, int len) = 0;
virtual int Reset() = 0;
protected:
int mPort;
};
virtual int Port() { return mPort; }
virtual void Port(int port) { mPort = port; }
} //namespace
protected:
int mPort;
};
} // namespace usb_eyetoy
#endif

View File

@ -24,60 +24,67 @@
#include "../helpers.h"
#include "../deviceproxy.h"
namespace usb_eyetoy {
class VideoDeviceError : public std::runtime_error
namespace usb_eyetoy
{
public:
VideoDeviceError(const char* msg) : std::runtime_error(msg) {}
virtual ~VideoDeviceError() throw () {}
};
class VideoDeviceProxyBase : public ProxyBase
{
VideoDeviceProxyBase(const VideoDeviceProxyBase&) = delete;
public:
VideoDeviceProxyBase() {}
VideoDeviceProxyBase(const std::string& name);
virtual VideoDevice* CreateObject(int port) const = 0;
};
template <class T>
class VideoDeviceProxy : public VideoDeviceProxyBase
{
VideoDeviceProxy(const VideoDeviceProxy&) = delete;
public:
VideoDeviceProxy() {}
VideoDeviceProxy(const std::string& name): VideoDeviceProxyBase(name) {}
VideoDevice* CreateObject(int port) const
class VideoDeviceError : public std::runtime_error
{
try
public:
VideoDeviceError(const char* msg)
: std::runtime_error(msg)
{
return new T(port);
}
catch(VideoDeviceError& err)
{
(void)err;
return nullptr;
}
}
virtual const TCHAR* Name() const
{
return T::Name();
}
virtual int Configure(int port, const char *dev_type, void *data)
{
return T::Configure(port, dev_type, data);
}
};
virtual ~VideoDeviceError() throw() {}
};
class VideoDeviceProxyBase : public ProxyBase
{
VideoDeviceProxyBase(const VideoDeviceProxyBase&) = delete;
class RegisterVideoDevice : public RegisterProxy<VideoDeviceProxyBase>
{
public:
static void Register();
};
VideoDeviceProxyBase() {}
VideoDeviceProxyBase(const std::string& name);
virtual VideoDevice* CreateObject(int port) const = 0;
};
} //namespace
template <class T>
class VideoDeviceProxy : public VideoDeviceProxyBase
{
VideoDeviceProxy(const VideoDeviceProxy&) = delete;
public:
VideoDeviceProxy() {}
VideoDeviceProxy(const std::string& name)
: VideoDeviceProxyBase(name)
{
}
VideoDevice* CreateObject(int port) const
{
try
{
return new T(port);
}
catch (VideoDeviceError& err)
{
(void)err;
return nullptr;
}
}
virtual const TCHAR* Name() const
{
return T::Name();
}
virtual int Configure(int port, const char* dev_type, void* data)
{
return T::Configure(port, dev_type, data);
}
};
class RegisterVideoDevice : public RegisterProxy<VideoDeviceProxyBase>
{
public:
static void Register();
};
} // namespace usb_eyetoy
#endif

View File

@ -21,169 +21,178 @@
#include <cstdio>
#include <sstream>
GtkWidget *new_combobox(const char* label, GtkWidget *vbox); // src/linux/config-gtk.cpp
GtkWidget* new_combobox(const char* label, GtkWidget* vbox); // src/linux/config-gtk.cpp
namespace usb_hid { namespace evdev {
namespace usb_hid
{
namespace evdev
{
#define EVDEV_DIR "/dev/input/by-path/"
typedef std::vector< std::pair<std::string, std::string> > devs_t;
struct ConfigData {
int port;
devs_t devs;
devs_t::const_iterator iter;
};
static void PopulateHIDs(ConfigData &cfg, HIDType hid_type)
{
std::stringstream str;
struct dirent* dp;
const char* devstr[] = {"event-kbd", "event-mouse"};
cfg.devs.clear();
cfg.devs.push_back(std::make_pair("None", ""));
DIR* dirp = opendir(EVDEV_DIR);
if(dirp == NULL) {
fprintf(stderr, "Error opening " EVDEV_DIR ": %s\n", strerror(errno));
return;
}
// Loop over dir entries using readdir
int len = strlen(devstr[hid_type]);
while((dp = readdir(dirp)) != NULL)
{
// Only select names that end in 'event-joystick'
int devlen = strlen(dp->d_name);
if(devlen >= len)
typedef std::vector<std::pair<std::string, std::string>> devs_t;
struct ConfigData
{
const char* const start = dp->d_name + devlen - len;
if(strncmp(start, devstr[hid_type], len) == 0) {
OSDebugOut("%s%s\n", EVDEV_DIR, dp->d_name);
int port;
devs_t devs;
devs_t::const_iterator iter;
};
str.clear(); str.str("");
str << EVDEV_DIR << dp->d_name;
static void PopulateHIDs(ConfigData& cfg, HIDType hid_type)
{
std::stringstream str;
struct dirent* dp;
const char* devstr[] = {"event-kbd", "event-mouse"};
char name[1024];
std::string dev_path = str.str();
if (!GetEvdevName(dev_path, name))
cfg.devs.clear();
cfg.devs.push_back(std::make_pair("None", ""));
DIR* dirp = opendir(EVDEV_DIR);
if (dirp == NULL)
{
fprintf(stderr, "Error opening " EVDEV_DIR ": %s\n", strerror(errno));
return;
}
// Loop over dir entries using readdir
int len = strlen(devstr[hid_type]);
while ((dp = readdir(dirp)) != NULL)
{
// Only select names that end in 'event-joystick'
int devlen = strlen(dp->d_name);
if (devlen >= len)
{
OSDebugOut("Failed to get name: %s\n", dev_path.c_str());
//XXX though it also could mean that controller is unusable
cfg.devs.push_back(std::make_pair(dp->d_name, dev_path));
}
else
{
OSDebugOut("Name: %s\n", name);
cfg.devs.push_back(std::make_pair(std::string(name), dev_path));
const char* const start = dp->d_name + devlen - len;
if (strncmp(start, devstr[hid_type], len) == 0)
{
OSDebugOut("%s%s\n", EVDEV_DIR, dp->d_name);
str.clear();
str.str("");
str << EVDEV_DIR << dp->d_name;
char name[1024];
std::string dev_path = str.str();
if (!GetEvdevName(dev_path, name))
{
OSDebugOut("Failed to get name: %s\n", dev_path.c_str());
//XXX though it also could mean that controller is unusable
cfg.devs.push_back(std::make_pair(dp->d_name, dev_path));
}
else
{
OSDebugOut("Name: %s\n", name);
cfg.devs.push_back(std::make_pair(std::string(name), dev_path));
}
}
}
}
closedir(dirp);
}
}
closedir(dirp);
}
static void combo_changed (GtkComboBox *widget, gpointer data)
{
gint idx = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
ConfigData *cfg = reinterpret_cast<ConfigData *> (data);
if (!cfg)
return;
std::string &name = (cfg->devs.begin() + idx)->first;
cfg->iter = (cfg->devs.begin() + idx);
if (idx > 0)
{
}
OSDebugOut("Selected player %d idx: %d dev: '%s'\n", 2 - cfg->port, idx, name.c_str());
}
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;
assert( (int)HIDTYPE_MOUSE == 1); //make sure there is atleast two types so we won't go beyond array length
ConfigData cfg;
cfg.port = port;
PopulateHIDs(cfg, hid_type);
cfg.iter = cfg.devs.end();
std::string path;
LoadSetting(dev_type, port, APINAME, N_DEVICE, path);
// ---------------------------
GtkWidget *dlg = gtk_dialog_new_with_buttons (
"HID Evdev Settings", parent, GTK_DIALOG_MODAL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (dlg), TRUE);
gtk_window_set_default_size (GTK_WINDOW(dlg), 320, 240);
// ---------------------------
GtkWidget *dlg_area_box = gtk_dialog_get_content_area (GTK_DIALOG (dlg));
main_hbox = gtk_hbox_new (FALSE, 5);
gtk_container_add (GTK_CONTAINER(dlg_area_box), main_hbox);
// left_vbox = gtk_vbox_new (FALSE, 5);
// gtk_box_pack_start (GTK_BOX (main_hbox), left_vbox, TRUE, TRUE, 5);
right_vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (main_hbox), right_vbox, TRUE, TRUE, 5);
// ---------------------------
rs_cb = new_combobox ("Device:", right_vbox);
const int evdev_dir_len = strlen(EVDEV_DIR);
int idx = 0, sel_idx = 0;
for (auto& it : cfg.devs)
{
std::stringstream str;
str << it.first;
if (!it.second.empty())
str << " [" << it.second.substr(evdev_dir_len) << "]";
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (rs_cb), str.str().c_str());
if (!path.empty() && it.second == path)
static void combo_changed(GtkComboBox* widget, gpointer data)
{
sel_idx = idx;
gint idx = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
ConfigData* cfg = reinterpret_cast<ConfigData*>(data);
if (!cfg)
return;
std::string& name = (cfg->devs.begin() + idx)->first;
cfg->iter = (cfg->devs.begin() + idx);
if (idx > 0)
{
}
OSDebugOut("Selected player %d idx: %d dev: '%s'\n", 2 - cfg->port, idx, name.c_str());
}
idx++;
}
//g_object_set_data (G_OBJECT (rs_cb), CFG, &cfg);
g_signal_connect (G_OBJECT (rs_cb), "changed", G_CALLBACK (combo_changed), reinterpret_cast<gpointer> (&cfg));
gtk_combo_box_set_active (GTK_COMBO_BOX (rs_cb), sel_idx);
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;
// ---------------------------
gtk_widget_show_all (dlg);
gint result = gtk_dialog_run (GTK_DIALOG (dlg));
assert((int)HIDTYPE_MOUSE == 1); //make sure there is atleast two types so we won't go beyond array length
int ret = RESULT_OK;
if (result == GTK_RESPONSE_OK)
{
if (cfg.iter != cfg.devs.end()) {
if (!SaveSetting(dev_type, port, APINAME, N_DEVICE, cfg.iter->second))
ret = RESULT_FAILED;
ConfigData cfg;
cfg.port = port;
PopulateHIDs(cfg, hid_type);
cfg.iter = cfg.devs.end();
std::string path;
LoadSetting(dev_type, port, APINAME, N_DEVICE, path);
// ---------------------------
GtkWidget* dlg = gtk_dialog_new_with_buttons(
"HID Evdev Settings", parent, GTK_DIALOG_MODAL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
gtk_window_set_resizable(GTK_WINDOW(dlg), TRUE);
gtk_window_set_default_size(GTK_WINDOW(dlg), 320, 240);
// ---------------------------
GtkWidget* dlg_area_box = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
main_hbox = gtk_hbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(dlg_area_box), main_hbox);
// left_vbox = gtk_vbox_new (FALSE, 5);
// gtk_box_pack_start (GTK_BOX (main_hbox), left_vbox, TRUE, TRUE, 5);
right_vbox = gtk_vbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(main_hbox), right_vbox, TRUE, TRUE, 5);
// ---------------------------
rs_cb = new_combobox("Device:", right_vbox);
const int evdev_dir_len = strlen(EVDEV_DIR);
int idx = 0, sel_idx = 0;
for (auto& it : cfg.devs)
{
std::stringstream str;
str << it.first;
if (!it.second.empty())
str << " [" << it.second.substr(evdev_dir_len) << "]";
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rs_cb), str.str().c_str());
if (!path.empty() && it.second == path)
{
sel_idx = idx;
}
idx++;
}
//g_object_set_data (G_OBJECT (rs_cb), CFG, &cfg);
g_signal_connect(G_OBJECT(rs_cb), "changed", G_CALLBACK(combo_changed), reinterpret_cast<gpointer>(&cfg));
gtk_combo_box_set_active(GTK_COMBO_BOX(rs_cb), sel_idx);
// ---------------------------
gtk_widget_show_all(dlg);
gint result = gtk_dialog_run(GTK_DIALOG(dlg));
int ret = RESULT_OK;
if (result == GTK_RESPONSE_OK)
{
if (cfg.iter != cfg.devs.end())
{
if (!SaveSetting(dev_type, port, APINAME, N_DEVICE, cfg.iter->second))
ret = RESULT_FAILED;
}
}
else
ret = RESULT_CANCELED;
gtk_widget_destroy(dlg);
return ret;
}
}
else
ret = RESULT_CANCELED;
gtk_widget_destroy (dlg);
return ret;
}
int EvDev::Configure(int port, const char* dev_type, HIDType hid_type, void *data)
{
return GtkHidConfigure(port, dev_type, hid_type, GTK_WINDOW (data));
}
int EvDev::Configure(int port, const char* dev_type, HIDType hid_type, void* data)
{
return GtkHidConfigure(port, dev_type, hid_type, GTK_WINDOW(data));
}
#undef EVDEV_DIR
}} //namespace
} // namespace evdev
} // namespace usb_hid

View File

@ -23,125 +23,133 @@
#ifdef USING_X11
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
extern Display *g_GSdsp;
extern Display* g_GSdsp;
extern Window g_GSwin;
#endif
namespace usb_hid { namespace evdev {
namespace usb_hid
{
namespace evdev
{
#define test_bit(nr, addr) \
(((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
#define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
#define NBITS(x) ((((x)-1) / (sizeof(long) * 8)) + 1)
bool FindHid(const std::string &evphys, std::string& hid_dev)
{
int fd;
int res;
char buf[256];
bool FindHid(const std::string& evphys, std::string& hid_dev)
{
int fd;
int res;
char buf[256];
std::stringstream str;
struct dirent* dp;
std::stringstream str;
struct dirent* dp;
DIR* dirp = opendir("/dev/input/");
if(dirp == NULL) {
perror("Error opening /dev/input/");
return false;
}
while((dp = readdir(dirp)) != NULL)
{
if(strncmp(dp->d_name, "hidraw", 6) == 0) {
OSDebugOut("%s\n", dp->d_name);
str.clear(); str.str("");
str << "/dev/input/" << dp->d_name;
fd = open(str.str().c_str(), O_RDWR|O_NONBLOCK);
if (fd < 0) {
perror("Unable to open device");
continue;
DIR* dirp = opendir("/dev/input/");
if (dirp == NULL)
{
perror("Error opening /dev/input/");
return false;
}
memset(buf, 0x0, sizeof(buf));
//res = ioctl(fd, HIDIOCGRAWNAME(256), buf);
while ((dp = readdir(dirp)) != NULL)
{
if (strncmp(dp->d_name, "hidraw", 6) == 0)
{
OSDebugOut("%s\n", dp->d_name);
/* res = ioctl(fd, HIDIOCGRAWPHYS(256), buf);
str.clear();
str.str("");
str << "/dev/input/" << dp->d_name;
fd = open(str.str().c_str(), O_RDWR | O_NONBLOCK);
if (fd < 0)
{
perror("Unable to open device");
continue;
}
memset(buf, 0x0, sizeof(buf));
//res = ioctl(fd, HIDIOCGRAWNAME(256), buf);
/* res = ioctl(fd, HIDIOCGRAWPHYS(256), buf);
if (res < 0)
perror("HIDIOCGRAWPHYS");
else
OSDebugOut("Raw Phys: %s\n", buf);*/
close(fd);
if (evphys == buf) {
closedir(dirp);
hid_dev = str.str();
return true;
close(fd);
if (evphys == buf)
{
closedir(dirp);
hid_dev = str.str();
return true;
}
}
}
quit:
closedir(dirp);
return false;
}
}
quit:
closedir(dirp);
return false;
}
int EvDev::TokenOut(const uint8_t *data, int len)
{
return len;
}
int EvDev::TokenOut(const uint8_t* data, int len)
{
return len;
}
int EvDev::Open()
{
// 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];
int EvDev::Open()
{
// 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 };
unsigned long keybit[NBITS(KEY_MAX)] = {0};
unsigned long absbit[NBITS(ABS_MAX)] = {0};
memset(mAxisMap, -1, sizeof(mAxisMap));
memset(mBtnMap, -1, sizeof(mBtnMap));
memset(mAxisMap, -1, sizeof(mAxisMap));
memset(mBtnMap, -1, sizeof(mBtnMap));
mAxisCount = 0;
mButtonCount = 0;
mHandle = -1;
mAxisCount = 0;
mButtonCount = 0;
mHandle = -1;
std::string path;
if (!LoadSetting(mDevType, mPort, APINAME, N_DEVICE, path))
{
OSDebugOut("Cannot load evdev hid device setting!\n");
return 1;
}
std::string path;
if (!LoadSetting(mDevType, mPort, APINAME, N_DEVICE, path))
{
OSDebugOut("Cannot load evdev hid device setting!\n");
return 1;
}
if(path.empty() || !file_exists(path))
goto quit;
if (path.empty() || !file_exists(path))
goto quit;
/*if (GetEvdevName(joypath, buf)) {
/*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 ((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) &&
/* 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;
/*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) {
/* for (int i = 0; i < KEY_MAX; ++i) {
if (test_bit(i, keybit)) {
OSDebugOut("Joystick has button: 0x%x\n", i);
mBtnMap[i] = mButtonCount;
@ -149,194 +157,203 @@ int EvDev::Open()
}
}*/
if (!mReaderThreadIsRunning)
{
if (mReaderThread.joinable())
mReaderThread.join();
mReaderThread = std::thread(EvDev::ReaderThread, this);
}
return 0;
quit:
Close();
return 1;
}
int EvDev::Close()
{
if (mHandle != -1)
close(mHandle);
mHandle = -1;
return 0;
}
void EvDev::ReaderThread(void *ptr)
{
ssize_t len;
input_event events[32];
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;
while (dev->mHandle != -1)
{
//Non-blocking read sets len to -1 and errno to EAGAIN if no new data
while((len = read(dev->mHandle, &events, sizeof(events))) > -1)
{
InputEvent ev{};
len /= sizeof(events[0]);
for (int i = 0; i < len; i++)
if (!mReaderThreadIsRunning)
{
input_event& event = events[i];
switch (event.type)
{
case EV_ABS:
{
OSDebugOut("EV_ABS: %d, val: %d\n", event.code, event.value);
if (dev->mHIDType == HIDTYPE_MOUSE) // usually mouse position is expected to be relative
continue;
if (!hs->ptr.eh_entry)
continue;
ev.type = INPUT_EVENT_KIND_ABS;
if (event.code == ABS_X)
{
ev.u.abs.axis = INPUT_AXIS_X;
ev.u.abs.value = event.value;
hs->ptr.eh_entry(hs, &ev);
}
else if (event.code == ABS_Y)
{
ev.u.abs.axis = INPUT_AXIS_Y;
ev.u.abs.value = event.value;
hs->ptr.eh_entry(hs, &ev);
}
}
break;
case EV_REL:
{
OSDebugOut("EV_REL: %d, val: %d\n", event.code, event.value);
if (!hs->ptr.eh_entry)
continue;
ev.type = INPUT_EVENT_KIND_REL;
ev.u.rel.value = event.value;
if (event.code == ABS_X)
{
ev.u.rel.axis = INPUT_AXIS_X;
hs->ptr.eh_entry(hs, &ev);
}
else if (event.code == ABS_Y)
{
ev.u.rel.axis = INPUT_AXIS_Y;
hs->ptr.eh_entry(hs, &ev);
}
}
break;
case EV_KEY:
{
OSDebugOut("EV_KEY: 0x%02x (%d), val: %d\n", event.code, event.code, event.value);
#ifdef USING_X11 //FIXME not thread-safe
if (event.code == KEY_LEFTSHIFT || event.code == KEY_RIGHTSHIFT)
shift = (event.value > 0);
if (event.code == KEY_F12 && (event.value == 1) && shift) {
if (!grabbed) {
grabbed = true;
XGrabPointer(g_GSdsp, g_GSwin, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, g_GSwin, None, CurrentTime);
XGrabKeyboard(g_GSdsp, g_GSwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
// Hides globally :(
XFixesHideCursor(g_GSdsp, g_GSwin);
} else {
grabbed = false;
XUngrabPointer(g_GSdsp, CurrentTime);
XUngrabKeyboard(g_GSdsp, CurrentTime);
XFixesShowCursor(g_GSdsp, g_GSwin);
}
}
#endif
if (hs->kbd.eh_entry) {
QKeyCode qcode = Q_KEY_CODE_UNMAPPED;
if (event.code < (uint16_t)qemu_input_map_linux_to_qcode_len)
qcode = qemu_input_map_linux_to_qcode[event.code];
if (event.value < 2) {
ev.type = INPUT_EVENT_KIND_KEY;
ev.u.key.down = (event.value == 1); // 2 if repeat
ev.u.key.key.type = KEY_VALUE_KIND_QCODE;
ev.u.key.key.u.qcode = qcode;
hs->kbd.eh_entry(hs, &ev);
}
}
if (hs->ptr.eh_entry) {
ev.type = INPUT_EVENT_KIND_BTN;
switch(event.code)
{
case BTN_LEFT:
ev.u.btn.button = INPUT_BUTTON_LEFT;
ev.u.btn.down = (event.value == 1);
hs->ptr.eh_entry(hs, &ev);
break;
case BTN_RIGHT:
ev.u.btn.button = INPUT_BUTTON_RIGHT;
ev.u.btn.down = (event.value == 1);
hs->ptr.eh_entry(hs, &ev);
break;
case BTN_MIDDLE:
ev.u.btn.button = INPUT_BUTTON_MIDDLE;
ev.u.btn.down = (event.value == 1);
hs->ptr.eh_entry(hs, &ev);
break;
default:
break;
}
}
}
break;
case EV_SYN: //TODO useful?
{
OSDebugOut("EV_SYN: %d, val: %d\n", event.code, event.value);
switch(event.code) {
case SYN_REPORT:
if (hs->ptr.eh_sync) //TODO sync here?
hs->ptr.eh_sync(hs);
break;
case SYN_DROPPED:
//restore last good state
break;
}
}
break;
default:
break;
}
if (mReaderThread.joinable())
mReaderThread.join();
mReaderThread = std::thread(EvDev::ReaderThread, this);
}
return 0;
if (len < sizeof(input_event) && errno != EAGAIN)
{
OSDebugOut("%s: evdev read error %d\n", APINAME, errno);
break;
}
quit:
Close();
return 1;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
OSDebugOut(TEXT("ReaderThread exited.\n"));
int EvDev::Close()
{
if (mHandle != -1)
close(mHandle);
dev->mReaderThreadIsRunning = false;
}
mHandle = -1;
return 0;
}
}} //namespace
void EvDev::ReaderThread(void* ptr)
{
ssize_t len;
input_event events[32];
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;
while (dev->mHandle != -1)
{
//Non-blocking read sets len to -1 and errno to EAGAIN if no new data
while ((len = read(dev->mHandle, &events, sizeof(events))) > -1)
{
InputEvent ev{};
len /= sizeof(events[0]);
for (int i = 0; i < len; i++)
{
input_event& event = events[i];
switch (event.type)
{
case EV_ABS:
{
OSDebugOut("EV_ABS: %d, val: %d\n", event.code, event.value);
if (dev->mHIDType == HIDTYPE_MOUSE) // usually mouse position is expected to be relative
continue;
if (!hs->ptr.eh_entry)
continue;
ev.type = INPUT_EVENT_KIND_ABS;
if (event.code == ABS_X)
{
ev.u.abs.axis = INPUT_AXIS_X;
ev.u.abs.value = event.value;
hs->ptr.eh_entry(hs, &ev);
}
else if (event.code == ABS_Y)
{
ev.u.abs.axis = INPUT_AXIS_Y;
ev.u.abs.value = event.value;
hs->ptr.eh_entry(hs, &ev);
}
}
break;
case EV_REL:
{
OSDebugOut("EV_REL: %d, val: %d\n", event.code, event.value);
if (!hs->ptr.eh_entry)
continue;
ev.type = INPUT_EVENT_KIND_REL;
ev.u.rel.value = event.value;
if (event.code == ABS_X)
{
ev.u.rel.axis = INPUT_AXIS_X;
hs->ptr.eh_entry(hs, &ev);
}
else if (event.code == ABS_Y)
{
ev.u.rel.axis = INPUT_AXIS_Y;
hs->ptr.eh_entry(hs, &ev);
}
}
break;
case EV_KEY:
{
OSDebugOut("EV_KEY: 0x%02x (%d), val: %d\n", event.code, event.code, event.value);
#ifdef USING_X11 //FIXME not thread-safe
if (event.code == KEY_LEFTSHIFT || event.code == KEY_RIGHTSHIFT)
shift = (event.value > 0);
if (event.code == KEY_F12 && (event.value == 1) && shift)
{
if (!grabbed)
{
grabbed = true;
XGrabPointer(g_GSdsp, g_GSwin, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, g_GSwin, None, CurrentTime);
XGrabKeyboard(g_GSdsp, g_GSwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
// Hides globally :(
XFixesHideCursor(g_GSdsp, g_GSwin);
}
else
{
grabbed = false;
XUngrabPointer(g_GSdsp, CurrentTime);
XUngrabKeyboard(g_GSdsp, CurrentTime);
XFixesShowCursor(g_GSdsp, g_GSwin);
}
}
#endif
if (hs->kbd.eh_entry)
{
QKeyCode qcode = Q_KEY_CODE_UNMAPPED;
if (event.code < (uint16_t)qemu_input_map_linux_to_qcode_len)
qcode = qemu_input_map_linux_to_qcode[event.code];
if (event.value < 2)
{
ev.type = INPUT_EVENT_KIND_KEY;
ev.u.key.down = (event.value == 1); // 2 if repeat
ev.u.key.key.type = KEY_VALUE_KIND_QCODE;
ev.u.key.key.u.qcode = qcode;
hs->kbd.eh_entry(hs, &ev);
}
}
if (hs->ptr.eh_entry)
{
ev.type = INPUT_EVENT_KIND_BTN;
switch (event.code)
{
case BTN_LEFT:
ev.u.btn.button = INPUT_BUTTON_LEFT;
ev.u.btn.down = (event.value == 1);
hs->ptr.eh_entry(hs, &ev);
break;
case BTN_RIGHT:
ev.u.btn.button = INPUT_BUTTON_RIGHT;
ev.u.btn.down = (event.value == 1);
hs->ptr.eh_entry(hs, &ev);
break;
case BTN_MIDDLE:
ev.u.btn.button = INPUT_BUTTON_MIDDLE;
ev.u.btn.down = (event.value == 1);
hs->ptr.eh_entry(hs, &ev);
break;
default:
break;
}
}
}
break;
case EV_SYN: //TODO useful?
{
OSDebugOut("EV_SYN: %d, val: %d\n", event.code, event.value);
switch (event.code)
{
case SYN_REPORT:
if (hs->ptr.eh_sync) //TODO sync here?
hs->ptr.eh_sync(hs);
break;
case SYN_DROPPED:
//restore last good state
break;
}
}
break;
default:
break;
}
}
if (len < sizeof(input_event) && errno != EAGAIN)
{
OSDebugOut("%s: evdev read error %d\n", APINAME, errno);
break;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
OSDebugOut(TEXT("ReaderThread exited.\n"));
dev->mReaderThreadIsRunning = false;
}
} // namespace evdev
} // namespace usb_hid

View File

@ -22,65 +22,71 @@
#include <atomic>
#include "../usb-hid.h"
namespace usb_hid { namespace evdev {
static const char *APINAME = "evdev";
class EvDev : public UsbHID
namespace usb_hid
{
public:
EvDev(int port, const char* dev_type): UsbHID(port, dev_type)
, mHandle(-1)
, mReaderThreadIsRunning(false)
namespace evdev
{
}
~EvDev() { Close(); }
int Open();
int Close();
int TokenIn(uint8_t *buf, int len);
int TokenOut(const uint8_t *data, int len);
int Reset() { return 0; }
static const char* APINAME = "evdev";
static const TCHAR* Name()
{
return TEXT("Evdev");
}
static int Configure(int port, const char* dev_type, HIDType hid_type, void *data);
protected:
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;
};
template< size_t _Size >
bool GetEvdevName(const std::string& path, char (&name)[_Size])
{
int fd = 0;
if ((fd = open(path.c_str(), O_RDONLY)) < 0)
{
fprintf(stderr, "Cannot open %s\n", path.c_str());
}
else
{
if (ioctl(fd, EVIOCGNAME(_Size), name) < -1)
class EvDev : public UsbHID
{
fprintf(stderr, "Cannot get controller's name\n");
close(fd);
public:
EvDev(int port, const char* dev_type)
: UsbHID(port, dev_type)
, mHandle(-1)
, mReaderThreadIsRunning(false)
{
}
~EvDev() { Close(); }
int Open();
int Close();
int TokenIn(uint8_t* buf, int len);
int TokenOut(const uint8_t* data, int len);
int Reset() { return 0; }
static const TCHAR* Name()
{
return TEXT("Evdev");
}
static int Configure(int port, const char* dev_type, HIDType hid_type, void* data);
protected:
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;
};
template <size_t _Size>
bool GetEvdevName(const std::string& path, char (&name)[_Size])
{
int fd = 0;
if ((fd = open(path.c_str(), O_RDONLY)) < 0)
{
fprintf(stderr, "Cannot open %s\n", path.c_str());
}
else
{
if (ioctl(fd, EVIOCGNAME(_Size), name) < -1)
{
fprintf(stderr, "Cannot get controller's name\n");
close(fd);
return false;
}
close(fd);
return true;
}
return false;
}
close(fd);
return true;
}
return false;
}
}} //namespace
} // namespace evdev
} // namespace usb_hid

View File

@ -24,66 +24,73 @@
#include "../helpers.h"
#include "../deviceproxy.h"
namespace usb_hid {
class UsbHIDError : public std::runtime_error
namespace usb_hid
{
public:
UsbHIDError(const char* msg) : std::runtime_error(msg) {}
virtual ~UsbHIDError() throw () {}
};
class UsbHIDProxyBase : public ProxyBase
{
UsbHIDProxyBase(const UsbHIDProxyBase&) = delete;
public:
UsbHIDProxyBase() {}
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, HIDType hid_type, void *data) = 0;
};
template <class T>
class UsbHIDProxy : public UsbHIDProxyBase
{
UsbHIDProxy(const UsbHIDProxy&) = delete;
public:
UsbHIDProxy() {}
UsbHIDProxy(const std::string& name): UsbHIDProxyBase(name) {}
UsbHID* CreateObject(int port, const char* dev_type) const
class UsbHIDError : public std::runtime_error
{
try
public:
UsbHIDError(const char* msg)
: std::runtime_error(msg)
{
return new T(port, dev_type);
}
catch(UsbHIDError& err)
{
(void)err;
return nullptr;
}
}
virtual const TCHAR* Name() const
{
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);
}
};
virtual ~UsbHIDError() throw() {}
};
class UsbHIDProxyBase : public ProxyBase
{
UsbHIDProxyBase(const UsbHIDProxyBase&) = delete;
class RegisterUsbHID : public RegisterProxy<UsbHIDProxyBase>
{
public:
static void Register();
};
UsbHIDProxyBase() {}
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, HIDType hid_type, void* data) = 0;
};
}
template <class T>
class UsbHIDProxy : public UsbHIDProxyBase
{
UsbHIDProxy(const UsbHIDProxy&) = delete;
public:
UsbHIDProxy() {}
UsbHIDProxy(const std::string& name)
: UsbHIDProxyBase(name)
{
}
UsbHID* CreateObject(int port, const char* dev_type) const
{
try
{
return new T(port, dev_type);
}
catch (UsbHIDError& err)
{
(void)err;
return nullptr;
}
}
virtual const TCHAR* Name() const
{
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);
}
};
class RegisterUsbHID : public RegisterProxy<UsbHIDProxyBase>
{
public:
static void Register();
};
} // namespace usb_hid
#endif

View File

@ -16,30 +16,37 @@
#include "usb-hid.h"
#include "hidproxy.h"
namespace usb_hid { namespace noop {
static const char *APINAME = "noop";
class NOOP : public UsbHID
namespace usb_hid
{
public:
NOOP(int port, const char* dev_type): UsbHID(port, dev_type) {}
~NOOP() {}
int Open() { return 0; }
int Close() { return 0; }
int TokenIn(uint8_t *buf, int len) { return len; }
int TokenOut(const uint8_t *data, int len) { return len; }
int Reset() { return 0; }
static const TCHAR* Name()
namespace noop
{
return TEXT("NOOP");
}
static int Configure(int port, const char* dev_type, HIDType type, void *data)
{
return RESULT_CANCELED;
}
};
static const char* APINAME = "noop";
}}
class NOOP : public UsbHID
{
public:
NOOP(int port, const char* dev_type)
: UsbHID(port, dev_type)
{
}
~NOOP() {}
int Open() { return 0; }
int Close() { return 0; }
int TokenIn(uint8_t* buf, int len) { return len; }
int TokenOut(const uint8_t* data, int len) { return len; }
int Reset() { return 0; }
static const TCHAR* Name()
{
return TEXT("NOOP");
}
static int Configure(int port, const char* dev_type, HIDType type, void* data)
{
return RESULT_CANCELED;
}
};
} // namespace noop
} // namespace usb_hid

View File

@ -18,216 +18,234 @@
#include "qemu-usb/input-keymap.h"
#include "qemu-usb/input-keymap-win32-to-qcode.h"
namespace usb_hid { namespace raw {
#define CHECK(exp) do{ if(!(exp)) goto Error; }while(0)
#define SAFE_FREE(p) do{ if(p) { free(p); (p) = NULL; } }while(0)
// VKEY from https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes
// and convert to HID usage id from "10 Keyboard/Keypad Page (0x07)"
// https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
int RawInput::TokenOut(const uint8_t *data, int len)
namespace usb_hid
{
// std::array<uint8_t, 8> report{ 0 };
// memcpy(report.data() + 1, data, report.size() - 1);
return len;
}
static void ParseRawInput(PRAWINPUT pRawInput, HIDState *hs)
{
PHIDP_PREPARSED_DATA pPreparsedData = NULL;
HIDP_CAPS Caps;
PHIDP_BUTTON_CAPS pButtonCaps = NULL;
PHIDP_VALUE_CAPS pValueCaps = NULL;
UINT bufferSize = 0;
ULONG usageLength, value;
TCHAR name[1024] = {0};
UINT nameSize = 1024;
RID_DEVICE_INFO devInfo = {0};
std::wstring devName;
USHORT capsLength = 0;
USAGE usage[32] = {0};
int numberOfButtons;
GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, name, &nameSize);
devName = name;
std::transform(devName.begin(), devName.end(), devName.begin(), ::toupper);
CHECK( GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, NULL, &bufferSize) == 0 );
CHECK( pPreparsedData = (PHIDP_PREPARSED_DATA)malloc(bufferSize) );
CHECK( (int)GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, pPreparsedData, &bufferSize) >= 0 );
CHECK( HidP_GetCaps(pPreparsedData, &Caps) == HIDP_STATUS_SUCCESS );
//Get pressed buttons
CHECK( pButtonCaps = (PHIDP_BUTTON_CAPS)malloc(sizeof(HIDP_BUTTON_CAPS) * Caps.NumberInputButtonCaps) );
//If fails, maybe wheel only has axes
capsLength = Caps.NumberInputButtonCaps;
HidP_GetButtonCaps(HidP_Input, pButtonCaps, &capsLength, pPreparsedData);
numberOfButtons = pButtonCaps->Range.UsageMax - pButtonCaps->Range.UsageMin + 1;
usageLength = countof(usage);//numberOfButtons;
NTSTATUS stat;
if((stat = HidP_GetUsages(
HidP_Input, pButtonCaps->UsagePage, 0, usage, &usageLength, pPreparsedData,
(PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid)) == HIDP_STATUS_SUCCESS )
namespace raw
{
for(uint32_t i = 0; i < usageLength; i++)
#define CHECK(exp) \
do \
{ \
if (!(exp)) \
goto Error; \
} while (0)
#define SAFE_FREE(p) \
do \
{ \
if (p) \
{ \
free(p); \
(p) = NULL; \
} \
} while (0)
// VKEY from https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes
// and convert to HID usage id from "10 Keyboard/Keypad Page (0x07)"
// https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
int RawInput::TokenOut(const uint8_t* data, int len)
{
uint16_t btn = usage[i] - pButtonCaps->Range.UsageMin;
// std::array<uint8_t, 8> report{ 0 };
// memcpy(report.data() + 1, data, report.size() - 1);
return len;
}
}
/// Get axes' values
CHECK( pValueCaps = (PHIDP_VALUE_CAPS)malloc(sizeof(HIDP_VALUE_CAPS) * Caps.NumberInputValueCaps) );
capsLength = Caps.NumberInputValueCaps;
if(HidP_GetValueCaps(HidP_Input, pValueCaps, &capsLength, pPreparsedData) == HIDP_STATUS_SUCCESS )
{
for(USHORT i = 0; i < capsLength; i++)
static void ParseRawInput(PRAWINPUT pRawInput, HIDState* hs)
{
if(HidP_GetUsageValue(
HidP_Input, pValueCaps[i].UsagePage, 0,
pValueCaps[i].Range.UsageMin, &value, pPreparsedData,
(PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid
) != HIDP_STATUS_SUCCESS )
PHIDP_PREPARSED_DATA pPreparsedData = NULL;
HIDP_CAPS Caps;
PHIDP_BUTTON_CAPS pButtonCaps = NULL;
PHIDP_VALUE_CAPS pValueCaps = NULL;
UINT bufferSize = 0;
ULONG usageLength, value;
TCHAR name[1024] = {0};
UINT nameSize = 1024;
RID_DEVICE_INFO devInfo = {0};
std::wstring devName;
USHORT capsLength = 0;
USAGE usage[32] = {0};
int numberOfButtons;
GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, name, &nameSize);
devName = name;
std::transform(devName.begin(), devName.end(), devName.begin(), ::toupper);
CHECK(GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, NULL, &bufferSize) == 0);
CHECK(pPreparsedData = (PHIDP_PREPARSED_DATA)malloc(bufferSize));
CHECK((int)GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_PREPARSEDDATA, pPreparsedData, &bufferSize) >= 0);
CHECK(HidP_GetCaps(pPreparsedData, &Caps) == HIDP_STATUS_SUCCESS);
//Get pressed buttons
CHECK(pButtonCaps = (PHIDP_BUTTON_CAPS)malloc(sizeof(HIDP_BUTTON_CAPS) * Caps.NumberInputButtonCaps));
//If fails, maybe wheel only has axes
capsLength = Caps.NumberInputButtonCaps;
HidP_GetButtonCaps(HidP_Input, pButtonCaps, &capsLength, pPreparsedData);
numberOfButtons = pButtonCaps->Range.UsageMax - pButtonCaps->Range.UsageMin + 1;
usageLength = countof(usage); //numberOfButtons;
NTSTATUS stat;
if ((stat = HidP_GetUsages(
HidP_Input, pButtonCaps->UsagePage, 0, usage, &usageLength, pPreparsedData,
(PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid)) == HIDP_STATUS_SUCCESS)
{
continue; // if here then maybe something is up with HIDP_CAPS.NumberInputValueCaps
for (uint32_t i = 0; i < usageLength; i++)
{
uint16_t btn = usage[i] - pButtonCaps->Range.UsageMin;
}
}
switch(pValueCaps[i].Range.UsageMin)
/// Get axes' values
CHECK(pValueCaps = (PHIDP_VALUE_CAPS)malloc(sizeof(HIDP_VALUE_CAPS) * Caps.NumberInputValueCaps));
capsLength = Caps.NumberInputValueCaps;
if (HidP_GetValueCaps(HidP_Input, pValueCaps, &capsLength, pPreparsedData) == HIDP_STATUS_SUCCESS)
{
case HID_USAGE_GENERIC_X: //0x30
case HID_USAGE_GENERIC_Y:
case HID_USAGE_GENERIC_Z:
case HID_USAGE_GENERIC_RX:
case HID_USAGE_GENERIC_RY:
case HID_USAGE_GENERIC_RZ: //0x35
//int axis = (value * 0x3FFF) / pValueCaps[i].LogicalMax;
break;
case HID_USAGE_GENERIC_HATSWITCH:
//fprintf(stderr, "Hat: %02X\n", value);
break;
for (USHORT i = 0; i < capsLength; i++)
{
if (HidP_GetUsageValue(
HidP_Input, pValueCaps[i].UsagePage, 0,
pValueCaps[i].Range.UsageMin, &value, pPreparsedData,
(PCHAR)pRawInput->data.hid.bRawData, pRawInput->data.hid.dwSizeHid) != HIDP_STATUS_SUCCESS)
{
continue; // if here then maybe something is up with HIDP_CAPS.NumberInputValueCaps
}
switch (pValueCaps[i].Range.UsageMin)
{
case HID_USAGE_GENERIC_X: //0x30
case HID_USAGE_GENERIC_Y:
case HID_USAGE_GENERIC_Z:
case HID_USAGE_GENERIC_RX:
case HID_USAGE_GENERIC_RY:
case HID_USAGE_GENERIC_RZ: //0x35
//int axis = (value * 0x3FFF) / pValueCaps[i].LogicalMax;
break;
case HID_USAGE_GENERIC_HATSWITCH:
//fprintf(stderr, "Hat: %02X\n", value);
break;
}
}
}
Error:
SAFE_FREE(pPreparsedData);
SAFE_FREE(pButtonCaps);
SAFE_FREE(pValueCaps);
}
static void ParseRawInputKB(RAWKEYBOARD& k, HIDState* hs)
{
if (!hs->kbd.eh_entry)
return;
static uint32_t nr = 0;
OSDebugOut(TEXT("%ud kb: %hu %hu %hu %u\n"), nr, k.MakeCode, k.VKey, k.Flags, k.ExtraInformation);
nr++;
if (nr > 10)
nr = 0;
if (KEYBOARD_OVERRUN_MAKE_CODE == k.MakeCode)
return;
QKeyCode qcode = Q_KEY_CODE_UNMAPPED;
if (k.VKey < (int)qemu_input_map_win32_to_qcode.size())
qcode = qemu_input_map_win32_to_qcode[k.VKey];
//TODO
if (k.Flags & RI_KEY_E0)
{
if (Q_KEY_CODE_SHIFT == qcode)
qcode = Q_KEY_CODE_SHIFT_R;
else if (Q_KEY_CODE_CTRL == qcode)
qcode = Q_KEY_CODE_CTRL_R;
else if (Q_KEY_CODE_ALT == qcode)
qcode = Q_KEY_CODE_ALT_R;
}
InputEvent ev{};
ev.type = INPUT_EVENT_KIND_KEY;
ev.u.key.down = !k.Flags;
ev.u.key.key.type = KEY_VALUE_KIND_QCODE;
ev.u.key.key.u.qcode = qcode;
hs->kbd.eh_entry(hs, &ev);
}
static void SendPointerEvent(InputEvent& ev, HIDState* hs)
{
if (hs->ptr.eh_entry)
{
hs->ptr.eh_entry(hs, &ev);
}
}
}
Error:
SAFE_FREE(pPreparsedData);
SAFE_FREE(pButtonCaps);
SAFE_FREE(pValueCaps);
}
static void ParseRawInputKB(RAWKEYBOARD &k, HIDState *hs)
{
if (!hs->kbd.eh_entry)
return;
static uint32_t nr = 0;
OSDebugOut(TEXT("%ud kb: %hu %hu %hu %u\n"), nr, k.MakeCode, k.VKey, k.Flags, k.ExtraInformation);
nr++;
if (nr > 10) nr = 0;
if (KEYBOARD_OVERRUN_MAKE_CODE == k.MakeCode)
return;
QKeyCode qcode = Q_KEY_CODE_UNMAPPED;
if (k.VKey < (int)qemu_input_map_win32_to_qcode.size())
qcode = qemu_input_map_win32_to_qcode[k.VKey];
//TODO
if (k.Flags & RI_KEY_E0) {
if (Q_KEY_CODE_SHIFT == qcode)
qcode = Q_KEY_CODE_SHIFT_R;
else if (Q_KEY_CODE_CTRL == qcode)
qcode = Q_KEY_CODE_CTRL_R;
else if (Q_KEY_CODE_ALT == qcode)
qcode = Q_KEY_CODE_ALT_R;
}
InputEvent ev{};
ev.type = INPUT_EVENT_KIND_KEY;
ev.u.key.down = !k.Flags;
ev.u.key.key.type = KEY_VALUE_KIND_QCODE;
ev.u.key.key.u.qcode = qcode;
hs->kbd.eh_entry(hs, &ev);
}
static void SendPointerEvent(InputEvent &ev, HIDState *hs)
{
if (hs->ptr.eh_entry) {
hs->ptr.eh_entry(hs, &ev);
}
}
static void ParseRawInputMS(RAWMOUSE &m, HIDState *hs)
{
int b = 0, z = 0;
InputEvent ev{};
if (m.usButtonFlags & RI_MOUSE_WHEEL)
z = (short)m.usButtonData / WHEEL_DELTA;
//OSDebugOut(TEXT("mouse: %d %d %u %hd\n"), m.lLastX, m.lLastY, m.ulButtons, z);
ev.type = INPUT_EVENT_KIND_BTN;
if (m.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN)
{
ev.u.btn.button = INPUT_BUTTON_LEFT;
ev.u.btn.down = true;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_LEFT_BUTTON_UP)
{
ev.u.btn.button = INPUT_BUTTON_LEFT;
ev.u.btn.down = false;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_RIGHT_BUTTON_DOWN)
{
ev.u.btn.button = INPUT_BUTTON_RIGHT;
ev.u.btn.down = true;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_RIGHT_BUTTON_UP)
{
ev.u.btn.button = INPUT_BUTTON_RIGHT;
ev.u.btn.down = false;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_MIDDLE_BUTTON_DOWN)
{
ev.u.btn.button = INPUT_BUTTON_MIDDLE;
ev.u.btn.down = true;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_MIDDLE_BUTTON_UP)
{
ev.u.btn.button = INPUT_BUTTON_MIDDLE;
ev.u.btn.down = false;
SendPointerEvent(ev, hs);
}
if (z != 0)
{
ev.u.btn.button = (z < 0) ? INPUT_BUTTON_WHEEL_DOWN : INPUT_BUTTON_WHEEL_UP;
for (int i = 0; i < z; i++)
static void ParseRawInputMS(RAWMOUSE& m, HIDState* hs)
{
ev.u.btn.down = true;
SendPointerEvent(ev, hs);
ev.u.btn.down = false; // TODO needs an UP event?
SendPointerEvent(ev, hs);
}
}
int b = 0, z = 0;
InputEvent ev{};
if (m.usFlags & MOUSE_MOVE_ABSOLUTE)
{
/*ev.type = INPUT_EVENT_KIND_ABS;
if (m.usButtonFlags & RI_MOUSE_WHEEL)
z = (short)m.usButtonData / WHEEL_DELTA;
//OSDebugOut(TEXT("mouse: %d %d %u %hd\n"), m.lLastX, m.lLastY, m.ulButtons, z);
ev.type = INPUT_EVENT_KIND_BTN;
if (m.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN)
{
ev.u.btn.button = INPUT_BUTTON_LEFT;
ev.u.btn.down = true;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_LEFT_BUTTON_UP)
{
ev.u.btn.button = INPUT_BUTTON_LEFT;
ev.u.btn.down = false;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_RIGHT_BUTTON_DOWN)
{
ev.u.btn.button = INPUT_BUTTON_RIGHT;
ev.u.btn.down = true;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_RIGHT_BUTTON_UP)
{
ev.u.btn.button = INPUT_BUTTON_RIGHT;
ev.u.btn.down = false;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_MIDDLE_BUTTON_DOWN)
{
ev.u.btn.button = INPUT_BUTTON_MIDDLE;
ev.u.btn.down = true;
SendPointerEvent(ev, hs);
}
if (m.ulButtons & RI_MOUSE_MIDDLE_BUTTON_UP)
{
ev.u.btn.button = INPUT_BUTTON_MIDDLE;
ev.u.btn.down = false;
SendPointerEvent(ev, hs);
}
if (z != 0)
{
ev.u.btn.button = (z < 0) ? INPUT_BUTTON_WHEEL_DOWN : INPUT_BUTTON_WHEEL_UP;
for (int i = 0; i < z; i++)
{
ev.u.btn.down = true;
SendPointerEvent(ev, hs);
ev.u.btn.down = false; // TODO needs an UP event?
SendPointerEvent(ev, hs);
}
}
if (m.usFlags & MOUSE_MOVE_ABSOLUTE)
{
/*ev.type = INPUT_EVENT_KIND_ABS;
ev.u.abs.axis = INPUT_AXIS_X;
ev.u.abs.value = m.lLastX;
SendPointerEvent(ev, hs);
@ -235,53 +253,54 @@ static void ParseRawInputMS(RAWMOUSE &m, HIDState *hs)
ev.u.abs.axis = INPUT_AXIS_Y;
ev.u.abs.value = m.lLastY;
SendPointerEvent(ev, hs);*/
}
else
{
ev.type = INPUT_EVENT_KIND_REL;
ev.u.rel.axis = INPUT_AXIS_X;
ev.u.rel.value = m.lLastX;
SendPointerEvent(ev, hs);
}
else
{
ev.type = INPUT_EVENT_KIND_REL;
ev.u.rel.axis = INPUT_AXIS_X;
ev.u.rel.value = m.lLastX;
SendPointerEvent(ev, hs);
ev.u.rel.axis = INPUT_AXIS_Y;
ev.u.rel.value = m.lLastY;
SendPointerEvent(ev, hs);
}
ev.u.rel.axis = INPUT_AXIS_Y;
ev.u.rel.value = m.lLastY;
SendPointerEvent(ev, hs);
}
if (hs->ptr.eh_sync)
hs->ptr.eh_sync(hs);
}
if (hs->ptr.eh_sync)
hs->ptr.eh_sync(hs);
}
void RawInput::ParseRawInput(PRAWINPUT pRawInput)
{
if (pRawInput->header.dwType == RIM_TYPEKEYBOARD)
ParseRawInputKB(pRawInput->data.keyboard, mHIDState);
else if (pRawInput->header.dwType == RIM_TYPEMOUSE)
ParseRawInputMS(pRawInput->data.mouse, mHIDState);
// else
// ParseRawInput(pRawInput, mHIDState);
}
void RawInput::ParseRawInput(PRAWINPUT pRawInput)
{
if (pRawInput->header.dwType == RIM_TYPEKEYBOARD)
ParseRawInputKB(pRawInput->data.keyboard, mHIDState);
else if (pRawInput->header.dwType == RIM_TYPEMOUSE)
ParseRawInputMS(pRawInput->data.mouse, mHIDState);
// else
// ParseRawInput(pRawInput, mHIDState);
}
int RawInput::Open()
{
Close();
shared::rawinput::RegisterCallback(this);
return 0;
}
int RawInput::Open()
{
Close();
shared::rawinput::RegisterCallback(this);
return 0;
}
int RawInput::Close()
{
Reset();
shared::rawinput::UnregisterCallback(this);
return 0;
}
int RawInput::Close()
{
Reset();
shared::rawinput::UnregisterCallback(this);
return 0;
}
int RawInput::Configure(int port, const char* dev_type, HIDType type, void *data)
{
Win32Handles *h = (Win32Handles*)data;
INT_PTR res = RESULT_CANCELED;
return res;
}
int RawInput::Configure(int port, const char* dev_type, HIDType type, void* data)
{
Win32Handles* h = (Win32Handles*)data;
INT_PTR res = RESULT_CANCELED;
return res;
}
}} //namespace
} // namespace raw
} // namespace usb_hid

View File

@ -17,33 +17,38 @@
#include "../hidproxy.h"
#include "../usb-hid.h"
namespace usb_hid { namespace raw {
static const char* APINAME = "rawinput";
class RawInput : public UsbHID, shared::rawinput::ParseRawInputCB
namespace usb_hid
{
public:
RawInput(int port, const char* dev_type) : UsbHID(port, dev_type)
namespace raw
{
}
~RawInput()
{
Close();
}
int Open();
int Close();
// int TokenIn(uint8_t *buf, int len);
int TokenOut(const uint8_t *data, int len);
int Reset() { return 0; }
void ParseRawInput(PRAWINPUT pRawInput);
static const TCHAR* Name()
{
return TEXT("Raw Input");
}
static const char* APINAME = "rawinput";
static int Configure(int port, const char* dev_type, HIDType, void *data);
};
class RawInput : public UsbHID, shared::rawinput::ParseRawInputCB
{
public:
RawInput(int port, const char* dev_type)
: UsbHID(port, dev_type)
{
}
~RawInput()
{
Close();
}
int Open();
int Close();
// int TokenIn(uint8_t *buf, int len);
int TokenOut(const uint8_t* data, int len);
int Reset() { return 0; }
void ParseRawInput(PRAWINPUT pRawInput);
}} // namespace
static const TCHAR* Name()
{
return TEXT("Raw Input");
}
static int Configure(int port, const char* dev_type, HIDType, void* data);
};
} // namespace raw
} // namespace usb_hid

View File

@ -24,7 +24,7 @@
#include "vl.h"
#include <windows.h>
#include <setupapi.h>
extern "C"{
extern "C" {
#include "../ddk/hidsdi.h"
}
@ -33,13 +33,13 @@ extern "C"{
#if 0
/* HID interface requests */
#define GET_REPORT 0xa101
#define GET_IDLE 0xa102
#define GET_REPORT 0xa101
#define GET_IDLE 0xa102
#define GET_PROTOCOL 0xa103
#define SET_IDLE 0x210a
#define SET_IDLE 0x210a
#define SET_PROTOCOL 0x210b
#define USB_MOUSE 1
#define USB_MOUSE 1
#define USB_TABLET 2
typedef struct USBKeyboardState {
@ -350,7 +350,7 @@ static const uint8_t vk_to_key_code[] = {
0x00, //FAIL: 0x00
};
#else
# ifdef ENABLE_KEYPAD_Fx
#ifdef ENABLE_KEYPAD_Fx
static const unsigned char scan_to_usb[] = {
0x00,0x29,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x2f,0x30,0x2a,0x2b,
0x14,0x1a,0x08,0x15,0x17,0x1c,0x18,0x0c,0x12,0x13,0x33,0x2e,0x28,0xe0,0x04,0x16,
@ -401,7 +401,7 @@ static const unsigned char scan_to_usb[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
# else
#else
static const unsigned char scan_to_usb[] = {
0x00,0x29,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x2f,0x30,0x2a,0x2b,
0x14,0x1a,0x08,0x15,0x17,0x1c,0x18,0x0c,0x12,0x13,0x33,0x2e,0x28,0xe0,0x04,0x16,
@ -452,7 +452,7 @@ static const unsigned char scan_to_usb[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
# endif
#endif
#endif
/* mostly the same values as the Bochs USB Keyboard device */
@ -623,9 +623,9 @@ static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
0xc0 // END_COLLECTION
};
#define BUZZER_VID 0x054C
#define BUZZER_PID 0x1000
#define BUZZER_PID2 0x0002
#define BUZZER_VID 0x054C
#define BUZZER_PID 0x1000
#define BUZZER_PID2 0x0002
unsigned char comp_data[6];
HANDLE usb_buzzer=(HANDLE)-1;

File diff suppressed because it is too large Load Diff

View File

@ -19,73 +19,78 @@
#include <list>
#include <string>
namespace usb_hid {
enum HIDType
namespace usb_hid
{
HIDTYPE_KBD,
HIDTYPE_MOUSE,
};
class UsbHID
{
public:
UsbHID(int port, const char* dev_type) : mPort(port), mDevType(dev_type) {}
virtual ~UsbHID() {}
virtual int Open() = 0;
virtual int Close() = 0;
// virtual int TokenIn(uint8_t *buf, int len) = 0;
virtual int TokenOut(const uint8_t *data, int len) = 0;
virtual int Reset() = 0;
enum HIDType
{
HIDTYPE_KBD,
HIDTYPE_MOUSE,
};
virtual int Port() { return mPort; }
virtual void Port(int port) { mPort = port; }
virtual void SetHIDState(HIDState *hs) { mHIDState = hs; }
virtual void SetHIDType(HIDType t) { mHIDType = t; }
class UsbHID
{
public:
UsbHID(int port, const char* dev_type)
: mPort(port)
, mDevType(dev_type)
{
}
virtual ~UsbHID() {}
virtual int Open() = 0;
virtual int Close() = 0;
// virtual int TokenIn(uint8_t *buf, int len) = 0;
virtual int TokenOut(const uint8_t* data, int len) = 0;
virtual int Reset() = 0;
protected:
int mPort;
HIDState *mHIDState;
HIDType mHIDType;
const char *mDevType;
};
virtual int Port() { return mPort; }
virtual void Port(int port) { mPort = port; }
virtual void SetHIDState(HIDState* hs) { mHIDState = hs; }
virtual void SetHIDType(HIDType t) { mHIDType = t; }
class HIDKbdDevice
{
public:
virtual ~HIDKbdDevice() {}
static USBDevice* CreateDevice(int port);
static const TCHAR* Name()
{
return TEXT("HID Keyboard");
}
static const char* TypeName()
{
return "hidkbd";
}
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);
};
protected:
int mPort;
HIDState* mHIDState;
HIDType mHIDType;
const char* mDevType;
};
class HIDMouseDevice
{
public:
virtual ~HIDMouseDevice() {}
static USBDevice* CreateDevice(int port);
static const TCHAR* Name()
{
return TEXT("HID Mouse");
}
static const char* TypeName()
{
return "hidmouse";
}
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);
};
class HIDKbdDevice
{
public:
virtual ~HIDKbdDevice() {}
static USBDevice* CreateDevice(int port);
static const TCHAR* Name()
{
return TEXT("HID Keyboard");
}
static const char* TypeName()
{
return "hidkbd";
}
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);
};
}
class HIDMouseDevice
{
public:
virtual ~HIDMouseDevice() {}
static USBDevice* CreateDevice(int port);
static const TCHAR* Name()
{
return TEXT("HID Mouse");
}
static const char* TypeName()
{
return "hidmouse";
}
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

View File

@ -21,106 +21,106 @@
/* Audio Interface Subclass Codes */
#define AUDIO_SUBCLASS_UNDEFINED 0x00
#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01
#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02
#define AUDIO_SUBCLASS_MIDISTREAMING 0x03
#define AUDIO_SUBCLASS_UNDEFINED 0x00
#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01
#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02
#define AUDIO_SUBCLASS_MIDISTREAMING 0x03
/* Audio Interface Protocol Codes */
#define AUDIO_PROTOCOL_UNDEFINED 0x00
#define AUDIO_PROTOCOL_UNDEFINED 0x00
/* Audio Descriptor Types */
#define AUDIO_UNDEFINED_DESCRIPTOR_TYPE 0x20
#define AUDIO_DEVICE_DESCRIPTOR_TYPE 0x21
#define AUDIO_CONFIGURATION_DESCRIPTOR_TYPE 0x22
#define AUDIO_STRING_DESCRIPTOR_TYPE 0x23
#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24
#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25
#define AUDIO_UNDEFINED_DESCRIPTOR_TYPE 0x20
#define AUDIO_DEVICE_DESCRIPTOR_TYPE 0x21
#define AUDIO_CONFIGURATION_DESCRIPTOR_TYPE 0x22
#define AUDIO_STRING_DESCRIPTOR_TYPE 0x23
#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24
#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25
/* Audio Control Interface Descriptor Subtypes */
#define AUDIO_CONTROL_UNDEFINED 0x00
#define AUDIO_CONTROL_HEADER 0x01
#define AUDIO_CONTROL_INPUT_TERMINAL 0x02
#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03
#define AUDIO_CONTROL_MIXER_UNIT 0x04
#define AUDIO_CONTROL_SELECTOR_UNIT 0x05
#define AUDIO_CONTROL_FEATURE_UNIT 0x06
#define AUDIO_CONTROL_PROCESSING_UNIT 0x07
#define AUDIO_CONTROL_EXTENSION_UNIT 0x08
#define AUDIO_CONTROL_UNDEFINED 0x00
#define AUDIO_CONTROL_HEADER 0x01
#define AUDIO_CONTROL_INPUT_TERMINAL 0x02
#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03
#define AUDIO_CONTROL_MIXER_UNIT 0x04
#define AUDIO_CONTROL_SELECTOR_UNIT 0x05
#define AUDIO_CONTROL_FEATURE_UNIT 0x06
#define AUDIO_CONTROL_PROCESSING_UNIT 0x07
#define AUDIO_CONTROL_EXTENSION_UNIT 0x08
/* Audio Streaming Interface Descriptor Subtypes */
#define AUDIO_STREAMING_UNDEFINED 0x00
#define AUDIO_STREAMING_GENERAL 0x01
#define AUDIO_STREAMING_FORMAT_TYPE 0x02
#define AUDIO_STREAMING_FORMAT_SPECIFIC 0x03
#define AUDIO_STREAMING_UNDEFINED 0x00
#define AUDIO_STREAMING_GENERAL 0x01
#define AUDIO_STREAMING_FORMAT_TYPE 0x02
#define AUDIO_STREAMING_FORMAT_SPECIFIC 0x03
/* Audio Endpoint Descriptor Subtypes */
#define AUDIO_ENDPOINT_UNDEFINED 0x00
#define AUDIO_ENDPOINT_GENERAL 0x01
#define AUDIO_ENDPOINT_UNDEFINED 0x00
#define AUDIO_ENDPOINT_GENERAL 0x01
/* Audio Descriptor Sizes */
#define AUDIO_CONTROL_INTERFACE_DESC_SZ(n) 0x08+n
#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07
#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0C
#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09
#define AUDIO_MIXER_UNIT_DESC_SZ(p,n) 0x0A+p+n
#define AUDIO_SELECTOR_UNIT_DESC_SZ(p) 0x06+p
#define AUDIO_FEATURE_UNIT_DESC_SZ(ch,n) 0x07+(ch+1)*n
#define AUDIO_PROCESSING_UNIT_DESC_SZ(p,n,x) 0x0D+p+n+x
#define AUDIO_EXTENSION_UNIT_DESC_SZ(p,n) 0x0D+p+n
#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09
#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07
#define AUDIO_CONTROL_INTERFACE_DESC_SZ(n) 0x08 + n
#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07
#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0C
#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09
#define AUDIO_MIXER_UNIT_DESC_SZ(p, n) 0x0A + p + n
#define AUDIO_SELECTOR_UNIT_DESC_SZ(p) 0x06 + p
#define AUDIO_FEATURE_UNIT_DESC_SZ(ch, n) 0x07 + (ch + 1) * n
#define AUDIO_PROCESSING_UNIT_DESC_SZ(p, n, x) 0x0D + p + n + x
#define AUDIO_EXTENSION_UNIT_DESC_SZ(p, n) 0x0D + p + n
#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09
#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07
/* Audio Processing Unit Process Types */
#define AUDIO_UNDEFINED_PROCESS 0x00
#define AUDIO_UP_DOWN_MIX_PROCESS 0x01
#define AUDIO_DOLBY_PROLOGIC_PROCESS 0x02
#define AUDIO_3D_STEREO_PROCESS 0x03
#define AUDIO_REVERBERATION_PROCESS 0x04
#define AUDIO_CHORUS_PROCESS 0x05
#define AUDIO_DYN_RANGE_COMP_PROCESS 0x06
#define AUDIO_UNDEFINED_PROCESS 0x00
#define AUDIO_UP_DOWN_MIX_PROCESS 0x01
#define AUDIO_DOLBY_PROLOGIC_PROCESS 0x02
#define AUDIO_3D_STEREO_PROCESS 0x03
#define AUDIO_REVERBERATION_PROCESS 0x04
#define AUDIO_CHORUS_PROCESS 0x05
#define AUDIO_DYN_RANGE_COMP_PROCESS 0x06
/* Audio Request Codes */
#define AUDIO_REQUEST_UNDEFINED 0x00
#define AUDIO_REQUEST_SET_CUR 0x01
#define AUDIO_REQUEST_GET_CUR 0x81
#define AUDIO_REQUEST_SET_MIN 0x02
#define AUDIO_REQUEST_GET_MIN 0x82
#define AUDIO_REQUEST_SET_MAX 0x03
#define AUDIO_REQUEST_GET_MAX 0x83
#define AUDIO_REQUEST_SET_RES 0x04
#define AUDIO_REQUEST_GET_RES 0x84
#define AUDIO_REQUEST_SET_MEM 0x05
#define AUDIO_REQUEST_GET_MEM 0x85
#define AUDIO_REQUEST_GET_STAT 0xFF
#define AUDIO_REQUEST_UNDEFINED 0x00
#define AUDIO_REQUEST_SET_CUR 0x01
#define AUDIO_REQUEST_GET_CUR 0x81
#define AUDIO_REQUEST_SET_MIN 0x02
#define AUDIO_REQUEST_GET_MIN 0x82
#define AUDIO_REQUEST_SET_MAX 0x03
#define AUDIO_REQUEST_GET_MAX 0x83
#define AUDIO_REQUEST_SET_RES 0x04
#define AUDIO_REQUEST_GET_RES 0x84
#define AUDIO_REQUEST_SET_MEM 0x05
#define AUDIO_REQUEST_GET_MEM 0x85
#define AUDIO_REQUEST_GET_STAT 0xFF
/* Audio Control Selector Codes */
#define AUDIO_CONTROL_UNDEFINED 0x00 /* Common Selector */
#define AUDIO_CONTROL_UNDEFINED 0x00 /* Common Selector */
/* Terminal Control Selectors */
#define AUDIO_COPY_PROTECT_CONTROL 0x01
#define AUDIO_COPY_PROTECT_CONTROL 0x01
/* Feature Unit Control Selectors */
#define AUDIO_MUTE_CONTROL 0x01
#define AUDIO_VOLUME_CONTROL 0x02
#define AUDIO_BASS_CONTROL 0x03
#define AUDIO_MID_CONTROL 0x04
#define AUDIO_TREBLE_CONTROL 0x05
#define AUDIO_GRAPHIC_EQUALIZER_CONTROL 0x06
#define AUDIO_AUTOMATIC_GAIN_CONTROL 0x07
#define AUDIO_DELAY_CONTROL 0x08
#define AUDIO_BASS_BOOST_CONTROL 0x09
#define AUDIO_LOUDNESS_CONTROL 0x0A
#define AUDIO_MUTE_CONTROL 0x01
#define AUDIO_VOLUME_CONTROL 0x02
#define AUDIO_BASS_CONTROL 0x03
#define AUDIO_MID_CONTROL 0x04
#define AUDIO_TREBLE_CONTROL 0x05
#define AUDIO_GRAPHIC_EQUALIZER_CONTROL 0x06
#define AUDIO_AUTOMATIC_GAIN_CONTROL 0x07
#define AUDIO_DELAY_CONTROL 0x08
#define AUDIO_BASS_BOOST_CONTROL 0x09
#define AUDIO_LOUDNESS_CONTROL 0x0A
/* Processing Unit Control Selectors: */
#define AUDIO_ENABLE_CONTROL 0x01 /* Common Selector */
#define AUDIO_MODE_SELECT_CONTROL 0x02 /* Common Selector */
#define AUDIO_ENABLE_CONTROL 0x01 /* Common Selector */
#define AUDIO_MODE_SELECT_CONTROL 0x02 /* Common Selector */
/* - Up/Down-mix Control Selectors */
/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
@ -132,127 +132,127 @@
/* - 3D Stereo Extender Control Selectors */
/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
#define AUDIO_SPACIOUSNESS_CONTROL 0x02
#define AUDIO_SPACIOUSNESS_CONTROL 0x02
/* - Reverberation Control Selectors */
/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
#define AUDIO_REVERB_LEVEL_CONTROL 0x02
#define AUDIO_REVERB_TIME_CONTROL 0x03
#define AUDIO_REVERB_FEEDBACK_CONTROL 0x04
#define AUDIO_REVERB_LEVEL_CONTROL 0x02
#define AUDIO_REVERB_TIME_CONTROL 0x03
#define AUDIO_REVERB_FEEDBACK_CONTROL 0x04
/* - Chorus Control Selectors */
/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
#define AUDIO_CHORUS_LEVEL_CONTROL 0x02
#define AUDIO_SHORUS_RATE_CONTROL 0x03
#define AUDIO_CHORUS_DEPTH_CONTROL 0x04
#define AUDIO_CHORUS_LEVEL_CONTROL 0x02
#define AUDIO_SHORUS_RATE_CONTROL 0x03
#define AUDIO_CHORUS_DEPTH_CONTROL 0x04
/* - Dynamic Range Compressor Control Selectors */
/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
#define AUDIO_COMPRESSION_RATE_CONTROL 0x02
#define AUDIO_MAX_AMPL_CONTROL 0x03
#define AUDIO_THRESHOLD_CONTROL 0x04
#define AUDIO_ATTACK_TIME_CONTROL 0x05
#define AUDIO_RELEASE_TIME_CONTROL 0x06
#define AUDIO_COMPRESSION_RATE_CONTROL 0x02
#define AUDIO_MAX_AMPL_CONTROL 0x03
#define AUDIO_THRESHOLD_CONTROL 0x04
#define AUDIO_ATTACK_TIME_CONTROL 0x05
#define AUDIO_RELEASE_TIME_CONTROL 0x06
/* Extension Unit Control Selectors */
/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
/* Endpoint Control Selectors */
#define AUDIO_SAMPLING_FREQ_CONTROL 0x01
#define AUDIO_PITCH_CONTROL 0x02
#define AUDIO_SAMPLING_FREQ_CONTROL 0x01
#define AUDIO_PITCH_CONTROL 0x02
/* Audio Format Specific Control Selectors */
/* MPEG Control Selectors */
#define AUDIO_MPEG_CONTROL_UNDEFINED 0x00
#define AUDIO_MPEG_DUAL_CHANNEL_CONTROL 0x01
#define AUDIO_MPEG_SECOND_STEREO_CONTROL 0x02
#define AUDIO_MPEG_MULTILINGUAL_CONTROL 0x03
#define AUDIO_MPEG_DYN_RANGE_CONTROL 0x04
#define AUDIO_MPEG_SCALING_CONTROL 0x05
#define AUDIO_MPEG_HILO_SCALING_CONTROL 0x06
#define AUDIO_MPEG_CONTROL_UNDEFINED 0x00
#define AUDIO_MPEG_DUAL_CHANNEL_CONTROL 0x01
#define AUDIO_MPEG_SECOND_STEREO_CONTROL 0x02
#define AUDIO_MPEG_MULTILINGUAL_CONTROL 0x03
#define AUDIO_MPEG_DYN_RANGE_CONTROL 0x04
#define AUDIO_MPEG_SCALING_CONTROL 0x05
#define AUDIO_MPEG_HILO_SCALING_CONTROL 0x06
/* AC-3 Control Selectors */
#define AUDIO_AC3_CONTROL_UNDEFINED 0x00
#define AUDIO_AC3_MODE_CONTROL 0x01
#define AUDIO_AC3_DYN_RANGE_CONTROL 0x02
#define AUDIO_AC3_SCALING_CONTROL 0x03
#define AUDIO_AC3_HILO_SCALING_CONTROL 0x04
#define AUDIO_AC3_CONTROL_UNDEFINED 0x00
#define AUDIO_AC3_MODE_CONTROL 0x01
#define AUDIO_AC3_DYN_RANGE_CONTROL 0x02
#define AUDIO_AC3_SCALING_CONTROL 0x03
#define AUDIO_AC3_HILO_SCALING_CONTROL 0x04
/* Audio Format Types */
#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00
#define AUDIO_FORMAT_TYPE_I 0x01
#define AUDIO_FORMAT_TYPE_II 0x02
#define AUDIO_FORMAT_TYPE_III 0x03
#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00
#define AUDIO_FORMAT_TYPE_I 0x01
#define AUDIO_FORMAT_TYPE_II 0x02
#define AUDIO_FORMAT_TYPE_III 0x03
/* Audio Format Type Descriptor Sizes */
#define AUDIO_FORMAT_TYPE_I_DESC_SZ(n) 0x08+(n*3)
#define AUDIO_FORMAT_TYPE_II_DESC_SZ(n) 0x09+(n*3)
#define AUDIO_FORMAT_TYPE_III_DESC_SZ(n) 0x08+(n*3)
#define AUDIO_FORMAT_MPEG_DESC_SIZE 0x09
#define AUDIO_FORMAT_AC3_DESC_SIZE 0x0A
#define AUDIO_FORMAT_TYPE_I_DESC_SZ(n) 0x08 + (n * 3)
#define AUDIO_FORMAT_TYPE_II_DESC_SZ(n) 0x09 + (n * 3)
#define AUDIO_FORMAT_TYPE_III_DESC_SZ(n) 0x08 + (n * 3)
#define AUDIO_FORMAT_MPEG_DESC_SIZE 0x09
#define AUDIO_FORMAT_AC3_DESC_SIZE 0x0A
/* Audio Data Format Codes */
/* Audio Data Format Type I Codes */
#define AUDIO_FORMAT_TYPE_I_UNDEFINED 0x0000
#define AUDIO_FORMAT_PCM 0x0001
#define AUDIO_FORMAT_PCM8 0x0002
#define AUDIO_FORMAT_IEEE_FLOAT 0x0003
#define AUDIO_FORMAT_ALAW 0x0004
#define AUDIO_FORMAT_MULAW 0x0005
#define AUDIO_FORMAT_TYPE_I_UNDEFINED 0x0000
#define AUDIO_FORMAT_PCM 0x0001
#define AUDIO_FORMAT_PCM8 0x0002
#define AUDIO_FORMAT_IEEE_FLOAT 0x0003
#define AUDIO_FORMAT_ALAW 0x0004
#define AUDIO_FORMAT_MULAW 0x0005
/* Audio Data Format Type II Codes */
#define AUDIO_FORMAT_TYPE_II_UNDEFINED 0x1000
#define AUDIO_FORMAT_MPEG 0x1001
#define AUDIO_FORMAT_AC3 0x1002
#define AUDIO_FORMAT_TYPE_II_UNDEFINED 0x1000
#define AUDIO_FORMAT_MPEG 0x1001
#define AUDIO_FORMAT_AC3 0x1002
/* Audio Data Format Type III Codes */
#define AUDIO_FORMAT_TYPE_III_UNDEFINED 0x2000
#define AUDIO_FORMAT_IEC1937_AC3 0x2001
#define AUDIO_FORMAT_IEC1937_MPEG1_L1 0x2002
#define AUDIO_FORMAT_IEC1937_MPEG1_L2_3 0x2003
#define AUDIO_FORMAT_IEC1937_MPEG2_NOEXT 0x2003
#define AUDIO_FORMAT_IEC1937_MPEG2_EXT 0x2004
#define AUDIO_FORMAT_IEC1937_MPEG2_L1_LS 0x2005
#define AUDIO_FORMAT_IEC1937_MPEG2_L2_3 0x2006
#define AUDIO_FORMAT_TYPE_III_UNDEFINED 0x2000
#define AUDIO_FORMAT_IEC1937_AC3 0x2001
#define AUDIO_FORMAT_IEC1937_MPEG1_L1 0x2002
#define AUDIO_FORMAT_IEC1937_MPEG1_L2_3 0x2003
#define AUDIO_FORMAT_IEC1937_MPEG2_NOEXT 0x2003
#define AUDIO_FORMAT_IEC1937_MPEG2_EXT 0x2004
#define AUDIO_FORMAT_IEC1937_MPEG2_L1_LS 0x2005
#define AUDIO_FORMAT_IEC1937_MPEG2_L2_3 0x2006
/* Predefined Audio Channel Configuration Bits */
#define AUDIO_CHANNEL_M 0x0000 /* Mono */
#define AUDIO_CHANNEL_L 0x0001 /* Left Front */
#define AUDIO_CHANNEL_R 0x0002 /* Right Front */
#define AUDIO_CHANNEL_C 0x0004 /* Center Front */
#define AUDIO_CHANNEL_LFE 0x0008 /* Low Freq. Enhance. */
#define AUDIO_CHANNEL_LS 0x0010 /* Left Surround */
#define AUDIO_CHANNEL_RS 0x0020 /* Right Surround */
#define AUDIO_CHANNEL_LC 0x0040 /* Left of Center */
#define AUDIO_CHANNEL_RC 0x0080 /* Right of Center */
#define AUDIO_CHANNEL_S 0x0100 /* Surround */
#define AUDIO_CHANNEL_SL 0x0200 /* Side Left */
#define AUDIO_CHANNEL_SR 0x0400 /* Side Right */
#define AUDIO_CHANNEL_T 0x0800 /* Top */
#define AUDIO_CHANNEL_M 0x0000 /* Mono */
#define AUDIO_CHANNEL_L 0x0001 /* Left Front */
#define AUDIO_CHANNEL_R 0x0002 /* Right Front */
#define AUDIO_CHANNEL_C 0x0004 /* Center Front */
#define AUDIO_CHANNEL_LFE 0x0008 /* Low Freq. Enhance. */
#define AUDIO_CHANNEL_LS 0x0010 /* Left Surround */
#define AUDIO_CHANNEL_RS 0x0020 /* Right Surround */
#define AUDIO_CHANNEL_LC 0x0040 /* Left of Center */
#define AUDIO_CHANNEL_RC 0x0080 /* Right of Center */
#define AUDIO_CHANNEL_S 0x0100 /* Surround */
#define AUDIO_CHANNEL_SL 0x0200 /* Side Left */
#define AUDIO_CHANNEL_SR 0x0400 /* Side Right */
#define AUDIO_CHANNEL_T 0x0800 /* Top */
/* Feature Unit Control Bits */
#define AUDIO_CONTROL_MUTE 0x0001
#define AUDIO_CONTROL_VOLUME 0x0002
#define AUDIO_CONTROL_BASS 0x0004
#define AUDIO_CONTROL_MID 0x0008
#define AUDIO_CONTROL_TREBLE 0x0010
#define AUDIO_CONTROL_GRAPHIC_EQUALIZER 0x0020
#define AUDIO_CONTROL_AUTOMATIC_GAIN 0x0040
#define AUDIO_CONTROL_DEALY 0x0080
#define AUDIO_CONTROL_BASS_BOOST 0x0100
#define AUDIO_CONTROL_LOUDNESS 0x0200
#define AUDIO_CONTROL_MUTE 0x0001
#define AUDIO_CONTROL_VOLUME 0x0002
#define AUDIO_CONTROL_BASS 0x0004
#define AUDIO_CONTROL_MID 0x0008
#define AUDIO_CONTROL_TREBLE 0x0010
#define AUDIO_CONTROL_GRAPHIC_EQUALIZER 0x0020
#define AUDIO_CONTROL_AUTOMATIC_GAIN 0x0040
#define AUDIO_CONTROL_DEALY 0x0080
#define AUDIO_CONTROL_BASS_BOOST 0x0100
#define AUDIO_CONTROL_LOUDNESS 0x0200
/* Processing Unit Control Bits: */
#define AUDIO_CONTROL_ENABLE 0x0001 /* Common Bit */
#define AUDIO_CONTROL_MODE_SELECT 0x0002 /* Common Bit */
#define AUDIO_CONTROL_ENABLE 0x0001 /* Common Bit */
#define AUDIO_CONTROL_MODE_SELECT 0x0002 /* Common Bit */
/* - Up/Down-mix Control Bits */
/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
@ -264,109 +264,109 @@
/* - 3D Stereo Extender Control Bits */
/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
#define AUDIO_CONTROL_SPACIOUSNESS 0x0002
#define AUDIO_CONTROL_SPACIOUSNESS 0x0002
/* - Reverberation Control Bits */
/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
#define AUDIO_CONTROL_REVERB_TYPE 0x0002
#define AUDIO_CONTROL_REVERB_LEVEL 0x0004
#define AUDIO_CONTROL_REVERB_TIME 0x0008
#define AUDIO_CONTROL_REVERB_FEEDBACK 0x0010
#define AUDIO_CONTROL_REVERB_TYPE 0x0002
#define AUDIO_CONTROL_REVERB_LEVEL 0x0004
#define AUDIO_CONTROL_REVERB_TIME 0x0008
#define AUDIO_CONTROL_REVERB_FEEDBACK 0x0010
/* - Chorus Control Bits */
/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
#define AUDIO_CONTROL_CHORUS_LEVEL 0x0002
#define AUDIO_CONTROL_SHORUS_RATE 0x0004
#define AUDIO_CONTROL_CHORUS_DEPTH 0x0008
#define AUDIO_CONTROL_CHORUS_LEVEL 0x0002
#define AUDIO_CONTROL_SHORUS_RATE 0x0004
#define AUDIO_CONTROL_CHORUS_DEPTH 0x0008
/* - Dynamic Range Compressor Control Bits */
/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
#define AUDIO_CONTROL_COMPRESSION_RATE 0x0002
#define AUDIO_CONTROL_MAX_AMPL 0x0004
#define AUDIO_CONTROL_THRESHOLD 0x0008
#define AUDIO_CONTROL_ATTACK_TIME 0x0010
#define AUDIO_CONTROL_RELEASE_TIME 0x0020
#define AUDIO_CONTROL_COMPRESSION_RATE 0x0002
#define AUDIO_CONTROL_MAX_AMPL 0x0004
#define AUDIO_CONTROL_THRESHOLD 0x0008
#define AUDIO_CONTROL_ATTACK_TIME 0x0010
#define AUDIO_CONTROL_RELEASE_TIME 0x0020
/* Extension Unit Control Bits */
/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
/* Endpoint Control Bits */
#define AUDIO_CONTROL_SAMPLING_FREQ 0x01
#define AUDIO_CONTROL_PITCH 0x02
#define AUDIO_MAX_PACKETS_ONLY 0x80
#define AUDIO_CONTROL_SAMPLING_FREQ 0x01
#define AUDIO_CONTROL_PITCH 0x02
#define AUDIO_MAX_PACKETS_ONLY 0x80
/* Audio Terminal Types */
/* USB Terminal Types */
#define AUDIO_TERMINAL_USB_UNDEFINED 0x0100
#define AUDIO_TERMINAL_USB_STREAMING 0x0101
#define AUDIO_TERMINAL_USB_VENDOR_SPECIFIC 0x01FF
#define AUDIO_TERMINAL_USB_UNDEFINED 0x0100
#define AUDIO_TERMINAL_USB_STREAMING 0x0101
#define AUDIO_TERMINAL_USB_VENDOR_SPECIFIC 0x01FF
/* Input Terminal Types */
#define AUDIO_TERMINAL_INPUT_UNDEFINED 0x0200
#define AUDIO_TERMINAL_MICROPHONE 0x0201
#define AUDIO_TERMINAL_DESKTOP_MICROPHONE 0x0202
#define AUDIO_TERMINAL_PERSONAL_MICROPHONE 0x0203
#define AUDIO_TERMINAL_OMNI_DIR_MICROPHONE 0x0204
#define AUDIO_TERMINAL_MICROPHONE_ARRAY 0x0205
#define AUDIO_TERMINAL_PROCESSING_MIC_ARRAY 0x0206
#define AUDIO_TERMINAL_INPUT_UNDEFINED 0x0200
#define AUDIO_TERMINAL_MICROPHONE 0x0201
#define AUDIO_TERMINAL_DESKTOP_MICROPHONE 0x0202
#define AUDIO_TERMINAL_PERSONAL_MICROPHONE 0x0203
#define AUDIO_TERMINAL_OMNI_DIR_MICROPHONE 0x0204
#define AUDIO_TERMINAL_MICROPHONE_ARRAY 0x0205
#define AUDIO_TERMINAL_PROCESSING_MIC_ARRAY 0x0206
/* Output Terminal Types */
#define AUDIO_TERMINAL_OUTPUT_UNDEFINED 0x0300
#define AUDIO_TERMINAL_SPEAKER 0x0301
#define AUDIO_TERMINAL_HEADPHONES 0x0302
#define AUDIO_TERMINAL_HEAD_MOUNTED_AUDIO 0x0303
#define AUDIO_TERMINAL_DESKTOP_SPEAKER 0x0304
#define AUDIO_TERMINAL_ROOM_SPEAKER 0x0305
#define AUDIO_TERMINAL_COMMUNICATION_SPEAKER 0x0306
#define AUDIO_TERMINAL_LOW_FREQ_SPEAKER 0x0307
#define AUDIO_TERMINAL_OUTPUT_UNDEFINED 0x0300
#define AUDIO_TERMINAL_SPEAKER 0x0301
#define AUDIO_TERMINAL_HEADPHONES 0x0302
#define AUDIO_TERMINAL_HEAD_MOUNTED_AUDIO 0x0303
#define AUDIO_TERMINAL_DESKTOP_SPEAKER 0x0304
#define AUDIO_TERMINAL_ROOM_SPEAKER 0x0305
#define AUDIO_TERMINAL_COMMUNICATION_SPEAKER 0x0306
#define AUDIO_TERMINAL_LOW_FREQ_SPEAKER 0x0307
/* Bi-directional Terminal Types */
#define AUDIO_TERMINAL_BIDIRECTIONAL_UNDEFINED 0x0400
#define AUDIO_TERMINAL_HANDSET 0x0401
#define AUDIO_TERMINAL_HEAD_MOUNTED_HANDSET 0x0402
#define AUDIO_TERMINAL_SPEAKERPHONE 0x0403
#define AUDIO_TERMINAL_BIDIRECTIONAL_UNDEFINED 0x0400
#define AUDIO_TERMINAL_HANDSET 0x0401
#define AUDIO_TERMINAL_HEAD_MOUNTED_HANDSET 0x0402
#define AUDIO_TERMINAL_SPEAKERPHONE 0x0403
#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOSUPRESS 0x0404
#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOCANCEL 0x0405
#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOCANCEL 0x0405
/* Telephony Terminal Types */
#define AUDIO_TERMINAL_TELEPHONY_UNDEFINED 0x0500
#define AUDIO_TERMINAL_PHONE_LINE 0x0501
#define AUDIO_TERMINAL_TELEPHONE 0x0502
#define AUDIO_TERMINAL_DOWN_LINE_PHONE 0x0503
#define AUDIO_TERMINAL_TELEPHONY_UNDEFINED 0x0500
#define AUDIO_TERMINAL_PHONE_LINE 0x0501
#define AUDIO_TERMINAL_TELEPHONE 0x0502
#define AUDIO_TERMINAL_DOWN_LINE_PHONE 0x0503
/* External Terminal Types */
#define AUDIO_TERMINAL_EXTERNAL_UNDEFINED 0x0600
#define AUDIO_TERMINAL_ANALOG_CONNECTOR 0x0601
#define AUDIO_TERMINAL_DIGITAL_AUDIO_INTERFACE 0x0602
#define AUDIO_TERMINAL_LINE_CONNECTOR 0x0603
#define AUDIO_TERMINAL_LEGACY_AUDIO_CONNECTOR 0x0604
#define AUDIO_TERMINAL_SPDIF_INTERFACE 0x0605
#define AUDIO_TERMINAL_1394_DA_STREAM 0x0606
#define AUDIO_TERMINAL_1394_DA_STREAM_TRACK 0x0607
#define AUDIO_TERMINAL_EXTERNAL_UNDEFINED 0x0600
#define AUDIO_TERMINAL_ANALOG_CONNECTOR 0x0601
#define AUDIO_TERMINAL_DIGITAL_AUDIO_INTERFACE 0x0602
#define AUDIO_TERMINAL_LINE_CONNECTOR 0x0603
#define AUDIO_TERMINAL_LEGACY_AUDIO_CONNECTOR 0x0604
#define AUDIO_TERMINAL_SPDIF_INTERFACE 0x0605
#define AUDIO_TERMINAL_1394_DA_STREAM 0x0606
#define AUDIO_TERMINAL_1394_DA_STREAM_TRACK 0x0607
/* Embedded Function Terminal Types */
#define AUDIO_TERMINAL_EMBEDDED_UNDEFINED 0x0700
#define AUDIO_TERMINAL_CALIBRATION_NOISE 0x0701
#define AUDIO_TERMINAL_EQUALIZATION_NOISE 0x0702
#define AUDIO_TERMINAL_CD_PLAYER 0x0703
#define AUDIO_TERMINAL_DAT 0x0704
#define AUDIO_TERMINAL_DCC 0x0705
#define AUDIO_TERMINAL_MINI_DISK 0x0706
#define AUDIO_TERMINAL_ANALOG_TAPE 0x0707
#define AUDIO_TERMINAL_PHONOGRAPH 0x0708
#define AUDIO_TERMINAL_VCR_AUDIO 0x0709
#define AUDIO_TERMINAL_VIDEO_DISC_AUDIO 0x070A
#define AUDIO_TERMINAL_DVD_AUDIO 0x070B
#define AUDIO_TERMINAL_TV_TUNER_AUDIO 0x070C
#define AUDIO_TERMINAL_EMBEDDED_UNDEFINED 0x0700
#define AUDIO_TERMINAL_CALIBRATION_NOISE 0x0701
#define AUDIO_TERMINAL_EQUALIZATION_NOISE 0x0702
#define AUDIO_TERMINAL_CD_PLAYER 0x0703
#define AUDIO_TERMINAL_DAT 0x0704
#define AUDIO_TERMINAL_DCC 0x0705
#define AUDIO_TERMINAL_MINI_DISK 0x0706
#define AUDIO_TERMINAL_ANALOG_TAPE 0x0707
#define AUDIO_TERMINAL_PHONOGRAPH 0x0708
#define AUDIO_TERMINAL_VCR_AUDIO 0x0709
#define AUDIO_TERMINAL_VIDEO_DISC_AUDIO 0x070A
#define AUDIO_TERMINAL_DVD_AUDIO 0x070B
#define AUDIO_TERMINAL_TV_TUNER_AUDIO 0x070C
#define AUDIO_TERMINAL_SATELLITE_RECEIVER_AUDIO 0x070D
#define AUDIO_TERMINAL_CABLE_TUNER_AUDIO 0x070E
#define AUDIO_TERMINAL_DSS_AUDIO 0x070F
#define AUDIO_TERMINAL_RADIO_RECEIVER 0x0710
#define AUDIO_TERMINAL_RADIO_TRANSMITTER 0x0711
#define AUDIO_TERMINAL_MULTI_TRACK_RECORDER 0x0712
#define AUDIO_TERMINAL_SYNTHESIZER 0x0713
#define AUDIO_TERMINAL_CABLE_TUNER_AUDIO 0x070E
#define AUDIO_TERMINAL_DSS_AUDIO 0x070F
#define AUDIO_TERMINAL_RADIO_RECEIVER 0x0710
#define AUDIO_TERMINAL_RADIO_TRANSMITTER 0x0711
#define AUDIO_TERMINAL_MULTI_TRACK_RECORDER 0x0712
#define AUDIO_TERMINAL_SYNTHESIZER 0x0713
#endif /* __AUDIO_H__ */
#endif /* __AUDIO_H__ */

View File

@ -16,66 +16,73 @@
#pragma once
#include "audiodeviceproxy.h"
namespace usb_mic { namespace audiodev_noop {
static const char *APINAME = "noop";
class NoopAudioDevice : public AudioDevice
namespace usb_mic
{
public:
NoopAudioDevice(int port, const char* dev_type, int mic, AudioDir dir): AudioDevice(port, dev_type, mic, dir) {}
~NoopAudioDevice() {}
void Start() {}
void Stop() {}
virtual bool GetFrames(uint32_t *size)
namespace audiodev_noop
{
return true;
}
virtual uint32_t GetBuffer(int16_t *outBuf, uint32_t outFrames)
{
return outFrames;
}
virtual uint32_t SetBuffer(int16_t *inBuf, uint32_t inFrames)
{
return inFrames;
}
virtual void SetResampling(int samplerate) {}
virtual uint32_t GetChannels()
{
return 1;
}
virtual bool Compare(AudioDevice* compare)
{
return false;
}
static const char* APINAME = "noop";
static const TCHAR* Name()
{
return TEXT("NOOP");
}
class NoopAudioDevice : public AudioDevice
{
public:
NoopAudioDevice(int port, const char* dev_type, int mic, AudioDir dir)
: AudioDevice(port, dev_type, mic, dir)
{
}
~NoopAudioDevice() {}
void Start() {}
void Stop() {}
virtual bool GetFrames(uint32_t* size)
{
return true;
}
virtual uint32_t GetBuffer(int16_t* outBuf, uint32_t outFrames)
{
return outFrames;
}
virtual uint32_t SetBuffer(int16_t* inBuf, uint32_t inFrames)
{
return inFrames;
}
virtual void SetResampling(int samplerate) {}
virtual uint32_t GetChannels()
{
return 1;
}
static bool AudioInit()
{
return true;
}
virtual bool Compare(AudioDevice* compare)
{
return false;
}
static void AudioDeinit()
{
}
static const TCHAR* Name()
{
return TEXT("NOOP");
}
static void AudioDevices(std::vector<AudioDeviceInfo> &devices, AudioDir )
{
AudioDeviceInfo info;
info.strID = TEXT("silence");
info.strName = TEXT("Silence");
devices.push_back(info);
}
static bool AudioInit()
{
return true;
}
static int Configure(int port, const char* dev_type, void *data)
{
return RESULT_OK;
}
};
static void AudioDeinit()
{
}
}}
static void AudioDevices(std::vector<AudioDeviceInfo>& devices, AudioDir)
{
AudioDeviceInfo info;
info.strID = TEXT("silence");
info.strName = TEXT("Silence");
devices.push_back(info);
}
static int Configure(int port, const char* dev_type, void* data)
{
return RESULT_OK;
}
};
} // namespace audiodev_noop
} // namespace usb_mic

File diff suppressed because it is too large Load Diff

View File

@ -25,140 +25,145 @@
#include <mutex>
#include <chrono>
namespace usb_mic { namespace audiodev_pulse {
namespace usb_mic
{
namespace audiodev_pulse
{
// macros for string concat
#undef APINAME_
#define APINAME_ "pulse"
static const char *APINAME = "pulse";
static const char* APINAME = "pulse";
using hrc = std::chrono::high_resolution_clock;
using ms = std::chrono::milliseconds;
using us = std::chrono::microseconds;
using ns = std::chrono::nanoseconds;
using sec = std::chrono::seconds;
using hrc = std::chrono::high_resolution_clock;
using ms = std::chrono::milliseconds;
using us = std::chrono::microseconds;
using ns = std::chrono::nanoseconds;
using sec = std::chrono::seconds;
class PulseAudioDevice : public AudioDevice
{
public:
PulseAudioDevice(int port, const char* dev_type, int device, AudioDir dir): AudioDevice(port, dev_type, device, dir)
, mBuffering(50)
, mPaused(true)
, mQuit(false)
, mPMainLoop(nullptr)
, mPContext(nullptr)
, mStream(nullptr)
, mServer(nullptr)
, mPAready(0)
, mResampleRatio(1.0)
, mTimeAdjust(1.0)
, mSamplesPerSec(48000)
, mResampler(nullptr)
, mOutSamples(0)
{
int i = dir == AUDIODIR_SOURCE ? 0 : 2;
const char* var_names[] = {
N_AUDIO_SOURCE0,
N_AUDIO_SOURCE1,
N_AUDIO_SINK0,
N_AUDIO_SINK1
class PulseAudioDevice : public AudioDevice
{
public:
PulseAudioDevice(int port, const char* dev_type, int device, AudioDir dir)
: AudioDevice(port, dev_type, device, dir)
, mBuffering(50)
, mPaused(true)
, mQuit(false)
, mPMainLoop(nullptr)
, mPContext(nullptr)
, mStream(nullptr)
, mServer(nullptr)
, mPAready(0)
, mResampleRatio(1.0)
, mTimeAdjust(1.0)
, mSamplesPerSec(48000)
, mResampler(nullptr)
, mOutSamples(0)
{
int i = dir == AUDIODIR_SOURCE ? 0 : 2;
const char* var_names[] = {
N_AUDIO_SOURCE0,
N_AUDIO_SOURCE1,
N_AUDIO_SINK0,
N_AUDIO_SINK1};
if (!LoadSetting(mDevType, mPort, APINAME, (device ? var_names[i + 1] : var_names[i]), mDeviceName) || mDeviceName.empty())
throw AudioDeviceError(APINAME_ ": failed to load device settings");
LoadSetting(mDevType, mPort, APINAME, (dir == AUDIODIR_SOURCE ? N_BUFFER_LEN_SRC : N_BUFFER_LEN_SINK), mBuffering);
mBuffering = MIN(1000, MAX(1, mBuffering));
if (!AudioInit())
throw AudioDeviceError(APINAME_ ": failed to bind pulseaudio library");
mSSpec.format = PA_SAMPLE_FLOAT32LE; //PA_SAMPLE_S16LE;
mSSpec.channels = 2;
mSSpec.rate = 48000;
if (!Init())
throw AudioDeviceError(APINAME_ ": failed to init");
}
~PulseAudioDevice()
{
mQuit = true;
std::lock_guard<std::mutex> lock(mMutex);
Uninit();
AudioDeinit();
mResampler = src_delete(mResampler);
if (file)
fclose(file);
}
uint32_t GetBuffer(short* buff, uint32_t frames);
uint32_t SetBuffer(short* buff, uint32_t frames);
bool GetFrames(uint32_t* size);
void SetResampling(int samplerate);
void Start();
void Stop();
virtual bool Compare(AudioDevice* compare);
void Uninit();
bool Init();
void ResetBuffers();
inline uint32_t GetChannels()
{
return mSSpec.channels;
}
static const char* TypeName()
{
return APINAME;
}
static const TCHAR* Name()
{
return "PulseAudio";
}
static int Configure(int port, const char* dev_type, void* data);
static void AudioDevices(std::vector<AudioDeviceInfo>& devices, AudioDir& dir);
static bool AudioInit();
static void AudioDeinit();
static void context_state_cb(pa_context* c, void* userdata);
static void stream_state_cb(pa_stream* s, void* userdata);
static void stream_read_cb(pa_stream* p, size_t nbytes, void* userdata);
static void stream_write_cb(pa_stream* p, size_t nbytes, void* userdata);
static void stream_success_cb(pa_stream* p, int success, void* userdata) {}
protected:
int mChannels;
int mBuffering;
std::string mDeviceName;
int mSamplesPerSec;
pa_sample_spec mSSpec;
SRC_STATE* mResampler;
double mResampleRatio;
// Speed up or slow down audio
double mTimeAdjust;
RingBuffer mOutBuffer;
RingBuffer mInBuffer;
//std::thread mThread;
//std::condition_variable mEvent;
std::mutex mMutex;
bool mQuit;
bool mPaused;
hrc::time_point mLastGetBuffer;
int mPAready;
pa_threaded_mainloop* mPMainLoop;
pa_context* mPContext;
pa_stream* mStream;
char* mServer; //TODO add server selector?
int mOutSamples;
hrc::time_point mLastOut;
FILE* file = nullptr;
};
if (!LoadSetting(mDevType, mPort, APINAME, (device ? var_names[i + 1] : var_names[i]), mDeviceName) || mDeviceName.empty())
throw AudioDeviceError(APINAME_ ": failed to load device settings");
LoadSetting(mDevType, mPort, APINAME, (dir == AUDIODIR_SOURCE ? N_BUFFER_LEN_SRC : N_BUFFER_LEN_SINK), mBuffering);
mBuffering = MIN(1000, MAX(1, mBuffering));
if (!AudioInit())
throw AudioDeviceError(APINAME_ ": failed to bind pulseaudio library");
mSSpec.format = PA_SAMPLE_FLOAT32LE; //PA_SAMPLE_S16LE;
mSSpec.channels = 2;
mSSpec.rate = 48000;
if (!Init())
throw AudioDeviceError(APINAME_ ": failed to init");
}
~PulseAudioDevice()
{
mQuit = true;
std::lock_guard<std::mutex> lock(mMutex);
Uninit();
AudioDeinit();
mResampler = src_delete(mResampler);
if (file) fclose(file);
}
uint32_t GetBuffer(short *buff, uint32_t frames);
uint32_t SetBuffer(short *buff, uint32_t frames);
bool GetFrames(uint32_t *size);
void SetResampling(int samplerate);
void Start();
void Stop();
virtual bool Compare(AudioDevice* compare);
void Uninit();
bool Init();
void ResetBuffers();
inline uint32_t GetChannels()
{
return mSSpec.channels;
}
static const char* TypeName()
{
return APINAME;
}
static const TCHAR* Name()
{
return "PulseAudio";
}
static int Configure(int port, const char* dev_type, void *data);
static void AudioDevices(std::vector<AudioDeviceInfo> &devices, AudioDir& dir);
static bool AudioInit();
static void AudioDeinit();
static void context_state_cb(pa_context *c, void *userdata);
static void stream_state_cb(pa_stream *s, void *userdata);
static void stream_read_cb (pa_stream *p, size_t nbytes, void *userdata);
static void stream_write_cb (pa_stream *p, size_t nbytes, void *userdata);
static void stream_success_cb (pa_stream *p, int success, void *userdata) {}
protected:
int mChannels;
int mBuffering;
std::string mDeviceName;
int mSamplesPerSec;
pa_sample_spec mSSpec;
SRC_STATE *mResampler;
double mResampleRatio;
// Speed up or slow down audio
double mTimeAdjust;
RingBuffer mOutBuffer;
RingBuffer mInBuffer;
//std::thread mThread;
//std::condition_variable mEvent;
std::mutex mMutex;
bool mQuit;
bool mPaused;
hrc::time_point mLastGetBuffer;
int mPAready;
pa_threaded_mainloop *mPMainLoop;
pa_context *mPContext;
pa_stream *mStream;
char *mServer; //TODO add server selector?
int mOutSamples;
hrc::time_point mLastOut;
FILE* file = nullptr;
};
}}
} // namespace audiodev_pulse
} // namespace usb_mic

File diff suppressed because it is too large Load Diff

View File

@ -22,135 +22,140 @@
#include <mmdeviceapi.h>
#include <audioclient.h>
namespace usb_mic { namespace audiodev_wasapi {
static const char *APINAME = "wasapi";
class MMAudioDevice : public AudioDevice
namespace usb_mic
{
public:
MMAudioDevice(int port, const char* dev_type, int device, AudioDir dir): AudioDevice(port, dev_type, device, dir)
, mmCapture(NULL)
, mmRender(NULL)
, mmClient(NULL)
, mmDevice(NULL)
, mmClock(NULL)
, mmEnumerator(NULL)
, mResampler(NULL)
, mDeviceLost(false)
, mResample(false)
, mFirstSamples(true)
, mSamplesPerSec(48000)
, mResampleRatio(1.0)
, mTimeAdjust(1.0)
, mThread(INVALID_HANDLE_VALUE)
, mQuit(false)
, mPaused(true)
, mLastGetBufferMS(0)
, mBuffering(50)
namespace audiodev_wasapi
{
mMutex = CreateMutex(NULL, FALSE, TEXT("ResampledQueueMutex"));
if(!Init())
throw AudioDeviceError("MMAudioDevice:: device name is empty, skipping");
if(!Reinitialize())
throw AudioDeviceError("MMAudioDevice:: WASAPI init failed!");
}
~MMAudioDevice();
void FreeData();
bool Init();
bool Reinitialize();
void Start();
void Stop();
void ResetBuffers();
//TODO or just return samples count in mOutBuffer?
virtual bool GetFrames(uint32_t *size);
static const char* APINAME = "wasapi";
static unsigned WINAPI CaptureThread(LPVOID ptr);
static unsigned WINAPI RenderThread(LPVOID ptr);
class MMAudioDevice : public AudioDevice
{
public:
MMAudioDevice(int port, const char* dev_type, int device, AudioDir dir)
: AudioDevice(port, dev_type, device, dir)
, mmCapture(NULL)
, mmRender(NULL)
, mmClient(NULL)
, mmDevice(NULL)
, mmClock(NULL)
, mmEnumerator(NULL)
, mResampler(NULL)
, mDeviceLost(false)
, mResample(false)
, mFirstSamples(true)
, mSamplesPerSec(48000)
, mResampleRatio(1.0)
, mTimeAdjust(1.0)
, mThread(INVALID_HANDLE_VALUE)
, mQuit(false)
, mPaused(true)
, mLastGetBufferMS(0)
, mBuffering(50)
{
mMutex = CreateMutex(NULL, FALSE, TEXT("ResampledQueueMutex"));
if (!Init())
throw AudioDeviceError("MMAudioDevice:: device name is empty, skipping");
if (!Reinitialize())
throw AudioDeviceError("MMAudioDevice:: WASAPI init failed!");
}
virtual uint32_t GetBuffer(int16_t *outBuf, uint32_t outFrames);
virtual uint32_t SetBuffer(int16_t *inBuf, uint32_t inFrames);
/*
~MMAudioDevice();
void FreeData();
bool Init();
bool Reinitialize();
void Start();
void Stop();
void ResetBuffers();
//TODO or just return samples count in mOutBuffer?
virtual bool GetFrames(uint32_t* size);
static unsigned WINAPI CaptureThread(LPVOID ptr);
static unsigned WINAPI RenderThread(LPVOID ptr);
virtual uint32_t GetBuffer(int16_t* outBuf, uint32_t outFrames);
virtual uint32_t SetBuffer(int16_t* inBuf, uint32_t inFrames);
/*
Returns read frame count.
*/
uint32_t GetMMBuffer();
virtual void SetResampling(int samplerate);
virtual uint32_t GetChannels()
{
return mDeviceChannels;
}
uint32_t GetMMBuffer();
virtual void SetResampling(int samplerate);
virtual uint32_t GetChannels()
{
return mDeviceChannels;
}
virtual bool Compare(AudioDevice* compare)
{
if (compare)
{
MMAudioDevice *src = static_cast<MMAudioDevice *>(compare);
if (src && mDevID == src->mDevID)
return true;
}
return false;
}
virtual bool Compare(AudioDevice* compare)
{
if (compare)
{
MMAudioDevice* src = static_cast<MMAudioDevice*>(compare);
if (src && mDevID == src->mDevID)
return true;
}
return false;
}
static const char* TypeName()
{
return APINAME;
}
static const char* TypeName()
{
return APINAME;
}
static const TCHAR* Name()
{
return TEXT("WASAPI");
}
static const TCHAR* Name()
{
return TEXT("WASAPI");
}
static bool AudioInit();
static bool AudioInit();
static void AudioDeinit()
{
}
static void AudioDeinit()
{
}
static void AudioDevices(std::vector<AudioDeviceInfo> &devices, AudioDir dir);
static int Configure(int port, const char* dev_type, void *data);
static void AudioDevices(std::vector<AudioDeviceInfo>& devices, AudioDir dir);
static int Configure(int port, const char* dev_type, void* data);
private:
IMMDeviceEnumerator *mmEnumerator;
private:
IMMDeviceEnumerator* mmEnumerator;
IMMDevice *mmDevice;
IAudioClient *mmClient;
IAudioCaptureClient *mmCapture;
IAudioRenderClient *mmRender;
IAudioClock *mmClock;
IMMDevice* mmDevice;
IAudioClient* mmClient;
IAudioCaptureClient* mmCapture;
IAudioRenderClient* mmRender;
IAudioClock* mmClock;
bool mResample;
bool mFloat;
bool mFirstSamples; //On the first call, empty the buffer to lower latency
UINT mDeviceChannels;
UINT mDeviceSamplesPerSec;
UINT mSamplesPerSec;
UINT mDeviceBitsPerSample;
UINT mDeviceBlockSize;
DWORD mInputChannelMask;
bool mResample;
bool mFloat;
bool mFirstSamples; //On the first call, empty the buffer to lower latency
UINT mDeviceChannels;
UINT mDeviceSamplesPerSec;
UINT mSamplesPerSec;
UINT mDeviceBitsPerSample;
UINT mDeviceBlockSize;
DWORD mInputChannelMask;
std::wstring mDevID;
bool mDeviceLost;
std::wstring mDeviceName;
LONGLONG mBuffering;
std::wstring mDevID;
bool mDeviceLost;
std::wstring mDeviceName;
LONGLONG mBuffering;
SRC_STATE *mResampler;
double mResampleRatio;
// Speed up or slow down audio
double mTimeAdjust;
RingBuffer mInBuffer;
RingBuffer mOutBuffer;
HANDLE mThread;
HANDLE mMutex;
bool mQuit;
bool mPaused;
LONGLONG mLastGetBufferMS;
SRC_STATE* mResampler;
double mResampleRatio;
// Speed up or slow down audio
double mTimeAdjust;
RingBuffer mInBuffer;
RingBuffer mOutBuffer;
HANDLE mThread;
HANDLE mMutex;
bool mQuit;
bool mPaused;
LONGLONG mLastGetBufferMS;
LONGLONG mTime = 0;
int mSamples = 0;
LONGLONG mLastTimeMS = 0;
LONGLONG mLastTimeNS = 0;
};
LONGLONG mTime = 0;
int mSamples = 0;
LONGLONG mLastTimeMS = 0;
LONGLONG mLastTimeNS = 0;
};
}} // namespace
} // namespace audiodev_wasapi
} // namespace usb_mic

View File

@ -24,29 +24,31 @@
#include <vector>
#include <queue>
#define S_AUDIO_SOURCE0 TEXT("Audio source 1")
#define S_AUDIO_SOURCE1 TEXT("Audio source 2")
#define S_AUDIO_SINK0 TEXT("Audio sink 1")
#define S_AUDIO_SINK1 TEXT("Audio sink 2")
#define N_AUDIO_SOURCE0 TEXT("audio_src_0")
#define N_AUDIO_SOURCE1 TEXT("audio_src_1")
#define N_AUDIO_SINK0 TEXT("audio_sink_0")
#define N_AUDIO_SINK1 TEXT("audio_sink_1")
#define S_BUFFER_LEN TEXT("Buffer length")
#define N_BUFFER_LEN TEXT("buffer_len")
#define N_BUFFER_LEN_SRC TEXT("buffer_len_src")
#define N_BUFFER_LEN_SINK TEXT("buffer_len_sink")
#define S_AUDIO_SOURCE0 TEXT("Audio source 1")
#define S_AUDIO_SOURCE1 TEXT("Audio source 2")
#define S_AUDIO_SINK0 TEXT("Audio sink 1")
#define S_AUDIO_SINK1 TEXT("Audio sink 2")
#define N_AUDIO_SOURCE0 TEXT("audio_src_0")
#define N_AUDIO_SOURCE1 TEXT("audio_src_1")
#define N_AUDIO_SINK0 TEXT("audio_sink_0")
#define N_AUDIO_SINK1 TEXT("audio_sink_1")
#define S_BUFFER_LEN TEXT("Buffer length")
#define N_BUFFER_LEN TEXT("buffer_len")
#define N_BUFFER_LEN_SRC TEXT("buffer_len_src")
#define N_BUFFER_LEN_SINK TEXT("buffer_len_sink")
enum MicMode {
enum MicMode
{
MIC_MODE_NONE,
MIC_MODE_SINGLE,
MIC_MODE_SEPARATE,
// Use same source for both player or
// left channel for P1 and right for P2 if stereo.
// Use same source for both player or
// left channel for P1 and right for P2 if stereo.
MIC_MODE_SHARED
};
enum AudioDir {
enum AudioDir
{
AUDIODIR_SOURCE = 0,
AUDIODIR_SINK
};
@ -75,28 +77,30 @@ struct AudioDeviceInfoW
class AudioDevice
{
public:
AudioDevice(int port, const char* dev_type, int device, AudioDir dir): mPort(port)
, mDevType(dev_type)
, mDevice(device)
, mAudioDir(dir)
AudioDevice(int port, const char* dev_type, int device, AudioDir dir)
: mPort(port)
, mDevType(dev_type)
, mDevice(device)
, mAudioDir(dir)
{
}
protected:
int mPort;
const char *mDevType;
const char* mDevType;
int mDevice;
AudioDir mAudioDir;
public:
virtual ~AudioDevice() {}
//get buffer, converted to 16bit int format
virtual uint32_t GetBuffer(int16_t *buff, uint32_t len) = 0;
virtual uint32_t SetBuffer(int16_t *buff, uint32_t len) = 0;
virtual uint32_t GetBuffer(int16_t* buff, uint32_t len) = 0;
virtual uint32_t SetBuffer(int16_t* buff, uint32_t len) = 0;
/*
Get how many frames has been recorded so that caller knows
how much to allocated for 16-bit buffer.
*/
virtual bool GetFrames(uint32_t *size) = 0;
virtual bool GetFrames(uint32_t* size) = 0;
virtual void SetResampling(int samplerate) = 0;
virtual uint32_t GetChannels() = 0;

View File

@ -27,78 +27,85 @@
#include "../osdebugout.h"
#include "audiodev.h"
namespace usb_mic {
class AudioDeviceError : public std::runtime_error
namespace usb_mic
{
public:
AudioDeviceError(const char* msg) : std::runtime_error(msg) {}
virtual ~AudioDeviceError() throw () {}
};
class AudioDeviceProxyBase : public ProxyBase
{
AudioDeviceProxyBase(const AudioDeviceProxyBase&) = delete;
AudioDeviceProxyBase& operator=(const AudioDeviceProxyBase&) = delete;
public:
AudioDeviceProxyBase() {};
AudioDeviceProxyBase(const std::string& name);
virtual AudioDevice* CreateObject(int port, const char* dev_type, int mic, AudioDir dir) const = 0; //Can be generalized? Probably not
virtual void AudioDevices(std::vector<AudioDeviceInfo> &devices, AudioDir) const = 0;
virtual bool AudioInit() = 0;
virtual void AudioDeinit() = 0;
};
template <class T>
class AudioDeviceProxy : public AudioDeviceProxyBase
{
AudioDeviceProxy(const AudioDeviceProxy&) = delete;
public:
AudioDeviceProxy() {}
AudioDeviceProxy(const std::string& name): AudioDeviceProxyBase(name) {} //Why can't it automagically, ugh
~AudioDeviceProxy() { OSDebugOut(TEXT("%p\n"), this); }
AudioDevice* CreateObject(int port, const char* dev_type, int mic, AudioDir dir) const
class AudioDeviceError : public std::runtime_error
{
try
public:
AudioDeviceError(const char* msg)
: std::runtime_error(msg)
{
return new T(port, dev_type, mic, dir);
}
catch(AudioDeviceError& err)
{
OSDebugOut(TEXT("AudioDevice port %d mic %d: %") TEXT(SFMTs) TEXT("\n"), port, mic, err.what());
(void)err;
return nullptr;
}
}
virtual const TCHAR* Name() const
{
return T::Name();
}
virtual int Configure(int port, const char* dev_type, void *data)
{
return T::Configure(port, dev_type, data);
}
virtual void AudioDevices(std::vector<AudioDeviceInfo> &devices, AudioDir dir) const
{
T::AudioDevices(devices, dir);
}
virtual bool AudioInit()
{
return T::AudioInit();
}
virtual void AudioDeinit()
{
T::AudioDeinit();
}
};
virtual ~AudioDeviceError() throw() {}
};
class AudioDeviceProxyBase : public ProxyBase
{
AudioDeviceProxyBase(const AudioDeviceProxyBase&) = delete;
AudioDeviceProxyBase& operator=(const AudioDeviceProxyBase&) = delete;
class RegisterAudioDevice : public RegisterProxy<AudioDeviceProxyBase>
{
public:
static void Register();
};
}
AudioDeviceProxyBase(){};
AudioDeviceProxyBase(const std::string& name);
virtual AudioDevice* CreateObject(int port, const char* dev_type, int mic, AudioDir dir) const = 0; //Can be generalized? Probably not
virtual void AudioDevices(std::vector<AudioDeviceInfo>& devices, AudioDir) const = 0;
virtual bool AudioInit() = 0;
virtual void AudioDeinit() = 0;
};
template <class T>
class AudioDeviceProxy : public AudioDeviceProxyBase
{
AudioDeviceProxy(const AudioDeviceProxy&) = delete;
public:
AudioDeviceProxy() {}
AudioDeviceProxy(const std::string& name)
: AudioDeviceProxyBase(name)
{
} //Why can't it automagically, ugh
~AudioDeviceProxy() { OSDebugOut(TEXT("%p\n"), this); }
AudioDevice* CreateObject(int port, const char* dev_type, int mic, AudioDir dir) const
{
try
{
return new T(port, dev_type, mic, dir);
}
catch (AudioDeviceError& err)
{
OSDebugOut(TEXT("AudioDevice port %d mic %d: %") TEXT(SFMTs) TEXT("\n"), port, mic, err.what());
(void)err;
return nullptr;
}
}
virtual const TCHAR* Name() const
{
return T::Name();
}
virtual int Configure(int port, const char* dev_type, void* data)
{
return T::Configure(port, dev_type, data);
}
virtual void AudioDevices(std::vector<AudioDeviceInfo>& devices, AudioDir dir) const
{
T::AudioDevices(devices, dir);
}
virtual bool AudioInit()
{
return T::AudioInit();
}
virtual void AudioDeinit()
{
T::AudioDeinit();
}
};
class RegisterAudioDevice : public RegisterProxy<AudioDeviceProxyBase>
{
public:
static void Register();
};
} // namespace usb_mic
#endif

File diff suppressed because it is too large Load Diff

View File

@ -16,26 +16,27 @@
#include "../deviceproxy.h"
#include "audiodeviceproxy.h"
namespace usb_mic {
class HeadsetDevice
namespace usb_mic
{
public:
virtual ~HeadsetDevice() {}
static USBDevice* CreateDevice(int port);
static USBDevice* CreateDevice(int port, const std::string& api);
static const char* TypeName()
{
return "headset";
}
static const TCHAR* Name()
{
return TEXT("Logitech USB Headset");
}
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);
};
}
class HeadsetDevice
{
public:
virtual ~HeadsetDevice() {}
static USBDevice* CreateDevice(int port);
static USBDevice* CreateDevice(int port, const std::string& api);
static const char* TypeName()
{
return "headset";
}
static const TCHAR* Name()
{
return TEXT("Logitech USB Headset");
}
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_mic

View File

@ -17,257 +17,256 @@
#include "audio.h"
#include "../qemu-usb/desc.h"
namespace usb_mic {
static const uint8_t logitech_mic_dev_descriptor[] = {
/* bLength */ 0x12, //(18)
/* bDescriptorType */ 0x01, //(1)
/* bcdUSB */ WBVAL(0x0110), //(272)
/* bDeviceClass */ 0x00, //(0)
/* bDeviceSubClass */ 0x00, //(0)
/* bDeviceProtocol */ 0x00, //(0)
/* bMaxPacketSize0 */ 0x08, //(8)
/* idVendor */ WBVAL(0x046D),
/* idProduct */ WBVAL(0x0000), //(0)
/* bcdDevice */ WBVAL(0x0001), //(1)
/* iManufacturer */ 0x01, //(1)
/* iProduct */ 0x02, //(2)
/* iSerialNumber */ 0x00, //(0) unused
/* bNumConfigurations */ 0x01, //(1)
};
static const uint8_t logitech_mic_config_descriptor[] = {
/* Configuration 1 */
0x09, /* bLength */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x00b1), /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
USB_CONFIG_BUS_POWERED, /* bmAttributes */
USB_CONFIG_POWER_MA(90), /* bMaxPower */
/* Interface 0, Alternate Setting 0, Audio Control */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio Control Interface */
AUDIO_CONTROL_INTERFACE_DESC_SZ(1), /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */
WBVAL(0x0100), /* 1.00 */ /* bcdADC */
WBVAL(0x0028), /* wTotalLength */
0x01, /* bInCollection */
0x01, /* baInterfaceNr */
/* Audio Input Terminal */
AUDIO_INPUT_TERMINAL_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */
0x01, /* bTerminalID */
WBVAL(AUDIO_TERMINAL_MICROPHONE), /* wTerminalType */
0x02, /* bAssocTerminal */
0x02, /* bNrChannels */
WBVAL(AUDIO_CHANNEL_L
| AUDIO_CHANNEL_R), /* wChannelConfig */
0x00, /* iChannelNames */
0x00, /* iTerminal */
/* Audio Output Terminal */
AUDIO_OUTPUT_TERMINAL_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */
0x02, /* bTerminalID */
WBVAL(AUDIO_TERMINAL_USB_STREAMING), /* wTerminalType */
0x01, /* bAssocTerminal */
0x03, /* bSourceID */
0x00, /* iTerminal */
/* Audio Feature Unit */
AUDIO_FEATURE_UNIT_DESC_SZ(2,1), /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */
0x03, /* bUnitID */
0x01, /* bSourceID */
0x01, /* bControlSize */
0x01, /* bmaControls(0) */
0x02, /* bmaControls(1) */
0x02, /* bmaControls(2) */
0x00, /* iTerminal */
/* Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Interface 1, Alternate Setting 1, Audio Streaming - Operational */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x01, /* bNumEndpoints */
USB_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio Streaming Interface */
AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */
0x02, /* bTerminalLink */
0x01, /* bDelay */
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag */
/* Audio Type I Format */
AUDIO_FORMAT_TYPE_I_DESC_SZ(5), /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */
AUDIO_FORMAT_TYPE_I, /* bFormatType */
0x01, /* bNrChannels */
0x02, /* bSubFrameSize */
0x10, /* bBitResolution */
0x05, /* bSamFreqType */
B3VAL(8000), /* tSamFreq 1 */
B3VAL(11025), /* tSamFreq 2 */
B3VAL(22050), /* tSamFreq 3 */
B3VAL(44100), /* tSamFreq 4 */
B3VAL(48000), /* tSamFreq 5 */
/* Endpoint - Standard Descriptor */
AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_ENDPOINT_IN(1), /* bEndpointAddress */
USB_ENDPOINT_TYPE_ISOCHRONOUS
| USB_ENDPOINT_SYNC_ASYNCHRONOUS, /* bmAttributes */
WBVAL(0x0064), /* wMaxPacketSize */
0x01, /* bInterval */
0x00, /* bRefresh */
0x00, /* bSynchAddress */
/* Endpoint - Audio Streaming */
AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */
0x01, /* bmAttributes */
0x00, /* bLockDelayUnits */
WBVAL(0x0000), /* wLockDelay */
/* Interface 1, Alternate Setting 2, Audio Streaming - ? */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x02, /* bAlternateSetting */
0x01, /* bNumEndpoints */
USB_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio Streaming Interface */
AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */
0x02, /* bTerminalLink */
0x01, /* bDelay */
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag */
/* Audio Type I Format */
AUDIO_FORMAT_TYPE_I_DESC_SZ(5), /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */
AUDIO_FORMAT_TYPE_I, /* bFormatType */
0x02, /* bNrChannels */
0x02, /* bSubFrameSize */
0x10, /* bBitResolution */
0x05, /* bSamFreqType */
B3VAL(8000), /* tSamFreq 1 */
B3VAL(11025), /* tSamFreq 2 */
B3VAL(22050), /* tSamFreq 3 */
B3VAL(44100), /* tSamFreq 4 */
B3VAL(48000), /* tSamFreq 5 */
/* Endpoint - Standard Descriptor */
AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_ENDPOINT_IN(1), /* bEndpointAddress */
USB_ENDPOINT_TYPE_ISOCHRONOUS
| USB_ENDPOINT_SYNC_ASYNCHRONOUS, /* bmAttributes */
WBVAL(0x00c8), /* wMaxPacketSize */
0x01, /* bInterval */
0x00, /* bRefresh */
0x00, /* bSynchAddress */
/* Endpoint - Audio Streaming */
AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */
0x01, /* bmAttributes */
0x00, /* bLockDelayUnits */
WBVAL(0x0000), /* wLockDelay */
/* Terminator */
0 /* bLength */
};
static const USBDescStrings lt_desc_strings = {
"",
"Logitech",
"USBMIC",
};
//Minified state
typedef struct SINGSTARMICMINIState {
USBDevice dev;
USBDesc desc;
USBDescDevice desc_dev;
} SINGSTARMICMINIState;
USBDevice* LogitechMicDevice::CreateDevice(int port)
namespace usb_mic
{
std::string api;
if (!LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, api))
static const uint8_t logitech_mic_dev_descriptor[] = {
/* bLength */ 0x12, //(18)
/* bDescriptorType */ 0x01, //(1)
/* bcdUSB */ WBVAL(0x0110), //(272)
/* bDeviceClass */ 0x00, //(0)
/* bDeviceSubClass */ 0x00, //(0)
/* bDeviceProtocol */ 0x00, //(0)
/* bMaxPacketSize0 */ 0x08, //(8)
/* idVendor */ WBVAL(0x046D),
/* idProduct */ WBVAL(0x0000), //(0)
/* bcdDevice */ WBVAL(0x0001), //(1)
/* iManufacturer */ 0x01, //(1)
/* iProduct */ 0x02, //(2)
/* iSerialNumber */ 0x00, //(0) unused
/* bNumConfigurations */ 0x01, //(1)
};
static const uint8_t logitech_mic_config_descriptor[] = {
/* Configuration 1 */
0x09, /* bLength */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x00b1), /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
USB_CONFIG_BUS_POWERED, /* bmAttributes */
USB_CONFIG_POWER_MA(90), /* bMaxPower */
/* Interface 0, Alternate Setting 0, Audio Control */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio Control Interface */
AUDIO_CONTROL_INTERFACE_DESC_SZ(1), /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */
WBVAL(0x0100), /* 1.00 */ /* bcdADC */
WBVAL(0x0028), /* wTotalLength */
0x01, /* bInCollection */
0x01, /* baInterfaceNr */
/* Audio Input Terminal */
AUDIO_INPUT_TERMINAL_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */
0x01, /* bTerminalID */
WBVAL(AUDIO_TERMINAL_MICROPHONE), /* wTerminalType */
0x02, /* bAssocTerminal */
0x02, /* bNrChannels */
WBVAL(AUDIO_CHANNEL_L | AUDIO_CHANNEL_R), /* wChannelConfig */
0x00, /* iChannelNames */
0x00, /* iTerminal */
/* Audio Output Terminal */
AUDIO_OUTPUT_TERMINAL_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */
0x02, /* bTerminalID */
WBVAL(AUDIO_TERMINAL_USB_STREAMING), /* wTerminalType */
0x01, /* bAssocTerminal */
0x03, /* bSourceID */
0x00, /* iTerminal */
/* Audio Feature Unit */
AUDIO_FEATURE_UNIT_DESC_SZ(2, 1), /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */
0x03, /* bUnitID */
0x01, /* bSourceID */
0x01, /* bControlSize */
0x01, /* bmaControls(0) */
0x02, /* bmaControls(1) */
0x02, /* bmaControls(2) */
0x00, /* iTerminal */
/* Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
USB_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Interface 1, Alternate Setting 1, Audio Streaming - Operational */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x01, /* bNumEndpoints */
USB_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio Streaming Interface */
AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */
0x02, /* bTerminalLink */
0x01, /* bDelay */
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag */
/* Audio Type I Format */
AUDIO_FORMAT_TYPE_I_DESC_SZ(5), /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */
AUDIO_FORMAT_TYPE_I, /* bFormatType */
0x01, /* bNrChannels */
0x02, /* bSubFrameSize */
0x10, /* bBitResolution */
0x05, /* bSamFreqType */
B3VAL(8000), /* tSamFreq 1 */
B3VAL(11025), /* tSamFreq 2 */
B3VAL(22050), /* tSamFreq 3 */
B3VAL(44100), /* tSamFreq 4 */
B3VAL(48000), /* tSamFreq 5 */
/* Endpoint - Standard Descriptor */
AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_ENDPOINT_IN(1), /* bEndpointAddress */
USB_ENDPOINT_TYPE_ISOCHRONOUS | USB_ENDPOINT_SYNC_ASYNCHRONOUS, /* bmAttributes */
WBVAL(0x0064), /* wMaxPacketSize */
0x01, /* bInterval */
0x00, /* bRefresh */
0x00, /* bSynchAddress */
/* Endpoint - Audio Streaming */
AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */
0x01, /* bmAttributes */
0x00, /* bLockDelayUnits */
WBVAL(0x0000), /* wLockDelay */
/* Interface 1, Alternate Setting 2, Audio Streaming - ? */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x02, /* bAlternateSetting */
0x01, /* bNumEndpoints */
USB_CLASS_AUDIO, /* bInterfaceClass */
AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */
AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Audio Streaming Interface */
AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */
0x02, /* bTerminalLink */
0x01, /* bDelay */
WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag */
/* Audio Type I Format */
AUDIO_FORMAT_TYPE_I_DESC_SZ(5), /* bLength */
AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */
AUDIO_FORMAT_TYPE_I, /* bFormatType */
0x02, /* bNrChannels */
0x02, /* bSubFrameSize */
0x10, /* bBitResolution */
0x05, /* bSamFreqType */
B3VAL(8000), /* tSamFreq 1 */
B3VAL(11025), /* tSamFreq 2 */
B3VAL(22050), /* tSamFreq 3 */
B3VAL(44100), /* tSamFreq 4 */
B3VAL(48000), /* tSamFreq 5 */
/* Endpoint - Standard Descriptor */
AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_ENDPOINT_IN(1), /* bEndpointAddress */
USB_ENDPOINT_TYPE_ISOCHRONOUS | USB_ENDPOINT_SYNC_ASYNCHRONOUS, /* bmAttributes */
WBVAL(0x00c8), /* wMaxPacketSize */
0x01, /* bInterval */
0x00, /* bRefresh */
0x00, /* bSynchAddress */
/* Endpoint - Audio Streaming */
AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */
AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
AUDIO_ENDPOINT_GENERAL, /* bDescriptor */
0x01, /* bmAttributes */
0x00, /* bLockDelayUnits */
WBVAL(0x0000), /* wLockDelay */
/* Terminator */
0 /* bLength */
};
static const USBDescStrings lt_desc_strings = {
"",
"Logitech",
"USBMIC",
};
//Minified state
typedef struct SINGSTARMICMINIState
{
USBDevice dev;
USBDesc desc;
USBDescDevice desc_dev;
} SINGSTARMICMINIState;
USBDevice* LogitechMicDevice::CreateDevice(int port)
{
std::string api;
if (!LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, api))
return nullptr;
USBDevice* dev = SingstarDevice::CreateDevice(port, api);
if (!dev)
return nullptr;
SINGSTARMICMINIState* s = (SINGSTARMICMINIState*)dev;
s->desc = {};
s->desc_dev = {};
s->desc.str = lt_desc_strings;
s->desc.full = &s->desc_dev;
if (usb_desc_parse_dev(logitech_mic_dev_descriptor, sizeof(logitech_mic_dev_descriptor), s->desc, s->desc_dev) < 0)
goto fail;
if (usb_desc_parse_config(logitech_mic_config_descriptor, sizeof(logitech_mic_config_descriptor), s->desc_dev) < 0)
goto fail;
s->dev.klass.usb_desc = &s->desc;
s->dev.klass.product_desc = lt_desc_strings[2];
usb_desc_init(&s->dev);
return dev;
fail:
s->dev.klass.unrealize(dev);
return nullptr;
}
USBDevice* dev = SingstarDevice::CreateDevice(port, api);
if (!dev)
return nullptr;
SINGSTARMICMINIState *s = (SINGSTARMICMINIState *)dev;
s->desc = {};
s->desc_dev = {};
s->desc.str = lt_desc_strings;
s->desc.full = &s->desc_dev;
if (usb_desc_parse_dev (logitech_mic_dev_descriptor, sizeof(logitech_mic_dev_descriptor), s->desc, s->desc_dev) < 0)
goto fail;
if (usb_desc_parse_config (logitech_mic_config_descriptor, sizeof(logitech_mic_config_descriptor), s->desc_dev) < 0)
goto fail;
s->dev.klass.usb_desc = &s->desc;
s->dev.klass.product_desc = lt_desc_strings[2];
usb_desc_init(&s->dev);
return dev;
fail:
s->dev.klass.unrealize (dev);
return nullptr;
}
}
} // namespace usb_mic

File diff suppressed because it is too large Load Diff

View File

@ -20,50 +20,51 @@
struct USBDevice;
namespace usb_mic {
class SingstarDevice
namespace usb_mic
{
public:
virtual ~SingstarDevice() {}
static USBDevice* CreateDevice(int port);
static USBDevice* CreateDevice(int port, const std::string& api);
static const TCHAR* Name()
class SingstarDevice
{
return TEXT("Singstar");
}
static const char* TypeName()
{
return "singstar";
}
static std::list<std::string> ListAPIs()
{
return RegisterAudioDevice::instance().Names();
}
static const TCHAR* LongAPIName(const std::string& name)
{
auto proxy = RegisterAudioDevice::instance().Proxy(name);
if (proxy)
return proxy->Name();
return nullptr;
}
static int Configure(int port, const std::string& api, void *data);
static int Freeze(int mode, USBDevice *dev, void *data);
};
public:
virtual ~SingstarDevice() {}
static USBDevice* CreateDevice(int port);
static USBDevice* CreateDevice(int port, const std::string& api);
static const TCHAR* Name()
{
return TEXT("Singstar");
}
static const char* TypeName()
{
return "singstar";
}
static std::list<std::string> ListAPIs()
{
return RegisterAudioDevice::instance().Names();
}
static const TCHAR* LongAPIName(const std::string& name)
{
auto proxy = RegisterAudioDevice::instance().Proxy(name);
if (proxy)
return proxy->Name();
return nullptr;
}
static int Configure(int port, const std::string& api, void* data);
static int Freeze(int mode, USBDevice* dev, void* data);
};
class LogitechMicDevice : public SingstarDevice
{
public:
virtual ~LogitechMicDevice() {}
static USBDevice* CreateDevice(int port);
static const char* TypeName()
class LogitechMicDevice : public SingstarDevice
{
return "logitech_usbmic";
}
static const TCHAR* Name()
{
return TEXT("Logitech USB Mic");
}
};
public:
virtual ~LogitechMicDevice() {}
static USBDevice* CreateDevice(int port);
static const char* TypeName()
{
return "logitech_usbmic";
}
static const TCHAR* Name()
{
return TEXT("Logitech USB Mic");
}
};
}
} // namespace usb_mic
#endif

View File

@ -18,104 +18,105 @@
#include "../configuration.h"
#include "../gtk.h"
namespace usb_msd {
static void entryChanged(GtkWidget *widget, gpointer data)
namespace usb_msd
{
const gchar *text = gtk_entry_get_text(GTK_ENTRY(widget));
//fprintf(stderr, "Entry text:%s\n", text);
}
static void fileChooser( GtkWidget *widget, gpointer data)
{
GtkWidget *dialog, *entry = NULL;
entry = (GtkWidget*)data;
dialog = gtk_file_chooser_dialog_new ("Open File",
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
//XXX check access? Dialog seems to default to "Recently used" etc.
//Or set to empty string anyway? Then it seems to default to some sort of "working dir"
if (access (gtk_entry_get_text (GTK_ENTRY (entry)), F_OK) == 0)
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), gtk_entry_get_text (GTK_ENTRY (entry)));
if (entry && gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
static void entryChanged(GtkWidget* widget, gpointer data)
{
char *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
fprintf (stderr, "%s\n", filename);
gtk_entry_set_text(GTK_ENTRY(entry), filename);
g_free (filename);
const gchar* text = gtk_entry_get_text(GTK_ENTRY(widget));
//fprintf(stderr, "Entry text:%s\n", text);
}
gtk_widget_destroy (dialog);
}
int MsdDevice::Configure(int port, const std::string& api, void *data)
{
GtkWidget *ro_frame, *ro_label, *rs_hbox, *rs_label, *rs_cb, *vbox;
GtkWidget *dlg = gtk_dialog_new_with_buttons (
"Mass Storage Settings", GTK_WINDOW (data), GTK_DIALOG_MODAL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (dlg), TRUE);
GtkWidget *dlg_area_box = gtk_dialog_get_content_area (GTK_DIALOG (dlg));
ro_frame = gtk_frame_new (NULL);
gtk_box_pack_start (GTK_BOX (dlg_area_box), ro_frame, TRUE, FALSE, 5);
ro_label = gtk_label_new ("Select USB image:");
gtk_frame_set_label_widget (GTK_FRAME (ro_frame), ro_label);
gtk_label_set_use_markup (GTK_LABEL (ro_label), TRUE);
vbox = gtk_vbox_new (FALSE, 5);
gtk_container_add (GTK_CONTAINER (ro_frame), vbox);
rs_hbox = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), rs_hbox, FALSE, TRUE, 0);
GtkWidget *entry = gtk_entry_new ();
gtk_entry_set_max_length (GTK_ENTRY (entry), MAX_PATH); //TODO max length
std::string var;
if (LoadSetting(TypeName(), port, APINAME, N_CONFIG_PATH, var))
gtk_entry_set_text(GTK_ENTRY(entry), var.c_str());
g_signal_connect (entry, "changed", G_CALLBACK (entryChanged), NULL);
GtkWidget *button = gtk_button_new_with_label ("Browse");
gtk_button_set_image(GTK_BUTTON (button), gtk_image_new_from_icon_name ("gtk-open", GTK_ICON_SIZE_BUTTON));
g_signal_connect (button, "clicked", G_CALLBACK (fileChooser), entry);
gtk_box_pack_start (GTK_BOX (rs_hbox), entry, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (rs_hbox), button, FALSE, FALSE, 5);
gtk_widget_show_all (dlg);
gint result = gtk_dialog_run (GTK_DIALOG (dlg));
std::string path = gtk_entry_get_text(GTK_ENTRY(entry));
gtk_widget_destroy (dlg);
// Wait for all gtk events to be consumed ...
while (gtk_events_pending ())
gtk_main_iteration_do (FALSE);
if (result == GTK_RESPONSE_OK)
static void fileChooser(GtkWidget* widget, gpointer data)
{
if(SaveSetting(TypeName(), port, APINAME, N_CONFIG_PATH, path))
return RESULT_OK;
else
return RESULT_FAILED;
GtkWidget *dialog, *entry = NULL;
entry = (GtkWidget*)data;
dialog = gtk_file_chooser_dialog_new("Open File",
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
//XXX check access? Dialog seems to default to "Recently used" etc.
//Or set to empty string anyway? Then it seems to default to some sort of "working dir"
if (access(gtk_entry_get_text(GTK_ENTRY(entry)), F_OK) == 0)
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), gtk_entry_get_text(GTK_ENTRY(entry)));
if (entry && gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
{
char* filename;
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
fprintf(stderr, "%s\n", filename);
gtk_entry_set_text(GTK_ENTRY(entry), filename);
g_free(filename);
}
gtk_widget_destroy(dialog);
}
return RESULT_CANCELED;
}
int MsdDevice::Configure(int port, const std::string& api, void* data)
{
GtkWidget *ro_frame, *ro_label, *rs_hbox, *rs_label, *rs_cb, *vbox;
} //namespace
GtkWidget* dlg = gtk_dialog_new_with_buttons(
"Mass Storage Settings", GTK_WINDOW(data), GTK_DIALOG_MODAL,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
gtk_window_set_resizable(GTK_WINDOW(dlg), TRUE);
GtkWidget* dlg_area_box = gtk_dialog_get_content_area(GTK_DIALOG(dlg));
ro_frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(dlg_area_box), ro_frame, TRUE, FALSE, 5);
ro_label = gtk_label_new("Select USB image:");
gtk_frame_set_label_widget(GTK_FRAME(ro_frame), ro_label);
gtk_label_set_use_markup(GTK_LABEL(ro_label), TRUE);
vbox = gtk_vbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(ro_frame), vbox);
rs_hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), rs_hbox, FALSE, TRUE, 0);
GtkWidget* entry = gtk_entry_new();
gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_PATH); //TODO max length
std::string var;
if (LoadSetting(TypeName(), port, APINAME, N_CONFIG_PATH, var))
gtk_entry_set_text(GTK_ENTRY(entry), var.c_str());
g_signal_connect(entry, "changed", G_CALLBACK(entryChanged), NULL);
GtkWidget* button = gtk_button_new_with_label("Browse");
gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_icon_name("gtk-open", GTK_ICON_SIZE_BUTTON));
g_signal_connect(button, "clicked", G_CALLBACK(fileChooser), entry);
gtk_box_pack_start(GTK_BOX(rs_hbox), entry, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(rs_hbox), button, FALSE, FALSE, 5);
gtk_widget_show_all(dlg);
gint result = gtk_dialog_run(GTK_DIALOG(dlg));
std::string path = gtk_entry_get_text(GTK_ENTRY(entry));
gtk_widget_destroy(dlg);
// Wait for all gtk events to be consumed ...
while (gtk_events_pending())
gtk_main_iteration_do(FALSE);
if (result == GTK_RESPONSE_OK)
{
if (SaveSetting(TypeName(), port, APINAME, N_CONFIG_PATH, path))
return RESULT_OK;
else
return RESULT_FAILED;
}
return RESULT_CANCELED;
}
} // namespace usb_msd

View File

@ -17,78 +17,84 @@
#include "../Win32/Config.h"
#include "../Win32/resource.h"
namespace usb_msd {
static OPENFILENAMEW ofn;
BOOL CALLBACK MsdDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) {
int port;
static wchar_t buff[4096] = { 0 };
switch (uMsg) {
case WM_INITDIALOG:
{
memset(buff, 0, sizeof(buff));
port = (int)lParam;
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
std::wstring var;
if (LoadSetting(MsdDevice::TypeName(), port, APINAME, N_CONFIG_PATH, var))
wcsncpy_s(buff, sizeof(buff), var.c_str(), countof(buff));
SetWindowTextW(GetDlgItem(hW, IDC_EDIT1), buff);
return TRUE;
}
case WM_CREATE:
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED) {
switch (LOWORD(wParam)) {
case IDC_BUTTON1:
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hW;
ofn.lpstrTitle = L"USB image file";
ofn.lpstrFile = buff;
ofn.nMaxFile = countof(buff);
ofn.lpstrFilter = L"All\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetOpenFileName(&ofn)) {
SetWindowText(GetDlgItem(hW, IDC_EDIT1), ofn.lpstrFile);
}
break;
case IDOK:
{
INT_PTR res = RESULT_OK;
GetWindowTextW(GetDlgItem(hW, IDC_EDIT1), buff, countof(buff));
port = (int)GetWindowLongPtr(hW, GWLP_USERDATA);
if (!SaveSetting<std::wstring>(MsdDevice::TypeName(), port, APINAME, N_CONFIG_PATH, buff))
res = RESULT_FAILED;
//strcpy_s(conf.usb_img, ofn.lpstrFile);
EndDialog(hW, res);
return TRUE;
}
case IDCANCEL:
EndDialog(hW, FALSE);
return TRUE;
}
}
}
return FALSE;
}
int MsdDevice::Configure(int port, const std::string& api, void *data)
namespace usb_msd
{
Win32Handles handles = *(Win32Handles*)data;
return DialogBoxParam(handles.hInst,
MAKEINTRESOURCE(IDD_DLGMSD),
handles.hWnd,
(DLGPROC)MsdDlgProc, port);
}
}
static OPENFILENAMEW ofn;
BOOL CALLBACK MsdDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int port;
static wchar_t buff[4096] = {0};
switch (uMsg)
{
case WM_INITDIALOG:
{
memset(buff, 0, sizeof(buff));
port = (int)lParam;
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
std::wstring var;
if (LoadSetting(MsdDevice::TypeName(), port, APINAME, N_CONFIG_PATH, var))
wcsncpy_s(buff, sizeof(buff), var.c_str(), countof(buff));
SetWindowTextW(GetDlgItem(hW, IDC_EDIT1), buff);
return TRUE;
}
case WM_CREATE:
SetWindowLongPtr(hW, GWLP_USERDATA, (LONG)lParam);
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case IDC_BUTTON1:
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hW;
ofn.lpstrTitle = L"USB image file";
ofn.lpstrFile = buff;
ofn.nMaxFile = countof(buff);
ofn.lpstrFilter = L"All\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetOpenFileName(&ofn))
{
SetWindowText(GetDlgItem(hW, IDC_EDIT1), ofn.lpstrFile);
}
break;
case IDOK:
{
INT_PTR res = RESULT_OK;
GetWindowTextW(GetDlgItem(hW, IDC_EDIT1), buff, countof(buff));
port = (int)GetWindowLongPtr(hW, GWLP_USERDATA);
if (!SaveSetting<std::wstring>(MsdDevice::TypeName(), port, APINAME, N_CONFIG_PATH, buff))
res = RESULT_FAILED;
//strcpy_s(conf.usb_img, ofn.lpstrFile);
EndDialog(hW, res);
return TRUE;
}
case IDCANCEL:
EndDialog(hW, FALSE);
return TRUE;
}
}
}
return FALSE;
}
int MsdDevice::Configure(int port, const std::string& api, void* data)
{
Win32Handles handles = *(Win32Handles*)data;
return DialogBoxParam(handles.hInst,
MAKEINTRESOURCE(IDD_DLGMSD),
handles.hWnd,
(DLGPROC)MsdDlgProc, port);
}
} // namespace usb_msd

File diff suppressed because it is too large Load Diff

View File

@ -17,31 +17,32 @@
#define USBMSD_H
#include "../deviceproxy.h"
namespace usb_msd {
static const char *APINAME = "cstdio";
class MsdDevice
namespace usb_msd
{
public:
virtual ~MsdDevice() {}
static USBDevice* CreateDevice(int port);
static const char* TypeName();
static const TCHAR* Name()
{
return TEXT("Mass storage device");
}
static std::list<std::string> ListAPIs()
{
return std::list<std::string> { APINAME };
}
static const TCHAR* LongAPIName(const std::string& name)
{
return TEXT("cstdio");
}
static int Configure(int port, const std::string& api, void *data);
static int Freeze(int mode, USBDevice *dev, void *data);
};
}
static const char* APINAME = "cstdio";
class MsdDevice
{
public:
virtual ~MsdDevice() {}
static USBDevice* CreateDevice(int port);
static const char* TypeName();
static const TCHAR* Name()
{
return TEXT("Mass storage device");
}
static std::list<std::string> ListAPIs()
{
return std::list<std::string>{APINAME};
}
static const TCHAR* LongAPIName(const std::string& name)
{
return TEXT("cstdio");
}
static int Configure(int port, const std::string& api, void* data);
static int Freeze(int mode, USBDevice* dev, void* data);
};
} // namespace usb_msd
#endif

View File

@ -23,115 +23,130 @@
// http://stackoverflow.com/questions/3534535/whats-a-time-efficient-algorithm-to-copy-unaligned-bit-arrays
//
#define PREPARE_FIRST_COPY() \
do { \
if (src_len >= (CHAR_BIT - dst_offset_modulo)) { \
*dst &= reverse_mask[dst_offset_modulo]; \
src_len -= CHAR_BIT - dst_offset_modulo; \
} else { \
*dst &= reverse_mask[dst_offset_modulo] \
| reverse_mask_xor[dst_offset_modulo + src_len + 1];\
c &= reverse_mask[dst_offset_modulo + src_len ];\
src_len = 0; \
} } while (0)
#define PREPARE_FIRST_COPY() \
do \
{ \
if (src_len >= (CHAR_BIT - dst_offset_modulo)) \
{ \
*dst &= reverse_mask[dst_offset_modulo]; \
src_len -= CHAR_BIT - dst_offset_modulo; \
} \
else \
{ \
*dst &= reverse_mask[dst_offset_modulo] | reverse_mask_xor[dst_offset_modulo + src_len + 1]; \
c &= reverse_mask[dst_offset_modulo + src_len]; \
src_len = 0; \
} \
} while (0)
//But copies bits in reverse?
void
bitarray_copy(const uint8_t*src_org, int src_offset, int src_len,
uint8_t*dst_org, int dst_offset)
void bitarray_copy(const uint8_t* src_org, int src_offset, int src_len,
uint8_t* dst_org, int dst_offset)
{
static const unsigned char mask[] =
{ 0x55, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
static const unsigned char reverse_mask[] =
{ 0x55, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
static const unsigned char reverse_mask_xor[] =
{ 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00 };
static const unsigned char mask[] =
{0x55, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
static const unsigned char reverse_mask[] =
{0x55, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
static const unsigned char reverse_mask_xor[] =
{0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00};
if (src_len) {
const unsigned char *src;
unsigned char *dst;
int src_offset_modulo,
dst_offset_modulo;
if (src_len)
{
const unsigned char* src;
unsigned char* dst;
int src_offset_modulo,
dst_offset_modulo;
src = src_org + (src_offset / CHAR_BIT);
dst = dst_org + (dst_offset / CHAR_BIT);
src = src_org + (src_offset / CHAR_BIT);
dst = dst_org + (dst_offset / CHAR_BIT);
src_offset_modulo = src_offset % CHAR_BIT;
dst_offset_modulo = dst_offset % CHAR_BIT;
src_offset_modulo = src_offset % CHAR_BIT;
dst_offset_modulo = dst_offset % CHAR_BIT;
if (src_offset_modulo == dst_offset_modulo) {
int byte_len;
int src_len_modulo;
if (src_offset_modulo) {
unsigned char c;
if (src_offset_modulo == dst_offset_modulo)
{
int byte_len;
int src_len_modulo;
if (src_offset_modulo)
{
unsigned char c;
c = reverse_mask_xor[dst_offset_modulo] & *src++;
c = reverse_mask_xor[dst_offset_modulo] & *src++;
PREPARE_FIRST_COPY();
*dst++ |= c;
}
PREPARE_FIRST_COPY();
*dst++ |= c;
}
byte_len = src_len / CHAR_BIT;
src_len_modulo = src_len % CHAR_BIT;
byte_len = src_len / CHAR_BIT;
src_len_modulo = src_len % CHAR_BIT;
if (byte_len) {
memcpy(dst, src, byte_len);
src += byte_len;
dst += byte_len;
}
if (src_len_modulo) {
*dst &= reverse_mask_xor[src_len_modulo];
*dst |= reverse_mask[src_len_modulo] & *src;
}
} else {
int bit_diff_ls,
bit_diff_rs;
int byte_len;
int src_len_modulo;
unsigned char c;
/*
if (byte_len)
{
memcpy(dst, src, byte_len);
src += byte_len;
dst += byte_len;
}
if (src_len_modulo)
{
*dst &= reverse_mask_xor[src_len_modulo];
*dst |= reverse_mask[src_len_modulo] & *src;
}
}
else
{
int bit_diff_ls,
bit_diff_rs;
int byte_len;
int src_len_modulo;
unsigned char c;
/*
* Begin: Line things up on destination.
*/
if (src_offset_modulo > dst_offset_modulo) {
bit_diff_ls = src_offset_modulo - dst_offset_modulo;
bit_diff_rs = CHAR_BIT - bit_diff_ls;
if (src_offset_modulo > dst_offset_modulo)
{
bit_diff_ls = src_offset_modulo - dst_offset_modulo;
bit_diff_rs = CHAR_BIT - bit_diff_ls;
c = *src++ << bit_diff_ls;
c |= *src >> bit_diff_rs;
c &= reverse_mask_xor[dst_offset_modulo];
} else {
bit_diff_rs = dst_offset_modulo - src_offset_modulo;
bit_diff_ls = CHAR_BIT - bit_diff_rs;
c = *src++ << bit_diff_ls;
c |= *src >> bit_diff_rs;
c &= reverse_mask_xor[dst_offset_modulo];
}
else
{
bit_diff_rs = dst_offset_modulo - src_offset_modulo;
bit_diff_ls = CHAR_BIT - bit_diff_rs;
c = *src >> bit_diff_rs &
reverse_mask_xor[dst_offset_modulo];
}
PREPARE_FIRST_COPY();
*dst++ |= c;
c = *src >> bit_diff_rs &
reverse_mask_xor[dst_offset_modulo];
}
PREPARE_FIRST_COPY();
*dst++ |= c;
/*
/*
* Middle: copy with only shifting the source.
*/
byte_len = src_len / CHAR_BIT;
byte_len = src_len / CHAR_BIT;
while (--byte_len >= 0) {
c = *src++ << bit_diff_ls;
c |= *src >> bit_diff_rs;
*dst++ = c;
}
while (--byte_len >= 0)
{
c = *src++ << bit_diff_ls;
c |= *src >> bit_diff_rs;
*dst++ = c;
}
/*
/*
* End: copy the remaing bits;
*/
src_len_modulo = src_len % CHAR_BIT;
if (src_len_modulo) {
c = *src++ << bit_diff_ls;
c |= *src >> bit_diff_rs;
c &= reverse_mask[src_len_modulo];
src_len_modulo = src_len % CHAR_BIT;
if (src_len_modulo)
{
c = *src++ << bit_diff_ls;
c |= *src >> bit_diff_rs;
c &= reverse_mask[src_len_modulo];
*dst &= reverse_mask_xor[src_len_modulo];
*dst |= c;
}
}
}
*dst &= reverse_mask_xor[src_len_modulo];
*dst |= c;
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -33,178 +33,187 @@
#define DINPUT_AXES_COUNT 32
namespace usb_pad { namespace dx {
extern int32_t BYPASSCAL;
//dinput control mappings
static const DWORD PRECMULTI = 100; //floating point precision multiplier, 100 - two digit precision after comma
extern int32_t GAINZ[2][1];
extern int32_t FFMULTI[2][1];
extern int32_t INVERTFORCES[2];
static bool didDIinit = false; //we have a handle
std::ostream& operator<<(std::ostream& os, REFGUID guid);
enum ControlID
namespace usb_pad
{
CID_STEERING,
CID_STEERING_R,
CID_THROTTLE,
CID_BRAKE,
CID_HATUP,
CID_HATDOWN,
CID_HATLEFT,
CID_HATRIGHT,
CID_SQUARE,
CID_TRIANGLE,
CID_CROSS,
CID_CIRCLE,
CID_L1,
CID_R1,
CID_L2,
CID_R2,
CID_L3,
CID_R3,
CID_SELECT,
CID_START,
CID_COUNT,
};
// Maybe merge with JoystickDevice
class JoystickDeviceFF : public FFDevice
{
public:
JoystickDeviceFF(int port): m_port(port) {}
~JoystickDeviceFF() {}
void SetConstantForce(int level);
void SetSpringForce(const parsed_ff_data& ff);
void SetDamperForce(const parsed_ff_data& ff);
void SetFrictionForce(const parsed_ff_data& ff);
void SetAutoCenter(int value);
void DisableForce(EffectID force);
private:
int m_port;
};
enum ControlType
{
CT_NONE,
CT_KEYBOARD,
CT_MOUSE,
CT_JOYSTICK,
};
enum MappingType
{
MT_NONE = 0, //TODO leave for sanity checking?
MT_AXIS,
MT_BUTTON,
};
struct InputMapped
{
size_t index; //index into g_pJoysticks
MappingType type = MT_NONE;
int32_t mapped; //device axis/button
bool INVERTED;
int32_t HALF;
int32_t LINEAR;
int32_t OFFSET;
int32_t DEADZONE;
};
class JoystickDevice
{
public:
JoystickDevice(ControlType type, LPDIRECTINPUTDEVICE8 device, GUID guid, TSTDSTRING name)
: m_type(type)
, m_guid(guid)
, m_device(device)
, m_product(name)
namespace dx
{
}
bool Poll();
extern int32_t BYPASSCAL;
/*void GetDeviceState(size_t sz, void *ptr)
//dinput control mappings
static const DWORD PRECMULTI = 100; //floating point precision multiplier, 100 - two digit precision after comma
extern int32_t GAINZ[2][1];
extern int32_t FFMULTI[2][1];
extern int32_t INVERTFORCES[2];
static bool didDIinit = false; //we have a handle
std::ostream& operator<<(std::ostream& os, REFGUID guid);
enum ControlID
{
CID_STEERING,
CID_STEERING_R,
CID_THROTTLE,
CID_BRAKE,
CID_HATUP,
CID_HATDOWN,
CID_HATLEFT,
CID_HATRIGHT,
CID_SQUARE,
CID_TRIANGLE,
CID_CROSS,
CID_CIRCLE,
CID_L1,
CID_R1,
CID_L2,
CID_R2,
CID_L3,
CID_R3,
CID_SELECT,
CID_START,
CID_COUNT,
};
// Maybe merge with JoystickDevice
class JoystickDeviceFF : public FFDevice
{
public:
JoystickDeviceFF(int port)
: m_port(port)
{
}
~JoystickDeviceFF() {}
void SetConstantForce(int level);
void SetSpringForce(const parsed_ff_data& ff);
void SetDamperForce(const parsed_ff_data& ff);
void SetFrictionForce(const parsed_ff_data& ff);
void SetAutoCenter(int value);
void DisableForce(EffectID force);
private:
int m_port;
};
enum ControlType
{
CT_NONE,
CT_KEYBOARD,
CT_MOUSE,
CT_JOYSTICK,
};
enum MappingType
{
MT_NONE = 0, //TODO leave for sanity checking?
MT_AXIS,
MT_BUTTON,
};
struct InputMapped
{
size_t index; //index into g_pJoysticks
MappingType type = MT_NONE;
int32_t mapped; //device axis/button
bool INVERTED;
int32_t HALF;
int32_t LINEAR;
int32_t OFFSET;
int32_t DEADZONE;
};
class JoystickDevice
{
public:
JoystickDevice(ControlType type, LPDIRECTINPUTDEVICE8 device, GUID guid, TSTDSTRING name)
: m_type(type)
, m_guid(guid)
, m_device(device)
, m_product(name)
{
}
bool Poll();
/*void GetDeviceState(size_t sz, void *ptr)
{
if (sz == sizeof(DIJOYSTATE2) && ptr)
*ptr = m_jstate;
}*/
DIJOYSTATE2 GetDeviceState()
{
//assert(m_type == CT_JOYSTICK);
return m_controls.js2;
}
DIJOYSTATE2 GetDeviceState()
{
//assert(m_type == CT_JOYSTICK);
return m_controls.js2;
}
HRESULT GetDeviceState(DWORD sz, LPVOID ptr)
{
return m_device->GetDeviceState(sz, ptr);
}
HRESULT GetDeviceState(DWORD sz, LPVOID ptr)
{
return m_device->GetDeviceState(sz, ptr);
}
bool GetButton(int b);
LONG GetAxis(int a);
bool GetButton(int b);
LONG GetAxis(int a);
LPDIRECTINPUTDEVICE8 GetDevice()
{
return m_device;
}
LPDIRECTINPUTDEVICE8 GetDevice()
{
return m_device;
}
GUID GetGUID()
{
return m_guid;
}
GUID GetGUID()
{
return m_guid;
}
const TSTDSTRING& Product() const
{
return m_product;
}
const TSTDSTRING& Product() const
{
return m_product;
}
ControlType GetControlType() { return m_type; }
ControlType GetControlType() { return m_type; }
~JoystickDevice();
private:
GUID m_guid;
TSTDSTRING m_product;
LPDIRECTINPUTDEVICE8 m_device;
ControlType m_type = CT_NONE;
union {
DIJOYSTATE2 js2;
DIMOUSESTATE2 ms2;
BYTE kbd[256];
} m_controls = {};
};
~JoystickDevice();
extern std::vector<JoystickDevice *> g_pJoysticks;
extern std::map<int, InputMapped> g_Controls[2];
private:
GUID m_guid;
TSTDSTRING m_product;
LPDIRECTINPUTDEVICE8 m_device;
ControlType m_type = CT_NONE;
union
{
DIJOYSTATE2 js2;
DIMOUSESTATE2 ms2;
BYTE kbd[256];
} m_controls = {};
};
void LoadDInputConfig(int port, const char *dev_type);
void SaveDInputConfig(int port, const char *dev_type);
extern std::vector<JoystickDevice*> g_pJoysticks;
extern std::map<int, InputMapped> g_Controls[2];
void InitDI(int port, const char *dev_type);
HRESULT InitDirectInput( HWND hWindow, int port );
void FreeDirectInput();
void PollDevices();
float ReadAxis(const InputMapped& im);
float ReadAxis(int port, ControlID axisid);
float FilterControl(float input, LONG linear, LONG offset, LONG dead);
bool KeyDown(DWORD KeyID);
void TestForce(int port);
LONG GetAxisValueFromOffset(int axis, const DIJOYSTATE2& j);
bool GetControl(int port, int id);
float GetAxisControl(int port, ControlID id);
void CreateFFB(int port, LPDIRECTINPUTDEVICE8 device, DWORD axis);
bool FindFFDevice(int port);
void LoadDInputConfig(int port, const char* dev_type);
void SaveDInputConfig(int port, const char* dev_type);
void AddInputMap(int port, int cid, const InputMapped& im);
void RemoveInputMap(int port, int cid);
bool GetInputMap(int port, int cid, InputMapped& im);
void InitDI(int port, const char* dev_type);
HRESULT InitDirectInput(HWND hWindow, int port);
void FreeDirectInput();
void PollDevices();
float ReadAxis(const InputMapped& im);
float ReadAxis(int port, ControlID axisid);
float FilterControl(float input, LONG linear, LONG offset, LONG dead);
bool KeyDown(DWORD KeyID);
void TestForce(int port);
LONG GetAxisValueFromOffset(int axis, const DIJOYSTATE2& j);
bool GetControl(int port, int id);
float GetAxisControl(int port, ControlID id);
void CreateFFB(int port, LPDIRECTINPUTDEVICE8 device, DWORD axis);
bool FindFFDevice(int port);
}} //namespace
void AddInputMap(int port, int cid, const InputMapped& im);
void RemoveInputMap(int port, int cid);
bool GetInputMap(int port, int cid, InputMapped& im);
} // namespace dx
} // namespace usb_pad

View File

@ -17,128 +17,155 @@
#include "dx.h"
#include <cmath>
namespace usb_pad { namespace dx {
static bool bdown=false;
static DWORD calibrationtime = 0;
static int calidata = 0;
static bool alternate = false;
static bool calibrating = false;
DInputPad::~DInputPad() { FreeDirectInput(); }
int DInputPad::TokenIn(uint8_t *buf, int len)
namespace usb_pad
{
int range = range_max(mType);
namespace dx
{
// Setting to unpressed
ZeroMemory(&mWheelData, sizeof(wheel_data_t));
mWheelData.steering = range >> 1;
mWheelData.clutch = 0xFF;
mWheelData.throttle = 0xFF;
mWheelData.brake = 0xFF;
mWheelData.hatswitch = 0x8;
static bool bdown = false;
static DWORD calibrationtime = 0;
static int calidata = 0;
static bool alternate = false;
static bool calibrating = false;
PollDevices();
DInputPad::~DInputPad() { FreeDirectInput(); }
if (mType == WT_BUZZ_CONTROLLER) {
for (int i = 0; i < 20; i++) {
if (GetControl(mPort, i)) {
mWheelData.buttons |= 1 << i;
int DInputPad::TokenIn(uint8_t* buf, int len)
{
int range = range_max(mType);
// Setting to unpressed
ZeroMemory(&mWheelData, sizeof(wheel_data_t));
mWheelData.steering = range >> 1;
mWheelData.clutch = 0xFF;
mWheelData.throttle = 0xFF;
mWheelData.brake = 0xFF;
mWheelData.hatswitch = 0x8;
PollDevices();
if (mType == WT_BUZZ_CONTROLLER)
{
for (int i = 0; i < 20; i++)
{
if (GetControl(mPort, i))
{
mWheelData.buttons |= 1 << i;
}
}
pad_copy_data(mType, buf, mWheelData);
return 5;
}
}
pad_copy_data(mType, buf, mWheelData);
return 5;
}
//Allow in both ports but warn in configure dialog that only one DX wheel is supported for now
//if(idx == 0){
//mWheelData.steering = 8191 + (int)(GetControl(STEERING, false)* 8191.0f) ;
if(calibrating){
//Alternate full extents
if (alternate)calidata--;
else calidata++;
//Allow in both ports but warn in configure dialog that only one DX wheel is supported for now
//if(idx == 0){
//mWheelData.steering = 8191 + (int)(GetControl(STEERING, false)* 8191.0f) ;
if(calidata>range-1 || calidata < 1) alternate = !alternate; //invert
if (calibrating)
{
//Alternate full extents
if (alternate)
calidata--;
else
calidata++;
mWheelData.steering = calidata; //pass fake
if (calidata > range - 1 || calidata < 1)
alternate = !alternate; //invert
//breakout after 11 seconds
if(GetTickCount()-calibrationtime > 11000){
calibrating = false;
mWheelData.steering = range >> 1;
mWheelData.steering = calidata; //pass fake
//breakout after 11 seconds
if (GetTickCount() - calibrationtime > 11000)
{
calibrating = false;
mWheelData.steering = range >> 1;
}
}
}else{
mWheelData.steering = (range>>1) + std::lround(GetAxisControl(mPort, CID_STEERING) * (float)(range>>1));
else
{
mWheelData.steering = (range >> 1) + std::lround(GetAxisControl(mPort, CID_STEERING) * (float)(range >> 1));
}
mWheelData.throttle = std::lround(255.f - (GetAxisControl(mPort, CID_THROTTLE) * 255.0f));
mWheelData.brake = std::lround(255.f - (GetAxisControl(mPort, CID_BRAKE) * 255.0f));
if (GetControl(mPort, CID_CROSS))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_CROSS);
if (GetControl(mPort, CID_SQUARE))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_SQUARE);
if (GetControl(mPort, CID_CIRCLE))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_CIRCLE);
if (GetControl(mPort, CID_TRIANGLE))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_TRIANGLE);
if (GetControl(mPort, CID_R1))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_R1);
if (GetControl(mPort, CID_L1))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_L1);
if (GetControl(mPort, CID_R2))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_R2);
if (GetControl(mPort, CID_L2))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_L2);
if (GetControl(mPort, CID_SELECT))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_SELECT);
if (GetControl(mPort, CID_START))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_START);
if (GetControl(mPort, CID_R3))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_R3);
if (GetControl(mPort, CID_L3))
mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_L3);
//diagonal
if (GetControl(mPort, CID_HATUP) && GetControl(mPort, CID_HATRIGHT))
mWheelData.hatswitch = 1;
if (GetControl(mPort, CID_HATRIGHT) && GetControl(mPort, CID_HATDOWN))
mWheelData.hatswitch = 3;
if (GetControl(mPort, CID_HATDOWN) && GetControl(mPort, CID_HATLEFT))
mWheelData.hatswitch = 5;
if (GetControl(mPort, CID_HATLEFT) && GetControl(mPort, CID_HATUP))
mWheelData.hatswitch = 7;
//regular
if (mWheelData.hatswitch == 0x8)
{
if (GetControl(mPort, CID_HATUP))
mWheelData.hatswitch = 0;
if (GetControl(mPort, CID_HATRIGHT))
mWheelData.hatswitch = 2;
if (GetControl(mPort, CID_HATDOWN))
mWheelData.hatswitch = 4;
if (GetControl(mPort, CID_HATLEFT))
mWheelData.hatswitch = 6;
}
pad_copy_data(mType, buf, mWheelData);
//} //if(idx ...
return len;
}
mWheelData.throttle = std::lround(255.f - (GetAxisControl(mPort, CID_THROTTLE) * 255.0f));
mWheelData.brake = std::lround(255.f - (GetAxisControl(mPort, CID_BRAKE) * 255.0f));
int DInputPad::TokenOut(const uint8_t* data, int len)
{
const ff_data* ffdata = (const ff_data*)data;
bool hires = (mType == WT_DRIVING_FORCE_PRO || mType == WT_DRIVING_FORCE_PRO_1102);
ParseFFData(ffdata, hires);
if(GetControl(mPort, CID_CROSS)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_CROSS);
if(GetControl(mPort, CID_SQUARE)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_SQUARE);
if(GetControl(mPort, CID_CIRCLE)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_CIRCLE);
if(GetControl(mPort, CID_TRIANGLE)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_TRIANGLE);
if(GetControl(mPort, CID_R1)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_R1);
if(GetControl(mPort, CID_L1)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_L1);
if(GetControl(mPort, CID_R2)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_R2);
if(GetControl(mPort, CID_L2)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_L2);
if(GetControl(mPort, CID_SELECT)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_SELECT);
if(GetControl(mPort, CID_START)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_START);
if(GetControl(mPort, CID_R3)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_R3);
if(GetControl(mPort, CID_L3)) mWheelData.buttons |= 1 << convert_wt_btn(mType, PAD_L3);
//diagonal
if(GetControl(mPort, CID_HATUP) && GetControl(mPort, CID_HATRIGHT))
mWheelData.hatswitch = 1;
if(GetControl(mPort, CID_HATRIGHT) && GetControl(mPort, CID_HATDOWN))
mWheelData.hatswitch = 3;
if(GetControl(mPort, CID_HATDOWN) && GetControl(mPort, CID_HATLEFT))
mWheelData.hatswitch = 5;
if(GetControl(mPort, CID_HATLEFT) && GetControl(mPort, CID_HATUP))
mWheelData.hatswitch = 7;
//regular
if(mWheelData.hatswitch==0x8){
if(GetControl(mPort, CID_HATUP))
mWheelData.hatswitch = 0;
if(GetControl(mPort, CID_HATRIGHT))
mWheelData.hatswitch = 2;
if(GetControl(mPort, CID_HATDOWN))
mWheelData.hatswitch = 4;
if(GetControl(mPort, CID_HATLEFT))
mWheelData.hatswitch = 6;
return len;
}
pad_copy_data(mType, buf, mWheelData);
//} //if(idx ...
return len;
}
int DInputPad::Open()
{
LoadSetting(mDevType, mPort, APINAME, TEXT("UseRamp"), mUseRamp);
InitDI(mPort, mDevType);
if (!mFFdev)
mFFdev = new JoystickDeviceFF(mPort /*, mUseRamp*/);
return 0;
}
int DInputPad::TokenOut(const uint8_t *data, int len)
{
const ff_data *ffdata = (const ff_data *)data;
bool hires = (mType == WT_DRIVING_FORCE_PRO || mType == WT_DRIVING_FORCE_PRO_1102);
ParseFFData(ffdata, hires);
int DInputPad::Close()
{
FreeDirectInput();
return 0;
}
return len;
}
int DInputPad::Open()
{
LoadSetting(mDevType, mPort, APINAME, TEXT("UseRamp"), mUseRamp);
InitDI(mPort, mDevType);
if (!mFFdev)
mFFdev = new JoystickDeviceFF(mPort /*, mUseRamp*/);
return 0;
}
int DInputPad::Close()
{
FreeDirectInput();
return 0;
}
}} //namespace
} // namespace dx
} // namespace usb_pad

View File

@ -16,29 +16,38 @@
#include "../padproxy.h"
#include "../../Win32/Config.h"
namespace usb_pad { namespace dx {
static const char *APINAME = "dinput";
class DInputPad : public Pad
namespace usb_pad
{
public:
DInputPad(int port, const char* dev_type) : Pad(port, dev_type), mUseRamp(0){}
~DInputPad();
int Open();
int Close();
int TokenIn(uint8_t *buf, int len);
int TokenOut(const uint8_t *data, int len);
int Reset() { return 0; }
static const TCHAR* Name()
namespace dx
{
return TEXT("DInput");
}
static int Configure(int port, const char* dev_type, void *data);
private:
int32_t mUseRamp;
};
static const char* APINAME = "dinput";
}} //namespace
class DInputPad : public Pad
{
public:
DInputPad(int port, const char* dev_type)
: Pad(port, dev_type)
, mUseRamp(0)
{
}
~DInputPad();
int Open();
int Close();
int TokenIn(uint8_t* buf, int len);
int TokenOut(const uint8_t* data, int len);
int Reset() { return 0; }
static const TCHAR* Name()
{
return TEXT("DInput");
}
static int Configure(int port, const char* dev_type, void* data);
private:
int32_t mUseRamp;
};
} // namespace dx
} // namespace usb_pad

Some files were not shown because too many files have changed in this diff Show More