Sunday, April 26, 2009

Lenovo Thinkpad X61 Tablet

Bought a Lenovo Thinkpad X61 Tablet recently. Will post some usage tips. Most useful links:

http://www.thinkwiki.org/wiki/ThinkWiki

Evtouch configuration

This article is mainly for Tablet Classmate PC.

Evtouch is a Xorg (X window system) input driver for touchscreen device with Linux kernel input/event driver. For example some USB touchscreen device with USBHID class.

To use evtouch Xorg driver, xorg should be setup as follow:


--------------------------------------------------------------------------------
Section "InputDevice"
Identifier "TOUCH"
Driver "evtouch"
Option "Device" "/dev/input/by-path/pci-0000:00:1d.3-usb-0:1:1.0-event-"

Option "DeviceName" "touchscreen"
Option "ReportingMode" "Raw"
Option "MoveLimit" "10"
Option "SendCoreEvents" "On"
# Option "Calibrate" "1"
Option "MinX" "1"
Option "MinY" "1"
Option "MaxX" "4090"
Option "MaxY" "4090"
Option "x0" "-6"
Option "y0" "8"
Option "x1" "1"
Option "y1" "2"
Option "x2" "12"
Option "y2" "2"
Option "x3" "5"
Option "y3" "3"
Option "x4" "-6"
Option "y4" "3"
Option "x5" "-4"
Option "y5" "3"
Option "x6" "0"
Option "y6" "5"
Option "x7" "1"
Option "y7" "5"
Option "x8" "1"
Option "y8" "5"
EndSection

Section "ServerLayout"
......
InputDevice "TOUCH"
EndSection
--------------------------------------------------------------------------------


Calibrate by hand


Evtouch comes with a calibration utility. It works, but I find the result is not very accurate. In fact it can be calibrated further by editing xorg.conf directly.

  • If you find when you touch the margin of the screen, the cursor is not at margin, you can change the "MinX", "MinY", "MaxX", "MaxY" in xorg.conf to calibrate.
  • The x0-y0 to x9-y9 corresponds to 9 regions on screen, with the x0-y0 at the left-bottom corner, x2-y0 at the right-bottom corner, x9-y9 at the right-top corner. To calibrate the touch screen in the region, just the values of corresponding options.

Rotate screen


To rotate screen:
xrandr --output LVDS --rotate left

evtouch should have supported rotation automatically. But the evtouch-0.8.7 in my debian does not work. I write a small patch 08__fix_rotate.patch to fix this issue.

Suspend and Resume


My touchscreen device is a usb device. This means it will be removed by Linux kernel before suspend and re-plugged after resume. Evtouch xorg driver has suspend and resume support mechansim, but it does not work sometimes. From the error message in /var/log/Xorg.0.log, it seems that the underlaying usb kernel device is not ready when evtouch xorg driver is being initialized. Fortunatally, it works sometimes. So if it your touchscreen does not work after resume, just go suspend again and hope it works after next resume.

Right Button


I am not successful in configuring right button. Maybe a kernel input driver issue, usbhid can not report BTN_TOUCHED for my device. But it seems that the following configuration should work for correct kernel input drivers.


--------------------------------------------------------------------------------
Section "InputDevice"
Identifier "TOUCH"
Driver "evtouch"
......
Option "longtouched_action" "down"
Option "longtouched_button" "3"
EndSection
--------------------------------------------------------------------------------

Thursday, April 2, 2009

IBSuite

To read book on my PRS505 e-book reader, I write some tools. Now I collect these tools into IBSuite (Image Book Suite), and put that on sourceforge. You can download the source code from the git of sourceforge project. Hope that can be useful for somebody.

http://sourceforge.net/projects/ibsuite/

IBSUITE

ibsuite stands for image book suite. It contains a set of tools to convert ebook in various format (pdf, chm, html) into a set of images, reformat the images (crop, embold, divide, etc), and assemble the result images into a new ebook.


