1/* 2 * 3 * Created by jguyton on Sun Apr 01 2001. 4 * Copyright (c) 2001 __CompanyName__. All rights reserved. 5 * 6 */ 7 8#include "IrDAUser.h" 9#include "AppleIrDA.h" 10#include "IrDAComm.h" 11#include "IrDALog.h" 12#include "IrDADebugging.h" 13 14#define super IOUserClient 15#undef ELG 16#define ELG(x,y,z,msg) ((void)0) 17 18OSDefineMetaClassAndStructors(IrDAUserClient, IOUserClient) 19 20/*static*/ 21IrDAUserClient* 22IrDAUserClient::withTask(task_t owningTask) 23{ 24 IrDAUserClient *client; 25 ELG(0, owningTask, 'irda', "IrDAUser: withTask"); 26 27 client = new IrDAUserClient; 28 29 if (client != NULL) { 30 if (client->init() == false) { 31 client->release(); 32 client = NULL; 33 } 34 } 35 if (client != NULL) { 36 client->fTask = owningTask; 37 } 38 return (client); 39} 40 41bool 42IrDAUserClient::start(IOService *provider) 43{ 44 bool result = false; 45 ELG(0, 0, 'irda', "IrDAUser: start"); 46 47 fDriver = OSDynamicCast(AppleIrDASerial, provider); 48 49 if (fDriver != NULL) 50 result = super::start(provider); 51 else 52 result = false; 53 54 if (result == false) { 55 IOLog("IrDAUserClient: provider start failed\n"); 56 } 57 else { 58 // Initialize the call structure. The method with index 59 // kSerialDoOneTrial calls the doOneTrial method 60 // with two parameters, a scalar and a buffer pointer 61 // that doOneTrial will write to. A pointer to this 62 // method structure is returned to the kernel when the 63 // user executes io_connect_method_scalarI_structureO. 64 // Thie kernel uses it to dispatch the command to the 65 // driver (running in kernel space) 66 67 fMethods[0].object = this; 68 fMethods[0].func = (IOMethod) &IrDAUserClient::userPostCommand; 69 fMethods[0].count0 = 0xFFFFFFFF; /* One input as big as I need */ 70 fMethods[0].count1 = 0xFFFFFFFF; /* One output as big as I need */ 71 fMethods[0].flags = kIOUCStructIStructO; 72 } 73 return (result); 74} 75IOReturn 76IrDAUserClient::clientClose(void) 77{ 78 ELG(0, 0, 'irda', "IrDAUser: client close"); 79 detach(fDriver); 80 return (kIOReturnSuccess); 81} 82 83IOReturn 84IrDAUserClient::clientDied(void) 85{ 86 ELG(0, 0, 'irda', "IrDAUser: client died"); 87 return (clientClose()); 88} 89 90IOReturn 91IrDAUserClient::connectClient(IOUserClient *client) 92{ 93 ELG(0, 0, 'irda', "IrDAUser: connect client"); 94 return (kIOReturnSuccess); 95} 96 97IOReturn 98IrDAUserClient::registerNotificationPort(mach_port_t port, UInt32 type) 99{ 100 ELG(0, 0, 'irda', "IrDAUser: register notification ignored"); 101 return (kIOReturnUnsupported); 102} 103 104IOExternalMethod * 105IrDAUserClient::getExternalMethodForIndex(UInt32 index) 106{ 107 IOExternalMethod *result = NULL; 108 ELG(0, index, 'irda', "IrDAUser: get external method"); 109 110 if (index == 0) { 111 result = &fMethods[0]; 112 } 113 return (result); 114} 115 116IOReturn 117IrDAUserClient::userPostCommand(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize) 118{ 119 // check first byte of input data for a command code 120 if (pIn && pOut && inputSize > 0) { 121 unsigned char *input = (unsigned char *)pIn; 122 switch(*input) { 123 case kIrDAUserCmd_GetLog: 124 return getIrDALog(pIn, pOut, inputSize, outPutSize); 125 126 case kIrDAUserCmd_GetStatus: 127 return getIrDAStatus(pIn, pOut, inputSize, outPutSize); 128 129 case kIrDAUserCmd_Enable: 130 return setIrDAState(true); 131 132 case kIrDAUserCmd_Disable: 133 return setIrDAState(false); 134 135 default: 136 IOLog("IrDA: Bad command to userPostCommand, %d\n", *input); 137 } 138 } 139 else IOLog("IrDA: pin/pout,size error\n"); 140 141 return kIOReturnBadArgument; 142} 143 144// get irda log 145// 146// input is 9 bytes: 147// command code (kIrDAUserCmd_GetLog) 148// four bytes of buffer address 149// four bytes of buffer size 150// 151// output set to IrDALogInfo record 152// and buffer filled with log data 153 154IOReturn 155IrDAUserClient::getIrDALog(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize) 156{ 157#if (hasTracing > 0) 158 159 IOMemoryDescriptor *md; // make a memory descriptor for the client's big buffer 160 unsigned char *input = (unsigned char *)pIn; 161 mach_vm_address_t bigaddr; 162 IOByteCount biglen; 163 IrDALogInfo *info; 164 165 require(inputSize == 9, Fail); 166 require(outPutSize, Fail); 167 require(*outPutSize == sizeof(IrDALogInfo), Fail); 168 169 //bigaddr = input[1] << 24 | input[2] << 16 | input[3] << 8 | input[4]; 170 //biglen = input[5] << 24 | input[6] << 16 | input[7] << 8 | input[8]; 171 bcopy(&input[1], &bigaddr, sizeof(bigaddr)); 172 bcopy(&input[5], &biglen, sizeof(biglen)); 173 174 //IOLog("biglen is %d\n", biglen); 175 176 // create and init the memory descriptor 177 //md = IOMemoryDescriptor::withAddress(bigaddr, biglen, kIODirectionOutIn, fTask); // REVIEW direction 178 //use withAddressRange() and prepare() instead 179 md = IOMemoryDescriptor::withAddressRange(bigaddr, biglen, kIODirectionOutIn, fTask); // REVIEW direction 180 md->prepare(kIODirectionOutIn); 181 182 require(md, Fail); 183 184 info = IrDALogGetInfo(); // get the info block 185 186 //ELG(info->hdr, info->hdrSize, 'irda', "info hdr"); 187 //ELG(info->eventLog, info->eventLogSize, 'irda', "info events"); 188 //ELG(info->msgBuffer, info->msgBufferSize, 'irda', "info msg buf"); 189 190 bcopy(info, pOut, sizeof(*info)); // copy the info record back to the client 191 *outPutSize = sizeof(*info); // set the output size (nop, it already is) 192 193 // copy the buffer over now if there is room 194 if (biglen >= info->hdrSize + info->eventLogSize + info->msgBufferSize) { 195 IOByteCount ct; 196 IOReturn rc; 197 198 rc = md->prepare(kIODirectionNone); 199 if (rc) {ELG(-1, rc, 'irda', "prepare failed"); } 200 201 ct = md->writeBytes(0, info->hdr, info->hdrSize); 202 if (ct != info->hdrSize) ELG(-1, rc, 'irda', "write of hdr failed"); 203 204 ct = md->writeBytes(info->hdrSize, info->eventLog, info->eventLogSize); 205 if (ct != info->eventLogSize) ELG(-1, rc, 'irda', "write of events failed"); 206 207 ct = md->writeBytes(info->hdrSize+info->eventLogSize, info->msgBuffer, info->msgBufferSize); 208 if (ct != info->msgBufferSize) ELG(-1, rc, 'irda', "write of msgs failed"); 209 210 ELG(0, info->hdrSize+info->eventLogSize, 'irda', "wrote msgs at offset"); 211 212 rc = md->complete(kIODirectionNone); 213 if (!rc) { ELG(0, 0, 'irda', "complete worked"); } 214 else { ELG(-1, rc, 'irda', "complete failed"); } 215 216 // todo check return code of above before resetting the buffer 217 IrDALogReset(); // reset the buffer now 218 } 219 md->release(); // free it 220 221 return kIOReturnSuccess; 222 223 224Fail: 225 226#endif // hasTracing > 0 227 228 return kIOReturnBadArgument; 229} 230 231// get irda status 232// 233// input: just the command byte 234// output: status buffer returned directly to pOut 235 236IOReturn 237IrDAUserClient::getIrDAStatus(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize) 238{ 239 IrDAComm *irda; 240 241 require(*outPutSize == sizeof(IrDAStatus), Fail); 242 require(fDriver, Fail); 243 244 bzero(pOut, sizeof(IrDAStatus)); 245 246 irda = fDriver->GetIrDAComm(); 247 if (irda) // sometimes IrDA may not be there 248 irda->GetIrDAStatus((IrDAStatus *)pOut); 249 250 fDriver->GetIrDAStatus((IrDAStatus *)pOut); 251 return kIOReturnSuccess; 252 253Fail: 254 IOLog("IrDA: Failing to get status\n"); 255 return kIOReturnBadArgument; 256} 257 258// set irda state 259// 260// input: just the state (true = on, false = off) 261// output: none 262 263IOReturn 264IrDAUserClient::setIrDAState(bool state) 265{ 266 IOReturn rtn = kIOReturnSuccess; 267 268 require(fDriver, Fail); 269 270 rtn = fDriver->SetIrDAUserClientState(state); 271 return rtn; 272 273Fail: 274 IOLog("IrDA: Failing to set IrDA state\n"); 275 return kIOReturnBadArgument; 276} 277