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> 26 27#include "IOHIDFamilyPrivate.h" 28#include "IOHIDPointingDevice.h" 29 30typedef struct __attribute__((packed)) ScrollDescriptor { 31 //09 38: Usage (Wheel) 32 UInt8 wheelUsageOp; 33 UInt8 wheelUsageNum; 34 //15 81: Logical Minimum.... (-127) 35 UInt8 wheelLogMinOp; 36 UInt8 wheelLogMinNum; 37 //25 7F: Logical Maximum.... (127) 38 UInt8 wheelLogMaxOp; 39 UInt8 wheelLogMaxNum; 40 //35 00: Physical Minimum.... (0) 41 UInt8 wheelPhyMinOp; 42 UInt8 wheelPhyMinNum; 43 //45 00: Physical Maximum.... (0) 44 UInt8 wheelPhyMaxOp; 45 UInt8 wheelPhyMaxNum; 46 //55 00: Unit Exponent.... (0) 47 UInt8 wheelUnitExpOp; 48 UInt8 wheelUnitExpNum; 49 //65 00: Unit.... (0) 50 UInt8 wheelUnitOp; 51 UInt8 wheelUnitNum; 52 //75 08: Report Size........ (8) 53 UInt8 wheelRptSizeOp; 54 UInt8 wheelRptSizeNum; 55 //95 01: Report Count....... (1) 56 UInt8 wheelCountOp; 57 UInt8 wheelCountNum; 58 //81 06: Input (Data) 59 UInt8 wheelInputOp; 60 UInt8 wheelInputNum; 61}ScrollDescriptor; 62 63typedef struct __attribute__((packed)) GenericMouseDescriptor { 64 //05 01: Usage Page (Generic Desktop) 65 UInt8 devUsagePageOp; 66 UInt8 devUsagePageNum; 67 //09 02: Usage (Mouse) 68 UInt8 devUsageOp; 69 UInt8 devUsageNum; 70 //A1 01: Collection (Application) 71 UInt8 appCollectionOp; 72 UInt8 appCollectionNum; 73 //05 09: Usage Page (Button) 74 UInt8 buttonUsagePageOp; 75 UInt8 buttonUsagePageNum; 76 //19 01: Usage Minimum...... (1) 77 UInt8 buttonUsageMinOp; 78 UInt8 buttonUsageMinNum; 79 //29 08: Usage Maximum...... (8) 80 UInt8 buttonUsageMaxOp; 81 UInt8 buttonUsageMaxNum; 82 //15 00: Logical Minimum.... (0) 83 UInt8 buttonLogMinOp; 84 UInt8 buttonLogMinNum; 85 //25 01: Logical Maximum.... (1) 86 UInt8 buttonLogMaxOp; 87 UInt8 buttonLogMaxNum; 88 //95 08: Report Count....... (8) 89 UInt8 buttonRptCountOp; 90 UInt8 buttonRptCountNum; 91 //75 01: Report Size........ (1) 92 UInt8 buttonRptSizeOp; 93 UInt8 buttonRptSizeNum; 94 //81 02: Input (Data) 95 UInt8 buttonInputOp; 96 UInt8 buttonInputNum; 97 //95 00: Report Count....... (0) 98 UInt8 fillCountOp; 99 UInt8 fillCountNum; 100 //75 01: Report Size........ (1) 101 UInt8 fillSizeOp; 102 UInt8 fillSizeNum; 103 //81 00: Input (Constant) 104 UInt8 fillInputOp; 105 UInt8 fillInputNum; 106 //05 01: Usage Page (Generic Desktop) 107 UInt8 pointerUsagePageOp; 108 UInt8 pointerUsagePageNum; 109 //09 01: Usage (Pointer) 110 UInt8 pointerUsageOp; 111 UInt8 pointerUsageNum; 112 //A1 00: Collection (Physical) 113 UInt8 pysCollectionOp; 114 UInt8 pysCollectionNum; 115 //09 30: Usage (X) 116 UInt8 xUsageOp; 117 UInt8 xUsageNum; 118 //09 31: Usage (Y) 119 UInt8 yUsageOp; 120 UInt8 yUsageNum; 121 //16 0: Logical Minimum.... (0) 122 UInt8 xyLogMinOp; 123 UInt8 xyLogMinNum[2];// 124 //26 0: Logical Maximum.... (0) 125 UInt8 xyLogMaxOp; 126 UInt8 xyLogMaxNum[2];// 127 //36 00: Physical Minimum.... (0) 128 UInt8 xyPhyMinOp; 129 UInt8 xyPhyMinNum[2];// 130 //46 00: Physical Maximum.... (0) 131 UInt8 xyPhyMaxOp; 132 UInt8 xyPhyMaxNum[2];// 133 //55 00: Unit Exponent.... (0) 134 UInt8 xyUnitExpOp; 135 UInt8 xyUnitExpNum; 136 //65 00: Unit.... (0) 137 UInt8 xyUnitOp; 138 UInt8 xyUnitNum; 139 //75 10: Report Size........ (16) 140 UInt8 xyRptSizeOp; 141 UInt8 xyRptSizeNum; 142 //95 02: Report Count....... (2) 143 UInt8 xyRptCountOp; 144 UInt8 xyRptCountNum; 145 //81 06: Input (Data) 146 UInt8 xyInputOp; 147 UInt8 xyInputNum; 148 //C0: End Collection 149 UInt8 pysCollectionEnd; 150 151 ScrollDescriptor scrollDescriptor; 152 153 UInt8 appCollectionEnd; 154} GenericMouseDescriptor; 155 156 157typedef struct __attribute__((packed)) GenericMouseReport{ 158 UInt8 buttons; 159 UInt8 x[2]; 160 UInt8 y[2]; 161 UInt8 wheel; 162} GenericMouseReport; 163 164static inline void convert16to8( const UInt16 src, 165 UInt8 * dst) 166{ 167 dst[0] = 0x00ff & src; 168 dst[1] = (0xff00 & src) >> 8; 169} 170 171static Boolean CheckDeviceUsage(IOHIDDevice * device, UInt32 usagePage, UInt32 usage) 172{ 173 OSDictionary * matchingDictionary = OSDictionary::withCapacity(2); 174 Boolean ret = FALSE; 175 176 if ( matchingDictionary ) 177 { 178 OSNumber * number; 179 180 number = OSNumber::withNumber(usagePage, 32); 181 if ( number ) 182 { 183 matchingDictionary->setObject(kIOHIDDeviceUsagePageKey, number); 184 number->release(); 185 } 186 187 number = OSNumber::withNumber(usage, 32); 188 if ( number ) 189 { 190 matchingDictionary->setObject(kIOHIDDeviceUsageKey, number); 191 number->release(); 192 } 193 194 ret = CompareDeviceUsage(device, matchingDictionary, NULL, 0); 195 196 matchingDictionary->release(); 197 } 198 199 return ret; 200} 201 202#define super IOHIDDeviceShim 203 204OSDefineMetaClassAndStructors( IOHIDPointingDevice, IOHIDDeviceShim ) 205 206 207IOHIDPointingDevice * 208IOHIDPointingDevice::newPointingDeviceAndStart(IOService *owner, UInt8 numButtons, UInt32 resolution, bool scroll, UInt32 location) 209{ 210 IOService * provider = owner; 211 212 while ( NULL != (provider = provider->getProvider()) ) 213 { 214 if(OSDynamicCast(IOHIDevice, provider) || 215 (OSDynamicCast(IOHIDDevice, provider) && CheckDeviceUsage((IOHIDDevice*)provider, kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse)) ) 216 { 217 return 0; 218 } 219 } 220 221 IOHIDPointingDevice * device = new IOHIDPointingDevice; 222 223 if (device) 224 { 225 if (!device->initWithLocation(location)){ 226 device->release(); 227 return 0; 228 } 229 device->_numButtons = numButtons; 230 device->_resolution = resolution; 231 device->_isScrollPresent = scroll; 232 233 if ( device->attach(owner) ) 234 { 235 if (!device->start(owner)) 236 { 237 device->detach(owner); 238 device->release(); 239 device = 0; 240 } 241 } 242 else 243 { 244 device->release(); 245 device = 0; 246 } 247 } 248 249 return device; 250} 251 252 253bool IOHIDPointingDevice::initWithLocation( UInt32 location ) 254{ 255 if (!super::initWithLocation(location)) 256 return false; 257 258 _report = 0; 259 260 return true; 261} 262 263void IOHIDPointingDevice::free() 264{ 265 if (_report) _report->release(); 266 267 super::free(); 268} 269 270bool IOHIDPointingDevice::handleStart( IOService * provider ) 271{ 272 if (!super::handleStart(provider)) 273 return false; 274 275 _pointing = OSDynamicCast(IOHIPointing, provider); 276 277 _report = IOBufferMemoryDescriptor::withCapacity( 278 sizeof(GenericMouseReport), kIODirectionNone, true); 279 280 bzero(_report->getBytesNoCopy(), sizeof(GenericMouseReport)); 281 282 return (_report) ? true : false; 283} 284 285IOReturn IOHIDPointingDevice::newReportDescriptor( 286 IOMemoryDescriptor ** descriptor ) const 287{ 288 void *desc; 289 290 if (!descriptor) 291 return kIOReturnBadArgument; 292 293 *descriptor = IOBufferMemoryDescriptor::withCapacity( 294 sizeof(GenericMouseDescriptor), 295 kIODirectionNone, 296 true); 297 298 if (! *descriptor) 299 return kIOReturnNoMemory; 300 301 desc = ((IOBufferMemoryDescriptor *)(*descriptor))->getBytesNoCopy(); 302 303 UInt8 genMouseDesc[] = { 304 0x05, 0x01, // Usage Page (Generic Desktop) 305 0x09, 0x02, // Usage (Mouse) 306 0xA1, 0x01, // Collection (Application) 307 0x05, 0x09, // Usage Page (Button) 308 0x19, 0x01, // Usage Minimum........... (1) 309 0x29, 0x08, // Usage Maximum........... (8) 310 0x15, 0x00, // Logical Minimum......... (0) 311 0x25, 0x01, // Logical Maximum......... (1) 312 0x95, 0x08, // Report Count............ (8) 313 0x75, 0x01, // Report Size............. (1) 314 0x81, 0x02, // Input...................(Data, Variable, Absolute) 315 0x95, 0x00, // Report Count............ (0) 316 0x75, 0x01, // Report Size............. (1) 317 0x81, 0x00, // Input...................(Data, Array, Absolute) 318 0x05, 0x01, // Usage Page (Generic Desktop) 319 0x09, 0x01, // Usage (Pointer) 320 0xA1, 0x00, // Collection (Physical) 321 0x09, 0x30, // Usage (X) 322 0x09, 0x31, // Usage (Y) 323 0x16, 0x01, 0x80, // Logical Minimum......... (-32767) 324 0x26, 0xFF, 0x7F, // Logical Maximum......... (32767) 325 0x36, 0x00, 0x00, // Physical Minimum........ (0) 326 0x46, 0x00, 0x00, // Physical Maximum........ (0) 327 0x55, 0x00, // Unit Exponent........... (0) 328 0x65, 0x00, // Unit.................... (0) 329 0x75, 0x10, // Report Size............. (16) 330 0x95, 0x02, // Report Count............ (2) 331 0x81, 0x06, // Input...................(Data, Variable, Relative) 332 0xC0, // End Collection 333 0x00, // 0x00, 334 0x00, // 0x00, 335 0x00, // 0x00, 336 0x00, // 0x00, 337 0x00, // 0x00, 338 0x00, // 0x00, 339 0x00, // 0x00, 340 0x00, // 0x00, 341 0x00, // 0x00, 342 0x00, // 0x00, 343 0x00, // 0x00, 344 0x00, // 0x00, 345 0x00, // 0x00, 346 0x00, // 0x00, 347 0x00, // 0x00, 348 0x00, // 0x00, 349 0x00, // 0x00, 350 0x00, // 0x00, 351 0x00, // 0x00, 352 0x00, // 0x00, 353 0xC0, // End Collection 354 }; 355 356 bcopy(genMouseDesc, desc, sizeof(GenericMouseDescriptor)); 357 358 GenericMouseDescriptor *mouse = (GenericMouseDescriptor *)desc; 359 360 if ((_numButtons <= 8) && 361 (_numButtons != mouse->buttonRptCountNum)) 362 { 363 mouse->buttonRptCountNum = _numButtons; 364 mouse->buttonUsageMaxNum = _numButtons; 365 mouse->fillCountNum = 8 - _numButtons; 366 } 367 368 369 if (_resolution && _resolution != 400) 370 { 371 convert16to8((unsigned short)-32767, mouse->xyLogMinNum); 372 convert16to8(32767, mouse->xyLogMaxNum); 373 374 UInt16 phys = 3276700 / _resolution; 375 convert16to8(-phys, mouse->xyPhyMinNum); 376 convert16to8(phys, mouse->xyPhyMaxNum); 377 378 mouse->xyUnitNum = 0x13; 379 mouse->xyUnitExpNum = 0x0e; 380 } 381 382 if (_isScrollPresent) 383 { 384 UInt8 scrollDes[] = { 385 0x09, 0x38, // Usage 56 (0x38) 386 0x15, 0x81, // Logical Minimum......... (-127) 387 0x25, 0x7F, // Logical Maximum......... (127) 388 0x35, 0x00, // Physical Minimum........ (0) 389 0x45, 0x00, // Physical Maximum........ (0) 390 0x55, 0x00, // Unit Exponent........... (0) 391 0x65, 0x00, // Unit.................... (0) 392 0x75, 0x08, // Report Size............. (8) 393 0x95, 0x01, // Report Count............ (1) 394 0x81, 0x06, // Input...................(Data, Variable, Relative) 395 }; 396 397 bcopy(scrollDes, &mouse->scrollDescriptor, sizeof(ScrollDescriptor)); 398 } 399 400 401 return kIOReturnSuccess; 402} 403 404IOReturn IOHIDPointingDevice::getReport(IOMemoryDescriptor *report, 405 IOHIDReportType reportType, 406 IOOptionBits options __unused ) 407{ 408 if (!report) 409 return kIOReturnError; 410 411 if ( reportType != kIOHIDReportTypeInput) 412 return kIOReturnUnsupported; 413 414 report->writeBytes(0, _report->getBytesNoCopy(), min(report->getLength(), _report->getLength())); 415 return kIOReturnSuccess; 416} 417 418void IOHIDPointingDevice::postMouseEvent(UInt8 buttons, UInt16 x, UInt16 y, UInt8 wheel) 419{ 420 GenericMouseReport *report = (GenericMouseReport*)_report->getBytesNoCopy(); 421 422 if (!report) 423 return; 424 425 report->buttons = buttons; 426 convert16to8(x, report->x); 427 convert16to8(y, report->y); 428 report->wheel = wheel; 429 430 handleReport(_report); 431} 432 433OSString * IOHIDPointingDevice::newProductString() const 434{ 435 OSString * string = 0; 436 437 if ( !(string = super::newProductString()) ) 438 string = OSString::withCString("Virtual Mouse"); 439 440 return string; 441} 442 443