COMPONENTS

  • ibhtml2img: convert html to image with xulrunner
  • ibhtml2pdf: convert html to pdf with xulrunner
  • iblineparser: parser input image, extract line information
  • ibpdfinfo: get some meta-information from pdf file, such as title, author, table of contents etc.
  • ibpy: python module, which is the driver of the whole system, it uses above programs to convert input file to image, extract line information from image, dilate image, and re-assemble lines into a new image, generate output e-book.
  • ibtools: A set of utilities and tools, some of them are used internal by ibsuite, others are user command provided by ibsuite.


USAGE

The most important command of ibsuite is ibreformat, the basic usage is as follow:

ibreformat [options] <input file>

In most cases, something like following:

ibreformat -o <output file> --iprof=<iprof> --oprof=<oprof>
--pprof=<pprof> <input file>

Where <input file> is input file name, <output file> is output file name, <iprof> is input profile, <pprof> is output profile, is <pprof> processing profile.

Available input/output/processing profiles are as follow:


input profiles:
img: for scanned book

output profiles:
prs505p: for Sony PRS505 in portrait mode
prs505l: for Sony PRS505 in landscape mode

processing profiles:

divide2: divide one line into two line (a kind of simple reflow)
resize: Resize and dilate pages
repage: Re-page input book, without much other processing such as dilate.

For other command line options, please refer to "ibreformat -h".


Some useful command line option combinations:

For scanned book on PRS505:

ibsuite -o -iprof=img -pprof=resize -oprof=prs505l
<input file>

For chm file on PRS505:

ibchm2imb .chm

When it finishs, .imb will be generated, then

ibsuite -o -pprof=repage --oprof=prs505l .imb


INSTALL

Currently, only Linux is supported, but I think it may work on some unix enviroment (including cygwin on Windows) after some work. Currently only install from source code is supported.

Pre-requirement:

  • gcc, g++, bash, make
  • libfontconfig-dev, libnetpbm-dev, libgtk-dev
  • python, python-imaging
  • imagemagick
  • for HTML/CHM support: python-chm, xulrunner
  • for scanned book: unpaper

Build:

./configure [--prefix=]
make [PREFIX=] [NO_XUL=1]

Install:

# become root
make install [PREFIX=]

Monday, November 24, 2008

Google notebook

I find google notebook is a convenient tool. You can take note quite freely during surfing. And you can share your notebook quite easy too. I think it is even easier than Blog. Some of my exported notebook:

Programming

Smart phone

Friday, July 18, 2008

An algorithm to render PDF on small devices

I am interested in ebook reader for quite a while. But after trying with a 6-inch e-ink reader (Hanlin V3), I found it is almost useless to read normal PDF files (A4 size) on these devices. The font size is too small, while the page size is too wide. So, a method to render PDF for these small devices is thought about and prototyped. The details are as follow:
  1. Convert pdf to image. I use pdftoppm of xpdf. Such as: pdftoppm -r 180 -f 245 -l 245 -gray -aa yes a.pdf a
  2. Analyze the generated images. Break page into lines.
  3. Divide each line long enough to two segments.
  4. Rearrange the segments into a new page, with half of the width.
A full functional PDF re-flow algorithm is very difficult to implemented. But a more simplified version as above is much easier.

No state updating: functional language

The programming model of command language is state machine. Such as in C, every variable is a state, one of the most common statements are assigning new value to a variable, that is, state updating. But in functional programming language, there is no state updating, how to program without state updating? Let's begin with a simple example of bank account management system.


struct account
{
char *name;
int remain;
struct account *next;
};

#define OP_NOP 0
#define OP_WITHDRAW 1
#define OP_DEPOSIT 2
#define OP_PRINT 3
#define OP_EXIT 4

void deposit(struct account *account, int val)
{
account->remain += val;
}

void withdraw(struct account *account, int val)
{
account->remain -= val;
}

int main(int argc, char *argv[])
{
struct account *accounts = NULL;
char *name;
int op = OP_NOP, val;

while (op != OP_EXIT) {
op = read_operation();
case OP_WITHDRAW:
case OP_DEPOSIT:
name = read_name();
account = list_find(accounts, name);
val = read_val();
if (op == OP_WITHDRAW)
withdraw(account, val);
else
deposit(account, val);
break;
case OP_NEW:
name = read_name();
account = malloc(sizeof(struct account));
account->name = name;
account->remain = 0;
list_add(&accounts, account);
break;
case OP_PRINT:
/* a macro to iterate every element of list */
list_for_each(accounts, account) {
printf("Name: %s\tRemain: %d\n", account->name, account->remain);
}
break;
case OP_EXIT:
break;
}
}
return 0;
}


