ACC SHELL
#!/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}();
ACC SHELL 2018