PDA

View Full Version : Playing with sensors and lights




balamw
Apr 8, 2011, 10:58 AM
Inspired by a user's thread who is unhappy with the way their KB backlight works (http://forums.macrumors.com/showthread.php?t=1130722), I decided to play with the Ambient Light Sensor and KB backlight on my MBP.

I was a bit disappointed to see that unlike under W7 (http://msdn.microsoft.com/en-us/library/dd318953(v=vs.85).aspx)there is no official API to access the sensor data. Really?

Anyhow, I quickly found this code: http://osxbook.com/book/bonus/chapter10/light/ and various comments around that it doesn't work anymore. A bit more digging led to this code: http://google-mac-qtz-patches.googlecode.com/svn-history/r5/trunk/AmbientLightSensor which does actually work and allowed me to whip this up.

A few reasons for the post:
To publish currently working code Google might be able to find in case someone else is looking
To ask is there really no better way to do this?


I presume since this uses the undocumented (apart from the header files) IOConnectCallMethod it would not be OK to include in an app for the Mac App Store?

Anyhow, here's the code:


// Inspired by the code found at
// http://google-mac-qtz-patches.googlecode.com/svn-history/r5/trunk/AmbientLightSensor
// and http://osxbook.com/book/bonus/chapter10/light/

#import <Foundation/Foundation.h>

#import <IOKit/IOKitLib.h>

io_connect_t dataPort;

enum {
kGetSensorReadingID = 0, // getSensorReading(int *, int *)
kGetLEDBrightnessID = 1, // getLEDBrightness(int, int *)
kSetLEDBrightnessID = 2, // setLEDBrightness(int, int, int *)
kSetLEDFadeID = 3, // setLEDFade(int, int, int, int *)
};

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

kern_return_t kr = KERN_FAILURE;
io_service_t serviceObject;

// Look up a registered IOService object whose class is AppleLMUController
serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("AppleLMUController"));
if (serviceObject) {
NSLog(@"Got device AppleLMUController");
kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &dataPort);
}
IOObjectRelease(serviceObject);

if (kr == KERN_SUCCESS) {
NSLog(@"IOServiceOpen succeeded");

while (1) {

//Get the ALS reading
uint32_t scalarOutputCount = 2;
uint64_t values[scalarOutputCount];

kr = IOConnectCallMethod(dataPort,
kGetSensorReadingID,
nil,
0,
nil,
0,
values,
&scalarOutputCount,
nil,
0);

// Get the LED reading
uint32_t scalarInputCountKB = 1;
uint32_t scalarOutputCountKB = 1;
uint64_t in_unknown = 0, out_brightness;

kr = IOConnectCallMethod(dataPort,
kGetLEDBrightnessID,
&in_unknown,
scalarInputCountKB,
nil,
0,
&out_brightness,
&scalarOutputCountKB,
nil,
0);

// The code at http://google-mac-qtz-patches.googlecode.com/svn-history/r5/trunk/AmbientLightSensor
// suggests that values be calibrated to 0x00FFFFFF for the MacbookPro5 family and 1600 otherwise
// This seems too low.
// Output as high as 67092480 (0x03ffc000) has been observed on my Macbook 5,2
// So I'll report the raw value instead and remove the calibration code.
// Also since for the MBP5,2 the two values agree
// (there is only one ALS sensor) I'll report only the maximum value.

// The LED value however does seem to go 0-4091 though the values do not seem fixed.
// They vary with light level and time such that maxing it out results in slightly
// lower values over time.
// Somewhere between 2500000 and 3000000 the KB light turns off. It's hard to capture it since the light ramps off.

NSLog(@"ALS, LED %d,%d",MAX(values[0],values[1]),out_brightness);

sleep(1); //lame way to slow down the output

}
}

[pool drain];
return 0;
}


B



chown33
Apr 8, 2011, 11:28 AM
I presume since this uses the undocumented (apart from the header files) IOConnectCallMethod it would not be OK to include in an app for the Mac App Store?

You'll probably have to try it to find out for sure.

However, a google search for IOConnectCallMethod found this:
http://lists.apple.com/archives/darwin-drivers/2008/mar/msg00007.html

It suggests IOConnectCall* functions are newer replacements for older deprecated functions. So using the older functions WOULD get you rejected, but the newer ones, I dunno: try it and see what happens.

balamw
Apr 8, 2011, 11:34 AM
You'll probably have to try it to find out for sure.

