Posts Tagged ‘x61t’
awesome 3.2 battery monitoring widget
Lua code to monitor battery status through thinkpad’s smapi. It generates, e.g., [-] 02:15 (86%) if the battery is 86% full, discharging and has an estimated remaining time of 2 hours 15 mins, [+] 00:30 (50%) if it’s expected to be fully charged in 30 mins, etc. Also, use 100:green:50:yellow:20:red bg color setup. Use with e.g. a textbox widget.
function read_file (path, ...)
-- read a text file and return its content
-- ... can be, e.g., "*n" for a number or "*a" for all, etc.
local f = io.open(path)
local result = f:read(...)
f:close()
return result
end
function format_time(num)
local h,m = math.floor(num/60),num%60
return string.format("%02d:%02d", h,m)
end
function battery_status (bat)
-- bat should be, e.g., BAT0
local path = "/sys/devices/platform/smapi/"
if read_file(path .. bat .. "/installed") == "0" then
-- battery not installed
return "[N/A]"
end
local percent = tonumber(read_file(path .. bat .. "/remaining_percent"))
local state = read_file(path .. bat .. "/state")
local msg
if state == "charging" then
msg = "[+] " .. format_time(
read_file(path .. bat .. "/remaining_charging_time"))
elseif state == "discharging" then
msg = "[-] " .. format_time(
read_file(path .. bat .. "/remaining_running_time"))
elseif state == "idle" then
msg = "[ ]"
else
msg = "*" .. state .. "* "
end
local pre,post
if percent > 50 then
pre,post = '<span font="mono" bgcolor="green" color="black">', '</span>'
elseif percent > 20 then
pre,post = '<span font="mono" bgcolor="yellow" color="black">','</span>'
else
pre,post = '<span font="mono" bgcolor="red" color="yellow">','</span>'
end
return pre .. msg .. " (" .. percent .. "%)" .. post
end
-- print(battery_status("BAT0"))
quick note on x61t tuxonice issues
- dhcpcd dies after resume
fix: add an OnResume entry in /etc/hibernateOnResume scripts - stylus geometry messed up. also reproducible if
- manually rotate to another direction by
xrandr -o right && xsetwacom set stylus rotate CW - switch to some VT and back
- now one or more of {Top/Bottom}{X/Y} is wrong
there’s no problem if both xrandr and xsetwacom are in normal orientation, so probably a problem of wacom driver. Never realized it before as I’ve never switched to VT from tablet mode, but IIRC hibernate-script has this trick of switching to some ficticious VT and then back to ensure X is displayed on resume, and so the weird problem.
fix: manually by DISPLAY=:0 xsetwacom set stylus xydefault for device named stylus, etc. . Here’s a script to reset all available devices:
#!/bin/sh # rst: reset tablet geometry export DISPLAY=:0.0 devices=`xsetwacom list dev | cut -f1 -d' '` for d in $devices; do xsetwacom set $d xydefault doneI just bound it to the tiny little reset button on the tablet panel (keycode 199 as revealed by showkey) in actkbd.
## tiny little button, code 199 199 :rep :grab,noexec : 199 :rel :grabbed,ungrab :/home/bin/rst 199 :rel :ungrabbed :/home/bin/rst
- manually rotate to another direction by
actkbd
After my X61 tablet arrived, I needed a keyboard daemon that can take care of hotkey events both under console and in X (I’d like to have control of brightness and volume level, etc., in both). After some search, I settled with actkbd, which to me is a good balance of speed (pure C), functionality and complexity (take a look at, say, gizmo daemon). It monitors evdev keyboard (e.g., /dev/input/event1. so need kernel evdev support), and reponds according to a config file.
- Simple config example
A typical snippet in actkbd’s configuration file looks like this:
## mute key # hard mute if pressed long, otherwise toggle #code event attrib ext command 113 :rep :grab,noexec : 113 :rel :grabbed,ungrab :/home/bin/mute 113 :rel :ungrabbed :/home/bin/toggle # hard unmute (all muters)if shift+ 42+113:key::/home/bin/unmute Master Headphone SpeakerWith the helper scripts mute and toggle, this snippet either mutes or toggles the mute status of my soundcard depending on whether the Mute key (113) is just pressed or hold for a while.
Each config line has four fields,
- code: keycode as shown in showkey. multiple keys concatenated by ‘+’
- event: one of key, rep (repeat), and rel (release)
- attrib: (un)grab to block/release device from/to other programs, (un)grabbed to ensure action taking place only when (un)grabbed. This is the major featureset of actkbd. For a complete list, see the official README
- ext command: external command to call. It could be better if actkbd can export relevant info as some sort of variable that can be passed to external commands (so that e.g. a general purpose hook program can handle all events).
- Tablet screen rotation
The X61 tablet has some buttons alongside the tablet panel. When in tablet mode, these are the only keys accessible as the whole keyboard is covered under the tablet, so we want to use these keys wisely. With an external helper script rotate, the following snippet will- reset screen to normal orientation if “rotate” button hold for long
- rotate screen 90 degrees clock-wise if “rotate” button is merely pressed
- rotate screen to a relative orientation (left, right, or invert) if the “rotate” button is hold while the orientation arrow keys are pressed
## grab as `clean' bit, detectable # 191: "rotate" button # rotate clockwise if only hold short 191 :key :grab,noexec : 191 :rel :grabbed,ungrab :/home/bin/rotate ## 192 as `hold' bit 191:rep:grabbed,set(192),noexec: # reset orientation if hold long 191+192 :rel :grabbed,ungrab,unset(192) :/home/bin/rotate monitor 191+192 :rel :ungrabbed,unset(192),noexec : ## u/d/l/r/enter: 103/108/105/106/28 # u/d: invert; l/r: rotate; enter: pin down # relative rotation 191+103 :rel :ungrab :/home/bin/rotate i 191+108 :rel :ungrab :/home/bin/rotate i 191+105 :rel :ungrab :/home/bin/rotate l 191+106 :rel :ungrab :/home/bin/rotate r 191+28 :rel :ungrab :/home/bin/rotate c 191+192+103 :rel :ungrab :/home/bin/rotate i 191+192+108 :rel :ungrab :/home/bin/rotate i 191+192+105 :rel :ungrab :/home/bin/rotate l 191+192+106 :rel :ungrab :/home/bin/rotate r 191+192+28 :rel :ungrab :/home/bin/rotate cHere, the trick is to use ‘grab’ to indicate whether the current 191 key event is being processed or not, and use the ficticious 192 key to indicate whether it’s a long hold or a short one.
- LCD brightness control
Similar trick can be used to control screen brightness. The master button to use now is “application” button right next to the “rotate” button.- short and long hold: reserverd for future use (:D)
- app + up/down: turn brightness up/down by 1.
app + left/right: turn brightness to min/max
app + enter: turn brightness midway (7)
## similar `grab' and `hold' trick, but for 152 152 :key :grab,noexec : 152 :rel :grabbed,ungrab :echo "short press" 152 :rep :grabbed,set(153),noexec : 152+153 :rel :grabbed,ungrab,unset(153) :echo "long press" 152+153 :rel :ungrabbed,unset(153),noexec : ## adjust brightness 152+103 :rel :ungrab :echo up > /proc/acpi/ibm/brightness 152+108 :rel :ungrab :echo down > /proc/acpi/ibm/brightness 152+105 :rel :ungrab :echo level 0 > /proc/acpi/ibm/brightness 152+106 :rel :ungrab :echo level 15 > /proc/acpi/ibm/brightness 152+28 :rel :ungrab :echo level 7 > /proc/acpi/ibm/brightness 152+153+103 :rel :ungrab :echo up > /proc/acpi/ibm/brightness 152+153+108 :rel :ungrab :echo down > /proc/acpi/ibm/brightness 152+153+105 :rel :ungrab :echo level 0 > /proc/acpi/ibm/brightness 152+153+106 :rel :ungrab :echo level 15 > /proc/acpi/ibm/brightness 152+153+28 :rel :ungrab :echo level 7 > /proc/acpi/ibm/brightness - Microsoft Natural Ergonomic Keyboard 4000 (NE4k)
The problem with NE4k, which I use on my desktop, is that kernel exports it as two devices, one for the normal keys (a,o,e,u,… yes I use dvorak), say /dev/input/event3, and one for all the multimedia/net/hot keys, say /dev/input/event4. Since each process of actkbd can only monitor a single device, there will be no way to capture something like shift+mute, which involves both devices. Even if you run two actkbd daemons monitoring both, there’s no easy way for them to crosstalk. A possible workaround is to somehow combine the two devices into one, or even one further step back, to “redirect” all events from one device to the other. Maybe I was using the wrong keywords, but a google search doesn’t reveal any such things, so here comes the stitch works: a simple “event replicator” which basically is a stripped down version of actkbd. Just gcc evpipe.c -o evpipe, and use ./evpipe /dev/input/event{4,3} to redirect event4 to event3. NB: although I “grabbed” the incoming device, it’d be a good idea to redirect the hotkey device to the standard keyboard instead of the other way around, so that even if something goes wrong you’ll still have a usable device. (I made the mistake of not “grabbing” the incoming device AND redirected the normal keyboard to the hotkeys, making each keypress of “a” generating “aa” and ended up having to kill the process from my laptop)./******************************************* * evpipe.c: * * basically c-k c-y of linux.c in actkbd. * * NO ERROR HANDLING!! (almost) * *******************************************/ #include <linux/input.h> #include <stdio.h> #include <signal.h> #include <sys/ioctl.h> static FILE *from; static FILE *to; struct input_event ev; int grabbed=0; int main(int argc, char* argv[]){ pipe(argv[1],argv[2]); } /* Allow SIGTERM to cause graceful termination */ void close_and_quit(int signum) { if (to) fclose(to); if (from) fclose(from); if (grabbed) ungrab_dev(); return; } int pipe(char* ffrom, char* fto){ signal(SIGTERM, close_and_quit); signal(SIGINT, close_and_quit); from = fopen(ffrom, "a+"); if (from == NULL) return 1; to = fopen(fto, "a+"); if (to == NULL) return 2; grab_dev(); while (get_key() == 0) { snd_key(); // printf("."); // fflush(stdout); } //fclose(to); //fclose(from); } int get_key(){ int ret; do { ret = fread(&ev, sizeof(ev), 1, from); if (ret < 1) return -1; /* read error */ } while (ev.type != EV_KEY); return 0; } int snd_key() { int ret; ret = fwrite(&ev, sizeof(ev), 1, to); fflush(to); if (ret < 1) return -2; /* write error */ return 0; } int grab_dev() { int ret; if (grabbed) return 0; ret = ioctl(fileno(from), EVIOCGRAB, (void *)1); if (ret == 0) grabbed = 1; // else // lprintf("Error: could not grab %s: %s\n", device, strerror(errno)); return ret; } int ungrab_dev() { int ret; if (!grabbed) return 0; ret = ioctl(fileno(from), EVIOCGRAB, (void *)0); if (ret == 0) grabbed = 0; // else // lprintf("Error: could not ungrab %s: %s\n", device, strerror(errno)); return ret; }Before I forget, there’s also a ruby evdev binding. I myself am not using the code above, nor the ruby evdev binding, since I don’t urgently need shift + VolUp, etc.
sd card reader on Thinkpad X61 tablet
need the following kernel modules before it’ll show up in fdisk -l:
sdhci_pci (depends on sdhci)
mmc_block (depends on mmc_core)
It is amusing to read the description of the mmc_block module though
This selects the disabler for the Ricoh MMC Controller. This proprietary controller is unnecessary because the SDHCI driver supports MMC cards on the SD controller, but if it is not disabled, it will steal the MMC cards away – rendering them useless. It is safe to select this driver even if you don’t have a Ricoh based card reader.