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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/device_monitor_mac.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/device_monitor_mac.mm
===================================================================
--- content/browser/device_monitor_mac.mm (revision 0)
+++ content/browser/device_monitor_mac.mm (revision 0)
@@ -0,0 +1,147 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/device_monitor_mac.h"
+
+#include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/usb/IOUSBLib.h>
+
+#include "base/logging.h"
+#include "base/system_monitor/system_monitor.h"
+
+namespace {
+
+struct {
+ base::SystemMonitor::DeviceType device_type;
+ SInt32 interface_class_code;
+ SInt32 interface_subclass_code;
+} kInterfaceTypeMap[] = {
+ // Add new types here if needed.
+ { base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE, kUSBAudioInterfaceClass,
+ kUSBAudioControlSubClass },
+ { base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE, kUSBVideoInterfaceClass,
+ kUSBVideoControlSubClass },
+};
+
+void AddValueToDictionary(CFMutableDictionaryRef dictionary,
+ SInt32 code,
+ const void *key) {
+ CFNumberRef number_ref = CFNumberCreate(kCFAllocatorDefault,
+ kCFNumberSInt32Type,
+ &code);
+ if (!number_ref) {
+ NOTREACHED() << "failed to create CFNumberRef for " << code;
+ return;
+ }
+
+ CFDictionaryAddValue(dictionary, key, number_ref);
+ CFRelease(number_ref);
+}
+
+CFMutableDictionaryRef CreateMatchingDictionary(
+ SInt32 interface_class_code,
+ SInt32 interface_subclass_code) {
+ CFMutableDictionaryRef matching_dictionary = IOServiceMatching(
+ kIOUSBInterfaceClassName);
+ AddValueToDictionary(matching_dictionary, interface_class_code,
+ CFSTR(kUSBInterfaceClass));
+ AddValueToDictionary(matching_dictionary, interface_subclass_code,
+ CFSTR(kUSBInterfaceSubClass));
+
+ return matching_dictionary;
+}
+
+void AddCallbackToIOService(IONotificationPortRef port,
+ const io_name_t type,
+ CFMutableDictionaryRef dictionary,
+ IOServiceMatchingCallback callback,
+ void* context) {
+ // Retain additional dictionary references because each call to
+ // IOServiceAddMatchingNotification consumes one reference.
+ dictionary = (CFMutableDictionaryRef)(CFRetain(dictionary));
+
+ io_iterator_t devices_iterator = 0;
+ kern_return_t err = IOServiceAddMatchingNotification(port,
+ type,
+ dictionary,
+ callback,
+ context,
+ &devices_iterator);
+ if (err) {
+ NOTREACHED() << "Failed to register the IO matched notification for type "
+ << type;
+ return;
+ }
+
+ // Iterate over set of matching devices to access already-present devices
+ // and to arm the notification.
+ io_object_t this_object;
+ while ((this_object = IOIteratorNext(devices_iterator)))
+ IOObjectRelease(this_object);
+}
+
+// For now, context is a cast of device_type. If |this| is needed,
+// DeviceMonitorMac can keep an list of objects of
+// struct Context {
+// base::SystemMonitor::DeviceType device_type;
+// DeviceMonitorMac* instance;
+// };
+void DevicesChangedCallback(void *context, io_iterator_t devices) {
+ io_object_t this_object;
+ while ((this_object = IOIteratorNext(devices))) {
+ if (context) {
+ base::SystemMonitor::DeviceType device_type =
+ *(static_cast<base::SystemMonitor::DeviceType*>(context));
+ base::SystemMonitor::Get()->ProcessDevicesChanged(device_type);
+ }
+ IOObjectRelease(this_object);
+ }
+}
+
+} // namespace
+
+namespace content {
+
+DeviceMonitorMac::DeviceMonitorMac() {
+ CFRunLoopRef runloop = CFRunLoopGetCurrent();
+ CFRetain(runloop);
+
+ // Add the notification port to the run loop.
+ IONotificationPortRef notification_port =
+ IONotificationPortCreate(kIOMasterPortDefault);
+ CFRunLoopSourceRef notification_cfsource =
+ IONotificationPortGetRunLoopSource(notification_port);
+
+ RegisterCallbacks(notification_port);
+ CFRunLoopAddSource(runloop, notification_cfsource, kCFRunLoopCommonModes);
+}
+
+DeviceMonitorMac::~DeviceMonitorMac() {}
+
+void DeviceMonitorMac::RegisterCallbacks(IONotificationPortRef port) {
+ for (size_t i = 0; i < arraysize(kInterfaceTypeMap); i++) {
+ CFMutableDictionaryRef matching_dictionary = CreateMatchingDictionary(
+ kInterfaceTypeMap[i].interface_class_code,
+ kInterfaceTypeMap[i].interface_subclass_code);
+
+ // Add a callback which will be called when a device is plugged in.
+ AddCallbackToIOService(
+ port,
+ kIOMatchedNotification,
+ matching_dictionary,
+ &DevicesChangedCallback,
+ static_cast<void*>(&kInterfaceTypeMap[i].device_type));
+
+ // Add a callback which will be called when a video device is terminated.
+ AddCallbackToIOService(
+ port,
+ kIOTerminatedNotification,
+ matching_dictionary,
+ &DevicesChangedCallback,
+ static_cast<void*>(&kInterfaceTypeMap[i].device_type));
+ }
+}
+
+} // namespace content
Property changes on: content/browser/device_monitor_mac.mm
___________________________________________________________________
Added: svn:eol-style
+ LF
« 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