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