1/* 2 File: CIrDevice.cpp 3 4 Contains: Generic interface to IR hardware. 5 6*/ 7 8#include "CIrDevice.h" 9#include "IrGlue.h" 10#include "IrLAP.h" 11#include "AppleIrDA.h" 12#include "IrDALog.h" 13 14#if (hasTracing > 0 && hasCIrDeviceTracing > 0) 15 16enum IrLogCodes 17{ 18 kLogNew = 1, 19 kLogFree, 20 kLogInit, 21 kLogStart, 22 kLogStop, 23 24 kLogChangeSpeed, 25 kLogSetSpeedComplete, 26 27 kLogReadComplete, 28 kLogPacketDropped, 29 30 kLogStartXmit, 31 kLogStartXmitPutBuf, 32 kLogStartXmitCtlBuf, 33 kLogStartXmitCtlSize, 34 kLogStartXmitDataBuf, 35 kLogStartXmitDataSize, 36 kLogStartXmitFrame, 37 kLogStartXmitLength, 38 kLogStartXmitData, 39 kLogTransmitComplete, 40 kLogStartXmitError, 41 42 kLogSetAddress, 43 kLogNotOurAddress, 44 45}; 46 47static 48EventTraceCauseDesc IrLogEvents[] = { 49 {kLogNew, "IrDevice: new, obj="}, 50 {kLogFree, "IrDevice: free, obj="}, 51 {kLogInit, "IrDevice: init, obj="}, 52 {kLogStart, "IrDevice: start"}, 53 {kLogStop, "IrDevice: stop"}, 54 55 {kLogChangeSpeed, "IrDevice: change speed, new="}, 56 {kLogSetSpeedComplete, "IrDevice: set speed complete, worked="}, 57 58 {kLogReadComplete, "IrDevice: read complete, len=,data="}, 59 {kLogPacketDropped, "IrDevice: packet dropped. no read pending from lap"}, 60 61 {kLogStartXmit, "IrDevice: start xmit"}, 62 {kLogStartXmitPutBuf, "IrDevice: xmit put buffer"}, 63 {kLogStartXmitCtlBuf, "IrDevice: xmit ctl buffer"}, 64 {kLogStartXmitCtlSize, "IrDevice: xmit ctl length"}, 65 {kLogStartXmitDataBuf, "IrDevice: xmit data buffer"}, 66 {kLogStartXmitDataSize, "IrDevice: xmit data length"}, 67 {kLogStartXmitFrame, "IrDevice: xmit frame buffer"}, 68 {kLogStartXmitLength, "IrDevice: xmit packet length"}, 69 {kLogStartXmitData, "IrDevice: xmit packet data"}, 70 {kLogTransmitComplete, "IrDevice: transmit complete"}, 71 {kLogStartXmitError, "IrDevice: start xmit logic ERROR. fXmitting="}, 72 73 {kLogSetAddress, "IrDevice: set lap address"}, 74 {kLogNotOurAddress, "IrDevice: not our lap address, in=, our="}, 75 76}; 77 78#define XTRACE(x, y, z) IrDALogAdd( x, y, (uintptr_t)z & 0xffff, IrLogEvents, true ) 79 80#else 81#define XTRACE(x,y,z)((void)0) 82#endif 83 84#define super OSObject 85 OSDefineMetaClassAndStructors(CIrDevice, OSObject); 86 87/*static*/ 88CIrDevice * 89CIrDevice::cIrDevice(TIrGlue *irda, AppleIrDASerial *driver) 90{ 91 CIrDevice *obj = new CIrDevice; 92 XTRACE(kLogNew, 0, obj); 93 if (obj && !obj->Init(irda, driver)) { 94 obj->release(); 95 obj = nil; 96 } 97 return obj; 98} 99 100void 101CIrDevice::free(void) 102{ 103 XTRACE(kLogFree, 0, this); 104 super::free(); 105} 106 107Boolean 108CIrDevice::Init(TIrGlue *irda, AppleIrDASerial *driver) 109{ 110 XTRACE(kLogInit, 0, this); 111 112 113 fIrDA = nil; 114 fDriver = nil; 115 fGetBuffer = nil; 116 bzero(&fIrStatus, sizeof(fIrStatus)); 117 fLAPAddr = 0; 118 fSpeed = 0; 119 fBofs = 0; 120 fXmitting = false; // true if in middle of xmit 121 122 if (!super::init()) return false; 123 124 fIrDA = irda; 125 fDriver = driver; 126 127 ResetStats(); 128 return true; 129} 130 131void 132CIrDevice::Start(void) 133{ 134 XTRACE(kLogStart, 0, 0); 135 ChangeSpeed(9600); // set to default speed 136} 137 138void 139CIrDevice::Stop(void) 140{ 141 XTRACE(kLogStop, 0, 0); 142 143 fDriver = nil; 144} 145 146void 147CIrDevice::SetLAPAddress(UInt8 addr) // Set our LAP address 148{ 149 XTRACE(kLogSetAddress, 0, addr); 150 fLAPAddr = addr; 151} 152 153 154//-------------------------------------------------------------------------------- 155// ValidFrameAddress 156// 157// Check the lap address field for either broadcast, or our address 158//-------------------------------------------------------------------------------- 159Boolean 160CIrDevice::ValidFrameAddress(UInt8 aField) 161{ 162 Boolean rc = ((aField >> 1) == kIrLAPBroadcastAddr) || ((aField >> 1) == fLAPAddr); 163 if (!rc) { 164 XTRACE(kLogNotOurAddress, aField, fLAPAddr); 165 } 166 return rc; 167} 168 169//-------------------------------------------------------------------------------- 170// ChangeSpeed 171//-------------------------------------------------------------------------------- 172IrDAErr CIrDevice::ChangeSpeed(unsigned long bps) 173{ 174 XTRACE(kLogChangeSpeed, bps >> 16, bps); 175 require(fDriver, Fail); 176 check(fXmitting == false); 177 178 if (bps != fSpeed) { 179 (void) fDriver->SetSpeed(bps); // start the speed change sequence 180 fSpeed = bps; 181 } 182 183 /*** 184 if (1) { // doing this right again finally 185 TIrLAP *lap; 186 require(fIrDA, Fail); 187 lap = fIrDA->GetLAP(); 188 require(lap, Fail); 189 lap->ChangeSpeedComplete(); // finally tell lap that the speed change finished 190 } 191 ***/ 192 return noErr; 193 194Fail: 195 return kIrDAErrWrongState; 196 197} // CIrDevice::ChangeSpeed 198 199void 200CIrDevice::SetSpeedComplete(Boolean worked) 201{ 202 TIrLAP *lap; 203 XTRACE(kLogSetSpeedComplete, 0, worked); 204 require(fIrDA, Fail); 205 lap = fIrDA->GetLAP(); 206 require(lap, Fail); 207 lap->ChangeSpeedComplete(); 208 209Fail: 210 return; 211} 212 213//-------------------------------------------------------------------------------- 214// GetMediaBusy 215//-------------------------------------------------------------------------------- 216Boolean CIrDevice::GetMediaBusy(void) 217{ 218 // return fDevice->GetMediaBusy(); 219 return false; 220} 221 222//-------------------------------------------------------------------------------- 223// ResetMediaBusy 224//-------------------------------------------------------------------------------- 225void CIrDevice::ResetMediaBusy(void) 226{ 227 // fDevice->ResetMediaBusy(); 228 return; 229} 230 231//-------------------------------------------------------------------------------- 232// StartReceive 233//-------------------------------------------------------------------------------- 234void CIrDevice::StartReceive(CBufferSegment* inputBuffer) 235{ 236// check(fGetBuffer == nil); // see if a read is "pending" already 237 fGetBuffer = inputBuffer; 238} 239 240//-------------------------------------------------------------------------------- 241// StopReceive 242//-------------------------------------------------------------------------------- 243void CIrDevice::StopReceive(void) 244{ 245 //check(fGetBuffer != nil); // this happens 246 fGetBuffer = nil; 247} 248 249//-------------------------------------------------------------------------------- 250// ReadComplete 251//-------------------------------------------------------------------------------- 252void CIrDevice::ReadComplete(UInt8 *buffer, UInt32 length) 253{ 254 XTRACE(kLogReadComplete, 0, length); 255 UByte aField, cField; 256 257 // if debugging really high, log data bytes too 258#if (hasTracing > 0 && hasCIrDeviceTracing > 1) 259 { 260 int len = length; 261 UInt32 w; 262 UInt8 *b = buffer; 263 int i; 264 265 while (len > 0) { 266 w = 0; 267 for (i = 0 ; i < 4; i++) { 268 w = w << 8; 269 if (len > 0) // don't run off end (pad w/zeros) 270 w = w | *b; 271 b++; 272 len--; 273 } 274 XTRACE(kLogReadComplete, w >> 16, w); 275 } 276 } 277 278#endif // hasCIrDeviceTracing > 1 279 280 // test for data recvd but LAP doesn't have a read pending 281 if (fGetBuffer == nil) { 282 XTRACE(kLogPacketDropped, 0, 0); 283 Stats_PacketDropped(); // different bucket for invalid sequence vs. this? 284 return; 285 } 286 287 require(length >= 2, Fail); 288 289 aField = buffer[0]; 290 cField = buffer[1]; 291 length -= 2; 292 buffer += 2; 293 294 if (length > 0) { 295 fGetBuffer->Putn(buffer, length); // copy to CBufferSegment 296 fGetBuffer->Hide(fGetBuffer->GetSize() - fGetBuffer->Position(), kPosEnd); 297 // Seek to beginning of the buffer for our client 298 fGetBuffer->Seek(0, kPosBeg); 299 } 300 301 if (ValidFrameAddress(aField)) { // if packet addressed to us 302 Stats_DataPacketIn(); 303 fGetBuffer = nil; // read is done, clear our "read pending" flag 304 fIrDA->GetLAP()->InputComplete(aField,cField); // then let LAP know about it (already owns "fGetBuffer") 305 } 306 else { 307 //int review_media_busy_logic; 308 // fMediaBusy = true; // else did we just saw someone else's traffic? 309 Stats_PacketDropped(); // different counters? 310 } 311Fail: 312 return; 313 314} // CIrDevice::ReadComplete 315 316//-------------------------------------------------------------------------------- 317// StartTransmit 318//-------------------------------------------------------------------------------- 319void CIrDevice::StartTransmit(TIrLAPPutBuffer* outputBuffer, ULong leadInCount) 320{ 321 UByte *ctlBuffer; 322 UByte *dataBuffer; 323 int ctlSize; 324 int dataSize; 325 IOReturn ior; 326 327 require(fDriver, Fail); 328 require(outputBuffer, Fail); 329 require(fXmitting == false, Fail); 330 331 fXmitting = true; 332 333 if (fBofs != leadInCount) { 334 fDriver->SetBofCount(leadInCount); // cache and call only if different? 335 fBofs = leadInCount; 336 } 337 338 XTRACE(kLogStartXmitPutBuf, 0, outputBuffer); 339 340 ctlBuffer = outputBuffer->GetCtrlBuffer(); 341 XTRACE(kLogStartXmitCtlBuf, 0, ctlBuffer); 342 343 ctlSize = outputBuffer->GetCtrlSize(); 344 XTRACE(kLogStartXmitCtlSize, 0, ctlSize); 345 346 dataBuffer = outputBuffer->GetDataBuffer(); 347 XTRACE(kLogStartXmitDataBuf, 0, dataBuffer); 348 349 dataSize = outputBuffer->GetDataSize(); 350 XTRACE(kLogStartXmitDataSize, (int)dataSize >> 16, dataSize); 351 352 //require(ctlSize + dataSize <= LapLength, Fail); 353 354#if (hasTracing > 0 && hasCIrDeviceTracing > 1) 355 if (1) { 356 int len = ctlSize + dataSize; // dump control and data buffers 357 UInt32 w; 358 UInt8 *b = ctlBuffer; // start with control buffer, then switch to data buffer 359 int i; 360 361 XTRACE(kLogStartXmitLength, len >> 16, len); 362 363 require(len > 0 && ctlSize > 0 && ctlBuffer != nil, Fail); // sanity (assumes non-empty ctlbuffer) 364 365 while (len > 0) { // loop over the packet 366 w = 0; // logging 4 bytes at a time 367 for (i = 0 ; i < 4; i++) { 368 w = w << 8; 369 if (len > 0) // don't run off end (pad w/zeros) 370 w = w | *b; 371 b++; 372 if (b == &ctlBuffer[ctlSize]) // if just incr'd past end of control buffer 373 b = dataBuffer; // then switch to data buffer 374 len--; 375 } 376 XTRACE(kLogStartXmitData, w >> 16, w); 377 } 378 } 379#endif // hasCIrDeviceTracing > 1 380 381 // start the transmit 382 ior = fDriver->StartTransmit(ctlSize, ctlBuffer, dataSize, dataBuffer); 383 if (ior != kIOReturnSuccess) { 384 XTRACE(kLogStartXmitError, ior >> 16, ior); 385 TransmitComplete(false); 386 return; 387 } 388 XTRACE(kLogStartXmitData, 0xffff, 0xffff); 389 return; 390 391Fail: 392 XTRACE(kLogStartXmitError, 0, fXmitting); 393 return; 394} 395 396void CIrDevice::TransmitComplete(Boolean worked) 397{ 398 TIrLAP *lap; 399 400 XTRACE(kLogTransmitComplete, 0, worked); 401 check(fXmitting); 402 403 fXmitting = false; 404 require(fIrDA, Fail); 405 406 lap = fIrDA->GetLAP(); 407 require(lap, Fail); 408 Stats_DataPacketOut(); 409 410 lap->OutputComplete(); // what to do if the write failed? 411 412Fail: 413 return; 414} 415 416//-------------------------------------------------------------------------------- 417// ResetStats 418//-------------------------------------------------------------------------------- 419void CIrDevice::ResetStats() 420{ 421 bzero(&fIrStatus, sizeof(fIrStatus)); 422} 423