Okay, by popular demand, here's a simple command-line program to let you query the iLiad's hardware buttons directly!
ButtonReader-1.0.tar.gz - This archive contains the source code, a precompiled binary, and a README with some notes on how it all works. The source code is distributed under the GNU GPL v3.
For those who are interested, here's the source code of the program for perusal and discussion:
Code:
/***********************************************************
* ButtonReader-1.0.c
*
* This is a simple program to read button presses on the iRex iLiad.
* It may be run from the command line. When a button is pressed, it
* prints a line to stdout stating which button was pressed.
*
* This program is Copyright 2007 by John C. Harker, who may be reached
* via email at John.C.Harker <at> gmail.com.
*
* 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
* 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, see <http://www.gnu.org/licenses/>.
*
* Typically a copy of the GNU General Public License is located in the
* file named COPYING.
*
***********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#define SLEEPTIME_NSEC 100000000
int main(void)
{
unsigned int data;
int i,j;
int fd_buttons;
int loop = 1;
struct timespec sleeptime;
sleeptime.tv_sec = (time_t) 0;
sleeptime.tv_nsec = SLEEPTIME_NSEC;
fd_buttons = open( "/dev/buttons", O_RDWR );
if ( fd_buttons < 0 )
{
printf("Could not open /dev/buttons.\n");
exit(1);
}
while ( loop == 1 )
{
nanosleep(&sleeptime, NULL);
// Clear the data variable
data = 0;
// Request any data
ioctl(fd_buttons, 0x80046207, &data);
// Print out the data
switch( data )
{
case 0x00000800:
printf("iDS Connect");
break;
case 0x00000801:
printf("Options");
break;
case 0x00000802:
printf("Escape (level up)");
loop = 0;
break;
case 0x00000803:
printf("News");
break;
case 0x00000804:
printf("Books");
break;
case 0x00000805:
printf("Docs");
break;
case 0x00000806:
printf("Notes");
break;
case 0x00000807:
printf("Pagebar Left");
break;
case 0x00000808:
printf("Pagebar Right");
break;
case 0x00000809:
printf("Up Arrow");
break;
case 0x0000080a:
printf("Dot (Enter)");
break;
case 0x0000080b:
printf("Down Arrow");
break;
case 0x0000080e:
printf("Power");
break;
case 0x000008ff:
/* no button pressed */
break;
default:
printf("***Unknown code 0x%08x ***", data);
break;
}
if ( data != 0x000008ff )
{
printf(" button pressed!\n");
}
} /* end of button-reading do loop */
printf("Halted!\n");
close(fd_buttons);
return 0;
}
You can see that it's pretty straightforward ioctl polling. A similar approach is used to run the flashing light. Note that the presence of the stylus in its slot is not represented by a button signal, but the power button DOES generate a button signal. This means that if you kill the ContentLister, the iLiad will not shut down when you slide the power switch!
The ioctl polling method is somewhat inconvenient because it means that the program must be constantly polling in order to read button presses. If we could rewrite the actual kernel driver we might be able to change this... but figuring out how THAT works would be even harder.
Still, this is cool stuff. I hope someone finds it useful!