Ambient Sensor Backlight Daemon

I am pasting this code here on this wiki in the hopes that it will be useful to others. I license it under the GPL version 3, and if you make changes to it, I'd love to see them:

What is it?
This is a daemon that I pieced together to watch the ambient light sensor, and to alter the back light in proportional response to it. It is very simple, and currently lacks options, which could easily be bolted on to control the ambient sensor thresholds, and perhaps a better form of jitter correction from the sensor. But for my purposes, it works, and I am providing it in the hope that you guys may find it ultimately useful for your purposes.

How does it work?
Answer? Very primitively. ;) It listens to the ambient light sensor which is attached to the SILABS I2C chip on the Joggler/OpenFrame units, acquires a sample, scales it to a more realistic curve, converts it to a brightness value, and sends the new brightness value to the backlight, after doing a little jitter correction (to avoid flickering).

Thanks
This code was pieced together with help of a code snippet that Andrew de Quincey wrote to query the ambient light sensor. Original code is here: https://code.google.com/p/adqmisc/source/browse/trunk/joggler/readlightsensor.c

Compiling
The code can easily be compiled on an x86 linux machine with the following command:

gcc -o joggler-backlight-ambient-sensor-daemon joggler-backlight-ambient-sensor-daemon.c

Running
To run, simply run the daemon, it will fork itself, and detach from the parent TTY, making it very useful for running as an init.d service, or as part of an X11 session script.

Source Code
static int quit = 0; static void daemonize (void) {  pid_t pid, sid; if (getppid == 1) return; pid = fork ; if (pid < 0) {      exit (1); }  if (pid > 0) {      exit (1); }  umask (0); sid = setsid ; if (sid < 0) {      exit (1); }   if ((chdir ("/")) < 0) {      exit (1); }  freopen ("/dev/null", "r", stdin); freopen ("/dev/null", "w", stdout); freopen ("/dev/null", "w", stderr); } void default_handler (int sig) {  quit = 1; } int file_exists (char *fileName) {  struct stat buf; int i = stat (fileName, &buf); /*   * File found */  if (i == 0) {      return 1; }  return 0; } int main (int argc, char *argv[]) {  unsigned char buf[5]; int fd, fd2; union i2c_smbus_data smbus_data; struct i2c_smbus_ioctl_data smbus_ioctl_data; unsigned int sensor_val; unsigned int brightness_val; unsigned int old_brightness_val; char cBrightness_val[5]; if (!file_exists ("/dev/i2c-0")) {      perror ("/dev/i2c-0"); exit (1); }   if (!file_exists ("/sys/class/backlight/openframe-bl/brightness")) {      perror ("/sys/class/backlight/openframe-bl/brightness"); exit (1); }   daemonize ; signal (SIGINT, default_handler); signal (SIGTERM, default_handler); signal (SIGKILL, default_handler); signal (SIGHUP, default_handler); fd = open ("/dev/i2c-0", O_RDWR); if (fd < 0) {      perror ("Open i2c bus\n"); exit (1); }  fd2 = open ("/sys/class/backlight/openframe-bl/brightness", O_WRONLY); if (fd < 0) {      perror ("Open backlight power control."); exit (1); }  // set slave device to 8051 microprocessor if (ioctl (fd, I2C_SLAVE, 0x34)) {      perror ("Set slave i2c address\n"); exit (1); }   old_brightness_val = brightness_val = 0; while (quit == 0) {       // send the initial request smbus_data.block[0] = 2;	// count of bytes smbus_data.block[1] = 0; smbus_data.block[2] = 0; smbus_ioctl_data.read_write = 0; smbus_ioctl_data.command = 0x27; smbus_ioctl_data.size = I2C_SMBUS_BLOCK_DATA; smbus_ioctl_data.data = &smbus_data; if (ioctl (fd, I2C_SMBUS, &smbus_ioctl_data)) { 	 perror ("Send initial request\n"); exit (1); }      // wait for response smbus_data.block[0] = 4; smbus_ioctl_data.read_write = 1; while (1) { 	 if (ioctl (fd, I2C_SMBUS, &smbus_ioctl_data)) { 	     perror ("Read result\n"); exit (1); } 	 if (smbus_data.block[1] == 0x87) break; usleep (1000); }      if (smbus_data.block[1] != 0x87) { 	 fprintf (stderr, "Failed to get response\n"); exit (1); }      sensor_val = (smbus_data.block[3] << 8 | smbus_data.block[2]); brightness_val = ((sensor_val * 20) / 32); printf ("n: %u o: %u\n", brightness_val, old_brightness_val); // Simple jitter correction. if (abs (brightness_val - old_brightness_val) > 1) { 	  sprintf (cBrightness_val, "%u", brightness_val); printf ("%s\n", cBrightness_val); write (fd2, cBrightness_val, strlen (cBrightness_val)); }      old_brightness_val = brightness_val; usleep (1000); }   close (fd); close (fd2); return 0; }
 * 1) include 
 * 2) include 
 * 3) include 
 * 4) include 
 * 5) include 
 * 6) include 
 * 7) include 
 * 8) include 
 * 9) include 
 * 10) include 

Code last modified by: --Tschak (talk) 13:57, 5 August 2013 (GMT) -- Initial code drop.