| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/hid/hid_service_mac.h" | 5 #include "device/hid/hid_service_mac.h" |
| 6 | 6 |
| 7 #include <CoreFoundation/CoreFoundation.h> | 7 #include <CoreFoundation/CoreFoundation.h> |
| 8 #include <IOKit/hid/IOHIDDevice.h> | 8 #include <IOKit/hid/IOHIDDevice.h> |
| 9 | 9 |
| 10 #include <set> | 10 #include <set> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/mac/foundation_util.h" | 17 #include "base/mac/foundation_util.h" |
| 18 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
| 19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
| 20 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
| 21 #include "base/strings/sys_string_conversions.h" | 21 #include "base/strings/sys_string_conversions.h" |
| 22 #include "base/thread_task_runner_handle.h" | 22 #include "base/thread_task_runner_handle.h" |
| 23 #include "base/threading/thread_restrictions.h" | 23 #include "base/threading/thread_restrictions.h" |
| 24 #include "components/device_event_log/device_event_log.h" |
| 24 #include "device/hid/hid_connection_mac.h" | 25 #include "device/hid/hid_connection_mac.h" |
| 25 | 26 |
| 26 namespace device { | 27 namespace device { |
| 27 | 28 |
| 28 namespace { | 29 namespace { |
| 29 | 30 |
| 30 bool TryGetHidIntProperty(IOHIDDeviceRef device, | 31 bool TryGetHidIntProperty(IOHIDDeviceRef device, |
| 31 CFStringRef key, | 32 CFStringRef key, |
| 32 int32_t* result) { | 33 int32_t* result) { |
| 33 CFNumberRef ref = | 34 CFNumberRef ref = |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 | 90 |
| 90 io_iterator_t iterator; | 91 io_iterator_t iterator; |
| 91 IOReturn result = | 92 IOReturn result = |
| 92 IOServiceAddMatchingNotification(notify_port_, | 93 IOServiceAddMatchingNotification(notify_port_, |
| 93 kIOFirstMatchNotification, | 94 kIOFirstMatchNotification, |
| 94 IOServiceMatching(kIOHIDDeviceKey), | 95 IOServiceMatching(kIOHIDDeviceKey), |
| 95 FirstMatchCallback, | 96 FirstMatchCallback, |
| 96 this, | 97 this, |
| 97 &iterator); | 98 &iterator); |
| 98 if (result != kIOReturnSuccess) { | 99 if (result != kIOReturnSuccess) { |
| 99 LOG(ERROR) << "Failed to listen for device arrival: " | 100 HID_LOG(ERROR) << "Failed to listen for device arrival: " |
| 100 << base::StringPrintf("0x%04x", result); | 101 << base::StringPrintf("0x%04x", result); |
| 101 return; | 102 return; |
| 102 } | 103 } |
| 103 | 104 |
| 104 // Drain the iterator to arm the notification. | 105 // Drain the iterator to arm the notification. |
| 105 devices_added_iterator_.reset(iterator); | 106 devices_added_iterator_.reset(iterator); |
| 106 AddDevices(); | 107 AddDevices(); |
| 107 iterator = IO_OBJECT_NULL; | 108 iterator = IO_OBJECT_NULL; |
| 108 | 109 |
| 109 result = IOServiceAddMatchingNotification(notify_port_, | 110 result = IOServiceAddMatchingNotification(notify_port_, |
| 110 kIOTerminatedNotification, | 111 kIOTerminatedNotification, |
| 111 IOServiceMatching(kIOHIDDeviceKey), | 112 IOServiceMatching(kIOHIDDeviceKey), |
| 112 TerminatedCallback, | 113 TerminatedCallback, |
| 113 this, | 114 this, |
| 114 &iterator); | 115 &iterator); |
| 115 if (result != kIOReturnSuccess) { | 116 if (result != kIOReturnSuccess) { |
| 116 LOG(ERROR) << "Failed to listen for device removal: " | 117 HID_LOG(ERROR) << "Failed to listen for device removal: " |
| 117 << base::StringPrintf("0x%04x", result); | 118 << base::StringPrintf("0x%04x", result); |
| 118 return; | 119 return; |
| 119 } | 120 } |
| 120 | 121 |
| 121 // Drain devices_added_iterator_ to arm the notification. | 122 // Drain devices_added_iterator_ to arm the notification. |
| 122 devices_removed_iterator_.reset(iterator); | 123 devices_removed_iterator_.reset(iterator); |
| 123 RemoveDevices(); | 124 RemoveDevices(); |
| 124 FirstEnumerationComplete(); | 125 FirstEnumerationComplete(); |
| 125 } | 126 } |
| 126 | 127 |
| 127 void HidServiceMac::Connect(const HidDeviceId& device_id, | 128 void HidServiceMac::Connect(const HidDeviceId& device_id, |
| 128 const ConnectCallback& callback) { | 129 const ConnectCallback& callback) { |
| 129 DCHECK(thread_checker_.CalledOnValidThread()); | 130 DCHECK(thread_checker_.CalledOnValidThread()); |
| 130 | 131 |
| 131 const auto& map_entry = devices().find(device_id); | 132 const auto& map_entry = devices().find(device_id); |
| 132 if (map_entry == devices().end()) { | 133 if (map_entry == devices().end()) { |
| 133 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 134 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 134 return; | 135 return; |
| 135 } | 136 } |
| 136 scoped_refptr<HidDeviceInfo> device_info = map_entry->second; | 137 scoped_refptr<HidDeviceInfo> device_info = map_entry->second; |
| 137 | 138 |
| 138 io_string_t service_path; | 139 io_string_t service_path; |
| 139 strncpy(service_path, device_id.c_str(), sizeof service_path); | 140 strncpy(service_path, device_id.c_str(), sizeof service_path); |
| 140 base::mac::ScopedIOObject<io_service_t> service( | 141 base::mac::ScopedIOObject<io_service_t> service( |
| 141 IORegistryEntryFromPath(kIOMasterPortDefault, service_path)); | 142 IORegistryEntryFromPath(kIOMasterPortDefault, service_path)); |
| 142 if (!service.get()) { | 143 if (!service.get()) { |
| 143 VLOG(1) << "IOService not found for path: " << device_id; | 144 HID_LOG(EVENT) << "IOService not found for path: " << device_id; |
| 144 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 145 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 145 return; | 146 return; |
| 146 } | 147 } |
| 147 | 148 |
| 148 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( | 149 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( |
| 149 IOHIDDeviceCreate(kCFAllocatorDefault, service)); | 150 IOHIDDeviceCreate(kCFAllocatorDefault, service)); |
| 150 if (!hid_device) { | 151 if (!hid_device) { |
| 151 VLOG(1) << "Unable to create IOHIDDevice object."; | 152 HID_LOG(EVENT) << "Unable to create IOHIDDevice object."; |
| 152 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 153 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 153 return; | 154 return; |
| 154 } | 155 } |
| 155 | 156 |
| 156 IOReturn result = IOHIDDeviceOpen(hid_device, kIOHIDOptionsTypeNone); | 157 IOReturn result = IOHIDDeviceOpen(hid_device, kIOHIDOptionsTypeNone); |
| 157 if (result != kIOReturnSuccess) { | 158 if (result != kIOReturnSuccess) { |
| 158 VLOG(1) << "Failed to open device: " << base::StringPrintf("0x%04x", | 159 HID_LOG(EVENT) << "Failed to open device: " << base::StringPrintf("0x%04x", |
| 159 result); | 160 result); |
| 160 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 161 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 161 return; | 162 return; |
| 162 } | 163 } |
| 163 | 164 |
| 164 task_runner_->PostTask( | 165 task_runner_->PostTask( |
| 165 FROM_HERE, base::Bind(callback, make_scoped_refptr(new HidConnectionMac( | 166 FROM_HERE, base::Bind(callback, make_scoped_refptr(new HidConnectionMac( |
| 166 hid_device.release(), device_info, | 167 hid_device.release(), device_info, |
| 167 file_task_runner_)))); | 168 file_task_runner_)))); |
| 168 } | 169 } |
| 169 | 170 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 } | 223 } |
| 223 } | 224 } |
| 224 | 225 |
| 225 // static | 226 // static |
| 226 scoped_refptr<HidDeviceInfo> HidServiceMac::CreateDeviceInfo( | 227 scoped_refptr<HidDeviceInfo> HidServiceMac::CreateDeviceInfo( |
| 227 io_service_t service) { | 228 io_service_t service) { |
| 228 io_string_t service_path; | 229 io_string_t service_path; |
| 229 IOReturn result = | 230 IOReturn result = |
| 230 IORegistryEntryGetPath(service, kIOServicePlane, service_path); | 231 IORegistryEntryGetPath(service, kIOServicePlane, service_path); |
| 231 if (result != kIOReturnSuccess) { | 232 if (result != kIOReturnSuccess) { |
| 232 VLOG(1) << "Failed to get IOService path: " << base::StringPrintf("0x%04x", | 233 HID_LOG(EVENT) << "Failed to get IOService path: " << base::StringPrintf( |
| 233 result); | 234 "0x%04x", result); |
| 234 return nullptr; | 235 return nullptr; |
| 235 } | 236 } |
| 236 | 237 |
| 237 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( | 238 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( |
| 238 IOHIDDeviceCreate(kCFAllocatorDefault, service)); | 239 IOHIDDeviceCreate(kCFAllocatorDefault, service)); |
| 239 if (!hid_device) { | 240 if (!hid_device) { |
| 240 VLOG(1) << "Unable to create IOHIDDevice object for " << service_path | 241 HID_LOG(EVENT) << "Unable to create IOHIDDevice object for " << service_path |
| 241 << "."; | 242 << "."; |
| 242 return nullptr; | 243 return nullptr; |
| 243 } | 244 } |
| 244 | 245 |
| 245 std::vector<uint8> report_descriptor; | 246 std::vector<uint8> report_descriptor; |
| 246 if (!TryGetHidDataProperty(hid_device, CFSTR(kIOHIDReportDescriptorKey), | 247 if (!TryGetHidDataProperty(hid_device, CFSTR(kIOHIDReportDescriptorKey), |
| 247 &report_descriptor)) { | 248 &report_descriptor)) { |
| 248 VLOG(1) << "Unable to get report descriptor for " << service_path << "."; | 249 HID_LOG(EVENT) << "Unable to get report descriptor for " << service_path |
| 250 << "."; |
| 249 return nullptr; | 251 return nullptr; |
| 250 } | 252 } |
| 251 | 253 |
| 252 return new HidDeviceInfo( | 254 return new HidDeviceInfo( |
| 253 service_path, GetHidIntProperty(hid_device, CFSTR(kIOHIDVendorIDKey)), | 255 service_path, GetHidIntProperty(hid_device, CFSTR(kIOHIDVendorIDKey)), |
| 254 GetHidIntProperty(hid_device, CFSTR(kIOHIDProductIDKey)), | 256 GetHidIntProperty(hid_device, CFSTR(kIOHIDProductIDKey)), |
| 255 GetHidStringProperty(hid_device, CFSTR(kIOHIDProductKey)), | 257 GetHidStringProperty(hid_device, CFSTR(kIOHIDProductKey)), |
| 256 GetHidStringProperty(hid_device, CFSTR(kIOHIDSerialNumberKey)), | 258 GetHidStringProperty(hid_device, CFSTR(kIOHIDSerialNumberKey)), |
| 257 kHIDBusTypeUSB, // TODO(reillyg): Detect Bluetooth. crbug.com/443335 | 259 kHIDBusTypeUSB, // TODO(reillyg): Detect Bluetooth. crbug.com/443335 |
| 258 report_descriptor); | 260 report_descriptor); |
| 259 } | 261 } |
| 260 | 262 |
| 261 } // namespace device | 263 } // namespace device |
| OLD | NEW |