Introduction: Kindle Web Remote Control

Description
This is a software solution to remote page turn on a kindle. In brief, I am running a webserver from my kindle. This is serving a cgi script which imitates a button press on my kindle. I access the scripts from a browser on my phone.
This means that my hands don't need to be near the kindle when turning pages.

Motivation
For me, this is an ideal set-up for reading in bed: my hands can be under the covers while the kindle itself is on a stand, but I don't need. It may also be helpful for those who find it difficult to hold the kindle themselves, or to control it using the built in buttons (see, for example, this modification http://hackaday.com/2011/08/24/more-frankenkindle-progress/ )

System requirements
The kindle you use needs to be jailbroken, and needs to have physical buttons (The specific method used here simulates a button press, but it may be possible to adjust the scripts to work with touchscreen kindles as well -- let me know and I'll add it to the instructable).

I am using a Kindle 4 NT, and this guide will be tailored to that, but it shouldn't be too difficult to adapt the process to other models.

For the remote control, I am using an iPhone 3GS, but all it is doing is accessing a web page, so it should work with any smart phone (in fact, any device capable of accessing the internet within your local network -- you could even control one kindle with another, although I'm not sure why you'd want to, exactly).

Now, on with the instructions.

Step 1: Jailbreak Your Kindle

Instructions for Kindle 4 are here: http://wiki.mobileread.com/wiki/Kindle4NTHacking#Jailbreak , earlier models are here: http://www.mobileread.com/forums/showthread.php?t=88004

(Image from http://wiki.mobileread.com/wiki/File:Kindle4NTdiagnostic.jpg, by Needsleep99, licensed under Creative Commons Attribution Non-Commercial Share Alike.)

Step 2: Install Usbnet

Download here: http://www.mobileread.com/forums/showthread.php?t=88004

Disclaimer:
The readme for usbnet is intentionally minimal.
Quote from the readme:
"As always, it may void your warranty, eat your Kindle, kill a kitten, and sell your first
born's soul to the devil.

I *strongly* recommend having a proper Linux CLI sysadmin background before trying to use this,
or you *WILL* probably end up messing your Kindle up. Do *NOT* do anything with this unless
your are *REALLY* sure you understand what you're doing."

So, if you have no idea what you're doing it's probably better to try and find someone to help you than risk bricking your kindle.


That said, to install drag the "update_usbnetwork_0.47.N_(yourkindlemodel)_install.bin" from the download to the root of the kindle mass storage device, eject and go to menu->Settings->menu->Update Your Kindle. There is a good guide to the usbnet setup process here: http://www.turnkeylinux.org/blog/kindle-root (start from section "Install usbnet hack").

Reason:
usbnet installs a modified version of the program called busybox. Busybox is already part of the kindle software, but the version installed by usbnet contains httpd, which is the server we are going to use to serve up our pages.

usbnet also allows us to ssh into the kindle to start the server if, like me, you couldn't make kite work (we'll come to that later)

Step 3: Add Cgi Scripts to Your Kindle

NOTE: files are available in steps 9 - 12

Put the file serverstart.sh in the root of your kindle (the mass storage drive which appears on the desktop, which maps to /mnt/us if using usbnet). If you have kite installed ( http://www.mobileread.com/forums/showthread.php?t=168270 ), put it in the kite folder instead.
Make serverstart.sh executable (chmod u+x serverstart.sh)

Running this script first allows incoming http connections, then starts the server.

Make a directory www in the root of your kindle, then a directory cgi-bin inside of that.
Put the scripts f.cgi and b.cgi in www/cgi-bin/
Make the scripts executable (chmod u+x f.cgi; chmod u+x b.cgi)

Step 4: Configure Busybox Httpd

Busybox httpd is the server we're going to be using.

Put httpd.conf in /mnt/us/usbnet/etc
If you want to allow non-local access to your kindle control scripts (not recommended), add the line A:* just above A:192.168. , and remove the line D:*
Change the line /cgi-bin:username:password , replacing username and password with your desired username and password. You can also hash the password using the procedure described in the comments to the file. If you don't want to have a password (not recommended) delete the line.

Step 5: Find Your Kindle's Ip Address

On a kindle 4 NT, this is done by going to menu->settings. Then press and hold the keyboard button and press the right page forward button. This brings up the "711 page". The kindle's ip address is on the second page of this dialog.

For other kindle models, search on http://www.mobileread.com/

Step 6: Start the Server, Finish the Instructable

If you have kite installed, start the serverstart.sh script from your kindle home screen.

If not, use a terminal ( on mac os x, linux, PuTTY on Windows, or any of several terminal emulators for your mobile device) and type the command "ssh root@(kindleipaddress) '/mnt/us/serverstart.sh' " (without double quotation marks, and replace (kindleipaddress) with your kindle's ip address (see step 5).

Access the scripts by going to (kindleipaddress)/cgi-bin/f.cgi in your browser.
You should see your kindle go forward one page!
Click on "f" to go forwards, and "b" to go backwards.

You're done!

Step 7: Discussion, Extending the Hack

You can obviously edit "f.cgi" and "b.cgi" to suit your own needs.
The main functional part of them is the last line "echo "send 104" > /proc/keypad" and "echo "send 109" > /proc/keypad". These simulate pressing the "page forward" and "page backward" buttons respectively (thanks to http://www.mobileread.com/forums/showthread.php?t=118480 #2). If you want to find out the key code for other button presses, you can do it by ssh-ing into the kindle, running the command "waitforkey" and pressing the button you want. The output will be something like "194 1" and the key code will be the first number, in this case 194 (which corresponds to the centre of the 5-way on the Kindle 4 NT.

It may be that different models have different keycodes associated with page forward and page back, so if the hack is giving strange behaviour, check that your key codes are 104 and 109 for forwards and backwards.

You can also send other commands to the kindle instead of simulated key presses. Try 'eips -p' to see what happens.


Wishlist
I wish I could get kite working. Can anyone help me with this?

It would be nice to be able to start the server using inetd, rather than manually. Unfortunately the current build of busybox in usbnet doesn't include inetd -- if anyone manages to implement it and interface it with this hack, let me know and I'll add it to the instructable.

Step 8: Files

Instructables won't let me upload the files*, so they are copied as text below (filenames in bold). Copy them into a text editor and save (make sure it is plain text, with mac os/ unix line endings). Remember to make the scripts executable!



*I'd guess this is for security reasons: not letting people upload their own cgi scripts to your server is probably a sensible move, even though the uploads are (presumably) sandboxed.

/mnt/us/serverstart.sh
#!/bin/sh
iptables -A INPUT -i wlan0 -p tcp --dport www -j ACCEPT;
/mnt/us/usbnet/bin/busybox httpd -h /mnt/us/www -c /mnt/us/usbnet/etc/httpd.conf

/mnt/us/www/cgi-bin/f.cgi
#!/bin/sh
echo Content-type: text/html; charset=utf-8
echo ""

/bin/cat << EOM
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head><TITLE>Kindle Page Turn</TITLE>
<style type="text/css">
html{min-height:100%;position:relative}
body{ height:100%; }
div { position:absolute;top:0;bottom:0;height:100%;width:50%;font:300px sans-serif;text-align:center; }
div#b { left:0;background-color:black;color:white; }
div#f { right:0;background-color:white;color:black; }
span.panel {
        position:absolute;
        width:100%;
        height:100%;
}
</style>
</head>
<body>
<div id="b"><a href="b.cgi"><span class="panel"></span></a>&#8678;</div>
<div id="f"><a href="f.cgi"><span class="panel"></span></a>&#8680;</div>
</body>
</html>
EOM

echo "send 104" > /proc/keypad

/mnt/us/www/cgi-bin/b.cgi
#!/bin/sh
echo Content-type: text/html; charset=utf-8
echo ""

/bin/cat << EOM
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head><TITLE>Kindle Page Turn</TITLE>
<style type="text/css">
html{min-height:100%;position:relative}
body{ height:100%; }
div { position:absolute;top:0;bottom:0;height:100%;width:50%;font:300px sans-serif;text-align:center; }
div#b { left:0;background-color:black;color:white; }
div#f { right:0;background-color:white;color:black; }
span.panel {
        position:absolute;
        width:100%;
        height:100%;
}
</style>
</head>
<body>
<div id="b"><a href="b.cgi"><span class="panel"></span></a>&#8678;</div>
<div id="f"><a href="f.cgi"><span class="panel"></span></a>&#8680;</div>
</body>
</html>
EOM

echo "send 109" > /proc/keypad

/mnt/us/usbnet/etc/httpd.conf
#
# httpd.conf - BusyBox v1.00 (2005.04.23-22:18+0000) multi-call binary
# Contribute by Dubravko Penezic, dpenezic@gmail.com , 2005-05-15
#

#
# Allow/Deny part
#
# [aA]:from    ip address allow, * for wildcard, network subnet allow
# [dD]:from    ip address deny, * for wildcard, network subnet allow
#
# network subnet definition
#  172.20.                    address from 172.20.0.0/16
#  10.0.0.0/25                address from 10.0.0.0-10.0.0.127
#  10.0.0.0/255.255.255.128   address that previous set
#
#  The Deny/Allow IP logic:
#
#  - Default is to allow all.  No addresses are denied unless
#         denied with a D: rule.
#  - Order of Deny/Allow rules is significant
#  - Deny rules take precedence over allow rules.
#  - If a deny all rule (D:*) is used it acts as a catch-all for unmatched
#       addresses.
#  - Specification of Allow all (A:*) is a no-op
#
# Example:
#   1. Allow only specified addresses
#     A:172.20          # Allow any address that begins with 172.20.
#     A:10.10.          # Allow any address that begins with 10.10.
#     A:127.0.0.1       # Allow local loopback connections
#     D:*               # Deny from other IP connections
#
#   2. Only deny specified addresses
#     D:1.2.3.        # deny from 1.2.3.0 - 1.2.3.255
#     D:2.3.4.        # deny from 2.3.4.0 - 2.3.4.255
#     A:*             # (optional line added for clarity)
#
# Note:
# A:*
# D:*
# Mean deny ALL !!!!
#

A:192.168.
A:127.

#
# Authentication part
#
# /path:user:pass     username/password
#
# password may be clear text or MD5 cript
#
# Example :
# /cgi-bin:admin:FOO
#
# MD5 crypt password :
# httpd -m "_password_"
# Example :
# httpd -m "astro"  =>  $1$$e6xMPuPW0w8dESCuffefU.
# /work:toor:$1$$e6xMPuPW0w8dESCuffefU.
#

/cgi-bin:username:password

#
# MIME type part
#
# .ext:mime/type   new mime type not compiled into httpd
#
# Example :
# .ipk:application/octet-stream
#
# MIME type compiled into httpd
#
# .htm:text/html
# .html:text/html
# .jpg:image/jpeg
# .jpeg:image/jpeg
# .gif:image/gif
# .png:image/png
# .txt:text/plain
# .h:text/plain
# .c:text/plain
# .cc:text/plain
# .cpp:text/plain
# .css:text/css
# .wav:audio/wav
# .avi:video/x-msvideo
# .qt:video/quicktime
# .mov:video/quicktime
# .mpe:video/mpeg
# .mpeg:video/mpeg
# .mid:audio/midi
# .midi:audio/midi
# .mp3:audio/mpeg
#
# Default MIME type is application/octet-stream if extension isnt set
#