Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: device/hid/hid_service_mac.cc

Issue 825523003: Convert HidDeviceInfo from a struct to a refcounted class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added TODO to remove friend class definitions. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « device/hid/hid_service_mac.h ('k') | device/hid/hid_service_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 if (collection_info.report_ids.size() > 0) { 120 if (collection_info.report_ids.size() > 0) {
121 *has_report_id = true; 121 *has_report_id = true;
122 } 122 }
123 top_level_collections->push_back(collection_info); 123 top_level_collections->push_back(collection_info);
124 } 124 }
125 } 125 }
126 126
127 return true; 127 return true;
128 } 128 }
129 129
130 bool PopulateDeviceInfo(io_service_t service, HidDeviceInfo* device_info) {
131 io_string_t service_path;
132 IOReturn result =
133 IORegistryEntryGetPath(service, kIOServicePlane, service_path);
134 if (result != kIOReturnSuccess) {
135 VLOG(1) << "Failed to get IOService path: "
136 << base::StringPrintf("0x%04x", result);
137 return false;
138 }
139
140 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device(
141 IOHIDDeviceCreate(kCFAllocatorDefault, service));
142 if (!hid_device) {
143 VLOG(1) << "Unable to create IOHIDDevice object for " << service_path
144 << ".";
145 return false;
146 }
147
148 device_info->device_id = service_path;
149 device_info->vendor_id =
150 GetHidIntProperty(hid_device, CFSTR(kIOHIDVendorIDKey));
151 device_info->product_id =
152 GetHidIntProperty(hid_device, CFSTR(kIOHIDProductIDKey));
153 device_info->product_name =
154 GetHidStringProperty(hid_device, CFSTR(kIOHIDProductKey));
155 device_info->serial_number =
156 GetHidStringProperty(hid_device, CFSTR(kIOHIDSerialNumberKey));
157 if (!GetCollectionInfos(hid_device, &device_info->has_report_id,
158 &device_info->collections)) {
159 VLOG(1) << "Unable to get collection info for " << service_path << ".";
160 return false;
161 }
162 device_info->max_input_report_size =
163 GetHidIntProperty(hid_device, CFSTR(kIOHIDMaxInputReportSizeKey));
164 if (device_info->has_report_id && device_info->max_input_report_size > 0) {
165 device_info->max_input_report_size--;
166 }
167 device_info->max_output_report_size =
168 GetHidIntProperty(hid_device, CFSTR(kIOHIDMaxOutputReportSizeKey));
169 if (device_info->has_report_id && device_info->max_output_report_size > 0) {
170 device_info->max_output_report_size--;
171 }
172 device_info->max_feature_report_size =
173 GetHidIntProperty(hid_device, CFSTR(kIOHIDMaxFeatureReportSizeKey));
174 if (device_info->has_report_id && device_info->max_feature_report_size > 0) {
175 device_info->max_feature_report_size--;
176 }
177
178 return true;
179 }
180
181 } // namespace 130 } // namespace
182 131
183 HidServiceMac::HidServiceMac( 132 HidServiceMac::HidServiceMac(
184 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) 133 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
185 : file_task_runner_(file_task_runner) { 134 : file_task_runner_(file_task_runner) {
186 task_runner_ = base::ThreadTaskRunnerHandle::Get(); 135 task_runner_ = base::ThreadTaskRunnerHandle::Get();
187 DCHECK(task_runner_.get()); 136 DCHECK(task_runner_.get());
188 137
189 notify_port_ = IONotificationPortCreate(kIOMasterPortDefault); 138 notify_port_ = IONotificationPortCreate(kIOMasterPortDefault);
190 CFRunLoopAddSource(CFRunLoopGetMain(), 139 CFRunLoopAddSource(CFRunLoopGetMain(),
(...skipping 30 matching lines...) Expand all
221 << base::StringPrintf("0x%04x", result); 170 << base::StringPrintf("0x%04x", result);
222 return; 171 return;
223 } 172 }
224 173
225 // Drain devices_added_iterator_ to arm the notification. 174 // Drain devices_added_iterator_ to arm the notification.
226 devices_removed_iterator_.reset(iterator); 175 devices_removed_iterator_.reset(iterator);
227 RemoveDevices(); 176 RemoveDevices();
228 FirstEnumerationComplete(); 177 FirstEnumerationComplete();
229 } 178 }
230 179
180 void HidServiceMac::Connect(const HidDeviceId& device_id,
181 const ConnectCallback& callback) {
182 DCHECK(thread_checker_.CalledOnValidThread());
183
184 const auto& map_entry = devices().find(device_id);
185 if (map_entry == devices().end()) {
186 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
187 return;
188 }
189 scoped_refptr<HidDeviceInfo> device_info = map_entry->second;
190
191 io_string_t service_path;
192 strncpy(service_path, device_id.c_str(), sizeof service_path);
193 base::mac::ScopedIOObject<io_service_t> service(
194 IORegistryEntryFromPath(kIOMasterPortDefault, service_path));
195 if (!service.get()) {
196 VLOG(1) << "IOService not found for path: " << device_id;
197 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
198 return;
199 }
200
201 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device(
202 IOHIDDeviceCreate(kCFAllocatorDefault, service));
203 if (!hid_device) {
204 VLOG(1) << "Unable to create IOHIDDevice object.";
205 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
206 return;
207 }
208
209 IOReturn result = IOHIDDeviceOpen(hid_device, kIOHIDOptionsTypeNone);
210 if (result != kIOReturnSuccess) {
211 VLOG(1) << "Failed to open device: " << base::StringPrintf("0x%04x",
212 result);
213 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
214 return;
215 }
216
217 task_runner_->PostTask(
218 FROM_HERE, base::Bind(callback, make_scoped_refptr(new HidConnectionMac(
219 hid_device.release(), device_info,
220 file_task_runner_))));
221 }
222
231 HidServiceMac::~HidServiceMac() { 223 HidServiceMac::~HidServiceMac() {
232 } 224 }
233 225
234 // static 226 // static
235 void HidServiceMac::FirstMatchCallback(void* context, io_iterator_t iterator) { 227 void HidServiceMac::FirstMatchCallback(void* context, io_iterator_t iterator) {
236 DCHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent()); 228 DCHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent());
237 HidServiceMac* service = static_cast<HidServiceMac*>(context); 229 HidServiceMac* service = static_cast<HidServiceMac*>(context);
238 DCHECK_EQ(service->devices_added_iterator_, iterator); 230 DCHECK_EQ(service->devices_added_iterator_, iterator);
239 service->AddDevices(); 231 service->AddDevices();
240 } 232 }
241 233
242 // static 234 // static
243 void HidServiceMac::TerminatedCallback(void* context, io_iterator_t iterator) { 235 void HidServiceMac::TerminatedCallback(void* context, io_iterator_t iterator) {
244 DCHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent()); 236 DCHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent());
245 HidServiceMac* service = static_cast<HidServiceMac*>(context); 237 HidServiceMac* service = static_cast<HidServiceMac*>(context);
246 DCHECK_EQ(service->devices_removed_iterator_, iterator); 238 DCHECK_EQ(service->devices_removed_iterator_, iterator);
247 service->RemoveDevices(); 239 service->RemoveDevices();
248 } 240 }
249 241
250 void HidServiceMac::AddDevices() { 242 void HidServiceMac::AddDevices() {
251 DCHECK(thread_checker_.CalledOnValidThread()); 243 DCHECK(thread_checker_.CalledOnValidThread());
252 244
253 io_service_t device; 245 io_service_t device;
254 while ((device = IOIteratorNext(devices_added_iterator_)) != IO_OBJECT_NULL) { 246 while ((device = IOIteratorNext(devices_added_iterator_)) != IO_OBJECT_NULL) {
255 HidDeviceInfo device_info; 247 scoped_refptr<HidDeviceInfo> device_info = CreateDeviceInfo(device);
256 if (PopulateDeviceInfo(device, &device_info)) { 248 if (device_info) {
257 AddDevice(device_info); 249 AddDevice(device_info);
250 // The reference retained by IOIteratorNext is released below in
251 // RemoveDevices when the device is removed.
252 } else {
253 IOObjectRelease(device);
258 } 254 }
259 // The reference retained by IOIteratorNext is released below in
260 // RemoveDevices when the device is removed.
261 } 255 }
262 } 256 }
263 257
264 void HidServiceMac::RemoveDevices() { 258 void HidServiceMac::RemoveDevices() {
265 DCHECK(thread_checker_.CalledOnValidThread()); 259 DCHECK(thread_checker_.CalledOnValidThread());
266 260
267 io_service_t device; 261 io_service_t device;
268 while ((device = IOIteratorNext(devices_removed_iterator_)) != 262 while ((device = IOIteratorNext(devices_removed_iterator_)) !=
269 IO_OBJECT_NULL) { 263 IO_OBJECT_NULL) {
270 io_string_t service_path; 264 io_string_t service_path;
271 IOReturn result = 265 IOReturn result =
272 IORegistryEntryGetPath(device, kIOServicePlane, service_path); 266 IORegistryEntryGetPath(device, kIOServicePlane, service_path);
273 if (result == kIOReturnSuccess) { 267 if (result == kIOReturnSuccess) {
274 RemoveDevice(service_path); 268 RemoveDevice(service_path);
275 } 269 }
276 270
277 // Release reference retained by AddDevices above. 271 // Release reference retained by AddDevices above.
278 IOObjectRelease(device); 272 IOObjectRelease(device);
279 // Release the reference retained by IOIteratorNext. 273 // Release the reference retained by IOIteratorNext.
280 IOObjectRelease(device); 274 IOObjectRelease(device);
281 } 275 }
282 } 276 }
283 277
284 void HidServiceMac::Connect(const HidDeviceId& device_id, 278 // static
285 const ConnectCallback& callback) { 279 scoped_refptr<HidDeviceInfo> HidServiceMac::CreateDeviceInfo(
286 DCHECK(thread_checker_.CalledOnValidThread()); 280 io_service_t service) {
287 281 scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfo());
288 const auto& map_entry = devices().find(device_id);
289 if (map_entry == devices().end()) {
290 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
291 return;
292 }
293 const HidDeviceInfo& device_info = map_entry->second;
294
295 io_string_t service_path; 282 io_string_t service_path;
296 strncpy(service_path, device_id.c_str(), sizeof service_path); 283 IOReturn result =
297 base::mac::ScopedIOObject<io_service_t> service( 284 IORegistryEntryGetPath(service, kIOServicePlane, service_path);
298 IORegistryEntryFromPath(kIOMasterPortDefault, service_path)); 285 if (result != kIOReturnSuccess) {
299 if (!service.get()) { 286 VLOG(1) << "Failed to get IOService path: " << base::StringPrintf("0x%04x",
300 VLOG(1) << "IOService not found for path: " << device_id; 287 result);
301 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); 288 return nullptr;
302 return;
303 } 289 }
304 290
305 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device( 291 base::ScopedCFTypeRef<IOHIDDeviceRef> hid_device(
306 IOHIDDeviceCreate(kCFAllocatorDefault, service)); 292 IOHIDDeviceCreate(kCFAllocatorDefault, service));
307 if (!hid_device) { 293 if (!hid_device) {
308 VLOG(1) << "Unable to create IOHIDDevice object."; 294 VLOG(1) << "Unable to create IOHIDDevice object for " << service_path
309 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); 295 << ".";
310 return; 296 return nullptr;
311 } 297 }
312 298
313 IOReturn result = IOHIDDeviceOpen(hid_device, kIOHIDOptionsTypeNone); 299 device_info->device_id_ = service_path;
314 if (result != kIOReturnSuccess) { 300 device_info->vendor_id_ =
315 VLOG(1) << "Failed to open device: " 301 GetHidIntProperty(hid_device, CFSTR(kIOHIDVendorIDKey));
316 << base::StringPrintf("0x%04x", result); 302 device_info->product_id_ =
317 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); 303 GetHidIntProperty(hid_device, CFSTR(kIOHIDProductIDKey));
318 return; 304 device_info->product_name_ =
305 GetHidStringProperty(hid_device, CFSTR(kIOHIDProductKey));
306 device_info->serial_number_ =
307 GetHidStringProperty(hid_device, CFSTR(kIOHIDSerialNumberKey));
308 if (!GetCollectionInfos(hid_device, &device_info->has_report_id_,
309 &device_info->collections_)) {
310 VLOG(1) << "Unable to get collection info for " << service_path << ".";
311 return nullptr;
312 }
313 device_info->max_input_report_size_ =
314 GetHidIntProperty(hid_device, CFSTR(kIOHIDMaxInputReportSizeKey));
315 if (device_info->has_report_id() &&
316 device_info->max_input_report_size() > 0) {
317 device_info->max_input_report_size_--;
318 }
319 device_info->max_output_report_size_ =
320 GetHidIntProperty(hid_device, CFSTR(kIOHIDMaxOutputReportSizeKey));
321 if (device_info->has_report_id() &&
322 device_info->max_output_report_size_ > 0) {
323 device_info->max_output_report_size_--;
324 }
325 device_info->max_feature_report_size_ =
326 GetHidIntProperty(hid_device, CFSTR(kIOHIDMaxFeatureReportSizeKey));
327 if (device_info->has_report_id() &&
328 device_info->max_feature_report_size_ > 0) {
329 device_info->max_feature_report_size_--;
319 } 330 }
320 331
321 task_runner_->PostTask( 332 return device_info;
322 FROM_HERE,
323 base::Bind(callback,
324 make_scoped_refptr(new HidConnectionMac(
325 hid_device.release(), device_info, file_task_runner_))));
326 } 333 }
327 334
328 } // namespace device 335 } // namespace device
OLDNEW
« no previous file with comments | « device/hid/hid_service_mac.h ('k') | device/hid/hid_service_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698