| 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> | |
| 9 #include <stdint.h> | 8 #include <stdint.h> |
| 10 | 9 |
| 11 #include <set> | 10 #include <set> |
| 12 #include <string> | 11 #include <string> |
| 13 #include <vector> | 12 #include <vector> |
| 14 | 13 |
| 15 #include "base/bind.h" | 14 #include "base/bind.h" |
| 16 #include "base/location.h" | 15 #include "base/location.h" |
| 17 #include "base/logging.h" | 16 #include "base/logging.h" |
| 18 #include "base/mac/foundation_util.h" | 17 #include "base/mac/foundation_util.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 base::STLClearObject(result); | 76 base::STLClearObject(result); |
| 78 const uint8_t* bytes = CFDataGetBytePtr(ref); | 77 const uint8_t* bytes = CFDataGetBytePtr(ref); |
| 79 result->insert(result->begin(), bytes, bytes + CFDataGetLength(ref)); | 78 result->insert(result->begin(), bytes, bytes + CFDataGetLength(ref)); |
| 80 return true; | 79 return true; |
| 81 } | 80 } |
| 82 | 81 |
| 83 } // namespace | 82 } // namespace |
| 84 | 83 |
| 85 HidServiceMac::HidServiceMac( | 84 HidServiceMac::HidServiceMac( |
| 86 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) | 85 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) |
| 87 : file_task_runner_(file_task_runner) { | 86 : file_task_runner_(file_task_runner), weak_factory_(this) { |
| 88 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 87 task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 89 DCHECK(task_runner_.get()); | 88 DCHECK(task_runner_.get()); |
| 90 | 89 |
| 91 notify_port_.reset(IONotificationPortCreate(kIOMasterPortDefault)); | 90 notify_port_.reset(IONotificationPortCreate(kIOMasterPortDefault)); |
| 92 CFRunLoopAddSource(CFRunLoopGetMain(), | 91 CFRunLoopAddSource(CFRunLoopGetMain(), |
| 93 IONotificationPortGetRunLoopSource(notify_port_.get()), | 92 IONotificationPortGetRunLoopSource(notify_port_.get()), |
| 94 kCFRunLoopDefaultMode); | 93 kCFRunLoopDefaultMode); |
| 95 | 94 |
| 96 IOReturn result = IOServiceAddMatchingNotification( | 95 IOReturn result = IOServiceAddMatchingNotification( |
| 97 notify_port_.get(), kIOFirstMatchNotification, | 96 notify_port_.get(), kIOFirstMatchNotification, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 125 | 124 |
| 126 void HidServiceMac::Connect(const HidDeviceId& device_id, | 125 void HidServiceMac::Connect(const HidDeviceId& device_id, |
| 127 const ConnectCallback& callback) { | 126 const ConnectCallback& callback) { |
| 128 DCHECK(thread_checker_.CalledOnValidThread()); | 127 DCHECK(thread_checker_.CalledOnValidThread()); |
| 129 | 128 |
| 130 const auto& map_entry = devices().find(device_id); | 129 const auto& map_entry = devices().find(device_id); |
| 131 if (map_entry == devices().end()) { | 130 if (map_entry == devices().end()) { |
| 132 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 131 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 133 return; | 132 return; |
| 134 } | 133 } |
| 135 scoped_refptr<HidDeviceInfo> device_info = map_entry->second; | |
| 136 | |
| 137 base::ScopedCFTypeRef<CFDictionaryRef> matching_dict( | |
| 138 IORegistryEntryIDMatching(device_id)); | |
| 139 if (!matching_dict.get()) { | |
| 140 HID_LOG(EVENT) << "Failed to create matching dictionary for ID: " | |
| 141 << device_id; | |
| 142 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | |
| 143 return; | |
| 144 } | |
| 145 | 134 |
| 135 file_task_runner_->PostTask( |
| 136 FROM_HERE, |
| 137 base::Bind(&HidServiceMac::OpenOnBlockingThread, map_entry->second, |
| 138 task_runner_, weak_factory_.GetWeakPtr(), callback)); |
| 139 } |
| 140 |
| 141 // static |
| 142 void HidServiceMac::OpenOnBlockingThread( |
| 143 scoped_refptr<HidDeviceInfo> device_info, |
| 144 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 145 base::WeakPtr<HidServiceMac> hid_service, |
| 146 const ConnectCallback& callback) { |
| 147 base::ScopedCFTypeRef<CFDictionaryRef> matching_dict( |
| 148 IORegistryEntryIDMatching(device_info->device_id())); |
| 149 if (!matching_dict.get()) { |
| 150 HID_LOG(EVENT) << "Failed to create matching dictionary for ID: " |
| 151 << device_info->device_id(); |
| 152 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 153 return; |
| 154 } |
| 155 |
| 146 // IOServiceGetMatchingService consumes a reference to the matching dictionary | 156 // IOServiceGetMatchingService consumes a reference to the matching dictionary |
| 147 // passed to it. | 157 // passed to it. |
| 148 base::mac::ScopedIOObject<io_service_t> service(IOServiceGetMatchingService( | 158 base::mac::ScopedIOObject<io_service_t> service(IOServiceGetMatchingService( |
| 149 kIOMasterPortDefault, matching_dict.release())); | 159 kIOMasterPortDefault, matching_dict.release())); |
| 150 if (!service.get()) { | 160 if (!service.get()) { |
| 151 HID_LOG(EVENT) << "IOService not found for ID: " << device_id; | 161 HID_LOG(EVENT) << "IOService not found for ID: " |
| 152 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 162 << device_info->device_id(); |
| 163 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 153 return; | 164 return; |
| 154 } | 165 } |
| 155 | 166 |
| 156 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( | 167 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( |
| 157 IOHIDDeviceCreate(kCFAllocatorDefault, service)); | 168 IOHIDDeviceCreate(kCFAllocatorDefault, service)); |
| 158 if (!hid_device) { | 169 if (!hid_device) { |
| 159 HID_LOG(EVENT) << "Unable to create IOHIDDevice object."; | 170 HID_LOG(EVENT) << "Unable to create IOHIDDevice object."; |
| 160 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 171 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 161 return; | 172 return; |
| 162 } | 173 } |
| 163 | 174 |
| 164 IOReturn result = IOHIDDeviceOpen(hid_device, kIOHIDOptionsTypeNone); | 175 IOReturn result = IOHIDDeviceOpen(hid_device, kIOHIDOptionsTypeNone); |
| 165 if (result != kIOReturnSuccess) { | 176 if (result != kIOReturnSuccess) { |
| 166 HID_LOG(EVENT) << "Failed to open device: " << HexErrorCode(result); | 177 HID_LOG(EVENT) << "Failed to open device: " << HexErrorCode(result); |
| 167 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 178 task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
| 168 return; | 179 return; |
| 169 } | 180 } |
| 170 | 181 |
| 171 task_runner_->PostTask( | 182 task_runner->PostTask( |
| 172 FROM_HERE, base::Bind(callback, make_scoped_refptr(new HidConnectionMac( | 183 FROM_HERE, base::Bind(&HidServiceMac::DeviceOpened, hid_service, |
| 173 hid_device.release(), device_info, | 184 device_info, base::Passed(&hid_device), callback)); |
| 174 file_task_runner_)))); | 185 } |
| 186 |
| 187 void HidServiceMac::DeviceOpened( |
| 188 scoped_refptr<HidDeviceInfo> device_info, |
| 189 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device, |
| 190 const ConnectCallback& callback) { |
| 191 callback.Run(make_scoped_refptr(new HidConnectionMac( |
| 192 std::move(hid_device), std::move(device_info), file_task_runner_))); |
| 175 } | 193 } |
| 176 | 194 |
| 177 // static | 195 // static |
| 178 void HidServiceMac::FirstMatchCallback(void* context, io_iterator_t iterator) { | 196 void HidServiceMac::FirstMatchCallback(void* context, io_iterator_t iterator) { |
| 179 DCHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent()); | 197 DCHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent()); |
| 180 HidServiceMac* service = static_cast<HidServiceMac*>(context); | 198 HidServiceMac* service = static_cast<HidServiceMac*>(context); |
| 181 DCHECK_EQ(service->devices_added_iterator_, iterator); | 199 DCHECK_EQ(service->devices_added_iterator_, iterator); |
| 182 service->AddDevices(); | 200 service->AddDevices(); |
| 183 } | 201 } |
| 184 | 202 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 return new HidDeviceInfo( | 270 return new HidDeviceInfo( |
| 253 entry_id, GetHidIntProperty(hid_device, CFSTR(kIOHIDVendorIDKey)), | 271 entry_id, GetHidIntProperty(hid_device, CFSTR(kIOHIDVendorIDKey)), |
| 254 GetHidIntProperty(hid_device, CFSTR(kIOHIDProductIDKey)), | 272 GetHidIntProperty(hid_device, CFSTR(kIOHIDProductIDKey)), |
| 255 GetHidStringProperty(hid_device, CFSTR(kIOHIDProductKey)), | 273 GetHidStringProperty(hid_device, CFSTR(kIOHIDProductKey)), |
| 256 GetHidStringProperty(hid_device, CFSTR(kIOHIDSerialNumberKey)), | 274 GetHidStringProperty(hid_device, CFSTR(kIOHIDSerialNumberKey)), |
| 257 kHIDBusTypeUSB, // TODO(reillyg): Detect Bluetooth. crbug.com/443335 | 275 kHIDBusTypeUSB, // TODO(reillyg): Detect Bluetooth. crbug.com/443335 |
| 258 report_descriptor); | 276 report_descriptor); |
| 259 } | 277 } |
| 260 | 278 |
| 261 } // namespace device | 279 } // namespace device |
| OLD | NEW |