1/*
2 *
3 * @APPLE_LICENSE_HEADER_START@
4 *
5 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include <IOKit/IOLib.h>    // IOMalloc/IOFree
26#include "IOHIDDeviceShim.h"
27
28#define super IOHIDDevice
29
30OSDefineMetaClassAndAbstractStructors( IOHIDDeviceShim, IOHIDDevice )
31
32bool IOHIDDeviceShim::initWithLocation(UInt32 location)
33{
34    if (!super::init())
35        return false;
36
37    _device 	= 0;
38    _hiDevice 	= 0;
39    _transport  = kIOHIDTransportNone;
40    _location   = location;
41
42    return true;
43}
44
45bool IOHIDDeviceShim::handleStart( IOService * provider )
46{
47    IOService *device = 0;
48
49    if (!super::handleStart(provider))
50        return false;
51
52    if ((_hiDevice = OSDynamicCast(IOHIDevice, provider)))
53    {
54        if (_hiDevice->getProperty(kIOHIDVirtualHIDevice) == kOSBooleanTrue)
55            return false;
56
57        device = _hiDevice;
58        do {
59			if ((_device = (IOService *)device->metaCast("IOHIDDevice")))
60			{
61				break;
62			}
63
64            if ((_device = (IOService *)device->metaCast("IOUSBDevice")) || (_device = (IOService *)device->metaCast("IOUSBInterface")))
65            {
66                _transport = kIOHIDTransportUSB;
67                break;
68            }
69
70			if ( NULL != (_device = (IOService *)device->metaCast("IOADBDevice")) )
71            {
72                _transport = kIOHIDTransportADB;
73                break;
74            }
75
76			if ( NULL != (_device = (IOService *)device->metaCast("ApplePS2Controller")) )
77            {
78                _transport = kIOHIDTransportPS2;
79                break;
80            }
81        }
82        while ( NULL != (device = device->getProvider()) );
83    }
84
85    return true;
86}
87
88OSString * IOHIDDeviceShim::newProductString() const
89{
90    OSString * string       = NULL;
91    OSString * returnString = NULL;
92
93    if (_device) {
94        string = (OSString*)_device->copyProperty("USB Product Name");
95        if (!OSDynamicCast(OSString,string))
96            OSSafeReleaseNULL(string);
97        if (!string) {
98            string = (OSString*)_device->copyProperty(kIOHIDProductKey);
99            if (!OSDynamicCast(OSString,string))
100                OSSafeReleaseNULL(string);
101        }
102    }
103
104    if (string) {
105        returnString = OSString::withString(string);
106    }
107    else if (_hiDevice) {
108        if (_hiDevice->hidKind() == kHIRelativePointingDevice) {
109            string = (OSString*)_hiDevice->copyProperty(kIOHIDPointerAccelerationTypeKey);
110            if (!OSDynamicCast(OSString,string))
111                OSSafeReleaseNULL(string);
112            if (string && string->isEqualTo(kIOHIDTrackpadAccelerationType)) {
113                returnString = OSString::withCString("Trackpad");
114            }
115            else  {
116                returnString = OSString::withCString("Mouse");
117            }
118        }
119        else if (_hiDevice->hidKind() == kHIKeyboardDevice) {
120            returnString = (_transport == kIOHIDTransportADB) ? OSString::withCString("Built-in keyboard") : OSString::withCString("Keyboard");
121        }
122    }
123
124    if ( _hiDevice && returnString )
125        _hiDevice->setProperty(kIOHIDProductKey, returnString);
126
127    OSSafeReleaseNULL(string);
128    return returnString;
129}
130
131OSString * IOHIDDeviceShim::newManufacturerString() const
132{
133    OSString * string       = NULL;
134    OSString * returnString = NULL;
135
136    if (_device) {
137        string = (OSString*)_device->copyProperty("USB Vendor Name");
138        if (!OSDynamicCast(OSString,string))
139            OSSafeReleaseNULL(string);
140        if (!string) {
141            string = (OSString*)_device->copyProperty(kIOHIDManufacturerKey);
142            if (!OSDynamicCast(OSString,string))
143                OSSafeReleaseNULL(string);
144        }
145    }
146
147    if (string) {
148        returnString = OSString::withString(string);
149    }
150    else if (_hiDevice && (_hiDevice->deviceType() > 2)) {
151        returnString = OSString::withCString("Apple");
152    }
153    OSSafeReleaseNULL(string);
154
155    if ( _hiDevice && returnString )
156        _hiDevice->setProperty(kIOHIDManufacturerKey, returnString);
157
158    return returnString;
159}
160
161OSString * IOHIDDeviceShim::newTransportString() const
162{
163    OSString * returnString = NULL;
164
165    switch (_transport)
166    {
167        case kIOHIDTransportUSB:
168            returnString = OSString::withCString("USB");
169			break;
170
171        case kIOHIDTransportADB:
172            returnString = OSString::withCString("ADB");
173			break;
174
175        case kIOHIDTransportPS2:
176            returnString = OSString::withCString("PS2");
177			break;
178
179		default:
180			returnString = _device ?
181								(OSString*)_device->copyProperty(kIOHIDTransportKey) :
182								NULL;
183			break;
184    }
185
186    if ( _hiDevice && returnString )
187        _hiDevice->setProperty(kIOHIDTransportKey, returnString);
188
189    return returnString;
190}
191
192OSNumber * IOHIDDeviceShim::newVendorIDNumber() const
193{
194    OSNumber * number       = NULL;
195    OSNumber * returnNumber = NULL;
196
197    if (_device) {
198        number = (OSNumber*)_device->copyProperty("idVendor");
199        if (!OSDynamicCast(OSNumber, number))
200            OSSafeReleaseNULL(number);
201        if (!number) {
202            number = (OSNumber*)_device->copyProperty(kIOHIDVendorIDKey);
203            if (!OSDynamicCast(OSNumber, number))
204                OSSafeReleaseNULL(number);
205        }
206    }
207
208    if (number) {
209        returnNumber = OSNumber::withNumber(number->unsigned32BitValue(), 32);
210    }
211    else if (_hiDevice && (_hiDevice->deviceType() > 2)) {
212        UInt32	vendorID = kIOHIDAppleVendorID;
213        returnNumber = OSNumber::withNumber(vendorID, 32);
214    }
215    OSSafeReleaseNULL(number);
216
217    if ( _hiDevice && returnNumber )
218        _hiDevice->setProperty(kIOHIDVendorIDKey, returnNumber);
219
220    return returnNumber;
221}
222
223OSNumber * IOHIDDeviceShim::newProductIDNumber() const
224{
225    OSNumber * number       = NULL;
226    OSNumber * returnNumber = NULL;
227
228    if (_device) {
229        number = (OSNumber*)_device->copyProperty("idProduct");
230        if (!OSDynamicCast(OSNumber, number))
231            OSSafeReleaseNULL(number);
232        if (!number) {
233            number = (OSNumber*)_device->copyProperty(kIOHIDProductIDKey);
234            if (!OSDynamicCast(OSNumber, number))
235                OSSafeReleaseNULL(number);
236        }
237    }
238
239    if (number)
240        returnNumber = OSNumber::withNumber(number->unsigned32BitValue(), 32);
241    OSSafeReleaseNULL(number);
242
243    if ( _hiDevice && returnNumber )
244        _hiDevice->setProperty(kIOHIDProductIDKey, returnNumber);
245
246    return returnNumber;
247}
248
249OSNumber * IOHIDDeviceShim::newLocationIDNumber() const
250{
251    UInt32      location = _location;
252
253    if (_device && !location)
254    {
255        OSNumber *number = (OSNumber*)_device->copyProperty("locationID");
256        if (!OSDynamicCast(OSNumber, number))
257            OSSafeReleaseNULL(number);
258        if (!number) {
259            number = (OSNumber*)_device->copyProperty(kIOHIDLocationIDKey);
260            if (!OSDynamicCast(OSNumber, number))
261                OSSafeReleaseNULL(number);
262        }
263
264        if (number)
265        {
266            location = number->unsigned32BitValue();
267        }
268        else
269        {
270            // Make up a location based on the ADB address and handler id
271            number = (OSNumber*)_device->copyProperty("address");
272            if ( OSDynamicCast(OSNumber, number) )
273                location |= number->unsigned8BitValue() << 24;
274            OSSafeReleaseNULL(number);
275
276            number = (OSNumber*)_device->copyProperty("handler id");
277            if ( OSDynamicCast(OSNumber, number) )
278                location |= number->unsigned8BitValue() << 16;
279        }
280        OSSafeReleaseNULL(number);
281    }
282
283    return (location) ? OSNumber::withNumber(location, 32) : 0;
284}
285
286OSString * IOHIDDeviceShim::newSerialNumberString() const
287{
288    OSNumber *number = NULL;
289    OSString *string = NULL;
290    char str[33];
291
292    if (_device) {
293        number = (OSNumber*)_device->copyProperty("iSerialNumber");
294        if ( OSDynamicCast(OSNumber, number) ) {
295            snprintf(str, sizeof (str), "%d", number->unsigned32BitValue());
296            str[32] = 0;
297            string = OSString::withCString(str);
298        }
299        else {
300            string = (OSString*)_device->copyProperty(kIOHIDSerialNumberKey);
301            if (!OSDynamicCast(OSString, string)) {
302                OSSafeReleaseNULL(string);
303            }
304        }
305        OSSafeReleaseNULL(number);
306    }
307
308    return string;
309}
310
311bool IOHIDDeviceShim::isSeized()
312{
313    return _reserved->seizedClient != NULL;
314}
315
316