1 /*******************************************************
2 HIDAPI - Multi-Platform library for
3 communication with HID devices.
10 Copyright 2010, All Rights Reserved.
12 At the discretion of the user of this library,
13 this software may be licensed under the terms of the
14 GNU General Public License v3, a BSD-Style license, or the
15 original HIDAPI license as outlined in the LICENSE.txt,
16 LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
17 files located at the root of the source distribution.
18 These files may also be found in the public source
19 code repository located at:
20 http://github.com/signal11/hidapi .
21 ********************************************************/
23 /* See Apple Technical Note TN2187 for details on IOHidManager. */
25 #include <IOKit/hid/IOHIDManager.h>
26 #include <IOKit/hid/IOHIDKeys.h>
27 #include <IOKit/IOKitLib.h>
28 #include <CoreFoundation/CoreFoundation.h>
38 /* Barrier implementation because Mac OSX doesn't have pthread_barrier.
39 It also doesn't have clock_gettime(). So much for POSIX and SUSv2.
40 This implementation came from Brent Priddy and was posted on
41 StackOverflow. It is used with his permission. */
42 typedef int pthread_barrierattr_t;
43 typedef struct pthread_barrier {
44 pthread_mutex_t mutex;
50 static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
57 if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
60 if(pthread_cond_init(&barrier->cond, 0) < 0) {
61 pthread_mutex_destroy(&barrier->mutex);
64 barrier->trip_count = count;
70 static int pthread_barrier_destroy(pthread_barrier_t *barrier)
72 pthread_cond_destroy(&barrier->cond);
73 pthread_mutex_destroy(&barrier->mutex);
77 static int pthread_barrier_wait(pthread_barrier_t *barrier)
79 pthread_mutex_lock(&barrier->mutex);
81 if(barrier->count >= barrier->trip_count)
84 pthread_cond_broadcast(&barrier->cond);
85 pthread_mutex_unlock(&barrier->mutex);
90 pthread_cond_wait(&barrier->cond, &(barrier->mutex));
91 pthread_mutex_unlock(&barrier->mutex);
96 static int return_data(hid_device *dev, unsigned char *data, size_t length);
98 /* Linked List of input reports received from the device. */
102 struct input_report *next;
106 IOHIDDeviceRef device_handle;
108 int uses_numbered_reports;
110 CFStringRef run_loop_mode;
111 CFRunLoopRef run_loop;
112 CFRunLoopSourceRef source;
113 uint8_t *input_report_buf;
114 CFIndex max_input_report_len;
115 struct input_report *input_reports;
118 pthread_mutex_t mutex; /* Protects input_reports */
119 pthread_cond_t condition;
120 pthread_barrier_t barrier; /* Ensures correct startup sequence */
121 pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */
125 static hid_device *new_hid_device(void)
127 hid_device *dev = calloc(1, sizeof(hid_device));
128 dev->device_handle = NULL;
130 dev->uses_numbered_reports = 0;
131 dev->disconnected = 0;
132 dev->run_loop_mode = NULL;
133 dev->run_loop = NULL;
135 dev->input_report_buf = NULL;
136 dev->input_reports = NULL;
137 dev->shutdown_thread = 0;
140 pthread_mutex_init(&dev->mutex, NULL);
141 pthread_cond_init(&dev->condition, NULL);
142 pthread_barrier_init(&dev->barrier, NULL, 2);
143 pthread_barrier_init(&dev->shutdown_barrier, NULL, 2);
148 static void free_hid_device(hid_device *dev)
153 /* Delete any input reports still left over. */
154 struct input_report *rpt = dev->input_reports;
156 struct input_report *next = rpt->next;
162 /* Free the string and the report buffer. The check for NULL
163 is necessary here as CFRelease() doesn't handle NULL like
164 free() and others do. */
165 if (dev->run_loop_mode)
166 CFRelease(dev->run_loop_mode);
168 CFRelease(dev->source);
169 free(dev->input_report_buf);
171 /* Clean up the thread objects */
172 pthread_barrier_destroy(&dev->shutdown_barrier);
173 pthread_barrier_destroy(&dev->barrier);
174 pthread_cond_destroy(&dev->condition);
175 pthread_mutex_destroy(&dev->mutex);
177 /* Free the structure itself. */
181 static IOHIDManagerRef hid_mgr = 0x0;
185 static void register_error(hid_device *device, const char *op)
192 static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key)
197 ref = IOHIDDeviceGetProperty(device, key);
199 if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
200 CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value);
207 static unsigned short get_vendor_id(IOHIDDeviceRef device)
209 return get_int_property(device, CFSTR(kIOHIDVendorIDKey));
212 static unsigned short get_product_id(IOHIDDeviceRef device)
214 return get_int_property(device, CFSTR(kIOHIDProductIDKey));
217 static int32_t get_max_report_length(IOHIDDeviceRef device)
219 return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey));
222 static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len)
229 str = IOHIDDeviceGetProperty(device, prop);
234 CFIndex str_len = CFStringGetLength(str);
236 CFIndex used_buf_len;
237 CFIndex chars_copied;
242 range.length = ((size_t)str_len > len)? len: (size_t)str_len;
243 chars_copied = CFStringGetBytes(str,
245 kCFStringEncodingUTF32LE,
249 len * sizeof(wchar_t),
252 if (chars_copied == len)
253 buf[len] = 0; /* len is decremented above */
255 buf[chars_copied] = 0;
264 static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len)
266 return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len);
269 static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
271 return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len);
274 static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
276 return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len);
280 /* Implementation of wcsdup() for Mac. */
281 static wchar_t *dup_wcs(const wchar_t *s)
283 size_t len = wcslen(s);
284 wchar_t *ret = malloc((len+1)*sizeof(wchar_t));
290 /* hidapi_IOHIDDeviceGetService()
292 * Return the io_service_t corresponding to a given IOHIDDeviceRef, either by:
293 * - on OS X 10.6 and above, calling IOHIDDeviceGetService()
294 * - on OS X 10.5, extract it from the IOHIDDevice struct
296 static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device)
298 static void *iokit_framework = NULL;
299 static io_service_t (*dynamic_IOHIDDeviceGetService)(IOHIDDeviceRef device) = NULL;
301 /* Use dlopen()/dlsym() to get a pointer to IOHIDDeviceGetService() if it exists.
302 * If any of these steps fail, dynamic_IOHIDDeviceGetService will be left NULL
303 * and the fallback method will be used.
305 if (iokit_framework == NULL) {
306 iokit_framework = dlopen("/System/Library/IOKit.framework/IOKit", RTLD_LAZY);
308 if (iokit_framework != NULL)
309 dynamic_IOHIDDeviceGetService = dlsym(iokit_framework, "IOHIDDeviceGetService");
312 if (dynamic_IOHIDDeviceGetService != NULL) {
313 /* Running on OS X 10.6 and above: IOHIDDeviceGetService() exists */
314 return dynamic_IOHIDDeviceGetService(device);
318 /* Running on OS X 10.5: IOHIDDeviceGetService() doesn't exist.
320 * Be naughty and pull the service out of the IOHIDDevice.
321 * IOHIDDevice is an opaque struct not exposed to applications, but its
322 * layout is stable through all available versions of OS X.
323 * Tested and working on OS X 10.5.8 i386, x86_64, and ppc.
325 struct IOHIDDevice_internal {
326 /* The first field of the IOHIDDevice struct is a
327 * CFRuntimeBase (which is a private CF struct).
329 * a, b, and c are the 3 fields that make up a CFRuntimeBase.
330 * See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h
332 * The second field of the IOHIDDevice is the io_service_t we're looking for.
339 io_service_t service;
341 struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device;
347 /* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */
348 static int init_hid_manager(void)
350 /* Initialize all the HID Manager Objects */
351 hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
353 IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
354 IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
361 /* Initialize the IOHIDManager if necessary. This is the public function, and
362 it is safe to call this function repeatedly. Return 0 for success and -1
364 int HID_API_EXPORT hid_init(void)
367 return init_hid_manager();
370 /* Already initialized. */
374 int HID_API_EXPORT hid_exit(void)
377 /* Close the HID manager. */
378 IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone);
386 static void process_pending_events(void) {
389 res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE);
390 } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut);
393 struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
395 struct hid_device_info *root = NULL; /* return object */
396 struct hid_device_info *cur_dev = NULL;
400 /* Set up the HID Manager if it hasn't been done */
404 /* give the IOHIDManager a chance to update itself */
405 process_pending_events();
407 /* Get a list of the Devices */
408 IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
409 CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
411 /* Convert the list into a C array so we can iterate easily. */
412 num_devices = CFSetGetCount(device_set);
413 IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
414 CFSetGetValues(device_set, (const void **) device_array);
416 /* Iterate over each device, making an entry for it. */
417 for (i = 0; i < num_devices; i++) {
418 unsigned short dev_vid;
419 unsigned short dev_pid;
421 wchar_t buf[BUF_LEN];
423 IOHIDDeviceRef dev = device_array[i];
428 dev_vid = get_vendor_id(dev);
429 dev_pid = get_product_id(dev);
431 /* Check the VID/PID against the arguments */
432 if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
433 (product_id == 0x0 || product_id == dev_pid)) {
434 struct hid_device_info *tmp;
435 io_object_t iokit_dev;
439 /* VID/PID match. Create the record. */
440 tmp = malloc(sizeof(struct hid_device_info));
449 /* Get the Usage Page and Usage for this device. */
450 cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey));
451 cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey));
453 /* Fill out the record */
454 cur_dev->next = NULL;
456 /* Fill in the path (IOService plane) */
457 iokit_dev = hidapi_IOHIDDeviceGetService(dev);
458 res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path);
459 if (res == KERN_SUCCESS)
460 cur_dev->path = strdup(path);
462 cur_dev->path = strdup("");
465 get_serial_number(dev, buf, BUF_LEN);
466 cur_dev->serial_number = dup_wcs(buf);
468 /* Manufacturer and Product strings */
469 get_manufacturer_string(dev, buf, BUF_LEN);
470 cur_dev->manufacturer_string = dup_wcs(buf);
471 get_product_string(dev, buf, BUF_LEN);
472 cur_dev->product_string = dup_wcs(buf);
475 cur_dev->vendor_id = dev_vid;
476 cur_dev->product_id = dev_pid;
479 cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));
481 /* Interface Number (Unsupported on Mac)*/
482 cur_dev->interface_number = -1;
487 CFRelease(device_set);
492 void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
494 /* This function is identical to the Linux version. Platform independent. */
495 struct hid_device_info *d = devs;
497 struct hid_device_info *next = d->next;
499 free(d->serial_number);
500 free(d->manufacturer_string);
501 free(d->product_string);
507 hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
509 /* This function is identical to the Linux version. Platform independent. */
510 struct hid_device_info *devs, *cur_dev;
511 const char *path_to_open = NULL;
512 hid_device * handle = NULL;
514 devs = hid_enumerate(vendor_id, product_id);
517 if (cur_dev->vendor_id == vendor_id &&
518 cur_dev->product_id == product_id) {
520 if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
521 path_to_open = cur_dev->path;
526 path_to_open = cur_dev->path;
530 cur_dev = cur_dev->next;
534 /* Open the device */
535 handle = hid_open_path(path_to_open);
538 hid_free_enumeration(devs);
543 static void hid_device_removal_callback(void *context, IOReturn result,
546 /* Stop the Run Loop for this device. */
547 hid_device *d = context;
550 CFRunLoopStop(d->run_loop);
553 /* The Run Loop calls this function for each input report received.
554 This function puts the data into a linked list to be picked up by
556 static void hid_report_callback(void *context, IOReturn result, void *sender,
557 IOHIDReportType report_type, uint32_t report_id,
558 uint8_t *report, CFIndex report_length)
560 struct input_report *rpt;
561 hid_device *dev = context;
563 /* Make a new Input Report object */
564 rpt = calloc(1, sizeof(struct input_report));
565 rpt->data = calloc(1, report_length);
566 memcpy(rpt->data, report, report_length);
567 rpt->len = report_length;
570 /* Lock this section */
571 pthread_mutex_lock(&dev->mutex);
573 /* Attach the new report object to the end of the list. */
574 if (dev->input_reports == NULL) {
575 /* The list is empty. Put it at the root. */
576 dev->input_reports = rpt;
579 /* Find the end of the list and attach. */
580 struct input_report *cur = dev->input_reports;
582 while (cur->next != NULL) {
588 /* Pop one off if we've reached 30 in the queue. This
589 way we don't grow forever if the user never reads
590 anything from the device. */
591 if (num_queued > 30) {
592 return_data(dev, NULL, 0);
596 /* Signal a waiting thread that there is data. */
597 pthread_cond_signal(&dev->condition);
600 pthread_mutex_unlock(&dev->mutex);
604 /* This gets called when the read_thread's run loop gets signaled by
605 hid_close(), and serves to stop the read_thread's run loop. */
606 static void perform_signal_callback(void *context)
608 hid_device *dev = context;
609 CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/
612 static void *read_thread(void *param)
614 hid_device *dev = param;
617 /* Move the device's run loop to this thread. */
618 IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
620 /* Create the RunLoopSource which is used to signal the
621 event loop to stop when hid_close() is called. */
622 CFRunLoopSourceContext ctx;
623 memset(&ctx, 0, sizeof(ctx));
626 ctx.perform = &perform_signal_callback;
627 dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx);
628 CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode);
630 /* Store off the Run Loop so it can be stopped from hid_close()
631 and on device disconnection. */
632 dev->run_loop = CFRunLoopGetCurrent();
634 /* Notify the main thread that the read thread is up and running. */
635 pthread_barrier_wait(&dev->barrier);
637 /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
638 reports into the hid_report_callback(). */
639 while (!dev->shutdown_thread && !dev->disconnected) {
640 code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
641 /* Return if the device has been disconnected */
642 if (code == kCFRunLoopRunFinished) {
643 dev->disconnected = 1;
648 /* Break if The Run Loop returns Finished or Stopped. */
649 if (code != kCFRunLoopRunTimedOut &&
650 code != kCFRunLoopRunHandledSource) {
651 /* There was some kind of error. Setting
652 shutdown seems to make sense, but
653 there may be something else more appropriate */
654 dev->shutdown_thread = 1;
659 /* Now that the read thread is stopping, Wake any threads which are
660 waiting on data (in hid_read_timeout()). Do this under a mutex to
661 make sure that a thread which is about to go to sleep waiting on
662 the condition actually will go to sleep before the condition is
664 pthread_mutex_lock(&dev->mutex);
665 pthread_cond_broadcast(&dev->condition);
666 pthread_mutex_unlock(&dev->mutex);
668 /* Wait here until hid_close() is called and makes it past
669 the call to CFRunLoopWakeUp(). This thread still needs to
670 be valid when that function is called on the other thread. */
671 pthread_barrier_wait(&dev->shutdown_barrier);
678 * path must be a valid path to an IOHIDDevice in the IOService plane
679 * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver"
681 hid_device * HID_API_EXPORT hid_open_path(const char *path)
683 hid_device *dev = NULL;
684 io_registry_entry_t entry = MACH_PORT_NULL;
686 dev = new_hid_device();
688 /* Set up the HID Manager if it hasn't been done */
692 /* Get the IORegistry entry for the given path */
693 entry = IORegistryEntryFromPath(kIOMasterPortDefault, path);
694 if (entry == MACH_PORT_NULL) {
695 /* Path wasn't valid (maybe device was removed?) */
699 /* Create an IOHIDDevice for the entry */
700 dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry);
701 if (dev->device_handle == NULL) {
702 /* Error creating the HID device */
706 /* Open the IOHIDDevice */
707 IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
708 if (ret == kIOReturnSuccess) {
711 /* Create the buffers for receiving data */
712 dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle);
713 dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t));
715 /* Create the Run Loop Mode for this device.
716 printing the reference seems to work. */
717 sprintf(str, "HIDAPI_%p", dev->device_handle);
719 CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
721 /* Attach the device to a Run Loop */
722 IOHIDDeviceRegisterInputReportCallback(
723 dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
724 &hid_report_callback, dev);
725 IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);
727 /* Start the read thread */
728 pthread_create(&dev->thread, NULL, read_thread, dev);
730 /* Wait here for the read thread to be initialized. */
731 pthread_barrier_wait(&dev->barrier);
733 IOObjectRelease(entry);
741 if (dev->device_handle != NULL)
742 CFRelease(dev->device_handle);
744 if (entry != MACH_PORT_NULL)
745 IOObjectRelease(entry);
747 free_hid_device(dev);
751 static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length)
753 const unsigned char *data_to_send;
754 size_t length_to_send;
757 /* Return if the device has been disconnected. */
758 if (dev->disconnected)
761 if (data[0] == 0x0) {
762 /* Not using numbered Reports.
763 Don't send the report number. */
764 data_to_send = data+1;
765 length_to_send = length-1;
768 /* Using numbered Reports.
769 Send the Report Number */
771 length_to_send = length;
774 if (!dev->disconnected) {
775 res = IOHIDDeviceSetReport(dev->device_handle,
777 data[0], /* Report ID*/
778 data_to_send, length_to_send);
780 if (res == kIOReturnSuccess) {
790 int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
792 return set_report(dev, kIOHIDReportTypeOutput, data, length);
795 /* Helper function, so that this isn't duplicated in hid_read(). */
796 static int return_data(hid_device *dev, unsigned char *data, size_t length)
798 /* Copy the data out of the linked list item (rpt) into the
799 return buffer (data), and delete the liked list item. */
800 struct input_report *rpt = dev->input_reports;
801 size_t len = (length < rpt->len)? length: rpt->len;
802 memcpy(data, rpt->data, len);
803 dev->input_reports = rpt->next;
809 static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex)
811 while (!dev->input_reports) {
812 int res = pthread_cond_wait(cond, mutex);
816 /* A res of 0 means we may have been signaled or it may
817 be a spurious wakeup. Check to see that there's acutally
818 data in the queue before returning, and if not, go back
819 to sleep. See the pthread_cond_timedwait() man page for
822 if (dev->shutdown_thread || dev->disconnected)
829 static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
831 while (!dev->input_reports) {
832 int res = pthread_cond_timedwait(cond, mutex, abstime);
836 /* A res of 0 means we may have been signaled or it may
837 be a spurious wakeup. Check to see that there's acutally
838 data in the queue before returning, and if not, go back
839 to sleep. See the pthread_cond_timedwait() man page for
842 if (dev->shutdown_thread || dev->disconnected)
850 int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
854 /* Lock the access to the report list. */
855 pthread_mutex_lock(&dev->mutex);
857 /* There's an input report queued up. Return it. */
858 if (dev->input_reports) {
859 /* Return the first one */
860 bytes_read = return_data(dev, data, length);
864 /* Return if the device has been disconnected. */
865 if (dev->disconnected) {
870 if (dev->shutdown_thread) {
871 /* This means the device has been closed (or there
872 has been an error. An error code of -1 should
878 /* There is no data. Go to sleep and wait for data. */
880 if (milliseconds == -1) {
883 res = cond_wait(dev, &dev->condition, &dev->mutex);
885 bytes_read = return_data(dev, data, length);
887 /* There was an error, or a device disconnection. */
891 else if (milliseconds > 0) {
892 /* Non-blocking, but called with timeout. */
896 gettimeofday(&tv, NULL);
897 TIMEVAL_TO_TIMESPEC(&tv, &ts);
898 ts.tv_sec += milliseconds / 1000;
899 ts.tv_nsec += (milliseconds % 1000) * 1000000;
900 if (ts.tv_nsec >= 1000000000L) {
902 ts.tv_nsec -= 1000000000L;
905 res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts);
907 bytes_read = return_data(dev, data, length);
908 else if (res == ETIMEDOUT)
914 /* Purely non-blocking */
920 pthread_mutex_unlock(&dev->mutex);
924 int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
926 return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
929 int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
931 /* All Nonblocking operation is handled by the library. */
932 dev->blocking = !nonblock;
937 int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
939 return set_report(dev, kIOHIDReportTypeFeature, data, length);
942 int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
944 CFIndex len = length;
947 /* Return if the device has been unplugged. */
948 if (dev->disconnected)
951 res = IOHIDDeviceGetReport(dev->device_handle,
952 kIOHIDReportTypeFeature,
953 data[0], /* Report ID */
955 if (res == kIOReturnSuccess)
962 void HID_API_EXPORT hid_close(hid_device *dev)
967 /* Disconnect the report callback before close. */
968 if (!dev->disconnected) {
969 IOHIDDeviceRegisterInputReportCallback(
970 dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
972 IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev);
973 IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode);
974 IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
977 /* Cause read_thread() to stop. */
978 dev->shutdown_thread = 1;
980 /* Wake up the run thread's event loop so that the thread can exit. */
981 CFRunLoopSourceSignal(dev->source);
982 CFRunLoopWakeUp(dev->run_loop);
984 /* Notify the read thread that it can shut down now. */
985 pthread_barrier_wait(&dev->shutdown_barrier);
987 /* Wait for read_thread() to end. */
988 pthread_join(dev->thread, NULL);
990 /* Close the OS handle to the device, but only if it's not
991 been unplugged. If it's been unplugged, then calling
992 IOHIDDeviceClose() will crash. */
993 if (!dev->disconnected) {
994 IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
997 /* Clear out the queue of received reports. */
998 pthread_mutex_lock(&dev->mutex);
999 while (dev->input_reports) {
1000 return_data(dev, NULL, 0);
1002 pthread_mutex_unlock(&dev->mutex);
1003 CFRelease(dev->device_handle);
1005 free_hid_device(dev);
1008 int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
1010 return get_manufacturer_string(dev->device_handle, string, maxlen);
1013 int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
1015 return get_product_string(dev->device_handle, string, maxlen);
1018 int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
1020 return get_serial_number(dev->device_handle, string, maxlen);
1023 int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
1031 HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
1045 static int32_t get_location_id(IOHIDDeviceRef device)
1047 return get_int_property(device, CFSTR(kIOHIDLocationIDKey));
1050 static int32_t get_usage(IOHIDDeviceRef device)
1053 res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey));
1055 res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey));
1059 static int32_t get_usage_page(IOHIDDeviceRef device)
1062 res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey));
1064 res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey));
1068 static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len)
1070 return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len);
1076 IOHIDManagerRef mgr;
1079 mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
1080 IOHIDManagerSetDeviceMatching(mgr, NULL);
1081 IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone);
1083 CFSetRef device_set = IOHIDManagerCopyDevices(mgr);
1085 CFIndex num_devices = CFSetGetCount(device_set);
1086 IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
1087 CFSetGetValues(device_set, (const void **) device_array);
1089 for (i = 0; i < num_devices; i++) {
1090 IOHIDDeviceRef dev = device_array[i];
1091 printf("Device: %p\n", dev);
1092 printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev));
1094 wchar_t serial[256], buf[256];
1096 get_serial_number(dev, serial, 256);
1099 printf(" Serial: %ls\n", serial);
1100 printf(" Loc: %ld\n", get_location_id(dev));
1101 get_transport(dev, buf, 256);
1102 printf(" Trans: %ls\n", buf);
1103 make_path(dev, cbuf, 256);
1104 printf(" Path: %s\n", cbuf);