cleanup
This commit is contained in:
@@ -15,7 +15,7 @@ extern "C" {
|
|||||||
#pragma warning( pop )
|
#pragma warning( pop )
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *GetUSBDevicePath (int num)
|
static CString GetUSBDevicePath (int num)
|
||||||
{
|
{
|
||||||
GUID guid;
|
GUID guid;
|
||||||
HidD_GetHidGuid(&guid);
|
HidD_GetHidGuid(&guid);
|
||||||
@@ -26,132 +26,191 @@ static char *GetUSBDevicePath (int num)
|
|||||||
SP_DEVICE_INTERFACE_DATA DeviceInterface;
|
SP_DEVICE_INTERFACE_DATA DeviceInterface;
|
||||||
DeviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
DeviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||||
|
|
||||||
char *ret = NULL;
|
|
||||||
PSP_INTERFACE_DEVICE_DETAIL_DATA DeviceDetail = NULL;
|
|
||||||
|
|
||||||
if (!SetupDiEnumDeviceInterfaces (DeviceInfo,
|
if (!SetupDiEnumDeviceInterfaces (DeviceInfo,
|
||||||
NULL, &guid, num, &DeviceInterface))
|
NULL, &guid, num, &DeviceInterface))
|
||||||
goto err;
|
{
|
||||||
|
SetupDiDestroyDeviceInfoList (DeviceInfo);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
SetupDiGetDeviceInterfaceDetail (DeviceInfo, &DeviceInterface, NULL, 0, &size, 0);
|
SetupDiGetDeviceInterfaceDetail (DeviceInfo, &DeviceInterface, NULL, 0, &size, 0);
|
||||||
|
|
||||||
DeviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(size);
|
PSP_INTERFACE_DEVICE_DETAIL_DATA DeviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(size);
|
||||||
DeviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
|
DeviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
|
||||||
|
|
||||||
|
CString ret;
|
||||||
if (SetupDiGetDeviceInterfaceDetail (DeviceInfo, &DeviceInterface,
|
if (SetupDiGetDeviceInterfaceDetail (DeviceInfo, &DeviceInterface,
|
||||||
DeviceDetail, size, &size, NULL))
|
DeviceDetail, size, &size, NULL))
|
||||||
{
|
ret = DeviceDetail->DevicePath;
|
||||||
ret = strdup(DeviceDetail->DevicePath);
|
free(DeviceDetail);
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
SetupDiDestroyDeviceInfoList (DeviceInfo);
|
||||||
SetupDiDestroyDeviceInfoList (DeviceInfo);
|
|
||||||
free (DeviceDetail);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HANDLE OpenUSB (int VID, int PID, int num)
|
|
||||||
|
bool USBDevice::Open(int VID, int PID, int blocksize, int num)
|
||||||
{
|
{
|
||||||
DWORD index = 0;
|
DWORD index = 0;
|
||||||
|
|
||||||
char *path;
|
CString path;
|
||||||
HANDLE h = INVALID_HANDLE_VALUE;
|
while ((path = GetUSBDevicePath (index++)) != "")
|
||||||
|
|
||||||
while ((path = GetUSBDevicePath (index++)) != NULL)
|
|
||||||
{
|
{
|
||||||
if(h != INVALID_HANDLE_VALUE)
|
HANDLE h = CreateFile (path, GENERIC_READ,
|
||||||
CloseHandle (h);
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
|
||||||
h = CreateFile (path, GENERIC_READ,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
||||||
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
if(h == INVALID_HANDLE_VALUE)
|
if(h == INVALID_HANDLE_VALUE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
HIDD_ATTRIBUTES attr;
|
HIDD_ATTRIBUTES attr;
|
||||||
if (!HidD_GetAttributes (h, &attr))
|
if (!HidD_GetAttributes (h, &attr))
|
||||||
|
{
|
||||||
|
CloseHandle(h);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
CloseHandle(h);
|
||||||
|
|
||||||
if ((VID != -1 && attr.VendorID != VID) &&
|
if ((VID != -1 && attr.VendorID != VID) &&
|
||||||
(PID != -1 && attr.ProductID != PID))
|
(PID != -1 && attr.ProductID != PID))
|
||||||
continue; /* This isn't it. */
|
continue; /* This isn't it. */
|
||||||
|
|
||||||
/* The VID and PID match. */
|
/* The VID and PID match. */
|
||||||
if(num-- == 0)
|
if(num-- > 0)
|
||||||
return h;
|
continue;
|
||||||
|
|
||||||
|
io.Open(path, blocksize);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if(h != INVALID_HANDLE_VALUE)
|
|
||||||
CloseHandle (h);
|
|
||||||
|
|
||||||
return INVALID_HANDLE_VALUE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
USBDevice::USBDevice()
|
bool USBDevice::IsOpen() const
|
||||||
{
|
{
|
||||||
ZeroMemory( &ov, sizeof(ov) );
|
return io.IsOpen();
|
||||||
pending=false;
|
|
||||||
h = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
USBDevice::~USBDevice()
|
|
||||||
{
|
|
||||||
if(h != INVALID_HANDLE_VALUE)
|
|
||||||
CloseHandle(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool USBDevice::Open(int VID, int PID, int num)
|
|
||||||
{
|
|
||||||
h = OpenUSB (VID, PID, num);
|
|
||||||
return h != INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool USBDevice::IsOpen()
|
|
||||||
{
|
|
||||||
return h != INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int USBDevice::GetPadEvent()
|
int USBDevice::GetPadEvent()
|
||||||
{
|
{
|
||||||
if(h == INVALID_HANDLE_VALUE)
|
if(!IsOpen())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int ret;
|
long buf;
|
||||||
|
if( io.read(&buf) <= 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
if(!pending)
|
return buf;
|
||||||
{
|
}
|
||||||
/* Request feedback from the device. */
|
|
||||||
unsigned long r;
|
WindowsFileIO::WindowsFileIO()
|
||||||
ret = ReadFile(h, &buf, sizeof(buf), &r, &ov);
|
{
|
||||||
pending=true;
|
ZeroMemory( &ov, sizeof(ov) );
|
||||||
|
h = INVALID_HANDLE_VALUE;
|
||||||
|
buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowsFileIO::~WindowsFileIO()
|
||||||
|
{
|
||||||
|
if(h != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(h);
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowsFileIO::Open(CString path, int blocksize_)
|
||||||
|
{
|
||||||
|
LOG->Trace( "WindowsFileIO::open(%s)", path.c_str() );
|
||||||
|
blocksize = blocksize_;
|
||||||
|
|
||||||
|
if(buf)
|
||||||
|
delete[] buf;
|
||||||
|
buf = new char[blocksize];
|
||||||
|
|
||||||
|
if(h != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle (h);
|
||||||
|
|
||||||
|
h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||||
|
|
||||||
|
if(h == INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
queue_read();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsFileIO::queue_read()
|
||||||
|
{
|
||||||
|
/* Request feedback from the device. */
|
||||||
|
unsigned long r;
|
||||||
|
ReadFile(h, buf, blocksize, &r, &ov);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WindowsFileIO::finish_read(void *p)
|
||||||
|
{
|
||||||
|
LOG->Trace("this %p, %p", this, p);
|
||||||
|
/* We do; get the result. It'll go into the original buf
|
||||||
|
* we supplied on the original call; that's why buf is a
|
||||||
|
* member instead of a local. */
|
||||||
|
unsigned long cnt;
|
||||||
|
int ret = GetOverlappedResult(h, &ov, &cnt, FALSE);
|
||||||
|
|
||||||
|
if(ret == 0 && (GetLastError() == ERROR_IO_PENDING || GetLastError() == ERROR_IO_INCOMPLETE))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
queue_read();
|
||||||
|
|
||||||
|
if(ret == 0)
|
||||||
|
{
|
||||||
|
LOG->Warn(werr_ssprintf(GetLastError(), "Error reading Pump pad"));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy( p, buf, cnt );
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WindowsFileIO::read(void *p)
|
||||||
|
{
|
||||||
|
LOG->Trace( "WindowsFileIO::read()" );
|
||||||
|
|
||||||
/* See if we have a response for our request (which we may
|
/* See if we have a response for our request (which we may
|
||||||
* have made on a previous call): */
|
* have made on a previous call): */
|
||||||
if(WaitForSingleObjectEx(h, 0, TRUE) == WAIT_TIMEOUT)
|
if(WaitForSingleObjectEx(h, 0, TRUE) == WAIT_TIMEOUT)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* We do; get the result. It'll go into the original &buf
|
return finish_read(p);
|
||||||
* we supplied on the original call; that's why buf is a
|
}
|
||||||
* member instead of a local. */
|
|
||||||
unsigned long cnt;
|
|
||||||
ret = GetOverlappedResult(h, &ov, &cnt, FALSE);
|
|
||||||
pending=false;
|
|
||||||
|
|
||||||
if(ret == 0 && (GetLastError() == ERROR_IO_PENDING || GetLastError() == ERROR_IO_INCOMPLETE))
|
int WindowsFileIO::read_several(const vector<WindowsFileIO *> &sources, void *p, int &actual, float timeout)
|
||||||
|
{
|
||||||
|
HANDLE *Handles = new HANDLE[sources.size()];
|
||||||
|
for( unsigned i = 0; i < sources.size(); ++i )
|
||||||
|
Handles[i] = sources[i]->h;
|
||||||
|
|
||||||
|
int ret = WaitForMultipleObjectsEx( sources.size(), Handles, false, int(timeout * 1000), true);
|
||||||
|
delete[] Handles;
|
||||||
|
|
||||||
|
if( ret == -1 )
|
||||||
|
{
|
||||||
|
LOG->Trace( werr_ssprintf(GetLastError(), "WaitForMultipleObjectsEx failed") );
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(ret == 0) {
|
if( ret >= int(WAIT_OBJECT_0) && ret < int(WAIT_OBJECT_0+sources.size()) )
|
||||||
// this prints too much info in Win98
|
{
|
||||||
// See if it's fixed--h should be INVALID_HANDLE_VALUE if
|
actual = ret - WAIT_OBJECT_0;
|
||||||
// the pad isn't there. -glenn
|
return sources[actual]->finish_read(p);
|
||||||
LOG->Warn(werr_ssprintf(GetLastError(), "Error reading Pump pad"));
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowsFileIO::IsOpen() const
|
||||||
|
{
|
||||||
|
return h != INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,20 +1,42 @@
|
|||||||
#ifndef WIN32_USB_H
|
#ifndef WIN32_USB_H
|
||||||
#define WIN32_USB_H
|
#define WIN32_USB_H
|
||||||
|
|
||||||
class USBDevice
|
#include <vector>
|
||||||
|
|
||||||
|
/* The API for Windows device I/O is obscenely horrible, so encapsulate it. */
|
||||||
|
class WindowsFileIO
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
USBDevice();
|
WindowsFileIO();
|
||||||
~USBDevice();
|
~WindowsFileIO();
|
||||||
int GetPadEvent();
|
bool Open(CString path, int blocksize);
|
||||||
bool Open(int VID, int PID, int num);
|
bool IsOpen() const;
|
||||||
bool IsOpen();
|
|
||||||
|
/* Returns the amount of data read. */
|
||||||
|
/* If nonblocking is true, this will */
|
||||||
|
/* Nonblocking read. size must always be the same. Returns the number of bytes
|
||||||
|
* read, or 0. */
|
||||||
|
int read(void *p);
|
||||||
|
static int read_several(const vector<WindowsFileIO *> &sources, void *p, int &actual, float timeout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
OVERLAPPED ov;
|
OVERLAPPED ov;
|
||||||
long buf;
|
char *buf;
|
||||||
bool pending;
|
int blocksize;
|
||||||
|
|
||||||
|
void queue_read();
|
||||||
|
int finish_read(void *p);
|
||||||
|
};
|
||||||
|
|
||||||
|
class USBDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int GetPadEvent();
|
||||||
|
bool Open(int VID, int PID, int blocksize, int num);
|
||||||
|
bool IsOpen() const;
|
||||||
|
|
||||||
|
WindowsFileIO io;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user