1/*
2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24//
25// xiodevices - additional code for finding and tracking devices via IOKit
26// >>> move this iodevices.cpp when final
27//
28#include "xiodevices.h"
29#include <security_utilities/cfutilities.h>
30#include <security_utilities/mach++.h>
31#include <IOKit/IOMessage.h>
32#include <IOKit/usb/IOUSBLib.h>
33
34using namespace MachPlusPlus;
35
36namespace Security {
37namespace IOKit {
38
39void XNotificationPort::add(DeviceMatch match, XReceiver &receiver, const char *type)
40{
41	// The kIOProviderClassKey key is required in a matching dictionary. We extract it
42	// here only for debugging purposes
43
44	CFTypeRef valueRef = NULL;
45	const char *pclass = "";
46	CFRef<CFMutableDictionaryRef> theDict = match.dict();
47	if (theDict && CFDictionaryGetValueIfPresent(theDict, CFSTR(kIOProviderClassKey), &valueRef) &&
48		CFGetTypeID(valueRef) == CFStringGetTypeID())
49		pclass = cfString(static_cast<CFStringRef>(valueRef)).c_str();
50
51	// type is usually IOServiceMatched
52	mach_port_t pp = NotificationPort::port();
53	secdebug("iokit", "XNotificationPort::add - type: %s [port: %p (0x%08X), class: %s]",
54		type, mPortRef, pp, pclass);
55
56//	CFShow(match.dict());
57	// p (void)CFShow(match.dict())
58	io_iterator_t iterator;
59 	Error::check(::IOServiceAddMatchingNotification(mPortRef, type,
60		match, ioNotify, &receiver, &iterator));
61	CFRetain(match);	// compensate for IOSAMN not retaining its argument
62
63	// run initial iterator to process existing devices
64	secdebug("iokit", "dispatching INITIAL device match iterator %p", reinterpret_cast<void *>(iterator));
65	DeviceIterator it(iterator);
66	receiver.ioChange(it);
67}
68
69void XNotificationPort::addInterestNotification(XReceiver &receiver, io_service_t service,
70	const io_name_t interestType)
71{
72	io_iterator_t iterator;
73	mach_port_t pp = NotificationPort::port();
74//	MachPlusPlus::Port(pp).dump(0);
75	secdebug("iokit", "XNotificationPort::addInterest - type: %s [port: %p (0x%08X), service: 0x%08X]",
76		interestType, mPortRef, pp, service);	// IOServiceMatched
77#if 1
78	CFRunLoopSourceRef notificationRunLoopSource = IONotificationPortGetRunLoopSource(mPortRef);
79	CFRunLoopSourceRef classRunLoopSource = NotificationPort::source();
80//    IONotificationPortRef r_notify_port = IONotificationPortCreate(0);
81	kern_return_t kr = ::IOServiceAddInterestNotification(mPortRef,	//,r_notify_port
82		service, interestType, ioDeviceNotification, &receiver, &iterator);
83	const char *msgstr = mach_error_string(kr);
84	const char *msgtyp = mach_error_type(kr);
85	if (msgstr && msgtyp)
86		secdebug("iokit", " msg: %s, typ: %s", msgstr, msgtyp);
87//	Error::check(kr);
88//    if(r_notify_port) IOObjectRelease((io_object_t)r_notify_port);
89#else
90	Error::check(::IOServiceAddInterestNotification(mPortRef,
91		service, interestType, ioDeviceNotification, &receiver, &iterator));
92#endif
93}
94
95// callbacks
96
97void XNotificationPort::ioNotify(void *refCon, io_iterator_t iterator)
98{
99	secdebug("iokit", "dispatching NEW device match iterator %p", reinterpret_cast<void *>(iterator));
100	DeviceIterator it(iterator);
101	reinterpret_cast<XReceiver *>(refCon)->ioChange(it);
102}
103
104void XNotificationPort::ioDeviceNotification(void *refCon, io_service_t service,
105	natural_t messageType, void *messageArgument)
106{
107	secdebug("iokit", "dispatching NEW device notification iterator, service 0x%08X, msg: 0x%04X, arg: %p",
108		service, messageType, messageArgument);
109
110	const char *msgstr = mach_error_string(messageType);
111	const char *msgtyp = mach_error_type(messageType);
112	if (msgstr && msgtyp)
113		secdebug("iokit", " msg: %s, typ: %s", msgstr, msgtyp);
114
115#if 0
116	secdebug("iokit", "kIOMessageServiceIsTerminated: 0x%04X", kIOMessageServiceIsTerminated);
117	secdebug("iokit", "kIOMessageServiceIsSuspended: 0x%04X", kIOMessageServiceIsSuspended);
118	secdebug("iokit", "kIOMessageServiceIsResumed: 0x%04X", kIOMessageServiceIsResumed);
119	secdebug("iokit", "kIOMessageServiceIsRequestingClose: 0x%04X", kIOMessageServiceIsRequestingClose);
120	secdebug("iokit", "kIOMessageServiceIsAttemptingOpen: 0x%04X", kIOMessageServiceIsAttemptingOpen);
121	secdebug("iokit", "kIOMessageServiceWasClosed: 0x%04X", kIOMessageServiceWasClosed);
122	secdebug("iokit", "kIOMessageServiceBusyStateChange: 0x%04X", kIOMessageServiceBusyStateChange);
123	secdebug("iokit", "kIOMessageServicePropertyChange: 0x%04X", kIOMessageServicePropertyChange);
124	secdebug("iokit", "kIOMessageCanDevicePowerOff: 0x%04X", kIOMessageCanDevicePowerOff);
125	secdebug("iokit", "kIOMessageDeviceWillPowerOff: 0x%04X", kIOMessageDeviceWillPowerOff);
126	secdebug("iokit", "kIOMessageDeviceWillNotPowerOff: 0x%04X", kIOMessageDeviceWillNotPowerOff);
127	secdebug("iokit", "kIOMessageDeviceHasPoweredOn: 0x%04X", kIOMessageDeviceHasPoweredOn);
128	secdebug("iokit", "kIOMessageCanSystemPowerOff: 0x%04X", kIOMessageCanSystemPowerOff);
129	secdebug("iokit", "iokit_vendor_specific_msg(0x000A): 0x%04X", iokit_vendor_specific_msg(0x000A));
130#endif
131
132//	assert(service!=io_service_t(-1));
133	if (service!=io_service_t(-1))
134		reinterpret_cast<XReceiver *>(refCon)->ioServiceChange(refCon, service, messageType, messageArgument);
135}
136
137
138} // end namespace IOKit
139} // end namespace Security
140
141
142