From 73cace2e547002e6f9b9843622c1181bb5d45e17 Mon Sep 17 00:00:00 2001 From: mattmenke Date: Sat, 12 Sep 2009 13:10:17 +0000 Subject: [PATCH] Highly experimental DS3 support added. Use newly added features at your own risk. Requires libusb installed and DS3 set up as per instructions at http://forums.pcsx2.net/thread-7582.html. Doesn't require sixaxis64.exe/sixaxis.exe, but might have to fool around with starting/stopping Pcsx2 or LilyPad's test device screen and the PS button on your controller until the "1" light turns on. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1810 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/LilyPad/Config.cpp | 34 ++- plugins/LilyPad/Config.h | 1 + plugins/LilyPad/DeviceEnumerator.cpp | 3 + plugins/LilyPad/DirectInput.cpp | 2 +- plugins/LilyPad/DualShock3.cpp | 390 +++++++++++++++++++++++++ plugins/LilyPad/DualShock3.h | 7 + plugins/LilyPad/HidDevice.cpp | 10 +- plugins/LilyPad/HidDevice.h | 1 + plugins/LilyPad/InputManager.h | 5 +- plugins/LilyPad/LilyPad.cpp | 16 +- plugins/LilyPad/LilyPad.rc | 73 ++--- plugins/LilyPad/LilyPad_VC2005.vcproj | 12 + plugins/LilyPad/LilyPad_VC2008.vcproj | 12 + plugins/LilyPad/XInput.cpp | 2 - plugins/LilyPad/XInput.h | 2 - plugins/LilyPad/resource.h | 5 +- plugins/LilyPad/usb.h | 397 ++++++++++++++++++++++++++ 17 files changed, 918 insertions(+), 54 deletions(-) create mode 100644 plugins/LilyPad/DualShock3.cpp create mode 100644 plugins/LilyPad/DualShock3.h create mode 100644 plugins/LilyPad/usb.h diff --git a/plugins/LilyPad/Config.cpp b/plugins/LilyPad/Config.cpp index 66b7c70e3f..3a249a2148 100644 --- a/plugins/LilyPad/Config.cpp +++ b/plugins/LilyPad/Config.cpp @@ -14,6 +14,7 @@ #include "InputManager.h" #include "KeyboardQueue.h" #include "WndProcEater.h" +#include "DualShock3.h" // Needed to know if raw input is available. It requires XP or higher. #include "RawInput.h" @@ -48,6 +49,7 @@ const GeneralSettingsBool BoolOptionsInfo[] = { {L"DirectInput Game Devices", IDC_G_DI, 1}, {L"XInput", IDC_G_XI, 1}, + {L"DualShock 3", IDC_G_DS3, 0}, {L"Multitap 1", IDC_MULTITAP1, 0}, {L"Multitap 2", IDC_MULTITAP2, 0}, @@ -151,8 +153,15 @@ void RefreshEnabledDevices(int updateDeviceList) { (dev->type == MOUSE && dev->api == config.mouseApi) || (dev->type == OTHER && ((dev->api == DI && config.gameApis.directInput) || + (dev->api == DS3 && config.gameApis.dualShock3) || (dev->api == XINPUT && config.gameApis.xInput)))) { - dm->EnableDevice(i); + if (config.gameApis.dualShock3 && dev->api == DI && dev->displayName && + !wcsnicmp(dev->displayName+3, L"PLAYSTATION(R)3", 15)) { + dm->DisableDevice(i); + } + else { + dm->EnableDevice(i); + } } else dm->DisableDevice(i); @@ -1485,6 +1494,9 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l } dm->Update(&info); dm->PostRead(); + Sleep(150); + dm->Update(&info); + dm->PostRead(); dev->SetEffect(ffb, 255); SetTimer(hWnd, 1, 3000, 0); } @@ -1712,6 +1724,11 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L RefreshEnabledDevicesAndDisplay(0, hWnd, 0); UpdatePadList(hWnd); + if (!DualShock3Possible()) { + config.gameApis.dualShock3 = 0; + EnableWindow(GetDlgItem(hWnd, IDC_G_DS3), 0); + } + for (int j=0; j +#include "usb.h" +#include "HidDevice.h" +#include "InputManager.h" + +#define VID 0x054c +#define PID 0x0268 + +#define CHECK_DELAY 5 +time_t lastDS3Check = 0; + +typedef void (__cdecl *_usb_init)(void); +typedef int (__cdecl *_usb_close)(usb_dev_handle *dev); +typedef int (__cdecl *_usb_get_string_simple)(usb_dev_handle *dev, int index, char *buf, size_t buflen); +typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev); +typedef int (__cdecl *_usb_find_busses)(void); +typedef int (__cdecl *_usb_find_devices)(void); +typedef struct usb_bus *(__cdecl *_usb_get_busses)(void); +typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev); +typedef int (__cdecl *_usb_control_msg)(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout); + +_usb_init pusb_init; +_usb_close pusb_close; +_usb_get_string_simple pusb_get_string_simple; +_usb_open pusb_open; +_usb_find_busses pusb_find_busses; +_usb_find_devices pusb_find_devices; +_usb_get_busses pusb_get_busses; +_usb_control_msg pusb_control_msg; + +HMODULE hModLibusb = 0; + +int DualShock3Possible(); +void EnumDualShock3s(); + + +void UninitLibUsb() { + if (hModLibusb) { + FreeLibrary(hModLibusb); + hModLibusb = 0; + } +} + +void TryInitDS3(usb_device *dev) { + while (dev) { + if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID) { + usb_dev_handle *handle = pusb_open(dev); + if (handle) { + char junk[20]; + pusb_control_msg(handle, 0xa1, 1, 0x03f2, 0, junk, 17, 1000); + pusb_close(handle); + } + } + if (dev->num_children) { + for (int i=0; inum_children; i++) { + TryInitDS3(dev->children[i]); + } + } + dev = dev->next; + } +} + +void DS3Check() { + pusb_find_busses(); + pusb_find_devices(); + usb_bus *bus = pusb_get_busses(); + while (bus) { + TryInitDS3(bus->devices); + bus = bus->next; + } + lastDS3Check = time(0); +} + +int InitLibUsb() { + if (hModLibusb) { + return 1; + } + hModLibusb = LoadLibraryA("C:\\windows\\system32\\libusb0.dll"); + if (hModLibusb) { + if ((pusb_init = (_usb_init) GetProcAddress(hModLibusb, "usb_init")) && + (pusb_close = (_usb_close) GetProcAddress(hModLibusb, "usb_close")) && + (pusb_get_string_simple = (_usb_get_string_simple) GetProcAddress(hModLibusb, "usb_get_string_simple")) && + (pusb_open = (_usb_open) GetProcAddress(hModLibusb, "usb_open")) && + (pusb_find_busses = (_usb_find_busses) GetProcAddress(hModLibusb, "usb_find_busses")) && + (pusb_find_devices = (_usb_find_devices) GetProcAddress(hModLibusb, "usb_find_devices")) && + (pusb_get_busses = (_usb_get_busses) GetProcAddress(hModLibusb, "usb_get_busses")) && + (pusb_control_msg = (_usb_control_msg) GetProcAddress(hModLibusb, "usb_control_msg"))) { + pusb_init(); + return 1; + } + UninitLibUsb(); + } + return 0; +} + +int DualShock3Possible() { + return InitLibUsb(); +} + +#include + +struct MotorState { + unsigned char duration; + unsigned char force; +}; + +struct LightState { + // 0xFF makes it stay on. + unsigned char duration; + // Have to make one or the other non-zero to turn on light. + unsigned char dunno[2]; + // 0 is fully lit. + unsigned char dimness; + // Have to make non-zero to turn on light. + unsigned char on; +}; + +// Data sent to DS3 to set state. +struct DS3Command { + unsigned char id; + unsigned char unsure; + // Big is first, then small. + MotorState motors[2]; + unsigned char noClue[4]; + // 2 is pad 1 light, 4 is pad 2, 8 is pad 3, 16 is pad 4. No clue about the others. + unsigned char lightFlags; + // Lights are in reverse order. pad 1 is last. + LightState lights[4]; + unsigned char dunno[18]; +}; + +#include + +int CharToAxis(unsigned char c) { + int v = (int)c + ((unsigned int)c >> 7); + return ((c-128) * FULLY_DOWN)>>7; +} + +int CharToButton(unsigned char c) { + int v = (int)c + ((unsigned int)c >> 7); + return (v * FULLY_DOWN)>>8; +} + +class DualShock3Device : public Device { + // Cached last vibration values by pad and motor. + // Need this, as only one value is changed at a time. + int ps2Vibration[2][4][2]; + int vibration[2]; +public: + int index; + HANDLE hFile; + DS3Command sendState; + unsigned char getState[49]; + OVERLAPPED readop; + OVERLAPPED writeop; + + int writeQueued; + int StartRead() { + readop.Offset = readop.OffsetHigh = 0; + int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop); + return (res || GetLastError() == ERROR_IO_PENDING); + } + int StartWrite() { + writeop.Offset = writeop.OffsetHigh = 0; + for (int i=0; i<2; i++) { + if (vibration[i]) { + sendState.motors[i].duration = 0x7F; + int force = vibration[i] * 256/FULLY_DOWN; + if (force > 255) force = 255; + sendState.motors[i].force = (unsigned char) force; + } + else { + sendState.motors[i].force = 0; + sendState.motors[i].duration = 0; + } + } + int res = WriteFile(hFile, &sendState, sizeof(sendState), 0, &writeop); + return (res || GetLastError() == ERROR_IO_PENDING); + } + + DualShock3Device(int index, wchar_t *name, wchar_t *path) : Device(DS3, OTHER, name, path) { + memset(&readop, 0, sizeof(readop)); + memset(&writeop, 0, sizeof(writeop)); + memset(&sendState, 0, sizeof(sendState)); + sendState.id = 1; + int temp = (index&4); + sendState.lightFlags = (1 << (temp+1)); + sendState.lights[3-temp].duration = 0xFF; + sendState.lights[3-temp].dunno[0] = 1; + sendState.lights[3-temp].on = 1; + memset(ps2Vibration, 0, sizeof(ps2Vibration)); + writeQueued = 0; + vibration[0] = vibration[1] = 0; + this->index = index; + int i; + for (i=0; i<16; i++) { + AddPhysicalControl(PSHBTN, i, 0); + } + for (; i<20; i++) { + AddPhysicalControl(ABSAXIS, i, 0); + } + AddFFAxis(L"Slow Motor", 0); + AddFFAxis(L"Fast Motor", 1); + AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT); + hFile = INVALID_HANDLE_VALUE; + } + + wchar_t *GetPhysicalControlName(PhysicalControl *c) { + const static wchar_t *names[] = { + L"Square", + L"Cross", + L"Circle", + L"Triangle", + L"R1", + L"L1", + L"R2", + L"L2", + L"R3", + L"L3", + L"Left", + L"Down", + L"Right", + L"Up", + L"Start", + L"Select", + L"Left Thumb X", + L"Left Thumb Y", + L"Right Thumb X", + L"Right Thumb Y", + }; + unsigned int i = (unsigned int) (c - physicalControls); + if (i < 20) { + return (wchar_t*)names[i]; + } + return Device::GetPhysicalControlName(c); + } + + int Activate(void *d) { + if (!lastDS3Check) { + DS3Check(); + } + else { + lastDS3Check = time(0) - CHECK_DELAY+3; + } + if (active) Deactivate(); + readop.hEvent = CreateEvent(0, 0, 0, 0); + writeop.hEvent = CreateEvent(0, 0, 0, 0); + hFile = CreateFileW(instanceID, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if (!readop.hEvent || !writeop.hEvent || hFile == INVALID_HANDLE_VALUE || + !StartRead() || !StartWrite()) { + Deactivate(); + return 0; + } + writeQueued = 1; + active = 1; + AllocState(); + return 1; + } + + int Update() { + if (!active) return 0; + HANDLE h[2] = { + readop.hEvent, + writeop.hEvent + }; + while (1) { + DWORD res = WaitForMultipleObjects(2, h, 0, 0); + if (res == WAIT_OBJECT_0) { + // Do stuff. + if (!StartRead()) { + Deactivate(); + return 0; + } + physicalControlState[0] = CharToButton(getState[25]); + physicalControlState[1] = CharToButton(getState[24]); + physicalControlState[2] = CharToButton(getState[23]); + physicalControlState[3] = CharToButton(getState[22]); + physicalControlState[4] = CharToButton(getState[21]); + physicalControlState[5] = CharToButton(getState[20]); + physicalControlState[6] = CharToButton(getState[19]); + physicalControlState[7] = CharToButton(getState[18]); + physicalControlState[10] = CharToButton(getState[17]); + physicalControlState[11] = CharToButton(getState[16]); + physicalControlState[12] = CharToButton(getState[15]); + physicalControlState[13] = CharToButton(getState[14]); + physicalControlState[8] = ((getState[2]&4)/4) * FULLY_DOWN; + physicalControlState[9] = ((getState[2]&2)/2) * FULLY_DOWN; + physicalControlState[15] = ((getState[2]&1)/1) * FULLY_DOWN; + physicalControlState[14] = ((getState[2]&8)/8) * FULLY_DOWN; + physicalControlState[16] = CharToAxis(getState[6]); + physicalControlState[17] = CharToAxis(getState[7]); + physicalControlState[18] = CharToAxis(getState[8]); + physicalControlState[19] = CharToAxis(getState[9]); + continue; + } + else if (res == WAIT_OBJECT_0+1) { + writeQueued--; + if (writeQueued) { + if (!StartWrite()) { + Deactivate(); + return 0; + } + } + } + else { + time_t test = time(0); + if (test - lastDS3Check >= CHECK_DELAY) { + DS3Check(); + } + } + break; + } + return 1; + } + + void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) { + ps2Vibration[port][slot][motor] = force; + vibration[0] = vibration[1] = 0; + for (int p=0; p<2; p++) { + for (int s=0; s<4; s++) { + for (int i=0; iaxes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); + vibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); + } + } + } + if (!writeQueued) { + StartWrite(); + } + if (writeQueued<2) { + writeQueued++; + } + } + + void SetEffect(ForceFeedbackBinding *binding, unsigned char force) { + PadBindings pBackup = pads[0][0]; + pads[0][0].ffBindings = binding; + pads[0][0].numFFBindings = 1; + SetEffects(0, 0, binding->motor, 255); + pads[0][0] = pBackup; + } + + void Deactivate() { + if (hFile != INVALID_HANDLE_VALUE) { + CancelIo(hFile); + CloseHandle(hFile); + hFile = INVALID_HANDLE_VALUE; + } + if (readop.hEvent) { + CloseHandle(readop.hEvent); + } + if (writeop.hEvent) { + CloseHandle(writeop.hEvent); + } + writeQueued = 0; + memset(ps2Vibration, 0, sizeof(ps2Vibration)); + vibration[0] = vibration[1] = 0; + + FreeState(); + active = 0; + } + + ~DualShock3Device() { + } +}; + +void EnumDualShock3s() { + if (!InitLibUsb()) return; + + HidDeviceInfo *foundDevs = 0; + + int numDevs = FindHids(&foundDevs, VID, PID); + if (!numDevs) return; + int index = 0; + for (int i=0; iAddDevice(new DualShock3Device(index, temp, foundDevs[i].path)); + index++; + } + free(foundDevs[i].path); + } + free(foundDevs); +} diff --git a/plugins/LilyPad/DualShock3.h b/plugins/LilyPad/DualShock3.h new file mode 100644 index 0000000000..97d7df3baa --- /dev/null +++ b/plugins/LilyPad/DualShock3.h @@ -0,0 +1,7 @@ +int DualShock3Possible(); +void EnumDualShock3s(); +#include "InputManager.h" + +// May move elsewhere in the future. +int InitLibUsb(); +void UninitLibUsb(); diff --git a/plugins/LilyPad/HidDevice.cpp b/plugins/LilyPad/HidDevice.cpp index 8a2d404c2e..55df5d34cb 100644 --- a/plugins/LilyPad/HidDevice.cpp +++ b/plugins/LilyPad/HidDevice.cpp @@ -20,6 +20,8 @@ typedef void (__stdcall *_HidD_GetHidGuid) (GUID* HidGuid); typedef BOOLEAN (__stdcall *_HidD_GetPreparsedData) (HANDLE HidDeviceObject, HIDP_PREPARSED_DATA **PreparsedData); typedef NTSTATUS (__stdcall *_HidP_GetCaps) (HIDP_PREPARSED_DATA* PreparsedData, HIDP_CAPS *caps); typedef BOOLEAN (__stdcall *_HidD_FreePreparsedData) (HIDP_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); GUID GUID_DEVINTERFACE_HID; _HidD_GetHidGuid pHidD_GetHidGuid; @@ -27,6 +29,8 @@ _HidD_GetAttributes pHidD_GetAttributes; _HidD_GetPreparsedData pHidD_GetPreparsedData; _HidP_GetCaps pHidP_GetCaps; _HidD_FreePreparsedData pHidD_FreePreparsedData; +_HidD_GetFeature pHidD_GetFeature; +_HidD_SetFeature pHidD_SetFeature; HMODULE hModHid = 0; @@ -40,7 +44,9 @@ int InitHid() { (pHidD_GetAttributes = (_HidD_GetAttributes) GetProcAddress(hModHid, "HidD_GetAttributes")) && (pHidD_GetPreparsedData = (_HidD_GetPreparsedData) GetProcAddress(hModHid, "HidD_GetPreparsedData")) && (pHidP_GetCaps = (_HidP_GetCaps) GetProcAddress(hModHid, "HidP_GetCaps")) && - (pHidD_FreePreparsedData = (_HidD_FreePreparsedData) GetProcAddress(hModHid, "HidD_FreePreparsedData"))) { + (pHidD_FreePreparsedData = (_HidD_FreePreparsedData) GetProcAddress(hModHid, "HidD_FreePreparsedData")) && + (pHidD_GetFeature = (_HidD_GetFeature) GetProcAddress(hModHid, "HidD_GetFeature")) && + (pHidD_SetFeature = (_HidD_SetFeature) GetProcAddress(hModHid, "HidD_SetFeature"))) { pHidD_GetHidGuid(&GUID_DEVINTERFACE_HID); return 1; } @@ -82,7 +88,7 @@ int FindHids(HidDeviceInfo **foundDevs, int vid, int pid) { if (pHidD_GetPreparsedData(hfile, &pData)) { if (HIDP_STATUS_SUCCESS == pHidP_GetCaps(pData, &caps)) { if (numFoundDevs % 32 == 0) { - *foundDevs = (HidDeviceInfo*) realloc(foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs)); + *foundDevs = (HidDeviceInfo*) realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs)); } HidDeviceInfo *dev = &foundDevs[0][numFoundDevs++]; dev->caps = caps; diff --git a/plugins/LilyPad/HidDevice.h b/plugins/LilyPad/HidDevice.h index 52f2565713..376d1694c8 100644 --- a/plugins/LilyPad/HidDevice.h +++ b/plugins/LilyPad/HidDevice.h @@ -35,5 +35,6 @@ struct HidDeviceInfo { }; void UninitHid(); +int FindHids(HidDeviceInfo **foundDevs, int vid, int pid); #endif diff --git a/plugins/LilyPad/InputManager.h b/plugins/LilyPad/InputManager.h index ac9bf8dc67..2ae97b8938 100644 --- a/plugins/LilyPad/InputManager.h +++ b/plugins/LilyPad/InputManager.h @@ -97,12 +97,13 @@ enum DeviceAPI { WM = 2, RAW = 3, XINPUT = 4, + DS3 = 5, // Not currently used. - LLHOOK = 5, + LLHOOK = 6, // Not a real API, obviously. Only used with keyboards, // to ignore individual buttons. Wrapper itself takes care // of ignoring bound keys. Otherwise, works normally. - IGNORE_KEYBOARD = 6, + IGNORE_KEYBOARD = 7, }; enum DeviceType { diff --git a/plugins/LilyPad/LilyPad.cpp b/plugins/LilyPad/LilyPad.cpp index f9a4313b3d..076555d220 100644 --- a/plugins/LilyPad/LilyPad.cpp +++ b/plugins/LilyPad/LilyPad.cpp @@ -17,6 +17,8 @@ #include "KeyboardQueue.h" #include "svnrev.h" #include "resource.h" +#include "DualShock3.h" +#include "HidDevice.h" #ifdef PCSX2_DEBUG #include "crtdbg.h" @@ -260,6 +262,8 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, void* lpvReserved) { while (openCount) PADclose(); PADshutdown(); + UninitHid(); + UninitLibUsb(); } return 1; } @@ -969,20 +973,20 @@ u8 CALLBACK PADpoll(u8 value) { u8 b1 = 0xFF, b2 = 0xFF; for (i = 0; i<4; i++) { - b1 -= (sum->buttons[i]>=0xF0) << i; + b1 -= (sum->buttons[i]>=0x30) << i; } for (i = 0; i<8; i++) { - b2 -= (sum->buttons[i+4]>=0xF0) << i; + b2 -= (sum->buttons[i+4]>=0x30) << i; } if (config.padConfigs[query.port][query.slot].type == GuitarPad && !config.GH2) { sum->sticks[0].horiz = -255; // Not sure about this. Forces wammy to be from 0 to 0x7F. // if (sum->sticks[2].vert > 0) sum->sticks[2].vert = 0; } - b1 -= ((sum->sticks[0].vert<=-0xF0) << 4); - b1 -= ((sum->sticks[0].horiz>=0xF0) << 5); - b1 -= ((sum->sticks[0].vert>=0xF0) << 6); - b1 -= ((sum->sticks[0].horiz<=-0xF0) << 7); + b1 -= ((sum->sticks[0].vert<=-0x30) << 4); + b1 -= ((sum->sticks[0].horiz>=0x30) << 5); + b1 -= ((sum->sticks[0].vert>=0x30) << 6); + b1 -= ((sum->sticks[0].horiz<=-0x30) << 7); query.response[3] = b1; query.response[4] = b2; diff --git a/plugins/LilyPad/LilyPad.rc b/plugins/LilyPad/LilyPad.rc index 48d82fdc84..f35c37a846 100644 --- a/plugins/LilyPad/LilyPad.rc +++ b/plugins/LilyPad/LilyPad.rc @@ -27,18 +27,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // TEXTINCLUDE // -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN "resource.h\0" END -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN "#include \r\n" "\0" END -3 TEXTINCLUDE +3 TEXTINCLUDE BEGIN "\r\n" "\0" @@ -198,21 +198,22 @@ BEGIN PUSHBUTTON "Small Motor",ID_SMALL_MOTOR,347,291,64,14 END -IDD_GENERAL DIALOGEX 0, 0, 424, 318 +IDD_GENERAL DIALOGEX 0, 0, 424, 327 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN - GROUPBOX "Input APIs",IDC_STATIC,7,6,410,131 + GROUPBOX "Input APIs",IDC_STATIC,7,6,410,141 GROUPBOX "Keyboard API",IDC_STATIC,16,16,192,61 CONTROL "Windows messaging (Recommended)",IDC_KB_WM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,22,28,134,10 CONTROL "Raw input (XP and later only)",IDC_KB_RAW,"Button",BS_AUTORADIOBUTTON,22,40,112,10 CONTROL "DirectInput",IDC_KB_DI,"Button",BS_AUTORADIOBUTTON,22,52,112,10 CONTROL "Disable (Intended for use with other pad plugins)",IDC_KB_DISABLE, "Button",BS_AUTORADIOBUTTON,22,64,175,10 - GROUPBOX "Game Device APIs",IDC_STATIC,16,81,191,49 - CONTROL "DirectInput",IDC_G_DI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,92,65,10 - CONTROL "XInput (Xbox 360 controllers only)",IDC_G_XI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,104,125,10 - CONTROL "Monitor when in background",IDC_BACKGROUND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,116,106,10 + GROUPBOX "Game Device APIs",IDC_STATIC,16,79,191,61 + CONTROL "DirectInput",IDC_G_DI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,91,65,10 + CONTROL "XInput (Xbox 360 controllers only)",IDC_G_XI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,103,125,10 + CONTROL "DualShock 3 (Requires libusb)",IDC_G_DS3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,115,110,10 + CONTROL "Monitor when in background",IDC_BACKGROUND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,127,106,10 GROUPBOX "Mouse API",IDC_STATIC,216,16,192,85 CONTROL "Windows messaging (Recommended)",IDC_M_WM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,223,27,134,10 CONTROL "Raw input (XP and later only)",IDC_M_RAW,"Button",BS_AUTORADIOBUTTON,223,39,112,10 @@ -220,34 +221,34 @@ BEGIN CONTROL "Disable",IDC_M_DISABLE,"Button",BS_AUTORADIOBUTTON,223,63,39,10 CONTROL "Start without mouse focus",IDC_MOUSE_UNFOCUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,75,97,10 CONTROL "Always hide cursor",IDC_FORCE_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,87,71,10 - GROUPBOX "Advanced",IDC_STATIC,216,105,192,25 + GROUPBOX "Advanced",IDC_STATIC,216,111,192,28 CONTROL "Allow binding multiple PS2 controls to one PC control",IDC_MULTIPLE_BINDING, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,116,182,10 - GROUPBOX "Pads",IDC_STATIC,7,140,410,67 - CONTROL "Port 1 Multitap",IDC_MULTITAP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,152,63,10 - CONTROL "Port 2 Multitap",IDC_MULTITAP2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,164,63,10 - CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_TABSTOP,81,151,183,50,WS_EX_CLIENTEDGE - COMBOBOX IDC_PAD_TYPE,270,152,140,41,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,124,182,10 + GROUPBOX "Pads",IDC_STATIC,7,150,410,67 + CONTROL "Port 1 Multitap",IDC_MULTITAP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,162,63,10 + CONTROL "Port 2 Multitap",IDC_MULTITAP2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,174,63,10 + CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_TABSTOP,81,161,183,50,WS_EX_CLIENTEDGE + COMBOBOX IDC_PAD_TYPE,270,162,140,41,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Use analog mode whenever possible",IDC_ANALOG_START1, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,169,132,10 - GROUPBOX "Device Diagnostics",IDC_STATIC,7,211,201,99 - CONTROL "",IDC_LIST,"SysListView32",LVS_LIST | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,15,224,185,61,WS_EX_CLIENTEDGE - PUSHBUTTON "Test Device",ID_TEST,86,289,57,15 - PUSHBUTTON "Refresh",ID_REFRESH,152,289,48,15 - GROUPBOX "Miscellaneous",IDC_STATIC,216,211,201,34 - CONTROL "Use GS thread",IDC_GS_THREAD_INPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,221,62,10 - CONTROL "Disable screensaver",IDC_DISABLE_SCREENSAVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,232,80,10 - CONTROL "Local volume control",IDC_VISTA_VOLUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,221,77,10 - CONTROL "Enable logging",IDC_DEBUG_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,232,62,10 - GROUPBOX "Hacks",IDC_STATIC,216,247,201,45 - CONTROL "Send escape on window close",IDC_CLOSE_HACK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,257,113,10 - CONTROL "Exit emulator on window close",IDC_CLOSE_HACK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,268,112,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,179,132,10 + GROUPBOX "Device Diagnostics",IDC_STATIC,7,221,201,99 + CONTROL "",IDC_LIST,"SysListView32",LVS_LIST | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,15,234,185,61,WS_EX_CLIENTEDGE + PUSHBUTTON "Test Device",ID_TEST,86,299,57,15 + PUSHBUTTON "Refresh",ID_REFRESH,152,299,48,15 + GROUPBOX "Miscellaneous",IDC_STATIC,216,221,201,34 + CONTROL "Use GS thread",IDC_GS_THREAD_INPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,231,62,10 + CONTROL "Disable screensaver",IDC_DISABLE_SCREENSAVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,242,80,10 + CONTROL "Local volume control",IDC_VISTA_VOLUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,231,77,10 + CONTROL "Enable logging",IDC_DEBUG_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,242,62,10 + GROUPBOX "Hacks",IDC_STATIC,216,257,201,45 + CONTROL "Send escape on window close",IDC_CLOSE_HACK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,267,113,10 + CONTROL "Exit emulator on window close",IDC_CLOSE_HACK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,278,112,10 CONTROL "Safe fullscreen exit on escape",IDC_ESCAPE_FULLSCREEN_HACK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,279,112,10 - CONTROL "Save state # in title",IDC_SAVE_STATE_TITLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,257,79,10 - CONTROL "Guitar Hero 2 Hack",IDC_GH2_HACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,268,76,10 - PUSHBUTTON "Load Bindings",ID_LOAD,283,295,62,15 - PUSHBUTTON "Save Bindings",ID_SAVE,355,295,62,15 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,289,112,10 + CONTROL "Save state # in title",IDC_SAVE_STATE_TITLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,267,79,10 + CONTROL "Guitar Hero 2 Hack",IDC_GH2_HACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,278,76,10 + PUSHBUTTON "Load Bindings",ID_LOAD,283,305,62,15 + PUSHBUTTON "Save Bindings",ID_SAVE,355,305,62,15 END IDD_ABOUT DIALOGEX 0, 0, 108, 66 @@ -275,7 +276,7 @@ END // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +GUIDELINES DESIGNINFO BEGIN IDD_CONFIG, DIALOG BEGIN @@ -298,7 +299,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 417 TOPMARGIN, 7 - BOTTOMMARGIN, 310 + BOTTOMMARGIN, 319 END IDD_ABOUT, DIALOG diff --git a/plugins/LilyPad/LilyPad_VC2005.vcproj b/plugins/LilyPad/LilyPad_VC2005.vcproj index 6d5c5809c3..a3a08a8e0a 100644 --- a/plugins/LilyPad/LilyPad_VC2005.vcproj +++ b/plugins/LilyPad/LilyPad_VC2005.vcproj @@ -608,6 +608,14 @@ RelativePath=".\DirectInput.h" > + + + + @@ -640,6 +648,10 @@ RelativePath=".\RawInput.h" > + + diff --git a/plugins/LilyPad/LilyPad_VC2008.vcproj b/plugins/LilyPad/LilyPad_VC2008.vcproj index 1ea04a28f3..037a6f92d1 100644 --- a/plugins/LilyPad/LilyPad_VC2008.vcproj +++ b/plugins/LilyPad/LilyPad_VC2008.vcproj @@ -543,6 +543,14 @@ RelativePath=".\DirectInput.h" > + + + + @@ -575,6 +583,10 @@ RelativePath=".\RawInput.h" > + + diff --git a/plugins/LilyPad/XInput.cpp b/plugins/LilyPad/XInput.cpp index 68bf7cd087..e24a0ed11e 100644 --- a/plugins/LilyPad/XInput.cpp +++ b/plugins/LilyPad/XInput.cpp @@ -1,9 +1,7 @@ #include "Global.h" #include "VKey.h" -#include "DirectInput.h" #include #include "InputManager.h" -#include "DeviceEnumerator.h" // This way, I don't require that XInput junk be installed. typedef void (CALLBACK *_XInputEnable)(BOOL enable); diff --git a/plugins/LilyPad/XInput.h b/plugins/LilyPad/XInput.h index d9240edcab..defdd6b8aa 100644 --- a/plugins/LilyPad/XInput.h +++ b/plugins/LilyPad/XInput.h @@ -1,3 +1 @@ -#include "InputManager.h" - void EnumXInputDevices(); diff --git a/plugins/LilyPad/resource.h b/plugins/LilyPad/resource.h index 0fba1fbb30..6fa9c6291f 100644 --- a/plugins/LilyPad/resource.h +++ b/plugins/LilyPad/resource.h @@ -23,7 +23,8 @@ #define IDC_M_RAW 1109 #define IDC_G_XI 1110 #define IDC_G_DI 1111 -#define IDC_CLOSE_HACK2 1112 +#define IDC_G_DS3 1112 +#define IDC_CLOSE_HACK2 1113 #define IDC_DEBUG_FILE 1114 #define IDC_GUITAR1 1115 #define IDC_ANALOG_START1 1117 @@ -137,7 +138,7 @@ #define IDC_FF_AXIS8_SCALE 0x1383 // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 112 diff --git a/plugins/LilyPad/usb.h b/plugins/LilyPad/usb.h new file mode 100644 index 0000000000..b00591cec4 --- /dev/null +++ b/plugins/LilyPad/usb.h @@ -0,0 +1,397 @@ +// Note: From libusb. + +#ifndef __USB_H__ +#define __USB_H__ + +#include +#include + +/* + * 'interface' is defined somewhere in the Windows header files. This macro + * is deleted here to avoid conflicts and compile errors. + */ + +#ifdef interface +#undef interface +#endif + +/* + * PATH_MAX from limits.h can't be used on Windows if the dll and + * import libraries are build/used by different compilers + */ + +#define LIBUSB_PATH_MAX 512 + + +/* + * USB spec information + * + * This is all stuff grabbed from various USB specs and is pretty much + * not subject to change + */ + +/* + * Device and/or Interface Class codes + */ +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_DATA 10 +#define USB_CLASS_VENDOR_SPEC 0xff + +/* + * Descriptor types + */ +#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_HID 0x21 +#define USB_DT_REPORT 0x22 +#define USB_DT_PHYSICAL 0x23 +#define USB_DT_HUB 0x29 + +/* + * Descriptor sizes per descriptor type + */ +#define USB_DT_DEVICE_SIZE 18 +#define USB_DT_CONFIG_SIZE 9 +#define USB_DT_INTERFACE_SIZE 9 +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ +#define USB_DT_HUB_NONVAR_SIZE 7 + + +/* ensure byte-packed structures */ +#include + + +/* All standard descriptors have these 2 fields in common */ +struct usb_descriptor_header { + unsigned char bLength; + unsigned char bDescriptorType; +}; + +/* String descriptor */ +struct usb_string_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short wData[1]; +}; + +/* HID descriptor */ +struct usb_hid_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short bcdHID; + unsigned char bCountryCode; + unsigned char bNumDescriptors; +}; + +/* Endpoint descriptor */ +#define USB_MAXENDPOINTS 32 +struct usb_endpoint_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bEndpointAddress; + unsigned char bmAttributes; + unsigned short wMaxPacketSize; + unsigned char bInterval; + unsigned char bRefresh; + unsigned char bSynchAddress; + + unsigned char *extra; /* Extra descriptors */ + int extralen; +}; + +#define USB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_TYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_TYPE_CONTROL 0 +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 1 +#define USB_ENDPOINT_TYPE_BULK 2 +#define USB_ENDPOINT_TYPE_INTERRUPT 3 + +/* Interface descriptor */ +#define USB_MAXINTERFACES 32 +struct usb_interface_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bInterfaceNumber; + unsigned char bAlternateSetting; + unsigned char bNumEndpoints; + unsigned char bInterfaceClass; + unsigned char bInterfaceSubClass; + unsigned char bInterfaceProtocol; + unsigned char iInterface; + + struct usb_endpoint_descriptor *endpoint; + + unsigned char *extra; /* Extra descriptors */ + int extralen; +}; + +#define USB_MAXALTSETTING 128 /* Hard limit */ + +struct usb_interface { + struct usb_interface_descriptor *altsetting; + + int num_altsetting; +}; + +/* Configuration descriptor information.. */ +#define USB_MAXCONFIG 8 +struct usb_config_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short wTotalLength; + unsigned char bNumInterfaces; + unsigned char bConfigurationValue; + unsigned char iConfiguration; + unsigned char bmAttributes; + unsigned char MaxPower; + + struct usb_interface *interface; + + unsigned char *extra; /* Extra descriptors */ + int extralen; +}; + +/* Device descriptor */ +struct usb_device_descriptor { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short bcdUSB; + unsigned char bDeviceClass; + unsigned char bDeviceSubClass; + unsigned char bDeviceProtocol; + unsigned char bMaxPacketSize0; + unsigned short idVendor; + unsigned short idProduct; + unsigned short bcdDevice; + unsigned char iManufacturer; + unsigned char iProduct; + unsigned char iSerialNumber; + unsigned char bNumConfigurations; +}; + +struct usb_ctrl_setup { + unsigned char bRequestType; + unsigned char bRequest; + unsigned short wValue; + unsigned short wIndex; + unsigned short wLength; +}; + +/* + * Standard requests + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +/* 0x02 is reserved */ +#define USB_REQ_SET_FEATURE 0x03 +/* 0x04 is reserved */ +#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_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_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +/* + * Various libusb API related stuff + */ + +#define USB_ENDPOINT_IN 0x80 +#define USB_ENDPOINT_OUT 0x00 + +/* Error codes */ +#define USB_ERROR_BEGIN 500000 + +/* + * This is supposed to look weird. This file is generated from autoconf + * and I didn't want to make this too complicated. + */ +#define USB_LE16_TO_CPU(x) + +/* Data types */ +/* struct usb_device; */ +/* struct usb_bus; */ + +struct usb_device { + struct usb_device *next, *prev; + + char filename[LIBUSB_PATH_MAX]; + + struct usb_bus *bus; + + struct usb_device_descriptor descriptor; + struct usb_config_descriptor *config; + + void *dev; /* Darwin support */ + + unsigned char devnum; + + unsigned char num_children; + struct usb_device **children; +}; + +struct usb_bus { + struct usb_bus *next, *prev; + + char dirname[LIBUSB_PATH_MAX]; + + struct usb_device *devices; + unsigned long location; + + struct usb_device *root_dev; +}; + +/* Version information, Windows specific */ +struct usb_version { + struct { + int major; + int minor; + int micro; + int nano; + } dll; + struct { + int major; + int minor; + int micro; + int nano; + } driver; +}; + + +struct usb_dev_handle; +typedef struct usb_dev_handle usb_dev_handle; + +/* Variables */ +#ifndef __USB_C__ +#define usb_busses usb_get_busses() +#endif + + + +#include + +#ifdef GOAT +#ifdef __cplusplus +extern "C" { +#endif + + /* Function prototypes */ + + /* usb.c */ + usb_dev_handle *usb_open(struct usb_device *dev); + int usb_close(usb_dev_handle *dev); + int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, + size_t buflen); + int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, + size_t buflen); + + /* descriptors.c */ + int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep, + unsigned char type, unsigned char index, + void *buf, int size); + int usb_get_descriptor(usb_dev_handle *udev, unsigned char type, + unsigned char index, void *buf, int size); + + /* .c */ + int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, + int timeout); + int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, + int timeout); + int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size, + int timeout); + int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, + int timeout); + int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, + int value, int index, char *bytes, int size, + int timeout); + int usb_set_configuration(usb_dev_handle *dev, int configuration); + int usb_claim_interface(usb_dev_handle *dev, int interface); + int usb_release_interface(usb_dev_handle *dev, int interface); + int usb_set_altinterface(usb_dev_handle *dev, int alternate); + int usb_resetep(usb_dev_handle *dev, unsigned int ep); + int usb_clear_halt(usb_dev_handle *dev, unsigned int ep); + int usb_reset(usb_dev_handle *dev); + + char *usb_strerror(void); + + void usb_init(void); + void usb_set_debug(int level); + int usb_find_busses(void); + int usb_find_devices(void); + struct usb_device *usb_device(usb_dev_handle *dev); + struct usb_bus *usb_get_busses(void); + + + /* Windows specific functions */ + + #define LIBUSB_HAS_INSTALL_SERVICE_NP 1 + int usb_install_service_np(void); + void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance, + LPSTR cmd_line, int cmd_show); + + #define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1 + int usb_uninstall_service_np(void); + void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance, + LPSTR cmd_line, int cmd_show); + + #define LIBUSB_HAS_INSTALL_DRIVER_NP 1 + int usb_install_driver_np(const char *inf_file); + void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance, + LPSTR cmd_line, int cmd_show); + + #define LIBUSB_HAS_TOUCH_INF_FILE_NP 1 + int usb_touch_inf_file_np(const char *inf_file); + void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance, + LPSTR cmd_line, int cmd_show); + + #define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1 + int usb_install_needs_restart_np(void); + + const struct usb_version *usb_get_version(void); + + int usb_isochronous_setup_async(usb_dev_handle *dev, void **context, + unsigned char ep, int pktsize); + int usb_bulk_setup_async(usb_dev_handle *dev, void **context, + unsigned char ep); + int usb_interrupt_setup_async(usb_dev_handle *dev, void **context, + unsigned char ep); + + int usb_submit_async(void *context, char *bytes, int size); + int usb_reap_async(void *context, int timeout); + int usb_reap_async_nocancel(void *context, int timeout); + int usb_cancel_async(void *context); + int usb_free_async(void **context); + + +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __USB_H__ */ +