Thursday, July 18, 2013

txtr Beagle - Part two - software


Thanks to Moritz I was able to connect to txtr via the Bluetooth SPP profile. To do this you need to disable the txtr app that is installed on your phone and install any app that does Bluetooth serial debugging. I used "Bluetooth SPP", available freely on the Play Store.

UPDATE: Andreas Schier has written an open-source java toolchain for Beagle:

My own version:

UPDATE: Florian Echtler has built two Python scripts, one emulating the server and another one for the client. The server allows you to send images to your reader:

Turn on Bluetooth on the phone and Beagle, start the app and choose "Real-time mode". Inside the prompt you should type "HELP" (all caps) followed by the enter key (not "Done") so a newline is inserted after the command. You should see a listing of available commands.
Here's the [obscured] output from my device:

Bluetooth connect OK.

Bluetooth Protocol v8

Accepted commands:


 Issuing the INFO command:
FIRMWARE ID=Beagle-F-U BUILDDATE=18.April.2013 GIT=cxxxxxx IAP=0 BLUETOOTH=u.3

DEVICE SERIAL=8888888 BDADDR=00:xx:xx:xx:xx:xx DISPLAY=V110

# bookselect button activated





 Issuing GETBOOKS:
BOOK ID=1111111111111111 FIRSTPAGE=1 LASTPAGE=19 CURRENTPAGE=19 AUTHOR=sgsdfgsdfgdgsd TITLE=sdfgsdfgsdfgsdfg
BOOK ID=888888888888888 FIRSTPAGE=1 LASTPAGE=183 CURRENTPAGE=5 AUTHOR=adfrgsdfgsdfgsdfgsdfgsdfg TITLE=sdfgsdfgsdfgsdfgsdfg


BOOK ID=888888888888888 FIRSTPAGE=1 LASTPAGE=447 CURRENTPAGE=321 AUTHOR=sdfgsdfgsdfgsdfg TITLE=sdfgsdfgsdfgsdfg


 Issuing MEMORY:

MEM TOTAL=8192 FREE=2168



Not much to see here but I assume the BOOK command signals the device that an upload is about to start. I was initially considering the fact that a different Bluetooth channel (binary) was used for the transfer but giving how much time it takes to actually transfer a book they might actually be using the same (Serial) channel.


The apk and application storage were retrieved from the device using TitaniumBackup.


