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 |