hotkey.pl 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #!/usr/bin/perl -w
  2. # Hotkey handler v1.0
  3. # Handles hotkey events for Panasonic notebooks
  4. #
  5. # Copyright (C) 2004 David Bronaugh
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License version 2 as
  9. # published by the Free Software Foundation
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program; if not, write to the Free Software
  18. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. use strict;
  20. use POSIX qw(ceil floor);
  21. our($config);
  22. our($power_state);
  23. sub read_file {
  24. my($file) = @_;
  25. my($fh);
  26. my($contents) = "";
  27. if(open($fh, $file)) {
  28. $/ = undef;
  29. $contents = <$fh>;
  30. close($fh);
  31. } else {
  32. print "Couldn't open file " . $file . "!\n";
  33. }
  34. return $contents;
  35. }
  36. sub write_file {
  37. my($file, $contents) = @_;
  38. my($fh);
  39. if(open($fh, ">", $file)) {
  40. print $fh $contents;
  41. close($fh);
  42. return 1;
  43. } else {
  44. print "Couldn't open file " . $file . "!\n";
  45. return 0;
  46. }
  47. }
  48. sub get_amixer_control_info {
  49. my($control) = @_;
  50. my($cmd) = $config->{'mixer_program'} . " cget name='" . $control . "'";
  51. my(%info);
  52. my($fh, $field);
  53. my($contents) = "";
  54. if(open($fh, $cmd . "|")) {
  55. while(<$fh>) {
  56. chomp;
  57. $contents .= $_;
  58. }
  59. } else {
  60. print "Couldn't run command " . $cmd . "!\n";
  61. }
  62. $contents =~ m/\; ([^\s]*)/;
  63. foreach(split(/,/, $+)) {
  64. my(@foo) = split(/=/, $_);
  65. $info{$foo[0]} = $foo[1];
  66. }
  67. $contents =~ m/\: ([^\s]*)/;
  68. my(@foo) = split(/=/, $+);
  69. $info{$foo[0]} = [];
  70. @{$info{$foo[0]}} = split(/,/, $foo[1]);
  71. return \%info;
  72. }
  73. sub set_amixer_control_info {
  74. my($control, $values) = @_;
  75. my($cmd) = $config->{'mixer_program'} . " -q cset name='" . $control . "' " . $values;
  76. if(system($cmd) == 0) {
  77. return 1;
  78. } else {
  79. return 0;
  80. }
  81. }
  82. sub get_pcc_field {
  83. my($field) = @_;
  84. my($file) = $config->{'pcc_path'} . "/" . $power_state . "_" . $field;
  85. return read_file($file);
  86. }
  87. sub set_pcc_field {
  88. my($field, $contents) = @_;
  89. my($file) = $config->{'pcc_path'} . "/" . $power_state . "_" . $field;
  90. if(!write_file($file, $contents)) {
  91. print "Couldn't set pcc " . $field . " field (are you root?)\n";
  92. return 0;
  93. }
  94. return 1;
  95. }
  96. sub get_brightness {
  97. return (get_pcc_field("brightness_min"), get_pcc_field("brightness_max"), get_pcc_field("brightness"));
  98. }
  99. sub set_brightness {
  100. my($value) = @_;
  101. return set_pcc_field("brightness", $value);
  102. }
  103. sub get_mute {
  104. my($info) = get_amixer_control_info($config->{'mute_switch'});
  105. if($info->{'values'}[0] eq "on") {
  106. return 0;
  107. } elsif($info->{'values'}[0] eq "off") {
  108. return 1;
  109. } else {
  110. print "Error getting mute status!\n";
  111. return -1;
  112. }
  113. }
  114. sub set_mute {
  115. my($value) = @_;
  116. if($value == 0) {
  117. $value = "on";
  118. } elsif($value == 1) {
  119. $value = "off";
  120. }
  121. if(set_amixer_control_info($config->{'mute_switch'}, $value)) {
  122. return 1;
  123. } else {
  124. print "Couldn't set mute status!\n";
  125. return 0;
  126. }
  127. }
  128. sub get_volume {
  129. my($config) = @_;
  130. my($info) = get_amixer_control_info($config->{'volume_ctl'});
  131. return ($info->{'min'}, $info->{'max'}, $info->{'values'});
  132. }
  133. sub set_volume {
  134. my($values) = @_;
  135. return set_amixer_control_info($config->{'volume_ctl'}, join(",", @{$values}));
  136. }
  137. sub get_power_state {
  138. my($data) = read_file($config->{"ac_state"});
  139. if($data =~ /on-line/) {
  140. return "ac";
  141. } elsif($data =~ /off-line/) {
  142. return "dc";
  143. } else {
  144. print "Couldn't get power state! (is ACPI enabled?)\n";
  145. exit(1);
  146. }
  147. }
  148. sub adjust_brightness {
  149. my($adjust) = @_;
  150. my($min, $max, $bright) = get_brightness($config);
  151. my($threshold) = $config->{'max_bright_levels'};
  152. my($divisor) = 1;
  153. $bright -= $min;
  154. if($max - $min > $threshold) {
  155. $divisor = ($max - $min) / $threshold;
  156. }
  157. $bright = ceil($bright / $divisor);
  158. $bright += $adjust;
  159. $bright = floor($bright * $divisor);
  160. $bright += $min;
  161. if($bright < $min) {
  162. $bright = $min;
  163. }
  164. if($bright > $max) {
  165. $bright = $max;
  166. }
  167. if(!set_brightness($bright)) {
  168. print "Couldn't adjust brightness!\n";
  169. }
  170. return;
  171. }
  172. sub adjust_volume {
  173. my($increment) = @_;
  174. my($min, $max, $volume) = get_volume($config);
  175. $volume->[0] += $increment;
  176. $volume->[1] += $increment;
  177. $volume->[0] = ($volume->[0] < $min)?$min:$volume->[0];
  178. $volume->[1] = ($volume->[1] < $min)?$min:$volume->[1];
  179. $volume->[0] = ($volume->[0] > $max)?$max:$volume->[0];
  180. $volume->[1] = ($volume->[1] > $max)?$max:$volume->[1];
  181. if(!set_volume($volume)) {
  182. print "Couldn't set volume!\n";
  183. }
  184. return;
  185. }
  186. # Functions which implement hotkey functions directly
  187. sub down_brightness {
  188. adjust_brightness(-1);
  189. }
  190. sub up_brightness {
  191. adjust_brightness(1);
  192. }
  193. sub switch_monitor {
  194. #STUB
  195. }
  196. sub toggle_mute {
  197. my($mute) = get_mute();
  198. if($mute >= 0) {
  199. set_mute($mute ^ 1);
  200. }
  201. }
  202. sub volume_up {
  203. adjust_volume($config->{"volume_increment"})
  204. }
  205. sub volume_down {
  206. adjust_volume(-1 * $config->{"volume_increment"})
  207. }
  208. sub suspend_to_ram {
  209. # This space intentionally left blank (because it doesn't work here)
  210. }
  211. sub spin_down_hd {
  212. if(system("hdparm -q -y /dev/hda") != 0) {
  213. print "Error running hdparm -- is it installed?\n";
  214. }
  215. }
  216. sub suspend_to_disk {
  217. system("hwclock --systohc");
  218. write_file($config->{'suspend_control'}, "disk");
  219. system("hwclock --hctosys");
  220. }
  221. my($key) = $ARGV[3];
  222. my(%dispatch) = (
  223. "00000081" => \&down_brightness,
  224. "00000082" => \&up_brightness,
  225. "00000003" => \&switch_monitor,
  226. "00000084" => \&toggle_mute,
  227. "00000085" => \&volume_down,
  228. "00000086" => \&volume_up,
  229. "00000007" => \&suspend_to_ram,
  230. "00000089" => \&spin_down_hd,
  231. "0000000a" => \&suspend_to_disk
  232. );
  233. $config = {
  234. "pcc_path" => "/proc/acpi/pcc",
  235. "mixer_program" => "amixer",
  236. "ac_state" => "/proc/acpi/ac_adapter/AC/state",
  237. "mute_switch" => "Master Playback Switch",
  238. "volume_ctl" => "Master Playback Volume",
  239. "max_bright_levels" => 20,
  240. "volume_increment" => 2,
  241. "suspend_control" => "/sys/power/state"
  242. };
  243. $power_state = get_power_state();
  244. $dispatch{$key}();