Shiny New E-Book Gizmo: The Amazon Kindle


View Full Version : Understanding the ContentLister


jharker
08-17-2007, 06:16 PM
Since the first step in changing (or replacing) something is understanding what it does, I thought I would start a thread about what the contentLister does.

I originally looked into this because I wanted to understand how button presses are handled by the iLiad's software. Now that I've learned a little bit, I've seen something surprising:

It seems that the contentLister does a LOT more than just display directories. I wouldn't be surprised if the contentLister does a large part of the job of running the iLiad. I strongly suspect that the contentLister actually functions as a keyboard driver for the iLiad's buttons (including the power button!). But I might be wrong about all of this.

Here's what I did:

First, I made a slightly modified version of iPDF. In this version, every keypress seen by iPDF is written to a log file. Using this I've been able to determine the GTK+ keycodes for:
forward pageturn
long forward pageturn
backward pageturn
long backward pageturn
up arrow and long up arrow
dot and long dot
down arrow and long down arrow
the "escape" button (upper left button), which quits the program
However, iPDF does NOT register or record keypresses for the "news", "books", "docs", or "notes" buttons, or for the menu button (the button just under the "escape" button).

I wanted to learn what happens when those buttons are pressed, and where the signals go. My first guess was to that the contentLister was intercepting those keypresses from X...

So, I wanted to learn what happens when we run the contentLister. I set up an ethernet connection to my iLiad and ran DropBear, then used ssh to log in as root. All of the following was done on the command line while logged in to the iLiad. It's possible that some error messages are a result of that.

First, I killed the old contentLister. Then, I had to define DISPLAY so that the new contentLister would know where the display was, then I called the contentLister, just as it's called by start.sh during boot:

# killall contentLister
# export DISPLAY=:0
# /usr/bin/contentLister --sync &

(CL_E)control.c:344,ctrl_read_configfile() cannot read [CONTENTLISTER] [doc_signing] - Key file does not have key 'doc_signing' [3]
(CL_E)erConnect.c:68,erConnectInit() Lock the connect mutex
(CL_E)metadataStoreManager.c:977,recreateArchives( ) Can not create directory /mnt/free/newspapers!
(CL_E)metadataStoreManager.c:988,recreateArchives( ) Can not create directory /mnt/free/books!
(CL_E)metadataStoreManager.c:999,recreateArchives( ) Can not create directory /mnt/free/documents!
(CL_E)metadataStoreManager.c:1010,recreateArchives () Can not create directory /mnt/free/notes!
(W)eripc.c:37,erIpcInitServer() Version: 256

(W)eripc.c:76,erIpcInitServer() Bound successfully to 127.0.0.1:50070.
(E)erregcommon.c:138,erRegGetExtInfoFromMemory() theExtInfo->iconlocation - Key file does not have key 'ari' [3]
(E)erregcommon.c:138,erRegGetExtInfoFromMemory() theExtInfo->iconlocation - Key file does not have key 'ARI' [3]
(E)erregcommon.c:138,erRegGetExtInfoFromMemory() theExtInfo->iconlocation - Key file does not have key 'sh' [3]
(E)erregcommon.c:138,erRegGetExtInfoFromMemory() theExtInfo->iconlocation - Key file does not have key 'SH' [3]

(E)erregcommon.c:1112,erRegGetAutoconnectFromMemor y() theAutoconnect->backgroundConnectTo - Key file does not have key 'background_connect_to' [3]
(CL_W)control.c:432,ctrl_background_connect_timeou t_start_withinterval() registry read: enable [0] interval [5]
Opening /dev/otgdev0 Try 1...Success
(CL_W)programManager.c:144,on_sigchld() entry: signo [17] pid [806] status [0x0000]
(CL_W)programManager.c:207,on_sigchld() end

Okay, that's pretty cool. What is this "Key file"? Any relation to key press signals?

Next, I moved to the "books" directory by pressing the "books" button, and navigated down a couple of subdirectories, all with button presses:

...

Nothing. Yup, no messages. Next, I opened a pdf file by selecting it in the contentLister:

(CL_E)programManager.c:887,pm_UpdateState() Failed to fetch class hint for window 0x200004
(CL_E)programManager.c:887,pm_UpdateState() Failed to fetch class hint for window 0x200004
(W)eripc.c:37,erIpcInitServer() Version: 256