However, a google search for IOConnectCallMethod found this:
http://lists.apple.com/archives/darwin-drivers/2008/mar/msg00007.html

It suggests IOConnectCall* functions are newer replacements for older deprecated functions. So using the older functions WOULD get you rejected, but the newer ones, I dunno: try it and see what happens.

Yeah, there's reference to them in the 64 bit porting guide but little of any use:

http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/64bitPorting/KernelExtensionsandDrivers/KernelExtensionsandDrivers.html%23//apple_ref/doc/uid/TP40001064-CH227-SW1
Replace outdated IOConnectMethod* calls—The following functions are not supported in a 64-bit environment:

IOConnectMethodScalarIScalarO
IOConnectMethodScalarIStructureO
IOConnectMethodScalarIStructureI
IOConnectMethodStructureIStructureO
IOConnectMethodScalarIScalarO
IOConnectMethodScalarIStructureO
IOConnectMethodScalarIStructureI
IOConnectMethodStructureIStructureO

You should instead use the IOConnectCall* functions:

IOConnectCallMethod
IOConnectCallAsyncMethod
IOConnectCallStructMethod
IOConnectCallAsyncStructMethod
IOConnectCallScalarMethod
IOConnectCallAsyncScalarMethod

codymac
Apr 8, 2011, 01:30 PM
Interesting.

I've been futzing with the same thing for the past couple of evenings. My purpose has been to see if it's possible to pull back the value from the ALS and scale/modify the point at which the keyboard lights turn on & off. Up until this point, I've just been trying unsuccessfully to capture the ALS value.

FWIW, your code doesn't work for me, but your call, in my code, seems to (replacing my malformed IOConnectCallScalarMethod with your IOConnectCallMethod). Thanks for that.
:)

I think it's the part about accessing the ALS that might keep it out of the App Store. It was my understanding, when I tried to find some information, that this is the part that's unpublished.

balamw
Apr 8, 2011, 01:44 PM
FWIW, your code doesn't work for me, but your call, in my code, seems to (replacing my malformed IOConnectCallScalarMethod with your IOConnectCallMethod). Thanks for that.


That's essentially what I was looking for as well, first just a way of figuring out how the backlight LED levels are determined and then trying to see if it could be controlled.

Interesting. It works great for me in Xcode 3.2.6 on OS X 10.6.6. Are you using another version or OS? How does it break for you? I just created a new Application -> Command Line Tool -> Foundation, add IOKit to the project and away we go.

B

codymac
Apr 8, 2011, 02:15 PM
That's essentially what I was looking for as well, first just a way of figuring out how the backlight LED levels are determined and then trying to see if it could be controlled.

Interesting. It works great for me in Xcode 3.2.6 on OS X 10.6.6. Are you using another version or OS? How does it break for you? I just created a new Application -> Command Line Tool -> Foundation, add IOKit to the project and away we go.

B

Mea culpa.

I just sort of autopiloted through creating a C program in Xcode 4. I should know better since I've been passing IOKit & CoreFoundation frameworks to gcc in a Terminal window for the past couple of evenings.
:o

Proof positive - yours works a treat on Xcode 4.0 on 10.6.7 on a MBP 8,2. Apologies for the confusion.
:)

FWIW, I've been basically trying to copy & update the OSX Book code you linked to but also found these other sources (using IOConnectCallScalarMethod):

http://code.google.com/p/vavi-sensor/source/browse/trunk/vavi-ambientlight/src/main/jni/LmuWrapper.c?spec=svn14&r=14

http://qt.gitorious.org/qt-mobility/qt-mobility/commit/6992060873beaa52aea43f14835f899ba45642e8/diffs?diffmode=sidebyside&fragment=1#src/systeminfo/qsysteminfo_mac.mm

I never stumbled across the google link you posted. Good info.

balamw
Apr 8, 2011, 04:45 PM
http://code.google.com/p/vavi-sensor/source/browse/trunk/vavi-ambientlight/src/main/jni/LmuWrapper.c?spec=svn14&r=14

http://qt.gitorious.org/qt-mobility/qt-mobility/commit/6992060873beaa52aea43f14835f899ba45642e8/diffs?diffmode=sidebyside&fragment=1#src/systeminfo/qsysteminfo_mac.mm


I had seen the first one too. The google one I had found was from Quartz Composer so it's almost Apple sanctioned.

B