[plain text]
#define TIMERSTREAM FALSE
#include "AppleUSBTrinityAudioDevice.h"
#include <IOKit/usb/USB.h>
#include <IOKit/usb/IOUSBDevice.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOKitKeys.h>
#include <libkern/OSByteOrder.h>
#include <kern/thread_call.h>
static SInt32 power4AEQSettings[] = {
228, -129968, 130513,
-279, -125942, 128415,
-1689, -123355, 126686,
-5136, -95891, 109553,
-18995, -993, 6924,
-45000
};
static SInt32 power3AEQSettings[] = {
228, -129968, 130513,
-279, -125942, 128415,
-1689, -123355, 126686,
-5137, -95891, 109553,
-18995, -993, 6924,
-42000};
static SInt32 power1500mAEQSettings[] = {
228, -129968, 130513,
-279, -125942, 128415,
-1689, -123355, 126686,
-5137, -95891, 109553,
-18995, -993, 6924,
-20000};
SInt32 power500mAEQSettings[] = {
228, -129968, 130513,
-279, -125942, 128415,
-1689, -123355, 126686,
-5137, -95891, 109553,
-18995, -993, 6924,
-8000};
static UInt8 pluginBinary[] = {
0xBF, 0x35, 0x81, 0xBA, 0x85, 0xEA, 0x7B, 0x80, 0xE1, 0x13, 0xBF, 0xDE, 0x0B, 0x8D, 0xB9, 0x85,
0xBF, 0x1A, 0x0C, 0x8D, 0xB9, 0xE9, 0xF3, 0x81, 0xE8, 0x80, 0x80, 0x79, 0x90, 0x03, 0xBC, 0xEC,
0x81, 0xEA, 0xA2, 0xB0, 0xE4, 0x00, 0xE5, 0x02, 0x44, 0x99, 0x01, 0x45, 0x15, 0x71, 0x14, 0x19,
0x90, 0xF6, 0xE0, 0xF0, 0xC8, 0x87, 0x80, 0xC8, 0x51, 0xB0, 0x12, 0x63, 0x90, 0x03, 0x28, 0x98,
0x02, 0xE0, 0x40, 0xC8, 0x89, 0x80, 0xC8, 0xA0, 0xB0, 0xE1, 0xFB, 0x12, 0x21, 0xC8, 0x88, 0x80,
0xE8, 0x80, 0x80, 0x90, 0x09, 0xE8, 0x01, 0xA0, 0xC8, 0x80, 0x80, 0xBF, 0x2F, 0x81, 0xE8, 0x80,
0x80, 0xC8, 0xF3, 0x81, 0xE1, 0x0C, 0x12, 0x21, 0x90, 0x25, 0xE9, 0xED, 0x81, 0xE8, 0x7B, 0x80,
0x59, 0x49, 0x74, 0xE9, 0xF0, 0x81, 0xE2, 0x80, 0x2A, 0x73, 0x11, 0x2A, 0x7B, 0x99, 0x0A, 0xE8,
0xF1, 0x81, 0x00, 0xC8, 0xF1, 0x81, 0xCC, 0x7B, 0x80, 0xE8, 0xEE, 0x81, 0xBC, 0xDA, 0x81, 0xE8,
0xF2, 0x81, 0x90, 0x29, 0xE9, 0x7B, 0x80, 0xE8, 0xED, 0x81, 0x51, 0x72, 0xE8, 0xF1, 0x81, 0x98,
0x16, 0x40, 0xC8, 0xF1, 0x81, 0x12, 0xE1, 0x80, 0x29, 0xE1, 0xB0, 0x79, 0x99, 0x04, 0x12, 0xBC,
0xD4, 0x81, 0xE0, 0x30, 0xC8, 0x7B, 0x80, 0xE8, 0xEF, 0x81, 0xC8, 0xF2, 0x81, 0xE8, 0xF2, 0x81,
0x90, 0x03, 0xBC, 0x24, 0x81, 0x40, 0xC8, 0xF2, 0x81, 0xBC, 0x24, 0x81, 0xB9, 0x01, 0x08, 0x0F,
0xD0, 0x01, 0x01, 0x01
};
UInt8 disableplugin = 0xba;
#define super AppleUSBAudioDevice
OSDefineMetaClassAndStructors (AppleUSBTrinityAudioDevice, AppleUSBAudioDevice)
IOReturn AppleUSBTrinityAudioDevice::xdfpSetMem (UInt8 * buf, UInt16 length, UInt16 xdfpAddr) {
IOUSBDevRequest devReq;
IOReturn result;
result = kIOReturnError;
FailWithAction (!controlInterface, debugIOLog ("AppleUSBTrinityAudioDevice::xdfpSetMem () - Error - no USB interface\n"), Exit);
devReq.bmRequestType = USBmakebmRequestType (kUSBOut, kUSBVendor, kUSBDevice);
devReq.bRequest = kMicronasSetMemReq;
devReq.wValue = 0;
devReq.wIndex = xdfpAddr;
devReq.wLength = length;
devReq.pData = buf;
result = controlInterface->DeviceRequest (&devReq);
Exit:
return result;
}
IOReturn AppleUSBTrinityAudioDevice::xdfpGetMem (UInt8 * buf, UInt16 length, UInt16 xdfpAddr) {
IOUSBDevRequest devReq;
IOReturn result;
result = kIOReturnError;
FailWithAction (!controlInterface, debugIOLog ("AppleUSBTrinityAudioDevice::xdfpGetMem () - Error - no USB interface\n"), Exit);
devReq.bmRequestType = USBmakebmRequestType (kUSBIn, kUSBVendor, kUSBDevice);
devReq.bRequest = kMicronasGetMemReq;
devReq.wValue = 0;
devReq.wIndex = xdfpAddr;
devReq.wLength = length;
devReq.pData = buf;
result = controlInterface->DeviceRequest (&devReq);
Exit:
return result;
}
IOReturn AppleUSBTrinityAudioDevice::xdfpWrite (UInt16 xdfpAddr, SInt32 value) {
static UInt8 xdfpData[5];
if (value < 0) value += 0x40000;
xdfpData[0] = (value >> 10) & 0xff;
xdfpData[1] = (value >> 2) & 0xff;
xdfpData[2] = value & 0x03;
xdfpData[3] = (xdfpAddr >> 8) & 0x03;
xdfpData[4] = xdfpAddr & 0xff;
return xdfpSetMem (xdfpData, 5, V8_WRITE_START_ADDR);
}
IOReturn AppleUSBTrinityAudioDevice::disablePlugin () {
return xdfpSetMem (&disableplugin, 1, V8_PLUGIN_START_ADDR);
}
SInt32 *AppleUSBTrinityAudioDevice::getProperEQSettings () {
IOUSBDevice * device;
IORegistryEntry * parent;
const IORegistryPlane * plane;
OSObject * powerProperty;
UInt32 availablePower;
OSNumber * powerNum;
OSData * powerData;
SInt32 * settings;
settings = NULL;
availablePower = 500;
FailIf (!controlInterface, Exit);
device = controlInterface->GetDevice ();
FailIf (!device, Exit);
plane = IORegistryEntry::getPlane (kIOUSBPlane); FailIf (!plane, Exit);
parent = device->getParentEntry (plane);
FailIf (!parent, Exit);
powerProperty = parent->getProperty ("AAPL,current-available");
FailIf (!powerProperty, Exit);
if (powerNum = OSDynamicCast (OSNumber, powerProperty)) {
availablePower = powerNum->unsigned32BitValue ();
} else if (powerData = OSDynamicCast (OSData, powerProperty)) {
availablePower = *(UInt32 *)powerData->getBytesNoCopy ();
}
debug3IOLog ("AppleUSBTrinityAudioDevice[0x%x]: Hub (%d) found.\n", this, availablePower);
if (availablePower >= 4000) {
settings = power4AEQSettings;
} else if (availablePower >= 3000) {
settings = power3AEQSettings;
} else if (availablePower >= 1500) {
settings = power1500mAEQSettings;
} else if (availablePower >= 500) {
settings = power500mAEQSettings;
}
Exit:
return settings;
}
IOReturn AppleUSBTrinityAudioDevice::downloadEQ () {
return downloadEQ (getProperEQSettings ());
}
IOReturn AppleUSBTrinityAudioDevice::downloadEQ (SInt32 * eqSettings) {
UInt32 eqIndex;
UInt16 xdfpAddr;
IOReturn result;
result = kIOReturnBadArgument;
FailWithAction (!eqSettings, debugIOLog("AppleUSBTrinityAudioDevice::downloadEQ() - error no EQ settings available.\n"), Exit);
for (eqIndex = 0, xdfpAddr = XDFP_STARTING_EQ_ADDR; eqIndex < EQ_TABLE_SIZE; eqIndex++, xdfpAddr++) {
result = xdfpWrite (xdfpAddr, eqSettings[eqIndex]);
if (result != kIOReturnSuccess) {
debug3IOLog ("AppleUSBTrinityAudioDevice::downloadEQ () - error writing settings %d: 0x%x\n", eqIndex, result);
break;
}
IOSleep (3);
}
Exit:
return result;
}
IOReturn AppleUSBTrinityAudioDevice::downloadPlugin () {
return xdfpSetMem (&pluginBinary[1], sizeof (pluginBinary), V8_PLUGIN_START_ADDR + 1);
}
IOReturn AppleUSBTrinityAudioDevice::enablePlugin () {
return xdfpSetMem (pluginBinary, 1, V8_PLUGIN_START_ADDR);
}
bool AppleUSBTrinityAudioDevice::start (IOService * provider) {
IOService * device;
bool result;
debug2IOLog ("AppleUSBTrinityAudioDevice[0x%x]: G4 Cube speakers detected.\n", this);
result = FALSE;
FailIf (FALSE == super::start (provider), Exit);
disablePlugin ();
downloadEQ ();
downloadPlugin ();
enablePlugin ();
device = controlInterface->GetDevice ();
FailIf (NULL == device, Exit);
result = TRUE;
Exit:
return result;
}
#if 0
void AppleUSBTrinityAudioDevice::performStop (IOService * provider) {
if (powerProvider) {
powerProvider->deRegisterInterestedDriver (this);
}
super::performStop (provider);
}
#endif
#if TIMERSTREAM
bool AppleUSBTrinityAudioDevice::reinitWithInterface (IOUSBInterface *interface) {
bool result;
result = FALSE;
FailIf (!super::reinitWithInterface (interface), Exit);
disablePlugin ();
downloadEQ ();
downloadPlugin ();
enablePlugin ();
debug2IOLog ("AppleUSBTrinityAudioDevice[0x%]: G4 Cube speakers re-initialized.\n", this);
result = TRUE;
Exit:
return result;
}
#endif
#if 0
IOReturn AppleUSBTrinityAudioDevice::powerStateDidChangeTo (IOPMPowerFlags newPowerFlags, unsigned long stateNumber, IOService *device) {
debug4IOLog ("AppleUSBTrinityAudioDevice::powerStateDidChangeTo (0x%x, %d, 0x%x)\n", newPowerFlags, stateNumber, device);
if (!(currentPowerFlags & IOPMDeviceUsable) && (newPowerFlags & IOPMDeviceUsable)) {
debugIOLog ("G4 Cube speakers: Waking from sleep - downloading power settings to speakers.\n");
eqRetryCount = 0;
attemptEQDownload ();
}
currentPowerFlags = newPowerFlags;
return 0;
}
#else
IOReturn AppleUSBTrinityAudioDevice::performPowerStateChange (IOAudioDevicePowerState oldPowerState, IOAudioDevicePowerState newPowerState, UInt32 *microSecsUntilComplete) {
if (oldPowerState == kIOAudioDeviceSleep) {
debugIOLog ("G4 Cube speakers: Waking from sleep - downloading power settings to speakers.\n");
eqRetryCount = 0;
attemptEQDownload ();
}
return kIOReturnSuccess;
}
#endif
void AppleUSBTrinityAudioDevice::scheduleEQDownloadRetry (void) {
AbsoluteTime fireTime;
UInt64 nanos;
retain (); clock_get_uptime (&fireTime);
absolutetime_to_nanoseconds (fireTime, &nanos);
nanos += 10000000; nanoseconds_to_absolutetime (nanos, &fireTime);
thread_call_func_delayed ((thread_call_func_t)retryEQDownload, this, fireTime);
}
void AppleUSBTrinityAudioDevice::attemptEQDownload (void) {
debug2IOLog ("AppleUSBTrinityAudioDevice::attemptEQDownload () - eqRetryCount = %d\n", eqRetryCount);
if (controlInterface) {
if (downloadEQ () != kIOReturnSuccess) {
if (++eqRetryCount < MAX_EQ_DOWNLOAD_RETRIES) {
scheduleEQDownloadRetry ();
} else {
debugIOLog ("G4 Cube Speakers: too many retries of downloadEQ () - aborting.\n");
}
}
} else {
debugIOLog ("There is no interface in attemptEQDownload!\n");
}
}
void AppleUSBTrinityAudioDevice::retryEQDownload (void * arg) {
AppleUSBTrinityAudioDevice * device = (AppleUSBTrinityAudioDevice *)arg;
if (device) {
device->attemptEQDownload ();
device->release (); }
}
Generated by GNU enscript 1.6.4.