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 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 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 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, 305 0x09, 0x02, 306 0xA1, 0x01, 307 // Button 308 0x05, 0x09, 0x19, 0x01, 309 0x29, 0x08, 0x15, 0x00, 310 0x25, 0x01, 0x95, 0x08, 311 0x75, 0x01, 0x81, 0x02, 312 313 // Constant 314 0x95, 0x00, 0x75, 0x01, 315 0x81, 0x00, 316 317 // Pointer 318 0x05, 0x01, 0x09, 0x01, 319 0xA1, 0x00, 320 0x09, 0x30, 321 0x09, 0x31, 322 323 // log min/max 324 0x16, 0x01, 0x80, 325 0x26, 0xff, 0x7f, 326 327 // Phy min/max 328 0x36, 0x00, 0x00, 329 0x46, 0x00, 0x00, 330 331 // Unit, Unit Exponent 332 0x55, 0x00, 333 0x65, 0x00, 334 335 0x75, 0x10, 0x95, 0x02, 336 0x81, 0x06, 337 0xC0, 338 // Wheel Padding 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 350 0xC0 351 }; 352 353 bcopy(genMouseDesc, desc, sizeof(GenericMouseDescriptor)); 354 355 GenericMouseDescriptor *mouse = (GenericMouseDescriptor *)desc; 356 357 if ((_numButtons <= 8) && 358 (_numButtons != mouse->buttonRptCountNum)) 359 { 360 mouse->buttonRptCountNum = _numButtons; 361 mouse->buttonUsageMaxNum = _numButtons; 362 mouse->fillCountNum = 8 - _numButtons; 363 } 364 365 366 if (_resolution && _resolution != 400) 367 { 368 convert16to8((unsigned short)-32767, mouse->xyLogMinNum); 369 convert16to8(32767, mouse->xyLogMaxNum); 370 371 UInt16 phys = 3276700 / _resolution; 372 convert16to8(-phys, mouse->xyPhyMinNum); 373 convert16to8(phys, mouse->xyPhyMaxNum); 374 375 mouse->xyUnitNum = 0x13; 376 mouse->xyUnitExpNum = 0x0e; 377 } 378 379 if (_isScrollPresent) 380 { 381 UInt8 scrollDes[] = { 382 0x09, 0x38, 383 0x15, 0x81, 384 0x25, 0x7f, 385 0x35, 0x00, 386 0x45, 0x00, 387 0x55, 0x00, 388 0x65, 0x00, 389 0x75, 0x08, 390 0x95, 0x01, 391 0x81, 0x06 392 }; 393 394 bcopy(scrollDes, &mouse->scrollDescriptor, sizeof(ScrollDescriptor)); 395 } 396 397 398 return kIOReturnSuccess; 399} 400 401IOReturn IOHIDPointingDevice::getReport(IOMemoryDescriptor *report, 402 IOHIDReportType reportType, 403 IOOptionBits options __unused ) 404{ 405 if (!report) 406 return kIOReturnError; 407 408 if ( reportType != kIOHIDReportTypeInput) 409 return kIOReturnUnsupported; 410 411 report->writeBytes(0, _report->getBytesNoCopy(), min(report->getLength(), _report->getLength())); 412 return kIOReturnSuccess; 413} 414 415void IOHIDPointingDevice::postMouseEvent(UInt8 buttons, UInt16 x, UInt16 y, UInt8 wheel) 416{ 417 GenericMouseReport *report = (GenericMouseReport*)_report->getBytesNoCopy(); 418 419 if (!report) 420 return; 421 422 report->buttons = buttons; 423 convert16to8(x, report->x); 424 convert16to8(y, report->y); 425 report->wheel = wheel; 426 427 handleReport(_report); 428} 429 430OSString * IOHIDPointingDevice::newProductString() const 431{ 432 OSString * string = 0; 433 434 if ( !(string = super::newProductString()) ) 435 string = OSString::withCString("Virtual Mouse"); 436 437 return string; 438} 439 440