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

Side by Side Diff: content/browser/device_monitor_mac.mm

Issue 10827163: add device monitoring on Mac. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « content/browser/device_monitor_mac.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/device_monitor_mac.h"
6
7 #include <CoreFoundation/CFNumber.h>
8 #include <CoreFoundation/CoreFoundation.h>
9 #include <IOKit/usb/IOUSBLib.h>
10
11 #include "base/logging.h"
12 #include "base/system_monitor/system_monitor.h"
13
14 namespace {
15
16 struct {
17 base::SystemMonitor::DeviceType device_type;
18 SInt32 interface_class_code;
19 SInt32 interface_subclass_code;
20 } kInterfaceTypeMap[] = {
21 // Add new types here if needed.
22 { base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE, kUSBAudioInterfaceClass,
23 kUSBAudioControlSubClass },
24 { base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE, kUSBVideoInterfaceClass,
25 kUSBVideoControlSubClass },
26 };
27
28 void AddValueToDictionary(CFMutableDictionaryRef dictionary,
29 SInt32 code,
30 const void *key) {
31 CFNumberRef number_ref = CFNumberCreate(kCFAllocatorDefault,
32 kCFNumberSInt32Type,
33 &code);
34 if (!number_ref) {
35 NOTREACHED() << "failed to create CFNumberRef for " << code;
36 return;
37 }
38
39 CFDictionaryAddValue(dictionary, key, number_ref);
40 CFRelease(number_ref);
41 }
42
43 CFMutableDictionaryRef CreateMatchingDictionary(
44 SInt32 interface_class_code,
45 SInt32 interface_subclass_code) {
46 CFMutableDictionaryRef matching_dictionary = IOServiceMatching(
47 kIOUSBInterfaceClassName);
48 AddValueToDictionary(matching_dictionary, interface_class_code,
49 CFSTR(kUSBInterfaceClass));
50 AddValueToDictionary(matching_dictionary, interface_subclass_code,
51 CFSTR(kUSBInterfaceSubClass));
52
53 return matching_dictionary;
54 }
55
56 void AddCallbackToIOService(IONotificationPortRef port,
57 const io_name_t type,
58 CFMutableDictionaryRef dictionary,
59 IOServiceMatchingCallback callback,
60 void* context) {
61 // Retain additional dictionary references because each call to
62 // IOServiceAddMatchingNotification consumes one reference.
63 dictionary = (CFMutableDictionaryRef)(CFRetain(dictionary));
64
65 io_iterator_t devices_iterator = 0;
66 kern_return_t err = IOServiceAddMatchingNotification(port,
67 type,
68 dictionary,
69 callback,
70 context,
71 &devices_iterator);
72 if (err) {
73 NOTREACHED() << "Failed to register the IO matched notification for type "
74 << type;
75 return;
76 }
77
78 // Iterate over set of matching devices to access already-present devices
79 // and to arm the notification.
80 io_object_t this_object;
81 while ((this_object = IOIteratorNext(devices_iterator)))
82 IOObjectRelease(this_object);
83 }
84
85 // For now, context is a cast of device_type. If |this| is needed,
86 // DeviceMonitorMac can keep an list of objects of
87 // struct Context {
88 // base::SystemMonitor::DeviceType device_type;
89 // DeviceMonitorMac* instance;
90 // };
91 void DevicesChangedCallback(void *context, io_iterator_t devices) {
92 io_object_t this_object;
93 while ((this_object = IOIteratorNext(devices))) {
94 if (context) {
95 base::SystemMonitor::DeviceType device_type =
96 *(static_cast<base::SystemMonitor::DeviceType*>(context));
97 base::SystemMonitor::Get()->ProcessDevicesChanged(device_type);
98 }
99 IOObjectRelease(this_object);
100 }
101 }
102
103 } // namespace
104
105 namespace content {
106
107 DeviceMonitorMac::DeviceMonitorMac() {
108 CFRunLoopRef runloop = CFRunLoopGetCurrent();
109 CFRetain(runloop);
110
111 // Add the notification port to the run loop.
112 IONotificationPortRef notification_port =
113 IONotificationPortCreate(kIOMasterPortDefault);
114 CFRunLoopSourceRef notification_cfsource =
115 IONotificationPortGetRunLoopSource(notification_port);
116
117 RegisterCallbacks(notification_port);
118 CFRunLoopAddSource(runloop, notification_cfsource, kCFRunLoopCommonModes);
119 }
120
121 DeviceMonitorMac::~DeviceMonitorMac() {}
122
123 void DeviceMonitorMac::RegisterCallbacks(IONotificationPortRef port) {
124 for (size_t i = 0; i < arraysize(kInterfaceTypeMap); i++) {
125 CFMutableDictionaryRef matching_dictionary = CreateMatchingDictionary(
126 kInterfaceTypeMap[i].interface_class_code,
127 kInterfaceTypeMap[i].interface_subclass_code);
128
129 // Add a callback which will be called when a device is plugged in.
130 AddCallbackToIOService(
131 port,
132 kIOMatchedNotification,
133 matching_dictionary,
134 &DevicesChangedCallback,
135 static_cast<void*>(&kInterfaceTypeMap[i].device_type));
136
137 // Add a callback which will be called when a video device is terminated.
138 AddCallbackToIOService(
139 port,
140 kIOTerminatedNotification,
141 matching_dictionary,
142 &DevicesChangedCallback,
143 static_cast<void*>(&kInterfaceTypeMap[i].device_type));
144 }
145 }
146
147 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/device_monitor_mac.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698