hid.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665
  1. /*******************************************************
  2. HIDAPI - Multi-Platform library for
  3. communication with HID devices.
  4. Alan Ott
  5. Signal 11 Software
  6. libusb/hidapi Team
  7. Copyright 2022, All Rights Reserved.
  8. At the discretion of the user of this library,
  9. this software may be licensed under the terms of the
  10. GNU General Public License v3, a BSD-Style license, or the
  11. original HIDAPI license as outlined in the LICENSE.txt,
  12. LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
  13. files located at the root of the source distribution.
  14. These files may also be found in the public source
  15. code repository located at:
  16. https://github.com/libusb/hidapi .
  17. ********************************************************/
  18. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
  19. /* Do not warn about wcsncpy usage.
  20. https://docs.microsoft.com/cpp/c-runtime-library/security-features-in-the-crt */
  21. #define _CRT_SECURE_NO_WARNINGS
  22. #endif
  23. #ifdef __cplusplus
  24. extern "C" {
  25. #endif
  26. #include "hidapi_winapi.h"
  27. #include <windows.h>
  28. #ifndef _NTDEF_
  29. typedef LONG NTSTATUS;
  30. #endif
  31. #ifndef WC_ERR_INVALID_CHARS
  32. #define WC_ERR_INVALID_CHARS 0x00000080
  33. #endif
  34. #ifndef _WIN32_WINNT_WIN8
  35. #define _WIN32_WINNT_WIN8 0x0602
  36. #endif
  37. #ifdef __CYGWIN__
  38. #include <ntdef.h>
  39. #include <wctype.h>
  40. #define _wcsdup wcsdup
  41. #endif
  42. /*#define HIDAPI_USE_DDK*/
  43. #include "hidapi_cfgmgr32.h"
  44. #include "hidapi_hidclass.h"
  45. #include "hidapi_hidsdi.h"
  46. #ifndef HIDAPI_USING_SDL_RUNTIME
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #endif
  51. #ifdef MIN
  52. #undef MIN
  53. #endif
  54. #define MIN(x,y) ((x) < (y)? (x): (y))
  55. /* MAXIMUM_USB_STRING_LENGTH from usbspec.h is 255 */
  56. /* BLUETOOTH_DEVICE_NAME_SIZE from bluetoothapis.h is 256 */
  57. #define MAX_STRING_WCHARS 256
  58. static struct hid_api_version api_version = {
  59. .major = HID_API_VERSION_MAJOR,
  60. .minor = HID_API_VERSION_MINOR,
  61. .patch = HID_API_VERSION_PATCH
  62. };
  63. #ifndef HIDAPI_USE_DDK
  64. /* Since we're not building with the DDK, and the HID header
  65. files aren't part of the Windows SDK, we define what we need ourselves.
  66. In lookup_functions(), the function pointers
  67. defined below are set. */
  68. static HidD_GetHidGuid_ HidD_GetHidGuid;
  69. static HidD_GetAttributes_ HidD_GetAttributes;
  70. static HidD_GetSerialNumberString_ HidD_GetSerialNumberString;
  71. static HidD_GetManufacturerString_ HidD_GetManufacturerString;
  72. static HidD_GetProductString_ HidD_GetProductString;
  73. static HidD_SetFeature_ HidD_SetFeature;
  74. static HidD_GetFeature_ HidD_GetFeature;
  75. static HidD_GetInputReport_ HidD_GetInputReport;
  76. static HidD_GetIndexedString_ HidD_GetIndexedString;
  77. static HidD_GetPreparsedData_ HidD_GetPreparsedData;
  78. static HidD_FreePreparsedData_ HidD_FreePreparsedData;
  79. static HidP_GetCaps_ HidP_GetCaps;
  80. static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers;
  81. static HidD_SetOutputReport_ HidD_SetOutputReport;
  82. static CM_Locate_DevNodeW_ CM_Locate_DevNodeW = NULL;
  83. static CM_Get_Parent_ CM_Get_Parent = NULL;
  84. static CM_Get_DevNode_PropertyW_ CM_Get_DevNode_PropertyW = NULL;
  85. static CM_Get_Device_Interface_PropertyW_ CM_Get_Device_Interface_PropertyW = NULL;
  86. static CM_Get_Device_Interface_List_SizeW_ CM_Get_Device_Interface_List_SizeW = NULL;
  87. static CM_Get_Device_Interface_ListW_ CM_Get_Device_Interface_ListW = NULL;
  88. static HMODULE hid_lib_handle = NULL;
  89. static HMODULE cfgmgr32_lib_handle = NULL;
  90. static BOOLEAN hidapi_initialized = FALSE;
  91. static void free_library_handles()
  92. {
  93. if (hid_lib_handle)
  94. FreeLibrary(hid_lib_handle);
  95. hid_lib_handle = NULL;
  96. if (cfgmgr32_lib_handle)
  97. FreeLibrary(cfgmgr32_lib_handle);
  98. cfgmgr32_lib_handle = NULL;
  99. }
  100. #if defined(__GNUC__)
  101. # pragma GCC diagnostic push
  102. # pragma GCC diagnostic ignored "-Wcast-function-type"
  103. #endif
  104. static int lookup_functions()
  105. {
  106. hid_lib_handle = LoadLibraryW(L"hid.dll");
  107. if (hid_lib_handle == NULL) {
  108. goto err;
  109. }
  110. cfgmgr32_lib_handle = LoadLibraryW(L"cfgmgr32.dll");
  111. if (cfgmgr32_lib_handle == NULL) {
  112. goto err;
  113. }
  114. #define RESOLVE(lib_handle, x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) goto err;
  115. RESOLVE(hid_lib_handle, HidD_GetHidGuid);
  116. RESOLVE(hid_lib_handle, HidD_GetAttributes);
  117. RESOLVE(hid_lib_handle, HidD_GetSerialNumberString);
  118. RESOLVE(hid_lib_handle, HidD_GetManufacturerString);
  119. RESOLVE(hid_lib_handle, HidD_GetProductString);
  120. RESOLVE(hid_lib_handle, HidD_SetFeature);
  121. RESOLVE(hid_lib_handle, HidD_GetFeature);
  122. RESOLVE(hid_lib_handle, HidD_GetInputReport);
  123. RESOLVE(hid_lib_handle, HidD_GetIndexedString);
  124. RESOLVE(hid_lib_handle, HidD_GetPreparsedData);
  125. RESOLVE(hid_lib_handle, HidD_FreePreparsedData);
  126. RESOLVE(hid_lib_handle, HidP_GetCaps);
  127. RESOLVE(hid_lib_handle, HidD_SetNumInputBuffers);
  128. RESOLVE(hid_lib_handle, HidD_SetOutputReport);
  129. RESOLVE(cfgmgr32_lib_handle, CM_Locate_DevNodeW);
  130. RESOLVE(cfgmgr32_lib_handle, CM_Get_Parent);
  131. RESOLVE(cfgmgr32_lib_handle, CM_Get_DevNode_PropertyW);
  132. RESOLVE(cfgmgr32_lib_handle, CM_Get_Device_Interface_PropertyW);
  133. RESOLVE(cfgmgr32_lib_handle, CM_Get_Device_Interface_List_SizeW);
  134. RESOLVE(cfgmgr32_lib_handle, CM_Get_Device_Interface_ListW);
  135. #undef RESOLVE
  136. return 0;
  137. err:
  138. free_library_handles();
  139. return -1;
  140. }
  141. #if defined(__GNUC__)
  142. # pragma GCC diagnostic pop
  143. #endif
  144. #endif /* HIDAPI_USE_DDK */
  145. struct hid_device_ {
  146. HANDLE device_handle;
  147. BOOL blocking;
  148. USHORT output_report_length;
  149. unsigned char *write_buf;
  150. size_t input_report_length;
  151. USHORT feature_report_length;
  152. unsigned char *feature_buf;
  153. wchar_t *last_error_str;
  154. BOOL read_pending;
  155. char *read_buf;
  156. OVERLAPPED ol;
  157. OVERLAPPED write_ol;
  158. struct hid_device_info* device_info;
  159. BOOL use_hid_write_output_report;
  160. };
  161. static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
  162. {
  163. OSVERSIONINFOEXW osvi;
  164. DWORDLONG const dwlConditionMask = VerSetConditionMask(
  165. VerSetConditionMask(
  166. VerSetConditionMask(
  167. 0, VER_MAJORVERSION, VER_GREATER_EQUAL ),
  168. VER_MINORVERSION, VER_GREATER_EQUAL ),
  169. VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
  170. memset(&osvi, 0, sizeof(osvi));
  171. osvi.dwOSVersionInfoSize = sizeof( osvi );
  172. osvi.dwMajorVersion = wMajorVersion;
  173. osvi.dwMinorVersion = wMinorVersion;
  174. osvi.wServicePackMajor = wServicePackMajor;
  175. return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
  176. }
  177. static hid_device *new_hid_device()
  178. {
  179. hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
  180. if (dev == NULL) {
  181. return NULL;
  182. }
  183. dev->device_handle = INVALID_HANDLE_VALUE;
  184. dev->blocking = TRUE;
  185. dev->output_report_length = 0;
  186. dev->write_buf = NULL;
  187. dev->input_report_length = 0;
  188. dev->feature_report_length = 0;
  189. dev->feature_buf = NULL;
  190. dev->last_error_str = NULL;
  191. dev->read_pending = FALSE;
  192. dev->read_buf = NULL;
  193. memset(&dev->ol, 0, sizeof(dev->ol));
  194. dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
  195. memset(&dev->write_ol, 0, sizeof(dev->write_ol));
  196. dev->write_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
  197. dev->device_info = NULL;
  198. return dev;
  199. }
  200. static void free_hid_device(hid_device *dev)
  201. {
  202. CloseHandle(dev->ol.hEvent);
  203. CloseHandle(dev->write_ol.hEvent);
  204. CloseHandle(dev->device_handle);
  205. free(dev->last_error_str);
  206. dev->last_error_str = NULL;
  207. free(dev->write_buf);
  208. free(dev->feature_buf);
  209. free(dev->read_buf);
  210. hid_free_enumeration(dev->device_info);
  211. free(dev);
  212. }
  213. static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR *op)
  214. {
  215. WCHAR system_err_buf[1024];
  216. DWORD error_code = GetLastError();
  217. free(*error_buffer);
  218. *error_buffer = NULL;
  219. #ifdef HIDAPI_USING_SDL_RUNTIME
  220. /* Thread-safe error handling */
  221. SDL_ClearError();
  222. #endif
  223. /* Only clear out error messages if NULL is passed into op */
  224. if (!op) {
  225. return;
  226. }
  227. DWORD system_err_len = FormatMessageW(
  228. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  229. NULL,
  230. error_code,
  231. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  232. system_err_buf, ARRAYSIZE(system_err_buf),
  233. NULL);
  234. DWORD op_len = (DWORD)wcslen(op);
  235. DWORD op_prefix_len =
  236. op_len
  237. + 15 /*: (0x00000000) */
  238. ;
  239. DWORD msg_len =
  240. + op_prefix_len
  241. + system_err_len
  242. ;
  243. WCHAR *msg = (WCHAR *)calloc(msg_len + 1, sizeof (WCHAR));
  244. if (!msg)
  245. return;
  246. int printf_written = swprintf(msg, msg_len + 1, L"%.*ls: (0x%08X) %.*ls", (int)op_len, op, error_code, (int)system_err_len, system_err_buf);
  247. if (printf_written < 0)
  248. {
  249. /* Highly unlikely */
  250. msg[0] = L'\0';
  251. return;
  252. }
  253. /* Get rid of the CR and LF that FormatMessage() sticks at the
  254. end of the message. Thanks Microsoft! */
  255. while(msg[msg_len-1] == L'\r' || msg[msg_len-1] == L'\n' || msg[msg_len-1] == L' ')
  256. {
  257. msg[msg_len-1] = L'\0';
  258. msg_len--;
  259. }
  260. #ifdef HIDAPI_USING_SDL_RUNTIME
  261. /* Thread-safe error handling */
  262. char *error_utf8 = SDL_iconv_wchar_utf8(msg);
  263. if (error_utf8) {
  264. SDL_SetError("%s", error_utf8);
  265. SDL_free(error_utf8);
  266. }
  267. free(msg);
  268. #else
  269. *error_buffer = msg;
  270. #endif
  271. }
  272. #if defined(__GNUC__)
  273. # pragma GCC diagnostic push
  274. # pragma GCC diagnostic ignored "-Warray-bounds"
  275. #endif
  276. /* A bug in GCC/mingw gives:
  277. * error: array subscript 0 is outside array bounds of 'wchar_t *[0]' {aka 'short unsigned int *[]'} [-Werror=array-bounds]
  278. * | free(*error_buffer);
  279. * Which doesn't make sense in this context. */
  280. static void register_string_error_to_buffer(wchar_t **error_buffer, const WCHAR *string_error)
  281. {
  282. free(*error_buffer);
  283. *error_buffer = NULL;
  284. #ifdef HIDAPI_USING_SDL_RUNTIME
  285. /* Thread-safe error handling */
  286. char *error_utf8 = string_error ? SDL_iconv_wchar_utf8(string_error) : NULL;
  287. if (error_utf8) {
  288. SDL_SetError("%s", error_utf8);
  289. SDL_free(error_utf8);
  290. } else {
  291. SDL_ClearError();
  292. }
  293. #else
  294. if (string_error) {
  295. *error_buffer = _wcsdup(string_error);
  296. }
  297. #endif /* HIDAPI_USING_SDL_RUNTIME */
  298. }
  299. #if defined(__GNUC__)
  300. # pragma GCC diagnostic pop
  301. #endif
  302. static void register_winapi_error(hid_device *dev, const WCHAR *op)
  303. {
  304. register_winapi_error_to_buffer(&dev->last_error_str, op);
  305. }
  306. static void register_string_error(hid_device *dev, const WCHAR *string_error)
  307. {
  308. register_string_error_to_buffer(&dev->last_error_str, string_error);
  309. }
  310. static wchar_t *last_global_error_str = NULL;
  311. static void register_global_winapi_error(const WCHAR *op)
  312. {
  313. register_winapi_error_to_buffer(&last_global_error_str, op);
  314. }
  315. static void register_global_error(const WCHAR *string_error)
  316. {
  317. register_string_error_to_buffer(&last_global_error_str, string_error);
  318. }
  319. static HANDLE open_device(const wchar_t *path, BOOL open_rw)
  320. {
  321. HANDLE handle;
  322. DWORD desired_access = (open_rw)? (GENERIC_WRITE | GENERIC_READ): 0;
  323. DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
  324. handle = CreateFileW(path,
  325. desired_access,
  326. share_mode,
  327. NULL,
  328. OPEN_EXISTING,
  329. FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
  330. 0);
  331. return handle;
  332. }
  333. HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void)
  334. {
  335. return &api_version;
  336. }
  337. HID_API_EXPORT const char* HID_API_CALL hid_version_str(void)
  338. {
  339. return HID_API_VERSION_STR;
  340. }
  341. int HID_API_EXPORT hid_init(void)
  342. {
  343. register_global_error(NULL);
  344. #ifndef HIDAPI_USE_DDK
  345. if (!hidapi_initialized) {
  346. if (lookup_functions() < 0) {
  347. register_global_winapi_error(L"resolve DLL functions");
  348. return -1;
  349. }
  350. hidapi_initialized = TRUE;
  351. }
  352. #endif
  353. return 0;
  354. }
  355. int HID_API_EXPORT hid_exit(void)
  356. {
  357. #ifndef HIDAPI_USE_DDK
  358. free_library_handles();
  359. hidapi_initialized = FALSE;
  360. #endif
  361. register_global_error(NULL);
  362. return 0;
  363. }
  364. static void* hid_internal_get_devnode_property(DEVINST dev_node, const DEVPROPKEY* property_key, DEVPROPTYPE expected_property_type)
  365. {
  366. ULONG len = 0;
  367. CONFIGRET cr;
  368. DEVPROPTYPE property_type;
  369. PBYTE property_value = NULL;
  370. cr = CM_Get_DevNode_PropertyW(dev_node, property_key, &property_type, NULL, &len, 0);
  371. if (cr != CR_BUFFER_SMALL || property_type != expected_property_type)
  372. return NULL;
  373. property_value = (PBYTE)calloc(len, sizeof(BYTE));
  374. cr = CM_Get_DevNode_PropertyW(dev_node, property_key, &property_type, property_value, &len, 0);
  375. if (cr != CR_SUCCESS) {
  376. free(property_value);
  377. return NULL;
  378. }
  379. return property_value;
  380. }
  381. static void* hid_internal_get_device_interface_property(const wchar_t* interface_path, const DEVPROPKEY* property_key, DEVPROPTYPE expected_property_type)
  382. {
  383. ULONG len = 0;
  384. CONFIGRET cr;
  385. DEVPROPTYPE property_type;
  386. PBYTE property_value = NULL;
  387. cr = CM_Get_Device_Interface_PropertyW(interface_path, property_key, &property_type, NULL, &len, 0);
  388. if (cr != CR_BUFFER_SMALL || property_type != expected_property_type)
  389. return NULL;
  390. property_value = (PBYTE)calloc(len, sizeof(BYTE));
  391. cr = CM_Get_Device_Interface_PropertyW(interface_path, property_key, &property_type, property_value, &len, 0);
  392. if (cr != CR_SUCCESS) {
  393. free(property_value);
  394. return NULL;
  395. }
  396. return property_value;
  397. }
  398. static void hid_internal_towupper(wchar_t* string)
  399. {
  400. for (wchar_t* p = string; *p; ++p) *p = towupper(*p);
  401. }
  402. static int hid_internal_extract_int_token_value(wchar_t* string, const wchar_t* token)
  403. {
  404. int token_value;
  405. wchar_t* startptr, * endptr;
  406. startptr = wcsstr(string, token);
  407. if (!startptr)
  408. return -1;
  409. startptr += wcslen(token);
  410. token_value = wcstol(startptr, &endptr, 16);
  411. if (endptr == startptr)
  412. return -1;
  413. return token_value;
  414. }
  415. static void hid_internal_get_usb_info(struct hid_device_info* dev, DEVINST dev_node)
  416. {
  417. wchar_t *device_id = NULL, *hardware_ids = NULL;
  418. device_id = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING);
  419. if (!device_id)
  420. goto end;
  421. /* Normalize to upper case */
  422. hid_internal_towupper(device_id);
  423. /* Check for Xbox Common Controller class (XUSB) device.
  424. https://docs.microsoft.com/windows/win32/xinput/directinput-and-xusb-devices
  425. https://docs.microsoft.com/windows/win32/xinput/xinput-and-directinput
  426. */
  427. if (hid_internal_extract_int_token_value(device_id, L"IG_") != -1) {
  428. /* Get devnode parent to reach out USB device. */
  429. if (CM_Get_Parent(&dev_node, dev_node, 0) != CR_SUCCESS)
  430. goto end;
  431. }
  432. /* Get the hardware ids from devnode */
  433. hardware_ids = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_HardwareIds, DEVPROP_TYPE_STRING_LIST);
  434. if (!hardware_ids)
  435. goto end;
  436. /* Get additional information from USB device's Hardware ID
  437. https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers
  438. https://docs.microsoft.com/windows-hardware/drivers/usbcon/enumeration-of-interfaces-not-grouped-in-collections
  439. */
  440. for (wchar_t* hardware_id = hardware_ids; *hardware_id; hardware_id += wcslen(hardware_id) + 1) {
  441. /* Normalize to upper case */
  442. hid_internal_towupper(hardware_id);
  443. if (dev->release_number == 0) {
  444. /* USB_DEVICE_DESCRIPTOR.bcdDevice value. */
  445. int release_number = hid_internal_extract_int_token_value(hardware_id, L"REV_");
  446. if (release_number != -1) {
  447. dev->release_number = (unsigned short)release_number;
  448. }
  449. }
  450. if (dev->interface_number == -1) {
  451. /* USB_INTERFACE_DESCRIPTOR.bInterfaceNumber value. */
  452. int interface_number = hid_internal_extract_int_token_value(hardware_id, L"MI_");
  453. if (interface_number != -1) {
  454. dev->interface_number = interface_number;
  455. }
  456. }
  457. }
  458. /* Try to get USB device manufacturer string if not provided by HidD_GetManufacturerString. */
  459. if (wcslen(dev->manufacturer_string) == 0) {
  460. wchar_t* manufacturer_string = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_Manufacturer, DEVPROP_TYPE_STRING);
  461. if (manufacturer_string) {
  462. free(dev->manufacturer_string);
  463. dev->manufacturer_string = manufacturer_string;
  464. }
  465. }
  466. /* Try to get USB device serial number if not provided by HidD_GetSerialNumberString. */
  467. if (wcslen(dev->serial_number) == 0) {
  468. DEVINST usb_dev_node = dev_node;
  469. if (dev->interface_number != -1) {
  470. /* Get devnode parent to reach out composite parent USB device.
  471. https://docs.microsoft.com/windows-hardware/drivers/usbcon/enumeration-of-the-composite-parent-device
  472. */
  473. if (CM_Get_Parent(&usb_dev_node, dev_node, 0) != CR_SUCCESS)
  474. goto end;
  475. }
  476. /* Get the device id of the USB device. */
  477. free(device_id);
  478. device_id = hid_internal_get_devnode_property(usb_dev_node, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING);
  479. if (!device_id)
  480. goto end;
  481. /* Extract substring after last '\\' of Instance ID.
  482. For USB devices it may contain device's serial number.
  483. https://docs.microsoft.com/windows-hardware/drivers/install/instance-ids
  484. */
  485. for (wchar_t *ptr = device_id + wcslen(device_id); ptr > device_id; --ptr) {
  486. /* Instance ID is unique only within the scope of the bus.
  487. For USB devices it means that serial number is not available. Skip. */
  488. if (*ptr == L'&')
  489. break;
  490. if (*ptr == L'\\') {
  491. free(dev->serial_number);
  492. dev->serial_number = _wcsdup(ptr + 1);
  493. break;
  494. }
  495. }
  496. }
  497. /* If we can't get the interface number, it means that there is only one interface. */
  498. if (dev->interface_number == -1)
  499. dev->interface_number = 0;
  500. end:
  501. free(device_id);
  502. free(hardware_ids);
  503. }
  504. /* HidD_GetProductString/HidD_GetManufacturerString/HidD_GetSerialNumberString is not working for BLE HID devices
  505. Request this info via dev node properties instead.
  506. https://docs.microsoft.com/answers/questions/401236/hidd-getproductstring-with-ble-hid-device.html
  507. */
  508. static void hid_internal_get_ble_info(struct hid_device_info* dev, DEVINST dev_node)
  509. {
  510. if (wcslen(dev->manufacturer_string) == 0) {
  511. /* Manufacturer Name String (UUID: 0x2A29) */
  512. wchar_t* manufacturer_string = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_Manufacturer, DEVPROP_TYPE_STRING);
  513. if (manufacturer_string) {
  514. free(dev->manufacturer_string);
  515. dev->manufacturer_string = manufacturer_string;
  516. }
  517. }
  518. if (wcslen(dev->serial_number) == 0) {
  519. /* Serial Number String (UUID: 0x2A25) */
  520. wchar_t* serial_number = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_DeviceAddress, DEVPROP_TYPE_STRING);
  521. if (serial_number) {
  522. free(dev->serial_number);
  523. dev->serial_number = serial_number;
  524. }
  525. }
  526. if (wcslen(dev->product_string) == 0) {
  527. /* Model Number String (UUID: 0x2A24) */
  528. wchar_t* product_string = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_ModelNumber, DEVPROP_TYPE_STRING);
  529. if (!product_string) {
  530. DEVINST parent_dev_node = 0;
  531. /* Fallback: Get devnode grandparent to reach out Bluetooth LE device node */
  532. if (CM_Get_Parent(&parent_dev_node, dev_node, 0) == CR_SUCCESS) {
  533. /* Device Name (UUID: 0x2A00) */
  534. product_string = hid_internal_get_devnode_property(parent_dev_node, &DEVPKEY_NAME, DEVPROP_TYPE_STRING);
  535. }
  536. }
  537. if (product_string) {
  538. free(dev->product_string);
  539. dev->product_string = product_string;
  540. }
  541. }
  542. }
  543. #ifdef HIDAPI_IGNORE_DEVICE
  544. static hid_bus_type get_bus_type(const wchar_t* interface_path)
  545. {
  546. wchar_t *device_id = NULL, *compatible_ids = NULL;
  547. CONFIGRET cr;
  548. DEVINST dev_node;
  549. hid_bus_type bus_type = HID_API_BUS_UNKNOWN;
  550. /* Get the device id from interface path */
  551. device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING);
  552. if (!device_id)
  553. goto end;
  554. /* Open devnode from device id */
  555. cr = CM_Locate_DevNodeW(&dev_node, (DEVINSTID_W)device_id, CM_LOCATE_DEVNODE_NORMAL);
  556. if (cr != CR_SUCCESS)
  557. goto end;
  558. /* Get devnode parent */
  559. cr = CM_Get_Parent(&dev_node, dev_node, 0);
  560. if (cr != CR_SUCCESS)
  561. goto end;
  562. /* Get the compatible ids from parent devnode */
  563. compatible_ids = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_CompatibleIds, DEVPROP_TYPE_STRING_LIST);
  564. if (!compatible_ids)
  565. goto end;
  566. /* Now we can parse parent's compatible IDs to find out the device bus type */
  567. for (wchar_t* compatible_id = compatible_ids; *compatible_id; compatible_id += wcslen(compatible_id) + 1) {
  568. /* Normalize to upper case */
  569. hid_internal_towupper(compatible_id);
  570. /* USB devices
  571. https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support
  572. https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers */
  573. if (wcsstr(compatible_id, L"USB") != NULL) {
  574. bus_type = HID_API_BUS_USB;
  575. break;
  576. }
  577. /* Bluetooth devices
  578. https://docs.microsoft.com/windows-hardware/drivers/bluetooth/installing-a-bluetooth-device */
  579. if (wcsstr(compatible_id, L"BTHENUM") != NULL) {
  580. bus_type = HID_API_BUS_BLUETOOTH;
  581. break;
  582. }
  583. /* Bluetooth LE devices */
  584. if (wcsstr(compatible_id, L"BTHLEDEVICE") != NULL) {
  585. bus_type = HID_API_BUS_BLUETOOTH;
  586. break;
  587. }
  588. /* I2C devices
  589. https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support-and-power-management */
  590. if (wcsstr(compatible_id, L"PNP0C50") != NULL) {
  591. bus_type = HID_API_BUS_I2C;
  592. break;
  593. }
  594. /* SPI devices
  595. https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-for-spi */
  596. if (wcsstr(compatible_id, L"PNP0C51") != NULL) {
  597. bus_type = HID_API_BUS_SPI;
  598. break;
  599. }
  600. }
  601. end:
  602. free(device_id);
  603. free(compatible_ids);
  604. return bus_type;
  605. }
  606. #endif /* HIDAPI_IGNORE_DEVICE */
  607. static void hid_internal_get_info(const wchar_t* interface_path, struct hid_device_info* dev)
  608. {
  609. wchar_t *device_id = NULL, *compatible_ids = NULL;
  610. CONFIGRET cr;
  611. DEVINST dev_node;
  612. /* Get the device id from interface path */
  613. device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING);
  614. if (!device_id)
  615. goto end;
  616. /* Open devnode from device id */
  617. cr = CM_Locate_DevNodeW(&dev_node, (DEVINSTID_W)device_id, CM_LOCATE_DEVNODE_NORMAL);
  618. if (cr != CR_SUCCESS)
  619. goto end;
  620. /* Get devnode parent */
  621. cr = CM_Get_Parent(&dev_node, dev_node, 0);
  622. if (cr != CR_SUCCESS)
  623. goto end;
  624. /* Get the compatible ids from parent devnode */
  625. compatible_ids = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_CompatibleIds, DEVPROP_TYPE_STRING_LIST);
  626. if (!compatible_ids)
  627. goto end;
  628. /* Now we can parse parent's compatible IDs to find out the device bus type */
  629. for (wchar_t* compatible_id = compatible_ids; *compatible_id; compatible_id += wcslen(compatible_id) + 1) {
  630. /* Normalize to upper case */
  631. hid_internal_towupper(compatible_id);
  632. /* USB devices
  633. https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support
  634. https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers */
  635. if (wcsstr(compatible_id, L"USB") != NULL) {
  636. dev->bus_type = HID_API_BUS_USB;
  637. hid_internal_get_usb_info(dev, dev_node);
  638. break;
  639. }
  640. /* Bluetooth devices
  641. https://docs.microsoft.com/windows-hardware/drivers/bluetooth/installing-a-bluetooth-device */
  642. if (wcsstr(compatible_id, L"BTHENUM") != NULL) {
  643. dev->bus_type = HID_API_BUS_BLUETOOTH;
  644. break;
  645. }
  646. /* Bluetooth LE devices */
  647. if (wcsstr(compatible_id, L"BTHLEDEVICE") != NULL) {
  648. dev->bus_type = HID_API_BUS_BLUETOOTH;
  649. hid_internal_get_ble_info(dev, dev_node);
  650. break;
  651. }
  652. /* I2C devices
  653. https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support-and-power-management */
  654. if (wcsstr(compatible_id, L"PNP0C50") != NULL) {
  655. dev->bus_type = HID_API_BUS_I2C;
  656. break;
  657. }
  658. /* SPI devices
  659. https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-for-spi */
  660. if (wcsstr(compatible_id, L"PNP0C51") != NULL) {
  661. dev->bus_type = HID_API_BUS_SPI;
  662. break;
  663. }
  664. }
  665. end:
  666. free(device_id);
  667. free(compatible_ids);
  668. }
  669. static char *hid_internal_UTF16toUTF8(const wchar_t *src)
  670. {
  671. char *dst = NULL;
  672. int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, NULL, 0, NULL, NULL);
  673. if (len) {
  674. dst = (char*)calloc(len, sizeof(char));
  675. if (dst == NULL) {
  676. return NULL;
  677. }
  678. WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, dst, len, NULL, NULL);
  679. }
  680. return dst;
  681. }
  682. static wchar_t *hid_internal_UTF8toUTF16(const char *src)
  683. {
  684. wchar_t *dst = NULL;
  685. int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, NULL, 0);
  686. if (len) {
  687. dst = (wchar_t*)calloc(len, sizeof(wchar_t));
  688. if (dst == NULL) {
  689. return NULL;
  690. }
  691. MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, dst, len);
  692. }
  693. return dst;
  694. }
  695. static struct hid_device_info *hid_internal_get_device_info(const wchar_t *path, HANDLE handle)
  696. {
  697. struct hid_device_info *dev = NULL; /* return object */
  698. HIDD_ATTRIBUTES attrib;
  699. PHIDP_PREPARSED_DATA pp_data = NULL;
  700. HIDP_CAPS caps;
  701. wchar_t string[MAX_STRING_WCHARS];
  702. /* Create the record. */
  703. dev = (struct hid_device_info*)calloc(1, sizeof(struct hid_device_info));
  704. if (dev == NULL) {
  705. return NULL;
  706. }
  707. /* Fill out the record */
  708. dev->next = NULL;
  709. dev->path = hid_internal_UTF16toUTF8(path);
  710. dev->interface_number = -1;
  711. attrib.Size = sizeof(HIDD_ATTRIBUTES);
  712. if (HidD_GetAttributes(handle, &attrib)) {
  713. /* VID/PID */
  714. dev->vendor_id = attrib.VendorID;
  715. dev->product_id = attrib.ProductID;
  716. /* Release Number */
  717. dev->release_number = attrib.VersionNumber;
  718. }
  719. /* Get the Usage Page and Usage for this device. */
  720. if (HidD_GetPreparsedData(handle, &pp_data)) {
  721. if (HidP_GetCaps(pp_data, &caps) == HIDP_STATUS_SUCCESS) {
  722. dev->usage_page = caps.UsagePage;
  723. dev->usage = caps.Usage;
  724. }
  725. HidD_FreePreparsedData(pp_data);
  726. }
  727. /* Serial Number */
  728. string[0] = L'\0';
  729. HidD_GetSerialNumberString(handle, string, sizeof(string));
  730. string[MAX_STRING_WCHARS - 1] = L'\0';
  731. dev->serial_number = _wcsdup(string);
  732. /* Manufacturer String */
  733. string[0] = L'\0';
  734. HidD_GetManufacturerString(handle, string, sizeof(string));
  735. string[MAX_STRING_WCHARS - 1] = L'\0';
  736. dev->manufacturer_string = _wcsdup(string);
  737. /* Product String */
  738. string[0] = L'\0';
  739. HidD_GetProductString(handle, string, sizeof(string));
  740. string[MAX_STRING_WCHARS - 1] = L'\0';
  741. dev->product_string = _wcsdup(string);
  742. hid_internal_get_info(path, dev);
  743. return dev;
  744. }
  745. static int hid_blacklist(unsigned short vendor_id, unsigned short product_id)
  746. {
  747. size_t i;
  748. static const struct { unsigned short vid; unsigned short pid; } known_bad[] = {
  749. { 0x045E, 0x0822 }, /* Microsoft Precision Mouse - causes deadlock asking for device details */
  750. { 0x0738, 0x2217 }, /* SPEEDLINK COMPETITION PRO - turns into an Android controller when enumerated */
  751. { 0x0D8C, 0x0014 }, /* Sharkoon Skiller SGH2 headset - causes deadlock asking for device details */
  752. { 0x1532, 0x0109 }, /* Razer Lycosa Gaming keyboard - causes deadlock asking for device details */
  753. { 0x1532, 0x010B }, /* Razer Arctosa Gaming keyboard - causes deadlock asking for device details */
  754. { 0x1B1C, 0x1B3D }, /* Corsair Gaming keyboard - causes deadlock asking for device details */
  755. { 0x1CCF, 0x0000 } /* All Konami Amusement Devices - causes deadlock asking for device details */
  756. };
  757. for (i = 0; i < (sizeof(known_bad)/sizeof(known_bad[0])); i++) {
  758. if ((vendor_id == known_bad[i].vid) && (product_id == known_bad[i].pid || known_bad[i].pid == 0x0000)) {
  759. return 1;
  760. }
  761. }
  762. return 0;
  763. }
  764. struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
  765. {
  766. struct hid_device_info *root = NULL; /* return object */
  767. struct hid_device_info *cur_dev = NULL;
  768. GUID interface_class_guid;
  769. CONFIGRET cr;
  770. wchar_t* device_interface_list = NULL;
  771. DWORD len;
  772. if (hid_init() < 0) {
  773. /* register_global_error: global error is reset by hid_init */
  774. return NULL;
  775. }
  776. /* Retrieve HID Interface Class GUID
  777. https://docs.microsoft.com/windows-hardware/drivers/install/guid-devinterface-hid */
  778. HidD_GetHidGuid(&interface_class_guid);
  779. /* Get the list of all device interfaces belonging to the HID class. */
  780. /* Retry in case of list was changed between calls to
  781. CM_Get_Device_Interface_List_SizeW and CM_Get_Device_Interface_ListW */
  782. do {
  783. cr = CM_Get_Device_Interface_List_SizeW(&len, &interface_class_guid, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
  784. if (cr != CR_SUCCESS) {
  785. register_global_error(L"Failed to get size of HID device interface list");
  786. break;
  787. }
  788. if (device_interface_list != NULL) {
  789. free(device_interface_list);
  790. }
  791. device_interface_list = (wchar_t*)calloc(len, sizeof(wchar_t));
  792. if (device_interface_list == NULL) {
  793. register_global_error(L"Failed to allocate memory for HID device interface list");
  794. return NULL;
  795. }
  796. cr = CM_Get_Device_Interface_ListW(&interface_class_guid, NULL, device_interface_list, len, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
  797. if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL) {
  798. register_global_error(L"Failed to get HID device interface list");
  799. }
  800. } while (cr == CR_BUFFER_SMALL);
  801. if (cr != CR_SUCCESS) {
  802. goto end_of_function;
  803. }
  804. /* Iterate over each device interface in the HID class, looking for the right one. */
  805. for (wchar_t* device_interface = device_interface_list; *device_interface; device_interface += wcslen(device_interface) + 1) {
  806. HANDLE device_handle = INVALID_HANDLE_VALUE;
  807. HIDD_ATTRIBUTES attrib;
  808. /* XInput devices don't get real HID reports and are better handled by the raw input driver */
  809. if (wcsstr(device_interface, L"&IG_") != NULL) {
  810. continue;
  811. }
  812. /* Open read-only handle to the device */
  813. device_handle = open_device(device_interface, FALSE);
  814. /* Check validity of device_handle. */
  815. if (device_handle == INVALID_HANDLE_VALUE) {
  816. /* Unable to open the device. */
  817. continue;
  818. }
  819. /* Get the Vendor ID and Product ID for this device. */
  820. attrib.Size = sizeof(HIDD_ATTRIBUTES);
  821. if (!HidD_GetAttributes(device_handle, &attrib)) {
  822. goto cont_close;
  823. }
  824. #ifdef HIDAPI_IGNORE_DEVICE
  825. /* See if there are any devices we should skip in enumeration */
  826. hid_bus_type bus_type = get_bus_type(device_interface);
  827. PHIDP_PREPARSED_DATA pp_data = NULL;
  828. HIDP_CAPS caps = { 0 };
  829. if (HidD_GetPreparsedData(device_handle, &pp_data)) {
  830. HidP_GetCaps(pp_data, &caps);
  831. HidD_FreePreparsedData(pp_data);
  832. }
  833. if (HIDAPI_IGNORE_DEVICE(bus_type, attrib.VendorID, attrib.ProductID, caps.UsagePage, caps.Usage)) {
  834. goto cont_close;
  835. }
  836. #endif
  837. /* Check the VID/PID to see if we should add this
  838. device to the enumeration list. */
  839. if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&
  840. (product_id == 0x0 || attrib.ProductID == product_id) &&
  841. !hid_blacklist(attrib.VendorID, attrib.ProductID)) {
  842. /* VID/PID match. Create the record. */
  843. struct hid_device_info *tmp = hid_internal_get_device_info(device_interface, device_handle);
  844. if (tmp == NULL) {
  845. goto cont_close;
  846. }
  847. if (cur_dev) {
  848. cur_dev->next = tmp;
  849. }
  850. else {
  851. root = tmp;
  852. }
  853. cur_dev = tmp;
  854. }
  855. cont_close:
  856. CloseHandle(device_handle);
  857. }
  858. if (root == NULL) {
  859. if (vendor_id == 0 && product_id == 0) {
  860. register_global_error(L"No HID devices found in the system.");
  861. } else {
  862. register_global_error(L"No HID devices with requested VID/PID found in the system.");
  863. }
  864. }
  865. end_of_function:
  866. free(device_interface_list);
  867. return root;
  868. }
  869. void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
  870. {
  871. /* TODO: Merge this with the Linux version. This function is platform-independent. */
  872. struct hid_device_info *d = devs;
  873. while (d) {
  874. struct hid_device_info *next = d->next;
  875. free(d->path);
  876. free(d->serial_number);
  877. free(d->manufacturer_string);
  878. free(d->product_string);
  879. free(d);
  880. d = next;
  881. }
  882. }
  883. HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
  884. {
  885. /* TODO: Merge this functions with the Linux version. This function should be platform independent. */
  886. struct hid_device_info *devs, *cur_dev;
  887. const char *path_to_open = NULL;
  888. hid_device *handle = NULL;
  889. /* register_global_error: global error is reset by hid_enumerate/hid_init */
  890. devs = hid_enumerate(vendor_id, product_id);
  891. if (!devs) {
  892. /* register_global_error: global error is already set by hid_enumerate */
  893. return NULL;
  894. }
  895. cur_dev = devs;
  896. while (cur_dev) {
  897. if (cur_dev->vendor_id == vendor_id &&
  898. cur_dev->product_id == product_id) {
  899. if (serial_number) {
  900. if (cur_dev->serial_number && wcscmp(serial_number, cur_dev->serial_number) == 0) {
  901. path_to_open = cur_dev->path;
  902. break;
  903. }
  904. }
  905. else {
  906. path_to_open = cur_dev->path;
  907. break;
  908. }
  909. }
  910. cur_dev = cur_dev->next;
  911. }
  912. if (path_to_open) {
  913. /* Open the device */
  914. handle = hid_open_path(path_to_open);
  915. } else {
  916. register_global_error(L"Device with requested VID/PID/(SerialNumber) not found");
  917. }
  918. hid_free_enumeration(devs);
  919. return handle;
  920. }
  921. HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
  922. {
  923. hid_device *dev = NULL;
  924. wchar_t* interface_path = NULL;
  925. HANDLE device_handle = INVALID_HANDLE_VALUE;
  926. PHIDP_PREPARSED_DATA pp_data = NULL;
  927. HIDP_CAPS caps;
  928. if (hid_init() < 0) {
  929. /* register_global_error: global error is reset by hid_init */
  930. goto end_of_function;
  931. }
  932. interface_path = hid_internal_UTF8toUTF16(path);
  933. if (!interface_path) {
  934. register_global_error(L"Path conversion failure");
  935. goto end_of_function;
  936. }
  937. /* Open a handle to the device */
  938. device_handle = open_device(interface_path, TRUE);
  939. /* Check validity of write_handle. */
  940. if (device_handle == INVALID_HANDLE_VALUE) {
  941. /* System devices, such as keyboards and mice, cannot be opened in
  942. read-write mode, because the system takes exclusive control over
  943. them. This is to prevent keyloggers. However, feature reports
  944. can still be sent and received. Retry opening the device, but
  945. without read/write access. */
  946. device_handle = open_device(interface_path, FALSE);
  947. /* Check the validity of the limited device_handle. */
  948. if (device_handle == INVALID_HANDLE_VALUE) {
  949. register_global_winapi_error(L"open_device");
  950. goto end_of_function;
  951. }
  952. }
  953. /* Set the Input Report buffer size to 64 reports. */
  954. if (!HidD_SetNumInputBuffers(device_handle, 64)) {
  955. register_global_winapi_error(L"set input buffers");
  956. goto end_of_function;
  957. }
  958. /* Get the Input Report length for the device. */
  959. if (!HidD_GetPreparsedData(device_handle, &pp_data)) {
  960. register_global_winapi_error(L"get preparsed data");
  961. goto end_of_function;
  962. }
  963. if (HidP_GetCaps(pp_data, &caps) != HIDP_STATUS_SUCCESS) {
  964. register_global_error(L"HidP_GetCaps");
  965. goto end_of_function;
  966. }
  967. dev = new_hid_device();
  968. if (dev == NULL) {
  969. register_global_error(L"hid_device allocation error");
  970. goto end_of_function;
  971. }
  972. dev->device_handle = device_handle;
  973. device_handle = INVALID_HANDLE_VALUE;
  974. dev->output_report_length = caps.OutputReportByteLength;
  975. dev->input_report_length = caps.InputReportByteLength;
  976. dev->feature_report_length = caps.FeatureReportByteLength;
  977. dev->read_buf = (char*) malloc(dev->input_report_length);
  978. dev->device_info = hid_internal_get_device_info(interface_path, dev->device_handle);
  979. /* On Windows 7, we need to use hid_write_output_report() over Bluetooth */
  980. if (dev->output_report_length > 512) {
  981. dev->use_hid_write_output_report = !IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN8 ), LOBYTE( _WIN32_WINNT_WIN8 ), 0 );
  982. }
  983. end_of_function:
  984. free(interface_path);
  985. CloseHandle(device_handle);
  986. if (pp_data) {
  987. HidD_FreePreparsedData(pp_data);
  988. }
  989. return dev;
  990. }
  991. static int hid_write_output_report(hid_device *dev, const unsigned char *data, size_t length)
  992. {
  993. BOOL res;
  994. res = HidD_SetOutputReport(dev->device_handle, (void *)data, (ULONG)length);
  995. if (res)
  996. return (int)length;
  997. else
  998. return -1;
  999. }
  1000. int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
  1001. {
  1002. DWORD bytes_written = 0;
  1003. int function_result = -1;
  1004. BOOL res;
  1005. BOOL overlapped = FALSE;
  1006. unsigned char *buf;
  1007. if (!data || !length) {
  1008. register_string_error(dev, L"Zero buffer/length");
  1009. return function_result;
  1010. }
  1011. register_string_error(dev, NULL);
  1012. if (dev->use_hid_write_output_report) {
  1013. return hid_write_output_report(dev, data, length);
  1014. }
  1015. /* Make sure the right number of bytes are passed to WriteFile. Windows
  1016. expects the number of bytes which are in the _longest_ report (plus
  1017. one for the report number) bytes even if the data is a report
  1018. which is shorter than that. Windows gives us this value in
  1019. caps.OutputReportByteLength. If a user passes in fewer bytes than this,
  1020. use cached temporary buffer which is the proper size. */
  1021. if (length >= dev->output_report_length) {
  1022. /* The user passed the right number of bytes. Use the buffer as-is. */
  1023. buf = (unsigned char *) data;
  1024. } else {
  1025. if (dev->write_buf == NULL)
  1026. dev->write_buf = (unsigned char *) malloc(dev->output_report_length);
  1027. buf = dev->write_buf;
  1028. memcpy(buf, data, length);
  1029. memset(buf + length, 0, dev->output_report_length - length);
  1030. length = dev->output_report_length;
  1031. }
  1032. res = WriteFile(dev->device_handle, buf, (DWORD) length, NULL, &dev->write_ol);
  1033. if (!res) {
  1034. if (GetLastError() != ERROR_IO_PENDING) {
  1035. /* WriteFile() failed. Return error. */
  1036. register_winapi_error(dev, L"WriteFile");
  1037. goto end_of_function;
  1038. }
  1039. overlapped = TRUE;
  1040. }
  1041. if (overlapped) {
  1042. /* Wait for the transaction to complete. This makes
  1043. hid_write() synchronous. */
  1044. res = WaitForSingleObject(dev->write_ol.hEvent, 1000);
  1045. if (res != WAIT_OBJECT_0) {
  1046. /* There was a Timeout. */
  1047. register_winapi_error(dev, L"hid_write/WaitForSingleObject");
  1048. goto end_of_function;
  1049. }
  1050. /* Get the result. */
  1051. res = GetOverlappedResult(dev->device_handle, &dev->write_ol, &bytes_written, FALSE/*wait*/);
  1052. if (res) {
  1053. function_result = bytes_written;
  1054. }
  1055. else {
  1056. /* The Write operation failed. */
  1057. register_winapi_error(dev, L"hid_write/GetOverlappedResult");
  1058. goto end_of_function;
  1059. }
  1060. }
  1061. end_of_function:
  1062. return function_result;
  1063. }
  1064. int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
  1065. {
  1066. DWORD bytes_read = 0;
  1067. size_t copy_len = 0;
  1068. BOOL res = FALSE;
  1069. BOOL overlapped = FALSE;
  1070. if (!data || !length) {
  1071. register_string_error(dev, L"Zero buffer/length");
  1072. return -1;
  1073. }
  1074. register_string_error(dev, NULL);
  1075. /* Copy the handle for convenience. */
  1076. HANDLE ev = dev->ol.hEvent;
  1077. if (!dev->read_pending) {
  1078. /* Start an Overlapped I/O read. */
  1079. dev->read_pending = TRUE;
  1080. memset(dev->read_buf, 0, dev->input_report_length);
  1081. ResetEvent(ev);
  1082. res = ReadFile(dev->device_handle, dev->read_buf, (DWORD) dev->input_report_length, &bytes_read, &dev->ol);
  1083. if (!res) {
  1084. if (GetLastError() != ERROR_IO_PENDING) {
  1085. /* ReadFile() has failed.
  1086. Clean up and return error. */
  1087. register_winapi_error(dev, L"ReadFile");
  1088. CancelIo(dev->device_handle);
  1089. dev->read_pending = FALSE;
  1090. goto end_of_function;
  1091. }
  1092. overlapped = TRUE;
  1093. }
  1094. }
  1095. else {
  1096. overlapped = TRUE;
  1097. }
  1098. if (overlapped) {
  1099. /* See if there is any data yet. */
  1100. res = WaitForSingleObject(ev, milliseconds >= 0 ? (DWORD)milliseconds : INFINITE);
  1101. if (res != WAIT_OBJECT_0) {
  1102. /* There was no data this time. Return zero bytes available,
  1103. but leave the Overlapped I/O running. */
  1104. return 0;
  1105. }
  1106. /* Get the number of bytes read. The actual data has been copied to the data[]
  1107. array which was passed to ReadFile(). We must not wait here because we've
  1108. already waited on our event above, and since it's auto-reset, it will have
  1109. been reset back to unsignalled by now. */
  1110. res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, FALSE/*don't wait now - already did on the prev step*/);
  1111. }
  1112. /* Set pending back to false, even if GetOverlappedResult() returned error. */
  1113. dev->read_pending = FALSE;
  1114. if (res && bytes_read > 0) {
  1115. if (dev->read_buf[0] == 0x0) {
  1116. /* If report numbers aren't being used, but Windows sticks a report
  1117. number (0x0) on the beginning of the report anyway. To make this
  1118. work like the other platforms, and to make it work more like the
  1119. HID spec, we'll skip over this byte. */
  1120. bytes_read--;
  1121. copy_len = length > bytes_read ? bytes_read : length;
  1122. memcpy(data, dev->read_buf+1, copy_len);
  1123. }
  1124. else {
  1125. /* Copy the whole buffer, report number and all. */
  1126. copy_len = length > bytes_read ? bytes_read : length;
  1127. memcpy(data, dev->read_buf, copy_len);
  1128. }
  1129. }
  1130. if (!res) {
  1131. register_winapi_error(dev, L"hid_read_timeout/GetOverlappedResult");
  1132. }
  1133. end_of_function:
  1134. if (!res) {
  1135. return -1;
  1136. }
  1137. return (int) copy_len;
  1138. }
  1139. int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length)
  1140. {
  1141. return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
  1142. }
  1143. int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock)
  1144. {
  1145. dev->blocking = !nonblock;
  1146. return 0; /* Success */
  1147. }
  1148. int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
  1149. {
  1150. BOOL res = FALSE;
  1151. unsigned char *buf;
  1152. size_t length_to_send;
  1153. if (!data || !length) {
  1154. register_string_error(dev, L"Zero buffer/length");
  1155. return -1;
  1156. }
  1157. register_string_error(dev, NULL);
  1158. /* Windows expects at least caps.FeatureReportByteLength bytes passed
  1159. to HidD_SetFeature(), even if the report is shorter. Any less sent and
  1160. the function fails with error ERROR_INVALID_PARAMETER set. Any more
  1161. and HidD_SetFeature() silently truncates the data sent in the report
  1162. to caps.FeatureReportByteLength. */
  1163. if (length >= dev->feature_report_length) {
  1164. buf = (unsigned char *) data;
  1165. length_to_send = length;
  1166. } else {
  1167. if (dev->feature_buf == NULL)
  1168. dev->feature_buf = (unsigned char *) malloc(dev->feature_report_length);
  1169. buf = dev->feature_buf;
  1170. memcpy(buf, data, length);
  1171. memset(buf + length, 0, dev->feature_report_length - length);
  1172. length_to_send = dev->feature_report_length;
  1173. }
  1174. res = HidD_SetFeature(dev->device_handle, (PVOID)buf, (DWORD) length_to_send);
  1175. if (!res) {
  1176. register_winapi_error(dev, L"HidD_SetFeature");
  1177. return -1;
  1178. }
  1179. return (int) length;
  1180. }
  1181. static int hid_get_report(hid_device *dev, DWORD report_type, unsigned char *data, size_t length)
  1182. {
  1183. BOOL res;
  1184. DWORD bytes_returned = 0;
  1185. OVERLAPPED ol;
  1186. memset(&ol, 0, sizeof(ol));
  1187. if (!data || !length) {
  1188. register_string_error(dev, L"Zero buffer/length");
  1189. return -1;
  1190. }
  1191. register_string_error(dev, NULL);
  1192. res = DeviceIoControl(dev->device_handle,
  1193. report_type,
  1194. data, (DWORD) length,
  1195. data, (DWORD) length,
  1196. &bytes_returned, &ol);
  1197. if (!res) {
  1198. if (GetLastError() != ERROR_IO_PENDING) {
  1199. /* DeviceIoControl() failed. Return error. */
  1200. register_winapi_error(dev, L"Get Input/Feature Report DeviceIoControl");
  1201. return -1;
  1202. }
  1203. }
  1204. /* Wait here until the write is done. This makes
  1205. hid_get_feature_report() synchronous. */
  1206. res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
  1207. if (!res) {
  1208. /* The operation failed. */
  1209. register_winapi_error(dev, L"Get Input/Feature Report GetOverLappedResult");
  1210. return -1;
  1211. }
  1212. /* When numbered reports aren't used,
  1213. bytes_returned seem to include only what is actually received from the device
  1214. (not including the first byte with 0, as an indication "no numbered reports"). */
  1215. if (data[0] == 0x0) {
  1216. bytes_returned++;
  1217. }
  1218. return bytes_returned;
  1219. }
  1220. int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
  1221. {
  1222. /* We could use HidD_GetFeature() instead, but it doesn't give us an actual length, unfortunately */
  1223. return hid_get_report(dev, IOCTL_HID_GET_FEATURE, data, length);
  1224. }
  1225. int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
  1226. {
  1227. /* We could use HidD_GetInputReport() instead, but it doesn't give us an actual length, unfortunately */
  1228. return hid_get_report(dev, IOCTL_HID_GET_INPUT_REPORT, data, length);
  1229. }
  1230. #if defined(__GNUC__)
  1231. # pragma GCC diagnostic push
  1232. # pragma GCC diagnostic ignored "-Wcast-function-type"
  1233. #endif
  1234. void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
  1235. {
  1236. typedef BOOL (WINAPI *CancelIoEx_t)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
  1237. CancelIoEx_t CancelIoExFunc = (CancelIoEx_t)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CancelIoEx");
  1238. if (!dev)
  1239. return;
  1240. if (CancelIoExFunc) {
  1241. CancelIoExFunc(dev->device_handle, NULL);
  1242. } else {
  1243. /* Windows XP, this will only cancel I/O on the current thread */
  1244. CancelIo(dev->device_handle);
  1245. }
  1246. if (dev->read_pending) {
  1247. DWORD bytes_read = 0;
  1248. GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
  1249. }
  1250. free_hid_device(dev);
  1251. }
  1252. #if defined(__GNUC__)
  1253. # pragma GCC diagnostic pop
  1254. #endif
  1255. int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
  1256. {
  1257. if (!string || !maxlen) {
  1258. register_string_error(dev, L"Zero buffer/length");
  1259. return -1;
  1260. }
  1261. if (!dev->device_info) {
  1262. register_string_error(dev, L"NULL device info");
  1263. return -1;
  1264. }
  1265. wcsncpy(string, dev->device_info->manufacturer_string, maxlen);
  1266. string[maxlen - 1] = L'\0';
  1267. register_string_error(dev, NULL);
  1268. return 0;
  1269. }
  1270. int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
  1271. {
  1272. if (!string || !maxlen) {
  1273. register_string_error(dev, L"Zero buffer/length");
  1274. return -1;
  1275. }
  1276. if (!dev->device_info) {
  1277. register_string_error(dev, L"NULL device info");
  1278. return -1;
  1279. }
  1280. wcsncpy(string, dev->device_info->product_string, maxlen);
  1281. string[maxlen - 1] = L'\0';
  1282. register_string_error(dev, NULL);
  1283. return 0;
  1284. }
  1285. int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
  1286. {
  1287. if (!string || !maxlen) {
  1288. register_string_error(dev, L"Zero buffer/length");
  1289. return -1;
  1290. }
  1291. if (!dev->device_info) {
  1292. register_string_error(dev, L"NULL device info");
  1293. return -1;
  1294. }
  1295. wcsncpy(string, dev->device_info->serial_number, maxlen);
  1296. string[maxlen - 1] = L'\0';
  1297. register_string_error(dev, NULL);
  1298. return 0;
  1299. }
  1300. HID_API_EXPORT struct hid_device_info * HID_API_CALL hid_get_device_info(hid_device *dev) {
  1301. if (!dev->device_info)
  1302. {
  1303. register_string_error(dev, L"NULL device info");
  1304. return NULL;
  1305. }
  1306. return dev->device_info;
  1307. }
  1308. int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
  1309. {
  1310. BOOL res;
  1311. res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * (DWORD) MIN(maxlen, MAX_STRING_WCHARS));
  1312. if (!res) {
  1313. register_winapi_error(dev, L"HidD_GetIndexedString");
  1314. return -1;
  1315. }
  1316. register_string_error(dev, NULL);
  1317. return 0;
  1318. }
  1319. int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *container_id)
  1320. {
  1321. wchar_t *interface_path = NULL, *device_id = NULL;
  1322. CONFIGRET cr = CR_FAILURE;
  1323. DEVINST dev_node;
  1324. DEVPROPTYPE property_type;
  1325. ULONG len;
  1326. if (!container_id) {
  1327. register_string_error(dev, L"Invalid Container ID");
  1328. return -1;
  1329. }
  1330. register_string_error(dev, NULL);
  1331. interface_path = hid_internal_UTF8toUTF16(dev->device_info->path);
  1332. if (!interface_path) {
  1333. register_string_error(dev, L"Path conversion failure");
  1334. goto end;
  1335. }
  1336. /* Get the device id from interface path */
  1337. device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING);
  1338. if (!device_id) {
  1339. register_string_error(dev, L"Failed to get device interface property InstanceId");
  1340. goto end;
  1341. }
  1342. /* Open devnode from device id */
  1343. cr = CM_Locate_DevNodeW(&dev_node, (DEVINSTID_W)device_id, CM_LOCATE_DEVNODE_NORMAL);
  1344. if (cr != CR_SUCCESS) {
  1345. register_string_error(dev, L"Failed to locate device node");
  1346. goto end;
  1347. }
  1348. /* Get the container id from devnode */
  1349. len = sizeof(*container_id);
  1350. cr = CM_Get_DevNode_PropertyW(dev_node, &DEVPKEY_Device_ContainerId, &property_type, (PBYTE)container_id, &len, 0);
  1351. if (cr == CR_SUCCESS && property_type != DEVPROP_TYPE_GUID)
  1352. cr = CR_FAILURE;
  1353. if (cr != CR_SUCCESS)
  1354. register_string_error(dev, L"Failed to read ContainerId property from device node");
  1355. end:
  1356. free(interface_path);
  1357. free(device_id);
  1358. return cr == CR_SUCCESS ? 0 : -1;
  1359. }
  1360. int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size)
  1361. {
  1362. PHIDP_PREPARSED_DATA pp_data = NULL;
  1363. if (!HidD_GetPreparsedData(dev->device_handle, &pp_data) || pp_data == NULL) {
  1364. register_string_error(dev, L"HidD_GetPreparsedData");
  1365. return -1;
  1366. }
  1367. int res = hid_winapi_descriptor_reconstruct_pp_data(pp_data, buf, buf_size);
  1368. HidD_FreePreparsedData(pp_data);
  1369. return res;
  1370. }
  1371. HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
  1372. {
  1373. if (dev) {
  1374. if (dev->last_error_str == NULL)
  1375. return L"Success";
  1376. return (wchar_t*)dev->last_error_str;
  1377. }
  1378. if (last_global_error_str == NULL)
  1379. return L"Success";
  1380. return last_global_error_str;
  1381. }
  1382. #ifndef hidapi_winapi_EXPORTS
  1383. #include "hidapi_descriptor_reconstruct.c"
  1384. #endif
  1385. #ifdef __cplusplus
  1386. } /* extern "C" */
  1387. #endif