aboutsummaryrefslogtreecommitdiff
path: root/hidio_windows.c
diff options
context:
space:
mode:
authorOlaf Matthes <olafmatt@users.sourceforge.net>2007-01-03 11:07:20 +0000
committerOlaf Matthes <olafmatt@users.sourceforge.net>2007-01-03 11:07:20 +0000
commitc71b92fd92572f60914bb39fd485c4331aa8caf6 (patch)
tree3750a44180bcbcb6a00ae999597d58e1b50649f5 /hidio_windows.c
parente3b1733304a5d04daa137e93b86c65f95b65ca8a (diff)
more orless working Windows code, needs to be adapted to work with global element[][] array
svn path=/trunk/externals/io/hidio/; revision=7158
Diffstat (limited to 'hidio_windows.c')
-rw-r--r--hidio_windows.c1282
1 files changed, 828 insertions, 454 deletions
diff --git a/hidio_windows.c b/hidio_windows.c
index 25623e9..896422d 100644
--- a/hidio_windows.c
+++ b/hidio_windows.c
@@ -24,59 +24,59 @@
#include <windows.h>
#include <winbase.h>
#include <stdio.h>
-#include <setupapi.h>
-
-/*
- * Please note that this file needs the Microsoft Driver Developent Kit (DDK)
- * to be installed in order to compile!
- */
+#include <setupapi.h>
+
+/*
+ * Please note that this file needs the Microsoft Driver Developent Kit (DDK)
+ * to be installed in order to compile!
+ */
#ifdef _MSC_VER
#include <hidsdi.h>
#else
#include <ddk/hidsdi.h>
-#endif /* _MSC_VER */
+#endif /* _MSC_VER */
#include "hidio.h"
//#define DEBUG(x)
-#define DEBUG(x) x
-
-#define debug_print(d, p) post(p)
-
-typedef struct _hid_device_
-{
- HANDLE fh; /* file handle to the hid device */
- OVERLAPPED overlapped;
-
- PHIDP_PREPARSED_DATA ppd; // The opaque parser info describing this device
- HIDP_CAPS caps; // The Capabilities of this hid device.
- HIDD_ATTRIBUTES attributes;
- char *inputReportBuffer;
- unsigned long inputDataLength; // Num elements in this array.
- PHIDP_BUTTON_CAPS inputButtonCaps;
- PHIDP_VALUE_CAPS inputValueCaps;
-
- char *outputReportBuffer;
- unsigned long outputDataLength;
- PHIDP_BUTTON_CAPS outputButtonCaps;
- PHIDP_VALUE_CAPS outputValueCaps;
-
- char *featureReportBuffer;
- unsigned long featureDataLength;
- PHIDP_BUTTON_CAPS featureButtonCaps;
- PHIDP_VALUE_CAPS featureValueCaps;
-} t_hid_device;
+#define DEBUG(x) x
+
+#define debug_print(d, p) post(p)
+
+typedef struct _hid_device_
+{
+ HANDLE fh; /* file handle to the hid device */
+ OVERLAPPED overlapped;
+
+ PHIDP_PREPARSED_DATA ppd; // The opaque parser info describing this device
+ HIDP_CAPS caps; // The Capabilities of this hid device.
+ HIDD_ATTRIBUTES attributes;
+ char *inputReportBuffer;
+ unsigned long inputDataLength; // Num elements in this array.
+ PHIDP_BUTTON_CAPS inputButtonCaps;
+ PHIDP_VALUE_CAPS inputValueCaps;
+
+ char *outputReportBuffer;
+ unsigned long outputDataLength;
+ PHIDP_BUTTON_CAPS outputButtonCaps;
+ PHIDP_VALUE_CAPS outputValueCaps;
+
+ char *featureReportBuffer;
+ unsigned long featureDataLength;
+ PHIDP_BUTTON_CAPS featureButtonCaps;
+ PHIDP_VALUE_CAPS featureValueCaps;
+} t_hid_device;
/*==============================================================================
* GLOBAL VARS
*======================================================================== */
-extern t_int hidio_instance_count; // in hidio.h
-
-/* store device pointers so I don't have to query them all the time */
-// t_hid_devinfo device_pointer[MAX_DEVICES];
+extern t_int hidio_instance_count; // in hidio.h
+
+/* store device pointers so I don't have to query them all the time */
+// t_hid_devinfo device_pointer[MAX_DEVICES];
/*==============================================================================
* FUNCTION PROTOTYPES
@@ -89,293 +89,628 @@ extern t_int hidio_instance_count; // in hidio.h
*==============================================================================
*/
-/* ============================================================================== */
-/* WINDOWS DDK HID SPECIFIC REALLY LOW-LEVEL STUFF */
-/* ============================================================================== */
-
-/* count devices by looking into the registry */
-short _hid_count_devices(void)
-{
- short i, gNumDevices = 0;
- long ret;
-
- HKEY hKey;
- long DeviceNameLen, KeyNameLen;
- char KeyName[MAXPDSTRING];
- char DeviceName[MAXPDSTRING];
-
- /* Search in Windows Registry for enumerated HID devices */
- if ((ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\hidusb\\Enum", 0, KEY_QUERY_VALUE, &hKey)) != ERROR_SUCCESS)
- {
- error("hidio: failed to get list of HID devices from registry");
- return -1;
- }
-
- for (i = 0; i < MAX_DEVICES + 3; i++) /* there are three entries that are no devices */
- {
- DeviceNameLen = 80;
- KeyNameLen = 100;
- ret = RegEnumValue(hKey, i, KeyName, &KeyNameLen, NULL, NULL, DeviceName, &DeviceNameLen);
- if (ret == ERROR_SUCCESS)
- {
- if (!strncmp(KeyName, "Count", 5))
- {
- /* this is the number of devices as HEX DWORD */
- continue;
- }
- else if (!strncmp(DeviceName, "USB\\Vid", 7))
- {
- /* we found a device, DeviceName contains the path */
- // post("device #%d: %s = %s", gNumDevices, KeyName, DeviceName);
- gNumDevices++;
- continue;
- }
- }
- else if (ret == ERROR_NO_MORE_ITEMS) /* no more entries in registry */
- {
- break;
- }
- else /* any other error while looking into registry */
- {
- char errbuf[MAXPDSTRING];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ret, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- errbuf, MAXPDSTRING, NULL);
- error("hidio: $s", errbuf);
- break;
- }
- }
- RegCloseKey(hKey);
- return gNumDevices; /* return number of devices */
-}
-
-/* get device path for a HID specified by number */
-static short _hid_get_device_path(short device_number, char **path, short length)
-{
- GUID guid;
- HDEVINFO DeviceInfo;
- SP_DEVICE_INTERFACE_DATA DeviceInterface;
- PSP_INTERFACE_DEVICE_DETAIL_DATA DeviceDetail;
- unsigned long iSize;
-
- HidD_GetHidGuid(&guid);
-
- DeviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
-
- DeviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-
- if (!SetupDiEnumDeviceInterfaces(DeviceInfo, NULL, &guid, device_number, &DeviceInterface))
- {
- SetupDiDestroyDeviceInfoList(DeviceInfo);
- return -1;
- }
-
- SetupDiGetDeviceInterfaceDetail( DeviceInfo, &DeviceInterface, NULL, 0, &iSize, 0 );
-
- DeviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(iSize);
- DeviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
-
- if (SetupDiGetDeviceInterfaceDetail(DeviceInfo, &DeviceInterface, DeviceDetail, iSize, &iSize, NULL))
- {
- if (!*path && !length) /* we got no memory passed in, allocate some */
- { /* WARNING: caller has to free this memory!! */
- *path = (char *)getbytes((short)(strlen(DeviceDetail->DevicePath) * sizeof(char)));
- }
- /* copy path */
- strcpy(*path, DeviceDetail->DevicePath);
- }
- free(DeviceDetail);
-
- SetupDiDestroyDeviceInfoList(DeviceInfo);
- return 0;
-}
-
-
-/* get capabilities (usage page & usage ID) of an already opened device */
-static short _hid_get_capabilities(HANDLE fd, HIDP_CAPS *capabilities)
-{
- PHIDP_PREPARSED_DATA preparsedData;
-
- if (fd == INVALID_HANDLE_VALUE)
- {
- error("hidio: couldn't get device capabilities due to an invalid handle");
- return -1;
- }
-
- /* returns and allocates a buffer with device info */
- HidD_GetPreparsedData(fd, &preparsedData);
-
- /* get capabilities of device from above buffer */
- HidP_GetCaps(preparsedData, capabilities);
-
- /* no need for PreparsedData any more, so free the memory it's using */
- HidD_FreePreparsedData(preparsedData);
- return 0;
-}
-
+/* ============================================================================== */
+/* WINDOWS DDK HID SPECIFIC REALLY LOW-LEVEL STUFF */
+/* ============================================================================== */
+/*
+ * connect to Ith USB device (count starting with 0)
+ */
+
+static HANDLE connectDeviceNumber(DWORD deviceIndex)
+{
+ GUID hidGUID;
+ HDEVINFO hardwareDeviceInfoSet;
+ SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
+ PSP_INTERFACE_DEVICE_DETAIL_DATA deviceDetail;
+ ULONG requiredSize;
+ HANDLE deviceHandle = INVALID_HANDLE_VALUE;
+ DWORD result;
+
+ //Get the HID GUID value - used as mask to get list of devices
+ HidD_GetHidGuid (&hidGUID);
+
+ //Get a list of devices matching the criteria (hid interface, present)
+ hardwareDeviceInfoSet = SetupDiGetClassDevs (&hidGUID,
+ NULL, // Define no enumerator (global)
+ NULL, // Define no
+ (DIGCF_PRESENT | // Only Devices present
+ DIGCF_DEVICEINTERFACE)); // Function class devices.
+
+ deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ //Go through the list and get the interface data
+ result = SetupDiEnumDeviceInterfaces (hardwareDeviceInfoSet,
+ NULL, //infoData,
+ &hidGUID, //interfaceClassGuid,
+ deviceIndex,
+ &deviceInterfaceData);
+
+ /* Failed to get a device - possibly the index is larger than the number of devices */
+ if (result == FALSE)
+ {
+ SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet);
+ error("%s: failed to get specified device number", CLASS_NAME);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ //Get the details with null values to get the required size of the buffer
+ SetupDiGetDeviceInterfaceDetail (hardwareDeviceInfoSet,
+ &deviceInterfaceData,
+ NULL, //interfaceDetail,
+ 0, //interfaceDetailSize,
+ &requiredSize,
+ 0); //infoData))
+
+ //Allocate the buffer
+ deviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(requiredSize);
+ deviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
+
+ //Fill the buffer with the device details
+ if (!SetupDiGetDeviceInterfaceDetail (hardwareDeviceInfoSet,
+ &deviceInterfaceData,
+ deviceDetail,
+ requiredSize,
+ &requiredSize,
+ NULL))
+ {
+ SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet);
+ free (deviceDetail);
+ error("%s: failed to get device info", CLASS_NAME);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ /* Open file on the device (read & write) */
+ deviceHandle = CreateFile
+ (deviceDetail->DevicePath,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL);
+
+ if (deviceHandle == INVALID_HANDLE_VALUE)
+ {
+ int err = GetLastError();
+ LPVOID lpMsgBuf;
+ if (err == ERROR_ACCESS_DENIED)
+ {
+ /* error("%s: can not read from mouse and keyboard", CLASS_NAME); */
+ return INVALID_HANDLE_VALUE;
+ }
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
+ error("%s: could not get device #%i: %s (%d)", CLASS_NAME, deviceIndex + 1, (LPCTSTR)lpMsgBuf, err);
+ LocalFree(lpMsgBuf);
+ }
+
+ SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet);
+ free (deviceDetail);
+ return deviceHandle;
+}
+
+static long _hidio_read(t_hid_device *self)
+{
+ unsigned long ret, err = 0;
+ long bytes = 0;
+
+ if (!ReadFile(self->fh, self->inputReportBuffer, self->caps.InputReportByteLength, &bytes, (LPOVERLAPPED)&self->overlapped))
+ {
+ if (ERROR_IO_PENDING != (err = GetLastError()))
+ {
+ LPVOID lpMsgBuf;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
+ error("%s: read: %s", CLASS_NAME, (LPCTSTR)lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ return -1;
+ }
+ }
+
+ ret = WaitForSingleObject(self->overlapped.hEvent, 0);
+
+ if (ret == WAIT_OBJECT_0) /* hey, we got signalled ! => data */
+ {
+ return bytes;
+ }
+ else /* if no data, cancel read */
+ {
+ if (!CancelIo(self->fh) && (self->fh != INVALID_HANDLE_VALUE))
+ return -1; /* CancelIo() failed */
+ }
+ if (!ResetEvent(self->overlapped.hEvent))
+ return -1; /* ResetEvent() failed */
+
+ return bytes;
+}
+
+/* count devices by looking into the registry */
+short _hid_count_devices(void)
+{
+ short i, gNumDevices = 0;
+ long ret;
+
+ HKEY hKey;
+ long DeviceNameLen, KeyNameLen;
+ char KeyName[MAXPDSTRING];
+ char DeviceName[MAXPDSTRING];
+
+ /* Search in Windows Registry for enumerated HID devices */
+ if ((ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\hidusb\\Enum", 0, KEY_QUERY_VALUE, &hKey)) != ERROR_SUCCESS)
+ {
+ error("hidio: failed to get list of HID devices from registry");
+ return EXIT_FAILURE;
+ }
+
+ for (i = 0; i < MAX_DEVICES + 3; i++) /* there are three entries that are no devices */
+ {
+ DeviceNameLen = 80;
+ KeyNameLen = 100;
+ ret = RegEnumValue(hKey, i, KeyName, &KeyNameLen, NULL, NULL, DeviceName, &DeviceNameLen);
+ if (ret == ERROR_SUCCESS)
+ {
+ if (!strncmp(KeyName, "Count", 5))
+ {
+ /* this is the number of devices as HEX DWORD */
+ continue;
+ }
+ else if (!strncmp(DeviceName, "USB\\Vid", 7))
+ {
+ /* we found a device, DeviceName contains the path */
+ // post("device #%d: %s = %s", gNumDevices, KeyName, DeviceName);
+ gNumDevices++;
+ continue;
+ }
+ }
+ else if (ret == ERROR_NO_MORE_ITEMS) /* no more entries in registry */
+ {
+ break;
+ }
+ else /* any other error while looking into registry */
+ {
+ char errbuf[MAXPDSTRING];
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ret, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ errbuf, MAXPDSTRING, NULL);
+ error("hidio: $s", errbuf);
+ break;
+ }
+ }
+ RegCloseKey(hKey);
+ return gNumDevices; /* return number of devices */
+}
+
+/* get device path for a HID specified by number */
+static short _hid_get_device_path(short device_number, char **path, short length)
+{
+ GUID guid;
+ HDEVINFO DeviceInfo;
+ SP_DEVICE_INTERFACE_DATA DeviceInterface;
+ PSP_INTERFACE_DEVICE_DETAIL_DATA DeviceDetail;
+ unsigned long iSize;
+
+ HidD_GetHidGuid(&guid);
+
+ DeviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+
+ DeviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ if (!SetupDiEnumDeviceInterfaces(DeviceInfo, NULL, &guid, device_number, &DeviceInterface))
+ {
+ SetupDiDestroyDeviceInfoList(DeviceInfo);
+ return EXIT_FAILURE;
+ }
+
+ SetupDiGetDeviceInterfaceDetail( DeviceInfo, &DeviceInterface, NULL, 0, &iSize, 0 );
+
+ DeviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(iSize);
+ DeviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
+
+ if (SetupDiGetDeviceInterfaceDetail(DeviceInfo, &DeviceInterface, DeviceDetail, iSize, &iSize, NULL))
+ {
+ if (!*path && !length) /* we got no memory passed in, allocate some */
+ { /* WARNING: caller has to free this memory!! */
+ *path = (char *)getbytes((short)(strlen(DeviceDetail->DevicePath) * sizeof(char)));
+ }
+ /* copy path */
+ strcpy(*path, DeviceDetail->DevicePath);
+ }
+ free(DeviceDetail);
+
+ SetupDiDestroyDeviceInfoList(DeviceInfo);
+ return 0;
+}
+
+
+/* get capabilities (usage page & usage ID) of an already opened device */
+static short _hid_get_capabilities(HANDLE fd, HIDP_CAPS *capabilities)
+{
+ PHIDP_PREPARSED_DATA preparsedData;
+
+ if (fd == INVALID_HANDLE_VALUE)
+ {
+ error("hidio: couldn't get device capabilities due to an invalid handle");
+ return EXIT_FAILURE;
+ }
+
+ /* returns and allocates a buffer with device info */
+ HidD_GetPreparsedData(fd, &preparsedData);
+
+ /* get capabilities of device from above buffer */
+ HidP_GetCaps(preparsedData, capabilities);
+
+ /* no need for PreparsedData any more, so free the memory it's using */
+ HidD_FreePreparsedData(preparsedData);
+ return 0;
+}
+
/* ============================================================================== */
/* WINDOWS DDK HID SPECIFIC SUPPORT FUNCTIONS */
/* ============================================================================== */
-short get_device_number_by_id(unsigned short vendor_id, unsigned short product_id)
+short get_device_number_by_id(unsigned short vendor_id, unsigned short product_id)
+{
+ return EXIT_FAILURE;
+}
+
+short get_device_number_from_usage(short device_number,
+ unsigned short usage_page,
+ unsigned short usage)
+{
+ HANDLE fd = INVALID_HANDLE_VALUE;
+ HIDP_CAPS capabilities;
+ char path[MAX_PATH];
+ char *pp = (char *)path;
+ short ret, i;
+ short device_count = _hid_count_devices();
+
+ for (i = device_number; i < device_count; i++)
+ {
+ /* get path for specified device number */
+ ret = _hid_get_device_path(i, &pp, MAX_PATH);
+ if (ret == -1)
+ {
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ /* open file on the device (read & write, no overlapp) */
+ fd = CreateFile(path,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (fd == INVALID_HANDLE_VALUE)
+ {
+ return EXIT_FAILURE;
+ }
+
+ /* get the capabilities */
+ _hid_get_capabilities(fd, &capabilities);
+
+ /* check whether they match with what we want */
+ if (capabilities.UsagePage == usage_page && capabilities.Usage == usage)
+ {
+ CloseHandle(fd);
+ return i;
+ }
+ CloseHandle(fd);
+ }
+ }
+ return EXIT_FAILURE;
+}
+
+
+/*
+ * This function is needed to translate the USB HID relative flag into the
+ * [hidio]/linux style events
+ */
+static void convert_axis_to_symbols(t_hid_element *new_element, int array_index)
+{
+ if (new_element->relative)
+ {
+ new_element->type = ps_relative;
+ new_element->name = relative_symbols[array_index];
+ }
+ else
+ {
+ new_element->type = ps_absolute;
+ new_element->name = absolute_symbols[array_index];
+ }
+}
+
+static void get_usage_symbols(unsigned short usage_page, unsigned short usage, t_hid_element *new_element)
+{
+ char buffer[MAXPDSTRING];
+
+ switch (usage_page)
+ {
+ case HID_USAGE_PAGE_GENERIC:
+ switch (usage)
+ {
+ case HID_USAGE_GENERIC_X: convert_axis_to_symbols(new_element, 0); break;
+ case HID_USAGE_GENERIC_Y: convert_axis_to_symbols(new_element, 1); break;
+ case HID_USAGE_GENERIC_Z: convert_axis_to_symbols(new_element, 2); break;
+ case HID_USAGE_GENERIC_RX: convert_axis_to_symbols(new_element, 3); break;
+ case HID_USAGE_GENERIC_RY: convert_axis_to_symbols(new_element, 4); break;
+ case HID_USAGE_GENERIC_RZ: convert_axis_to_symbols(new_element, 5); break;
+ case HID_USAGE_GENERIC_SLIDER: convert_axis_to_symbols(new_element, 6); break;
+ case HID_USAGE_GENERIC_DIAL: convert_axis_to_symbols(new_element, 7); break;
+ case HID_USAGE_GENERIC_WHEEL: convert_axis_to_symbols(new_element, 8); break;
+ case HID_USAGE_GENERIC_HATSWITCH:
+ // TODO: this is still a mystery how to handle, due to USB HID vs. Linux input.h
+ new_element->type = ps_absolute;
+ new_element->name = absolute_symbols[9]; /* hatswitch */
+ break;
+ default:
+ new_element->type = gensym("DESKTOP");
+ snprintf(buffer, sizeof(buffer), "DESKTOP%ld", usage);
+ new_element->name = gensym(buffer);
+ }
+ break;
+ case HID_USAGE_PAGE_SIMULATION:
+ switch (usage)
+ {
+ case HID_USAGE_SIMULATION_RUDDER:
+ new_element->type = ps_absolute;
+ new_element->name = absolute_symbols[5]; /* rz */
+ break;
+ case HID_USAGE_SIMULATION_THROTTLE:
+ new_element->type = ps_absolute;
+ new_element->name = absolute_symbols[6]; /* slider */
+ break;
+ default:
+ new_element->type = gensym("SIMULATION");
+ snprintf(buffer, sizeof(buffer), "SIMULATION%ld", usage);
+ new_element->name = gensym(buffer);
+ }
+ break;
+ case HID_USAGE_PAGE_KEYBOARD:
+ new_element->type = ps_key;
+ if( (usage > -1) &&
+ (usage < KEY_ARRAY_MAX) )
+ new_element->name = key_symbols[usage];
+ else /* PowerBook ADB keyboard reports 0xffffffff */
+ new_element->name = key_symbols[0];
+ break;
+ case HID_USAGE_PAGE_BUTTON:
+ new_element->type = ps_button;
+ new_element->name = button_symbols[usage];
+ break;
+ case HID_USAGE_PAGE_LED:
+ new_element->type = ps_led;
+ new_element->name = led_symbols[usage];
+ break;
+ case HID_USAGE_PAGE_DIGITIZER: /* no sure whether this is the right for PID in OS X */
+ new_element->type = ps_pid;
+ new_element->name = pid_symbols[usage];
+ break;
+ default:
+ /* the rest are "vendor defined" so no translation table is possible */
+ snprintf(buffer, sizeof(buffer), "0x%04x", (unsigned int) usage_page);
+ new_element->type = gensym(buffer);
+ snprintf(buffer, sizeof(buffer), "0x%04x", (unsigned int) usage);
+ new_element->name = gensym(buffer);
+ }
+}
+
+static void hidio_build_element_list(t_hidio *x)
{
- return -1;
-}
-
-short get_device_number_from_usage(short device_number,
- unsigned short usage_page,
- unsigned short usage)
-{
- HANDLE fd = INVALID_HANDLE_VALUE;
- HIDP_CAPS capabilities;
- char path[MAX_PATH];
- char *pp = (char *)path;
- short ret, i;
- short device_count = _hid_count_devices();
-
- for (i = device_number; i < device_count; i++)
- {
- /* get path for specified device number */
- ret = _hid_get_device_path(i, &pp, MAX_PATH);
- if (ret == -1)
- {
- return -1;
- }
- else
- {
- /* open file on the device (read & write, no overlapp) */
- fd = CreateFile(path,
- GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- (LPSECURITY_ATTRIBUTES)NULL,
- OPEN_EXISTING,
- 0,
- NULL);
- if (fd == INVALID_HANDLE_VALUE)
- {
- return -1;
- }
-
- /* get the capabilities */
- _hid_get_capabilities(fd, &capabilities);
-
- /* check whether they match with what we want */
- if (capabilities.UsagePage == usage_page && capabilities.Usage == usage)
- {
- CloseHandle(fd);
- return i;
- }
- CloseHandle(fd);
- }
- }
- return -1;
-}
-
-
-void hidio_build_element_list(t_hidio *x)
-{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
- char type_name[256];
- char usage_name[256];
-
- t_hid_element *current_element;
- t_hid_element *new_element = NULL;
- HIDP_CAPS capabilities;
- short i;
-
- element_count[x->x_device_number] = 0;
- if (self->fh != INVALID_HANDLE_VALUE)
- {
- /* now get device capabilities */
- _hid_get_capabilities(self->fh, &capabilities);
-
- /* for every possible element check what we got */
- for (i = 0; i < capabilities.NumberInputDataIndices; i++)
- {
-#if 0
- for (j = 0; j < capabilities.NumberInputButtonCaps; j++)
- {
- new_element = getbytes(sizeof(t_hid_element));
- if ((i == EV_ABS) && (test_bit(j, abs_bitmask)))
- {
- /* this means that the bit is set in the axes list */
- if(ioctl(self->fh, EVIOCGABS(j), &abs_features))
- perror("evdev EVIOCGABS ioctl");
- new_element->min = abs_features.minimum;
- new_element->max = abs_features.maximum;
- }
- else
- {
- new_element->min = 0;
- new_element->max = 0;
- }
- if(test_bit(j, element_bitmask[i]))
- {
- new_element->linux_type = i; /* the int from linux/input.h */
- new_element->type = gensym(ev[i] ? ev[i] : "?"); /* the symbol */
- new_element->linux_code = j;
- if((i == EV_KEY) && (j >= BTN_MISC) && (j < KEY_OK) )
- {
- new_element->name = hidio_convert_linux_buttons_to_numbers(j);
- }
- else
- {
- new_element->name = gensym(event_names[i][j] ? event_names[i][j] : "?");
- }
- if( i == EV_REL )
- new_element->relative = 1;
- else
- new_element->relative = 0;
-
- /* fill in the t_hid_element struct here */
- post("x->x_device_number: %d element_count[]: %d",
- x->x_device_number, element_count[x->x_device_number]);
- post("usage_page/usage_id: %d/%d type/name: %s/%s max: %d min: %d ",
- new_element->usage_page, new_element->usage_id,
- new_element->type->s_name, new_element->name->s_name,
- new_element->max, new_element->min);
- post("\tpolled: %d relative: %d",
- new_element->polled, new_element->relative);
- element[x->x_device_number][element_count[x->x_device_number]] = new_element;
- ++element_count[x->x_device_number];
- }
- }
- }
-#endif
- }
- }
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+
+ t_hid_element *new_element = NULL;
+ unsigned short numButtons = 0;
+ unsigned short numValues = 0;
+ unsigned short numelem; /* total number of elements */
+ unsigned short numCaps;
+ unsigned long i;
+ PHIDP_BUTTON_CAPS buttonCaps;
+ PHIDP_VALUE_CAPS valueCaps;
+ USAGE usage;
+
+ element_count[x->x_device_number] = 0;
+ if (self->fh != INVALID_HANDLE_VALUE)
+ {
+ /* now get device capabilities */
+ HidD_GetPreparsedData(self->fh, &self->ppd);
+ HidP_GetCaps(self->ppd, &self->caps);
+
+ /* allocate memory for input and output reports */
+ /* these buffers get used for sending and receiving */
+ self->inputReportBuffer = (char *)getbytes((short)(self->caps.InputReportByteLength * sizeof(char)));
+ self->outputReportBuffer = (char *)getbytes((short)(self->caps.OutputReportByteLength * sizeof(char)));
+ self->featureReportBuffer = (char *)getbytes((short)(self->caps.FeatureReportByteLength * sizeof(char)));
+
+ /* allocate memory for input info */
+ self->inputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS)getbytes((short)(self->caps.NumberInputButtonCaps * sizeof(HIDP_BUTTON_CAPS)));
+ self->inputValueCaps = valueCaps = (PHIDP_VALUE_CAPS)getbytes((short)(self->caps.NumberInputValueCaps * sizeof(HIDP_VALUE_CAPS)));
+
+
+ /* get capapbilities for buttons and values from device */
+ numCaps = self->caps.NumberInputButtonCaps;
+ HidP_GetButtonCaps (HidP_Input,
+ buttonCaps,
+ &numCaps,
+ self->ppd);
+
+ numCaps = self->caps.NumberInputValueCaps;
+ HidP_GetValueCaps (HidP_Input,
+ valueCaps,
+ &numCaps,
+ self->ppd);
+
+ /* number of elements is number of values (axes) plus number of buttons */
+#if 1
+ for (i = 0; i < self->caps.NumberInputValueCaps; i++, valueCaps++)
+ {
+ if (valueCaps->IsRange)
+ numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1;
+ else
+ numValues++;
+ }
+ for (i = 0; i < self->caps.NumberInputButtonCaps; i++, buttonCaps++)
+ {
+ if (buttonCaps->IsRange)
+ numButtons += buttonCaps->Range.UsageMax - buttonCaps->Range.UsageMin + 1;
+ else
+ numButtons++;
+ }
+ numelem = numValues + numButtons;
+
+ valueCaps = self->inputValueCaps;
+ buttonCaps = self->inputButtonCaps;
+#else
+ /* maybe this could be done as well? works with my gamepad at least */
+ numelem = HidP_MaxDataListLength(HidP_Input, self->ppd);
+ + HidP_MaxUsageListLength(HidP_Input, 0, self->ppd);
+#endif
+
+ /* now look through the reported capabilities of the devcie and fill in the elements struct */
+ for (i = 0; i < self->caps.NumberInputButtonCaps; i++, buttonCaps++)
+ {
+ if (buttonCaps->IsRange)
+ {
+ for (usage = buttonCaps->Range.UsageMin; usage <= buttonCaps->Range.UsageMax; usage++)
+ {
+ new_element = getbytes(sizeof(t_hid_element));
+ new_element->usage_page = buttonCaps->UsagePage;
+ new_element->usage_id = usage;
+ new_element->relative = !buttonCaps->IsAbsolute; /* buttons always are absolute, no? */
+ new_element->min = 0;
+ new_element->max = 1;
+ new_element->instance = 0;
+
+ get_usage_symbols(new_element->usage_page, new_element->usage_id, new_element);
+#ifdef PD
+ SETSYMBOL(new_element->output_message, new_element->name);
+ SETFLOAT(new_element->output_message + 1, new_element->instance);
+#else /* Max */
+ atom_setsym(new_element->output_message, new_element->name);
+ atom_setlong(new_element->output_message + 1, (long)new_element->instance);
+#endif /* PD */
+ element[x->x_device_number][element_count[x->x_device_number]] = new_element;
+ ++element_count[x->x_device_number];
+ }
+ }
+ else
+ {
+ new_element = getbytes(sizeof(t_hid_element));
+ new_element->usage_page = buttonCaps->UsagePage;
+ new_element->usage_id = buttonCaps->NotRange.Usage;
+ new_element->relative = !buttonCaps->IsAbsolute; /* buttons always are absolute, no? */
+ new_element->min = 0;
+ new_element->max = 1;
+ new_element->instance = 0;
+
+ get_usage_symbols(new_element->usage_page, new_element->usage_id, new_element);
+#ifdef PD
+ SETSYMBOL(new_element->output_message, new_element->name);
+ SETFLOAT(new_element->output_message + 1, new_element->instance);
+#else /* Max */
+ atom_setsym(new_element->output_message, new_element->name);
+ atom_setlong(new_element->output_message + 1, (long)new_element->instance);
+#endif /* PD */
+ element[x->x_device_number][element_count[x->x_device_number]] = new_element;
+ ++element_count[x->x_device_number];
+ }
+ }
+ /* get value data */
+ for (i = 0; i < numValues; i++, valueCaps++)
+ {
+ if (valueCaps->IsRange)
+ {
+ for (usage = valueCaps->Range.UsageMin; usage <= valueCaps->Range.UsageMax; usage++)
+ {
+ new_element = getbytes(sizeof(t_hid_element));
+ new_element->usage_page = valueCaps->UsagePage;
+ new_element->usage_id = usage;
+ new_element->relative = !valueCaps->IsAbsolute;
+ new_element->min = valueCaps->LogicalMin;
+ new_element->max = valueCaps->LogicalMax;
+ new_element->instance = 0;
+
+ get_usage_symbols(new_element->usage_page, new_element->usage_id, new_element);
+#ifdef PD
+ SETSYMBOL(new_element->output_message, new_element->name);
+ SETFLOAT(new_element->output_message + 1, new_element->instance);
+#else /* Max */
+ atom_setsym(new_element->output_message, new_element->name);
+ atom_setlong(new_element->output_message + 1, (long)new_element->instance);
+#endif /* PD */
+ element[x->x_device_number][element_count[x->x_device_number]] = new_element;
+ ++element_count[x->x_device_number];
+ }
+ }
+ else
+ {
+ new_element = getbytes(sizeof(t_hid_element));
+ new_element->usage_page = valueCaps->UsagePage;
+ new_element->usage_id = valueCaps->NotRange.Usage;
+ new_element->relative = !valueCaps->IsAbsolute;
+ new_element->min = valueCaps->LogicalMin;
+ new_element->max = valueCaps->LogicalMax;
+ new_element->instance = 0;
+
+ get_usage_symbols(new_element->usage_page, new_element->usage_id, new_element);
+#ifdef PD
+ SETSYMBOL(new_element->output_message, new_element->name);
+ SETFLOAT(new_element->output_message + 1, new_element->instance);
+#else /* Max */
+ atom_setsym(new_element->output_message, new_element->name);
+ atom_setlong(new_element->output_message + 1, (long)new_element->instance);
+#endif /* PD */
+ element[x->x_device_number][element_count[x->x_device_number]] = new_element;
+ ++element_count[x->x_device_number];
+ }
+ }
+ }
}
t_int hidio_print_element_list(t_hidio *x)
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
-
- debug_print(LOG_DEBUG,"hidio_print_element_list");
-
- return (0);
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_element *current_element;
+ int i;
+
+ debug_print(LOG_DEBUG,"hidio_print_element_list");
+
+ post("[hidio] found %d elements:", element_count[x->x_device_number]);
+ post("\n TYPE\tCODE\t#\tEVENT NAME");
+ post("-----------------------------------------------------------");
+ for (i = 0; i < element_count[x->x_device_number]; i++)
+ {
+ current_element = element[x->x_device_number][i];
+ post(" %s\t%s\t%d", current_element->type->s_name,
+ current_element->name->s_name,(int) current_element->instance);
+ }
+ post("");
+
+ return EXIT_SUCCESS;
}
t_int hidio_print_device_list(t_hidio *x)
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
struct _GUID GUID;
SP_INTERFACE_DEVICE_DATA DeviceInterfaceData;
- struct
- {
- DWORD cbSize;
- char DevicePath[MAX_PATH];
+ struct
+ {
+ DWORD cbSize;
+ char DevicePath[MAX_PATH];
} FunctionClassDeviceData;
HIDD_ATTRIBUTES HIDAttributes;
SECURITY_ATTRIBUTES SecurityAttributes;
int i;
HANDLE PnPHandle, HIDHandle;
ULONG BytesReturned;
- int Success, ManufacturerName, ProductName;
+ int Success, ManufacturerName, ProductName;
PWCHAR widestring[MAXPDSTRING];
char ManufacturerBuffer[MAXPDSTRING];
char ProductBuffer[MAXPDSTRING];
const char NotSupplied[] = "NULL";
- DWORD lastError = 0;
+ DWORD lastError = 0;
/* Initialize the GUID array and setup the security attributes for Win2000 */
HidD_GetHidGuid(&GUID);
@@ -392,18 +727,18 @@ t_int hidio_print_device_list(t_hidio *x)
error("[hidio] ERROR: Could not attach to PnP node");
return (t_int) GetLastError();
}
-
- post("");
+
+ post("");
/* Lets look for a maximum of 32 Devices */
- for (i = 0; i < MAX_DEVICES; i++)
+ for (i = 0; i < MAX_DEVICES; i++)
{
/* Initialize our data */
DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
/* Is there a device at this table entry */
Success = SetupDiEnumDeviceInterfaces(PnPHandle, NULL, &GUID, i,
&DeviceInterfaceData);
- if (Success)
+ if (Success)
{
/* There is a device here, get it's name */
FunctionClassDeviceData.cbSize = 5;
@@ -416,7 +751,7 @@ t_int hidio_print_device_list(t_hidio *x)
error("[hidio] ERROR: Could not find the system name for device %d",i);
return GetLastError();
}
- /* Can now open this device */
+ /* Can now open this device */
HIDHandle = CreateFile(FunctionClassDeviceData.DevicePath,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
@@ -436,31 +771,31 @@ t_int hidio_print_device_list(t_hidio *x)
return GetLastError();
}
ManufacturerName = HidD_GetManufacturerString(HIDHandle, widestring, MAXPDSTRING);
- wcstombs(ManufacturerBuffer, (const unsigned short *)widestring, MAXPDSTRING);
- ProductName = HidD_GetProductString(HIDHandle, widestring, MAXPDSTRING);
- wcstombs(ProductBuffer, (const unsigned short *)widestring, MAXPDSTRING);
+ wcstombs(ManufacturerBuffer, (const unsigned short *)widestring, MAXPDSTRING);
+ ProductName = HidD_GetProductString(HIDHandle, widestring, MAXPDSTRING);
+ wcstombs(ProductBuffer, (const unsigned short *)widestring, MAXPDSTRING);
/* And display it! */
- post("__________________________________________________");
- post("Device %d: '%s' '%s' version %d", i,
- ManufacturerName ? ManufacturerBuffer : NotSupplied, ProductName ? ProductBuffer : NotSupplied,
- HIDAttributes.VersionNumber);
- post(" vendorID: 0x%04x productID: 0x%04x",
- HIDAttributes.VendorID, HIDAttributes.ProductID);
-
+ post("__________________________________________________");
+ post("Device %d: '%s' '%s' version %d", i,
+ ManufacturerName ? ManufacturerBuffer : NotSupplied, ProductName ? ProductBuffer : NotSupplied,
+ HIDAttributes.VersionNumber);
+ post(" vendorID: 0x%04x productID: 0x%04x",
+ HIDAttributes.VendorID, HIDAttributes.ProductID);
+
CloseHandle(HIDHandle);
} // if (SetupDiEnumDeviceInterfaces . .
} // for (i = 0; i < 32; i++)
- SetupDiDestroyDeviceInfoList(PnPHandle);
-
+ SetupDiDestroyDeviceInfoList(PnPHandle);
+
post("");
-
- return 0;
+
+ return EXIT_SUCCESS;
}
void hidio_output_device_name(t_hidio *x, char *manufacturer, char *product)
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
char *device_name;
t_symbol *device_name_symbol;
@@ -470,11 +805,11 @@ void hidio_output_device_name(t_hidio *x, char *manufacturer, char *product)
strcat( device_name, manufacturer );
strcat ( device_name, " ");
strcat( device_name, product );
-// outlet_anything( x->x_status_outlet, gensym( device_name ),0,NULL );
+// outlet_anything( x->x_status_outlet, gensym( device_name ),0,NULL );
#ifdef PD
- outlet_symbol( x->x_status_outlet, gensym( device_name ) );
-#else
- outlet_anything( x->x_status_outlet, gensym( device_name ),0,NULL );
+ outlet_symbol( x->x_status_outlet, gensym( device_name ) );
+#else
+ outlet_anything( x->x_status_outlet, gensym( device_name ),0,NULL );
#endif
}
@@ -483,183 +818,222 @@ void hidio_output_device_name(t_hidio *x, char *manufacturer, char *product)
/* ------------------------------------------------------------------------------ */
/* cross-platform force feedback functions */
-void hidio_ff_autocenter( t_hidio *x, t_float value )
+t_int hidio_ff_autocenter( t_hidio *x, t_float value )
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ return EXIT_SUCCESS;
}
-void hidio_ff_gain( t_hidio *x, t_float value )
+t_int hidio_ff_gain( t_hidio *x, t_float value )
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ return EXIT_SUCCESS;
}
-void hidio_ff_motors( t_hidio *x, t_float value )
+t_int hidio_ff_motors( t_hidio *x, t_float value )
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ return EXIT_SUCCESS;
}
-void hidio_ff_continue( t_hidio *x )
+t_int hidio_ff_continue( t_hidio *x )
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ return EXIT_SUCCESS;
}
-void hidio_ff_pause( t_hidio *x )
+t_int hidio_ff_pause( t_hidio *x )
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ return EXIT_SUCCESS;
}
-void hidio_ff_reset( t_hidio *x )
+t_int hidio_ff_reset( t_hidio *x )
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ return EXIT_SUCCESS;
}
-void hidio_ff_stopall( t_hidio *x )
+t_int hidio_ff_stopall( t_hidio *x )
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ return EXIT_SUCCESS;
}
// these are just for testing...
-void hidio_ff_fftest ( t_hidio *x, t_float value)
+t_int hidio_ff_fftest ( t_hidio *x, t_float value)
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ return EXIT_SUCCESS;
}
void hidio_ff_print( t_hidio *x )
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
}
/* ============================================================================== */
/* Pd [hidio] FUNCTIONS */
/* ============================================================================== */
-void hidio_platform_specific_info(t_hidio *x)
-{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
- //debug_print(LOG_DEBUG,"hidio_platform_specific_info");
-}
-
+void hidio_platform_specific_info(t_hidio *x)
+{
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ //debug_print(LOG_DEBUG,"hidio_platform_specific_info");
+}
+
void hidio_get_events(t_hidio *x)
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
- long bytesRead;
-
- debug_print(LOG_DEBUG,"hidio_get_events");
-#if 0
- while (1)
- {
- if (!ReadFile(current_device->device,
- current_device->inputReportBuffer,
- current_device->caps.InputReportByteLength,
- &bytesRead,
- NULL))
- {
- debug_error(x,LOG_ERR,"[hidio]: failed to read from device %d", x->x_device_number);
- return;
- }
-
- if (bytesRead)
- {
- debug_error(x,LOG_INFO,"[hidio]: got event from device %d", x->x_device_number);
- }
- else /* no more data to read */
- {
- break;
- }
- }
-#endif
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+ t_hid_element *current_element = NULL;
+ long bytesRead;
+
+ debug_print(LOG_DEBUG,"hidio_get_events");
+
+ while (_hidio_read(self) > 0)
+ {
+ unsigned long i;
+ unsigned long size, length;
+ unsigned short *usages;
+
+ for (i = 0; i < element_count[x->x_device_number]; i++)
+ {
+ current_element = element[x->x_device_number][i];
+
+ /* first try getting value data */
+ if (HIDP_STATUS_SUCCESS == HidP_GetUsageValue(HidP_Input, current_element[i].usage_page, 0, current_element[i].usage_id, &current_element[i].value,
+ self->ppd, self->inputReportBuffer, self->caps.InputReportByteLength))
+ {
+ continue;
+ }
+ /* now try getting scaled value data */
+ if (HIDP_STATUS_SUCCESS == HidP_GetScaledUsageValue(HidP_Input, current_element[i].usage_page, 0, current_element[i].usage_id, &current_element[i].value,
+ self->ppd, self->inputReportBuffer, self->caps.InputReportByteLength))
+ {
+ continue;
+ }
+
+ /* ask Windows how many usages we might expect at max. */
+ length = size = HidP_MaxUsageListLength(HidP_Input, current_element[i].usage_page, self->ppd);
+ if (size)
+ {
+ /* uh, can't I alloc this memory in advance? but we might have several button usages on
+ different usage pages, so I'd have to figure out the largest one */
+ usages = (unsigned short *)getbytes((short)(size * sizeof(unsigned short)));
+ /* finally try getting button data */
+ if (HIDP_STATUS_SUCCESS == HidP_GetUsages(HidP_Input, current_element[i].usage_page, 0, usages, &length,
+ self->ppd, self->inputReportBuffer, self->caps.InputReportByteLength))
+ {
+ unsigned long j;
+
+ current_element[i].value = 0;
+
+ for (j = 0; j < length, usages[j] != 0; j++)
+ {
+ if (current_element[i].usage_id == usages[j])
+ {
+ current_element[i].value = 1;
+ break;
+ }
+ }
+ }
+ freebytes(usages, (short)(size * sizeof(unsigned short)));
+ }
+ }
+ }
}
t_int hidio_open_device(t_hidio *x, short device_number)
-{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
- short ret;
- char path[MAX_PATH];
- char *pp = (char *)path;
- short device_count = -1;
-
- debug_print(LOG_DEBUG,"hidio_open_device");
-
- device_count = _hid_count_devices();
-
- if (device_number > device_count)
- {
- debug_error(x,LOG_ERR,"[hidio]: device %d is not a valid device (%d)\n", device_number, device_count);
- return 1;
- }
-
- /* get path for specified device number */
- ret = _hid_get_device_path(device_number, &pp, MAX_PATH);
- if (ret == -1)
- {
- debug_error(x,LOG_ERR,"[hidio]: could not obtain path for device %d\n", device_number);
- return 1;
- }
- else
- {
- /* open file on the device (read & write, no overlapp) */
- self->fh = CreateFile(path,
- GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- (LPSECURITY_ATTRIBUTES)NULL,
- OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED,
- NULL);
- if (self->fh == INVALID_HANDLE_VALUE)
- {
- debug_error(x,LOG_ERR,"[hidio]: failed to open device %d at %s\n", device_number, path);
- return 1;
- }
- /* LATER get the real device name here instead of displaying the path */
- post ("[hidio] opened device %d: %s", device_number, path);
-
- post("pre hidio_build_element_list");
- hidio_build_element_list(x);
- }
- return 0;
+{
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+
+ if (device_number >= 0)
+ {
+ // open new device
+ self->fh = connectDeviceNumber(device_number);
+
+ if (self->fh != INVALID_HANDLE_VALUE)
+ {
+ hidio_build_element_list(x);
+
+ /* prepare overlapped structure */
+ self->overlapped.Offset = 0;
+ self->overlapped.OffsetHigh = 0;
+ self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, "");
+
+ return EXIT_SUCCESS;
+ }
+ else
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
}
t_int hidio_close_device(t_hidio *x)
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
- t_int result = 0;
-
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+
debug_print(LOG_DEBUG, "hidio_close_device");
-
- if (x->x_device_number > -1)
- {
- if (self->fh != INVALID_HANDLE_VALUE)
- {
- CloseHandle(self->fh);
- self->fh = INVALID_HANDLE_VALUE;
- }
- }
-
- return (result);
+
+ if (x->x_device_number > -1)
+ {
+ if (self->fh != INVALID_HANDLE_VALUE)
+ {
+ unsigned long i;
+
+ CloseHandle(self->fh);
+ self->fh = INVALID_HANDLE_VALUE;
+
+ /* free element list */
+ for (i = 0; i < element_count[x->x_device_number]; i++);
+ freebytes(element[x->x_device_number][i], sizeof(t_hid_element));
+ element_count[x->x_device_number] = 0;
+
+ /* free allocated memory */
+ if (self->inputButtonCaps)
+ freebytes(self->inputButtonCaps, (short)(self->caps.NumberInputButtonCaps * sizeof(HIDP_BUTTON_CAPS)));
+ if (self->inputValueCaps)
+ freebytes(self->inputValueCaps, (short)(self->caps.NumberInputValueCaps * sizeof(HIDP_VALUE_CAPS)));
+
+ /* free report buffers */
+ if (self->inputReportBuffer)
+ freebytes(self->inputReportBuffer, (short)(self->caps.InputReportByteLength * sizeof(char)));
+ if (self->outputReportBuffer)
+ freebytes(self->outputReportBuffer, (short)(self->caps.OutputReportByteLength * sizeof(char)));
+ if (self->featureReportBuffer)
+ freebytes(self->featureReportBuffer, (short)(self->caps.FeatureReportByteLength * sizeof(char)));
+
+ /* free preparsed data */
+ if (self->ppd)
+ HidD_FreePreparsedData(self->ppd);
+ }
+ }
+
+ return EXIT_SUCCESS;
}
void hidio_build_device_list(void)
-{
- debug_print(LOG_DEBUG,"hidio_build_device_list");
+{
+ debug_print(LOG_DEBUG,"hidio_build_device_list");
}
void hidio_print(t_hidio *x)
{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
-
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
+
hidio_print_device_list(x);
if (x->x_device_open)
@@ -671,27 +1045,27 @@ void hidio_print(t_hidio *x)
void hidio_platform_specific_free(t_hidio *x)
-{
- t_hid_device *self = (t_hid_device *)x->x_hid_device;
+{
+ t_hid_device *self = (t_hid_device *)x->x_hid_device;
debug_print(LOG_DEBUG,"hidio_platform_specific_free");
-
- if (self)
- freebytes(self, sizeof(t_hid_device));
+
+ if (self)
+ freebytes(self, sizeof(t_hid_device));
}
-void *hidio_platform_specific_new(t_hidio *x)
-{
- t_hid_device *self;
-
- debug_print(LOG_DEBUG,"hidio_platform_specific_new");
-
- /* alloc memory for our instance */
- self = (t_hid_device *)getbytes(sizeof(t_hid_device));
- self->fh = INVALID_HANDLE_VALUE;
-
- return (void *)self; /* return void pointer to our data struct */
-}
+void *hidio_platform_specific_new(t_hidio *x)
+{
+ t_hid_device *self;
+
+ debug_print(LOG_DEBUG,"hidio_platform_specific_new");
+
+ /* alloc memory for our instance */
+ self = (t_hid_device *)getbytes(sizeof(t_hid_device));
+ self->fh = INVALID_HANDLE_VALUE;
+
+ return (void *)self; /* return void pointer to our data struct */
+}
#endif /* _WINDOWS */