The storage archive contains the following data:
- fonts
- hyphenation dictionaries (de, en, es, fr, it, pt)
- some web tracking databases (cache and cookies), Google analytics client id
- Adobe Digital Edition - activation xml; I assume this is some fingerprint used to register the pdf parser with Adobe (
- fingerprint id - either for the phone or the Beagle, not sure
- adobe DRM registration id - xml
- authenti[fi]cation xml containing user and token, in my case Facebook
- billing info xml
- preferences xml - for the app


The apk was unpacked and the .dex file was passed to the dex2jar utility. Jd-gui was used to browse and dump the decompiled source code. I will not post any code dump since it's probably illegal.

However, it's probably no problem to post the package structure and figure out what might be happening.

There's the Google analytics package there but I've seen that in almost every Android app.

Facebook is there for login.

GMS is play services SDK.

The sonyericsson package implements a humanized version of touch zooming, I haven't studied that yet.

And a bunch of other stuff, but it's interesting to note the renderer service has only two renderers: EPUB and PDF.

Jumping over some details, it seems that the books are rendered on the Android device inside a Bitmap object
The settings flag is Bitmap.Config.ARGB_8888, which means each pixel is stored on 4 bytes.
For grayscale conversion a new bitmap is created and receives a color matrix filter with saturation set to zero. For raw retrieval, the getPixels () method is called with the parameters (int[480000], 0, 600, 0, 0, 600, 800).
public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
Added in API level 1
Returns in pixels[] a copy of the data in the bitmap. Each value is a packed int representing a Color. The stride parameter allows the caller to allow for gaps in the returned pixels array between rows. For normal packed results, just pass width for the stride value. The returned colors are non-premultiplied ARGB values.

pixels The array to receive the bitmap's colors
offset The first index to write into pixels[]
stride The number of entries in pixels[] to skip between rows (must be >= bitmap's width). Can be negative.
x The x coordinate of the first pixel to read from the bitmap
y The y coordinate of the first pixel to read from the bitmap
width The number of pixels to read from each row
height The number of rows to read

IllegalArgumentException if x, y, width, height exceed the bounds of the bitmap, or if abs(stride) < width.
ArrayIndexOutOfBoundsException if the pixels array is too small to receive the specified number of pixels.
There are a few native methods stored in (5 MBytes!) most notably getCurrentScreenBuffer() which does not return anything.


The main actions are stored in BeagleDevice.class, showing some more commands than what HELP listed:
  •  PAGE [pagenum] - also passes a byte[] array, used for uploading
  •  UTILITYPAGE [pagenum] - with byte[] parameter
  •  VCOM [num]
  •  BOOK ID=[num]
  •  TITLE [string]
  •  AUTHOR [string]
I'll go over some details in a next post, for now what's interesting is the transfer payload type. It's a compressed byte[] array retrieved by calling convertToZipped4bpp(int[], 600, 800, 16, false) native method.
The 4-bit format is called 3BIT+DITHER.


  1. Hey Ligius,

    thanks for the teardown. Got myself a Beagle today and am very curious, if there's a way to pass the complicated process to get an ebook file on the device (upload to, download on phone, upload to device). My knowledge of this hacking stuff tends to zero but I admire guys like you who try their best to free devices like the Beagle.

    I am looking forward to your next posts regarding this device. Thanks for the effort


  2. Hi Czery,
    That's my final goal, but until then I'm documenting every step. So the answer is: no, currently not possible.

  3. Hey Czery, Ligius,
    a friend of mine has reverse-engineered the book transfer last weekend.
    He wanted to clean up the code (Python) a little bit before putting it on GitHub over the next days:

  4. It would be great to know if we could use the Transfer like Serial Console because if it would be true we could build up own Android APP ;)

  5. Yes, transfer works via BT Serial Port Profile using the BOOK, PAGE, ... commands.
    However, images are PGM files with a special zlib compression, so you have to convert them first.
    The code is still very rough, but I guess Florian will put it online soon.
    If you are impatient (or curious): write a small script that poses as a Beagle and let the Android txtr app connect to it - that's (partially) how Florian reverse-engineered the exact protocol.

  6. I'm not getting it completely but looks like some code for the beagle "txtr a" ?
    Also, why do you have a limit of 15 books? I only have five :-(

  7. Thanks for the comments, I added a final(?) chapter describing how to protocol works.
    Anyone can develop an Android or even Python app to talk to the device and upload the books, but I haven't actually provided any code. It should be a 2 hour job.

  8. I didn't really clean anything up, but here's my code on github:

    I've also written a short blog post about it:

    Thanks for sharing!

  9. I've written a Java application that allows to manage ebooks on the beagle (list and delete books, upload PDFs as new books).

    The code is available on github:

    1. Your piece of software seems absolutely fantastic. Call me stupid, but I couldn't for the life of me, figure out how to pair the beagle with a pc. I never got past, the "please return to the txtr beagle app to finish pairing" screen. Do you have any tips on that. With that of course Jbeagle just says "searching for begale" (This is on windows by the way).

    2. Windows 8.1 or 10? Click start, type 'add device', select 'add or remove devices', select the Bluetooth section. Now keep pressed on the power button of the Beagle until it starts flashing blue, it should be in pairing mode. It should afterwards appear in the Windows dialog.
      For more control over PDF rendering check out my fork of the project

    3. Thanks for replying.

      Problem is, that when I put my beagle into pairing mode, when connected to a PC it will just say, "Pairing successful, please return to the txtr app". If I launch JBeagle in this state, it will just say "searching for beagle", and than the beagle will give a timeout message after a while, but JBeagle fail to find it. I can connect the beagle to and android device through to -soon to be shut down but still operating- official app, and then it will say "Waiting for books", when in bluetooth mode, and like that I can even transfer a book. I have Win10 on my main pc, but if needed I have a Pc in the house With Win8.1 (On that it does the same thing BTW), and WinXP if that helps. Also in bluetooth settings its says that if for example the beagle is on COM port N than the "beagle spp dev" is on COM N-1. (I don't know if that is supposed to be like that or not). So if you have any idea what I am doing wrong, please hit me with t :D

    4. This comment has been removed by the author.

    5. Here's what I did, step by step, Win10:

      - start the beagle (pwr btn), keep pressed pwr to get into the pairing mode (blue led flashing)

      - keep pressed left and right arrows to reset the device (this will remove all books and settings!)

      - disabled and re-enabled the bluetooth adapter in device manager as it was acting up on my pc

      - started beagle, put it into pairing mode

      - started the pc discovery (add bluetooth device), found the beagle, got a confirmation code, accepted that

      - started the jBeagle application, the top status bar should display 'Searching for beagle...' and then shortly 'retrieving books' and then 'done'.

      - press browse to select a file (from my app, link above, go to releases)

      - press upload

    6. Well I did just that, 3 times, just to make sure, I also removed th batteries in the beagle and restarted, the computer just to make absolutely sure, But I am stuck at the "Searching for beagle screen" . Tried it with the win8 pc --->same. Also I got the compiled java package to rule out the problem with eclipse, but no change. By the way my beagle is a Hungarian language model... Does that make a difference? Also, is there a way for me to tell, where the process gets stuck? Also as I stated before the begale gets stuck on screen that says "Bluetooth pairing successful. Please return to the txt app to continue pairing... So at the moment I am completely stumped...

    7. I have the German model, though it should not be any difference. As soon as the device is paired in Windows the Bluecove library should take care of connecting to it.
      If you have some knowledge of Java, start the app in Debug mode, set a breakpoint in and try to step over the code. See if it throws any exceptions there. I'll be happy to assist.

    8. Sadly I know nothing about java, but I have seen other programming languages (c# and visual basic), so at least I have a basic idea :D. Very nice from the original programmer to comment to every subroutine what it does. So I found the bit where it searches for the beagle

      beagle = BeagleUtil.searchForBeagle();

      This is the line it gets stuck on. It does not even exit with an exeption, it just stays there. I guess BeagleUtil.searchForBeagle(); is a subroutine defined somewhere else. How can I find where that is?

    9. Press F3 to go to that function. Press F5 to step into it. Press F6 to step over functions. Select a text and press Ctrl+Shift+i to see an evaluation of that expression. F8 to resume running. By stepping over stuff you are able to see if something throws an exception (jumps to the catch block) and see what the exception is. I would have modified the code to show the exceptions in the console, but have not bothered to do that.

    10. This comment has been removed by the author.

    11. Just enter this chat room: and we can work from there, it's getting too detailed to have a meaningful conversation here.

    12. I've made a new release a few days ago on my Github project that addresses that issue - the Hungarian version of Beagle is shown as 'txtr beagle' instead of 'Beagle'. A nicer way to do that would be to have a list of BT devices from which to choose. Next release maybe... Also included are some small features and fixes (reconnection, keep-alive ping)