(W)eripc.c:76,erIpcInitServer() Bound successfully to 127.0.0.1:50067.
(ERM_TRACE)ermanifest.c:95,LocateTo() LocateTo failed! no or empty xmlNodeSet
(ERM_TRACE)ermanifest.c:95,LocateTo() LocateTo failed! no or empty xmlNodeSet
(ERM_TRACE)ermanifest.c:95,LocateTo() LocateTo failed! no or empty xmlNodeSet
CPDFApp::loadScribble uses 45247
PDFDoc::displayPage 127 uses 891228

drawImage and XSync time 36792
PDFDoc::displayPage 128 uses 1348748
PDFDoc::displayPage 129 uses 876218
PDFDoc::displayPage 130 uses 891040
PDFDoc::displayPage 131 uses 759569
PDFDoc::displayPage 132 uses 836193

Clearly there's a window opening, then what appears to be some timing messages from iPDF giving how long different procedures take. The numbers are probably in milliseconds, suggesting that each page draw takes about 0.89 seconds on the average. I happen to know that after drawing the current page, iPDF draws and caches the next few pages immediately. Obviously, that's what's happening here.

The "PDFDoc::displayPage 131 uses 759569" messages are actually from iPDF, although they are obviously being passed along through the contentLister's output.

Let's turn the page backward:

(CL_E)programManager.c:887,pm_UpdateState() Failed to fetch class hint for window 0x200004
PDFDoc::displayPage 126 uses 820161

drawImage and XSync time 34761
PDFDoc::displayPage 125 uses 955291
PDFDoc::displayPage 124 uses 612510
PDFDoc::displayPage 123 uses 425989
PDFDoc::displayPage 122 uses 793361
PDFDoc::displayPage 121 uses 885760

Yes, it caches a row of pages backwards. No mention of a keypress. Up arrow, down arrow, and dot presses give this:

(CL_E)programManager.c:887,pm_UpdateState() Failed to fetch class hint for window 0x200004
(CL_E)programManager.c:887,pm_UpdateState() Failed to fetch class hint for window 0x200004
(CL_E)programManager.c:887,pm_UpdateState() Failed to fetch class hint for window 0x200004

Let's try quitting iPDF by pressing the 'escape' button, in the upper left corner of the iLiad:

(CL_E)programManager.c:887,pm_UpdateState() Failed to fetch class hint for window 0x200004
(CL_E)programManager.c:448,pm_SendKey() NOT Sending keyrelease for UP key....
(CL_W)programManager.c:144,on_sigchld() entry: signo [17] pid [808] status [0x0000]
(CL_W)programManager.c:168,on_sigchld() last started [IPDF] pid [808]
(CL_W)programManager.c:207,on_sigchld() end

