123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- #!/usr/bin/perl -w
- # Hotkey handler v1.0
- # Handles hotkey events for Panasonic notebooks
- #
- # Copyright (C) 2004 David Bronaugh
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License version 2 as
- # published by the Free Software Foundation
- #
- # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- use strict;
- use POSIX qw(ceil floor);
- our($config);
- our($power_state);
- sub read_file {
- my($file) = @_;
- my($fh);
- my($contents) = "";
- if(open($fh, $file)) {
- $/ = undef;
- $contents = <$fh>;
- close($fh);
- } else {
- print "Couldn't open file " . $file . "!\n";
- }
- return $contents;
- }
- sub write_file {
- my($file, $contents) = @_;
- my($fh);
- if(open($fh, ">", $file)) {
- print $fh $contents;
- close($fh);
- return 1;
- } else {
- print "Couldn't open file " . $file . "!\n";
- return 0;
- }
- }
- sub get_amixer_control_info {
- my($control) = @_;
- my($cmd) = $config->{'mixer_program'} . " cget name='" . $control . "'";
- my(%info);
- my($fh, $field);
- my($contents) = "";
- if(open($fh, $cmd . "|")) {
- while(<$fh>) {
- chomp;
- $contents .= $_;
- }
- } else {
- print "Couldn't run command " . $cmd . "!\n";
- }
- $contents =~ m/\; ([^\s]*)/;
- foreach(split(/,/, $+)) {
- my(@foo) = split(/=/, $_);
- $info{$foo[0]} = $foo[1];
- }
- $contents =~ m/\: ([^\s]*)/;
- my(@foo) = split(/=/, $+);
- $info{$foo[0]} = [];
- @{$info{$foo[0]}} = split(/,/, $foo[1]);
- return \%info;
- }
- sub set_amixer_control_info {
- my($control, $values) = @_;
- my($cmd) = $config->{'mixer_program'} . " -q cset name='" . $control . "' " . $values;
- if(system($cmd) == 0) {
- return 1;
- } else {
- return 0;
- }
- }
- sub get_pcc_field {
- my($field) = @_;
- my($file) = $config->{'pcc_path'} . "/" . $power_state . "_" . $field;
- return read_file($file);
- }
- sub set_pcc_field {
- my($field, $contents) = @_;
- my($file) = $config->{'pcc_path'} . "/" . $power_state . "_" . $field;
- if(!write_file($file, $contents)) {
- print "Couldn't set pcc " . $field . " field (are you root?)\n";
- return 0;
- }
- return 1;
- }
- sub get_brightness {
- return (get_pcc_field("brightness_min"), get_pcc_field("brightness_max"), get_pcc_field("brightness"));
- }
- sub set_brightness {
- my($value) = @_;
- return set_pcc_field("brightness", $value);
- }
- sub get_mute {
- my($info) = get_amixer_control_info($config->{'mute_switch'});
- if($info->{'values'}[0] eq "on") {
- return 0;
- } elsif($info->{'values'}[0] eq "off") {
- return 1;
- } else {
- print "Error getting mute status!\n";
- return -1;
- }
- }
- sub set_mute {
- my($value) = @_;
- if($value == 0) {
- $value = "on";
- } elsif($value == 1) {
- $value = "off";
- }
- if(set_amixer_control_info($config->{'mute_switch'}, $value)) {
- return 1;
- } else {
- print "Couldn't set mute status!\n";
- return 0;
- }
- }
- sub get_volume {
- my($config) = @_;
- my($info) = get_amixer_control_info($config->{'volume_ctl'});
- return ($info->{'min'}, $info->{'max'}, $info->{'values'});
- }
- sub set_volume {
- my($values) = @_;
- return set_amixer_control_info($config->{'volume_ctl'}, join(",", @{$values}));
- }
- sub get_power_state {
- my($data) = read_file($config->{"ac_state"});
- if($data =~ /on-line/) {
- return "ac";
- } elsif($data =~ /off-line/) {
- return "dc";
- } else {
- print "Couldn't get power state! (is ACPI enabled?)\n";
- exit(1);
- }
- }
- sub adjust_brightness {
- my($adjust) = @_;
- my($min, $max, $bright) = get_brightness($config);
- my($threshold) = $config->{'max_bright_levels'};
- my($divisor) = 1;
- $bright -= $min;
- if($max - $min > $threshold) {
- $divisor = ($max - $min) / $threshold;
- }
- $bright = ceil($bright / $divisor);
- $bright += $adjust;
- $bright = floor($bright * $divisor);
- $bright += $min;
- if($bright < $min) {
- $bright = $min;
- }
- if($bright > $max) {
- $bright = $max;
- }
- if(!set_brightness($bright)) {
- print "Couldn't adjust brightness!\n";
- }
- return;
- }
- sub adjust_volume {
- my($increment) = @_;
- my($min, $max, $volume) = get_volume($config);
- $volume->[0] += $increment;
- $volume->[1] += $increment;
- $volume->[0] = ($volume->[0] < $min)?$min:$volume->[0];
- $volume->[1] = ($volume->[1] < $min)?$min:$volume->[1];
- $volume->[0] = ($volume->[0] > $max)?$max:$volume->[0];
- $volume->[1] = ($volume->[1] > $max)?$max:$volume->[1];
- if(!set_volume($volume)) {
- print "Couldn't set volume!\n";
- }
- return;
- }
- # Functions which implement hotkey functions directly
- sub down_brightness {
- adjust_brightness(-1);
- }
- sub up_brightness {
- adjust_brightness(1);
- }
- sub switch_monitor {
- #STUB
- }
- sub toggle_mute {
- my($mute) = get_mute();
- if($mute >= 0) {
- set_mute($mute ^ 1);
- }
- }
- sub volume_up {
- adjust_volume($config->{"volume_increment"})
- }
- sub volume_down {
- adjust_volume(-1 * $config->{"volume_increment"})
- }
- sub suspend_to_ram {
- # This space intentionally left blank (because it doesn't work here)
- }
- sub spin_down_hd {
- if(system("hdparm -q -y /dev/hda") != 0) {
- print "Error running hdparm -- is it installed?\n";
- }
- }
- sub suspend_to_disk {
- system("hwclock --systohc");
- write_file($config->{'suspend_control'}, "disk");
- system("hwclock --hctosys");
- }
- my($key) = $ARGV[3];
- my(%dispatch) = (
- "00000081" => \&down_brightness,
- "00000082" => \&up_brightness,
- "00000003" => \&switch_monitor,
- "00000084" => \&toggle_mute,
- "00000085" => \&volume_down,
- "00000086" => \&volume_up,
- "00000007" => \&suspend_to_ram,
- "00000089" => \&spin_down_hd,
- "0000000a" => \&suspend_to_disk
- );
- $config = {
- "pcc_path" => "/proc/acpi/pcc",
- "mixer_program" => "amixer",
- "ac_state" => "/proc/acpi/ac_adapter/AC/state",
- "mute_switch" => "Master Playback Switch",
- "volume_ctl" => "Master Playback Volume",
- "max_bright_levels" => 20,
- "volume_increment" => 2,
- "suspend_control" => "/sys/power/state"
- };
- $power_state = get_power_state();
- $dispatch{$key}();
|