Hello,

I have modified Nicolas Boichat's excellent backlight script; while the
substance of it remains the same, I have added help options,
percentage-based lighting increases, and some other things. Since I'm
now using it on my computer, I thought I'd share it with you folks in
case you're interested. Attached is mblight.c.

I'm compiling it with:

gcc -I/usr/src/linux/include mblight.c -o mblight -lpci

-- Erik
/*
 * Apple Macbook Pro LCD backlight control
 *
 * Written in 2006 Nicolas Boichat <[EMAIL PROTECTED]>
 * Modified in 2007 by Erik Osheim <[EMAIL PROTECTED]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdio.h>
#include <sys/io.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pci/pci.h>

/* Some nice macros */
#define INREG(addr) readl(memory + addr)
#define OUTREG(addr,val) writel(val, memory + addr)
#define STREQ(s1, s2) (strcmp(s1, s2) == 0)
#define MIN(i1, i2) (i1 < i2 ? i1 : i2)
#define MAX(i1, i2) (i1 > i2 ? i1 : i2)

/* global pointer to our device's memory */
char *memory;

static inline unsigned int readl(const volatile void *addr) {
    return *(volatile unsigned int*) addr;
}

static inline void writel(unsigned int b, volatile void *addr) {
    *(volatile unsigned int*) addr = b;
}

unsigned char read_backlight() {
    return INREG(0x7af8) >> 8;
}

void write_backlight(unsigned char value) {
    OUTREG(0x7af8, 0x00000001 | ((unsigned int)value << 8));
}

int usage(char* argv0, int exit) {
    printf("usages: %s               display current brightness\n", argv0);
    printf("        %s  [0-255]      set brightness to amount\n", argv0);
    printf("        %s %%[0-100]      set brightness to percentage\n", argv0);
    printf("        %s +[0-255]      increase brightness by amount\n", argv0);
    printf("        %s -[0-255]      reduce brightness by amount\n", argv0);
    printf("        %s  [-h|--help]  print this message and exit\n", argv0);
    return exit;
}

int main(int argc, char** argv) {
    /* See if the user asked for help */
    int i;
    for(i=1; i < argc; i++) {
        if(STREQ(argv[i], "-h") || STREQ(argv[i], "--help")) {
            return usage(argv[0], 1);
        }
    }

    /* More than one argument is not allowed */
    if(argc > 2) {
        printf("too many arguments given\n");
        return usage(argv[0], 1);
    }

    /* Initialize the PCI devices */
    struct pci_access *pacc = pci_alloc();
    pci_init(pacc);
    pci_scan_bus(pacc);

    /* Iterate over all devices, looking for the ATI X1600 */
    long address = 0;
    long length = 0;
    struct pci_dev *dev = pacc->devices;
    while(dev) {
        pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES);
        if (dev->vendor_id == 0x1002 && dev->device_id == 0x71c5) {
            address = dev->base_addr[2];
            length = dev->size[2];
            break;
        }
        dev = dev->next;
    }
    pci_cleanup(pacc);

    if (!address) {
        printf("failed to detect ATI X1600\n");
        return 2;
    }

    int fd = open("/dev/mem", O_RDWR);
    if (fd < 0) {
        perror("cannot open /dev/mem");
        return 3;
    }

    /* Initialize our global pointer to the device's memory */
    memory = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, address);
    if (memory == MAP_FAILED) {
        perror("mmap failed");
        return 3;
    }

    /* Is it really necessary? */
    OUTREG(0x4dc, 0x00000005);
    OUTREG(0x7ae4, INREG(0x7ae4));

    if (argc == 2) {
        /* Figure out what kind of operation the user wants to do */
        char op = ' ';
        char *s_amount = argv[1];
        if (argv[1][0] == '+' || argv[1][0] == '-' || argv[1][0] == '%') {
            op = argv[1][0];
            s_amount = &argv[1][1];
        }

        /* Get the actual integer value the user input (without - or +) */
        char* endptr;
        int amount = strtol(s_amount, &endptr, 10);

        /* Read the integer value of the argument, or report an error */
        if(endptr[0]) {
            printf("invalid argument '%s' (should be integer)\n", s_amount);
            return usage(argv[0], 1);
        }

        /* Do the adjustment, or report an error */
        if(op == '%') {
            if(amount < 0 || amount > 100) {
                printf("invalid argument '%s' (should be 0-100)\n", s_amount);
                return usage(argv[0], 1);
            }
            write_backlight(255 * amount / 100);
        } else if(amount < 0 || amount > 255 || endptr[0]) {
            printf("invalid argument '%s' (should be 0-255)\n", s_amount);
            return usage(argv[0], 1);
        } else if(op == '+') {
            write_backlight(MIN(read_backlight() + amount, 255));
        } else if(op == '-') {
            write_backlight(MAX(read_backlight() - amount, 0));
        } else {
            write_backlight(amount);
        }
    } else {
        /* Show the user the current setting */
        printf("current value: %d\n", read_backlight());
    }

    munmap(memory, length);
    close(fd);

    return 0;
}
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Mactel-linux-devel mailing list
Mactel-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mactel-linux-devel

Reply via email to