In erlang, a functional programming language:


-module(bank).
-export([service/1]).

deposit(Account, Val) ->
{Name, Remain} = Account,
{Name, Remain + Val}.

withdraw(Account, Val) ->
{Name, Remain} = Account,
{Name, Remain - Val}.

print_account({Name, Remain}) ->
io:format("Name: ~s Remain: ~B~n", [Name, Remain]).

service(Accounts) ->
{ok, [Operation|_]} = io:fread("Operation: ", "~a"),
if
Operation == deposit; Operation == withdraw ->
{ok, [Name|_]} = io:fread("Name: ", "~s"),
{ok, [Val|_]} = io:fread("Val: ", "~d"),
case lists:keysearch(Name, 1, Accounts) of
false ->
io:format("Error: no such account.~n"),
NewAccounts = Accounts;
{value, Account} ->
case Operation of
deposit ->
NewAccount = deposit(Account, Val);
withdraw ->
NewAccount = withdraw(Account, Val)
end,
NewAccounts = lists:keyreplace(Name, 1, Accounts,
NewAccount)
end,
service(NewAccounts);
Operation == new ->
{ok, [Name|_]} = io:fread("Name: ", "~s"),
case lists:keymember(Name, 1, Accounts) of
true ->
NewAccounts = Accounts,
io:format("Error: account already exist.~n");
false ->
NewAccounts = [{Name, 0} | Accounts]
end,
service(NewAccounts);
Operation == print ->
lists:foreach(fun print_account/1, Accounts),
service(Accounts);
Operation == exit ->
ok;
true ->
io:format("Error: unknown operation~n"),
service(Accounts)
end.


Notes:
  • In functional programming language, instead of updating object (value) in-place, every time a new object (value) is constructed. In example above, in C, deposit() change account->remain directly, while in erlang, a new account is constructed and returned.
  • If data of program is organized in a hierarchical way, to change the data in leaf, in command language, only the leaf is changed in place; in functional language, all data structure from that leaf to root will be reconstructed. In example above, in C, during deposit operation, only the corresponding account object is changed in-place, while in erlang, both corresponding account object and the whole account list will be re-constructed. With the help of carefully designed implementation, althought the performance of that in functional language is wrose, it is not so bad as it appears.
  • In functional programming language, instead of updating the binding of variable name to new value directly, a new scope is constructed and in the new scope, same variable name is binded to a new value. In example above, during "new" operation, accounts may be bind to a new value, in erlang, a new scope is constructed by "recursing", that is, the new constructed account list is bind to Accounts in a new scope. Thanks to the "tail recursing" optimization, the performance is not so bad.
Questions:
  • How to shared objects in functional programming language? Such as in a database system, the cached database table should be shared between service threads.

Saturday, April 28, 2007

OS as parallel system

  1. There are subsystems as following in Linux kernel
    • process management (virtual memory system, kernel entry point)
    • physical memory management system
    • file system
    • device driver, device management
    • network system
  2. The subsystems in Linux kernel like the "server" in micro-kernel operating system. They can be seen as multi-thread server too. Although the Linux kernel provides multi-process environment for user space, the kernel itself should be seen as a multi-thread program, because everything is shared.
  3. Most resources are not shared between processes in process management system, i.e., the virtual memory system is not shared between processes, while they are shared between threads.
  4. Process/thread is used as one of the parallel roles, the other parallel roles include IRQ handler, softirq, tasklet, work queue, timer operations. The subsystems in Linux kernel can be seen as multi-thread server system.
  5. If multiple threads access different objects, such as the different file, there will be no conflict.
  6. Copy, cache, transaction technologies in parallel system can be used in Linux kernel too, such as the per CPU cache in slab subsystem.