#!/usr/bin/perl -w # Copyright (C) 2007 Michael Kurz michi.kurz (at) googlemail.com # Copyright (C) 2007 Petr Tomasek tomasek (#) etf,cuni,cz # Copyright (C) 2007 Carlos Corbacho cathectic (at) gmail.com # # Version 0.6.1 (2007-11-08) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 # of the License, or (at your option) any later version. # # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 5.004; use strict; use Fcntl; use POSIX; use File::Basename; sub initialize_ioports { sysopen (IOPORTS, "/dev/port", O_RDWR) or die "/dev/port: $!\n"; binmode IOPORTS; } sub close_ioports { close (IOPORTS) or print "Warning: $!\n"; } sub inb { my ($res,$nrchars); sysseek IOPORTS, $_[0], 0 or return -1; $nrchars = sysread IOPORTS, $res, 1; return -1 if not defined $nrchars or $nrchars != 1; $res = unpack "C",$res ; return $res; } # $_[0]: value to write # $_[1]: port to write # Returns: -1 on failure, 0 on success. sub outb { if ($_[0] > 0xff) { my ($package, $filename, $line, $sub) = caller(1); print "\n*** Called outb with value=$_[1] from line $line\n", "*** (in $sub). PLEASE REPORT!\n", "*** Terminating.\n"; exit(-1); } my $towrite = pack "C", $_[0]; sysseek IOPORTS, $_[1], 0 or return -1; my $nrchars = syswrite IOPORTS, $towrite, 1; return -1 if not defined $nrchars or $nrchars != 1; return 0; } sub wait_write { my $i = 0; while ((inb($_[0]) & 0x02) && ($i < 10000)) { sleep(0.01); $i++; } return -($i == 10000); } sub wait_read { my $i = 0; while (!(inb($_[0]) & 0x01) && ($i < 10000)) { sleep(0.01); $i++; } return -($i == 10000); } sub wait_write_ec { wait_write(0x66); } sub wait_read_ec { wait_read(0x66); } sub send_ec { if (!wait_write_ec()) { outb($_[0], 0x66); } if (!wait_write_ec()) { outb($_[1], 0x62); } } sub write_ec { if (!wait_write_ec()) { outb(0x81, 0x66 ); } if (!wait_write_ec()) { outb($_[0], 0x62); } if (!wait_write_ec()) { outb($_[1], 0x62); } } sub read_ec { if (!wait_write_ec()) { outb(0x80, 0x66 ); } if (!wait_write_ec()) { outb($_[0], 0x62); } if (!wait_read_ec()) { inb(0x62); } } sub write_kc { if (!wait_write(0x64)) { outb($_[0], 0x64); } if (!wait_write(0x64)) { outb($_[1], 0x60); } } sub print_regs { initialize_ioports(); my @arr = ("00","10","20","30","40","50","60","70","80","90","A0","B0","C0","D0","E0","F0", ""); my $i = 0; my $t = 0; print "\n \t00\t01\t02\t03\t04\t05\t06\t07\t|\t08\t09\t0A\t0B\t0C\t0D\t0E\t0F\n"; print " \t__\t__\t__\t__\t__\t__\t__\t__\t|\t__\t__\t__\t__\t__\t__\t__\t__\n"; print "00 |\t"; for ($i = 0; $i < 256; $i++) { $t = read_ec($i); print $t; print "\t"; if ((($i + 1) % 8) == 0){ if ((($i + 1) % 16) == 0) { if ($i != 255) { print "\n$arr[(($i-(($i + 1) % 16)) / 16) + 1] |\t"; } } else { print "|\t"; } } } print "\n"; close_ioports(); } sub write_temp { initialize_ioports(); write_ec($_[0],$_[1]); close_ioports(); } sub testnum { my $i; for ($i = 0; $i<256;$i++) { if ($_[0] eq "$i") { return 1 }; } return 0; } my $ii; if (!$ARGV[0]){ print "wrong arguments!\n"; print "usage:\n"; print "\'probook_ec regs\' \t\t\t\tdumps all ec registers\n"; print "\'probook_ec ledon\' \t\t\t\tswitch on 'mail LED' (WMID)\n"; print "\'probook_ec ledoff\' \t\t\t\tswitch off 'mail LED' (WMID)\n"; print "\'probook_ec getled\' \t\t\t\tget 'mail LED' status (WMID)\n"; print "\'probook_ec getled2\' \t\t\t\tget 'mail LED' status(AMW0)\n"; print "\'probook_ec getwireless\' \t\t\t\tget 'wireless' status (AMW0)\n"; print "\'probook_ec gettouch\' \t\t\t\tis the touchpad disabled?\n"; print "\'probook_ec setfanthresh \' \t\t\t\tset temperature threshhold to , DANGEROUS!\n"; print "\'probook_ec getfanthresh\' \t\t\t\tget temperature threshhold\n"; print "\'probook_ec \' \tfor setting a temperature\n"; print "where is from 0-7, and is from 0-255\n"; print "\'probook_ec ?= \' \t\tQuery register's value\n"; print "\'probook_ec := \' \tSet register's value\n"; print "\'probook_ec +f \' \tOr register's value with val (to set flags)\n"; print "\'probook_ec -f \' \tAnd register's value with ~val (to clear flags)\n"; print "\'forcekc\' \tTry all possible values on writeable RAM of keyboard controller\n"; print "\'kcw \' \tWrite a command and a value to the keyboard controller\n"; } elsif ($ARGV[0] eq "regs") { print_regs(); } elsif ($ARGV[0] eq "getled") { # TM2490 only (WMID) initialize_ioports(); if (read_ec(0x9f)&0x01) { print "Mail LED on\n"; } else { print "Mail LED off\n"; } close_ioports(); } elsif ($ARGV[0] eq "getled2") { # Aspire 5020 only (AMW0) initialize_ioports(); if (read_ec(0x0A)&0x80) { print "Mail LED on\n"; } else { print "Mail LED off\n"; } close_ioports(); } elsif ($ARGV[0] eq "getwireless") { # Aspire 5020 only (AMW0) initialize_ioports(); if (read_ec(0x0A)&0x4) { print "Wireless on\n"; } else { print "Wireless off\n"; } close_ioports(); } elsif ($ARGV[0] eq "gettouch") { # TM2490 only - needs testing initialize_ioports(); if (read_ec(0x9e)&0x08) { print "touchpad disabled\n"; } else { print "touchpad enabled\n"; } close_ioports(); } elsif ($ARGV[0] eq "?=") { initialize_ioports(); my $r = hex($ARGV[1]); printf("REG[0x%02x] == 0x%02x\n", $r, read_ec($r)); close_ioports(); } elsif ($ARGV[0] eq ":=") { initialize_ioports(); my $r = hex($ARGV[1]); my $f = hex($ARGV[2]); my $val = read_ec($r); #printf("REG[0x%02x] == 0x%02x\n", $r, $val); #printf("REG[0x%02x] := 0x%02x\n", $r, $f); write_ec( $r, $f); #printf("REG[0x%02x] == 0x%02x\n", $r, read_ec($r)); #echo "$r:$f\n" >> regs_set close_ioports(); } elsif ($ARGV[0] eq "FANCTL") { initialize_ioports(); write_ec(0x22,1); write_ec(0x26,0x1F); #write_ec(0x2F,0xFF); #printf("REG[0x%02x] == 0x%02x\n", 0x1E, read_ec(0x1E)); close_ioports(); #`notify-send FANOFF`; } elsif ($ARGV[0] eq "FANOFF") { initialize_ioports(); write_ec(0x22,1); write_ec(0x26,0x1F); write_ec(0x2F,0xFF); #printf("REG[0x%02x] == 0x%02x\n", 0x1E, read_ec(0x1E)); close_ioports(); #`notify-send FANOFF`; } elsif ($ARGV[0] eq "FANRST") { initialize_ioports(); write_ec(0x22,0x01); write_ec(0x26,0x00); #printf("REG[0x%02x] == 0x%02x\n", 0x22, read_ec(0x22)); close_ioports(); } elsif ($ARGV[0] eq "+f") { initialize_ioports(); my $r = hex($ARGV[1]); my $f = hex($ARGV[2]); my $val = read_ec($r); printf("REG[0x%02x] == 0x%02x\n", $r, $val); printf("REG[0x%02x] := 0x%02x\n", $r, $val | $f); write_ec( $r, $val | $f); printf("REG[0x%02x] == 0x%02x\n", $r, read_ec($r)); close_ioports(); } elsif ($ARGV[0] eq "-f") { initialize_ioports(); my $r = hex($ARGV[1]); my $f = hex($ARGV[2]); my $val = read_ec($r); printf("REG[0x%02x] == 0x%02x\n", $r, $val); printf("REG[0x%02x] := 0x%02x\n", $r, $val & ~$f); write_ec( $r, $val & ~$f); printf("REG[0x%02x] == 0x%02x\n", $r, read_ec($r)); close_ioports(); } elsif ($ARGV[0] eq "ledon") { # TM2490 only - needs testing initialize_ioports(); if (!wait_write(0x64)) { outb(0x59, 0x64); } if (!wait_write(0x64)) { outb(0x92, 0x60); } close_ioports(); } elsif ($ARGV[0] eq "ledoff") { # TM2490 only - needs testing initialize_ioports(); if (!wait_write(0x64)) { outb(0x59, 0x64); } if (!wait_write(0x64)) { outb(0x93, 0x60); } close_ioports(); } elsif ($ARGV[0] eq "getfanthresh") { initialize_ioports(); $ii=read_ec(0xa9); close_ioports(); print "Temperature threshhold: $ii (celsius)\n"; } elsif (($ARGV[0] eq "setfanthresh") && testnum($ARGV[1])) { write_temp(0xA9,$ARGV[1]); } elsif ($ARGV[0] eq "setbright") { # Aspire 5020 only (AMW0) if ($ARGV[1] >= 0 && $ARGV[1] <= 15) { write_temp(0x83, $ARGV[1]); } else { print "second argument must be a number between 0 and 15\n"; } } elsif ($ARGV[0] eq "forcekc") { # Be smart - we only send the commands for writing to keyboard RAM initialize_ioports(); my ($kbdata, $cont, $kbreg); for ($kbreg = 0x40; $kbreg <= 0x5f; $kbreg++) { for ($kbdata = 0; $kbdata < 256; $kbdata++) { write_kc($kbreg, $kbdata); print sprintf("%0#4x", $kbreg), ", ", sprintf("%0#4x", $kbdata), "\n"; print "Continue? y/n: "; $cont = ; if ($cont eq "n") { last; } } } close_ioports(); } elsif ($ARGV[0] eq "kcw") { initialize_ioports(); write_kc($ARGV[1], $ARGV[2]); close_ioports(); } else { print "wrong arguments!\n"; }