Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

balamw

Moderator emeritus
Original poster
Aug 16, 2005
19,366
979
New England
Inspired by a user's thread who is unhappy with the way their KB backlight works, 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 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:

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
 
Last edited:

chown33

Moderator
Staff member
Aug 9, 2009
10,740
8,416
A sea of green
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

Moderator emeritus
Original poster
Aug 16, 2005
19,366
979
New England
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/...html#//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

macrumors 6502
Jun 12, 2009
449
2
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

Moderator emeritus
Original poster
Aug 16, 2005
19,366
979
New England
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

macrumors 6502
Jun 12, 2009
449
2
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.
:eek:

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-senso...ght/src/main/jni/LmuWrapper.c?spec=svn14&r=14

http://qt.gitorious.org/qt-mobility...&fragment=1#src/systeminfo/qsysteminfo_mac.mm

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

Attachments

  • screenshot.png
    screenshot.png
    297.1 KB · Views: 207
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.