1/*
2cc AppleSamplePCIClient.c -o /tmp/sampleclient -framework IOKit -framework CoreFoundation -Wno-four-char-constants -Wall -g -arch ppc -arch i386 -arch ppc64 -arch x86_64
3*/
4
5#include <assert.h>
6#include <stdlib.h>
7#include <string.h>
8#include <stdio.h>
9#include <unistd.h>
10#include <pthread.h>
11#include <inttypes.h>
12#include <IOKit/IOKitLib.h>
13
14#include "AppleSamplePCIShared.h"
15
16void Test( mach_port_t masterPort, io_service_t service );
17void TestSharedMemory( io_connect_t connect );
18
19
20int main( int argc, char * argv[] )
21{
22    mach_port_t                 masterPort;
23    io_iterator_t               iter;
24    io_service_t                service;
25    kern_return_t               kr;
26    CFMutableDictionaryRef      properties;
27    CFStringRef                 cfStr;
28
29    kr = IOMasterPort( MACH_PORT_NULL, &masterPort);
30    assert( KERN_SUCCESS == kr );
31
32    // Look up the object we wish to open. This example uses simple class
33    // matching (IOServiceMatching()) to look up the object that is the
34    // AppleSamplePCI driver class instantiated by the kext.
35
36    kr = IOServiceGetMatchingServices( masterPort,
37                        IOServiceMatching( kAppleSamplePCIClassName ), &iter);
38    assert( KERN_SUCCESS == kr );
39
40    for( ;
41      (service = IOIteratorNext(iter));
42      IOObjectRelease(service)) {
43
44        io_string_t path;
45        kr = IORegistryEntryGetPath(service, kIOServicePlane, path);
46        assert( KERN_SUCCESS == kr );
47        printf("Found a device of class "kAppleSamplePCIClassName": %s\n", path);
48
49        // print the value of kIONameMatchedKey property, as an example of
50        // getting properties from the registry. Property based access
51        // doesn't require a user client connection.
52
53        // grab a copy of the properties
54        kr = IORegistryEntryCreateCFProperties( service, &properties,
55                    kCFAllocatorDefault, kNilOptions );
56        assert( KERN_SUCCESS == kr );
57
58        cfStr = CFDictionaryGetValue( properties, CFSTR(kIONameMatchedKey) );
59        if( cfStr) {
60            const char * c = NULL;
61            char * buffer = NULL;
62            c = CFStringGetCStringPtr(cfStr, kCFStringEncodingMacRoman);
63            if(!c) {
64                CFIndex bufferSize = CFStringGetLength(cfStr) + 1;
65                buffer = malloc(bufferSize);
66                if(buffer) {
67                    if(CFStringGetCString(cfStr, buffer, bufferSize, kCFStringEncodingMacRoman))
68                        c = buffer;
69                }
70            }
71            if(c)
72                printf("it matched on name \"%s\"\n", c);
73            if(buffer)
74                free(buffer);
75        }
76        CFRelease( properties );
77
78        // test out the user client
79        Test( masterPort, service );
80    }
81    IOObjectRelease(iter);
82
83    exit(0);
84    return(0);
85}
86
87#define arrayCnt(var) (sizeof(var) / sizeof(var[0]))
88
89void Test( mach_port_t masterPort, io_service_t service )
90{
91    kern_return_t               kr;
92    io_connect_t                connect;
93    size_t                      structureOutputSize;
94    AppleSampleStructForMethod2  method2Param;
95    AppleSampleResultsForMethod2 method2Results;
96    uint32_t                    varStructParam[3] = { 1, 2, 3 };
97    IOByteCount                 bigBufferLen;
98    uint32_t *                  bigBuffer;
99
100    kr = IOServiceOpen( service, mach_task_self(), kAppleSamplePCIConnectType, &connect );
101    assert( KERN_SUCCESS == kr );
102
103    // test a simple struct in/out method
104    structureOutputSize = sizeof(varStructParam);
105
106
107#if MAC_OS_X_VERSION_10_5
108    kr = IOConnectCallStructMethod( connect, kAppleSampleMethod1,
109                            // inputStructure
110                            &varStructParam, sizeof(varStructParam),
111                            // ouputStructure
112                            &varStructParam, &structureOutputSize );
113#else
114    kr = IOConnectMethodStructureIStructureO( connect, kAppleSampleMethod1,
115                                                sizeof(varStructParam), /* structureInputSize */
116                                                &structureOutputSize,   /* structureOutputSize */
117                                                &varStructParam,        /* inputStructure */
118                                                &varStructParam);       /* ouputStructure */
119#endif
120
121    assert( KERN_SUCCESS == kr );
122    printf("kAppleSampleMethod1 results 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "\n",
123            varStructParam[0], varStructParam[1], varStructParam[2]);
124
125    // test shared memory
126    TestSharedMemory( connect );
127
128    // test method with out of line memory
129    bigBufferLen = 0x4321;
130    bigBuffer = malloc( bigBufferLen );
131
132    strcpy( (char *) (bigBuffer + (32 / 4)), "some out of line data");
133
134    method2Param.parameter1   = 0x12345678;
135    method2Param.data_pointer = (uintptr_t) bigBuffer;
136    method2Param.data_length  = bigBufferLen;
137
138    structureOutputSize = sizeof(method2Results);
139#if MAC_OS_X_VERSION_10_5
140    kr = IOConnectCallStructMethod( connect, kAppleSampleMethod2,
141                            // inputStructure
142                            &method2Param, sizeof(method2Param),
143                            // ouputStructure
144                            &method2Results, &structureOutputSize );
145#else
146    kr = IOConnectMethodStructureIStructureO( connect, kAppleSampleMethod2,
147                                                sizeof(method2Param),   /* structureInputSize */
148                                                &structureOutputSize,   /* structureOutputSize */
149                                                &method2Param,          /* inputStructure */
150                                                &method2Results);       /* ouputStructure */
151#endif
152
153    assert( KERN_SUCCESS == kr );
154    printf("kAppleSampleMethod2 result 0x%" PRIx64 "\n", method2Results.results1);
155
156    free( bigBuffer );
157
158}
159
160void TestSharedMemory( io_connect_t connect )
161{
162    kern_return_t               kr;
163    AppleSampleSharedMemory *   shared;
164
165#if __LP64__
166    mach_vm_address_t           addr;
167    mach_vm_size_t              size;
168#else
169    vm_address_t                addr;
170    vm_size_t           size;
171#endif
172
173    kr = IOConnectMapMemory( connect, kAppleSamplePCIMemoryType1,
174                            mach_task_self(), &addr, &size,
175                            kIOMapAnywhere | kIOMapDefaultCache );
176    assert( KERN_SUCCESS == kr );
177    assert( size == sizeof( AppleSampleSharedMemory ));
178
179    shared = (AppleSampleSharedMemory *) addr;
180
181    printf("From AppleSampleSharedMemory: %08" PRIx32 ", %08" PRIx32 ", %08" PRIx32 ", \"%s\"\n",
182            shared->field1, shared->field2, shared->field3, shared->string);
183
184    strcpy( shared->string, "some other data" );
185}
186
187
188
189