Okay, programManager.c has a function called pm_SendKey whose role clearly deals with keypresses, including whether to pass on key signals to other programs. It's worth noting that the escape (or "UP") key is a key that DOES get read by iPDF. So I launched iPDF again. Here's the output after I exited iPDF by pressing the "books" button (it's the same output for "news", "docs", "notes", or menu buttons):

(CL_E)programManager.c:887,pm_UpdateState() Failed to fetch class hint for window 0x200004
(CL_W)programManager.c:521,pm_TerminateUserApp() Terminate process [ipdf] pid [811]
On receive signal 15 pid 811
(CL_W)programManager.c:144,on_sigchld() entry: signo [17] pid [811] status [0x0000]
(CL_W)programManager.c:168,on_sigchld() last started [IPDF] pid [811]
(CL_W)programManager.c:207,on_sigchld() end

The function pm_SendKey isn't mentioned. Interesting.

Finally, here's a small experiment. I opened a pdf document using my modified iPDF which dumps keypresses to a log file. After testing it by turning pages (and reading the corresponding pagebar "keypresses" in the log), I killed the contentLister manually, then checked to be sure iPDF was still running:

# killall contentLister
# ps | grep ipdf
820 root 14656 S /usr/bin/ipdf /mnt/free/books/Doyle, Arthur Conan/Doyle - The Memoirs of Sherlock Holmes.pdf/Doyle - The Memoirs of Sherlock Holmes.pdf
821 root 14656 S /usr/bin/ipdf /mnt/free/books/Doyle, Arthur Conan/Doyle - The Memoirs of Sherlock Holmes.pdf/Doyle - The Memoirs of Sherlock Holmes.pdf
822 root 14656 S /usr/bin/ipdf /mnt/free/books/Doyle, Arthur Conan/Doyle - The Memoirs of Sherlock Holmes.pdf/Doyle - The Memoirs of Sherlock Holmes.pdf
833 root 448 S grep ipdf

Then I tried turning pages in iPDF, and pushed every button I could find. No buttons worked at all, and the logfile registered no keypresses. The power switch also did not work.

Finally, I killed iPDF and restarted the contentLister again. Keys worked as before, and on sliding the power switch, I got this:

(CL_W)control.c:3293,ctrl_shutdown() entry

** (contentLister:850): CRITICAL **: ctrl_hide_pincode_screen: assertion `g_listerState == STATE_PINCODE' failed

Broadcast message from root (pts/0) (Mon Apr 12 14:12:20 1954):

The system is going down for system halt NOW!
(CL_W)control.c:3317,ctrl_shutdown() end

From the above experiments, I conclude that the "contentLister" is not just a simple content lister. It actually plays a key role in orchestrating many of the iLiad's functions. Notably, the contentLister seems responsible for reading and processing all button input.

One interesting message from the contentLister's start sequence is "Opening /dev/otgdev0 Try 1...Success". My guess would be that one of iRex's binary kernel drivers translates button interrupts into keypress data and dumps it to /dev/otgdev0. Then the contentLister takes that data from /dev/otgdev0 and forwards button press codes to window applications as necessary.

Bear in mind that this might be completely wrong. My interpretation and understanding of these experiments may be flawed. As I understand it, the conventional approach to X is that normally an X keyboard driver does the work of reading keyboard data and passing it along to the window manager. I have not yet read the iRex patches to the kernel and the xserver, and one of them may deal with button presses.

Comments, questions, suggestions, corrections, etc....?

wallcraft
08-18-2007, 02:09 AM
Have you seen the post Mobipocket Reader for GNU/Linux, Mac, all! (http://www.mobileread.com/forums/showthread.php?t=12559)? It is about running the iLiad (Java) MobiPocket Reader on other machines. The strange thing about the reader is that it is just the book display pane (no icons etcetera) and is controlled by "a UDP socket running on port 50079". I initially attributed the strangeness to MobiPocket, but perhaps this is another example of splitting window manager like actions into a separate program.

By the way, FBReader has a menu item to bind keys to actions (keys tab under the options icon) and it will tell you what key it detected for each keypress. So you can get some of this info from FBReader without recompiling. It may also be possible to bind two actions to some keys (standard and long keypresses), which isn't something I would have thought to try.

jharker
08-18-2007, 02:57 AM
Interesting about the Mobipocket reader, I hadn't thought about that...

Well, the way things seem to work on the iLiad, button press interrupts are dealt with on a low level (kernel driver, probably) and converted to more conventional keypress signals, which are then picked up by another low-level program (I thought an X11 driver, but now I think the ContentLister) and passed to the window manager, which passes it to programs like iPDF and FBReader.

Ultimately, many of the buttons are seen by applications as normal keyboard keys. For example, the "escape" button, to iPDF or FBReader, looks like F5. A forward pageflip looks like PgUp, back pageflip looks like PgDn, etc. Interestingly, a LONG forward pageflip isn't simply a long-held PgUp, but instead generates a F1. Similarly, the long backward pageflip generates an F2. Somewhere I have a list of the keyboard keys associated with each button action, and it's always a different key for short and long. This is how the buttons are seen at the GTK level within the window manager in X windows.

The problem is, that the "books", "news", etc. buttons do NOT generate any keyboard key press visible to a regular application. So my question was, what DO they do, and where are those signals handled? The answer seems to be that the ContentLister takes care of interpreting button presses, but it only translates some into keyboard key press events for the Xserver / window manager. The "books" etc. buttons are intercepted and never get sent to the X server / window manager at all.

At least, that's my theory at the moment...

jharker
08-18-2007, 11:57 PM
Somewhat obviously, I realized that button signals are probably piped out through... surprise, surprise, /dev/buttons ! However, I can't seem to read any signals from it. cat /dev/buttons gives nothing, and I wrote a little program to read files character by character, which works fine in my computer for the mouse (/dev/psaux) but gives nothing from /dev/buttons when buttons are pressed.

Anyone have any ideas?