| 1346 | } |
| 1347 | |
| 1348 | void HID_API_EXPORT hid_close(hid_device *dev) |
| 1349 | { |
| 1350 | if (!dev) |
| 1351 | return; |
| 1352 | |
| 1353 | /* Disconnect the report callback before close. |
| 1354 | See comment below. |
| 1355 | */ |
| 1356 | if (is_macos_10_10_or_greater || !dev->disconnected) { |
| 1357 | IOHIDDeviceRegisterInputReportCallback( |
| 1358 | dev->device_handle, dev->input_report_buf, dev->max_input_report_len, |
| 1359 | NULL, dev); |
| 1360 | IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev); |
| 1361 | IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode); |
| 1362 | IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode); |
| 1363 | } |
| 1364 | |
| 1365 | /* Cause read_thread() to stop. */ |
| 1366 | dev->shutdown_thread = 1; |
| 1367 | |
| 1368 | /* Wake up the run thread's event loop so that the thread can exit. */ |
| 1369 | CFRunLoopSourceSignal(dev->source); |
| 1370 | CFRunLoopWakeUp(dev->run_loop); |
| 1371 | |
| 1372 | /* Notify the read thread that it can shut down now. */ |
| 1373 | pthread_barrier_wait(&dev->shutdown_barrier); |
| 1374 | |
| 1375 | /* Wait for read_thread() to end. */ |
| 1376 | pthread_join(dev->thread, NULL); |
| 1377 | |
| 1378 | /* Close the OS handle to the device, but only if it's not |
| 1379 | been unplugged. If it's been unplugged, then calling |
| 1380 | IOHIDDeviceClose() will crash. |
| 1381 | |
| 1382 | UPD: The crash part was true in/until some version of macOS. |
| 1383 | Starting with macOS 10.15, there is an opposite effect in some environments: |
| 1384 | crash happenes if IOHIDDeviceClose() is not called. |
| 1385 | Not leaking a resource in all tested environments. |
| 1386 | */ |
| 1387 | if (is_macos_10_10_or_greater || !dev->disconnected) { |
| 1388 | IOHIDDeviceClose(dev->device_handle, dev->open_options); |
| 1389 | } |
| 1390 | |
| 1391 | /* Clear out the queue of received reports. */ |
| 1392 | pthread_mutex_lock(&dev->mutex); |
| 1393 | while (dev->input_reports) { |
| 1394 | return_data(dev, NULL, 0); |
| 1395 | } |
| 1396 | pthread_mutex_unlock(&dev->mutex); |
| 1397 | CFRelease(dev->device_handle); |
| 1398 | |
| 1399 | free_hid_device(dev); |
| 1400 | } |
| 1401 | |
| 1402 | int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) |
| 1403 | { |