[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 (!mControlInterface, 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 = mControlInterface->DeviceRequest (&devReq);
Exit:
return result;
}
IOReturn AppleUSBTrinityAudioDevice::xdfpGetMem (UInt8 * buf, UInt16 length, UInt16 xdfpAddr) {
IOUSBDevRequest devReq;
IOReturn result;
result = kIOReturnError;
FailWithAction (!mControlInterface, 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 = mControlInterface->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 (!mControlInterface, Exit);
device = mControlInterface->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 ();
}
debugIOLog ("AppleUSBTrinityAudioDevice[0x%x]: Hub (%d) found.", this, availablePower);
if (availablePower >= 4000) {
debugIOLog ("Usinging 4 amp EQ");
settings = power4AEQSettings;
} else if (availablePower >= 3000) {
debugIOLog ("Usinging 3 amp EQ");
settings = power3AEQSettings;
} else if (availablePower >= 1500) {
debugIOLog ("Usinging 1.5 amp EQ");
settings = power1500mAEQSettings;
} else if (availablePower >= 500) {
debugIOLog ("Usinging 0.5 amp EQ");
settings = power500mAEQSettings;
}
Exit:
return settings;
}
IOReturn AppleUSBTrinityAudioDevice::downloadEQ () {
return downloadEQ (getProperEQSettings ());
}
IOReturn AppleUSBTrinityAudioDevice::downloadEQ (SInt32 * eqSettings) {
UInt32 eqIndex;
UInt16 xdfpAddr;
IOReturn result;
debugIOLog ("+AppleUSBTrinityAudioDevice::downloadEQ (%p)", eqSettings);
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) {
debugIOLog ("AppleUSBTrinityAudioDevice::downloadEQ () - error writing settings %d: 0x%x", eqIndex, result);
break;
}
IOSleep (3);
}
Exit:
debugIOLog ("-AppleUSBTrinityAudioDevice::downloadEQ (%p), result = %d", eqSettings, result);
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;
debugIOLog ("AppleUSBTrinityAudioDevice[0x%x]: G4 Cube speakers detected.", this);
result = FALSE;
FailIf (FALSE == super::start (provider), Exit);
disablePlugin ();
downloadEQ ();
downloadPlugin ();
enablePlugin ();
device = mControlInterface->GetDevice ();
FailIf (NULL == device, Exit);
result = TRUE;
Exit:
return result;
}
IOReturn AppleUSBTrinityAudioDevice::performPowerStateChange (IOAudioDevicePowerState oldPowerState, IOAudioDevicePowerState newPowerState, UInt32 *microSecsUntilComplete) {
IOReturn result;
debugIOLog ("+AppleUSBTrinityAudioDevice::performPowerStateChange (%d, %d, %p)", oldPowerState, newPowerState, microSecsUntilComplete);
result = super::performPowerStateChange (oldPowerState, newPowerState, microSecsUntilComplete);
if (oldPowerState == kIOAudioDeviceSleep) {
debugIOLog ("G4 Cube speakers: Waking from sleep - downloading power settings to speakers.");
eqRetryCount = 0;
attemptEQDownload ();
}
return result;
}
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) {
debugIOLog ("AppleUSBTrinityAudioDevice::attemptEQDownload () - eqRetryCount = %d", eqRetryCount);
FailIf (NULL == mControlInterface, Exit);
if (downloadEQ () != kIOReturnSuccess) {
if (++eqRetryCount < MAX_EQ_DOWNLOAD_RETRIES) {
scheduleEQDownloadRetry ();
} else {
debugIOLog ("G4 Cube Speakers: too many retries of downloadEQ () - aborting.");
}
}
Exit:
return;
}
void AppleUSBTrinityAudioDevice::retryEQDownload (void * arg) {
AppleUSBTrinityAudioDevice * device = (AppleUSBTrinityAudioDevice *)arg;
if (device) {
device->attemptEQDownload ();
device->release (); }
}
Generated by GNU enscript 1.6.4.