22 #include "../../SDL_internal.h" 24 #ifdef SDL_JOYSTICK_HIDAPI 36 #define _wcsdup wcsdup 41 typedef LONG NTSTATUS;
47 #define calloc SDL_calloc 49 #define malloc SDL_malloc 50 #define memcpy SDL_memcpy 51 #define memset SDL_memset 52 #define strcmp SDL_strcmp 53 #define strlen SDL_strlen 54 #define strncpy SDL_strlcpy 55 #define strstr SDL_strstr 56 #define strtol SDL_strtol 57 #define wcscmp SDL_wcscmp 58 #define _wcsdup SDL_wcsdup 62 #define MAX_STRING_WCHARS 0xFFF 76 #define HID_OUT_CTL_CODE(id) \ 77 CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) 78 #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) 88 #include "../hidapi/hidapi.h" 91 #define MIN(x,y) ((x) < (y)? (x): (y)) 95 #pragma warning(disable:4996) 102 #ifndef HIDAPI_USE_DDK 107 typedef struct _HIDD_ATTRIBUTES{
111 USHORT VersionNumber;
112 } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
114 typedef USHORT USAGE;
115 typedef struct _HIDP_CAPS {
118 USHORT InputReportByteLength;
119 USHORT OutputReportByteLength;
120 USHORT FeatureReportByteLength;
122 USHORT fields_not_used_by_hidapi[10];
123 } HIDP_CAPS, *PHIDP_CAPS;
124 typedef void* PHIDP_PREPARSED_DATA;
125 #define HIDP_STATUS_SUCCESS 0x110000 127 typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE
device, PHIDD_ATTRIBUTES attrib);
128 typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE
device, PVOID
buffer, ULONG buffer_len);
129 typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE
handle, PVOID
buffer, ULONG buffer_len);
130 typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE
handle, PVOID
buffer, ULONG buffer_len);
131 typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE
handle, PVOID
data, ULONG
length);
132 typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE
handle, PVOID
data, ULONG
length);
133 typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE
handle, ULONG string_index, PVOID
buffer, ULONG buffer_len);
134 typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE
handle, PHIDP_PREPARSED_DATA *preparsed_data);
135 typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
136 typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps);
137 typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE
handle, ULONG number_buffers);
138 typedef BOOLEAN(__stdcall *HidD_SetOutputReport_ )(HANDLE
handle, PVOID
buffer, ULONG buffer_len);
139 static HidD_GetAttributes_ HidD_GetAttributes;
140 static HidD_GetSerialNumberString_ HidD_GetSerialNumberString;
141 static HidD_GetManufacturerString_ HidD_GetManufacturerString;
142 static HidD_GetProductString_ HidD_GetProductString;
143 static HidD_SetFeature_ HidD_SetFeature;
144 static HidD_GetFeature_ HidD_GetFeature;
145 static HidD_GetIndexedString_ HidD_GetIndexedString;
146 static HidD_GetPreparsedData_ HidD_GetPreparsedData;
147 static HidD_FreePreparsedData_ HidD_FreePreparsedData;
148 static HidP_GetCaps_ HidP_GetCaps;
149 static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers;
150 static HidD_SetOutputReport_ HidD_SetOutputReport;
152 static HMODULE lib_handle =
NULL;
153 static BOOLEAN initialized =
FALSE;
157 HANDLE device_handle;
159 USHORT output_report_length;
160 size_t input_report_length;
161 void *last_error_str;
162 DWORD last_error_num;
168 static hid_device *new_hid_device()
170 hid_device *dev = (hid_device*) calloc(1,
sizeof(hid_device));
171 dev->device_handle = INVALID_HANDLE_VALUE;
172 dev->blocking =
TRUE;
173 dev->output_report_length = 0;
174 dev->input_report_length = 0;
175 dev->last_error_str =
NULL;
176 dev->last_error_num = 0;
177 dev->read_pending =
FALSE;
178 dev->read_buf =
NULL;
179 memset(&dev->ol, 0,
sizeof(dev->ol));
185 static void free_hid_device(hid_device *dev)
187 CloseHandle(dev->ol.hEvent);
188 CloseHandle(dev->device_handle);
189 LocalFree(dev->last_error_str);
194 static void register_error(hid_device *device,
const char *op)
198 DWORD
count = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
199 FORMAT_MESSAGE_FROM_SYSTEM |
200 FORMAT_MESSAGE_IGNORE_INSERTS,
203 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
222 LocalFree(device->last_error_str);
223 device->last_error_str = msg;
226 #ifndef HIDAPI_USE_DDK 227 static int lookup_functions()
229 lib_handle = LoadLibraryA(
"hid.dll");
231 #define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; 232 RESOLVE(HidD_GetAttributes);
233 RESOLVE(HidD_GetSerialNumberString);
234 RESOLVE(HidD_GetManufacturerString);
235 RESOLVE(HidD_GetProductString);
236 RESOLVE(HidD_SetFeature);
237 RESOLVE(HidD_GetFeature);
238 RESOLVE(HidD_GetIndexedString);
239 RESOLVE(HidD_GetPreparsedData);
240 RESOLVE(HidD_FreePreparsedData);
241 RESOLVE(HidP_GetCaps);
242 RESOLVE(HidD_SetNumInputBuffers);
243 RESOLVE(HidD_SetOutputReport);
253 static HANDLE open_device(
const char *
path, BOOL enumerate, BOOL bExclusive )
260 DWORD desired_access = ( GENERIC_WRITE | GENERIC_READ );
261 DWORD share_mode = bExclusive ? 0 : ( FILE_SHARE_READ | FILE_SHARE_WRITE );
263 handle = CreateFileA(path,
268 FILE_FLAG_OVERLAPPED,
276 #ifndef HIDAPI_USE_DDK 278 if (lookup_functions() < 0) {
290 #ifndef HIDAPI_USE_DDK 292 FreeLibrary(lib_handle);
306 GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
307 SP_DEVINFO_DATA devinfo_data;
308 SP_DEVICE_INTERFACE_DATA device_interface_data;
309 SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data =
NULL;
310 HDEVINFO device_info_set = INVALID_HANDLE_VALUE;
311 int device_index = 0;
318 memset(&devinfo_data, 0
x0,
sizeof(devinfo_data));
319 devinfo_data.cbSize =
sizeof(SP_DEVINFO_DATA);
320 device_interface_data.cbSize =
sizeof(SP_DEVICE_INTERFACE_DATA);
323 device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid,
NULL,
NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
328 HANDLE write_handle = INVALID_HANDLE_VALUE;
329 DWORD required_size = 0;
330 HIDD_ATTRIBUTES attrib;
332 res = SetupDiEnumDeviceInterfaces(device_info_set,
336 &device_interface_data);
347 res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
348 &device_interface_data,
355 device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*)
malloc(required_size);
356 device_interface_detail_data->cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
361 res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
362 &device_interface_data,
363 device_interface_detail_data,
377 char driver_name[256];
381 res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data);
385 res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
386 SPDRP_CLASS,
NULL, (PBYTE)driver_name,
sizeof(driver_name),
NULL);
390 if (strcmp(driver_name,
"HIDClass") == 0) {
392 res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
393 SPDRP_DRIVER,
NULL, (PBYTE)driver_name,
sizeof(driver_name),
NULL);
402 write_handle = open_device(device_interface_detail_data->DevicePath,
TRUE,
FALSE);
405 if (write_handle == INVALID_HANDLE_VALUE) {
413 attrib.Size =
sizeof(HIDD_ATTRIBUTES);
414 HidD_GetAttributes(write_handle, &attrib);
419 if ((vendor_id == 0
x0 || attrib.VendorID == vendor_id) &&
420 (product_id == 0
x0 || attrib.ProductID == product_id)) {
425 PHIDP_PREPARSED_DATA pp_data =
NULL;
429 wchar_t wstr[WSTR_LEN];
443 hidp_res = HidD_GetPreparsedData(write_handle, &pp_data);
445 nt_res = HidP_GetCaps(pp_data, &caps);
446 if (nt_res == HIDP_STATUS_SUCCESS) {
448 cur_dev->
usage = caps.Usage;
451 HidD_FreePreparsedData(pp_data);
456 str = device_interface_detail_data->DevicePath;
459 cur_dev->
path = (
char*) calloc(len+1,
sizeof(
char));
460 strncpy(cur_dev->
path, str, len+1);
467 hidp_res = HidD_GetSerialNumberString(write_handle, wstr,
sizeof(wstr));
468 wstr[WSTR_LEN-1] = 0x0000;
474 hidp_res = HidD_GetManufacturerString(write_handle, wstr,
sizeof(wstr));
475 wstr[WSTR_LEN-1] = 0x0000;
481 hidp_res = HidD_GetProductString(write_handle, wstr,
sizeof(wstr));
482 wstr[WSTR_LEN-1] = 0x0000;
501 char *interface_component = strstr(cur_dev->
path,
"&mi_");
502 if (interface_component) {
503 char *hex_str = interface_component + 4;
506 if (endptr == hex_str) {
515 CloseHandle(write_handle);
518 free(device_interface_detail_data);
525 SetupDiDestroyDeviceInfoList(device_info_set);
551 const char *path_to_open =
NULL;
552 hid_device *handle =
NULL;
561 path_to_open = cur_dev->
path;
566 path_to_open = cur_dev->
path;
570 cur_dev = cur_dev->
next;
587 PHIDP_PREPARSED_DATA pp_data =
NULL;
595 dev = new_hid_device();
598 dev->device_handle = open_device(path,
FALSE, bExclusive);
601 if (dev->device_handle == INVALID_HANDLE_VALUE) {
603 register_error(dev,
"CreateFile");
608 res = HidD_SetNumInputBuffers(dev->device_handle, 64);
610 register_error(dev,
"HidD_SetNumInputBuffers");
615 res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
617 register_error(dev,
"HidD_GetPreparsedData");
620 nt_res = HidP_GetCaps(pp_data, &caps);
621 if (nt_res != HIDP_STATUS_SUCCESS) {
622 register_error(dev,
"HidP_GetCaps");
625 dev->output_report_length = caps.OutputReportByteLength;
626 dev->input_report_length = caps.InputReportByteLength;
627 HidD_FreePreparsedData(pp_data);
629 dev->read_buf = (
char*)
malloc(dev->input_report_length);
634 HidD_FreePreparsedData(pp_data);
636 free_hid_device(dev);
643 res = HidD_SetOutputReport(dev->device_handle, (
void *)data, (ULONG)length);
654 size_t stashed_length =
length;
657 memset(&ol, 0,
sizeof(ol));
665 if (length >= dev->output_report_length) {
667 buf = (
unsigned char *) data;
671 buf = (
unsigned char *)
malloc(dev->output_report_length);
672 memcpy(buf, data, length);
673 memset(buf + length, 0, dev->output_report_length - length);
674 length = dev->output_report_length;
678 return hid_write_output_report( dev, data, stashed_length );
682 res = WriteFile( dev->device_handle, buf, ( DWORD ) length,
NULL, &ol );
684 if (GetLastError() != ERROR_IO_PENDING) {
686 register_error(dev,
"WriteFile");
687 bytes_written = (DWORD) -1;
688 goto end_of_function;
694 res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written,
TRUE);
697 register_error(dev,
"WriteFile");
698 bytes_written = (DWORD) -1;
699 goto end_of_function;
706 return bytes_written;
712 DWORD bytes_read = 0;
717 HANDLE ev = dev->ol.hEvent;
719 if (!dev->read_pending) {
721 dev->read_pending =
TRUE;
722 memset(dev->read_buf, 0, dev->input_report_length);
724 res = ReadFile(dev->device_handle, dev->read_buf, (DWORD)dev->input_report_length, &bytes_read, &dev->ol);
727 if (GetLastError() != ERROR_IO_PENDING) {
730 CancelIo(dev->device_handle);
731 dev->read_pending =
FALSE;
732 goto end_of_function;
737 if (milliseconds >= 0) {
739 res = WaitForSingleObject(ev, milliseconds);
740 if (res != WAIT_OBJECT_0) {
750 res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read,
TRUE);
753 dev->read_pending =
FALSE;
755 if (res && bytes_read > 0) {
756 if (dev->read_buf[0] == 0
x0) {
762 copy_len = length > bytes_read ? bytes_read :
length;
763 memcpy(data, dev->read_buf+1, copy_len);
767 copy_len = length > bytes_read ? bytes_read :
length;
768 memcpy(data, dev->read_buf, copy_len);
774 register_error(dev,
"GetOverlappedResult");
778 return (
int)copy_len;
788 dev->blocking = !nonblock;
794 BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, (ULONG)length);
796 register_error(dev,
"HidD_SetFeature");
808 res = HidD_GetFeature(dev->device_handle, (PVOID)data, (ULONG)length);
810 register_error(dev,
"HidD_GetFeature");
815 DWORD bytes_returned;
818 memset(&ol, 0,
sizeof(ol));
820 res = DeviceIoControl(dev->device_handle,
821 IOCTL_HID_GET_FEATURE,
824 &bytes_returned, &ol);
827 if (GetLastError() != ERROR_IO_PENDING) {
829 register_error(dev,
"Send Feature Report DeviceIoControl");
836 res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned,
TRUE);
839 register_error(dev,
"Send Feature Report GetOverLappedResult");
849 return bytes_returned;
857 CancelIo(dev->device_handle);
858 free_hid_device(dev);
865 res = HidD_GetManufacturerString(dev->device_handle,
string, (ULONG)(
sizeof(
wchar_t) *
MIN(maxlen, MAX_STRING_WCHARS)));
867 register_error(dev,
"HidD_GetManufacturerString");
878 res = HidD_GetProductString(dev->device_handle,
string, (ULONG)(
sizeof(
wchar_t) *
MIN(maxlen, MAX_STRING_WCHARS)));
880 register_error(dev,
"HidD_GetProductString");
891 res = HidD_GetSerialNumberString(dev->device_handle,
string, (ULONG)(
sizeof(
wchar_t) *
MIN(maxlen, MAX_STRING_WCHARS)));
893 register_error(dev,
"HidD_GetSerialNumberString");
904 res = HidD_GetIndexedString(dev->device_handle, string_index,
string, (ULONG)(
sizeof(
wchar_t) *
MIN(maxlen, MAX_STRING_WCHARS)));
906 register_error(dev,
"HidD_GetIndexedString");
915 return (
wchar_t*)dev->last_error_str;
925 unsigned short VendorID = 0xa0a0;
926 unsigned short ProductID = 0x0001;
930 unsigned short VendorID = 0x04d8;
931 unsigned short ProductID = 0x3f;
935 unsigned short VendorID = 0x04d8;
936 unsigned short ProductID = 0x0033;
939 int __cdecl
main(
int argc,
char* argv[])
942 unsigned char buf[65];
944 UNREFERENCED_PARAMETER(argc);
945 UNREFERENCED_PARAMETER(argv);
948 memset(buf,0x00,
sizeof(buf));
954 int handle = open(VendorID, ProductID, L
"12345");
956 printf(
"unable to open device\n");
961 res = write(handle, buf, 65);
963 printf(
"Unable to write()\n");
967 write(handle, buf, 65);
969 printf(
"Unable to write() (2)\n");
972 read(handle, buf, 65);
974 printf(
"Unable to read()\n");
977 for (
int i = 0; i < 4; i++)
978 printf(
"buf[%d]: %d\n", i, buf[i]);
HID_API_EXPORT const wchar_t *HID_API_CALL hid_error(hid_device *device)
Get a string describing the last error which occurred.
GLuint GLuint GLsizei count
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
Free an enumeration Linked List.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
wchar_t * manufacturer_string
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
Get a string from a HID device, based on its string index.
static SDL_AudioDeviceID device
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
struct hid_device_info * next
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
Set the device handle to be non-blocking.
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Product String from a HID device.
unsigned short product_id
EGLImageKHR EGLint EGLint * handle
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
int hid_exit(void)
Finalize the HIDAPI library.
HID_API_EXPORT hid_device *HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally a serial number...
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
Get a feature report from a HID device.
GLenum GLuint GLenum GLsizei const GLchar * buf
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Serial Number String from a HID device.
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
#define HID_API_EXPORT_CALL
int hid_init(void)
Initialize the HIDAPI library.
unsigned short usage_page
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
GLsizei const GLchar *const * path
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
Send a Feature report to the device.
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
Get The Manufacturer String from a HID device.
GLuint GLsizei GLsizei * length
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
Enumerate the HID Devices.
unsigned short release_number
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
Read an Input report from a HID device.