/* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #include #include #include #include #include #include // mig generated #include /* * Ports */ extern mach_port_t mach_task_self(); const mach_port_t kIOMasterPortDefault = MACH_PORT_NULL; static mach_port_t __IOGetDefaultMasterPort() { kern_return_t result; mach_port_t masterPort; result = IOMasterPort(MACH_PORT_NULL, &masterPort); if( KERN_SUCCESS != result) { masterPort = MACH_PORT_NULL; } return( masterPort ); } kern_return_t IOMasterPort( mach_port_t bootstrapPort, mach_port_t * masterPort ) { kern_return_t result = KERN_SUCCESS; mach_port_t host_port = 0; host_port = mach_host_self(); result = host_get_io_master(host_port, masterPort); /* Dispose of the host port to prevent security breaches and port * leaks. We don't care about the kern_return_t value of this * call for now as there's nothing we can do if it fails. */ if (host_port) mach_port_deallocate(mach_task_self(), host_port); return result; } kern_return_t IOCreateReceivePort( int msgType, mach_port_t * recvPort ) { kern_return_t res; switch (msgType) { case kOSNotificationMessageID: case kOSAsyncCompleteMessageID: res = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, recvPort); break; default: res = kIOReturnBadArgument; } return res; } /* * IOObject */ kern_return_t IOObjectRelease( io_object_t object ) { return( mach_port_deallocate( mach_task_self(), object )); } kern_return_t IOObjectRetain( io_object_t object ) { return( mach_port_mod_refs(mach_task_self(), object, MACH_PORT_RIGHT_SEND, 1 )); } kern_return_t IOObjectGetClass( io_object_t object, io_name_t className ) { return( io_object_get_class( object, className )); } CFStringRef IOObjectCopyClass(io_object_t object) { io_name_t my_name; CFStringRef my_str = NULL; // if there's no argument, no point going on. Return NULL. if (object == NULL) { return my_str; } io_object_get_class( object, &my_name ); my_str = CFStringCreateWithCString (kCFAllocatorDefault, my_name, kCFStringEncodingUTF8); return my_str; } CFStringRef IOObjectCopySuperclassForClass(CFStringRef classname) { io_name_t my_name, orig_name; CFStringRef my_str = NULL; char * my_cstr; kern_return_t kr; mach_port_t masterPort = __IOGetDefaultMasterPort(); // if there's no argument, no point going on. Return NULL. if (classname == NULL) { return my_str; } my_cstr = malloc(sizeof(char) * 128); CFStringGetCString (classname, my_cstr, 128, kCFStringEncodingUTF8); strncpy(orig_name, my_cstr, sizeof(io_name_t)); kr = io_object_get_superclass(masterPort, &orig_name, &my_name); if (kr == kIOReturnSuccess) { my_str = CFStringCreateWithCString (kCFAllocatorDefault, my_name, kCFStringEncodingUTF8); } free(my_cstr); return my_str; } CFStringRef IOObjectCopyBundleIdentifierForClass(CFStringRef classname) { io_name_t my_name, orig_name; CFStringRef my_str = NULL; char * my_cstr; kern_return_t kr; mach_port_t masterPort = __IOGetDefaultMasterPort(); // if there's no argument, no point going on. Return NULL. if (classname == NULL) { return my_str; } my_cstr = malloc(sizeof(char) * 128); CFStringGetCString (classname, my_cstr, 128, kCFStringEncodingUTF8); strncpy(orig_name, my_cstr, sizeof(io_name_t)); kr = io_object_get_bundle_identifier(masterPort, &orig_name, &my_name); if (kr == kIOReturnSuccess) { my_str = CFStringCreateWithCString (kCFAllocatorDefault, my_name, kCFStringEncodingUTF8); } free(my_cstr); return my_str; } boolean_t IOObjectConformsTo( io_object_t object, const io_name_t className ) { boolean_t conforms; if( kIOReturnSuccess != io_object_conforms_to( object, (char *) className, &conforms )) conforms = 0; return( conforms ); } boolean_t IOObjectIsEqualTo( io_object_t object, io_object_t anObject ) { return( object == anObject ); } int IOObjectGetRetainCount( io_object_t object ) { int count; if( kIOReturnSuccess != io_object_get_retain_count( object, &count)) count = 0; return( count ); } /* * IOIterator */ io_object_t IOIteratorNext( io_iterator_t iterator ) { io_object_t next; if( kIOReturnSuccess != io_iterator_next( iterator, &next)) next = 0; return( next ); } void IOIteratorReset( io_iterator_t iterator ) { io_iterator_reset( iterator ); } boolean_t IOIteratorIsValid( io_iterator_t iterator ) { boolean_t valid; if( kIOReturnSuccess != io_iterator_is_valid( iterator, &valid )) valid = FALSE; return( valid ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IOService */ io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching ) { io_iterator_t iter = NULL; io_service_t service = NULL; IOServiceGetMatchingServices( masterPort, matching, &iter ); if( iter) { service = IOIteratorNext( iter ); IOObjectRelease( iter ); } return( service ); } kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing ) { kern_return_t kr; CFDataRef data; CFIndex dataLen; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; if( !matching) return( kIOReturnBadArgument); data = IOCFSerialize( matching, kNilOptions ); CFRelease( matching ); if( !data) return( kIOReturnUnsupported ); dataLen = CFDataGetLength(data); if (dataLen < sizeof(io_string_t)) kr = io_service_get_matching_services( masterPort, (char *) CFDataGetBytePtr(data), existing ); else { kern_return_t result; kr = io_service_get_matching_services_ool( masterPort, (char *) CFDataGetBytePtr(data), dataLen, &result, existing ); if (KERN_SUCCESS == kr) kr = result; } CFRelease( data ); return( kr ); } kern_return_t IOServiceMatchPropertyTable( io_service_t service, CFDictionaryRef matching, boolean_t * matches ) { kern_return_t kr; CFDataRef data; CFIndex dataLen; if( !matching) return( kIOReturnBadArgument); data = IOCFSerialize( matching, kNilOptions ); if( !data) return( kIOReturnUnsupported ); dataLen = CFDataGetLength(data); if (dataLen < sizeof(io_string_t)) kr = io_service_match_property_table( service, (char *) CFDataGetBytePtr(data), matches ); else { kern_return_t result; kr = io_service_match_property_table_ool( service, (char *) CFDataGetBytePtr(data), dataLen, &result, matches ); if (KERN_SUCCESS == kr) kr = result; } CFRelease( data ); return( kr ); } kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, int reference, io_iterator_t * notification ) { kern_return_t kr; CFDataRef data; CFIndex dataLen; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; if( !matching) return( kIOReturnBadArgument); data = IOCFSerialize( matching, kNilOptions ); CFRelease( matching ); if( !data) return( kIOReturnUnsupported ); dataLen = CFDataGetLength(data); if (dataLen < sizeof(io_string_t)) kr = io_service_add_notification( masterPort, (char *) notificationType, (char *) CFDataGetBytePtr(data), wakePort, &reference, 1, notification ); else { kern_return_t result; kr = io_service_add_notification_ool( masterPort, (char *) notificationType, (char *) CFDataGetBytePtr(data), dataLen, wakePort, &reference, 1, &result, notification ); if (KERN_SUCCESS == kr) kr = result; } CFRelease( data ); return( kr ); } kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refcon, io_iterator_t * notification ) { kern_return_t kr; CFDataRef data; CFIndex dataLen; natural_t asyncRef[kIOMatchingCalloutCount]; if( !matching) return( kIOReturnBadArgument); data = IOCFSerialize( matching, kNilOptions ); CFRelease( matching ); if( !data) return( kIOReturnUnsupported ); asyncRef[kIOMatchingCalloutFuncIndex] = (natural_t) callback; asyncRef[kIOMatchingCalloutRefconIndex] = (natural_t) refcon; dataLen = CFDataGetLength(data); if (dataLen < sizeof(io_string_t)) kr = io_service_add_notification( notifyPort->masterPort, (char *) notificationType, (char *) CFDataGetBytePtr(data), notifyPort->wakePort, asyncRef, kIOMatchingCalloutCount, notification ); else { kern_return_t result; kr = io_service_add_notification_ool( notifyPort->masterPort, (char *) notificationType, (char *) CFDataGetBytePtr(data), dataLen, notifyPort->wakePort, asyncRef, kIOMatchingCalloutCount, &result, notification ); if (KERN_SUCCESS == kr) kr = result; } CFRelease( data ); return( kr ); } kern_return_t IOServiceAddInterestNotification( IONotificationPortRef notifyPort, io_service_t service, const io_name_t interestType, IOServiceInterestCallback callback, void * refcon, io_object_t * notification ) { natural_t asyncRef[kIOInterestCalloutCount]; kern_return_t kr; asyncRef[kIOInterestCalloutFuncIndex] = (natural_t) callback; asyncRef[kIOInterestCalloutRefconIndex] = (natural_t) refcon; asyncRef[kIOInterestCalloutServiceIndex] = (natural_t) service; kr = io_service_add_interest_notification( service, (char *) interestType, notifyPort->wakePort, asyncRef, kIOInterestCalloutCount, notification ); return( kr ); } IONotificationPortRef IONotificationPortCreate( mach_port_t masterPort ) { kern_return_t kr; IONotificationPort * notify; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; notify = calloc( 1, sizeof( IONotificationPort)); if( !notify) return( 0 ); notify->masterPort = masterPort; kr = IOCreateReceivePort(kOSNotificationMessageID, ¬ify->wakePort); if( kr != kIOReturnSuccess) { free( notify ); return( 0 ); } return notify; } void IONotificationPortDestroy( IONotificationPortRef notify ) { if( notify->source) CFRelease( notify->source); mach_port_destroy( mach_task_self(), notify->wakePort); free( notify ); } CFRunLoopSourceRef IONotificationPortGetRunLoopSource( IONotificationPortRef notify ) { CFMachPortRef cfPort; CFMachPortContext context; CFRunLoopSourceRef cfSource; Boolean shouldFreeInfo; if( notify->source) return( notify->source ); context.version = 1; context.info = (void *) notify; context.retain = NULL; context.release = NULL; context.copyDescription = NULL; cfPort = CFMachPortCreateWithPort(NULL, notify->wakePort, IODispatchCalloutFromCFMessage, &context, &shouldFreeInfo); if (!cfPort) return( 0 ); cfSource = CFMachPortCreateRunLoopSource(NULL, cfPort, 0); CFRelease(cfPort); notify->source = cfSource; return( cfSource ); } mach_port_t IONotificationPortGetMachPort( IONotificationPortRef notify ) { return( notify->wakePort ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Matching creation helpers */ CFMutableDictionaryRef IOMakeMatching( mach_port_t masterPort, unsigned int type, unsigned int options, void * args, unsigned int argsSize ) { IOReturn err; CFMutableDictionaryRef result = 0; char * matching; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; matching = (char *) malloc( sizeof( io_string_t)); if( matching) { err = io_make_matching( masterPort, type, options, (char *)args, argsSize, matching ); if( KERN_SUCCESS == err) { result = (CFMutableDictionaryRef) IOCFUnserialize( matching, kCFAllocatorDefault, kNilOptions, 0 ); } free( matching ); } return( result ); } static CFMutableDictionaryRef MakeOneStringProp( CFStringRef key, const char * name ) { CFMutableDictionaryRef dict; CFStringRef string; dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if( !dict) return( dict); string = CFStringCreateWithCString( kCFAllocatorDefault, name, kCFStringEncodingMacRoman ); if( string) { CFDictionarySetValue( dict, key, string ); CFRelease( string ); } else { CFRelease( dict ); dict = 0; } return( dict ); } CFMutableDictionaryRef IOServiceMatching( const char * name ) { return( MakeOneStringProp( CFSTR(kIOProviderClassKey), name ) ); } CFMutableDictionaryRef IOServiceNameMatching( const char * name ) { return( MakeOneStringProp( CFSTR(kIONameMatchKey), name )); } CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, unsigned int options, const char * name ) { if (name == NULL) { return 0; } else { return( IOMakeMatching( masterPort, kIOBSDNameMatching, options, (void *)name, strlen( name) + 1)); } } CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, unsigned int options, const char * path ) { return( IOMakeMatching( masterPort, kIOOFPathMatching, options, (void *)path, strlen( path) + 1)); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ kern_return_t OSGetNotificationFromMessage( mach_msg_header_t * msg, unsigned int index, unsigned long int * type, unsigned long int * reference, void ** content, vm_size_t * size ) { OSNotificationHeader * header; if( msg->msgh_id != kOSNotificationMessageID) return( kIOReturnBadMessageID ); if( msg->msgh_size < (sizeof( mach_msg_header_t) + sizeof( OSNotificationHeader))) return( kIOReturnNoResources ); if( index) return( kIOReturnNoResources ); header = (OSNotificationHeader *) (msg + 1); if( type) *type = header->type; if( reference) *reference = header->reference[0]; if( size) *size = header->size; if( content) { if( header->size) *content = &header->content[0]; else *content = 0; } return( kIOReturnSuccess ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #if __ppc__ static void swapOSNotification( OSNotificationHeader * header, unsigned int leftOver ) { // Do some conditional byte-swapping if we're running a ppc binary, // under Rosetta on x86 HW. // We expect this function to be called ONLY when running in Rosetta, not // when running on native ppc HW. header->size = OSSwapInt32(header->size); header->type = OSSwapInt32(header->type); int i; for (i = 0; i < sizeof(header->reference) / sizeof(header->reference[0]); i++) { header->reference[i] = OSSwapInt32(header->reference[i]); } switch (header->type) { case kIOServicePublishNotificationType: case kIOServiceMatchedNotificationType: case kIOServiceTerminatedNotificationType: // only need to swap the reference field break; case kIOAsyncCompletionNotificationType: { IOAsyncCompletionContent *asyncHdr = (IOAsyncCompletionContent *)(header + 1); leftOver = (leftOver - sizeof(*asyncHdr)) / sizeof(void *); asyncHdr->result = OSSwapInt32(asyncHdr->result); for (i = 0; i < leftOver; i++) { asyncHdr->args[i] = OSSwapInt32(asyncHdr->args[i]); } break; } case kIOServiceMessageNotificationType: { IOServiceInterestContent *interestHdr = (IOServiceInterestContent *)(header + 1); leftOver = (leftOver - sizeof(*interestHdr) + sizeof(interestHdr->messageArgument)) / sizeof(void *); interestHdr->messageType = OSSwapInt32(interestHdr->messageType); for (i = 0; i < leftOver; i++) { interestHdr->messageArgument[i] = OSSwapInt32(interestHdr->messageArgument[i]); } break; } default: printf("unknown OSNotificationHeader type %d\n", header->type); break; } } #endif void IODispatchCalloutFromMessage(void *cfPort, mach_msg_header_t *msg, void *info) { return( IODispatchCalloutFromCFMessage( cfPort, msg, -1, info )); } void IODispatchCalloutFromCFMessage(CFMachPortRef port, void *_msg, CFIndex size, void *info) { struct ComplexMsg { mach_msg_header_t msgHdr; mach_msg_body_t msgBody; mach_msg_port_descriptor_t ports[1]; } * complexMsg = NULL; mach_msg_header_t * msg = (mach_msg_header_t *)_msg; OSNotificationHeader * header; io_iterator_t notifier = MACH_PORT_NULL; io_service_t service = MACH_PORT_NULL; int leftOver; boolean_t deliver = TRUE; if( msg->msgh_id != kOSNotificationMessageID) return; if( MACH_MSGH_BITS_COMPLEX & msg->msgh_bits) { complexMsg = (struct ComplexMsg *)_msg; if( complexMsg->msgBody.msgh_descriptor_count) service = complexMsg->ports[0].name; header = (OSNotificationHeader *) &complexMsg->ports[complexMsg->msgBody.msgh_descriptor_count]; } else header = (OSNotificationHeader *) (msg + 1); leftOver = msg->msgh_size - (((vm_address_t) (header + 1)) - ((vm_address_t) msg)); #if __ppc__ // If this is ppc code running under Rosetta over an x86 kernel, // we may need to do some byte swapping. The magic cookie in the // inline asm makes Rosetta ignore this branch command. asm volatile ("b L_SkipSwap_label \n .long 0x14400004"); swapOSNotification(header, leftOver); asm volatile ("L_SkipSwap_label:"); #endif // remote port is the notification (an iterator_t) that fired notifier = msg->msgh_remote_port; if( MACH_PORT_NULL != notifier) { kern_return_t kr; mach_port_urefs_t urefs; kr = mach_port_get_refs( mach_task_self(), msg->msgh_remote_port, MACH_PORT_RIGHT_SEND, &urefs); if( (KERN_SUCCESS != kr) || (urefs < 2)) { // one ref carried by the message - < 2 means owner has released the notifier deliver = false; } } if(deliver) { switch( header->type ) { case kIOAsyncCompletionNotificationType: { IOAsyncCompletionContent *asyncHdr; asyncHdr = (IOAsyncCompletionContent *)(header + 1); leftOver = (leftOver - sizeof(*asyncHdr)) / sizeof(void *); switch (leftOver) { case 0: ((IOAsyncCallback0 )header->reference[kIOAsyncCalloutFuncIndex])( (void *) header->reference[kIOAsyncCalloutRefconIndex], asyncHdr->result); break; case 1: ((IOAsyncCallback1 )header->reference[kIOAsyncCalloutFuncIndex])( (void *) header->reference[kIOAsyncCalloutRefconIndex], asyncHdr->result, asyncHdr->args[0]); break; case 2: ((IOAsyncCallback2 )header->reference[kIOAsyncCalloutFuncIndex])( (void *) header->reference[kIOAsyncCalloutRefconIndex], asyncHdr->result, asyncHdr->args[0], asyncHdr->args[1]); break; default: ((IOAsyncCallback )header->reference[kIOAsyncCalloutFuncIndex])( (void *) header->reference[kIOAsyncCalloutRefconIndex], asyncHdr->result, asyncHdr->args, leftOver); break; } break; } case kIOServiceMessageNotificationType: { IOServiceInterestContent * interestHdr; void * arg; interestHdr = (IOServiceInterestContent *)(header + 1); leftOver = (leftOver - sizeof(*interestHdr) + sizeof(interestHdr->messageArgument)) / sizeof(void *); if (leftOver <= 1) arg = interestHdr->messageArgument[0]; else arg = &interestHdr->messageArgument[0]; ((IOServiceInterestCallback)header->reference[kIOInterestCalloutFuncIndex])( (void *) header->reference[kIOInterestCalloutRefconIndex], service ? service : (io_service_t) header->reference[kIOInterestCalloutServiceIndex], interestHdr->messageType, arg ); break; } case kIOServicePublishNotificationType: case kIOServiceMatchedNotificationType: case kIOServiceTerminatedNotificationType: ((IOServiceMatchingCallback)header->reference[kIOMatchingCalloutFuncIndex])( (void *) header->reference[kIOMatchingCalloutRefconIndex], notifier); break; } } if( MACH_PORT_NULL != notifier) mach_port_deallocate( mach_task_self(), notifier ); if( complexMsg) { unsigned int i; for( i = 0; i < complexMsg->msgBody.msgh_descriptor_count; i++) mach_port_deallocate( mach_task_self(), complexMsg->ports[i].name ); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ kern_return_t IOServiceGetBusyState( io_service_t service, int * busyState ) { kern_return_t kr; kr = io_service_get_busy_state( service, busyState ); if( kr != KERN_SUCCESS) *busyState = 0; return( kr ); } kern_return_t IOServiceGetState( io_service_t service, uint64_t * state ) { kern_return_t kr; kr = io_service_get_state( service, state ); if( kr != KERN_SUCCESS) *state = 0; return( kr ); } kern_return_t IOKitGetBusyState( mach_port_t masterPort, int * busyState ) { io_service_t root; kern_return_t kr; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; kr = io_registry_entry_from_path( masterPort, kIOServicePlane ":/", &root ); if( kr == KERN_SUCCESS) { kr = io_service_get_busy_state( root, busyState ); IOObjectRelease( root ); } else *busyState = 0; return( kr ); } kern_return_t IOServiceWaitQuiet( io_service_t service, mach_timespec_t * waitTime ) { kern_return_t kr; mach_timespec_t defaultWait = { 0, -1 }; if( 0 == waitTime) waitTime = &defaultWait; kr = io_service_wait_quiet( service, *waitTime ); return( kr ); } kern_return_t IOKitWaitQuiet( mach_port_t masterPort, mach_timespec_t * waitTime ) { io_service_t root; kern_return_t kr; mach_timespec_t defaultWait = { 0, -1 }; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; kr = io_registry_entry_from_path( masterPort, kIOServicePlane ":/", &root ); if( kr == KERN_SUCCESS) { if( 0 == waitTime) waitTime = &defaultWait; kr = io_service_wait_quiet( root, *waitTime ); IOObjectRelease( root ); } return( kr ); } kern_return_t IOServiceOpen( io_service_t service, task_port_t owningTask, unsigned int type, io_connect_t * connect ) { return( io_service_open( service, owningTask, type, connect )); } kern_return_t IOServiceClose( io_connect_t connect ) { kern_return_t kr; kr = io_service_close( connect); IOObjectRelease( connect ); return( kr ); } kern_return_t IOServiceRequestProbe( io_service_t service, unsigned int options ) { return( io_service_request_probe( service, options )); } /* * IOService connection */ kern_return_t IOConnectAddRef( io_connect_t connect ) { return mach_port_mod_refs(mach_task_self(), connect, MACH_PORT_RIGHT_SEND, 1); } kern_return_t IOConnectRelease( io_connect_t connect ) { // @@@ gvdl: Check with Simon about last reference removal return mach_port_mod_refs(mach_task_self(), connect, MACH_PORT_RIGHT_SEND, -1); } kern_return_t IOConnectGetService( io_connect_t connect, io_service_t * service ) { return( io_connect_get_service( connect, service )); } kern_return_t IOConnectSetNotificationPort( io_connect_t connect, unsigned int type, mach_port_t port, unsigned int reference ) { return( io_connect_set_notification_port( connect, type, port, reference)); } kern_return_t IOConnectMapMemory( io_connect_t connect, unsigned int memoryType, task_port_t intoTask, vm_address_t * atAddress, vm_size_t * ofSize, IOOptionBits options ) { return( io_connect_map_memory( connect, memoryType, intoTask, atAddress, ofSize, options)); } kern_return_t IOConnectUnmapMemory( io_connect_t connect, unsigned int memoryType, task_port_t intoTask, vm_address_t atAddress ) { return( io_connect_unmap_memory( connect, memoryType, intoTask, atAddress)); } kern_return_t IOConnectAddClient( io_connect_t connect, io_connect_t client ) { return( io_connect_add_client( connect, client)); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ kern_return_t IOConnectMethodScalarIScalarO( io_connect_t connect, unsigned int index, IOItemCount scalarInputCount, IOItemCount scalarOutputCount, ... ) { int params[8]; int * input; int ** output; kern_return_t err; int i; input = (int *) __builtin_next_arg( scalarOutputCount ); output = (int **)(input + scalarInputCount); err = io_connect_method_scalarI_scalarO( connect, index, input, scalarInputCount, params, (unsigned int *) &scalarOutputCount); if( kIOReturnSuccess == err) { for( i = 0; i < scalarOutputCount; i++) *output[i] = params[i]; } return( err ); } kern_return_t IOConnectMethodScalarIStructureO( io_connect_t connect, unsigned int index, IOItemCount scalarInputCount, IOByteCount * structureSize, ... ) { int * input; char * structure; kern_return_t err; input = (int *) __builtin_next_arg( structureSize ); structure = (char *) input[scalarInputCount]; err = io_connect_method_scalarI_structureO( connect, index, input, scalarInputCount, structure, (unsigned int *) structureSize); return( err ); } kern_return_t IOConnectMethodScalarIStructureI( io_connect_t connect, unsigned int index, IOItemCount scalarInputCount, IOByteCount structureSize, ... ) { int * input; char * structure; kern_return_t err; input = (int *) __builtin_next_arg( structureSize ); structure = (char *) input[scalarInputCount]; err = io_connect_method_scalarI_structureI( connect, index, input, scalarInputCount, structure, structureSize ); return( err ); } kern_return_t IOConnectMethodStructureIStructureO( io_connect_t connect, unsigned int index, IOItemCount structureInputSize, IOByteCount * structureOutputSize, void * inputStructure, void * ouputStructure ) { return( io_connect_method_structureI_structureO( connect, index, inputStructure, structureInputSize, ouputStructure, (unsigned int *) structureOutputSize )); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ kern_return_t IOConnectTrap0( io_connect_t connect, unsigned int index ) { return iokit_user_client_trap(connect, index, NULL, NULL, NULL, NULL, NULL, NULL); } kern_return_t IOConnectTrap1( io_connect_t connect, unsigned int index, void *p1 ) { return iokit_user_client_trap(connect, index, p1, NULL, NULL, NULL, NULL, NULL); } kern_return_t IOConnectTrap2( io_connect_t connect, unsigned int index, void *p1, void *p2 ) { return iokit_user_client_trap(connect, index, p1, p2, NULL, NULL, NULL, NULL); } kern_return_t IOConnectTrap3( io_connect_t connect, unsigned int index, void *p1, void *p2, void *p3 ) { return iokit_user_client_trap(connect, index, p1, p2, p3, NULL, NULL, NULL); } kern_return_t IOConnectTrap4( io_connect_t connect, unsigned int index, void *p1, void *p2, void *p3, void *p4 ) { return iokit_user_client_trap(connect, index, p1, p2, p3, p4, NULL, NULL); } kern_return_t IOConnectTrap5( io_connect_t connect, unsigned int index, void *p1, void *p2, void *p3, void *p4, void *p5 ) { return iokit_user_client_trap(connect, index, p1, p2, p3, p4, p5, NULL); } kern_return_t IOConnectTrap6( io_connect_t connect, unsigned int index, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6 ) { return iokit_user_client_trap(connect, index, p1, p2, p3, p4, p5, p6); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ kern_return_t IOConnectSetCFProperties( io_connect_t connect, CFTypeRef properties ) { CFDataRef data; kern_return_t kr; kern_return_t result; data = IOCFSerialize( properties, kNilOptions ); if( !data) return( kIOReturnUnsupported ); kr = io_connect_set_properties( connect, (UInt8 *) CFDataGetBytePtr(data), CFDataGetLength(data), &result ); CFRelease(data); if( KERN_SUCCESS == kr) kr = result; return( kr ); } kern_return_t IOConnectSetCFProperty( io_connect_t connect, CFStringRef propertyName, CFTypeRef property ) { CFDictionaryRef dict; kern_return_t kr; dict = CFDictionaryCreate( kCFAllocatorDefault, (const void **) &propertyName, (const void **) &property, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); if( !dict) return( kIOReturnNoMemory ); kr = IOConnectSetCFProperties( connect, dict ); CFRelease( dict ); return( kr ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IORegistry accessors */ kern_return_t IORegistryCreateIterator( mach_port_t masterPort, const io_name_t plane, IOOptionBits options, io_iterator_t * iterator ) { masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; return( io_registry_create_iterator( masterPort, (char *) plane, options, iterator)); } kern_return_t IORegistryEntryCreateIterator( io_registry_entry_t entry, const io_name_t plane, IOOptionBits options, io_iterator_t * iterator ) { return( io_registry_entry_create_iterator( entry, (char *) plane, options, iterator)); } kern_return_t IORegistryIteratorEnterEntry( io_iterator_t iterator ) { return( io_registry_iterator_enter_entry( iterator)); } kern_return_t IORegistryIteratorExitEntry( io_iterator_t iterator ) { return( io_registry_iterator_exit_entry( iterator)); } io_registry_entry_t IORegistryEntryFromPath( mach_port_t masterPort, const io_string_t path ) { kern_return_t kr; io_registry_entry_t entry; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; kr = io_registry_entry_from_path( masterPort, (char *) path, &entry ); if( kIOReturnSuccess != kr) entry = 0; return( entry ); } io_registry_entry_t IORegistryGetRootEntry( mach_port_t masterPort ) { kern_return_t kr; io_registry_entry_t entry; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; kr = io_registry_get_root_entry( masterPort, &entry ); if( kIOReturnSuccess != kr) entry = 0; return( entry ); } kern_return_t IORegistryEntryGetPath( io_registry_entry_t entry, const io_name_t plane, io_string_t path ) { return( io_registry_entry_get_path( entry, (char *) plane, path )); } boolean_t IORegistryEntryInPlane( io_registry_entry_t entry, const io_name_t plane ) { boolean_t inPlane; if( kIOReturnSuccess != io_registry_entry_in_plane( entry, (char *) plane, &inPlane )) inPlane = false; return( inPlane ); } kern_return_t IORegistryEntryGetName( io_registry_entry_t entry, io_name_t name ) { return( io_registry_entry_get_name( entry, name )); } kern_return_t IORegistryEntryGetNameInPlane( io_registry_entry_t entry, const io_name_t plane, io_name_t name ) { if( NULL == plane) plane = ""; return( io_registry_entry_get_name_in_plane( entry, (char *) plane, name )); } kern_return_t IORegistryEntryGetLocationInPlane( io_registry_entry_t entry, const io_name_t plane, io_name_t location ) { if( NULL == plane) plane = ""; return( io_registry_entry_get_location_in_plane( entry, (char *) plane, location )); } kern_return_t IORegistryEntryCreateCFProperties( io_registry_entry_t entry, CFMutableDictionaryRef * properties, CFAllocatorRef allocator, IOOptionBits options ) { kern_return_t kr; unsigned int size; char * propertiesBuffer; CFStringRef errorString; const char * cstr; kr = io_registry_entry_get_properties(entry, &propertiesBuffer, &size); if (kr != kIOReturnSuccess) return kr; *properties = (CFMutableDictionaryRef) IOCFUnserialize(propertiesBuffer, allocator, 0, &errorString); if (!(*properties) && errorString) { if ((cstr = CFStringGetCStringPtr(errorString, kCFStringEncodingMacRoman))) printf("%s\n", cstr); CFRelease(errorString); } // free propertiesBuffer ! vm_deallocate(mach_task_self(), (vm_address_t)propertiesBuffer, size); return( *properties ? kIOReturnSuccess : kIOReturnInternalError ); } CFTypeRef IORegistryEntryCreateCFProperty( io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options ) { IOReturn kr; CFTypeRef type; unsigned int size; char * propertiesBuffer; CFStringRef errorString; const char * cStr; char * buffer = NULL; cStr = CFStringGetCStringPtr( key, kCFStringEncodingMacRoman); if( !cStr) { CFIndex bufferSize = CFStringGetLength(key) + 1; buffer = malloc( bufferSize); if( buffer && CFStringGetCString( key, buffer, bufferSize, kCFStringEncodingMacRoman)) cStr = buffer; } if( cStr) kr = io_registry_entry_get_property(entry, (char *) cStr, &propertiesBuffer, &size); else kr = kIOReturnError; if( buffer) free( buffer); if( kr != kIOReturnSuccess) return( NULL ); type = (CFMutableDictionaryRef) IOCFUnserialize(propertiesBuffer, allocator, 0, &errorString); if (!type && errorString) { if ((cStr = CFStringGetCStringPtr(errorString, kCFStringEncodingMacRoman))) printf("%s\n", cStr); CFRelease(errorString); } // free propertiesBuffer ! vm_deallocate(mach_task_self(), (vm_address_t)propertiesBuffer, size); return( type ); } CFTypeRef IORegistryEntrySearchCFProperty( io_registry_entry_t entry, const io_name_t plane, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options ) { IOReturn kr; CFTypeRef type; unsigned int size; char * propertiesBuffer; CFStringRef errorString; const char * cStr; char * buffer = NULL; cStr = CFStringGetCStringPtr( key, kCFStringEncodingMacRoman); if( !cStr) { CFIndex bufferSize = CFStringGetLength(key) + 1; buffer = malloc( bufferSize); if( buffer && CFStringGetCString( key, buffer, bufferSize, kCFStringEncodingMacRoman)) cStr = buffer; } if( cStr) kr = io_registry_entry_get_property_recursively(entry, (char *) plane, (char *) cStr, options, &propertiesBuffer, &size); else kr = kIOReturnError; if( buffer) free( buffer); if( kr != kIOReturnSuccess) return( NULL ); type = (CFMutableDictionaryRef) IOCFUnserialize(propertiesBuffer, allocator, 0, &errorString); if (!type && errorString) { if ((cStr = CFStringGetCStringPtr(errorString, kCFStringEncodingMacRoman))) printf("%s\n", cStr); CFRelease(errorString); } // free propertiesBuffer ! vm_deallocate(mach_task_self(), (vm_address_t)propertiesBuffer, size); return( type ); } kern_return_t IORegistryEntryGetProperty( io_registry_entry_t entry, const io_name_t name, io_struct_inband_t buffer, unsigned int * size ) { return( io_registry_entry_get_property_bytes( entry, (char *) name, buffer, size )); } kern_return_t IORegistryEntrySetCFProperties( io_registry_entry_t entry, CFTypeRef properties ) { CFDataRef data; kern_return_t kr; kern_return_t result; data = IOCFSerialize( properties, kNilOptions ); if( !data) return( kIOReturnUnsupported ); kr = io_registry_entry_set_properties( entry, (UInt8 *) CFDataGetBytePtr(data), CFDataGetLength(data), &result ); CFRelease(data); if( KERN_SUCCESS == kr) kr = result; return( kr ); } kern_return_t IORegistryEntrySetCFProperty( io_registry_entry_t entry, CFStringRef propertyName, CFTypeRef property ) { CFDictionaryRef dict; kern_return_t kr; dict = CFDictionaryCreate( kCFAllocatorDefault, (const void **) &propertyName, (const void **) &property, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); if( !dict) return( kIOReturnNoMemory ); kr = IORegistryEntrySetCFProperties( entry, dict ); CFRelease( dict ); return( kr ); } kern_return_t IORegistryEntryGetChildIterator( io_registry_entry_t entry, const io_name_t plane, io_iterator_t * iterator ) { return( io_registry_entry_get_child_iterator( entry, (char *) plane, iterator)); } kern_return_t IORegistryEntryGetParentIterator( io_registry_entry_t entry, const io_name_t plane, io_iterator_t * iterator ) { return( io_registry_entry_get_parent_iterator( entry, (char *) plane, iterator)); } kern_return_t IORegistryEntryGetChildEntry( io_registry_entry_t entry, const io_name_t plane, io_registry_entry_t * child ) { kern_return_t kr; io_iterator_t iter; kr = IORegistryEntryGetChildIterator( entry, plane, &iter ); if( KERN_SUCCESS == kr) { *child = IOIteratorNext( iter ); IOObjectRelease( iter ); if( MACH_PORT_NULL == *child) kr = kIOReturnNoDevice; } return( kr ); } kern_return_t IORegistryEntryGetParentEntry( io_registry_entry_t entry, const io_name_t plane, io_registry_entry_t * parent ) { kern_return_t kr; io_iterator_t iter; kr = IORegistryEntryGetParentIterator( entry, plane, &iter ); if( KERN_SUCCESS == kr) { *parent = IOIteratorNext( iter ); IOObjectRelease( iter ); if( MACH_PORT_NULL == *parent) kr = kIOReturnNoDevice; } return( kr ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ kern_return_t IOServiceOFPathToBSDName(mach_port_t masterPort, const io_name_t openFirmwarePath, io_name_t bsdName) { kern_return_t kr; io_registry_entry_t service; io_iterator_t services; // Initialize return values. bsdName[0] = 0; // Find objects matching the given open firmware name. kr = IOServiceGetMatchingServices( /* mach_port_t */ masterPort, /* void * */ IOOpenFirmwarePathMatching( /* mach_port_t */ masterPort, /* unsigned int */ 0, /* const char * */ openFirmwarePath ), /* io_iterator * */ &services ); if( KERN_SUCCESS != kr ) return( kr ); // Obtain the first (and presumably the only) match. service = IOIteratorNext( services ); if( service ) { // Obtain the BSD name property from this object. unsigned int bsdNameSize = sizeof(io_name_t); kr = IORegistryEntryGetProperty( /* mach_port_t */ service, /* io_name_t */ kIOBSDNameKey, /* io_struct_inband_t */ bsdName, /* unsigned int * */ &bsdNameSize); if( KERN_SUCCESS != kr ) bsdName[0] = 0; IOObjectRelease( service ); } else { kr = KERN_FAILURE; } IOObjectRelease( services ); return kr; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ kern_return_t IOCatalogueSendData( mach_port_t masterPort, int flag, const char *buffer, int size ) { kern_return_t kr; kern_return_t result; masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; kr = io_catalog_send_data( masterPort, flag, (char *) buffer, size, &result ); if( KERN_SUCCESS == kr) kr = result; return( kr ); } kern_return_t IOCatalogueTerminate( mach_port_t masterPort, int flag, io_name_t description ) { masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; return( io_catalog_terminate( masterPort, flag, description )); } kern_return_t IOCatalogueGetData( mach_port_t masterPort, int flag, char **buffer, int *size ) { masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; return ( io_catalog_get_data( masterPort, flag, (char **)buffer, (unsigned *)size ) ); } kern_return_t IOCatlogueGetGenCount( mach_port_t masterPort, int *genCount ) { masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; return ( io_catalog_get_gen_count( masterPort, genCount ) ); } kern_return_t IOCatalogueModuleLoaded( mach_port_t masterPort, io_name_t name ) { masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; return ( io_catalog_module_loaded( masterPort, name ) ); } kern_return_t IOCatalogueReset( mach_port_t masterPort, int flag ) { masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; return ( io_catalog_reset(masterPort, flag) ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // obsolete API kern_return_t IORegistryCreateEnumerator( mach_port_t masterPort, mach_port_t * enumerator ) { masterPort = (NULL == masterPort) ? __IOGetDefaultMasterPort() : masterPort; return( io_registry_create_iterator( masterPort, "IOService", true, enumerator)); } kern_return_t IORegistryEnumeratorReset( mach_port_t enumerator ) { return( io_iterator_reset( enumerator)); } static io_object_t lastRegIter; kern_return_t IORegistryEnumeratorNextConforming( mach_port_t enumerator, const char * name, boolean_t recursive ) { io_object_t next = 0; while( (next = IOIteratorNext( enumerator ))) { if( IOObjectConformsTo( next, (char *) name )) break; IOObjectRelease( next ); } lastRegIter = next; return( next ? kIOReturnSuccess : kIOReturnNoDevice ); } #if 0 kern_return_t IORegistryGetProperties( mach_port_t enumerator , void ** properties ) { return( IORegistryEntryGetProperties( lastRegIter, (struct IOObject **)properties)); } #endif kern_return_t IOOpenConnection( mach_port_t enumerator, task_port_t owningTask, unsigned int type, mach_port_t * connect ) { kern_return_t kr; kr = io_service_open( lastRegIter, owningTask, type, connect ); IOObjectRelease( lastRegIter ); return( kr ); } kern_return_t IOCloseConnection( mach_port_t connect ) { return( io_service_close( connect)); } kern_return_t IOSetNotificationPort( mach_port_t connect, unsigned int type, mach_port_t port ) { return( io_connect_set_notification_port( connect, type, port, 0)); } kern_return_t IORegisterClient( mach_port_t connect, mach_port_t client ) { return( io_connect_add_client( connect, client)); } kern_return_t IORegistryDisposeEnumerator( io_enumerator_t enumerator ) { return( IOObjectRelease( enumerator )); } kern_return_t IOMapMemory( io_connect_t connect, unsigned int memoryType, task_port_t intoTask, vm_address_t * atAddress, vm_size_t * ofSize, unsigned int flags ) { return( io_connect_map_memory( connect, memoryType, intoTask, atAddress, ofSize, flags)); } /* -------------------------- */ kern_return_t IOCompatibiltyNumber( mach_port_t connect, unsigned int * objectNumber ) { *objectNumber = 1; return( kIOReturnSuccess); } void IOInitContainerClasses() { } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */