1/* 2 * Copyright (c) 1991 NeXT Computer, Inc. 3 * Copyright (c) 1996-2000 Apple Computer, Inc. All rights reserved. 4 * 5 * @APPLE_LICENSE_HEADER_START@ 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 event_status_driver_api.c 26 API for the events status driver. 27 This file implements public API. 28 mpaque 11Oct91 29 30 Modified: 31 29 June 1992 Mike Paquette at NeXT 32 Implemented API for the new Mach based Event Driver. 33 34******************************************************************************/ 35 36#include <mach/mach.h> 37 38#include <CoreFoundation/CoreFoundation.h> 39 40#include <IOKit/hidsystem/event_status_driver.h> 41#include <IOKit/IOKitLib.h> 42#include <IOKit/hidsystem/IOHIDLib.h> 43#include <IOKit/hidsystem/IOHIDParameter.h> 44 45#include <math.h> 46#include <limits.h> 47 48/* Definitions specific to the Mach based event driver */ 49#define BRIGHT_MAX 64 50 51static void secs_to_packed_nsecs(double secs, UInt64 *nsecs) 52{ 53 *nsecs = (1000.0 * 1000.0 * 1000.0 * secs); 54} 55 56static double packed_nsecs_to_secs(UInt64 nsecs) 57{ 58 return( ((double)nsecs) / 1000.0 / 1000.0 / 1000.0); 59} 60 61/* Open and Close */ 62NXEventHandle NXOpenEventStatus(void) 63{ 64 NXEventHandle handle = MACH_PORT_NULL; 65 register kern_return_t kr; 66 io_service_t service = MACH_PORT_NULL; 67 mach_port_t masterPort; 68 69 do { 70 71 kr = IOMasterPort( MACH_PORT_NULL, &masterPort ); 72 if( kr != KERN_SUCCESS) 73 break; 74 75 service = IORegistryEntryFromPath( masterPort, 76 kIOServicePlane ":/IOResources/IOHIDSystem" ); 77 if( !service) 78 break; 79 80 kr = IOServiceOpen( service, 81 mach_task_self(), 82 kIOHIDParamConnectType, 83 &handle); 84 85 IOObjectRelease( service ); 86 87 } while( false ); 88 89 return( handle ); 90} 91 92void NXCloseEventStatus(NXEventHandle handle) 93{ 94 IOServiceClose( handle ); 95} 96 97/* Status query */ 98NXEventSystemInfoType NXEventSystemInfo(NXEventHandle handle, 99 char *flavor, 100 NXEventSystemInfoType evs_info, 101 unsigned int *evs_info_cnt) 102{ 103 kern_return_t kr; 104 NXEventSystemDevice * info = (NXEventSystemDevice *) evs_info; 105 int maxDeviceCount = (*evs_info_cnt) * sizeof( int) / sizeof( NXEventSystemDevice); 106 int deviceCount = 0; 107 int i; 108 109 io_registry_entry_t hidsystem; 110 111 CFArrayRef array; 112 CFDictionaryRef dict; 113 CFNumberRef num; 114 SInt32 val; 115 116 // Translate the one existing old case to new format 117 if ( ((uintptr_t) flavor) == __OLD_NX_EVS_DEVICE_INFO ) 118 flavor = NX_EVS_DEVICE_INFO; 119 120 if( strcmp( flavor, NX_EVS_DEVICE_INFO)) 121 kr = kIOReturnUnsupported; 122 123 do { 124 kr = IOConnectGetService( handle, &hidsystem ); 125 if( KERN_SUCCESS != kr ) 126 break; 127 128 array = IORegistryEntryCreateCFProperty(hidsystem, CFSTR("NXSystemInfo"), 129 kCFAllocatorDefault, kNilOptions); 130 131 IOObjectRelease( hidsystem ); 132 133 if( !array ) 134 break; 135 136 deviceCount = CFArrayGetCount(array); 137 138 if ( deviceCount > maxDeviceCount ) 139 deviceCount = maxDeviceCount; 140 141 for ( i=0; i<deviceCount; i++) { 142 dict = CFArrayGetValueAtIndex(array, i); 143 144 if( !dict ) 145 continue; 146 147 if( (num = CFDictionaryGetValue( dict, CFSTR(kIOHIDKindKey )))) { 148 149 CFNumberGetValue( num, kCFNumberSInt32Type, &val ); 150 info[ i ].dev_type = val; 151 152 if( (num = CFDictionaryGetValue( dict, CFSTR(kIOHIDInterfaceIDKey )))) 153 CFNumberGetValue( num, kCFNumberSInt32Type, &val ); 154 else 155 val = 0; 156 info[ i ].interface = val; 157 158 if( (num = CFDictionaryGetValue( dict, CFSTR(kIOHIDSubinterfaceIDKey )))) 159 CFNumberGetValue( num, kCFNumberSInt32Type, &val ); 160 else 161 val = 0; 162 info[ i ].id = val; 163 164 info[ i ].interface_addr = 0; 165 166 } 167 } 168 CFRelease(array); 169 170 } while( false ); 171 172 if ( kr == KERN_SUCCESS ) 173 *evs_info_cnt = (deviceCount * sizeof( NXEventSystemDevice) / sizeof( int)); 174 else 175 evs_info = (NXEventSystemInfoType) 0; 176 177 return evs_info; 178} 179 180kern_return_t IOHIDSetParameter( io_connect_t handle, CFStringRef key, 181 const void * bytes, IOByteCount size ) 182{ 183 kern_return_t kr = kIOReturnNoMemory; 184 CFNumberType numberType; 185 CFNumberRef numberRef; 186 187 if (!bytes || !size) 188 return kIOReturnError; 189 190 switch ( size ) 191 { 192 case sizeof(UInt64): 193 numberType = kCFNumberSInt64Type; 194 break; 195 case sizeof(UInt32): 196 numberType = kCFNumberSInt32Type; 197 break; 198 case sizeof(UInt16): 199 numberType = kCFNumberSInt16Type; 200 break; 201 case sizeof(UInt8): 202 numberType = kCFNumberSInt8Type; 203 break; 204 default: 205 numberType = kCFNumberSInt32Type; 206 break; 207 } 208 209 numberRef = CFNumberCreate(kCFAllocatorDefault, numberType, bytes); 210 if( numberRef) 211 { 212 kr = IOConnectSetCFProperty( handle, key, numberRef ); 213 CFRelease(numberRef); 214 } 215 216 217 return( kr ); 218} 219 220kern_return_t IOHIDSetCFTypeParameter( io_connect_t handle, CFStringRef key, CFTypeRef parameter) 221{ 222 kern_return_t kr = kIOReturnError; 223 224 if ( parameter ) 225 kr = IOConnectSetCFProperty( handle, key, parameter ); 226 else 227 kr = kIOReturnBadArgument; 228 229 return( kr ); 230} 231 232#ifndef kIOHIDParametersKey 233#define kIOHIDParametersKey "HIDParameters" 234#endif 235 236kern_return_t IOHIDGetParameter( io_connect_t handle, CFStringRef key, 237 IOByteCount maxSize, void * bytes, IOByteCount * actualSize ) 238{ 239 kern_return_t kr; 240 // io_service_t hidsystem; 241 CFDataRef data; 242 CFNumberRef number; 243 CFNumberType numberType; 244 CFTypeRef typeRef = NULL; 245 IOByteCount copySize; 246 247 if (!bytes || !maxSize) 248 return kIOReturnBadArgument; 249 250 kr = IOHIDCopyCFTypeParameter(handle, key, &typeRef); 251 252 if ( kr != kIOReturnSuccess ) 253 return kr; 254 255 if( !typeRef ) 256 return kIOReturnBadArgument; 257 258 if (CFGetTypeID(typeRef) == CFDataGetTypeID()) 259 { 260 data = (CFDataRef)typeRef; 261 copySize = CFDataGetLength(data); 262 *actualSize = copySize; 263 if( maxSize < copySize) 264 copySize = maxSize; 265 bcopy( CFDataGetBytePtr(data), bytes, copySize ); 266 } 267 else if (CFGetTypeID(typeRef) == CFNumberGetTypeID()) 268 { 269 number = (CFNumberRef)typeRef; 270 copySize = CFNumberGetByteSize(number); 271 *actualSize = copySize; 272 if( maxSize < copySize) 273 copySize = maxSize; 274 275 switch ( copySize ) 276 { 277 case sizeof(UInt64): 278 numberType = kCFNumberSInt64Type; 279 break; 280 case sizeof(UInt32): 281 numberType = kCFNumberSInt32Type; 282 break; 283 case sizeof(UInt16): 284 numberType = kCFNumberSInt16Type; 285 break; 286 case sizeof(UInt8): 287 numberType = kCFNumberSInt8Type; 288 break; 289 default: 290 numberType = kCFNumberSInt32Type; 291 break; 292 } 293 294 CFNumberGetValue( number, numberType, bytes ); 295 } 296 else 297 { 298 kr = kIOReturnBadArgument; 299 } 300 301 CFRelease(typeRef); 302 303 return( kr ); 304 305} 306 307kern_return_t IOHIDCopyCFTypeParameter( io_connect_t handle, CFStringRef key, CFTypeRef * parameter ) 308{ 309 kern_return_t kr; 310 io_service_t hidsystem; 311 CFDictionaryRef paramDict; 312 CFTypeRef tempParameter = NULL; 313 314 if (!parameter) 315 return kIOReturnError; 316 317 kr = IOConnectGetService( handle, &hidsystem ); 318 if( KERN_SUCCESS != kr ) 319 return( kr ); 320 321 if( (paramDict = IORegistryEntryCreateCFProperty( hidsystem, CFSTR(kIOHIDParametersKey), kCFAllocatorDefault, kNilOptions))) 322 { 323 if ( (tempParameter = CFDictionaryGetValue( paramDict, key)) ) 324 CFRetain(tempParameter); 325 326 CFRelease(paramDict); 327 } 328 329 if ( !tempParameter ) 330 tempParameter = IORegistryEntryCreateCFProperty( hidsystem, key, kCFAllocatorDefault, kNilOptions); 331 332 if ( !tempParameter ) 333 kr = kIOReturnBadArgument; 334 335 *parameter = tempParameter; 336 337 IOObjectRelease( hidsystem ); 338 339 return( kr ); 340} 341 342 343#define NXEvGetParameterChar( h,n,mx,p,sz ) IOHIDGetParameter( h, n,mx,p,sz ) 344 345static inline int NXEvSetParameterChar( io_connect_t handle, 346 CFStringRef key, 347 const void * bytes, 348 IOByteCount size ) 349{ 350 kern_return_t kr = kIOReturnNoMemory; 351 CFDataRef data; 352 353 do { 354 data = CFDataCreate( kCFAllocatorDefault, bytes, size ); 355 if( !data) 356 continue; 357 kr = IOHIDSetCFTypeParameter( handle, key, data ); 358 CFRelease(data); 359 360 } while( false ); 361 362 return( kr ); 363} 364 365static inline int NXEvSetParameterInt( NXEventHandle handle, 366 CFStringRef parameterName, 367 unsigned int *parameterArray, 368 unsigned int count) 369{ 370 371 CFMutableArrayRef arrayRef; 372 CFNumberRef numberRef; 373 IOReturn ret = kIOReturnNoMemory; 374 unsigned int i; 375 376 377 if (!parameterArray || !count) 378 return kIOReturnError; 379 380 if (count > 1) 381 { 382 arrayRef = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks); 383 if ( !arrayRef ) 384 return kIOReturnNoMemory; 385 386 for (i=0; i<count; i++) 387 { 388 numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &(parameterArray[i])); 389 390 if (numberRef) 391 { 392 CFArraySetValueAtIndex(arrayRef, i, numberRef); 393 CFRelease(numberRef); 394 } 395 } 396 397 ret = IOHIDSetCFTypeParameter(handle, parameterName, arrayRef); 398 399 CFRelease(arrayRef); 400 } 401 else 402 { 403 numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &(parameterArray[0])); 404 405 if (numberRef) 406 { 407 ret = IOHIDSetCFTypeParameter(handle, parameterName, numberRef); 408 CFRelease(numberRef); 409 } 410 411 } 412 return ret; 413} 414 415static inline int NXEvGetParameterInt( NXEventHandle handle, 416 CFStringRef parameterName, 417 unsigned int maxCount, 418 unsigned int *parameterArray, 419 unsigned int *returnedCount) 420{ 421 422 CFArrayRef arrayRef; 423 CFNumberRef numberRef; 424 CFTypeRef typeRef; 425 IOReturn ret; 426 unsigned int i; 427 428 429 ret = IOHIDCopyCFTypeParameter(handle, parameterName, &typeRef); 430 431 if ( ret != kIOReturnSuccess ) 432 return ret; 433 434 if ( !typeRef || (CFGetTypeID(typeRef) != CFArrayGetTypeID()) || !parameterArray || !maxCount) 435 return kIOReturnBadArgument; 436 437 arrayRef = (CFArrayRef)typeRef; 438 439 *returnedCount = CFArrayGetCount(arrayRef); 440 441 if( maxCount < *returnedCount) 442 *returnedCount = maxCount; 443 444 for (i=0; i<*returnedCount; i++) 445 { 446 numberRef = CFArrayGetValueAtIndex(arrayRef, i); 447 448 if (numberRef) 449 CFNumberGetValue(numberRef, kCFNumberIntType, &(parameterArray[i])); 450 } 451 452 CFRelease(arrayRef); 453 454 return ret; 455} 456 457 458/* Keyboard */ 459 460void NXResetKeyboard(NXEventHandle handle) 461{ 462 unsigned int params[EVSIORKBD_SIZE]; 463 464 NXEvSetParameterInt( handle, CFSTR(EVSIORKBD), params, EVSIORKBD_SIZE); 465} 466 467void NXSetKeyRepeatInterval(NXEventHandle handle, double rate) 468{ 469 UInt64 params; 470 secs_to_packed_nsecs( rate, ¶ms ); 471 IOHIDSetParameter( handle, CFSTR(EVSIOSKR), ¶ms, sizeof(UInt64)); 472} 473 474double NXKeyRepeatInterval(NXEventHandle handle) 475{ 476 UInt64 params; 477 IOByteCount rcnt = EVSIOCKR_SIZE; 478 int r; 479 480 r = IOHIDGetParameter( handle, CFSTR(EVSIOSKR), sizeof(params), 481 ¶ms, &rcnt ); 482 if ( r != kIOReturnSuccess ) 483 return 0.0; 484 485 return packed_nsecs_to_secs( params ); 486} 487 488void NXSetKeyRepeatThreshold(NXEventHandle handle, double threshold) 489{ 490 UInt64 params; 491 secs_to_packed_nsecs( threshold, ¶ms ); 492 IOHIDSetParameter( handle, CFSTR(EVSIOSIKR), ¶ms, sizeof(params)); 493} 494 495double NXKeyRepeatThreshold(NXEventHandle handle) 496{ 497 UInt64 params; 498 IOByteCount rcnt = EVSIOCKR_SIZE; 499 int r; 500 501 r = IOHIDGetParameter( handle, CFSTR(EVSIOSIKR), sizeof(UInt64), 502 ¶ms, &rcnt ); 503 if ( r != kIOReturnSuccess ) 504 return 0.0; 505 return packed_nsecs_to_secs( params ); 506} 507 508NXKeyMapping * NXSetKeyMapping(NXEventHandle handle, NXKeyMapping *keymap) 509{ 510 int r; 511 512 if ( keymap->size > EVSIOSKM_SIZE ) 513 return (NXKeyMapping *)0; 514 r = NXEvSetParameterChar(handle, CFSTR(EVSIOSKM), 515 (unsigned char *) keymap->mapping, 516 keymap->size); 517 if ( r != kIOReturnSuccess ) 518 return (NXKeyMapping *)0; 519 return keymap; 520} 521 522int NXKeyMappingLength(NXEventHandle handle) 523{ 524 int r; 525 IOByteCount size; 526 527 r = NXEvGetParameterChar( handle, CFSTR(EVSIOCKM), 0, 528 (unsigned char *) 0, 529 &size ); 530 if ( r != kIOReturnSuccess ) 531 size = 0; 532 return size; 533} 534 535NXKeyMapping * NXGetKeyMapping(NXEventHandle handle, NXKeyMapping *keymap) 536{ 537 int r; 538 539 r = NXEvGetParameterChar( handle, CFSTR(EVSIOCKM), keymap->size, 540 (unsigned char *) keymap->mapping, 541 (IOByteCount *) &keymap->size ); 542 if ( r != kIOReturnSuccess ) 543 return (NXKeyMapping *)0; 544 return keymap; 545} 546 547/* Mouse */ 548 549void NXResetMouse(NXEventHandle handle) 550{ 551 unsigned int params[EVSIORMS_SIZE]; 552 553 NXEvSetParameterInt(handle, CFSTR(EVSIORMS), params, EVSIORMS_SIZE); 554} 555 556void NXSetClickTime(NXEventHandle handle, double secs) 557{ 558 UInt64 params; 559 560 secs_to_packed_nsecs( secs, ¶ms ); 561 IOHIDSetParameter(handle, CFSTR(EVSIOSCT), ¶ms, sizeof(params)); 562} 563 564double NXClickTime(NXEventHandle handle) 565{ 566 UInt64 params; 567 IOByteCount rcnt = EVSIOCCT_SIZE; 568 int r; 569 570 r = IOHIDGetParameter(handle, CFSTR(EVSIOCCT), sizeof(UInt64), 571 ¶ms, &rcnt ); 572 if ( r != kIOReturnSuccess ) 573 return 0.0; 574 return packed_nsecs_to_secs( params ); 575} 576 577void NXSetClickSpace(NXEventHandle handle, _NXSize_ *area) 578{ 579 unsigned int params[EVSIOSCS_SIZE]; 580 581 params[EVSIOSCS_X] = (unsigned int)(area->width); 582 params[EVSIOSCS_Y] = (unsigned int)(area->height); 583 584 NXEvSetParameterInt(handle, CFSTR(EVSIOSCS), params, EVSIOSCS_SIZE); 585} 586 587void NXGetClickSpace(NXEventHandle handle, _NXSize_ *area) 588{ 589 unsigned int params[EVSIOCCS_SIZE]; 590 unsigned int rcnt = EVSIOCCS_SIZE; 591 592 NXEvGetParameterInt(handle, CFSTR(EVSIOCCS), EVSIOCCS_SIZE, 593 params, &rcnt ); 594 area->width = params[EVSIOCCS_X]; 595 area->height = params[EVSIOCCS_Y]; 596} 597 598kern_return_t IOHIDGetScrollAcceleration( io_connect_t handle, double * acceleration ) 599{ 600 kern_return_t kr; 601 unsigned int fixed; 602 IOByteCount rsize; 603 604 kr = IOHIDGetParameter( handle, CFSTR(kIOHIDScrollAccelerationKey), 605 sizeof( fixed), (unsigned char *) &fixed, &rsize ); 606 607 if( kr == kIOReturnSuccess) 608 *acceleration = ((double) fixed) / 65536.0; 609 610 return( kr ); 611} 612 613kern_return_t IOHIDSetScrollAcceleration( io_connect_t handle, double acceleration ) 614{ 615 unsigned int fixed; 616 617 fixed = (unsigned int) (acceleration * 65536.0); 618 619 return( IOHIDSetParameter(handle, CFSTR(kIOHIDScrollAccelerationKey), 620 (unsigned char *) &fixed, sizeof(fixed)) ); 621} 622 623kern_return_t IOHIDGetMouseButtonMode( io_connect_t handle, int * mode ) 624{ 625 IOByteCount rsize; 626 627 return( IOHIDGetParameter( handle, CFSTR(kIOHIDPointerButtonMode), 628 sizeof( *mode), (unsigned char *) mode, &rsize )); 629} 630 631kern_return_t IOHIDSetMouseButtonMode( io_connect_t handle, int mode ) 632{ 633 return( IOHIDSetParameter(handle, CFSTR(kIOHIDPointerButtonMode), 634 (unsigned char *) &mode, sizeof(mode)) ); 635} 636 637kern_return_t IOHIDGetMouseAcceleration( io_connect_t handle, double * acceleration ) 638{ 639 kern_return_t kr; 640 unsigned int fixed; 641 IOByteCount rsize; 642 643 kr = IOHIDGetParameter( handle, CFSTR(kIOHIDPointerAccelerationKey), 644 sizeof( fixed), (unsigned char *) &fixed, &rsize ); 645 646 if( kr == kIOReturnSuccess) 647 *acceleration = ((double) fixed) / 65536.0; 648 649 return( kr ); 650} 651 652kern_return_t IOHIDSetMouseAcceleration( io_connect_t handle, double acceleration ) 653{ 654 unsigned int fixed; 655 656 fixed = (unsigned int) (acceleration * 65536.0); 657 658 return( IOHIDSetParameter(handle, CFSTR(kIOHIDPointerAccelerationKey), 659 (unsigned char *) &fixed, sizeof( fixed)) ); 660} 661 662kern_return_t IOHIDGetAccelerationWithKey( io_connect_t handle, CFStringRef key, double * acceleration ) 663{ 664 kern_return_t kr; 665 unsigned int fixed; 666 IOByteCount rsize; 667 668 kr = IOHIDGetParameter( handle, key, 669 sizeof( fixed), (unsigned char *) &fixed, &rsize ); 670 671 if( kr == kIOReturnSuccess) 672 *acceleration = ((double) fixed) / 65536.0; 673 674 return( kr ); 675} 676 677kern_return_t IOHIDSetAccelerationWithKey( io_connect_t handle, CFStringRef key, double acceleration ) 678{ 679 unsigned int fixed; 680 681 fixed = (unsigned int) (acceleration * 65536.0); 682 683 return( IOHIDSetParameter(handle, key, 684 (unsigned char *) &fixed, sizeof( fixed)) ); 685} 686