#include #include #include #include #include #include #include #include #include #include #include #include #include gchar *mixername = NULL; gchar *fbname = NULL; gboolean use_alsa = FALSE; enum actions { VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE, BACKLIGHT_UP, BACKLIGHT_DOWN }; struct poptOption options[] = { { "alsa", 'a', POPT_ARG_NONE, &use_alsa, 0, "Use ALSA mixer instead of OSS mixer", NULL }, { "mixer", 'm', POPT_ARG_STRING, &mixername, 0, "Use a device other than /dev/mixer for the volume control", "MIXER" }, { "fb", 'f', POPT_ARG_STRING, &fbname, 0, "Use a device other than /dev/fb0 for the backlight control", "FB" }, { NULL, 0, 0, NULL, 0 } }; static void quit(gint i, gchar *msg) { g_print("%s\n",msg); exit(i); } static void do_signal(gint signum) { gchar *msg; /* There's a leak here, but we don't care since we're * quitting the app */ g_strdup_printf("Caught signal %d", signum); quit(signum == SIGTERM ? 0 : -1, msg); } static int open_action_dev(gchar *device) { int fd; fd = open(device, O_RDONLY); return fd; } static void volume_actions_oss(int action) { int actionfd; int vol; #define CHANNELS 2 int channel[CHANNELS]={SOUND_MIXER_VOLUME,SOUND_MIXER_SPEAKER}; int channelidx=0; #define CHANNEL channel[channelidx] int mute=0; int parm; actionfd = open_action_dev(mixername); switch (action) { #ifdef SINGLE_CHANNEL case VOLUME_UP: ioctl(actionfd,MIXER_READ(CHANNEL),&vol); mute=1; vol=(vol&0xff)+8; if(vol>100) vol=100; vol|=vol<<8; parm=vol; break; case VOLUME_DOWN: ioctl(actionfd,MIXER_READ(CHANNEL),&parm); if(parm||mute){ mute=0; if(parm) vol=parm; vol=(vol&0xff)-8; if(vol<0) vol=0; vol|=vol<<8; } else { mute=1; } parm=vol; break; case VOLUME_MUTE: if(!mute){ parm=0; mute=1; } else { parm=vol; mute=0; } break; #else case VOLUME_UP: vol=(vol&0xff)+8; if(vol>100) vol=100; vol|=vol<<8; break; case VOLUME_DOWN: vol=(vol&0xff)-8; if(vol<0) vol=0; vol|=vol<<8; break; case VOLUME_MUTE: parm=0; ioctl(actionfd,MIXER_WRITE(CHANNEL),&parm); parm=0; ioctl(actionfd,MIXER_WRITE(CHANNEL),&parm); channelidx = (channelidx+1)%CHANNELS; #endif } ioctl(actionfd,MIXER_WRITE(CHANNEL),&parm); close(actionfd); } static void backlight_actions(int action) { int actionfd; __u32 bklight; actionfd = open_action_dev(fbname); ioctl(actionfd,FBIOGET_BACKLIGHT,&bklight); switch(action) { case BACKLIGHT_UP: bklight++; if(bklight>FBBACKLIGHT_MAX) bklight=FBBACKLIGHT_MAX; break; case BACKLIGHT_DOWN: if(bklight>FBBACKLIGHT_OFF) bklight--; break; } ioctl(actionfd,FBIOSET_BACKLIGHT,&bklight); close(actionfd); } int main(int argc, const char **argv) { poptContext pctx; const char **args; int eventfd; //,actionfd; struct input_event inp; struct sigaction sigpipe = { {SIG_IGN}, {{0}}, SA_RESTART, 0 }; struct sigaction sigterm = {{do_signal}, {{0}}, SA_RESTART , 0 }; short ids[4]; char *filename; //[50]; // int vol; #define CHANNELS 2 int channel[CHANNELS]={SOUND_MIXER_VOLUME,SOUND_MIXER_SPEAKER}; int channelidx=0; #define CHANNEL channel[channelidx] // int mute=0; int parm; // __u32 bklight; int i; pctx = poptGetContext(NULL, argc, argv, options, 0); args = poptGetArgs(pctx); if (mixername == NULL) { if (use_alsa == FALSE) mixername = g_strdup("/dev/mixer"); else g_print("somebody please fix this ;)\n"); } if (fbname == NULL) fbname = g_strdup("/dev/fb0"); if(sigaction(SIGTERM, &sigterm, 0)) quit(-1, "could not install SIGTERM handler"); if(sigaction(SIGPIPE, &sigpipe, 0)) quit(-1, "could not install SIGPIPE handler"); for(i=0;i<32;i++){ filename = g_strdup_printf("/dev/input/event%i",i); eventfd = open(filename, O_RDONLY); if(eventfd>=0){ ioctl(eventfd, EVIOCGID, ids); if((ids[2]&0xfff)==0x71f){ syslog(LOG_INFO, "Powerbook Button device found at event%i.\n",i); break; } #ifdef DEBUG fprintf(stderr,"[%x] ids - %x %x %x %x\n",i,ids[0],ids[1],ids[2],ids[3]); #endif close(eventfd); eventfd=-1; } #ifdef DEBUG else{ fprintf(stderr,"[%x] nil\n",i); } #endif } if(eventfd<0){ syslog(LOG_INFO, "Powerbook Button device not found.\n"); exit(-1); } #if 1 { int pid = fork(); if(pid < 0){ printf("Couldn't fork\n"); exit(-1); } if (pid > 0) quit(0, "parent exiting [note PID]"); chdir("/"); setsid(); close(0); close(1); close(2); } #endif while(read(eventfd,&inp,sizeof(inp))){ if(inp.value) switch(inp.code){ case KEY_MUTE: if(inp.value==2) continue; if (!use_alsa) volume_actions_oss(VOLUME_MUTE); else g_print("fixme\n"); break; case KEY_VOLUMEDOWN: if (!use_alsa) volume_actions_oss(VOLUME_DOWN); else g_print("fixme\n"); break; case KEY_VOLUMEUP: if (!use_alsa) volume_actions_oss(VOLUME_UP); else g_print("fixme\n"); break; case KEY_BRIGHTNESSDOWN: backlight_actions(BACKLIGHT_UP); break; case KEY_BRIGHTNESSUP: backlight_actions(BACKLIGHT_DOWN); break; } } close(eventfd); }