hid.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  1. /*******************************************************
  2. HIDAPI - Multi-Platform library for
  3. communication with HID devices.
  4. Alan Ott
  5. Signal 11 Software
  6. 2010-07-03
  7. Copyright 2010, 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. http://github.com/signal11/hidapi .
  17. ********************************************************/
  18. /* See Apple Technical Note TN2187 for details on IOHidManager. */
  19. #include <IOKit/hid/IOHIDManager.h>
  20. #include <IOKit/hid/IOHIDKeys.h>
  21. #include <IOKit/IOKitLib.h>
  22. #include <CoreFoundation/CoreFoundation.h>
  23. #include <wchar.h>
  24. #include <locale.h>
  25. #include <pthread.h>
  26. #include <sys/time.h>
  27. #include <unistd.h>
  28. #include <dlfcn.h>
  29. #include "hidapi.h"
  30. /* Barrier implementation because Mac OSX doesn't have pthread_barrier.
  31. It also doesn't have clock_gettime(). So much for POSIX and SUSv2.
  32. This implementation came from Brent Priddy and was posted on
  33. StackOverflow. It is used with his permission. */
  34. typedef int pthread_barrierattr_t;
  35. typedef struct pthread_barrier {
  36. pthread_mutex_t mutex;
  37. pthread_cond_t cond;
  38. int count;
  39. int trip_count;
  40. } pthread_barrier_t;
  41. static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
  42. {
  43. if(count == 0) {
  44. errno = EINVAL;
  45. return -1;
  46. }
  47. if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
  48. return -1;
  49. }
  50. if(pthread_cond_init(&barrier->cond, 0) < 0) {
  51. pthread_mutex_destroy(&barrier->mutex);
  52. return -1;
  53. }
  54. barrier->trip_count = count;
  55. barrier->count = 0;
  56. return 0;
  57. }
  58. static int pthread_barrier_destroy(pthread_barrier_t *barrier)
  59. {
  60. pthread_cond_destroy(&barrier->cond);
  61. pthread_mutex_destroy(&barrier->mutex);
  62. return 0;
  63. }
  64. static int pthread_barrier_wait(pthread_barrier_t *barrier)
  65. {
  66. pthread_mutex_lock(&barrier->mutex);
  67. ++(barrier->count);
  68. if(barrier->count >= barrier->trip_count)
  69. {
  70. barrier->count = 0;
  71. pthread_cond_broadcast(&barrier->cond);
  72. pthread_mutex_unlock(&barrier->mutex);
  73. return 1;
  74. }
  75. else
  76. {
  77. pthread_cond_wait(&barrier->cond, &(barrier->mutex));
  78. pthread_mutex_unlock(&barrier->mutex);
  79. return 0;
  80. }
  81. }
  82. static int return_data(hid_device *dev, unsigned char *data, size_t length);
  83. /* Linked List of input reports received from the device. */
  84. struct input_report {
  85. uint8_t *data;
  86. size_t len;
  87. struct input_report *next;
  88. };
  89. struct hid_device_ {
  90. IOHIDDeviceRef device_handle;
  91. int blocking;
  92. int uses_numbered_reports;
  93. int disconnected;
  94. CFStringRef run_loop_mode;
  95. CFRunLoopRef run_loop;
  96. CFRunLoopSourceRef source;
  97. uint8_t *input_report_buf;
  98. CFIndex max_input_report_len;
  99. struct input_report *input_reports;
  100. pthread_t thread;
  101. pthread_mutex_t mutex; /* Protects input_reports */
  102. pthread_cond_t condition;
  103. pthread_barrier_t barrier; /* Ensures correct startup sequence */
  104. pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */
  105. int shutdown_thread;
  106. };
  107. static hid_device *new_hid_device(void)
  108. {
  109. hid_device *dev = calloc(1, sizeof(hid_device));
  110. dev->device_handle = NULL;
  111. dev->blocking = 1;
  112. dev->uses_numbered_reports = 0;
  113. dev->disconnected = 0;
  114. dev->run_loop_mode = NULL;
  115. dev->run_loop = NULL;
  116. dev->source = NULL;
  117. dev->input_report_buf = NULL;
  118. dev->input_reports = NULL;
  119. dev->shutdown_thread = 0;
  120. /* Thread objects */
  121. pthread_mutex_init(&dev->mutex, NULL);
  122. pthread_cond_init(&dev->condition, NULL);
  123. pthread_barrier_init(&dev->barrier, NULL, 2);
  124. pthread_barrier_init(&dev->shutdown_barrier, NULL, 2);
  125. return dev;
  126. }
  127. static void free_hid_device(hid_device *dev)
  128. {
  129. if (!dev)
  130. return;
  131. /* Delete any input reports still left over. */
  132. struct input_report *rpt = dev->input_reports;
  133. while (rpt) {
  134. struct input_report *next = rpt->next;
  135. free(rpt->data);
  136. free(rpt);
  137. rpt = next;
  138. }
  139. /* Free the string and the report buffer. The check for NULL
  140. is necessary here as CFRelease() doesn't handle NULL like
  141. free() and others do. */
  142. if (dev->run_loop_mode)
  143. CFRelease(dev->run_loop_mode);
  144. if (dev->source)
  145. CFRelease(dev->source);
  146. free(dev->input_report_buf);
  147. /* Clean up the thread objects */
  148. pthread_barrier_destroy(&dev->shutdown_barrier);
  149. pthread_barrier_destroy(&dev->barrier);
  150. pthread_cond_destroy(&dev->condition);
  151. pthread_mutex_destroy(&dev->mutex);
  152. /* Free the structure itself. */
  153. free(dev);
  154. }
  155. static IOHIDManagerRef hid_mgr = 0x0;
  156. #if 0
  157. static void register_error(hid_device *device, const char *op)
  158. {
  159. }
  160. #endif
  161. static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key)
  162. {
  163. CFTypeRef ref;
  164. int32_t value;
  165. ref = IOHIDDeviceGetProperty(device, key);
  166. if (ref) {
  167. if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
  168. CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value);
  169. return value;
  170. }
  171. }
  172. return 0;
  173. }
  174. static unsigned short get_vendor_id(IOHIDDeviceRef device)
  175. {
  176. return get_int_property(device, CFSTR(kIOHIDVendorIDKey));
  177. }
  178. static unsigned short get_product_id(IOHIDDeviceRef device)
  179. {
  180. return get_int_property(device, CFSTR(kIOHIDProductIDKey));
  181. }
  182. static int32_t get_max_report_length(IOHIDDeviceRef device)
  183. {
  184. return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey));
  185. }
  186. static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len)
  187. {
  188. CFStringRef str;
  189. if (!len)
  190. return 0;
  191. str = IOHIDDeviceGetProperty(device, prop);
  192. buf[0] = 0;
  193. if (str) {
  194. CFIndex str_len = CFStringGetLength(str);
  195. CFRange range;
  196. CFIndex used_buf_len;
  197. CFIndex chars_copied;
  198. len --;
  199. range.location = 0;
  200. range.length = ((size_t)str_len > len)? len: (size_t)str_len;
  201. chars_copied = CFStringGetBytes(str,
  202. range,
  203. kCFStringEncodingUTF32LE,
  204. (char)'?',
  205. FALSE,
  206. (UInt8*)buf,
  207. len * sizeof(wchar_t),
  208. &used_buf_len);
  209. if (chars_copied == len)
  210. buf[len] = 0; /* len is decremented above */
  211. else
  212. buf[chars_copied] = 0;
  213. return 0;
  214. }
  215. else
  216. return -1;
  217. }
  218. static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len)
  219. {
  220. return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len);
  221. }
  222. static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
  223. {
  224. return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len);
  225. }
  226. static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
  227. {
  228. return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len);
  229. }
  230. /* Implementation of wcsdup() for Mac. */
  231. static wchar_t *dup_wcs(const wchar_t *s)
  232. {
  233. size_t len = wcslen(s);
  234. wchar_t *ret = malloc((len+1)*sizeof(wchar_t));
  235. wcscpy(ret, s);
  236. return ret;
  237. }
  238. /* hidapi_IOHIDDeviceGetService()
  239. *
  240. * Return the io_service_t corresponding to a given IOHIDDeviceRef, either by:
  241. * - on OS X 10.6 and above, calling IOHIDDeviceGetService()
  242. * - on OS X 10.5, extract it from the IOHIDDevice struct
  243. */
  244. static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device)
  245. {
  246. static void *iokit_framework = NULL;
  247. static io_service_t (*dynamic_IOHIDDeviceGetService)(IOHIDDeviceRef device) = NULL;
  248. /* Use dlopen()/dlsym() to get a pointer to IOHIDDeviceGetService() if it exists.
  249. * If any of these steps fail, dynamic_IOHIDDeviceGetService will be left NULL
  250. * and the fallback method will be used.
  251. */
  252. if (iokit_framework == NULL) {
  253. iokit_framework = dlopen("/System/Library/IOKit.framework/IOKit", RTLD_LAZY);
  254. if (iokit_framework != NULL)
  255. dynamic_IOHIDDeviceGetService = dlsym(iokit_framework, "IOHIDDeviceGetService");
  256. }
  257. if (dynamic_IOHIDDeviceGetService != NULL) {
  258. /* Running on OS X 10.6 and above: IOHIDDeviceGetService() exists */
  259. return dynamic_IOHIDDeviceGetService(device);
  260. }
  261. else
  262. {
  263. /* Running on OS X 10.5: IOHIDDeviceGetService() doesn't exist.
  264. *
  265. * Be naughty and pull the service out of the IOHIDDevice.
  266. * IOHIDDevice is an opaque struct not exposed to applications, but its
  267. * layout is stable through all available versions of OS X.
  268. * Tested and working on OS X 10.5.8 i386, x86_64, and ppc.
  269. */
  270. struct IOHIDDevice_internal {
  271. /* The first field of the IOHIDDevice struct is a
  272. * CFRuntimeBase (which is a private CF struct).
  273. *
  274. * a, b, and c are the 3 fields that make up a CFRuntimeBase.
  275. * See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h
  276. *
  277. * The second field of the IOHIDDevice is the io_service_t we're looking for.
  278. */
  279. uintptr_t a;
  280. uint8_t b[4];
  281. #if __LP64__
  282. uint32_t c;
  283. #endif
  284. io_service_t service;
  285. };
  286. struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device;
  287. return tmp->service;
  288. }
  289. }
  290. /* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */
  291. static int init_hid_manager(void)
  292. {
  293. /* Initialize all the HID Manager Objects */
  294. hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
  295. if (hid_mgr) {
  296. IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
  297. IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
  298. return 0;
  299. }
  300. return -1;
  301. }
  302. /* Initialize the IOHIDManager if necessary. This is the public function, and
  303. it is safe to call this function repeatedly. Return 0 for success and -1
  304. for failure. */
  305. int HID_API_EXPORT hid_init(void)
  306. {
  307. if (!hid_mgr) {
  308. return init_hid_manager();
  309. }
  310. /* Already initialized. */
  311. return 0;
  312. }
  313. int HID_API_EXPORT hid_exit(void)
  314. {
  315. if (hid_mgr) {
  316. /* Close the HID manager. */
  317. IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone);
  318. CFRelease(hid_mgr);
  319. hid_mgr = NULL;
  320. }
  321. return 0;
  322. }
  323. static void process_pending_events(void) {
  324. SInt32 res;
  325. do {
  326. res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE);
  327. } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut);
  328. }
  329. struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
  330. {
  331. struct hid_device_info *root = NULL; /* return object */
  332. struct hid_device_info *cur_dev = NULL;
  333. CFIndex num_devices;
  334. int i;
  335. /* Set up the HID Manager if it hasn't been done */
  336. if (hid_init() < 0)
  337. return NULL;
  338. /* give the IOHIDManager a chance to update itself */
  339. process_pending_events();
  340. /* Get a list of the Devices */
  341. IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
  342. CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
  343. /* Convert the list into a C array so we can iterate easily. */
  344. num_devices = CFSetGetCount(device_set);
  345. IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
  346. CFSetGetValues(device_set, (const void **) device_array);
  347. /* Iterate over each device, making an entry for it. */
  348. for (i = 0; i < num_devices; i++) {
  349. unsigned short dev_vid;
  350. unsigned short dev_pid;
  351. #define BUF_LEN 256
  352. wchar_t buf[BUF_LEN];
  353. IOHIDDeviceRef dev = device_array[i];
  354. if (!dev) {
  355. continue;
  356. }
  357. dev_vid = get_vendor_id(dev);
  358. dev_pid = get_product_id(dev);
  359. /* Check the VID/PID against the arguments */
  360. if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
  361. (product_id == 0x0 || product_id == dev_pid)) {
  362. struct hid_device_info *tmp;
  363. io_object_t iokit_dev;
  364. kern_return_t res;
  365. io_string_t path;
  366. /* VID/PID match. Create the record. */
  367. tmp = malloc(sizeof(struct hid_device_info));
  368. if (cur_dev) {
  369. cur_dev->next = tmp;
  370. }
  371. else {
  372. root = tmp;
  373. }
  374. cur_dev = tmp;
  375. /* Get the Usage Page and Usage for this device. */
  376. cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey));
  377. cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey));
  378. /* Fill out the record */
  379. cur_dev->next = NULL;
  380. /* Fill in the path (IOService plane) */
  381. iokit_dev = hidapi_IOHIDDeviceGetService(dev);
  382. res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path);
  383. if (res == KERN_SUCCESS)
  384. cur_dev->path = strdup(path);
  385. else
  386. cur_dev->path = strdup("");
  387. /* Serial Number */
  388. get_serial_number(dev, buf, BUF_LEN);
  389. cur_dev->serial_number = dup_wcs(buf);
  390. /* Manufacturer and Product strings */
  391. get_manufacturer_string(dev, buf, BUF_LEN);
  392. cur_dev->manufacturer_string = dup_wcs(buf);
  393. get_product_string(dev, buf, BUF_LEN);
  394. cur_dev->product_string = dup_wcs(buf);
  395. /* VID/PID */
  396. cur_dev->vendor_id = dev_vid;
  397. cur_dev->product_id = dev_pid;
  398. /* Release Number */
  399. cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));
  400. /* Interface Number (Unsupported on Mac)*/
  401. cur_dev->interface_number = -1;
  402. }
  403. }
  404. free(device_array);
  405. CFRelease(device_set);
  406. return root;
  407. }
  408. void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
  409. {
  410. /* This function is identical to the Linux version. Platform independent. */
  411. struct hid_device_info *d = devs;
  412. while (d) {
  413. struct hid_device_info *next = d->next;
  414. free(d->path);
  415. free(d->serial_number);
  416. free(d->manufacturer_string);
  417. free(d->product_string);
  418. free(d);
  419. d = next;
  420. }
  421. }
  422. hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
  423. {
  424. /* This function is identical to the Linux version. Platform independent. */
  425. struct hid_device_info *devs, *cur_dev;
  426. const char *path_to_open = NULL;
  427. hid_device * handle = NULL;
  428. devs = hid_enumerate(vendor_id, product_id);
  429. cur_dev = devs;
  430. while (cur_dev) {
  431. if (cur_dev->vendor_id == vendor_id &&
  432. cur_dev->product_id == product_id) {
  433. if (serial_number) {
  434. if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
  435. path_to_open = cur_dev->path;
  436. break;
  437. }
  438. }
  439. else {
  440. path_to_open = cur_dev->path;
  441. break;
  442. }
  443. }
  444. cur_dev = cur_dev->next;
  445. }
  446. if (path_to_open) {
  447. /* Open the device */
  448. handle = hid_open_path(path_to_open);
  449. }
  450. hid_free_enumeration(devs);
  451. return handle;
  452. }
  453. static void hid_device_removal_callback(void *context, IOReturn result,
  454. void *sender)
  455. {
  456. /* Stop the Run Loop for this device. */
  457. hid_device *d = context;
  458. d->disconnected = 1;
  459. CFRunLoopStop(d->run_loop);
  460. }
  461. /* The Run Loop calls this function for each input report received.
  462. This function puts the data into a linked list to be picked up by
  463. hid_read(). */
  464. static void hid_report_callback(void *context, IOReturn result, void *sender,
  465. IOHIDReportType report_type, uint32_t report_id,
  466. uint8_t *report, CFIndex report_length)
  467. {
  468. struct input_report *rpt;
  469. hid_device *dev = context;
  470. /* Make a new Input Report object */
  471. rpt = calloc(1, sizeof(struct input_report));
  472. rpt->data = calloc(1, report_length);
  473. memcpy(rpt->data, report, report_length);
  474. rpt->len = report_length;
  475. rpt->next = NULL;
  476. /* Lock this section */
  477. pthread_mutex_lock(&dev->mutex);
  478. /* Attach the new report object to the end of the list. */
  479. if (dev->input_reports == NULL) {
  480. /* The list is empty. Put it at the root. */
  481. dev->input_reports = rpt;
  482. }
  483. else {
  484. /* Find the end of the list and attach. */
  485. struct input_report *cur = dev->input_reports;
  486. int num_queued = 0;
  487. while (cur->next != NULL) {
  488. cur = cur->next;
  489. num_queued++;
  490. }
  491. cur->next = rpt;
  492. /* Pop one off if we've reached 30 in the queue. This
  493. way we don't grow forever if the user never reads
  494. anything from the device. */
  495. if (num_queued > 30) {
  496. return_data(dev, NULL, 0);
  497. }
  498. }
  499. /* Signal a waiting thread that there is data. */
  500. pthread_cond_signal(&dev->condition);
  501. /* Unlock */
  502. pthread_mutex_unlock(&dev->mutex);
  503. }
  504. /* This gets called when the read_thread's run loop gets signaled by
  505. hid_close(), and serves to stop the read_thread's run loop. */
  506. static void perform_signal_callback(void *context)
  507. {
  508. hid_device *dev = context;
  509. CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/
  510. }
  511. static void *read_thread(void *param)
  512. {
  513. hid_device *dev = param;
  514. SInt32 code;
  515. /* Move the device's run loop to this thread. */
  516. IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
  517. /* Create the RunLoopSource which is used to signal the
  518. event loop to stop when hid_close() is called. */
  519. CFRunLoopSourceContext ctx;
  520. memset(&ctx, 0, sizeof(ctx));
  521. ctx.version = 0;
  522. ctx.info = dev;
  523. ctx.perform = &perform_signal_callback;
  524. dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx);
  525. CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode);
  526. /* Store off the Run Loop so it can be stopped from hid_close()
  527. and on device disconnection. */
  528. dev->run_loop = CFRunLoopGetCurrent();
  529. /* Notify the main thread that the read thread is up and running. */
  530. pthread_barrier_wait(&dev->barrier);
  531. /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
  532. reports into the hid_report_callback(). */
  533. while (!dev->shutdown_thread && !dev->disconnected) {
  534. code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
  535. /* Return if the device has been disconnected */
  536. if (code == kCFRunLoopRunFinished) {
  537. dev->disconnected = 1;
  538. break;
  539. }
  540. /* Break if The Run Loop returns Finished or Stopped. */
  541. if (code != kCFRunLoopRunTimedOut &&
  542. code != kCFRunLoopRunHandledSource) {
  543. /* There was some kind of error. Setting
  544. shutdown seems to make sense, but
  545. there may be something else more appropriate */
  546. dev->shutdown_thread = 1;
  547. break;
  548. }
  549. }
  550. /* Now that the read thread is stopping, Wake any threads which are
  551. waiting on data (in hid_read_timeout()). Do this under a mutex to
  552. make sure that a thread which is about to go to sleep waiting on
  553. the condition actually will go to sleep before the condition is
  554. signaled. */
  555. pthread_mutex_lock(&dev->mutex);
  556. pthread_cond_broadcast(&dev->condition);
  557. pthread_mutex_unlock(&dev->mutex);
  558. /* Wait here until hid_close() is called and makes it past
  559. the call to CFRunLoopWakeUp(). This thread still needs to
  560. be valid when that function is called on the other thread. */
  561. pthread_barrier_wait(&dev->shutdown_barrier);
  562. return NULL;
  563. }
  564. /* hid_open_path()
  565. *
  566. * path must be a valid path to an IOHIDDevice in the IOService plane
  567. * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver"
  568. */
  569. hid_device * HID_API_EXPORT hid_open_path(const char *path)
  570. {
  571. hid_device *dev = NULL;
  572. io_registry_entry_t entry = MACH_PORT_NULL;
  573. dev = new_hid_device();
  574. /* Set up the HID Manager if it hasn't been done */
  575. if (hid_init() < 0)
  576. return NULL;
  577. /* Get the IORegistry entry for the given path */
  578. entry = IORegistryEntryFromPath(kIOMasterPortDefault, path);
  579. if (entry == MACH_PORT_NULL) {
  580. /* Path wasn't valid (maybe device was removed?) */
  581. goto return_error;
  582. }
  583. /* Create an IOHIDDevice for the entry */
  584. dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry);
  585. if (dev->device_handle == NULL) {
  586. /* Error creating the HID device */
  587. goto return_error;
  588. }
  589. /* Open the IOHIDDevice */
  590. IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
  591. if (ret == kIOReturnSuccess) {
  592. char str[32];
  593. /* Create the buffers for receiving data */
  594. dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle);
  595. dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t));
  596. /* Create the Run Loop Mode for this device.
  597. printing the reference seems to work. */
  598. sprintf(str, "HIDAPI_%p", dev->device_handle);
  599. dev->run_loop_mode =
  600. CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
  601. /* Attach the device to a Run Loop */
  602. IOHIDDeviceRegisterInputReportCallback(
  603. dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
  604. &hid_report_callback, dev);
  605. IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);
  606. /* Start the read thread */
  607. pthread_create(&dev->thread, NULL, read_thread, dev);
  608. /* Wait here for the read thread to be initialized. */
  609. pthread_barrier_wait(&dev->barrier);
  610. IOObjectRelease(entry);
  611. return dev;
  612. }
  613. else {
  614. goto return_error;
  615. }
  616. return_error:
  617. if (dev->device_handle != NULL)
  618. CFRelease(dev->device_handle);
  619. if (entry != MACH_PORT_NULL)
  620. IOObjectRelease(entry);
  621. free_hid_device(dev);
  622. return NULL;
  623. }
  624. static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length)
  625. {
  626. const unsigned char *data_to_send;
  627. size_t length_to_send;
  628. IOReturn res;
  629. /* Return if the device has been disconnected. */
  630. if (dev->disconnected)
  631. return -1;
  632. if (data[0] == 0x0) {
  633. /* Not using numbered Reports.
  634. Don't send the report number. */
  635. data_to_send = data+1;
  636. length_to_send = length-1;
  637. }
  638. else {
  639. /* Using numbered Reports.
  640. Send the Report Number */
  641. data_to_send = data;
  642. length_to_send = length;
  643. }
  644. if (!dev->disconnected) {
  645. res = IOHIDDeviceSetReport(dev->device_handle,
  646. type,
  647. data[0], /* Report ID*/
  648. data_to_send, length_to_send);
  649. if (res == kIOReturnSuccess) {
  650. return length;
  651. }
  652. else
  653. return -1;
  654. }
  655. return -1;
  656. }
  657. int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
  658. {
  659. return set_report(dev, kIOHIDReportTypeOutput, data, length);
  660. }
  661. /* Helper function, so that this isn't duplicated in hid_read(). */
  662. static int return_data(hid_device *dev, unsigned char *data, size_t length)
  663. {
  664. /* Copy the data out of the linked list item (rpt) into the
  665. return buffer (data), and delete the liked list item. */
  666. struct input_report *rpt = dev->input_reports;
  667. size_t len = (length < rpt->len)? length: rpt->len;
  668. memcpy(data, rpt->data, len);
  669. dev->input_reports = rpt->next;
  670. free(rpt->data);
  671. free(rpt);
  672. return len;
  673. }
  674. static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex)
  675. {
  676. while (!dev->input_reports) {
  677. int res = pthread_cond_wait(cond, mutex);
  678. if (res != 0)
  679. return res;
  680. /* A res of 0 means we may have been signaled or it may
  681. be a spurious wakeup. Check to see that there's acutally
  682. data in the queue before returning, and if not, go back
  683. to sleep. See the pthread_cond_timedwait() man page for
  684. details. */
  685. if (dev->shutdown_thread || dev->disconnected)
  686. return -1;
  687. }
  688. return 0;
  689. }
  690. static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
  691. {
  692. while (!dev->input_reports) {
  693. int res = pthread_cond_timedwait(cond, mutex, abstime);
  694. if (res != 0)
  695. return res;
  696. /* A res of 0 means we may have been signaled or it may
  697. be a spurious wakeup. Check to see that there's acutally
  698. data in the queue before returning, and if not, go back
  699. to sleep. See the pthread_cond_timedwait() man page for
  700. details. */
  701. if (dev->shutdown_thread || dev->disconnected)
  702. return -1;
  703. }
  704. return 0;
  705. }
  706. int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
  707. {
  708. int bytes_read = -1;
  709. /* Lock the access to the report list. */
  710. pthread_mutex_lock(&dev->mutex);
  711. /* There's an input report queued up. Return it. */
  712. if (dev->input_reports) {
  713. /* Return the first one */
  714. bytes_read = return_data(dev, data, length);
  715. goto ret;
  716. }
  717. /* Return if the device has been disconnected. */
  718. if (dev->disconnected) {
  719. bytes_read = -1;
  720. goto ret;
  721. }
  722. if (dev->shutdown_thread) {
  723. /* This means the device has been closed (or there
  724. has been an error. An error code of -1 should
  725. be returned. */
  726. bytes_read = -1;
  727. goto ret;
  728. }
  729. /* There is no data. Go to sleep and wait for data. */
  730. if (milliseconds == -1) {
  731. /* Blocking */
  732. int res;
  733. res = cond_wait(dev, &dev->condition, &dev->mutex);
  734. if (res == 0)
  735. bytes_read = return_data(dev, data, length);
  736. else {
  737. /* There was an error, or a device disconnection. */
  738. bytes_read = -1;
  739. }
  740. }
  741. else if (milliseconds > 0) {
  742. /* Non-blocking, but called with timeout. */
  743. int res;
  744. struct timespec ts;
  745. struct timeval tv;
  746. gettimeofday(&tv, NULL);
  747. TIMEVAL_TO_TIMESPEC(&tv, &ts);
  748. ts.tv_sec += milliseconds / 1000;
  749. ts.tv_nsec += (milliseconds % 1000) * 1000000;
  750. if (ts.tv_nsec >= 1000000000L) {
  751. ts.tv_sec++;
  752. ts.tv_nsec -= 1000000000L;
  753. }
  754. res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts);
  755. if (res == 0)
  756. bytes_read = return_data(dev, data, length);
  757. else if (res == ETIMEDOUT)
  758. bytes_read = 0;
  759. else
  760. bytes_read = -1;
  761. }
  762. else {
  763. /* Purely non-blocking */
  764. bytes_read = 0;
  765. }
  766. ret:
  767. /* Unlock */
  768. pthread_mutex_unlock(&dev->mutex);
  769. return bytes_read;
  770. }
  771. int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
  772. {
  773. return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
  774. }
  775. int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
  776. {
  777. /* All Nonblocking operation is handled by the library. */
  778. dev->blocking = !nonblock;
  779. return 0;
  780. }
  781. int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
  782. {
  783. return set_report(dev, kIOHIDReportTypeFeature, data, length);
  784. }
  785. int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
  786. {
  787. CFIndex len = length;
  788. IOReturn res;
  789. /* Return if the device has been unplugged. */
  790. if (dev->disconnected)
  791. return -1;
  792. res = IOHIDDeviceGetReport(dev->device_handle,
  793. kIOHIDReportTypeFeature,
  794. data[0], /* Report ID */
  795. data, &len);
  796. if (res == kIOReturnSuccess)
  797. return len;
  798. else
  799. return -1;
  800. }
  801. void HID_API_EXPORT hid_close(hid_device *dev)
  802. {
  803. if (!dev)
  804. return;
  805. /* Disconnect the report callback before close. */
  806. if (!dev->disconnected) {
  807. IOHIDDeviceRegisterInputReportCallback(
  808. dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
  809. NULL, dev);
  810. IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev);
  811. IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode);
  812. IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
  813. }
  814. /* Cause read_thread() to stop. */
  815. dev->shutdown_thread = 1;
  816. /* Wake up the run thread's event loop so that the thread can exit. */
  817. CFRunLoopSourceSignal(dev->source);
  818. CFRunLoopWakeUp(dev->run_loop);
  819. /* Notify the read thread that it can shut down now. */
  820. pthread_barrier_wait(&dev->shutdown_barrier);
  821. /* Wait for read_thread() to end. */
  822. pthread_join(dev->thread, NULL);
  823. /* Close the OS handle to the device, but only if it's not
  824. been unplugged. If it's been unplugged, then calling
  825. IOHIDDeviceClose() will crash. */
  826. if (!dev->disconnected) {
  827. IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
  828. }
  829. /* Clear out the queue of received reports. */
  830. pthread_mutex_lock(&dev->mutex);
  831. while (dev->input_reports) {
  832. return_data(dev, NULL, 0);
  833. }
  834. pthread_mutex_unlock(&dev->mutex);
  835. CFRelease(dev->device_handle);
  836. free_hid_device(dev);
  837. }
  838. int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
  839. {
  840. return get_manufacturer_string(dev->device_handle, string, maxlen);
  841. }
  842. int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
  843. {
  844. return get_product_string(dev->device_handle, string, maxlen);
  845. }
  846. int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
  847. {
  848. return get_serial_number(dev->device_handle, string, maxlen);
  849. }
  850. int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
  851. {
  852. /* TODO: */
  853. return 0;
  854. }
  855. HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
  856. {
  857. /* TODO: */
  858. return NULL;
  859. }
  860. #if 0
  861. static int32_t get_location_id(IOHIDDeviceRef device)
  862. {
  863. return get_int_property(device, CFSTR(kIOHIDLocationIDKey));
  864. }
  865. static int32_t get_usage(IOHIDDeviceRef device)
  866. {
  867. int32_t res;
  868. res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey));
  869. if (!res)
  870. res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey));
  871. return res;
  872. }
  873. static int32_t get_usage_page(IOHIDDeviceRef device)
  874. {
  875. int32_t res;
  876. res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey));
  877. if (!res)
  878. res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey));
  879. return res;
  880. }
  881. static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len)
  882. {
  883. return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len);
  884. }
  885. int main(void)
  886. {
  887. IOHIDManagerRef mgr;
  888. int i;
  889. mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
  890. IOHIDManagerSetDeviceMatching(mgr, NULL);
  891. IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone);
  892. CFSetRef device_set = IOHIDManagerCopyDevices(mgr);
  893. CFIndex num_devices = CFSetGetCount(device_set);
  894. IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
  895. CFSetGetValues(device_set, (const void **) device_array);
  896. for (i = 0; i < num_devices; i++) {
  897. IOHIDDeviceRef dev = device_array[i];
  898. printf("Device: %p\n", dev);
  899. printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev));
  900. wchar_t serial[256], buf[256];
  901. char cbuf[256];
  902. get_serial_number(dev, serial, 256);
  903. printf(" Serial: %ls\n", serial);
  904. printf(" Loc: %ld\n", get_location_id(dev));
  905. get_transport(dev, buf, 256);
  906. printf(" Trans: %ls\n", buf);
  907. make_path(dev, cbuf, 256);
  908. printf(" Path: %s\n", cbuf);
  909. }
  910. return 0;
  911. }
  912. #endif