Full Code of hwhw/kindlevncviewer for AI

master 5849208c2406 cached
44 files
206.4 KB
70.6k tokens
76 symbols
1 requests
Download .txt
Showing preview only (218K chars total). Download the full file or copy to clipboard to get everything.
Repository: hwhw/kindlevncviewer
Branch: master
Commit: 5849208c2406
Files: 44
Total size: 206.4 KB

Directory structure:
gitextract_35m4v9ie/

├── .gitignore
├── .gitmodules
├── COPYING
├── Makefile
├── README.md
├── Xvnc-start.sh
├── config.lua
├── ffi/
│   ├── SDL.lua
│   ├── SDL1_2_h.lua
│   ├── blitbuffer.lua
│   ├── einkfb_h.lua
│   ├── eventloop.lua
│   ├── framebuffer.lua
│   ├── framebuffer_SDL.lua
│   ├── framebuffer_linux.lua
│   ├── input.lua
│   ├── input_SDL.lua
│   ├── input_kindle.lua
│   ├── linux_fb_h.lua
│   ├── linux_input_h.lua
│   ├── mxcfb_kindle_h.lua
│   ├── mxcfb_kobo_h.lua
│   ├── posix_h.lua
│   ├── rfbclient.lua
│   ├── rfbclient_h.lua
│   └── util.lua
├── ffi-cdecl/
│   ├── SDL1_2_decl.c
│   ├── einkfb_decl.c
│   ├── include/
│   │   ├── README
│   │   ├── einkfb.h
│   │   ├── mxcfb-kindle.h
│   │   ├── mxcfb-kobo.h
│   │   └── mxcfb.h
│   ├── linux_fb_decl.c
│   ├── linux_input_decl.c
│   ├── mxcfb_kindle_decl.c
│   ├── mxcfb_kobo_decl.c
│   ├── posix_decl.c
│   └── rfbclient_decl.c
├── keys.lua
├── kvncviewer.ini
├── kvncviewer.sh
├── rfbkeys.lua
└── vncviewer.lua

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
version.lua
libvncclient.so
dist/
libjpeg-turbo-1.3.0/*
luajit-2.0/*
zlib/*


================================================
FILE: .gitmodules
================================================
[submodule "libvncserver"]
	path = libvncserver
	url = https://github.com/LibVNC/libvncserver.git
[submodule "luajit-2.0"]
	path = luajit-2.0
	url = http://luajit.org/git/luajit-2.0.git
[submodule "zlib"]
	path = zlib
	url = https://github.com/madler/zlib.git


================================================
FILE: COPYING
================================================
		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                          59 Temple Place - Suite 330, Boston, MA
                          02111-1307, USA.
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS

	Appendix: How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 19yy  <name of author>

    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 2 of the License, or
    (at your option) 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, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) 19yy name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.


================================================
FILE: Makefile
================================================
ifdef ARCH
CC=$(ARCH)-gcc
CROSS=$(ARCH)-
# for luajit:
HOST_CC="gcc -m32"
STRIP?=$(ARCH)-strip
else
STRIP?=strip
ARCH=$(shell $(CC) -dumpmachine)
endif
CFLAGS?="-D_GNU_SOURCE=1"

VERSION=$(shell git describe HEAD)
#VERSION=$(shell date +'%Y-%m-%d_%H-%m')

LIBVNCCLIENT_DIR=libvncserver/libvncclient
LIBVNCCLIENT=libvncclient.so

LUAJIT_DIR=luajit-2.0
LUAJIT=$(LUAJIT_DIR)/src/luajit

LIBJPEG_DIR=libjpeg-turbo-1.3.0
LIBJPEG=$(LIBJPEG_DIR)/.libs/libjpeg.so.62
LIBJPEG_CONFIG=-without-simd

ZLIB_DIR=zlib
ZLIB=$(ZLIB_DIR)/libz.so.1

FFI_CDECL=../koreader-misc/ffi-cdecl/ffi-cdecl $(CC) -I$(LIBVNCCLIENT_DIR)/../

OBJECTS= \
	$(LUAJIT) \
	$(LIBVNCCLIENT) \
	$(ZLIB) \
	$(LIBJPEG)

DISTRIBUTE=ffi config.lua keys.lua rfbkeys.lua vncviewer.lua \
	README COPYING \
	$(OBJECTS)

all: dist/kvncviewer-$(ARCH)-$(VERSION).zip

$(LUAJIT):
ifdef CROSS
	sed -i -e "s/CC= gcc/CC= gcc -D_GNU_SOURCE=1/" $(LUAJIT_DIR)/src/Makefile
	$(MAKE) -C $(LUAJIT_DIR) HOST_CC=$(HOST_CC) CROSS=$(CROSS)
else
	$(MAKE) -C $(LUAJIT_DIR)
endif


LIBVNCCLIENT_SOURCES=\
	$(LIBVNCCLIENT_DIR)/cursor.c \
	$(LIBVNCCLIENT_DIR)/listen.c \
	$(LIBVNCCLIENT_DIR)/rfbproto.c \
	$(LIBVNCCLIENT_DIR)/sockets.c \
	$(LIBVNCCLIENT_DIR)/vncviewer.c \
	$(LIBVNCCLIENT_DIR)/tls_none.c \
	$(LIBVNCCLIENT_DIR)/../common/minilzo.c

LIBVNCCLIENT_CFLAGS=-D_GNU_SOURCE=1 -fPIC -shared \
	-DLIBVNCSERVER_HAVE_LIBZ -DLIBVNCSERVER_HAVE_LIBJPEG \
	-I$(LIBVNCCLIENT_DIR)/.. -I$(LIBVNCCLIENT_DIR)/../common/ -I$(LIBVNCCLIENT) \
	-I$(ZLIB_DIR)/ -I$(LIBJPEG_DIR)/ \
	-Wl,-E -Wl,-rpath,'$$ORIGIN'

$(LIBVNCCLIENT): $(LIBVNCCLIENT_SOURCES) $(LIBJPEG) $(ZLIB)
	touch $(LIBVNCCLIENT_DIR)/../rfb/rfbconfig.h
	echo '#include <stdint.h>' > $(LIBVNCCLIENT_DIR)/../rfb/rfbint.h
	$(CC) $(LIBVNCCLIENT_CFLAGS) -o $@ $(LIBVNCCLIENT_SOURCES) $(ZLIB) $(LIBJPEG)

$(LIBJPEG):
	cd $(LIBJPEG_DIR) && \
		CC=$(CC) CFLAGS="$(CFLAGS)" \
		./configure --disable-static --enable-shared \
				$(LIBJPEG_CONFIG) \
				--host=$(ARCH)
	$(MAKE) -C $(LIBJPEG_DIR)

$(ZLIB):
	cd $(ZLIB_DIR) && \
		CC=$(CC) CFLAGS="$(CFLAGS)" \
		./configure
	$(MAKE) -C $(ZLIB_DIR)

cdecl: \
	ffi/posix_h.lua \
	ffi/linux_fb_h.lua \
	ffi/einkfb_h.lua \
	ffi/mxcfb_kindle_h.lua \
	ffi/mxcfb_kobo_h.lua \
	ffi/linux_input_h.lua \
	ffi/rfbclient_h.lua

ffi/%_h.lua: ffi-cdecl/%_decl.c
	$(FFI_CDECL) $< > $@

version.lua: $(DISTRIBUTE)
	echo 'return "$(VERSION)"' > version.lua

dist/kvncviewer-$(ARCH)-$(VERSION).zip: $(DISTRIBUTE) version.lua cdecl
	-rm $@
	-rm -rf dist/$(ARCH)
	mkdir -p dist/$(ARCH)/kvncviewer
	cp -rL $(DISTRIBUTE) dist/$(ARCH)/kvncviewer/
	cd dist/$(ARCH)/kvncviewer && $(STRIP) --strip-unneeded *.so* luajit
	cd dist/$(ARCH) && zip -r9 ../../$@ kvncviewer

clean:
	$(MAKE) -C $(LUAJIT_DIR) clean
	$(MAKE) -C $(LIBJPEG_DIR) clean
	$(MAKE) -C $(ZLIB_DIR) clean
	-rm $(LIBVNCCLIENT)



================================================
FILE: README.md
================================================
## About

This is a VNC viewer for eReaders.
Copyright (c) 2013 Hans-Werner Hilse <hilse@web.de>

It works on the framebuffer, using the einkfb API from e-ink devices (einkfb.h) to do screen refreshes.
This is based on LibVNCClient, part of the [LibVNCServer project](https://libvnc.github.io/).


There is a discussion thread on MobileRead:
http://www.mobileread.com/forums/showthread.php?t=150434

Note that the current version is a major rewrite of the original version.
The current version is implemented in Lua, targeted at LuaJIT.


## Configuration

Input handling is configurable/customizable in "config.lua".

kVNCviewer supports many options that determine various settings. Run it without arguments to show a list of supported options. In addition, LibVNCClient parses options, which allows for additional configuration. Look into the [documentation of LibVNCClient](https://libvnc.github.io/doc/html/group__libvncclient__api.html#gabb2299d1644f3cf38544eb97d2356475) to see the options it accepts.


## Building

In order to build kVNCViewer, you can use GNU make. A Kindle (and other eReaders)-specific toolchain can be found at [@koreader/koxtoolchain](https://github.com/koreader/koxtoolchain). Specify a toolchain prefix as the "ARCH" variable, and it should build luajit, zlib, libjpeg and finally libvncclient. E.g., for legacy Kindles:

```
make ARCH=arm-kindle-linux-gnueabi
```

You can find the result in the "dist/<ARCH>" subdirectory. Also, a .zip file is created for distribution.


## Running

You need to copy the program and the libraries it needs onto your eReader (you can try running it without and it will show you which libraries are missing). Then, from a launcher app or shell, call:

```
./luajit vncviewer.lua 192.168.1.1:5900
```

You will need to enter the correct server address or name and screen number.


## Licensing/Copying

This software is licensed under the GPLv2 (see file COPYING).


================================================
FILE: Xvnc-start.sh
================================================
#!/bin/sh -xe

orientation=`ssh root@192.168.2.2 cat /sys/module/eink_fb_hal_broads/parameters/bs_orientation`
if [ $orientation == 1 ] ; then
	geometry=1200x824
else
	geometry=824x1200
fi

/usr/bin/Xvnc --SecurityTypes=None -geometry $geometry -depth 16 -dpi 160 -alwaysshared :1 &
sleep 1
DISPLAY=:1 xterm &
DISPLAY=:1 dwm &
vncviewer :1 &
x2vnc -west 127.0.0.1:1 &
ssh root@192.168.2.2 /mnt/us/kindlevncviewer/kvncviewer.sh 192.168.2.1:1



================================================
FILE: config.lua
================================================
require "keys"
require "rfbkeys"

-- comment out the following line on a KDX
set_k3_keycodes()


-- variables client_width and client_height will be available when handleInput() is called
client_width = 0
client_height = 0

--[[
   you have also the following API functions:

   Quit( [status] )
      will quit the application. optional: return code (must be positive)

   SendKeyEvent( keyCode, pressed )
      sends a key event to the rfb server. "pressed" is a bool value
      telling whether the key was pressed (true) or released (false)

   SendPointerEvent( x, y, buttonMask )
      sends a pointer event to the rfb server
]]--


-- globals for remembering key state
shift = false
sym = false

-- this handler will be called upon key presses (input events, actually)
function handleInput(channel, itype, code, value)
	--print("input:", channel, itype, code, value)
	if itype == EV_KEY then
		local pressed = false
		if value == EVENT_VALUE_KEY_PRESS then
			pressed = true
		elseif value == EVENT_VALUE_KEY_RELEASE then
			pressed = false
		else
			return -- we don't know how to handle this.
		end

		-- will toggle state 
		if code == KEY_SYM then sym = pressed
		elseif code == KEY_SHIFT then shift = pressed

		-- number keys, not present on K3
		elseif code == KEY_1 then SendKeyEvent(XK_1, pressed)
		elseif code == KEY_2 then SendKeyEvent(XK_2, pressed)
		elseif code == KEY_3 then SendKeyEvent(XK_3, pressed)
		elseif code == KEY_4 then SendKeyEvent(XK_4, pressed)
		elseif code == KEY_5 then SendKeyEvent(XK_5, pressed)
		elseif code == KEY_6 then SendKeyEvent(XK_6, pressed)
		elseif code == KEY_7 then SendKeyEvent(XK_7, pressed)
		elseif code == KEY_8 then SendKeyEvent(XK_8, pressed)
		elseif code == KEY_9 then SendKeyEvent(XK_9, pressed)
		elseif code == KEY_0 then SendKeyEvent(XK_0, pressed)

		-- letter keys
		elseif not shift and code == KEY_Q then SendKeyEvent(XK_q, pressed)
		elseif not shift and code == KEY_W then SendKeyEvent(XK_w, pressed)
		elseif not shift and code == KEY_E then SendKeyEvent(XK_e, pressed)
		elseif not shift and code == KEY_R then SendKeyEvent(XK_r, pressed)
		elseif not shift and code == KEY_T then SendKeyEvent(XK_t, pressed)
		elseif not shift and code == KEY_Y then SendKeyEvent(XK_y, pressed)
		elseif not shift and code == KEY_U then SendKeyEvent(XK_u, pressed)
		elseif not shift and code == KEY_I then SendKeyEvent(XK_i, pressed)
		elseif not shift and code == KEY_O then SendKeyEvent(XK_o, pressed)
		elseif not shift and code == KEY_P then SendKeyEvent(XK_p, pressed)
		elseif not shift and code == KEY_A then SendKeyEvent(XK_a, pressed)
		elseif not shift and code == KEY_S then SendKeyEvent(XK_s, pressed)
		elseif not shift and code == KEY_D then SendKeyEvent(XK_d, pressed)
		elseif not shift and code == KEY_F then SendKeyEvent(XK_f, pressed)
		elseif not shift and code == KEY_G then SendKeyEvent(XK_g, pressed)
		elseif not shift and code == KEY_H then SendKeyEvent(XK_h, pressed)
		elseif not shift and code == KEY_J then SendKeyEvent(XK_j, pressed)
		elseif not shift and code == KEY_K then SendKeyEvent(XK_k, pressed)
		elseif not shift and code == KEY_L then SendKeyEvent(XK_l, pressed)
		elseif not shift and code == KEY_Z then SendKeyEvent(XK_z, pressed)
		elseif not shift and code == KEY_X then SendKeyEvent(XK_x, pressed)
		elseif not shift and code == KEY_C then SendKeyEvent(XK_c, pressed)
		elseif not shift and code == KEY_V then SendKeyEvent(XK_v, pressed)
		elseif not shift and code == KEY_B then SendKeyEvent(XK_b, pressed)
		elseif not shift and code == KEY_N then SendKeyEvent(XK_n, pressed)
		elseif not shift and code == KEY_M then SendKeyEvent(XK_m, pressed)
		elseif shift and code == KEY_Q then SendKeyEvent(XK_Q, pressed)
		elseif shift and code == KEY_W then SendKeyEvent(XK_W, pressed)
		elseif shift and code == KEY_E then SendKeyEvent(XK_E, pressed)
		elseif shift and code == KEY_R then SendKeyEvent(XK_R, pressed)
		elseif shift and code == KEY_T then SendKeyEvent(XK_T, pressed)
		elseif shift and code == KEY_Y then SendKeyEvent(XK_Y, pressed)
		elseif shift and code == KEY_U then SendKeyEvent(XK_U, pressed)
		elseif shift and code == KEY_I then SendKeyEvent(XK_I, pressed)
		elseif shift and code == KEY_O then SendKeyEvent(XK_O, pressed)
		elseif shift and code == KEY_P then SendKeyEvent(XK_P, pressed)
		elseif shift and code == KEY_A then SendKeyEvent(XK_A, pressed)
		elseif shift and code == KEY_S then SendKeyEvent(XK_S, pressed)
		elseif shift and code == KEY_D then SendKeyEvent(XK_D, pressed)
		elseif shift and code == KEY_F then SendKeyEvent(XK_F, pressed)
		elseif shift and code == KEY_G then SendKeyEvent(XK_G, pressed)
		elseif shift and code == KEY_H then SendKeyEvent(XK_H, pressed)
		elseif shift and code == KEY_J then SendKeyEvent(XK_J, pressed)
		elseif shift and code == KEY_K then SendKeyEvent(XK_K, pressed)
		elseif shift and code == KEY_L then SendKeyEvent(XK_L, pressed)
		elseif shift and code == KEY_Z then SendKeyEvent(XK_Z, pressed)
		elseif shift and code == KEY_X then SendKeyEvent(XK_X, pressed)
		elseif shift and code == KEY_C then SendKeyEvent(XK_C, pressed)
		elseif shift and code == KEY_V then SendKeyEvent(XK_V, pressed)
		elseif shift and code == KEY_B then SendKeyEvent(XK_B, pressed)
		elseif shift and code == KEY_N then SendKeyEvent(XK_N, pressed)
		elseif shift and code == KEY_M then SendKeyEvent(XK_M, pressed)

		-- other keys
		elseif not shift and code == KEY_DEL then SendKeyEvent(XK_Delete, pressed)
		elseif shift and code == KEY_DEL then SendKeyEvent(XK_BackSpace, pressed)
		elseif code == KEY_DOT then SendKeyEvent(XK_period, pressed)
		elseif code == KEY_SLASH then SendKeyEvent(XK_slash, pressed)
		elseif code == KEY_ENTER then SendKeyEvent(XK_Return, pressed)
		elseif code == KEY_SPACE then SendKeyEvent(XK_space, pressed)

		elseif code == KEY_ALT then SendKeyEvent(XK_Alt_L, pressed)
		elseif code == KEY_AA then SendKeyEvent(XK_Control_L, pressed)

		-- special keys
		--elseif code == KEY_VPLUS then SendKeyEvent(XK_, pressed)
		--elseif code == KEY_VMINUS then SendKeyEvent(XK_, pressed)
		elseif code == KEY_HOME then
			Quit()
		elseif code == KEY_PGBCK then SendKeyEvent(XK_Escape, pressed)
		elseif code == KEY_PGFWD then SendKeyEvent(XK_Tab, pressed)
		-- the following two exist only on K3
		elseif code == KEY_LPGBCK then SendKeyEvent(XK_Escape, pressed)
		elseif code == KEY_LPGFWD then SendKeyEvent(XK_Tab, pressed)
		--elseif code == KEY_MENU then SendKeyEvent(XK_, pressed)
		--elseif code == KEY_BACK then SendKeyEvent(XK_, pressed)
		elseif code == KEY_FW_LEFT then SendKeyEvent(XK_Left, pressed)
		elseif code == KEY_FW_RIGHT then SendKeyEvent(XK_Right, pressed)
		elseif code == KEY_FW_UP then SendKeyEvent(XK_Up, pressed)
		elseif code == KEY_FW_DOWN then SendKeyEvent(XK_Down, pressed)
		elseif code == KEY_FW_PRESS then SendKeyEvent(XK_Return, pressed)
		end
	end
end


================================================
FILE: ffi/SDL.lua
================================================
--[[
Module for interfacing SDL video/input facilities

This module is intended to provide input/output facilities on a
typical desktop (rather than a dedicated e-ink reader, for which
there would probably be raw framebuffer/input device access
instead).
]]

local ffi = require("ffi")

local dummy = require("ffi/SDL1_2_h")
local dummy = require("ffi/linux_input_h")

-----------------------------------------------------------------

local SDL = ffi.load("SDL")

local S = {
	screen = nil,
	SDL = SDL
}

-- initialization for both input and eink output
function S.open()
	if SDL.SDL_WasInit(SDL.SDL_INIT_VIDEO) ~= 0 then
		-- already initialized
		return true
	end
	if SDL.SDL_Init(SDL.SDL_INIT_VIDEO) ~= 0 then
		error("cannot initialize SDL")
	end

	-- set up screen (window)
	S.screen = SDL.SDL_SetVideoMode(
		tonumber(os.getenv("EMULATE_READER_W")) or 600,
		tonumber(os.getenv("EMULATE_READER_H")) or 800,
		32, SDL.SDL_HWSURFACE)

	-- init keyboard delay/repeat rate
	SDL.SDL_EnableKeyRepeat(500, 10)
end

return S


================================================
FILE: ffi/SDL1_2_h.lua
================================================
local ffi = require("ffi")
ffi.cdef[[
typedef unsigned int Uint32;
typedef int Sint32;
typedef short unsigned int Uint16;
typedef short int Sint16;
typedef unsigned char Uint8;
typedef signed char Sint8;
struct SDL_keysym {
  unsigned char scancode;
  enum {
    SDLK_UNKNOWN = 0,
    SDLK_FIRST = 0,
    SDLK_BACKSPACE = 8,
    SDLK_TAB = 9,
    SDLK_CLEAR = 12,
    SDLK_RETURN = 13,
    SDLK_PAUSE = 19,
    SDLK_ESCAPE = 27,
    SDLK_SPACE = 32,
    SDLK_EXCLAIM = 33,
    SDLK_QUOTEDBL = 34,
    SDLK_HASH = 35,
    SDLK_DOLLAR = 36,
    SDLK_AMPERSAND = 38,
    SDLK_QUOTE = 39,
    SDLK_LEFTPAREN = 40,
    SDLK_RIGHTPAREN = 41,
    SDLK_ASTERISK = 42,
    SDLK_PLUS = 43,
    SDLK_COMMA = 44,
    SDLK_MINUS = 45,
    SDLK_PERIOD = 46,
    SDLK_SLASH = 47,
    SDLK_0 = 48,
    SDLK_1 = 49,
    SDLK_2 = 50,
    SDLK_3 = 51,
    SDLK_4 = 52,
    SDLK_5 = 53,
    SDLK_6 = 54,
    SDLK_7 = 55,
    SDLK_8 = 56,
    SDLK_9 = 57,
    SDLK_COLON = 58,
    SDLK_SEMICOLON = 59,
    SDLK_LESS = 60,
    SDLK_EQUALS = 61,
    SDLK_GREATER = 62,
    SDLK_QUESTION = 63,
    SDLK_AT = 64,
    SDLK_LEFTBRACKET = 91,
    SDLK_BACKSLASH = 92,
    SDLK_RIGHTBRACKET = 93,
    SDLK_CARET = 94,
    SDLK_UNDERSCORE = 95,
    SDLK_BACKQUOTE = 96,
    SDLK_a = 97,
    SDLK_b = 98,
    SDLK_c = 99,
    SDLK_d = 100,
    SDLK_e = 101,
    SDLK_f = 102,
    SDLK_g = 103,
    SDLK_h = 104,
    SDLK_i = 105,
    SDLK_j = 106,
    SDLK_k = 107,
    SDLK_l = 108,
    SDLK_m = 109,
    SDLK_n = 110,
    SDLK_o = 111,
    SDLK_p = 112,
    SDLK_q = 113,
    SDLK_r = 114,
    SDLK_s = 115,
    SDLK_t = 116,
    SDLK_u = 117,
    SDLK_v = 118,
    SDLK_w = 119,
    SDLK_x = 120,
    SDLK_y = 121,
    SDLK_z = 122,
    SDLK_DELETE = 127,
    SDLK_WORLD_0 = 160,
    SDLK_WORLD_1 = 161,
    SDLK_WORLD_2 = 162,
    SDLK_WORLD_3 = 163,
    SDLK_WORLD_4 = 164,
    SDLK_WORLD_5 = 165,
    SDLK_WORLD_6 = 166,
    SDLK_WORLD_7 = 167,
    SDLK_WORLD_8 = 168,
    SDLK_WORLD_9 = 169,
    SDLK_WORLD_10 = 170,
    SDLK_WORLD_11 = 171,
    SDLK_WORLD_12 = 172,
    SDLK_WORLD_13 = 173,
    SDLK_WORLD_14 = 174,
    SDLK_WORLD_15 = 175,
    SDLK_WORLD_16 = 176,
    SDLK_WORLD_17 = 177,
    SDLK_WORLD_18 = 178,
    SDLK_WORLD_19 = 179,
    SDLK_WORLD_20 = 180,
    SDLK_WORLD_21 = 181,
    SDLK_WORLD_22 = 182,
    SDLK_WORLD_23 = 183,
    SDLK_WORLD_24 = 184,
    SDLK_WORLD_25 = 185,
    SDLK_WORLD_26 = 186,
    SDLK_WORLD_27 = 187,
    SDLK_WORLD_28 = 188,
    SDLK_WORLD_29 = 189,
    SDLK_WORLD_30 = 190,
    SDLK_WORLD_31 = 191,
    SDLK_WORLD_32 = 192,
    SDLK_WORLD_33 = 193,
    SDLK_WORLD_34 = 194,
    SDLK_WORLD_35 = 195,
    SDLK_WORLD_36 = 196,
    SDLK_WORLD_37 = 197,
    SDLK_WORLD_38 = 198,
    SDLK_WORLD_39 = 199,
    SDLK_WORLD_40 = 200,
    SDLK_WORLD_41 = 201,
    SDLK_WORLD_42 = 202,
    SDLK_WORLD_43 = 203,
    SDLK_WORLD_44 = 204,
    SDLK_WORLD_45 = 205,
    SDLK_WORLD_46 = 206,
    SDLK_WORLD_47 = 207,
    SDLK_WORLD_48 = 208,
    SDLK_WORLD_49 = 209,
    SDLK_WORLD_50 = 210,
    SDLK_WORLD_51 = 211,
    SDLK_WORLD_52 = 212,
    SDLK_WORLD_53 = 213,
    SDLK_WORLD_54 = 214,
    SDLK_WORLD_55 = 215,
    SDLK_WORLD_56 = 216,
    SDLK_WORLD_57 = 217,
    SDLK_WORLD_58 = 218,
    SDLK_WORLD_59 = 219,
    SDLK_WORLD_60 = 220,
    SDLK_WORLD_61 = 221,
    SDLK_WORLD_62 = 222,
    SDLK_WORLD_63 = 223,
    SDLK_WORLD_64 = 224,
    SDLK_WORLD_65 = 225,
    SDLK_WORLD_66 = 226,
    SDLK_WORLD_67 = 227,
    SDLK_WORLD_68 = 228,
    SDLK_WORLD_69 = 229,
    SDLK_WORLD_70 = 230,
    SDLK_WORLD_71 = 231,
    SDLK_WORLD_72 = 232,
    SDLK_WORLD_73 = 233,
    SDLK_WORLD_74 = 234,
    SDLK_WORLD_75 = 235,
    SDLK_WORLD_76 = 236,
    SDLK_WORLD_77 = 237,
    SDLK_WORLD_78 = 238,
    SDLK_WORLD_79 = 239,
    SDLK_WORLD_80 = 240,
    SDLK_WORLD_81 = 241,
    SDLK_WORLD_82 = 242,
    SDLK_WORLD_83 = 243,
    SDLK_WORLD_84 = 244,
    SDLK_WORLD_85 = 245,
    SDLK_WORLD_86 = 246,
    SDLK_WORLD_87 = 247,
    SDLK_WORLD_88 = 248,
    SDLK_WORLD_89 = 249,
    SDLK_WORLD_90 = 250,
    SDLK_WORLD_91 = 251,
    SDLK_WORLD_92 = 252,
    SDLK_WORLD_93 = 253,
    SDLK_WORLD_94 = 254,
    SDLK_WORLD_95 = 255,
    SDLK_KP0 = 256,
    SDLK_KP1 = 257,
    SDLK_KP2 = 258,
    SDLK_KP3 = 259,
    SDLK_KP4 = 260,
    SDLK_KP5 = 261,
    SDLK_KP6 = 262,
    SDLK_KP7 = 263,
    SDLK_KP8 = 264,
    SDLK_KP9 = 265,
    SDLK_KP_PERIOD = 266,
    SDLK_KP_DIVIDE = 267,
    SDLK_KP_MULTIPLY = 268,
    SDLK_KP_MINUS = 269,
    SDLK_KP_PLUS = 270,
    SDLK_KP_ENTER = 271,
    SDLK_KP_EQUALS = 272,
    SDLK_UP = 273,
    SDLK_DOWN = 274,
    SDLK_RIGHT = 275,
    SDLK_LEFT = 276,
    SDLK_INSERT = 277,
    SDLK_HOME = 278,
    SDLK_END = 279,
    SDLK_PAGEUP = 280,
    SDLK_PAGEDOWN = 281,
    SDLK_F1 = 282,
    SDLK_F2 = 283,
    SDLK_F3 = 284,
    SDLK_F4 = 285,
    SDLK_F5 = 286,
    SDLK_F6 = 287,
    SDLK_F7 = 288,
    SDLK_F8 = 289,
    SDLK_F9 = 290,
    SDLK_F10 = 291,
    SDLK_F11 = 292,
    SDLK_F12 = 293,
    SDLK_F13 = 294,
    SDLK_F14 = 295,
    SDLK_F15 = 296,
    SDLK_NUMLOCK = 300,
    SDLK_CAPSLOCK = 301,
    SDLK_SCROLLOCK = 302,
    SDLK_RSHIFT = 303,
    SDLK_LSHIFT = 304,
    SDLK_RCTRL = 305,
    SDLK_LCTRL = 306,
    SDLK_RALT = 307,
    SDLK_LALT = 308,
    SDLK_RMETA = 309,
    SDLK_LMETA = 310,
    SDLK_LSUPER = 311,
    SDLK_RSUPER = 312,
    SDLK_MODE = 313,
    SDLK_COMPOSE = 314,
    SDLK_HELP = 315,
    SDLK_PRINT = 316,
    SDLK_SYSREQ = 317,
    SDLK_BREAK = 318,
    SDLK_MENU = 319,
    SDLK_POWER = 320,
    SDLK_EURO = 321,
    SDLK_UNDO = 322,
    SDLK_LAST = 323,
  } sym;
  enum {
    KMOD_NONE = 0,
    KMOD_LSHIFT = 1,
    KMOD_RSHIFT = 2,
    KMOD_LCTRL = 64,
    KMOD_RCTRL = 128,
    KMOD_LALT = 256,
    KMOD_RALT = 512,
    KMOD_LMETA = 1024,
    KMOD_RMETA = 2048,
    KMOD_NUM = 4096,
    KMOD_CAPS = 8192,
    KMOD_MODE = 16384,
    KMOD_RESERVED = 32768,
  } mod;
  short unsigned int unicode;
};
typedef enum {
  SDL_NOEVENT = 0,
  SDL_ACTIVEEVENT = 1,
  SDL_KEYDOWN = 2,
  SDL_KEYUP = 3,
  SDL_MOUSEMOTION = 4,
  SDL_MOUSEBUTTONDOWN = 5,
  SDL_MOUSEBUTTONUP = 6,
  SDL_JOYAXISMOTION = 7,
  SDL_JOYBALLMOTION = 8,
  SDL_JOYHATMOTION = 9,
  SDL_JOYBUTTONDOWN = 10,
  SDL_JOYBUTTONUP = 11,
  SDL_QUIT = 12,
  SDL_SYSWMEVENT = 13,
  SDL_EVENT_RESERVEDA = 14,
  SDL_EVENT_RESERVEDB = 15,
  SDL_VIDEORESIZE = 16,
  SDL_VIDEOEXPOSE = 17,
  SDL_EVENT_RESERVED2 = 18,
  SDL_EVENT_RESERVED3 = 19,
  SDL_EVENT_RESERVED4 = 20,
  SDL_EVENT_RESERVED5 = 21,
  SDL_EVENT_RESERVED6 = 22,
  SDL_EVENT_RESERVED7 = 23,
  SDL_USEREVENT = 24,
  SDL_NUMEVENTS = 32,
} SDL_EventType;
typedef enum {
  SDL_ACTIVEEVENTMASK = 2,
  SDL_KEYDOWNMASK = 4,
  SDL_KEYUPMASK = 8,
  SDL_KEYEVENTMASK = 12,
  SDL_MOUSEMOTIONMASK = 16,
  SDL_MOUSEBUTTONDOWNMASK = 32,
  SDL_MOUSEBUTTONUPMASK = 64,
  SDL_MOUSEEVENTMASK = 112,
  SDL_JOYAXISMOTIONMASK = 128,
  SDL_JOYBALLMOTIONMASK = 256,
  SDL_JOYHATMOTIONMASK = 512,
  SDL_JOYBUTTONDOWNMASK = 1024,
  SDL_JOYBUTTONUPMASK = 2048,
  SDL_JOYEVENTMASK = 3968,
  SDL_VIDEORESIZEMASK = 65536,
  SDL_VIDEOEXPOSEMASK = 131072,
  SDL_QUITMASK = 4096,
  SDL_SYSWMEVENTMASK = 8192,
} SDL_EventMask;
struct SDL_ActiveEvent {
  unsigned char type;
  unsigned char gain;
  unsigned char state;
};
struct SDL_KeyboardEvent {
  unsigned char type;
  unsigned char which;
  unsigned char state;
  struct SDL_keysym keysym;
};
struct SDL_MouseMotionEvent {
  unsigned char type;
  unsigned char which;
  unsigned char state;
  short unsigned int x;
  short unsigned int y;
  short int xrel;
  short int yrel;
};
struct SDL_MouseButtonEvent {
  unsigned char type;
  unsigned char which;
  unsigned char button;
  unsigned char state;
  short unsigned int x;
  short unsigned int y;
};
struct SDL_JoyAxisEvent {
  unsigned char type;
  unsigned char which;
  unsigned char axis;
  short int value;
};
struct SDL_JoyBallEvent {
  unsigned char type;
  unsigned char which;
  unsigned char ball;
  short int xrel;
  short int yrel;
};
struct SDL_JoyHatEvent {
  unsigned char type;
  unsigned char which;
  unsigned char hat;
  unsigned char value;
};
struct SDL_JoyButtonEvent {
  unsigned char type;
  unsigned char which;
  unsigned char button;
  unsigned char state;
};
struct SDL_ResizeEvent {
  unsigned char type;
  int w;
  int h;
};
struct SDL_ExposeEvent {
  unsigned char type;
};
struct SDL_QuitEvent {
  unsigned char type;
};
struct SDL_UserEvent {
  unsigned char type;
  int code;
  void *data1;
  void *data2;
};
struct SDL_SysWMEvent {
  unsigned char type;
  struct SDL_SysWMmsg *msg;
};
union SDL_Event {
  unsigned char type;
  struct SDL_ActiveEvent active;
  struct SDL_KeyboardEvent key;
  struct SDL_MouseMotionEvent motion;
  struct SDL_MouseButtonEvent button;
  struct SDL_JoyAxisEvent jaxis;
  struct SDL_JoyBallEvent jball;
  struct SDL_JoyHatEvent jhat;
  struct SDL_JoyButtonEvent jbutton;
  struct SDL_ResizeEvent resize;
  struct SDL_ExposeEvent expose;
  struct SDL_QuitEvent quit;
  struct SDL_UserEvent user;
  struct SDL_SysWMEvent syswm;
};
struct SDL_Rect {
  short int x;
  short int y;
  short unsigned int w;
  short unsigned int h;
};
struct SDL_Color {
  unsigned char r;
  unsigned char g;
  unsigned char b;
  unsigned char unused;
};
struct SDL_Palette {
  int ncolors;
  struct SDL_Color *colors;
};
struct SDL_PixelFormat {
  struct SDL_Palette *palette;
  unsigned char BitsPerPixel;
  unsigned char BytesPerPixel;
  unsigned char Rloss;
  unsigned char Gloss;
  unsigned char Bloss;
  unsigned char Aloss;
  unsigned char Rshift;
  unsigned char Gshift;
  unsigned char Bshift;
  unsigned char Ashift;
  unsigned int Rmask;
  unsigned int Gmask;
  unsigned int Bmask;
  unsigned int Amask;
  unsigned int colorkey;
  unsigned char alpha;
};
struct SDL_Surface {
  unsigned int flags;
  struct SDL_PixelFormat *format;
  int w;
  int h;
  short unsigned int pitch;
  void *pixels;
  int offset;
  struct private_hwdata *hwdata;
  struct SDL_Rect clip_rect;
  unsigned int unused1;
  unsigned int locked;
  struct SDL_BlitMap *map;
  unsigned int format_version;
  int refcount;
};
int SDL_Init(unsigned int) __attribute__((visibility("default")));
unsigned int SDL_WasInit(unsigned int) __attribute__((visibility("default")));
void SDL_Quit(void) __attribute__((visibility("default")));
struct SDL_Surface *SDL_SetVideoMode(int, int, int, unsigned int) __attribute__((visibility("default")));
int SDL_EnableKeyRepeat(int, int) __attribute__((visibility("default")));
int SDL_WaitEvent(union SDL_Event *) __attribute__((visibility("default")));
int SDL_PollEvent(union SDL_Event *) __attribute__((visibility("default")));
unsigned int SDL_GetTicks(void) __attribute__((visibility("default")));
void SDL_Delay(unsigned int) __attribute__((visibility("default")));
int SDL_LockSurface(struct SDL_Surface *) __attribute__((visibility("default")));
void SDL_UnlockSurface(struct SDL_Surface *) __attribute__((visibility("default")));
int SDL_FillRect(struct SDL_Surface *, struct SDL_Rect *, unsigned int) __attribute__((visibility("default")));
int SDL_Flip(struct SDL_Surface *) __attribute__((visibility("default")));
unsigned int SDL_MapRGB(const struct SDL_PixelFormat *const, const unsigned char, const unsigned char, const unsigned char) __attribute__((visibility("default")));
static const int SDL_INIT_TIMER = 1;
static const int SDL_INIT_AUDIO = 16;
static const int SDL_INIT_VIDEO = 32;
static const int SDL_INIT_CDROM = 256;
static const int SDL_INIT_JOYSTICK = 512;
static const int SDL_INIT_NOPARACHUTE = 1048576;
static const int SDL_INIT_EVENTTHREAD = 16777216;
static const int SDL_INIT_EVERYTHING = 65535;
static const int SDL_SWSURFACE = 0;
static const int SDL_HWSURFACE = 1;
static const int SDL_ASYNCBLIT = 4;
static const int SDL_ANYFORMAT = 268435456;
static const int SDL_HWPALETTE = 536870912;
static const int SDL_DOUBLEBUF = 1073741824;
static const int SDL_FULLSCREEN = 2147483648;
static const int SDL_OPENGL = 2;
static const int SDL_OPENGLBLIT = 10;
static const int SDL_RESIZABLE = 16;
static const int SDL_NOFRAME = 32;
static const int SDL_HWACCEL = 256;
static const int SDL_SRCCOLORKEY = 4096;
static const int SDL_RLEACCELOK = 8192;
static const int SDL_RLEACCEL = 16384;
static const int SDL_SRCALPHA = 65536;
static const int SDL_PREALLOC = 16777216;
]]


================================================
FILE: ffi/blitbuffer.lua
================================================
--[[
Generic blitbuffer/GFX stuff that works on memory buffers
--]]

local ffi = require("ffi")
local util = require("ffi/util")

-- we will use this extensively
local floor = math.floor
local rshift = bit.rshift
local lshift = bit.lshift
local band = bit.band
local bor = bit.bor
local bxor = bit.bxor

local intt = ffi.typeof("int")
local uint32pt = ffi.typeof("uint32_t*")
local uint8pt = ffi.typeof("uint8_t*")
local posix = require("ffi/posix_h")

-- the following definitions are redundant.
-- they need to be since only this way we can set
-- different metatables for them.
ffi.cdef[[
typedef struct Color4L {
    uint8_t a;
} Color4L;
typedef struct Color4U {
    uint8_t a;
} Color4U;
typedef struct Color8 {
    uint8_t a;
} Color8;
typedef struct Color8A {
    uint8_t a;
    uint8_t dummy; // only support pre-multiplied for now
} Color8A;
typedef struct ColorRGB16 {
    uint16_t v;
} ColorRGB16;
typedef struct ColorRGB24 {
    uint8_t r;
    uint8_t g;
    uint8_t b;
} ColorRGB24;
typedef struct ColorRGB32 {
    uint8_t r;
    uint8_t g;
    uint8_t b;
    uint8_t a;
} ColorRGB32;
typedef struct ColorBGR32 {
    uint8_t r;
    uint8_t g;
    uint8_t b;
    uint8_t a;
} ColorBGR32;

typedef struct BlitBuffer4 {
    int w;
    int h;
    int pitch;
    uint8_t *data;
    uint8_t config;
} BlitBuffer4;
typedef struct BlitBuffer8 {
    int w;
    int h;
    int pitch;
    Color8 *data;
    uint8_t config;
} BlitBuffer8;
typedef struct BlitBuffer8A {
    int w;
    int h;
    int pitch;
    Color8A *data;
    uint8_t config;
} BlitBuffer8A;
typedef struct BlitBufferRGB16 {
    int w;
    int h;
    int pitch;
    ColorRGB16 *data;
    uint8_t config;
} BlitBufferRGB16;
typedef struct BlitBufferRGB24 {
    int w;
    int h;
    int pitch;
    ColorRGB24 *data;
    uint8_t config;
} BlitBufferRGB24;
typedef struct BlitBufferRGB32 {
    int w;
    int h;
    int pitch;
    ColorRGB32 *data;
    uint8_t config;
} BlitBufferRGB32;
typedef struct BlitBufferBGR32 {
    int w;
    int h;
    int pitch;
    ColorBGR32 *data;
    uint8_t config;
} BlitBufferBGR32;

void *malloc(int size);
void free(void *ptr);
]]

-- color value types
local Color4U = ffi.typeof("Color4U")
local Color4L = ffi.typeof("Color4L")
local Color8 = ffi.typeof("Color8")
local Color8A = ffi.typeof("Color8A")
local ColorRGB16 = ffi.typeof("ColorRGB16")
local ColorRGB24 = ffi.typeof("ColorRGB24")
local ColorRGB32 = ffi.typeof("ColorRGB32")
local ColorBGR32 = ffi.typeof("ColorBGR32")

-- color value pointer types
local P_Color4U = ffi.typeof("Color4U*")
local P_Color4L = ffi.typeof("Color4L*")
local P_Color8 = ffi.typeof("Color8*")
local P_Color8A = ffi.typeof("Color8A*")
local P_ColorRGB16 = ffi.typeof("ColorRGB16*")
local P_ColorRGB24 = ffi.typeof("ColorRGB24*")
local P_ColorRGB32 = ffi.typeof("ColorRGB32*")
local P_ColorBGR32 = ffi.typeof("ColorBGR32*")

-- metatables for color types:
local Color4L_mt = {__index={}}
local Color4U_mt = {__index={}}
local Color8_mt = {__index={}}
local Color8A_mt = {__index={}}
local ColorRGB16_mt = {__index={}}
local ColorRGB24_mt = {__index={}}
local ColorRGB32_mt = {__index={}}
local ColorBGR32_mt = {__index={}}

-- color setting
function Color4L_mt.__index:set(color)
    self.a = bor(band(0xF0, self.a), color:getColor4L().a)
end
function Color4U_mt.__index:set(color)
    self.a = bor(band(0x0F, self.a), color:getColor4U().a)
end
function Color8_mt.__index:set(color) self.a = color:getColor8().a end
function Color8A_mt.__index:set(color) self.a = color:getColor8A().a end
function ColorRGB16_mt.__index:set(color) self.v = color:getColorRGB16().v end
function ColorRGB24_mt.__index:set(color)
    local c = color:getColorRGB24()
    self.r = c.r
    self.g = c.g
    self.b = c.b
end
function ColorRGB32_mt.__index:set(color)
    local c = color:getColorRGB32()
    self.r = c.r
    self.g = c.g
    self.b = c.b
end
function ColorBGR32_mt.__index:set(color)
    local c = color:getColorBGR32()
    self.r = c.r
    self.g = c.g
    self.b = c.b
end
-- adding two colors:
function Color4L_mt.__index:add(color, intensity)
    local value = tonumber(self.a) * (1-intensity) + tonumber(color:getColor4L().a) * intensity
    if value > 0x0F then value = 0x0F end
    self:set(Color4L(value))
end
function Color4U_mt.__index:add(color, intensity)
    local orig = band(self.a, 0xF0)
    local value = tonumber(orig) * (1-intensity) + tonumber(color:getColor4U().a) * intensity
    if value > 0xF0 then value = 0xF0 end
    self:set(Color4U(band(0xF0, value)))
end
function Color8_mt.__index:add(color, intensity)
    local value = tonumber(self.a) * (1-intensity) + tonumber(color:getColor8().a) * intensity
    if value > 0xFF then value = 0xFF end
    self:set(Color8(value))
end
Color8A_mt.__index.add = Color8_mt.__index.add
function ColorRGB16_mt.__index:add(color, intensity)
    local r = tonumber(self:getR()) * (1-intensity) + tonumber(color:getR()) * intensity
    if r > 255 then r = 255 end
    local g = tonumber(self:getG()) * (1-intensity) + tonumber(color:getG()) * intensity
    if g > 255 then g = 255 end
    local b = tonumber(self:getB()) * (1-intensity) + tonumber(color:getB()) * intensity
    if b > 255 then b = 255 end
    self:set(ColorRGB24(r, g, b))
end
ColorRGB24_mt.__index.add = ColorRGB16_mt.__index.add
ColorRGB32_mt.__index.add = ColorRGB16_mt.__index.add
ColorBGR32_mt.__index.add = ColorRGB16_mt.__index.add

-- dimming
function Color4L_mt.__index:dim()
    return Color8(rshift(self:getColor8().a, 1))
end
Color4U_mt.__index.dim = Color4L_mt.__index.dim
Color8_mt.__index.dim = Color4L_mt.__index.dim
Color8A_mt.__index.dim = Color4L_mt.__index.dim
ColorRGB16_mt.__index.dim = Color4L_mt.__index.dim
ColorRGB24_mt.__index.dim = Color4L_mt.__index.dim
ColorRGB32_mt.__index.dim = Color4L_mt.__index.dim
ColorBGR32_mt.__index.dim = Color4L_mt.__index.dim
-- lighten up
function Color4L_mt.__index:lighten(low)
    local value = self:getColor4L().a
    low = low * 0x0F
    if value < low then
        return Color4L(low)
    else
        return self
    end
end
Color4U_mt.__index.lighten = Color4L_mt.__index.lighten
Color8_mt.__index.lighten = Color4L_mt.__index.lighten
Color8A_mt.__index.lighten = Color4L_mt.__index.lighten
ColorRGB16_mt.__index.lighten = Color4L_mt.__index.lighten
ColorRGB24_mt.__index.lighten = Color4L_mt.__index.lighten
ColorRGB32_mt.__index.lighten = Color4L_mt.__index.lighten
ColorBGR32_mt.__index.lighten = Color4L_mt.__index.lighten

-- color conversions:
-- to Color4L:
function Color4L_mt.__index:getColor4L() return Color4L(band(0x0F, self.a)) end
function Color4U_mt.__index:getColor4L() return Color4L(rshift(self.a, 4)) end
function Color8_mt.__index:getColor4L() return Color4L(rshift(self.a, 4)) end
function Color8A_mt.__index:getColor4L() return Color4L(rshift(self.a, 4)) end
--[[
Uses luminance match for approximating the human perception of colour, as per
http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale

L = 0.299*Red + 0.587*Green + 0.114*Blue
--]]
function ColorRGB16_mt.__index:getColor4L()
    local r = rshift(self.v, 11)
    local g = band(rshift(self.v, 5, 0x3F))
    local b = band(self.v, 0x001F)
    return Color4L(rshift(39190*r + 38469*g + 14942*b, 18))
end
function ColorRGB24_mt.__index:getColor4L()
    return Color4L(rshift(4897*self.r + 9617*self.g + 1868*self.b, 18))
end
ColorRGB32_mt.__index.getColor4L = ColorRGB24_mt.__index.getColor4L
ColorBGR32_mt.__index.getColor4L = ColorRGB24_mt.__index.getColor4L

-- to Color4U:
function Color4L_mt.__index:getColor4U() return Color4U(lshift(self.a, 4)) end
function Color4U_mt.__index:getColor4U() return Color4U(band(0xF0, self.a)) end
function Color8_mt.__index:getColor4U() return Color4U(band(0xF0, self.a)) end
function Color8A_mt.__index:getColor4U() return Color4U(band(0xF0, self.a)) end
function ColorRGB16_mt.__index:getColor4U()
    local r = rshift(self.v, 11)
    local g = band(rshift(self.v, 5, 0x3F))
    local b = band(self.v, 0x001F)
    return Color4U(band(0xF0, rshift(39190*r + 38469*g + 14942*b, 14)))
end
function ColorRGB24_mt.__index:getColor4U()
    return Color4U(band(0xF0, rshift(4897*self.r + 9617*self.g + 1868*self.b, 14)))
end
ColorRGB32_mt.__index.getColor4U = ColorRGB24_mt.__index.getColor4U
ColorBGR32_mt.__index.getColor4U = ColorRGB24_mt.__index.getColor4U

-- to Color8:
function Color4L_mt.__index:getColor8()
    local v = band(0x0F, self.a)
    return Color8(v*0x11)
end
function Color4U_mt.__index:getColor8()
    local v = band(0xF0, self.a)
    return Color8(bor(rshift(v, 4), v))
end
function Color8_mt.__index:getColor8() return self end
function Color8A_mt.__index:getColor8() return Color8(self.a) end
function ColorRGB16_mt.__index:getColor8()
    local r = rshift(self.v, 11)
    local g = band(rshift(self.v, 5, 0x3F))
    local b = band(self.v, 0x001F)
    return Color8(rshift(39190*r + 38469*g + 14942*b, 14))
end
function ColorRGB24_mt.__index:getColor8()
    return Color8(rshift(4897*self:getR() + 9617*self:getG() + 1868*self:getB(), 14))
end
ColorRGB32_mt.__index.getColor8 = ColorRGB24_mt.__index.getColor8
ColorBGR32_mt.__index.getColor8 = ColorRGB24_mt.__index.getColor8

-- to Color8A:
function Color4L_mt.__index:getColor8A()
    local v = band(0x0F, self.a)
    return Color8A(v*0x11)
end
function Color4U_mt.__index:getColor8A()
    local v = band(0xF0, self.a)
    return Color8A(bor(rshift(v, 4), v))
end
function Color8_mt.__index:getColor8A() return Color8A(self.a) end
function Color8A_mt.__index:getColor8A() return self end
function ColorRGB16_mt.__index:getColor8A()
    local r = rshift(self.v, 11)
    local g = band(rshift(self.v, 5, 0x3F))
    local b = band(self.v, 0x001F)
    return Color8A(rshift(39190*r + 38469*g + 14942*b, 14))
end
function ColorRGB24_mt.__index:getColor8A()
    return Color8A(rshift(4897*self:getR() + 9617*self:getG() + 1868*self:getB(), 14))
end
ColorRGB32_mt.__index.getColor8A = ColorRGB24_mt.__index.getColor8A
ColorBGR32_mt.__index.getColor8A = ColorRGB24_mt.__index.getColor8A

-- to ColorRGB16:
function Color4L_mt.__index:getColorRGB16()
    local v = self:getColor8().a
    local v5bit = rshift(v, 3)
    return ColorRGB16(lshift(v5bit, 11) + lshift(band(v, 0xFC), 3) + v5bit)
end
Color4U_mt.__index.getColorRGB16 = Color4L_mt.__index.getColorRGB16
Color8_mt.__index.getColorRGB16 = Color4L_mt.__index.getColorRGB16
Color8A_mt.__index.getColorRGB16 = Color4L_mt.__index.getColorRGB16
function ColorRGB16_mt.__index:getColorRGB16() return self end
function ColorRGB24_mt.__index:getColorRGB16()
    return ColorRGB16(lshift(band(self.r, 0xF8), 8) + lshift(band(self.g, 0xFC), 3)  + rshift(self.b, 3))
end
ColorRGB32_mt.__index.getColorRGB16 = ColorRGB24_mt.__index.getColorRGB16
ColorBGR32_mt.__index.getColorRGB16 = ColorRGB24_mt.__index.getColorRGB16

-- to ColorRGB24:
function Color4L_mt.__index:getColorRGB24()
    local v = self:getColor8()
    return ColorRGB24(v.a, v.a, v.a)
end
Color4U_mt.__index.getColorRGB24 = Color4L_mt.__index.getColorRGB24
Color8_mt.__index.getColorRGB24 = Color4L_mt.__index.getColorRGB24
Color8A_mt.__index.getColorRGB24 = Color4L_mt.__index.getColorRGB24
function ColorRGB16_mt.__index:getColorRGB24()
    local r = rshift(self.v, 11)
    local g = band(rshift(self.v, 5), 0x3F)
    local b = band(self.v, 0x001F)
    return ColorRGB24(lshift(r, 3) + rshift(r, 2), lshift(g, 2) + rshift(g, 4), lshift(b, 3) + rshift(b, 2))
end
function ColorRGB24_mt.__index:getColorRGB24() return self end
function ColorRGB32_mt.__index:getColorRGB24() return ColorRGB24(self.r, self.g, self.b) end
ColorBGR32_mt.__index.getColorRGB24 = ColorRGB32_mt.__index.getColorRGB24

-- to ColorRGB32:
function Color4L_mt.__index:getColorRGB32()
    local v = self:getColor8()
    return ColorRGB32(v.a, v.a, v.a, 0)
end
Color4U_mt.__index.getColorRGB32 = Color4L_mt.__index.getColorRGB32
Color8_mt.__index.getColorRGB32 = Color4L_mt.__index.getColorRGB32
Color8A_mt.__index.getColorRGB32 = Color4L_mt.__index.getColorRGB32
function ColorRGB16_mt.__index:getColorRGB32()
    local r = rshift(self.v, 11)
    local g = band(rshift(self.v, 5), 0x3F)
    local b = band(self.v, 0x001F)
    return ColorRGB32(lshift(r, 3) + rshift(r, 2), lshift(g, 2) + rshift(g, 4), lshift(b, 3) + rshift(b, 2), 0)
end
function ColorRGB24_mt.__index:getColorRGB32() return ColorRGB32(self.r, self.g, self.b) end
function ColorRGB32_mt.__index:getColorRGB32() return self end
function ColorBGR32_mt.__index:getColorRGB32() return ColorRGB32(self.r, self.g, self.b) end

-- to ColorBGR32:
function Color4L_mt.__index:getColorBGR32()
    local v = self:getColor8()
    return ColorBGR32(v.a, v.a, v.a, 0)
end
Color4U_mt.__index.getColorBGR32 = Color4L_mt.__index.getColorBGR32
Color8_mt.__index.getColorBGR32 = Color4L_mt.__index.getColorBGR32
Color8A_mt.__index.getColorBGR32 = Color4L_mt.__index.getColorBGR32
function ColorRGB16_mt.__index:getColorBGR32()
    local r = rshift(self.v, 11)
    local g = band(rshift(self.v, 5), 0x3F)
    local b = band(self.v, 0x001F)
    return ColorBGR32(lshift(b, 3) + rshift(b, 2), lshift(g, 2) + rshift(g, 4), lshift(r, 3) + rshift(r, 2), 0)
end
function ColorRGB24_mt.__index:getColorBGR32() return ColorBGR32(self.b, self.g, self.r) end
function ColorRGB32_mt.__index:getColorBGR32() return ColorBGR32(self.b, self.g, self.r) end
function ColorBGR32_mt.__index:getColorBGR32() return self end

-- RGB getters (special case for 4bpp mode)
function Color4L_mt.__index:getR() return self:getColor8().a end
Color4L_mt.__index.getG = Color4L_mt.__index.getR
Color4L_mt.__index.getB = Color4L_mt.__index.getR
Color4U_mt.__index.getR = Color4L_mt.__index.getR
Color4U_mt.__index.getG = Color4L_mt.__index.getR
Color4U_mt.__index.getB = Color4L_mt.__index.getR
Color8_mt.__index.getR = Color4L_mt.__index.getR
Color8_mt.__index.getG = Color4L_mt.__index.getR
Color8_mt.__index.getB = Color4L_mt.__index.getR
Color8A_mt.__index.getR = Color4L_mt.__index.getR
Color8A_mt.__index.getG = Color4L_mt.__index.getR
Color8A_mt.__index.getB = Color4L_mt.__index.getR
function ColorRGB16_mt.__index:getR()
    local r = rshift(self.v, 11)
    return lshift(r, 3) + rshift(r, 2)
end
function ColorRGB16_mt.__index:getG()
    local g = band(rshift(self.v, 5, 0x3F))
    return lshift(g, 2) + rshift(g, 4)
end
function ColorRGB16_mt.__index:getB()
    local b = band(self.v, 0x001F)
    return lshift(b, 3) + rshift(b, 2)
end
function ColorRGB24_mt.__index:getR() return self.r end
function ColorRGB24_mt.__index:getG() return self.g end
function ColorRGB24_mt.__index:getB() return self.b end
ColorRGB32_mt.__index.getR = ColorRGB24_mt.__index.getR
ColorRGB32_mt.__index.getG = ColorRGB24_mt.__index.getG
ColorRGB32_mt.__index.getB = ColorRGB24_mt.__index.getB
function ColorRGB32_mt.__index:getAlpha() return self.a end
ColorBGR32_mt.__index.getR = ColorRGB24_mt.__index.getR
ColorBGR32_mt.__index.getG = ColorRGB24_mt.__index.getG
ColorBGR32_mt.__index.getB = ColorRGB24_mt.__index.getB
function ColorBGR32_mt.__index:getAlpha() return self.a end

-- modifications:
-- inversion:
function Color4L_mt.__index:invert() return Color4L(bxor(self.a, 0x0F)) end
function Color4U_mt.__index:invert() return Color4U(bxor(self.a, 0xF0)) end
function Color8_mt.__index:invert() return Color8(bxor(self.a, 0xFF)) end
function Color8A_mt.__index:invert() return Color8A(bxor(self.a, 0xFF)) end
function ColorRGB16_mt.__index:invert() return ColorRGB16(bxor(self.v, 0xFFFF)) end
function ColorRGB24_mt.__index:invert()
    return ColorRGB24(bxor(self.r, 0xFF), bxor(self.g, 0xFF), bxor(self.b, 0xFF))
end
function ColorRGB32_mt.__index:invert()
    return ColorRGB32(bxor(self.r, 0xFF), bxor(self.g, 0xFF), bxor(self.b, 0xFF))
end
function ColorBGR32_mt.__index:invert()
    return ColorBGR32(bxor(self.b, 0xFF), bxor(self.g, 0xFF), bxor(self.r, 0xFF))
end

-- comparison:
function Color4L_mt.__index:isEqual(c)
    return self:getR() == c:getR()
end
Color4U_mt.__index.isEqual = Color4L_mt.__index.isEqual
Color8_mt.__index.isEqual = Color4L_mt.__index.isEqual
Color8A_mt.__index.isEqual = Color4L_mt.__index.isEqual
function ColorRGB24_mt.__index:isEqual(c)
    return (self:getR() == c:getR())
    and (self:getG() == c:getG())
    and (self:getB() == c:getB())
end
ColorRGB16_mt.__index.isEqual = ColorRGB24_mt.__index.isEqual
function ColorRGB32_mt.__index:isEqual(c)
    return (self:getR() == c:getR())
    and (self:getG() == c:getG())
    and (self:getB() == c:getB())
    and (self:getAlpha() == c:getAlpha())
end
ColorBGR32_mt.__index.isEqual = ColorRGB32_mt.__index.isEqual

local MASK_ALLOCATED = 0x01
local SHIFT_ALLOCATED = 0
local MASK_INVERSE = 0x02
local SHIFT_INVERSE = 1
local MASK_ROTATED = 0x0C
local SHIFT_ROTATED = 2
local MASK_TYPE = 0xF0
local SHIFT_TYPE = 4

local TYPE_BB4 = 0
local TYPE_BB8 = 1
local TYPE_BB8A = 2
local TYPE_BBRGB16 = 3
local TYPE_BBRGB24 = 4
local TYPE_BBRGB32 = 5
local TYPE_BBBGR32 = 6

local BB = {}

-- metatables for BlitBuffer objects:
local BB4_mt = {__index={}}
local BB8_mt = {__index={}}
local BB8A_mt = {__index={}}
local BBRGB16_mt = {__index={}}
local BBRGB24_mt = {__index={}}
local BBRGB32_mt = {__index={}}
local BBBGR32_mt = {__index={}}

-- this is like a metatable for the others,
-- but we don't make it a metatable because LuaJIT
-- doesn't cope well with ctype metatables with
-- metatables on them
-- we just replicate what's in the following table
-- when we set the other metatables for their types
local BB_mt = {__index={}}

function BB_mt.__index:getRotation()
    return rshift(band(MASK_ROTATED, self.config), SHIFT_ROTATED)
end
function BB_mt.__index:setRotation(rotation_mode)
    self.config = bor(band(self.config, bxor(MASK_ROTATED, 0xFF)), lshift(rotation_mode, SHIFT_ROTATED))
end
function BB_mt.__index:rotateAbsolute(degree)
    local mode = (degree % 360) / 90
    self:setRotation(mode)
    return self
end
function BB_mt.__index:rotate(degree)
    degree = degree + self:getRotation()*90
    return self:rotateAbsolute(degree)
end
function BB_mt.__index:getInverse()
    return rshift(band(MASK_INVERSE, self.config), SHIFT_INVERSE)
end
function BB_mt.__index:setInverse(inverse)
    self.config = bor(band(self.config, bxor(MASK_INVERSE, 0xFF)), lshift(inverse, SHIFT_INVERSE))
end
function BB_mt.__index:invert()
    self:setInverse((self:getInverse() + 1) % 2)
    return self
end
function BB_mt.__index:getAllocated()
    return rshift(band(MASK_ALLOCATED, self.config), SHIFT_ALLOCATED)
end
function BB_mt.__index:setAllocated(allocated)
    self.config = bor(band(self.config, bxor(MASK_ALLOCATED, 0xFF)), lshift(allocated, SHIFT_ALLOCATED))
end
function BB_mt.__index:getType()
    return rshift(band(MASK_TYPE, self.config), SHIFT_TYPE)
end
function BB4_mt.__index:getBpp() return 4 end
function BB8_mt.__index:getBpp() return 8 end
function BB8A_mt.__index:getBpp() return 8 end
function BBRGB16_mt.__index:getBpp() return 16 end
function BBRGB24_mt.__index:getBpp() return 24 end
function BBRGB32_mt.__index:getBpp() return 32 end
function BBBGR32_mt.__index:getBpp() return 32 end
function BB_mt.__index:isRGB()
    local bb_type = self:getType()
    if bb_type == TYPE_BBRGB16
        or bb_type == TYPE_BBRGB24
        or bb_type == TYPE_BBRGB32 then
        return true
    end
    return false
end
function BB_mt.__index:setType(type_id)
    self.config = bor(band(self.config, bxor(MASK_TYPE, 0xFF)), lshift(type_id, SHIFT_TYPE))
end
function BB_mt.__index:getPhysicalCoordinates(x, y)
    local rotation = self:getRotation()
    if rotation == 0 then
        return x, y
    elseif rotation == 1 then
        return self.w - y - 1, x
    elseif rotation == 2 then
        return self.w - x - 1, self.h - y - 1
    elseif rotation == 3 then
        return y, self.h - x - 1
    end
end
function BB_mt.__index:getPhysicalRect(x, y, w, h)
    local px1, py1 = self:getPhysicalCoordinates(x, y)
    local px2, py2 = self:getPhysicalCoordinates(x+w-1, y+h-1)
    if self:getRotation() % 2 == 1 then w, h = h, w end
    return math.min(px1, px2), math.min(py1, py2), w, h
end

-- physical coordinate checking
function BB_mt.__index:checkCoordinates(x, y)
    assert(x >= 0, "x coordinate >= 0")
    assert(y >= 0, "y coordinate >= 0")
    assert(x < self.w, "x coordinate < width")
    assert(y < self.h, "y coordinate < height")
end

-- getPixelP (pointer) routines, working on physical coordinates
function BB_mt.__index:getPixelP(x, y)
    --self:checkCoordinates(x, y)
    return ffi.cast(self.data, ffi.cast(uint8pt, self.data) + self.pitch*y) + x
end
function BB4_mt.__index:getPixelP(x, y)
    --self:checkCoordinates(x, y)
    local p = self.data + self.pitch*y + rshift(x, 1)
    if band(x, 1) == 0 then
        return ffi.cast(P_Color4U, p)
    else
        return ffi.cast(P_Color4L, p)
    end
end

function BB_mt.__index:getPixel(x, y)
    local px, py = self:getPhysicalCoordinates(x, y)
    local color = self:getPixelP(px, py)[0]
    if self:getInverse() == 1 then color = color:invert() end
    return color
end

-- blitbuffer specific color conversions
function BB4_mt.__index.getMyColor(color) return color:getColor4L() end
function BB8_mt.__index.getMyColor(color) return color:getColor8() end
function BB8A_mt.__index.getMyColor(color) return color:getColor8A() end
function BBRGB16_mt.__index.getMyColor(color) return color:getColorRGB16() end
function BBRGB24_mt.__index.getMyColor(color) return color:getColorRGB24() end
function BBRGB32_mt.__index.getMyColor(color) return color:getColorRGB32() end
function BBBGR32_mt.__index.getMyColor(color) return color:getColorBGR32() end

-- set pixel values
function BB_mt.__index:setPixel(x, y, color)
    local px, py = self:getPhysicalCoordinates(x, y)
    if self:getInverse() == 1 then color = color:invert() end
    self:getPixelP(px, py)[0]:set(color)
end
function BB_mt.__index:setPixelAdd(x, y, color, intensity)
    local px, py = self:getPhysicalCoordinates(x, y)
    if self:getInverse() == 1 then color = color:invert() end
    self:getPixelP(px, py)[0]:add(color, intensity)
end
function BB_mt.__index:setPixelInverted(x, y, color)
    self:setPixel(x, y, color:invert())
end

-- checked Pixel setting:
function BB_mt.__index:setPixelClamped(x, y, color)
    if x >= 0 and x < self:getWidth() and y >= 0 and y < self:getHeight() then
        self:setPixel(x, y, color)
    end
end

-- functions for accessing dimensions
function BB_mt.__index:getWidth()
    if 0 == bit.band(1, self:getRotation()) then
        return self.w
    else
        return self.h
    end
end
function BB_mt.__index:getHeight()
    if 0 == bit.band(1, self:getRotation()) then
        return self.h
    else
        return self.w
    end
end

-- names of optimized blitting routines
BB_mt.__index.blitfunc = "blitDefault" -- not optimized
BB4_mt.__index.blitfunc = "blitTo4"
BB8_mt.__index.blitfunc = "blitTo8"
BB8A_mt.__index.blitfunc = "blitTo8A"
BBRGB16_mt.__index.blitfunc = "blitToRGB16"
BBRGB24_mt.__index.blitfunc = "blitToRGB24"
BBRGB32_mt.__index.blitfunc = "blitToRGB32"
BBBGR32_mt.__index.blitfunc = "blitToBGR32"

--[[
generic boundary check for copy operations

@param length length of copy operation
@param target_offset where to place part into target
@param source_offset where to take part from in source
@param target_size length of target buffer
@param source_size length of source buffer

@return adapted length that actually fits
@return adapted target offset, guaranteed within range 0..(target_size-1)
@return adapted source offset, guaranteed within range 0..(source_size-1)
--]]
function BB.checkBounds(length, target_offset, source_offset, target_size, source_size)
    -- deal with negative offsets
    if target_offset < 0 then
        length = length + target_offset
        source_offset = source_offset - target_offset
        target_offset = 0
    end
    if source_offset < 0 then
        length = length + source_offset
        target_offset = target_offset - source_offset
        source_offset = 0
    end
    -- calculate maximum lengths (size left starting at offset)
    local target_left = target_size - target_offset
    local source_left = source_size - source_offset
    -- return corresponding values
    if target_left <= 0 or source_left <= 0 then
        return 0, 0, 0
    elseif length <= target_left and length <= source_left then
        -- length is the smallest value
        return floor(length), floor(target_offset), floor(source_offset)
    elseif target_left < length and target_left < source_left then
        -- target_left is the smalles value
        return floor(target_left), floor(target_offset), floor(source_offset)
    else
        -- source_left must be the smallest value
        return floor(source_left), floor(target_offset), floor(source_offset)
    end
end

function BB_mt.__index:blitDefault(dest, dest_x, dest_y, offs_x, offs_y, width, height, setter, set_param)
    -- slow default variant:
    local o_y = offs_y
    for y = dest_y, dest_y+height-1 do
        local o_x = offs_x
        for x = dest_x, dest_x+width-1 do
            setter(dest, x, y, self:getPixel(o_x, o_y), set_param)
            o_x = o_x + 1
        end
        o_y = o_y + 1
    end
end
-- no optimized blitting by default:
BB_mt.__index.blitTo4 = BB_mt.__index.blitDefault
BB_mt.__index.blitTo8 = BB_mt.__index.blitDefault
BB_mt.__index.blitTo8A = BB_mt.__index.blitDefault
BB_mt.__index.blitToRGB16 = BB_mt.__index.blitDefault
BB_mt.__index.blitToRGB24 = BB_mt.__index.blitDefault
BB_mt.__index.blitToRGB32 = BB_mt.__index.blitDefault
BB_mt.__index.blitToBGR32 = BB_mt.__index.blitDefault

function BB_mt.__index:blitFrom(source, dest_x, dest_y, offs_x, offs_y, width, height, setter, set_param)
    width, height = width or source:getWidth(), height or source:getHeight()
    width, dest_x, offs_x = BB.checkBounds(width, dest_x or 0, offs_x or 0, self:getWidth(), source:getWidth())
    height, dest_y, offs_y = BB.checkBounds(height, dest_y or 0, offs_y or 0, self:getHeight(), source:getHeight())
    if not setter then setter = self.setPixel end

    if width <= 0 or height <= 0 then return end
    return source[self.blitfunc](source, self, dest_x, dest_y, offs_x, offs_y, width, height, setter, set_param)
end
BB_mt.__index.blitFullFrom = BB_mt.__index.blitFrom

function BB_mt.__index:addblitFrom(source, dest_x, dest_y, offs_x, offs_y, width, height, intensity)
    self:blitFrom(source, dest_x, dest_y, offs_x, offs_y, width, height, self.setPixelAdd, intensity)
end

function BB_mt.__index:blitFromRotate(source, degree)
    self:rotate(degree)
    self:blitFrom(source, dest_x, dest_y, offs_x, offs_y, width, height, self.setPixel, intensity)
    self:rotate(-degree)
end

-- scale method does not modify the original blitbuffer, instead, it allocates
-- and returns a new scaled blitbuffer.
function BB_mt.__index:scale(new_width, new_height)
    local self_w, self_h = self:getWidth(), self:getHeight()
    local scaled_bb = BB.new(new_width, new_height, self:getType())
    -- uses very simple nearest neighbour scaling
    for y=0, new_height-1 do
        for x=0, new_width-1 do
            scaled_bb:setPixel(x, y,
            self:getPixel(util.idiv(x*self_w, new_width),
                          util.idiv(y*self_h, new_height)))
        end
    end
    return scaled_bb
end

--[[
explicit unset

will free resources immediately
this is also called upon garbage collection
--]]
function BB_mt.__index:free()
    if band(lshift(1, SHIFT_ALLOCATED), self.config) ~= 0 then
        self.config = band(self.config, bxor(0xFF, lshift(1, SHIFT_ALLOCATED)))
        ffi.C.free(self.data)
    end
end

--[[
memory management
--]]
BB_mt.__gc = BB_mt.__index.free


--[[
PAINTING
--]]

--[[
invert a rectangle within the buffer

@param x X coordinate
@param y Y coordinate
@param w width
@param h height
--]]
function BB_mt.__index:invertRect(x, y, w, h)
    self:blitFrom(self, x, y, x, y, w, h, self.setPixelInverted)
end

--[[
paint a rectangle onto this buffer

@param x X coordinate
@param y Y coordinate
@param w width
@param h height
@param value color value
--]]
function BB_mt.__index:paintRect(x, y, w, h, value)
    -- compatibility:
    if type(value) == "number" then value = Color4L(value) end
    if w <= 0 or h <= 0 then return end
    w, x = BB.checkBounds(w, x, 0, self:getWidth(), 0xFFFF)
    h, y = BB.checkBounds(h, y, 0, self:getHeight(), 0xFFFF)
    for y = y, y+h-1 do
        for x = x, x+w-1 do
            self:setPixel(x, y, value)
        end
    end
end

--[[
paint a circle onto this buffer

@param x1 X coordinate of the circle's center
@param y1 Y coordinate of the circle's center
@param r radius
@param c color value (defaults to black)
@param w width of line (defaults to radius)
--]]
function BB_mt.__index:paintCircle(center_x, center_y, r, c, w)
    -- compatibility:
    if type(c) == "number" then c = Color4L(c) end
    if r == 0 then return end
    if w == nil then w = r end
    if w > r then w = r end

    -- for outer circle
    local x = 0
    local y = r
    local delta = 5/4 - r

    -- for inner circle
    local r2 = r - w
    local x2 = 0
    local y2 = r2
    local delta2 = 5/4 - r

    -- draw two axles
    for tmp_y = r, r2+1, -1 do
        self:setPixelClamped(center_x+0, center_y+tmp_y, c)
        self:setPixelClamped(center_x-0, center_y-tmp_y, c)
        self:setPixelClamped(center_x+tmp_y, center_y+0, c)
        self:setPixelClamped(center_x-tmp_y, center_y-0, c)
    end

    while x < y do
        -- decrease y if we are out of circle
        x = x + 1;
        if delta > 0 then
            y = y - 1
            delta = delta + 2*x - 2*y + 2
        else
            delta = delta + 2*x + 1
        end

        -- inner circle finished drawing, increase y linearly for filling
        if x2 > y2 then
            y2 = y2 + 1
            x2 = x2 + 1
        else
            x2 = x2 + 1
            if delta2 > 0 then
                y2 = y2 - 1
                delta2 = delta2 + 2*x2 - 2*y2 + 2
            else
                delta2 = delta2 + 2*x2 + 1
            end
        end

        for tmp_y = y, y2+1, -1 do
            self:setPixelClamped(center_x+x, center_y+tmp_y, c)
            self:setPixelClamped(center_x+tmp_y, center_y+x, c)

            self:setPixelClamped(center_x+tmp_y, center_y-x, c)
            self:setPixelClamped(center_x+x, center_y-tmp_y, c)

            self:setPixelClamped(center_x-x, center_y-tmp_y, c)
            self:setPixelClamped(center_x-tmp_y, center_y-x, c)

            self:setPixelClamped(center_x-tmp_y, center_y+x, c)
            self:setPixelClamped(center_x-x, center_y+tmp_y, c)
        end
    end
    if r == w then
        self:setPixelClamped(center_x, center_y, c)
    end
end

function BB_mt.__index:paintRoundedCorner(off_x, off_y, w, h, bw, r, c)
    -- compatibility:
    if type(c) == "number" then c = Color4L(c) end
    if 2*r > h
        or 2*r > w
        or r == 0
        then
            -- no operation
            return
        end

        r = math.min(r, h, w)
        if bw > r then
            bw = r
        end

        -- for outer circle
        local x = 0
        local y = r
        local delta = 5/4 - r

        -- for inner circle
        local r2 = r - bw
        local x2 = 0
        local y2 = r2
        local delta2 = 5/4 - r

        while x < y do
            -- decrease y if we are out of circle
            x = x + 1
            if delta > 0 then
                y = y - 1
                delta = delta + 2*x - 2*y + 2
            else
                delta = delta + 2*x + 1
            end

            -- inner circle finished drawing, increase y linearly for filling
            if x2 > y2 then
                y2 = y2 + 1
                x2 = x2 + 1
            else
                x2 = x2 + 1
                if delta2 > 0 then
                    y2 = y2 - 1
                    delta2 = delta2 + 2*x2 - 2*y2 + 2
                else
                    delta2 = delta2 + 2*x2 + 1
                end
            end

            for tmp_y = y, y2+1, -1 do
                self:setPixelClamped((w-r)+off_x+x-1, (h-r)+off_y+tmp_y-1, c)
                self:setPixelClamped((w-r)+off_x+tmp_y-1, (h-r)+off_y+x-1, c)

                self:setPixelClamped((w-r)+off_x+tmp_y-1, (r)+off_y-x, c)
                self:setPixelClamped((w-r)+off_x+x-1, (r)+off_y-tmp_y, c)

                self:setPixelClamped((r)+off_x-x, (r)+off_y-tmp_y, c)
                self:setPixelClamped((r)+off_x-tmp_y, (r)+off_y-x, c)

                self:setPixelClamped((r)+off_x-tmp_y, (h-r)+off_y+x-1, c)
                self:setPixelClamped((r)+off_x-x, (h-r)+off_y+tmp_y-1, c)
            end
        end
    end

    --[[
    Draw a border

    @x:  start position in x axis
    @y:  start position in y axis
    @w:  width of the border
    @h:  height of the border
    @bw: line width of the border
    @c:  color for loading bar
    @r:  radius of for border's corner (nil or 0 means right corner border)
    --]]
    function BB_mt.__index:paintBorder(x, y, w, h, bw, c, r)
        x, y = math.ceil(x), math.ceil(y)
        h, w = math.ceil(h), math.ceil(w)
        if not r or r == 0 then
            self:paintRect(x, y, w, bw, c)
            self:paintRect(x, y+h-bw, w, bw, c)
            self:paintRect(x, y+bw, bw, h - 2*bw, c)
            self:paintRect(x+w-bw, y+bw, bw, h - 2*bw, c)
        else
            if h < 2*r then r = math.floor(h/2) end
            if w < 2*r then r = math.floor(w/2) end
            self:paintRoundedCorner(x, y, w, h, bw, r, c)
            self:paintRect(r+x, y, w-2*r, bw, c)
            self:paintRect(r+x, y+h-bw, w-2*r, bw, c)
            self:paintRect(x, r+y, bw, h-2*r, c)
            self:paintRect(x+w-bw, r+y, bw, h-2*r, c)
        end
    end


    --[[
    Fill a rounded corner rectangular area

    @x:  start position in x axis
    @y:  start position in y axis
    @w:  width of the area
    @h:  height of the area
    @c:  color used to fill the area
    @r:  radius of for four corners
    --]]
    function BB_mt.__index:paintRoundedRect(x, y, w, h, c, r)
        x, y = math.ceil(x), math.ceil(y)
        h, w = math.ceil(h), math.ceil(w)
        if not r or r == 0 then
            self:paintRect(x, y, w, h, c)
        else
            if h < 2*r then r = math.floor(h/2) end
            if w < 2*r then r = math.floor(w/2) end
            self:paintBorder(x, y, w, h, r, c, r)
            self:paintRect(x+r, y+r, w-2*r, h-2*r, c)
        end
    end


    --[[
    Draw a progress bar according to following args:

    @x:  start position in x axis
    @y:  start position in y axis
    @w:  width for progress bar
    @h:  height for progress bar
    @load_m_w: width margin for loading bar
    @load_m_h: height margin for loading bar
    @load_percent: progress in percent
    @c:  color for loading bar
    --]]
    function BB_mt.__index:progressBar(x, y, w, h, load_m_w, load_m_h, load_percent, c)
        if load_m_h*2 > h then
            load_m_h = h/2
        end
        self:paintBorder(x, y, w, h, 2, 15)
        self:paintRect(x+load_m_w, y+load_m_h,
        (w-2*load_m_w)*load_percent, (h-2*load_m_h), c)
    end


    --[[
    dim color values in rectangular area

    @param x X coordinate
    @param y Y coordinate
    @param w width
    @param h height
    --]]
    function BB_mt.__index:dimRect(x, y, w, h)
        if w <= 0 or h <= 0 then return end
        w, x = BB.checkBounds(w, x, 0, self:getWidth(), 0xFFFF)
        h, y = BB.checkBounds(h, y, 0, self:getHeight(), 0xFFFF)
        for y = y, y+h-1 do
            for x = x, x+w-1 do
                self:setPixel(x, y, self:getPixel(x, y):dim())
            end
        end
    end

    --[[
    lighten color values in rectangular area

    @param x X coordinate
    @param y Y coordinate
    @param w width
    @param h height
    --]]
    function BB_mt.__index:lightenRect(x, y, w, h, low)
        if w <= 0 or h <= 0 then return end
        w, x = BB.checkBounds(w, x, 0, self:getWidth(), 0xFFFF)
        h, y = BB.checkBounds(h, y, 0, self:getHeight(), 0xFFFF)
        for y = y, y+h-1 do
            for x = x, x+w-1 do
                self:setPixel(x, y, self:getPixel(x, y):lighten(low))
            end
        end
    end

    function BB_mt.__index:copy()
        local mytype = ffi.typeof(self)
        local buffer = ffi.C.malloc(self.pitch * self.h)
        assert(buffer, "cannot allocate buffer")
        ffi.copy(buffer, self.data, self.pitch * self.h)
        local copy = mytype(self.w, self.h, self.pitch, buffer, self.config)
        copy:setAllocated(1)
        return copy
    end

    --[[
    write blitbuffer contents to a PAM file

    see http://netpbm.sourceforge.net/doc/pam.html for PAM file specs.

    @param filename the name of the file to be created
    --]]
    function BB_mt.__index:writePAM(filename)
        local f = io.open(filename, "w")
        f:write("P7\n")
        f:write("# written by blitbuffer.lua\n")
        f:write("WIDTH ", self:getWidth(), "\n")
        f:write("HEIGHT ", self:getHeight(), "\n")
        local bb_type = self:getType()
        if bb_type == TYPE_BB4 then
            f:write("DEPTH 1\n", "MAXVAL 15\n", "TUPLTYPE GRAYSCALE\n")
        elseif bb_type == TYPE_BB8 then
            f:write("DEPTH 1\n", "MAXVAL 255\n", "TUPLTYPE GRAYSCALE\n")
        elseif bb_type == TYPE_BB8A then
            f:write("DEPTH 2\n", "MAXVAL 255\n", "TUPLTYPE GRAYSCALE_ALPHA\n")
        elseif bb_type == TYPE_BBRGB16 then
            -- this is not supported by PAM since the tuple consists of different bit widths
            -- so we convert to RGB24 in this case
            f:write("DEPTH 3\n", "MAXVAL 255\n", "TUPLTYPE RGB\n")
        elseif bb_type == TYPE_BBRGB24 then
            f:write("DEPTH 3\n", "MAXVAL 255\n", "TUPLTYPE RGB\n")
        elseif bb_type == TYPE_BBRGB32 or bb_type == TYPE_BBBGR32 then
            f:write("DEPTH 4\n", "MAXVAL 255\n", "TUPLTYPE RGB_ALPHA\n")
        end
        f:write("ENDHDR\n")
        for y = 0, self:getHeight()-1 do
            for x = 0, self:getWidth()-1 do
                local v = self:getPixel(x, y)
                if bb_type == TYPE_BB4 or bb_type == TYPE_BB8 then
                    ffi.C.fputc(v.a, f)
                elseif bb_type == TYPE_BB8A then
                    ffi.C.fputc(v.a, f)
                    -- note that other functions do not support
                    -- alpha values for now
                    -- TODO: use correct alpha value of struct here
                    ffi.C.fputc(255, f)
                elseif bb_type == TYPE_BBRGB16 then
                    v = v:getColorRGB24()
                    ffi.C.fputc(v.r, f)
                    ffi.C.fputc(v.g, f)
                    ffi.C.fputc(v.b, f)
                elseif bb_type == TYPE_BBRGB24 then
                    ffi.C.fputc(v.r, f)
                    ffi.C.fputc(v.g, f)
                    ffi.C.fputc(v.b, f)
                elseif bb_type == TYPE_BBRGB32 or bb_type == TYPE_BBBGR32 then
                    ffi.C.fputc(v.r, f)
                    ffi.C.fputc(v.g, f)
                    ffi.C.fputc(v.b, f)
                    -- note that other functions do not support
                    -- alpha values for now
                    -- TODO: use correct alpha value of struct here
                    ffi.C.fputc(255, f)
                end
            end
        end
        f:close()
    end

    -- if no special case in BB???_mt exists, use function from BB_mt
    -- (we do not use BB_mt as metatable for BB???_mt since this causes
    --  a major slowdown and would not get properly JIT-compiled)
    for name, func in pairs(BB_mt.__index) do
        if not BB4_mt.__index[name] then BB4_mt.__index[name] = func end
        if not BB8_mt.__index[name] then BB8_mt.__index[name] = func end
        if not BB8A_mt.__index[name] then BB8A_mt.__index[name] = func end
        if not BBRGB16_mt.__index[name] then BBRGB16_mt.__index[name] = func end
        if not BBRGB24_mt.__index[name] then BBRGB24_mt.__index[name] = func end
        if not BBRGB32_mt.__index[name] then BBRGB32_mt.__index[name] = func end
        if not BBBGR32_mt.__index[name] then BBBGR32_mt.__index[name] = func end
    end

    -- set metatables for the BlitBuffer types
    local BlitBuffer4 = ffi.metatype("BlitBuffer4", BB4_mt)
    local BlitBuffer8 = ffi.metatype("BlitBuffer8", BB8_mt)
    local BlitBuffer8A = ffi.metatype("BlitBuffer8A", BB8A_mt)
    local BlitBufferRGB16 = ffi.metatype("BlitBufferRGB16", BBRGB16_mt)
    local BlitBufferRGB24 = ffi.metatype("BlitBufferRGB24", BBRGB24_mt)
    local BlitBufferRGB32 = ffi.metatype("BlitBufferRGB32", BBRGB32_mt)
    local BlitBufferBGR32 = ffi.metatype("BlitBufferBGR32", BBBGR32_mt)

    -- set metatables for the Color types
    ffi.metatype("Color4L", Color4L_mt)
    ffi.metatype("Color4U", Color4U_mt)
    ffi.metatype("Color8", Color8_mt)
    ffi.metatype("Color8A", Color8A_mt)
    ffi.metatype("ColorRGB16", ColorRGB16_mt)
    ffi.metatype("ColorRGB24", ColorRGB24_mt)
    ffi.metatype("ColorRGB32", ColorRGB32_mt)
    ffi.metatype("ColorBGR32", ColorBGR32_mt)

    function BB.new(width, height, buffertype, dataptr, pitch)
        local bb = nil
        buffertype = buffertype or TYPE_BB4
        if pitch == nil then
            if buffertype == TYPE_BB4 then pitch = band(1, width) + rshift(width, 1)
            elseif buffertype == TYPE_BB8 then pitch = width
            elseif buffertype == TYPE_BB8A then pitch = lshift(width, 1)
            elseif buffertype == TYPE_BBRGB16 then pitch = lshift(width, 1)
            elseif buffertype == TYPE_BBRGB24 then pitch = width * 3
            elseif buffertype == TYPE_BBRGB32 or buffertype == TYPE_BBBGR32 then pitch = lshift(width, 2)
            end
        end
        if buffertype == TYPE_BB4 then bb = BlitBuffer4(width, height, pitch, nil, 0)
        elseif buffertype == TYPE_BB8 then bb = BlitBuffer8(width, height, pitch, nil, 0)
        elseif buffertype == TYPE_BB8A then bb = BlitBuffer8A(width, height, pitch, nil, 0)
        elseif buffertype == TYPE_BBRGB16 then bb = BlitBufferRGB16(width, height, pitch, nil, 0)
        elseif buffertype == TYPE_BBRGB24 then bb = BlitBufferRGB24(width, height, pitch, nil, 0)
        elseif buffertype == TYPE_BBRGB32 then bb = BlitBufferRGB32(width, height, pitch, nil, 0)
        elseif buffertype == TYPE_BBBGR32 then bb = BlitBufferBGR32(width, height, pitch, nil, 0)
        else error("unknown blitbuffer type")
        end
        bb:setType(buffertype)
        if dataptr == nil then
            dataptr = ffi.C.malloc(pitch*height)
            assert(dataptr, "cannot allocate memory for blitbuffer")
            ffi.fill(dataptr, pitch*height)
            bb:setAllocated(1)
        end
        bb.data = ffi.cast(bb.data, dataptr)
        return bb
    end

    function BB.compat(oldbuffer)
        return ffi.cast("BlitBuffer4*", oldbuffer)[0]
    end

    function BB.fromstring(width, height, buffertype, str, pitch)
        local dataptr = ffi.C.malloc(#str)
        ffi.copy(dataptr, str, #str)
        return BB.new(width, height, buffertype, dataptr, pitch)
    end

    function BB.tostring(bb)
        return ffi.string(bb.data, bb.pitch * bb.h)
    end

    -- accessors for color types:
    BB.Color4 = Color4L
    BB.Color4L = Color4L
    BB.Color4U = Color4U
    BB.Color8 = Color8
    BB.ColorRGB16 = ColorRGB16
    BB.ColorRGB24 = ColorRGB24
    BB.ColorRGB32 = ColorRGB32
    BB.ColorBGR32 = ColorBGR32

    -- accessors for Blitbuffer types
    BB.BlitBuffer4 = BlitBuffer4
    BB.BlitBuffer8 = BlitBuffer8
    BB.BlitBuffer8A = BlitBuffer8A
    BB.BlitBufferRGB16 = BlitBufferRGB16
    BB.BlitBufferRGB24 = BlitBufferRGB24
    BB.BlitBufferRGB32 = BlitBufferRGB32
    BB.BlitBufferBGR32 = BlitBufferBGR32
    BB.TYPE_BB4 = TYPE_BB4
    BB.TYPE_BB8 = TYPE_BB8
    BB.TYPE_BB8A = TYPE_BB8A
    BB.TYPE_BBRGB16 = TYPE_BBRGB16
    BB.TYPE_BBRGB24 = TYPE_BBRGB24
    BB.TYPE_BBRGB32 = TYPE_BBRGB32
    BB.TYPE_BBBGR32 = TYPE_BBBGR32

    return BB


================================================
FILE: ffi/einkfb_h.lua
================================================
local ffi = require("ffi")
ffi.cdef[[
enum fx_type {
  fx_mask = 11,
  fx_buf_is_mask = 14,
  fx_none = -1,
  fx_flash = 20,
  fx_invert = 21,
  fx_update_partial = 0,
  fx_update_full = 1,
};
struct update_area_t {
  int x1;
  int y1;
  int x2;
  int y2;
  enum fx_type which_fx;
  unsigned char *buffer;
};
enum orientation_t {
  orientation_portrait = 0,
  orientation_portrait_upside_down = 1,
  orientation_landscape = 2,
  orientation_landscape_upside_down = 3,
};
enum einkfb_events_t {
  einkfb_event_update_display = 0,
  einkfb_event_update_display_area = 1,
  einkfb_event_blank_display = 2,
  einkfb_event_rotate_display = 3,
  einkfb_event_null = -1,
};
struct einkfb_event_t {
  enum einkfb_events_t event;
  enum fx_type update_mode;
  int x1;
  int y1;
  int x2;
  int y2;
  enum orientation_t orientation;
};
static const int FBIO_EINK_UPDATE_DISPLAY = 18139;
static const int FBIO_EINK_UPDATE_DISPLAY_AREA = 18141;
static const int FBIO_EINK_SET_DISPLAY_ORIENTATION = 18160;
static const int FBIO_EINK_GET_DISPLAY_ORIENTATION = 18161;
]]


================================================
FILE: ffi/eventloop.lua
================================================
-- dependencies
local ffi = require("ffi")
local bit = require("bit")
local posix = require("ffi/posix_h")

-- this module
local events = {}

-- Lua table storing file descriptors and callbacks
local fds = {}
-- Lua table storing timers and their callbacks
local timers = nil

-- C array for poll()
local poll_fds = nil
-- counter for that C array
local open_fds = 0

-- flag for the event loop
local running = true

--[[
register a file descriptor to get monitored

expects a table with functions that are called
upon events for the given file descriptor
all functions are optional, however you should
define at least "read" or "write".

function names:
  read: will get called when data can be read
  write: will get called when data can be written
  err: will get called upon errors
  hup: will get called upon a hangup

@parm fd file descriptor (integer)
@parm callback table
--]]
function events.register_fd(fd, callbacks)
	assert(not fds[fd], "fd is already registered")
	fds[fd] = callbacks
	-- invalidate cache
	poll_fds = nil
end

--[[
register a timer

registers a callback to be called at a given time.
the time is given as a "struct timeval"
--]]
function events.register_timer(timeval, callback, id)
	-- append to the end of the list
	-- this is needed to properly calculate times
	-- in the loop: new timers must be taken into account
	local timer = { next = nil, tv = timeval, cb = callback, id = id }
	if not timers then
		timers = timer
	else
		local tail = timers
		while tail.next do tail = tail.next end
		tail.next = timer
	end
end

--[[
register a timer to fire in n milliseconds

this is a convenience wrapper that does all the calculating
--]]
function events.register_timer_in_ms(milliseconds, callback, id)
	local tv = ffi.new("struct timeval")
	ffi.C.gettimeofday(tv, nil)
	while milliseconds > 1000 do
		tv.tv_sec = tv.tv_sec + 1
		milliseconds = milliseconds - 1000
	end
	tv.tv_usec = tv.tv_usec + milliseconds * 1000
	if tv.tv_usec > 1000000 then
		tv.tv_sec = tv.tv_sec + 1
		tv.tv_usec = tv.tv_usec - 1000000
	end
	events.register_timer(tv, callback, id)
end

--[[
check if a timer exists (and is running)
--]]
function events.timer_running(id)
	if not timers then return false end
	local tail = timers
	repeat
		if tail.id == id then return true end
		tail = tail.next
	until not tail
	return false
end

--[[
remove a filedescriptor from being monitored
--]]
function events.unregister_fd(fd)
	assert(fds[fd], "fd is not registered, cannot unregister")
	table.remove(fds, fd)
	poll_fds = nil
end

--[[
remove a named timer
--]]
function events.unregister_timer(id)
	assert(id, "only timers with ID can be unregistered")
	local prev = nil
	local timer = timers
	while timer do
		if timer.id == id then
			if not prev then timers = timer.next else prev.next = timer.next end
			break
		end
		prev = timer
		timer = timer.next
	end
end

-- internal helper to recreate poll_fd array
local function check_poll_fds()
	-- check if we have a valid cache
	if poll_fds then return end
	-- otherwise, rescan
	poll_fds = nil
	open_fds = 0
	for _, _ in pairs(fds) do open_fds = open_fds + 1 end
	if open_fds > 0 then
		poll_fds = ffi.new("struct pollfd[?]", open_fds)
		local c = 0
		for fd, callbacks in pairs(fds) do
			poll_fds[c].fd = fd
			if callbacks.read then
				poll_fds[c].events = bit.bor(poll_fds[c].events, ffi.C.POLLIN)
			end
			if callbacks.write then
				poll_fds[c].events = bit.bor(poll_fds[c].events, ffi.C.POLLOUT)
			end
			c = c + 1
		end
	end
end

--[[
convenience wrapper that exits after a timeout
--]]
function events.loopusecs(timeout)
	return events.loop(timeout / 1000)
end

--[[
abort routine that will stop the event loop
--]]
function events.abort_loop()
	running = false
end

-- allocate these only once
local now = ffi.new("struct timeval")
local up_to = ffi.new("struct timeval")

--[[
main event loop
--]]
function events.loop(timeout)
	if timeout then
		events.register_timer_in_ms(timeout, events.abort_loop)
	end
	running = true
	local poll_duration
	while running do
		-- check and update poll_fd cache
		check_poll_fds()
		
		-- get time to check timers
		ffi.C.gettimeofday(now, nil)
		up_to.tv_sec = 0
		local timer = timers
		local prev = nil
		while timer do
			if now.tv_sec > timer.tv.tv_sec
			or ( now.tv_sec == timer.tv.tv_sec and now.tv_usec >= timer.tv.tv_usec) then
				timer.cb()
				-- remove from list
				if not prev then timers = timer.next else prev.next = timer.next end
			else
				if up_to.tv_sec == 0
				or timer.tv.tv_sec < up_to.tv_sec
				or (timer.tv.tv_sec == up_to.tv_sec and timer.tv.tv_usec < up_to.tv_usec) then
					up_to.tv_sec = timer.tv.tv_sec
					up_to.tv_usec = timer.tv.tv_usec
				end
				prev = timer
			end
			timer = timer.next
		end

		-- intermediate check after doing the timer work
		if not running then break end

		-- calculate wait time
		if up_to.tv_sec == 0 then
			if open_fds == 0 then
				error("got no timers waiting, got no input fds")
			end
			poll_duration = -1
		else
			poll_duration = (up_to.tv_usec - now.tv_usec) / 1000
			poll_duration = poll_duration + (up_to.tv_sec - now.tv_sec) * 1000 + 1
		end

		-- do the poll()
		local ret = ffi.C.poll(poll_fds, open_fds, poll_duration)
		if ret > 0 then
			for i = 0, open_fds-1 do
				local fd = poll_fds[i].fd
				if bit.band(poll_fds[i].revents, ffi.C.POLLIN) ~= 0 then
					fds[fd].read(fd)
				end
				if bit.band(poll_fds[i].revents, ffi.C.POLLOUT) ~= 0 then
					fds[fd].write(fd)
				end
				if bit.band(poll_fds[i].revents, ffi.C.POLLERR) ~= 0 then
					if fds[fd].err then fds[fd].err(fd) end
				end
				if bit.band(poll_fds[i].revents, ffi.C.POLLHUP) ~= 0 then
					if fds[fd].hup then fds[fd].hup(fd) end
				end
			end
		elseif ret < 0 then
			local errno = ffi.errno()
			if errno == ffi.C.EINTR then
				-- unhandled signal, ignore this for now...
			else
				error("poll(): " .. ffi.string(ffi.C.strerror(errno)))
			end
		end
	end
end

return events


================================================
FILE: ffi/framebuffer.lua
================================================
local util = require("ffi/util")

if util.isEmulated() then
	return require("ffi/framebuffer_SDL")
else
	return require("ffi/framebuffer_linux")
end



================================================
FILE: ffi/framebuffer_SDL.lua
================================================
local ffi = require("ffi")
local bit = require("bit")
-- load common SDL input/video library
local SDL = require("ffi/SDL")

local BB = require("ffi/blitbuffer")

local fb = {}

function fb.open()
	SDL.open()

	-- we present this buffer to the outside
	fb.bb = BB.new(SDL.screen.w, SDL.screen.h)

	fb.real_bb = BB.new(SDL.screen.w, SDL.screen.h, BB.TYPE_BBRGB32,
		SDL.screen.pixels, SDL.screen.pitch)
	fb.real_bb:invert()

	fb:refresh()

	return fb
end

function fb:getSize()
	return self.bb.w, self.bb.h
end

function fb:getPitch()
	return self.bb.pitch
end

function fb:setOrientation(mode)
	if mode == 1 or mode == 3 then
		-- TODO: landscape setting
	else
		-- TODO: flip back to portrait
	end
end

function fb:getOrientation()
	if SDL.screen.w > SDL.screen.h then
		return 1
	else
		return 0
	end
end

function fb:refresh(refreshtype, waveform_mode, x1, y1, w, h)
	if x1 == nil then x1 = 0 end
	if y1 == nil then y1 = 0 end

	-- adapt to possible rotation changes
	self.real_bb:setRotation(self.bb:getRotation())
	
	if SDL.SDL.SDL_LockSurface(SDL.screen) < 0 then
		error("Locking screen surface")
	end
	self.real_bb:blitFrom(self.bb, x1, y1, x1, y1, w, h)

	SDL.SDL.SDL_UnlockSurface(SDL.screen)
	SDL.SDL.SDL_Flip(SDL.screen)
end

function fb:close()
	-- for now, we do nothing when in emulator mode
end

return fb


================================================
FILE: ffi/framebuffer_linux.lua
================================================
local ffi = require("ffi")
local bit = require("bit")
local BB = require("ffi/blitbuffer")

local dummy = require("ffi/linux_fb_h")
local dummy = require("ffi/posix_h")

local framebuffer = {}
local framebuffer_mt = {__index={}}
-- Init our marker to 0, which happens to be an invalid value, so we can detect our first update
local update_marker = ffi.new("uint32_t[1]", 0)

local function einkfb_update(fb, refreshtype, waveform_mode, x, y, w, h)
	local refarea = ffi.new("struct update_area_t[1]")

	refarea[0].x1 = x or 0
	refarea[0].y1 = y or 0
	refarea[0].x2 = x + (w or (fb.vinfo.xres-x))
	refarea[0].y2 = y + (h or (fb.vinfo.yres-y))
	refarea[0].buffer = nil
	if refreshtype == 0 then
		refarea[0].which_fx = ffi.C.fx_update_partial
	else
		refarea[0].which_fx = ffi.C.fx_update_full
	end

	return ffi.C.ioctl(fb.fd, ffi.C.FBIO_EINK_UPDATE_DISPLAY_AREA, refarea);
end

local function mxc_new_update_marker()
	-- Simply increment our current marker
	local new_update_marker = ffi.new("uint32_t[1]", update_marker[0] + 1)
	-- 1 to 16, strictly clamped.
	if new_update_marker[0] > 16 or new_update_marker[0] < 1 then
		new_update_marker[0] = 1
	end
	-- Keep track of it, and return it
	update_marker[0] = new_update_marker[0]
	return new_update_marker[0]
end

-- Kindle's MXCFB_WAIT_FOR_UPDATE_COMPLETE_PEARL == 0x4004462f
local function kindle_pearl_mxc_wait_for_update_complete(fb)
	-- Wait for the previous update to be completed
	return ffi.C.ioctl(fb.fd, ffi.C.MXCFB_WAIT_FOR_UPDATE_COMPLETE_PEARL, update_marker)
end

-- Kindle's MXCFB_WAIT_FOR_UPDATE_COMPLETE == 0xc008462f
local function kindle_carta_mxc_wait_for_update_complete(fb)
	-- Wait for the previous update to be completed
	local carta_update_marker = ffi.new("struct mxcfb_update_marker_data[1]")
	carta_update_marker[0].update_marker = update_marker[0];
	-- We're not using EPDC_FLAG_TEST_COLLISION, assume 0 is okay.
	carta_update_marker[0].collision_test = 0;
	return ffi.C.ioctl(fb.fd, ffi.C.MXCFB_WAIT_FOR_UPDATE_COMPLETE, carta_update_marker)
end

-- Kobo's MXCFB_WAIT_FOR_UPDATE_COMPLETE == 0x4004462f

-- Kindle's MXCFB_SEND_UPDATE == 0x4048462e | Kobo's MXCFB_SEND_UPDATE == 0x4044462e
local function mxc_update(fb, refarea, refreshtype, waveform_mode, x, y, w, h)
	refarea[0].update_mode = refreshtype or 0
	refarea[0].waveform_mode = waveform_mode or 2
	refarea[0].update_region.left = x or 0
	refarea[0].update_region.top = y or 0
	refarea[0].update_region.width = w or fb.vinfo.xres
	refarea[0].update_region.height = h or fb.vinfo.yres
	-- Get a new update marker
	refarea[0].update_marker = mxc_new_update_marker()
	-- TODO: make the flag configurable from UI,
	-- e.g., the EPDC_FLAG_ENABLE_INVERSION flag inverts all the pixels on display  09.01 2013 (houqp)
	refarea[0].flags = 0
	-- NOTE: We're not using EPDC_FLAG_USE_ALT_BUFFER
	refarea[0].alt_buffer_data.phys_addr = 0
	refarea[0].alt_buffer_data.width = 0
	refarea[0].alt_buffer_data.height = 0
	refarea[0].alt_buffer_data.alt_update_region.top = 0
	refarea[0].alt_buffer_data.alt_update_region.left = 0
	refarea[0].alt_buffer_data.alt_update_region.width = 0
	refarea[0].alt_buffer_data.alt_update_region.height = 0
	return ffi.C.ioctl(fb.fd, ffi.C.MXCFB_SEND_UPDATE, refarea)
end

-- Kindle's MXCFB_WAIT_FOR_UPDATE_SUBMISSION == 0x40044637
local function kindle_mxc_wait_for_update_submission(fb)
	-- Wait for the current (the one we just sent) update to be submitted
	return ffi.C.ioctl(fb.fd, ffi.C.MXCFB_WAIT_FOR_UPDATE_SUBMISSION, update_marker)
end

local function k51_update(fb, refreshtype, waveform_mode, x, y, w, h)
	local refarea = ffi.new("struct mxcfb_update_data[1]")
	-- only for Amazon's driver (NOTE: related to debugPaint prefbw & prefgray?):
	refarea[0].hist_bw_waveform_mode = 0
	refarea[0].hist_gray_waveform_mode = 0
	-- TEMP_USE_PAPYRUS on Touch/PW1, TEMP_USE_AUTO on PW2
	refarea[0].temp = 0x1001

	return mxc_update(fb, refarea, refreshtype, waveform_mode, x, y, w, h)
end

local function kobo_update(fb, refreshtype, waveform_mode, x, y, w, h)
	local refarea = ffi.new("struct mxcfb_update_data[1]")
	-- only for Kobo's driver:
	refarea[0].alt_buffer_data.virt_addr = nil
	-- TEMP_USE_AMBIENT
	refarea[0].temp = 0x1000

	return mxc_update(fb, refarea, refreshtype, waveform_mode, x, y, w, h)
end

function framebuffer.open(device)
	local fb = {
		fd = -1,
		finfo = ffi.new("struct fb_fix_screeninfo"),
		vinfo = ffi.new("struct fb_var_screeninfo"),
		fb_size = -1,
		einkWaitForCompleteFunc = nil,
		einkUpdateFunc = nil,
		einkWaitForSubmissionFunc = nil,
		wait_for_full_updates = false,
		wait_for_every_updates = false,
		bb = nil,
		data = nil
	}
	setmetatable(fb, framebuffer_mt)

	fb.fd = ffi.C.open(device, ffi.C.O_RDWR)
	assert(fb.fd ~= -1, "cannot open framebuffer")

	-- Get fixed screen information
	assert(ffi.C.ioctl(fb.fd, ffi.C.FBIOGET_FSCREENINFO, fb.finfo) == 0,
		"cannot get screen info")

	assert(ffi.C.ioctl(fb.fd, ffi.C.FBIOGET_VSCREENINFO, fb.vinfo) == 0,
		"cannot get variable screen info")

	assert(fb.finfo.type == ffi.C.FB_TYPE_PACKED_PIXELS,
		"video type not supported")

	--Kindle Paperwhite doesn't set this properly?
	--assert(fb.vinfo.grayscale == 0, "only grayscale is supported but framebuffer says it isn't")
	assert(fb.vinfo.xres_virtual > 0 and fb.vinfo.yres_virtual > 0, "invalid framebuffer resolution")

	-- it seems that fb.finfo.smem_len is unreliable on kobo
	-- Figure out the size of the screen in bytes
	fb.fb_size = fb.vinfo.xres_virtual * fb.vinfo.yres_virtual * fb.vinfo.bits_per_pixel / 8

	fb.data = ffi.C.mmap(nil, fb.fb_size, bit.bor(ffi.C.PROT_READ, ffi.C.PROT_WRITE), ffi.C.MAP_SHARED, fb.fd, 0)
	assert(fb.data ~= ffi.C.MAP_FAILED, "can not mmap() framebuffer")

	if ffi.string(fb.finfo.id, 11) == "mxc_epdc_fb" then
		-- TODO: implement a better check for Kobo
		if fb.vinfo.bits_per_pixel == 16 then
			-- this ought to be a Kobo
			local dummy = require("ffi/mxcfb_kobo_h")
			fb.einkUpdateFunc = kobo_update
			fb.bb = BB.new(fb.vinfo.xres, fb.vinfo.yres, BB.TYPE_BBRGB16, fb.data, fb.finfo.line_length)
			fb.bb:invert()
			if fb.vinfo.xres > fb.vinfo.yres then
				-- Kobo framebuffers need to be rotated counter-clockwise (they start in landscape mode)
				fb.bb:rotate(-90)
			end
		elseif fb.vinfo.bits_per_pixel == 8 then
			-- Kindle PaperWhite and KT with 5.1 or later firmware
			local dummy = require("ffi/mxcfb_kindle_h")
			-- NOTE: We need to differentiate the PW2 from the Touch/PW1... I hope this check is solid enough... (cf #550).
			if fb.finfo.smem_len == 3145728 then
				-- We're a PW2! Use the correct function, and ask to wait for every update.
				fb.wait_for_every_updates = true
				fb.einkWaitForCompleteFunc = kindle_carta_mxc_wait_for_update_complete
			elseif fb.finfo.smem_len == 2179072 or fb.finfo.smem_len == 4718592 then
				-- We're a Touch/PW1
				fb.wait_for_full_updates = true
				fb.einkWaitForCompleteFunc = kindle_pearl_mxc_wait_for_update_complete
			else
				error("unknown smem_len value for the Kindle mxc eink driver")
			end
			fb.einkUpdateFunc = k51_update
			fb.einkWaitForSubmissionFunc = kindle_mxc_wait_for_update_submission
			fb.bb = BB.new(fb.vinfo.xres, fb.vinfo.yres, BB.TYPE_BB8, fb.data, fb.finfo.line_length)
			fb.bb:invert()
		else
			error("unknown bpp value for the mxc eink driver")
		end
	elseif ffi.string(fb.finfo.id, 7) == "eink_fb" then
		local dummy = require("ffi/einkfb_h")
		fb.einkUpdateFunc = einkfb_update

		if fb.vinfo.bits_per_pixel == 8 then
			fb.bb = BB.new(fb.vinfo.xres, fb.vinfo.yres, BB.TYPE_BB8, fb.data, fb.finfo.line_length)
		elseif fb.vinfo.bits_per_pixel == 4 then
			fb.bb = BB.new(fb.vinfo.xres, fb.vinfo.yres, BB.TYPE_BB4, fb.data, fb.finfo.line_length)
		else
			error("unknown bpp value for the classic eink driver")
		end
	else
		error("eink model not supported");
	end

	return fb
end

function framebuffer_mt:getOrientation()
	local mode = ffi.new("int[1]")
	ffi.C.ioctl(self.fd, ffi.C.FBIO_EINK_GET_DISPLAY_ORIENTATION, mode)

	-- adjust ioctl's rotate mode definition to KPV's
	-- refer to screen.lua
	if mode == 2 then
		return 1
	elseif mode == 1 then
		return 2
	end
	return mode
end

function framebuffer_mt:setOrientation(mode)
	mode = ffi.cast("int", mode or 0)
	if mode < 0 or mode > 3 then
		error("Wrong rotation mode given!")
	end

	--[[
         ioctl has a different definition for rotation mode.
	 	          1
	 	   +--------------+
	 	   | +----------+ |
	 	   | |          | |
	 	   | | Freedom! | |
	 	   | |          | |
	 	   | |          | |
	 	 3 | |          | | 2
	 	   | |          | |
	 	   | |          | |
	 	   | +----------+ |
	 	   |              |
	 	   |              |
	 	   +--------------+
	 	          0
	--]]
	if mode == 1 then
		mode = 2
	elseif mode == 2 then
		mode = 1
	end

	ffi.C.ioctl(self.fd, ffi.C.FBIO_EINK_SET_DISPLAY_ORIENTATION, mode)
end

function framebuffer_mt.__index:refresh(refreshtype, waveform_mode, x, y, w, h)
	-- The Touch/PW1 only do this for full updates
	if refreshtype == 1 and self.wait_for_full_updates or self.wait_for_every_updates then
		-- Start by checking that our previous update has completed
		if self.einkWaitForCompleteFunc then
			-- We have nothing to check on our first refresh() call!
			if update_marker[0] ~= 0 then
				self:einkWaitForCompleteFunc()
			end
		end
	end

	w, x = BB.checkBounds(w or self.bb:getWidth(), x or 0, 0, self.bb:getWidth(), 0xFFFF)
	h, y = BB.checkBounds(h or self.bb:getHeight(), y or 0, 0, self.bb:getHeight(), 0xFFFF)
	x, y, w, h = self.bb:getPhysicalRect(x, y, w, h)
	self:einkUpdateFunc(refreshtype, waveform_mode, x, y, w, h)

	-- Finish by waiting for our curren tupdate to be submitted
	if refreshtype == 1 and self.wait_for_full_updates or self.wait_for_every_updates then
		if self.einkWaitForSubmissionFunc then
			self:einkWaitForSubmissionFunc()
		end
	end
end

function framebuffer_mt.__index:getSize()
	return self.bb:getWidth(), self.bb:getHeight()
end

function framebuffer_mt.__index:getPitch()
	return self.bb.pitch
end

function framebuffer_mt.__index:close()
	ffi.C.munmap(self.data, self.fb_size)
	ffi.C.close(self.fd)
	self.fd = -1
	self.data = nil
	self.bb = nil
end

return framebuffer


================================================
FILE: ffi/input.lua
================================================
local util = require("ffi/util")

if util.isEmulated() then
	return require("ffi/input_SDL")
else
	return require("ffi/input_kindle")
end


================================================
FILE: ffi/input_SDL.lua
================================================
local ffi = require("ffi")
local evloop = require("ffi/eventloop")

local dummy = require("ffi/posix_h")
local dummy = require("ffi/linux_input_h")

local SDL = require("ffi/SDL")

-- this module
local input = {}

-- the input event buffer
local input_queue = {}

local poll_time = 50 -- 50 ms
local event = ffi.new("union SDL_Event")

local function genEmuEvent(evtype, code, value)
	local ev = ffi.new("struct input_event")
	ev.type = evtype
	ev.code = code
	ev.value = value
	ffi.C.gettimeofday(ev.time, nil)
	table.insert(input_queue, ev)
end

local is_in_touch = false
function input.poller()
	local got_event = SDL.SDL.SDL_PollEvent(event)
	if got_event == 0 then
		evloop.register_timer_in_ms(poll_time, input.poller)
	else
		while got_event > 0 do
			-- if we got an event, examine it here and generate
			-- events for koreader
			if event.type == SDL.SDL.SDL_KEYDOWN then
				genEmuEvent(ffi.C.EV_KEY, event.key.keysym.scancode, 1)
			elseif event.type == SDL.SDL.SDL_KEYUP then
				genEmuEvent(ffi.C.EV_KEY, event.key.keysym.scancode, 0)
			elseif event.type == SDL.SDL.SDL_MOUSEMOTION then
				if is_in_touch then
					if event.motion.xrel ~= 0 then
						genEmuEvent(ffi.C.EV_ABS, ffi.C.ABS_MT_POSITION_X, event.button.x)
					end
					if event.motion.yrel ~= 0 then
						genEmuEvent(ffi.C.EV_ABS, ffi.C.ABS_MT_POSITION_Y, event.button.y)
					end
					genEmuEvent(ffi.C.EV_SYN, ffi.C.SYN_REPORT, 0)
				end
			elseif event.type == SDL.SDL.SDL_MOUSEBUTTONUP then
				is_in_touch = false;
				genEmuEvent(ffi.C.EV_ABS, ffi.C.ABS_MT_TRACKING_ID, -1)
				genEmuEvent(ffi.C.EV_SYN, ffi.C.SYN_REPORT, 0)
			elseif event.type == SDL.SDL.SDL_MOUSEBUTTONDOWN then
				-- use mouse click to simulate single tap
				is_in_touch = true
				genEmuEvent(ffi.C.EV_ABS, ffi.C.ABS_MT_TRACKING_ID, 0)
				genEmuEvent(ffi.C.EV_ABS, ffi.C.ABS_MT_POSITION_X, event.button.x)
				genEmuEvent(ffi.C.EV_ABS, ffi.C.ABS_MT_POSITION_Y, event.button.y)
				genEmuEvent(ffi.C.EV_SYN, ffi.C.SYN_REPORT, 0)
			elseif event.type == SDL.SDL.SDL_QUIT then
				error("application forced to quit")
			end

			-- check if there are more events to flush
			got_event = SDL.SDL.SDL_PollEvent(event)
		end
		evloop.abort_loop()
	end
end

function input.open()
	SDL.open()
end

function input.waitForEvent()
	while #input_queue == 0 do
		evloop.register_timer_in_ms(poll_time, input.poller)
		evloop.loop()
	end
	return table.remove(input_queue, 1)
end

return input


================================================
FILE: ffi/input_kindle.lua
================================================
local ffi = require("ffi")
local evloop = require("ffi/eventloop")

local dummy = require("ffi/posix_h")
local dummy = require("ffi/linux_input_h")

-- this module
local input = {}

-- the input event buffer
local input_queue = {}

function input.read(fd)
	local event = ffi.new("struct input_event")
	local n = ffi.C.read(fd, event, ffi.sizeof(event))
	if n ~= ffi.sizeof(event) then error("could not read full input_event") end
	table.insert(input_queue, event)
	evloop.abort_loop()
end

function input.err(fd)
	io.stderr:write("problem reading from fd "..fd..", closing.\n")
	evloop.unregister_fd(fd)
end

function input.hup(fd)
	io.stderr:write("hangup on fd "..fd..", closing.\n")
	evloop.unregister_fd(fd)
end

function input.open(device)
	local fd = ffi.C.open(device, bit.bor(ffi.C.O_RDONLY, ffi.C.O_NONBLOCK))
	if fd == -1 then
		error("cannot open device " .. device .. ", error " .. ffi.errno())
	end
	ffi.C.ioctl(fd, ffi.C.EVIOCGRAB, ffi.new("uint64_t", 1))
	evloop.register_fd(fd, input)
end

function input.waitForEvent()
	if #input_queue == 0 then
		evloop.loop()
	end
	assert(#input_queue > 0, "no input events could be aquired")
	return table.remove(input_queue, 1)
end

return input


================================================
FILE: ffi/linux_fb_h.lua
================================================
local ffi = require("ffi")
ffi.cdef[[
static const int FBIOGET_FSCREENINFO = 17922;
static const int FBIOGET_VSCREENINFO = 17920;
static const int FB_TYPE_PACKED_PIXELS = 0;
struct fb_bitfield {
  unsigned int offset;
  unsigned int length;
  unsigned int msb_right;
};
struct fb_fix_screeninfo {
  char id[16];
  long unsigned int smem_start;
  unsigned int smem_len;
  unsigned int type;
  unsigned int type_aux;
  unsigned int visual;
  short unsigned int xpanstep;
  short unsigned int ypanstep;
  short unsigned int ywrapstep;
  unsigned int line_length;
  long unsigned int mmio_start;
  unsigned int mmio_len;
  unsigned int accel;
  short unsigned int capabilities;
  short unsigned int reserved[2];
};
struct fb_var_screeninfo {
  unsigned int xres;
  unsigned int yres;
  unsigned int xres_virtual;
  unsigned int yres_virtual;
  unsigned int xoffset;
  unsigned int yoffset;
  unsigned int bits_per_pixel;
  unsigned int grayscale;
  struct fb_bitfield red;
  struct fb_bitfield green;
  struct fb_bitfield blue;
  struct fb_bitfield transp;
  unsigned int nonstd;
  unsigned int activate;
  unsigned int height;
  unsigned int width;
  unsigned int accel_flags;
  unsigned int pixclock;
  unsigned int left_margin;
  unsigned int right_margin;
  unsigned int upper_margin;
  unsigned int lower_margin;
  unsigned int hsync_len;
  unsigned int vsync_len;
  unsigned int sync;
  unsigned int vmode;
  unsigned int rotate;
  unsigned int colorspace;
  unsigned int reserved[4];
};
]]


================================================
FILE: ffi/linux_input_h.lua
================================================
local ffi = require("ffi")
ffi.cdef[[
static const int EVIOCGRAB = 1074021776;
static const int EV_SYN = 0;
static const int EV_KEY = 1;
static const int EV_REL = 2;
static const int EV_ABS = 3;
static const int EV_MSC = 4;
static const int EV_SW = 5;
static const int EV_LED = 17;
static const int EV_SND = 18;
static const int EV_REP = 20;
static const int EV_FF = 21;
static const int EV_PWR = 22;
static const int EV_FF_STATUS = 23;
static const int EV_MAX = 31;
static const int SYN_REPORT = 0;
static const int SYN_CONFIG = 1;
static const int SYN_MT_REPORT = 2;
static const int SYN_DROPPED = 3;
static const int ABS_MT_SLOT = 47;
static const int ABS_MT_TOUCH_MAJOR = 48;
static const int ABS_MT_TOUCH_MINOR = 49;
static const int ABS_MT_WIDTH_MAJOR = 50;
static const int ABS_MT_WIDTH_MINOR = 51;
static const int ABS_MT_ORIENTATION = 52;
static const int ABS_MT_POSITION_X = 53;
static const int ABS_MT_POSITION_Y = 54;
static const int ABS_MT_TOOL_TYPE = 55;
static const int ABS_MT_BLOB_ID = 56;
static const int ABS_MT_TRACKING_ID = 57;
static const int ABS_MT_PRESSURE = 58;
static const int ABS_MT_DISTANCE = 59;
static const int ABS_MT_TOOL_X = 60;
static const int ABS_MT_TOOL_Y = 61;
struct input_event {
  struct timeval time;
  short unsigned int type;
  short unsigned int code;
  int value;
};
]]


================================================
FILE: ffi/mxcfb_kindle_h.lua
================================================
local ffi = require("ffi")
ffi.cdef[[
struct mxcfb_rect {
  unsigned int top;
  unsigned int left;
  unsigned int width;
  unsigned int height;
};
struct mxcfb_alt_buffer_data {
  unsigned int phys_addr;
  unsigned int width;
  unsigned int height;
  struct mxcfb_rect alt_update_region;
};
struct mxcfb_alt_buffer_data_kobo;
struct mxcfb_update_data {
  struct mxcfb_rect update_region;
  unsigned int waveform_mode;
  unsigned int update_mode;
  unsigned int update_marker;
  unsigned int hist_bw_waveform_mode;
  unsigned int hist_gray_waveform_mode;
  int temp;
  unsigned int flags;
  struct mxcfb_alt_buffer_data alt_buffer_data;
};
struct mxcfb_update_data_kobo;
static const int MXCFB_SEND_UPDATE = 1078478382;
]]


================================================
FILE: ffi/mxcfb_kobo_h.lua
================================================
local ffi = require("ffi")
ffi.cdef[[
struct mxcfb_rect {
  unsigned int top;
  unsigned int left;
  unsigned int width;
  unsigned int height;
};
struct mxcfb_alt_buffer_data {
  void *virt_addr;
  unsigned int phys_addr;
  unsigned int width;
  unsigned int height;
  struct mxcfb_rect alt_update_region;
};
struct mxcfb_alt_buffer_data_kobo;
struct mxcfb_update_data {
  struct mxcfb_rect update_region;
  unsigned int waveform_mode;
  unsigned int update_mode;
  unsigned int update_marker;
  int temp;
  unsigned int flags;
  struct mxcfb_alt_buffer_data alt_buffer_data;
};
struct mxcfb_update_data_kobo;
static const int MXCFB_SEND_UPDATE = 0x4044462e;
]]


================================================
FILE: ffi/posix_h.lua
================================================
local ffi = require("ffi")
ffi.cdef[[
typedef long unsigned int size_t;
typedef long int off_t;
struct timeval {
  long int tv_sec;
  long int tv_usec;
};
struct statvfs {
  long unsigned int f_bsize;
  long unsigned int f_frsize;
  long unsigned int f_blocks;
  long unsigned int f_bfree;
  long unsigned int f_bavail;
  long unsigned int f_files;
  long unsigned int f_ffree;
  long unsigned int f_favail;
  long unsigned int f_fsid;
  long unsigned int f_flag;
  long unsigned int f_namemax;
  int __f_spare[6];
};
int pipe(int *) __attribute__((__nothrow__, __leaf__));
int fork(void) __attribute__((nothrow));
int dup(int) __attribute__((__nothrow__, __leaf__));
int dup2(int, int) __attribute__((__nothrow__, __leaf__));
static const int O_RDWR = 2;
static const int O_RDONLY = 0;
static const int O_NONBLOCK = 2048;
int open(const char *, int, ...);
int close(int);
int fcntl(int, int, ...);
int execl(const char *, const char *, ...) __attribute__((__nothrow__, __leaf__));
int execlp(const char *, const char *, ...) __attribute__((__nothrow__, __leaf__));
int execv(const char *, char *const *) __attribute__((__nothrow__, __leaf__));
int execvp(const char *, char *const *) __attribute__((__nothrow__, __leaf__));
long int write(int, const void *, long unsigned int);
long int read(int, void *, long unsigned int);
int kill(int, int) __attribute__((__nothrow__, __leaf__));
int waitpid(int, int *, int);
struct pollfd {
  int fd;
  short int events;
  short int revents;
};
static const int POLLIN = 1;
static const int POLLOUT = 4;
static const int POLLERR = 8;
static const int POLLHUP = 16;
int poll(struct pollfd *, long unsigned int, int);
static const int PROT_READ = 1;
static const int PROT_WRITE = 2;
static const int MAP_SHARED = 1;
static const int MAP_FAILED = -1;
void *mmap(void *, long unsigned int, int, int, int, long int) __attribute__((__nothrow__, __leaf__));
int ioctl(int, long unsigned int, ...) __attribute__((__nothrow__, __leaf__));
unsigned int sleep(unsigned int);
int usleep(unsigned int);
int statvfs(const char *restrict, struct statvfs *restrict) __attribute__((__nothrow__, __leaf__));
int gettimeofday(struct timeval *restrict, struct timezone *restrict) __attribute__((__nothrow__, __leaf__));
char *realpath(const char *restrict, char *restrict) __attribute__((__nothrow__, __leaf__));
void *malloc(long unsigned int) __attribute__((malloc, leaf, nothrow));
void free(void *) __attribute__((__nothrow__, __leaf__));
char *strdup(const char *) __attribute__((malloc, leaf, nothrow));
char *strndup(const char *, long unsigned int) __attribute__((malloc, leaf, nothrow));
struct _IO_FILE *fopen(const char *restrict, const char *restrict);
int fclose(struct _IO_FILE *);
int printf(const char *, ...);
int sprintf(char *, const char *, ...) __attribute__((nothrow));
int fprintf(struct _IO_FILE *restrict, const char *restrict, ...);
int fputc(int, struct _IO_FILE *);
char *strerror(int) __attribute__((__nothrow__, __leaf__));
static const int EINTR = 4;
]]


================================================
FILE: ffi/rfbclient.lua
================================================
local ffi = require("ffi")

require("ffi/rfbclient_h")

local rfb = ffi.load("./libvncclient.so")

return rfb


================================================
FILE: ffi/rfbclient_h.lua
================================================
local ffi = require("ffi")
ffi.cdef[[
struct z_stream_s {
  unsigned char *next_in;
  unsigned int avail_in;
  long unsigned int total_in;
  unsigned char *next_out;
  unsigned int avail_out;
  long unsigned int total_out;
  char *msg;
  struct internal_state *state;
  void *(*zalloc)(void *, unsigned int, unsigned int);
  void (*zfree)(void *, void *);
  void *opaque;
  int data_type;
  long unsigned int adler;
  long unsigned int reserved;
};
struct rfbClientData {
  void *tag;
  void *data;
  struct rfbClientData *next;
};
typedef struct _rfbClient rfbClient;
typedef signed char rfbBool;
struct _rfbClient {
  unsigned char *frameBuffer;
  int width;
  int height;
  int endianTest;
  struct {
    signed char shareDesktop;
    signed char viewOnly;
    const char *encodingsString;
    signed char useBGR233;
    int nColours;
    signed char forceOwnCmap;
    signed char forceTrueColour;
    int requestedDepth;
    int compressLevel;
    int qualityLevel;
    signed char enableJPEG;
    signed char useRemoteCursor;
    signed char palmVNC;
    int scaleSetting;
  } appData;
  const char *programName;
  char *serverHost;
  int serverPort;
  signed char listenSpecified;
  int listenPort;
  int flashPort;
  struct {
    int x;
    int y;
    int w;
    int h;
  } updateRect;
  char buffer[307200];
  int sock;
  signed char canUseCoRRE;
  signed char canUseHextile;
  char *desktopName;
  struct {
    unsigned char bitsPerPixel;
    unsigned char depth;
    unsigned char bigEndian;
    unsigned char trueColour;
    short unsigned int redMax;
    short unsigned int greenMax;
    short unsigned int blueMax;
    unsigned char redShift;
    unsigned char greenShift;
    unsigned char blueShift;
    unsigned char pad1;
    short unsigned int pad2;
  } format;
  struct {
    short unsigned int framebufferWidth;
    short unsigned int framebufferHeight;
    struct {
      unsigned char bitsPerPixel;
      unsigned char depth;
      unsigned char bigEndian;
      unsigned char trueColour;
      short unsigned int redMax;
      short unsigned int greenMax;
      short unsigned int blueMax;
      unsigned char redShift;
      unsigned char greenShift;
      unsigned char blueShift;
      unsigned char pad1;
      short unsigned int pad2;
    } format;
    unsigned int nameLength;
  } si;
  char buf[8192];
  char *bufoutptr;
  int buffered;
  int ultra_buffer_size;
  char *ultra_buffer;
  int raw_buffer_size;
  char *raw_buffer;
  struct z_stream_s decompStream;
  signed char decompStreamInited;
  char zlib_buffer[30000];
  struct z_stream_s zlibStream[4];
  signed char zlibStreamActive[4];
  signed char cutZeros;
  int rectWidth;
  int rectColors;
  char tightPalette[1024];
  unsigned char tightPrevRow[12288];
  signed char jpegError;
  struct jpeg_source_mgr *jpegSrcManager;
  void *jpegBufferPtr;
  long unsigned int jpegBufferLen;
  unsigned char *rcSource;
  unsigned char *rcMask;
  struct rfbClientData *clientData;
  struct {
    struct _IO_FILE *file;
    struct timeval tv;
    signed char readTimestamp;
    signed char doNotSleep;
  } *vncRec;
  int KeyboardLedStateEnabled;
  int CurrentKeyboardLedState;
  int canHandleNewFBSize;
  void (*HandleTextChat)(struct _rfbClient *, int, char *);
  void (*HandleKeyboardLedState)(struct _rfbClient *, int, int);
  signed char (*HandleCursorPos)(struct _rfbClient *, int, int);
  void (*SoftCursorLockArea)(struct _rfbClient *, int, int, int, int);
  void (*SoftCursorUnlockScreen)(struct _rfbClient *);
  void (*GotFrameBufferUpdate)(struct _rfbClient *, int, int, int, int);
  char *(*GetPassword)(struct _rfbClient *);
  signed char (*MallocFrameBuffer)(struct _rfbClient *);
  void (*GotXCutText)(struct _rfbClient *, const char *, int);
  void (*Bell)(struct _rfbClient *);
  void (*GotCursorShape)(struct _rfbClient *, int, int, int, int, int);
  void (*GotCopyRect)(struct _rfbClient *, int, int, int, int, int, int);
  struct {
    unsigned char client2server[32];
    unsigned char server2client[32];
  } supportedMessages;
  int major;
  int minor;
  unsigned int authScheme;
  unsigned int subAuthScheme;
  void *tlsSession;
  union _rfbCredential *(*GetCredential)(struct _rfbClient *, int);
  unsigned int *clientAuthSchemes;
  char *destHost;
  int destPort;
  int QoS_DSCP;
  void (*HandleXvpMsg)(struct _rfbClient *, unsigned char, unsigned char);
  int listenSock;
  void (*FinishedFrameBufferUpdate)(struct _rfbClient *);
  char *listenAddress;
  int listen6Sock;
  char *listen6Address;
  int listen6Port;
  long unsigned int outputWindow;
};
struct _rfbClient *rfbGetClient(int, int, int);
signed char rfbInitClient(struct _rfbClient *, int *, char **);
extern void (*rfbClientLog)(const char *, ...);
signed char SendKeyEvent(struct _rfbClient *, unsigned int, signed char);
signed char SendPointerEvent(struct _rfbClient *, int, int, int);
signed char SendFramebufferUpdateRequest(struct _rfbClient *, int, int, int, int, signed char);
signed char SendIncrementalFramebufferUpdateRequest(struct _rfbClient *);
signed char SendScaleSetting(struct _rfbClient *, int);
signed char SetFormatAndEncodings(struct _rfbClient *);
void rfbClientCleanup(struct _rfbClient *);
signed char HandleRFBServerMessage(struct _rfbClient *);
]]


================================================
FILE: ffi/util.lua
================================================
--[[
Module for various utility functions
]]

local ffi = require "ffi"
local bit = require "bit"

require("ffi/posix_h")

local util = {}

local timeval = ffi.new("struct timeval")
function util.gettime()
	ffi.C.gettimeofday(timeval, nil)
	return tonumber(timeval.tv_sec),
		tonumber(timeval.tv_usec)
end

util.sleep=ffi.C.sleep
util.usleep=ffi.C.usleep

local statvfs = ffi.new("struct statvfs")
function util.df(path)
	ffi.C.statvfs(path, statvfs)
	return tonumber(statvfs.f_blocks * statvfs.f_bsize),
		tonumber(statvfs.f_bfree * statvfs.f_bsize)
end

function util.realpath(path)
	local path_ptr = ffi.C.realpath(path, nil)
	if path_ptr == nil then
		return nil
	end
	path = ffi.string(path_ptr)
	ffi.C.free(path_ptr)
	return path
end

function util.utf8charcode(charstring)
	local ptr = ffi.cast("uint8_t *", charstring)
	local len = #charstring
	local result = 0
	if len == 1 then
		return bit.band(ptr[0], 0x7F)
	elseif len == 2 then 
		return bit.lshift(bit.band(ptr[0], 0x1F), 6) +
			bit.band(ptr[1], 0x3F)
	elseif len == 3 then
		return bit.lshift(bit.band(ptr[0], 0x0F), 12) +
			bit.lshift(bit.band(ptr[1], 0x3F), 6) +
			bit.band(ptr[2], 0x3F)
	end
end

function util.isEmulated()
	return (ffi.arch ~= "arm")
end

return util


================================================
FILE: ffi-cdecl/SDL1_2_decl.c
================================================
#include <SDL/SDL.h>

#include "cdecl.h"

cdecl_type(Uint32)
cdecl_type(Sint32)
cdecl_type(Uint16)
cdecl_type(Sint16)
cdecl_type(Uint8)
cdecl_type(Sint8)

//cdecl_type(SDLKey)
//cdecl_type(SDLMod)
cdecl_struct(SDL_keysym)

cdecl_type(SDL_EventType)
cdecl_type(SDL_EventMask)

cdecl_struct(SDL_ActiveEvent)
cdecl_struct(SDL_KeyboardEvent)
cdecl_struct(SDL_MouseMotionEvent)
cdecl_struct(SDL_MouseButtonEvent)
cdecl_struct(SDL_JoyAxisEvent)
cdecl_struct(SDL_JoyBallEvent)
cdecl_struct(SDL_JoyHatEvent)
cdecl_struct(SDL_JoyButtonEvent)
cdecl_struct(SDL_ResizeEvent)
cdecl_struct(SDL_ExposeEvent)
cdecl_struct(SDL_QuitEvent)
cdecl_struct(SDL_UserEvent)
cdecl_struct(SDL_SysWMEvent)
cdecl_union(SDL_Event)

cdecl_struct(SDL_Rect)
cdecl_struct(SDL_Color)
cdecl_struct(SDL_Palette)
cdecl_struct(SDL_PixelFormat)
cdecl_struct(SDL_Surface)

cdecl_func(SDL_Init)
cdecl_func(SDL_WasInit)
cdecl_func(SDL_Quit)
cdecl_func(SDL_SetVideoMode)
cdecl_func(SDL_EnableKeyRepeat)
cdecl_func(SDL_WaitEvent)
cdecl_func(SDL_PollEvent)
cdecl_func(SDL_GetTicks)
cdecl_func(SDL_Delay)
cdecl_func(SDL_LockSurface)
cdecl_func(SDL_UnlockSurface)
cdecl_func(SDL_FillRect)
cdecl_func(SDL_Flip)
cdecl_func(SDL_MapRGB)

cdecl_const(SDL_INIT_TIMER)
cdecl_const(SDL_INIT_AUDIO)
cdecl_const(SDL_INIT_VIDEO)
cdecl_const(SDL_INIT_CDROM)
cdecl_const(SDL_INIT_JOYSTICK)
cdecl_const(SDL_INIT_NOPARACHUTE)
cdecl_const(SDL_INIT_EVENTTHREAD)
cdecl_const(SDL_INIT_EVERYTHING)

cdecl_const(SDL_SWSURFACE)
cdecl_const(SDL_HWSURFACE)
cdecl_const(SDL_ASYNCBLIT)

cdecl_const(SDL_ANYFORMAT)
cdecl_const(SDL_HWPALETTE)
cdecl_const(SDL_DOUBLEBUF)
cdecl_const(SDL_FULLSCREEN)
cdecl_const(SDL_OPENGL)
cdecl_const(SDL_OPENGLBLIT)
cdecl_const(SDL_RESIZABLE)
cdecl_const(SDL_NOFRAME)

cdecl_const(SDL_HWACCEL)
cdecl_const(SDL_SRCCOLORKEY)
cdecl_const(SDL_RLEACCELOK)
cdecl_const(SDL_RLEACCEL)
cdecl_const(SDL_SRCALPHA)
cdecl_const(SDL_PREALLOC)


================================================
FILE: ffi-cdecl/einkfb_decl.c
================================================
// standard Linux framebuffer headers
#include <linux/fb.h>

#include <linux/ioctl.h>
// specialized eink framebuffer headers
typedef unsigned int u_int;
typedef unsigned long u_long;
#include "include/einkfb.h"

#include "cdecl.h"

cdecl_enum(fx_type)
cdecl_struct(update_area_t)
cdecl_enum(orientation_t)

cdecl_enum(einkfb_events_t)
cdecl_struct(einkfb_event_t)

cdecl_const(FBIO_EINK_UPDATE_DISPLAY)
cdecl_const(FBIO_EINK_UPDATE_DISPLAY_AREA)
cdecl_const(FBIO_EINK_SET_DISPLAY_ORIENTATION)
cdecl_const(FBIO_EINK_GET_DISPLAY_ORIENTATION)



================================================
FILE: ffi-cdecl/include/README
================================================
The include file "einkfb.h" is distributed with Amazons Linux kernel sources
for the Kindle. It has no further copyright notice, so it's assumed to be
released under the GPLv2 originally. Under the "any later version" clause, it
should be OK to include it in this GPLv3 application.



================================================
FILE: ffi-cdecl/include/einkfb.h
================================================
#ifndef _EINKFB_H
#define _EINKFB_H

#define EINK_1BPP               1
#define EINK_2BPP               2
#define EINK_4BPP               4
#define EINK_8BPP               8
#define EINK_BPP_MAX            EINK_8BPP

#define EINK_WHITE              0x00    // For whacking all the pixels in a...
#define EINK_BLACK              0xFF    // ...byte (8, 4, 2, or 1) at once.

// Replace EINK_WHITE & EINK_BLACK with the following macros.
//
#define eink_white(b)           EINK_WHITE
#define eink_black(b)           EINK_BLACK

// For pixels (at bytes at a time) other than white/black, the following holds.
//
#define eink_pixels(b, p)       (p)

#define EINK_ORIENT_LANDSCAPE   1
#define EINK_ORIENT_PORTRAIT    0

#define BPP_SIZE(r, b)          (((r)*(b))/8)
#define BPP_MAX(b)              (1 << (b))

#define U_IN_RANGE(n, m, M)     ((((n) == 0) && ((m) == 0)) || (((n) > (m)) && ((n) <= (M))))
#define IN_RANGE(n, m, M)       (((n) >= (m)) && ((n) <= (M)))

#define ORIENTATION(x, y)       (((y) > (x)) ? EINK_ORIENT_PORTRAIT : EINK_ORIENT_LANDSCAPE)

struct raw_image_t
{
    int xres,		// image's width, in pixels
        yres,		// image's height
        bpp;		// image's pixel (bit) depth
    
    __u8  start[]; 	// actual start of image
};
typedef struct raw_image_t raw_image_t;

struct image_t
{
    int xres,       // image's visual width, in pixels
        xlen,       // image's actual width, used for rowbyte & memory size calculations
        yres,       // image's height
        bpp;        // image's pixel (bit) depth
        
    __u8  *start;     // pointer to start of image
};
typedef struct image_t image_t;

#define INIT_IMAGE_T() { 0, 0, 0, 0, NULL }

enum splash_screen_type
{
    // Simple (non-composite) splash screens.
    //
    //splash_screen_powering_off = 0,        // Deprecated.
    //splash_screen_powering_on,             // Deprecated.

    //splash_screen_powering_off_wireless,   // Deprecated.
    //splash_screen_powering_on_wireless,    // Deprecated.
    
    //splash_screen_exit,                    // Deprecated.
    splash_screen_logo = 5,
    
    //splash_screen_usb_internal,            // Deprecated.
    //splash_screen_usb_external,            // Deprecated.
    //splash_screen_usb,                     // Deprecated.
    
    //splash_screen_sleep,                   // Deprecated.
    //splash_screen_update,                  // Deprecated.
    
    //num_splash_screens,                    // Deprecated.

    // Composite splash screens & messages.
    //
    //splash_screen_drivemode_0,              // Deprecated.
    //splash_screen_drivemode_1,              // Deprecated.
    //splash_screen_drivemode_2,              // Deprecated.
    //splash_screen_drivemode_3,              // Deprecated.
    
    splash_screen_power_off_clear_screen = 16,// Message: clear screen and power down controller.
    //splash_screen_screen_saver_picture,     // Deprecated.
    
    splash_screen_shim_picture = 18,          // Message: shim wants a picture displayed.

    splash_screen_lowbatt,                    // Picture: Not composite, post-legacy ordering (Mario only).
    splash_screen_reboot,                     // Picture: Composite (not used on Fiona).
    
    splash_screen_update_initial,             // Composite software-update screens. 
    splash_screen_update_success,             //
    splash_screen_update_failure,             //
    splash_screen_update_failure_no_wait,     //
    
    splash_screen_repair_needed,              // More composite screens.
    splash_screen_boot,                       // 

    splash_screen_invalid = -1
};
typedef enum splash_screen_type splash_screen_type;

// Alias some of the legacy enumerations for Mario.
//
#define splash_screen_usb_recovery_util ((splash_screen_type)8) // splash_screen_usb

struct power_override_t
{
    u_int   cmd;
    u_long  arg;
};
typedef struct power_override_t power_override_t;

enum fx_type
{
    // Deprecated from the HAL, but still supported by the Shim.
    //
    fx_mask = 11,                           // Only for use with update_area_t's non-NULL buffer which_fx.
    fx_buf_is_mask = 14,                    // Same as fx_mask, but doesn't require a doubling (i.e., the buffer & mask are the same).
    
    fx_none = -1,                           // No legacy-FX to apply.
    
    // Screen-update FX, supported by HAL.
    //
    fx_flash = 20,                          // Only for use with update_area_t (for faking a flashing update).
    fx_invert = 21,                         // Only for use with update_area_t (only inverts output data).
    
    fx_update_partial = 0,                  // eInk GU/PU/MU-style (non-flashing) update.
    fx_update_full = 1                      // eInk GC-style (slower, flashing) update.
};
typedef enum fx_type fx_type;

// The only valid legacy-FX types for area updates are fx_mask and fx_buf_is_mask.
//
#define UPDATE_AREA_FX(f)                   \
    ((fx_mask == (f))                   ||  \
     (fx_buf_is_mask == (f)))

// The default ("none") for area updates is partial (non-flashing); full (flashing) updates
// are for FX and such (i.e., explicit completion is desired).
//
#define UPDATE_AREA_PART(f)                 \
    ((fx_none == (f))           ||          \
     (fx_update_partial == (f)))
     
#define UPDATE_AREA_FULL(f)                 \
    (UPDATE_AREA_FX(f)          ||          \
     (fx_update_full == (f)))

#define UPDATE_AREA_MODE(f)                 \
    (UPDATE_AREA_FULL(f) ? fx_update_full   \
                         : fx_update_partial)

// For use with the FBIO_EINK_UPDATE_DISPLAY ioctl.
//
#define UPDATE_PART(f)                      \
    (fx_update_partial == (f))
#define UPDATE_FULL(f)                      \
    (fx_update_full == (f))
#define UPDATE_MODE(f)                      \
    (UPDATE_FULL(f) ? fx_update_full        \
                    : fx_update_partial)

struct rect_t
{
    // Note:  The bottom-right (x2, y2) coordinate is actually such that (x2 - x1) and (y2 - y1)
    //        are xres and yres, respectively, when normally xres and yres would be
    //        (x2 - x1) + 1 and (y2 - y1) + 1, respectively.
    //
    int x1, y1, x2, y2;
};
typedef struct rect_t rect_t;

#define INIT_RECT_T() { 0, 0, 0, 0 }
#define MAX_EXCLUDE_RECTS 8

struct fx_t
{
    fx_type     update_mode,                // Screen-update FX:  fx_update_full | fx_update_partial.
                which_fx;                   // Shim (legacy) FX.
    
    int         num_exclude_rects;          // 0..MAX_EXCLUDE_RECTS.
    rect_t      exclude_rects[MAX_EXCLUDE_RECTS];
};
typedef struct fx_t fx_t;

#define INIT_FX_T()                     \
    { fx_update_partial, fx_none, 0, {  \
      INIT_RECT_T(),                    \
      INIT_RECT_T(),                    \
      INIT_RECT_T(),                    \
      INIT_RECT_T(),                    \
      INIT_RECT_T(),                    \
      INIT_RECT_T(),                    \
      INIT_RECT_T(),                    \
      INIT_RECT_T()} }

struct update_area_t
{
    // Note:  The bottom-right (x2, y2) coordinate is actually such that (x2 - x1) and (y2 - y1)
    //        are xres and yres, respectively, when normally xres and yres would be
    //        (x2 - x1) + 1 and (y2 - y1) + 1, respectively.
    //
    int         x1, y1,                     // Top-left...
                x2, y2;                     // ...bottom-right.
    
    fx_type     which_fx;                   // FX to use.
        
    __u8        *buffer;                    // If NULL, extract from framebuffer, top-left to bottom-right, by rowbytes.
};
typedef struct update_area_t update_area_t;

#define INIT_UPDATE_AREA_T() { 0, 0, 0, 0, fx_none, NULL }

struct progressbar_xy_t
{
    int         x, y;                       // Top-left corner of progressbar's position (ignores x for now).
};
typedef struct progressbar_xy_t progressbar_xy_t;

enum screen_saver_t
{
    screen_saver_invalid = 0,
    screen_saver_valid
};
typedef enum screen_saver_t screen_saver_t;

enum orientation_t
{
    orientation_portrait,
    orientation_portrait_upside_down,
    orientation_landscape,
    orientation_landscape_upside_down
};
typedef enum orientation_t orientation_t;

#define num_orientations (orientation_landscape_upside_down + 1)

#define ORIENTATION_PORTRAIT(o)     \
    ((orientation_portrait == (o))  || (orientation_portrait_upside_down == (o)))
    
#define ORIENTATION_LANDSCAPE(o)    \
    ((orientation_landscape == (o)) || (orientation_landscape_upside_down == (o)))
    
#define ORIENTATION_SAME(o1, o2)    \
    ((ORIENTATION_PORTRAIT(o1)  && ORIENTATION_PORTRAIT(o2)) || \
     (ORIENTATION_LANDSCAPE(o1) && ORIENTATION_LANDSCAPE(o2)))

enum einkfb_events_t
{
    einkfb_event_update_display = 0,        // FBIO_EINK_UPDATE_DISPLAY
    einkfb_event_update_display_area,       // FBIO_EINK_UPDATE_DISPLAY_AREA
    
    einkfb_event_blank_display,             // FBIOBLANK (fb.h)
    einkfb_event_rotate_display,            // FBIO_EINK_SET_DISPLAY_ORIENTATION
    
    einkfb_event_null = -1
};
typedef enum einkfb_events_t einkfb_events_t;

struct einkfb_event_t
{
    einkfb_events_t event;                  // Not all einkfb_events_t use all of the einkfb_event_t fields.
    
    fx_type         update_mode;            // Screen-update FX:  fx_update_full | fx_update_partial.
    
    // Note:  The bottom-right (x2, y2) coordinate is actually such that (x2 - x1) and (y2 - y1)
    //        are xres and yres, respectively, when normally xres and yres would be
    //        (x2 - x1) + 1 and (y2 - y1) + 1, respectively.
    //
    int             x1, y1,                 // Top-left...
                    x2, y2;                 // ...bottom-right.
                    
    orientation_t   orientation;            // Display rotated into this orientation.
};
typedef struct einkfb_event_t einkfb_event_t;

enum reboot_behavior_t
{
    reboot_screen_asis,
    reboot_screen_clear,
    reboot_screen_splash
};
typedef enum reboot_behavior_t reboot_behavior_t;

enum progressbar_badge_t
{
    progressbar_badge_success,
    progressbar_badge_failure,
    
    progressbar_badge_none
};
typedef enum progressbar_badge_t progressbar_badge_t;

enum sleep_behavior_t
{
    sleep_behavior_allow_sleep,
    sleep_behavior_prevent_sleep
};
typedef enum sleep_behavior_t sleep_behavior_t;

#define EINK_FRAME_BUFFER                   "/dev/fb/0"

#define SIZEOF_EINK_EVENT                   sizeof(einkfb_event_t)
#define EINK_EVENTS                         "/dev/misc/eink_events"

#define EINK_ROTATE_FILE                    "/sys/devices/platform/eink_fb.0/send_fake_rotate"
#define EINK_ROTATE_FILE_LEN                1
#define ORIENT_PORTRAIT                     orientation_portrait
#define ORIENT_PORTRAIT_UPSIDE_DOWN         orientation_portrait_upside_down
#define ORIENT_LANDSCAPE                    orientation_landscape
#define ORIENT_LANDSCAPE_UPSIDE_DOWN        orientation_landscape_upside_down
#define ORIENT_ASIS                         (-1)

#define EINK_USID_FILE                      "/var/local/eink/usid"

#define EINK_CLEAR_SCREEN                   0
#define EINK_CLEAR_BUFFER                   1

#define FBIO_EINK_SCREEN_CLEAR              FBIO_EINK_CLEAR_SCREEN, EINK_CLEAR_SCREEN
#define FBIO_EINK_BUFFER_CLEAR              FBIO_EINK_CLEAR_SCREEN, EINK_CLEAR_BUFFER

#define FBIO_MIN_SCREEN                     splash_screen_powering_off
#define FBIO_MAX_SCREEN                     num_splash_screens
#define FBIO_SCREEN_IN_RANGE(s)             \
    ((FBIO_MIN_SCREEN <= (s)) && (FBIO_MAX_SCREEN > (s)))

#define FBIO_MAGIC_NUMBER                   'F'

// Implemented in the eInk HAL.
//
#define FBIO_EINK_UPDATE_DISPLAY            _IO(FBIO_MAGIC_NUMBER, 0xdb) // 0x46db (fx_type)
#define FBIO_EINK_UPDATE_DISPLAY_AREA       _IO(FBIO_MAGIC_NUMBER, 0xdd) // 0x46dd (update_area_t *)

#define FBIO_EINK_RESTORE_DISPLAY           _IO(FBIO_MAGIC_NUMBER, 0xef) // 0x46ef (fx_type)

#define FBIO_EINK_SET_REBOOT_BEHAVIOR       _IO(FBIO_MAGIC_NUMBER, 0xe9) // 0x46e9 (reboot_behavior_t)
#define FBIO_EINK_GET_REBOOT_BEHAVIOR       _IO(FBIO_MAGIC_NUMBER, 0xed) // 0x46ed (reboot_behavior_t *)

#define FBIO_EINK_SET_DISPLAY_ORIENTATION   _IO(FBIO_MAGIC_NUMBER, 0xf0) // 0x46f0 (orientation_t)
#define FBIO_EINK_GET_DISPLAY_ORIENTATION   _IO(FBIO_MAGIC_NUMBER, 0xf1) // 0x46f1 (orientation_t *)

#define FBIO_EINK_SET_SLEEP_BEHAVIOR        _IO(FBIO_MAGIC_NUMBER, 0xf2) // 0x46f2 (sleep_behavior_t)
#define FBIO_EINK_GET_SLEEP_BEHAVIOR        _IO(FBIO_MAGIC_NUMBER, 0xf3) // 0x46f3 (sleep_behavior_t *)

// Implemented in the eInk Shim.
//
#define FBIO_EINK_UPDATE_DISPLAY_FX         _IO(FBIO_MAGIC_NUMBER, 0xe4) // 0x46e4 (fx_t *)
#define FBIO_EINK_SPLASH_SCREEN             _IO(FBIO_MAGIC_NUMBER, 0xdc) // 0x46dc (splash_screen_type)
#define FBIO_EINK_SPLASH_SCREEN_SLEEP       _IO(FBIO_MAGIC_NUMBER, 0xe0) // 0x46e0 (splash_screen_type)
#define FBIO_EINK_OFF_CLEAR_SCREEN          _IO(FBIO_MAGIC_NUMBER, 0xdf) // 0x46df (EINK_CLEAR_SCREEN || EINK_CLEAR_BUFFER)
#define FBIO_EINK_CLEAR_SCREEN              _IO(FBIO_MAGIC_NUMBER, 0xe1) // 0x46e1 (no args)
#define FBIO_EINK_POWER_OVERRIDE            _IO(FBIO_MAGIC_NUMBER, 0xe3) // 0x46e3 (power_override_t *)

#define FBIO_EINK_PROGRESSBAR               _IO(FBIO_MAGIC_NUMBER, 0xea) // 0x46ea (int: 0..100 -> draw progressbar || !(0..100) -> clear progressbar)
#define FBIO_EINK_PROGRESSBAR_SET_XY        _IO(FBIO_MAGIC_NUMBER, 0xeb) // 0x46eb (progressbar_xy_t *)
#define FBIO_EINK_PROGRESSBAR_BADGE         _IO(FBIO_MAGIC_NUMBER, 0xec) // 0x46ec (progressbar_badge_t);
#define FBIO_EINK_PROGRESSBAR_BACKGROUND    _IO(FBIO_MAGIC_NUMBER, 0xf4) // 0x46f4 (int: EINKFB_WHITE || EINKFB_BLACK)

// Deprecated from the HAL & Shim.
//
//#define FBIO_EINK_UPDATE_DISPLAY_ASYNC    _IO(FBIO_MAGIC_NUMBER, 0xde) // 0x46de (fx_type: fx_update_full || fx_update_partial)
//#define FBIO_EINK_FAKE_PNLCD              _IO(FBIO_MAGIC_NUMBER, 0xe8) // 0x46e8 (char *)

// For use with /proc/eink_fb/update_display.
//
#define PROC_EINK_UPDATE_DISPLAY_CLS        0   // FBIO_EINK_CLEAR_SCREEN
#define PROC_EINK_UPDATE_DISPLAY_PART       1   // FBIO_EINK_UPDATE_DISPLAY(fx_update_partial)
#define PROC_EINK_UPDATE_DISPLAY_FULL       2   // FBIO_EINK_UPDATE_DISPLAY(fx_update_full)
#define PROC_EINK_UPDATE_DISPLAY_AREA       3   // FBIO_EINK_UPDATE_DISPLAY_AREA
//#define PROC_EINK_UPDATE_DISPLAY_REST     4   // FBIO_EINK_RESTORE_SCREEN
#define PROC_EINK_UPDATE_DISPLAY_SCRN       5   // FBIO_EINK_SPLASH_SCREEN
#define PROC_EINK_UPDATE_DISPLAY_OVRD       6   // FBIO_EINK_FPOW_OVERRIDE
#define PROC_EINK_UPDATE_DISPLAY_FX         7   // FBIO_EINK_UPDATE_DISPLAY_FX
//#define PROC_EINK_UPDATE_DISPLAY_SYNC     8   // FBIO_EINK_SYNC_BUFFERS
//#define PROC_EINK_UPDATE_DISPLAY_PNLCD    9   // FBIO_EINK_FAKE_PNLCD
#define PROC_EINK_SET_REBOOT_BEHAVIOR      10   // FBIO_EINK_SET_REBOOT_BEHAVIOR
#define PROC_EINK_SET_PROGRESSBAR_XY       11   // FBIO_EINK_PROGRESSBAR_SET_XY
#define PROC_EINK_UPDATE_DISPLAY_SCRN_SLP  12   // FBIO_EINK_SPLASH_SCREEN_SLEEP
#define PROC_EINK_PROGRESSBAR_BADGE        13   // FBIO_EINK_PROGRESSBAR_BADGE
#define PROC_EINK_SET_DISPLAY_ORIENTATION  14   // FBIO_EINK_SET_DISPLAY_ORIENTATION
#define PROC_EINK_RESTORE_DISPLAY          15   // FBIO_EINK_RESTORE_DISPLAY
#define PROC_EINK_SET_SLEEP_BEHAVIOR       16   // FBIO_EINK_SET_SLEEP_BEHAVIOR
#define PROC_EINK_PROGRESSBAR_BACKGROUND   17   // FBIO_EINK_PROGRESSBAR_BACKGROUND
#define PROC_EINK_UPDATE_DISPLAY_WHICH     18   // FBIO_EINK_UPDATE_DISPLAY

//#define PROC_EINK_FAKE_PNLCD_TEST       100   // Programmatically drive FBIO_EINK_FAKE_PNLCD (not implemented).
#define PROC_EINK_GRAYSCALE_TEST          101   // Fills display with white-to-black ramp at current bit depth.

// Inter-module/inter-driver eink ioctl access.
//
extern int fiona_eink_ioctl_stub(unsigned int cmd, unsigned long arg);

#define eink_sys_ioctl(cmd, arg)            (get_fb_ioctl() ? (*get_fb_ioctl())((unsigned int)cmd, (unsigned long)arg)      \
                                                            : fiona_eink_ioctl_stub((unsigned int)cmd, (unsigned long)arg))

#endif // _EINKFB_H


================================================
FILE: ffi-cdecl/include/mxcfb-kindle.h
================================================
/*
 * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * - Modified by houqp, added mxcfb_update_data struct from GeekMaster's
 *   video player, refer to:
 *   http://www.mobileread.com/forums/showthread.php?t=177455&page=10
 *
 * - Modified mxcfb_alt_buffer_data struct according to include/linux/mxcfb.h
 *   from Kindle 5.3.0 firmware. Thanks to eureka@mobileread.
 *   http://www.mobileread.com/forums/showpost.php?p=2337118&postcount=818
 */

/*
 * The code contained herein is licensed under the GNU Lesser General
 * Public License.  You may obtain a copy of the GNU Lesser General
 * Public License Version 2.1 or later at the following locations:
 *
 * http://www.opensource.org/licenses/lgpl-license.html
 * http://www.gnu.org/copyleft/lgpl.html
 */

/*
 * @file arch-mxc/   mxcfb.h
 *
 * @brief Global header file for the MXC Frame buffer
 *
 * @ingroup Framebuffer
 */
#ifndef __ASM_ARCH_MXCFB_H__
#define __ASM_ARCH_MXCFB_H__

//#include <linux/fb.h>

#define FB_SYNC_OE_LOW_ACT	0x80000000
#define FB_SYNC_CLK_LAT_FALL	0x40000000
#define FB_SYNC_DATA_INVERT	0x20000000
#define FB_SYNC_CLK_IDLE_EN	0x10000000
#define FB_SYNC_SHARP_MODE	0x08000000
#define FB_SYNC_SWAP_RGB	0x04000000

struct mxcfb_gbl_alpha {
	int enable;
	int alpha;
};

struct mxcfb_loc_alpha {
	int enable;
	int alpha_in_pixel;
	unsigned long alpha_phy_addr0;
	unsigned long alpha_phy_addr1;
};

struct mxcfb_color_key {
	int enable;
	__u32 color_key;
};

struct mxcfb_pos {
	__u16 x;
	__u16 y;
};

struct mxcfb_gamma {
	int enable;
	int constk[16];
	int slopek[16];
};

struct mxcfb_rect {
	__u32 top;
	__u32 left;
	__u32 width;
	__u32 height;
};

#define GRAYSCALE_8BIT				0x1
#define GRAYSCALE_8BIT_INVERTED			0x2

#define AUTO_UPDATE_MODE_REGION_MODE		0
#define AUTO_UPDATE_MODE_AUTOMATIC_MODE		1

#define UPDATE_SCHEME_SNAPSHOT			0
#define UPDATE_SCHEME_QUEUE			1
#define UPDATE_SCHEME_QUEUE_AND_MERGE		2

#define UPDATE_MODE_PARTIAL			0x0
#define UPDATE_MODE_FULL			0x1

#define WAVEFORM_MODE_INIT			0x0	/* Screen goes to white (clears) */
#define WAVEFORM_MODE_DU			0x1	/* Grey->white/grey->black */
#define WAVEFORM_MODE_GC16			0x2	/* High fidelity (flashing) */
#define WAVEFORM_MODE_GC4			WAVEFORM_MODE_GC16 /* For compatibility */
#define WAVEFORM_MODE_GC16_FAST		0x3	/* Medium fidelity */
#define WAVEFORM_MODE_A2			0x4	/* Faster but even lower fidelity */
#define WAVEFORM_MODE_GL16			0x5	/* High fidelity from white transition */
#define WAVEFORM_MODE_GL16_FAST		0x6	/* Medium fidelity from white transition */

#define WAVEFORM_MODE_AUTO			257

#define TEMP_USE_AMBIENT			0x1000

#define EPDC_FLAG_ENABLE_INVERSION		0x01
#define EPDC_FLAG_FORCE_MONOCHROME		0x02
#define EPDC_FLAG_USE_ALT_BUFFER		0x100

#define FB_POWERDOWN_DISABLE			-1
#define FB_TEMP_AUTO_UPDATE_DISABLE     -1

struct mxcfb_alt_buffer_data {
	__u32 phys_addr;
	__u32 width;	/* width of entire buffer */
	__u32 height;	/* height of entire buffer */
	struct mxcfb_rect alt_update_region;	/* region within buffer to update */
};

struct mxcfb_update_data {
	struct mxcfb_rect update_region;
	__u32 waveform_mode;
	__u32 update_mode;
	__u32 update_marker;
	/* these two fields have been added by amazon */
	__u32 hist_bw_waveform_mode;
	__u32 hist_gray_waveform_mode;
	int temp;
	uint flags;
	struct mxcfb_alt_buffer_data alt_buffer_data;
};
typedef struct mxcfb_update_data mxcfb_update_data;

/* this is only used in kindle firmware 5.0, later version (5.1) has changed
 * the struct to mxcfb_update_data (see above) */
struct mxcfb_update_data_50x {
	struct mxcfb_rect update_region;
	__u32 waveform_mode;
	__u32 update_mode;
	__u32 update_marker;
	int temp;
	uint flags;
	struct mxcfb_alt_buffer_data alt_buffer_data;
};

/*
 * Structure used to define waveform modes for driver
 * Needed for driver to perform auto-waveform selection
 */
struct mxcfb_waveform_modes {
	int mode_init;
	int mode_du;
	int mode_gc4;
	int mode_gc8;
	int mode_gc16;
	int mode_gc32;
};

#define MXCFB_WAIT_FOR_VSYNC	_IOW('F', 0x20, u_int32_t)
#define MXCFB_SET_GBL_ALPHA     _IOW('F', 0x21, struct mxcfb_gbl_alpha)
#define MXCFB_SET_CLR_KEY       _IOW('F', 0x22, struct mxcfb_color_key)
#define MXCFB_SET_OVERLAY_POS   _IOWR('F', 0x24, struct mxcfb_pos)
#define MXCFB_GET_FB_IPU_CHAN 	_IOR('F', 0x25, u_int32_t)
#define MXCFB_SET_LOC_ALPHA     _IOWR('F', 0x26, struct mxcfb_loc_alpha)
#define MXCFB_SET_LOC_ALP_BUF    _IOW('F', 0x27, unsigned long)
#define MXCFB_SET_GAMMA	       _IOW('F', 0x28, struct mxcfb_gamma)
#define MXCFB_GET_FB_IPU_DI 	_IOR('F', 0x29, u_int32_t)
#define MXCFB_GET_DIFMT	       _IOR('F', 0x2A, u_int32_t)
#define MXCFB_GET_FB_BLANK     _IOR('F', 0x2B, u_int32_t)
#define MXCFB_SET_DIFMT		_IOW('F', 0x2C, u_int32_t)

/* IOCTLs for E-ink panel updates */
#define MXCFB_SET_WAVEFORM_MODES	_IOW('F', 0x2B, struct mxcfb_waveform_modes)
#define MXCFB_SET_TEMPERATURE		_IOW('F', 0x2C, int32_t)
#define MXCFB_SET_AUTO_UPDATE_MODE	_IOW('F', 0x2D, __u32)
#define MXCFB_SEND_UPDATE_50X		_IOW('F', 0x2E, struct mxcfb_update_data_50x)
#define MXCFB_WAIT_FOR_UPDATE_COMPLETE	_IOW('F', 0x2F, __u32)
#define MXCFB_SET_PWRDOWN_DELAY		_IOW('F', 0x30, int32_t)
#define MXCFB_GET_PWRDOWN_DELAY		_IOR('F', 0x31, int32_t)
#define MXCFB_SET_UPDATE_SCHEME		_IOW('F', 0x32, __u32)
#define MXCFB_GET_PMIC_TEMPERATURE	_IOR('F', 0x32, int32_t)
#define MXCFB_SET_BORDER_MODE		_IOR('F', 0x33, int32_t)
#define MXCFB_SET_EPD_PWR0_CTRL		_IOR('F', 0x34, int32_t)
#define MXCFB_SET_EPD_PWR2_CTRL		_IOR('F', 0x35, int32_t)
#define MXCFB_SET_TEMP_AUTO_UPDATE_PERIOD     _IOR('F', 0x36, int32_t)
#define MXCFB_SET_MERGE_ON_WAVEFORM_MISMATCH	_IOW('F', 0x37, int32_t)

/* IOCTLs for E-ink panel updates, kindle firmware version >= 5.1 */
#define MXCFB_SEND_UPDATE _IOW('F', 0x2E, struct mxcfb_update_data)

#ifdef __KERNEL__

extern struct fb_videomode mxcfb_modedb[];
extern int mxcfb_modedb_sz;

enum {
	MXCFB_REFRESH_OFF,
	MXCFB_REFRESH_AUTO,
	MXCFB_REFRESH_PARTIAL,
};

int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode,
			   struct mxcfb_rect *update_region);

int mxc_elcdif_frame_addr_setup(dma_addr_t phys);
#endif				/* __KERNEL__ */
#endif


================================================
FILE: ffi-cdecl/include/mxcfb-kobo.h
================================================
/*
 * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * - slightly modified (commented out include of fb.h) for Lua integration
 */

/*
 * The code contained herein is licensed under the GNU Lesser General
 * Public License.  You may obtain a copy of the GNU Lesser General
 * Public License Version 2.1 or later at the following locations:
 *
 * http://www.opensource.org/licenses/lgpl-license.html
 * http://www.gnu.org/copyleft/lgpl.html
 */

/*
 * @file arch-mxc/   mxcfb.h
 *
 * @brief Global header file for the MXC Frame buffer
 *
 * @ingroup Framebuffer
 */
#ifndef __ASM_ARCH_MXCFB_H__
#define __ASM_ARCH_MXCFB_H__

//#include <linux/fb.h>

#define FB_SYNC_OE_LOW_ACT	0x80000000
#define FB_SYNC_CLK_LAT_FALL	0x40000000
#define FB_SYNC_DATA_INVERT	0x20000000
#define FB_SYNC_CLK_IDLE_EN	0x10000000
#define FB_SYNC_SHARP_MODE	0x08000000
#define FB_SYNC_SWAP_RGB	0x04000000

struct mxcfb_gbl_alpha {
	int enable;
	int alpha;
};

struct mxcfb_loc_alpha {
	int enable;
	int alpha_in_pixel;
	unsigned long alpha_phy_addr0;
	unsigned long alpha_phy_addr1;
};

struct mxcfb_color_key {
	int enable;
	__u32 color_key;
};

struct mxcfb_pos {
	__u16 x;
	__u16 y;
};

struct mxcfb_gamma {
	int enable;
	int constk[16];
	int slopek[16];
};

struct mxcfb_rect {
	__u32 top;
	__u32 left;
	__u32 width;
	__u32 height;
};

#define GRAYSCALE_8BIT				0x1
#define GRAYSCALE_8BIT_INVERTED			0x2

#define AUTO_UPDATE_MODE_REGION_MODE		0
#define AUTO_UPDATE_MODE_AUTOMATIC_MODE		1

#define UPDATE_SCHEME_SNAPSHOT			0
#define UPDATE_SCHEME_QUEUE			1
#define UPDATE_SCHEME_QUEUE_AND_MERGE		2

#define UPDATE_MODE_PARTIAL			0x0
#define UPDATE_MODE_FULL			0x1

#define WAVEFORM_MODE_AUTO			257

#define TEMP_USE_AMBIENT			0x1000

#define EPDC_FLAG_ENABLE_INVERSION		0x01
#define EPDC_FLAG_FORCE_MONOCHROME		0x02
#define EPDC_FLAG_USE_ALT_BUFFER		0x100

#define FB_POWERDOWN_DISABLE			-1
#define FB_TEMP_AUTO_UPDATE_DISABLE     -1

struct mxcfb_alt_buffer_data {
	void *virt_addr;
	__u32 phys_addr;
	__u32 width;	/* width of entire buffer */
	__u32 height;	/* height of entire buffer */
	struct mxcfb_rect alt_update_region;	/* region within buffer to update */
};

struct mxcfb_update_data {
	struct mxcfb_rect update_region;
	__u32 waveform_mode;
	__u32 update_mode;
	__u32 update_marker;
	int temp;
	uint flags;
	struct mxcfb_alt_buffer_data alt_buffer_data;
};

/*
 * Structure used to define waveform modes for driver
 * Needed for driver to perform auto-waveform selection
 */
struct mxcfb_waveform_modes {
	int mode_init;
	int mode_du;
	int mode_gc4;
	int mode_gc8;
	int mode_gc16;
	int mode_gc32;
};

#define MXCFB_WAIT_FOR_VSYNC	_IOW('F', 0x20, u_int32_t)
#define MXCFB_SET_GBL_ALPHA     _IOW('F', 0x21, struct mxcfb_gbl_alpha)
#define MXCFB_SET_CLR_KEY       _IOW('F', 0x22, struct mxcfb_color_key)
#define MXCFB_SET_OVERLAY_POS   _IOWR('F', 0x24, struct mxcfb_pos)
#define MXCFB_GET_FB_IPU_CHAN 	_IOR('F', 0x25, u_int32_t)
#define MXCFB_SET_LOC_ALPHA     _IOWR('F', 0x26, struct mxcfb_loc_alpha)
#define MXCFB_SET_LOC_ALP_BUF    _IOW('F', 0x27, unsigned long)
#define MXCFB_SET_GAMMA	       _IOW('F', 0x28, struct mxcfb_gamma)
#define MXCFB_GET_FB_IPU_DI 	_IOR('F', 0x29, u_int32_t)
#define MXCFB_GET_DIFMT	       _IOR('F', 0x2A, u_int32_t)
#define MXCFB_GET_FB_BLANK     _IOR('F', 0x2B, u_int32_t)
#define MXCFB_SET_DIFMT		_IOW('F', 0x2C, u_int32_t)

/* IOCTLs for E-ink panel updates */
#define MXCFB_SET_WAVEFORM_MODES	_IOW('F', 0x2B, struct mxcfb_waveform_modes)
#define MXCFB_SET_TEMPERATURE		_IOW('F', 0x2C, int32_t)
#define MXCFB_SET_AUTO_UPDATE_MODE	_IOW('F', 0x2D, __u32)
#define MXCFB_SEND_UPDATE		_IOW('F', 0x2E, struct mxcfb_update_data)
#define MXCFB_WAIT_FOR_UPDATE_COMPLETE	_IOW('F', 0x2F, __u32)
#define MXCFB_SET_PWRDOWN_DELAY		_IOW('F', 0x30, int32_t)
#define MXCFB_GET_PWRDOWN_DELAY		_IOR('F', 0x31, int32_t)
#define MXCFB_SET_UPDATE_SCHEME		_IOW('F', 0x32, __u32)
#define MXCFB_GET_PMIC_TEMPERATURE	_IOR('F', 0x32, int32_t)
#define MXCFB_SET_BORDER_MODE		_IOR('F', 0x33, int32_t)
#define MXCFB_SET_EPD_PWR0_CTRL		_IOR('F', 0x34, int32_t)
#define MXCFB_SET_EPD_PWR2_CTRL		_IOR('F', 0x35, int32_t)
#define MXCFB_SET_TEMP_AUTO_UPDATE_PERIOD     _IOR('F', 0x36, int32_t)
#define MXCFB_SET_MERGE_ON_WAVEFORM_MISMATCH	_IOW('F', 0x37, int32_t)

#ifdef __KERNEL__

extern struct fb_videomode mxcfb_modedb[];
extern int mxcfb_modedb_sz;

enum {
	MXCFB_REFRESH_OFF,
	MXCFB_REFRESH_AUTO,
	MXCFB_REFRESH_PARTIAL,
};

int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode,
			   struct mxcfb_rect *update_region);

int mxc_elcdif_frame_addr_setup(dma_addr_t phys);
#endif				/* __KERNEL__ */
#endif


================================================
FILE: ffi-cdecl/include/mxcfb.h
================================================
/*
 * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * - Modified by houqp, added mxcfb_update_data struct from GeekMaster's
 *   video player, refer to:
 *   http://www.mobileread.com/forums/showthread.php?t=177455&page=10
 *
 * - Modified mxcfb_alt_buffer_data struct according to include/linux/mxcfb.h
 *   from Kindle 5.3.0 firmware. Thanks to eureka@mobileread.
 *   http://www.mobileread.com/forums/showpost.php?p=2337118&postcount=818
 *
 *
 * The code contained herein is licensed under the GNU Lesser General
 * Public License.  You may obtain a copy of the GNU Lesser General
 * Public License Version 2.1 or later at the following locations:
 *
 * http://www.opensource.org/licenses/lgpl-license.html
 * http://www.gnu.org/copyleft/lgpl.html
 */


/*
 * @file arch-mxc/   mxcfb.h
 *
 * @brief Global header file for the MXC Frame buffer
 *
 * @ingroup Framebuffer
 */

#ifndef __ASM_ARCH_MXCFB_H__
#define __ASM_ARCH_MXCFB_H__

//#include <linux/fb.h>

#define FB_SYNC_OE_LOW_ACT	0x80000000
#define FB_SYNC_CLK_LAT_FALL	0x40000000
#define FB_SYNC_DATA_INVERT	0x20000000
#define FB_SYNC_CLK_IDLE_EN	0x10000000
#define FB_SYNC_SHARP_MODE	0x08000000
#define FB_SYNC_SWAP_RGB	0x04000000

struct mxcfb_gbl_alpha {
	int enable;
	int alpha;
};

struct mxcfb_loc_alpha {
	int enable;
	int alpha_in_pixel;
	unsigned long alpha_phy_addr0;
	unsigned long alpha_phy_addr1;
};

struct mxcfb_color_key {
	int enable;
	__u32 color_key;
};

struct mxcfb_pos {
	__u16 x;
	__u16 y;
};

struct mxcfb_gamma {
	int enable;
	int constk[16];
	int slopek[16];
};

struct mxcfb_rect {
	__u32 top;
	__u32 left;
	__u32 width;
	__u32 height;
};

#define GRAYSCALE_8BIT				0x1
#define GRAYSCALE_8BIT_INVERTED			0x2

#define AUTO_UPDATE_MODE_REGION_MODE		0
#define AUTO_UPDATE_MODE_AUTOMATIC_MODE		1

#define UPDATE_SCHEME_SNAPSHOT			0
#define UPDATE_SCHEME_QUEUE			1
#define UPDATE_SCHEME_QUEUE_AND_MERGE		2

#define UPDATE_MODE_PARTIAL			0x0
#define UPDATE_MODE_FULL			0x1

#define WAVEFORM_MODE_INIT			0x0	/* Screen goes to white (clears) */
#define WAVEFORM_MODE_DU			0x1	/* Grey->white/grey->black */
#define WAVEFORM_MODE_GC16			0x2	/* High fidelity (flashing) */
#define WAVEFORM_MODE_GC4			WAVEFORM_MODE_GC16 /* For compatibility */
#define WAVEFORM_MODE_GC16_FAST		0x3	/* Medium fidelity */
#define WAVEFORM_MODE_A2			0x4	/* Faster but even lower fidelity */
#define WAVEFORM_MODE_GL16			0x5	/* High fidelity from white transition */
#define WAVEFORM_MODE_GL16_FAST		0x6	/* Medium fidelity from white transition */

#define WAVEFORM_MODE_AUTO			257

#define TEMP_USE_AMBIENT			0x1000

#define EPDC_FLAG_ENABLE_INVERSION		0x01
#define EPDC_FLAG_FORCE_MONOCHROME		0x02
#define EPDC_FLAG_USE_ALT_BUFFER		0x100

#define FB_POWERDOWN_DISABLE			-1
#define FB_TEMP_AUTO_UPDATE_DISABLE     -1

struct mxcfb_alt_buffer_data {
#ifdef KOBO_PLATFORM
	/* virt_addr is not included in amazon's source */
	void *virt_addr;
#endif
	__u32 phys_addr;
	__u32 width;	/* width of entire buffer */
	__u32 height;	/* height of entire buffer */
	struct mxcfb_rect alt_update_region;	/* region within buffer to update */
};

struct mxcfb_update_data {
	struct mxcfb_rect update_region;
	__u32 waveform_mode;
	__u32 update_mode;
	__u32 update_marker;
#ifndef KOBO_PLATFORM
	/* these two fields have been added by amazon */
	__u32 hist_bw_waveform_mode;
	__u32 hist_gray_waveform_mode;
#endif
	int temp;
	uint flags;
	struct mxcfb_alt_buffer_data alt_buffer_data;
};
typedef struct mxcfb_update_data mxcfb_update_data;

/* this is only used in kindle firmware 5.0, later version (5.1) has changed
 * the struct to mxcfb_update_data (see above) */
struct mxcfb_update_data_50x {
	struct mxcfb_rect update_region;
	__u32 waveform_mode;
	__u32 update_mode;
	__u32 update_marker;
	int temp;
	uint flags;
	struct mxcfb_alt_buffer_data alt_buffer_data;
};

/*
 * Structure used to define waveform modes for driver
 * Needed for driver to perform auto-waveform selection
 */
struct mxcfb_waveform_modes {
	int mode_init;
	int mode_du;
	int mode_gc4;
	int mode_gc8;
	int mode_gc16;
	int mode_gc32;
};

#define MXCFB_WAIT_FOR_VSYNC	_IOW('F', 0x20, u_int32_t)
#define MXCFB_SET_GBL_ALPHA     _IOW('F', 0x21, struct mxcfb_gbl_alpha)
#define MXCFB_SET_CLR_KEY       _IOW('F', 0x22, struct mxcfb_color_key)
#define MXCFB_SET_OVERLAY_POS   _IOWR('F', 0x24, struct mxcfb_pos)
#define MXCFB_GET_FB_IPU_CHAN 	_IOR('F', 0x25, u_int32_t)
#define MXCFB_SET_LOC_ALPHA     _IOWR('F', 0x26, struct mxcfb_loc_alpha)
#define MXCFB_SET_LOC_ALP_BUF    _IOW('F', 0x27, unsigned long)
#define MXCFB_SET_GAMMA	       _IOW('F', 0x28, struct mxcfb_gamma)
#define MXCFB_GET_FB_IPU_DI 	_IOR('F', 0x29, u_int32_t)
#define MXCFB_GET_DIFMT	       _IOR('F', 0x2A, u_int32_t)
#define MXCFB_GET_FB_BLANK     _IOR('F', 0x2B, u_int32_t)
#define MXCFB_SET_DIFMT		_IOW('F', 0x2C, u_int32_t)

/* IOCTLs for E-ink panel updates */
#define MXCFB_SET_WAVEFORM_MODES	_IOW('F', 0x2B, struct mxcfb_waveform_modes)
#define MXCFB_SET_TEMPERATURE		_IOW('F', 0x2C, int32_t)
#define MXCFB_SET_AUTO_UPDATE_MODE	_IOW('F', 0x2D, __u32)
#define MXCFB_SEND_UPDATE_50X		_IOW('F', 0x2E, struct mxcfb_update_data_50x)
#define MXCFB_WAIT_FOR_UPDATE_COMPLETE	_IOW('F', 0x2F, __u32)
#define MXCFB_SET_PWRDOWN_DELAY		_IOW('F', 0x30, int32_t)
#define MXCFB_GET_PWRDOWN_DELAY		_IOR('F', 0x31, int32_t)
#define MXCFB_SET_UPDATE_SCHEME		_IOW('F', 0x32, __u32)
#define MXCFB_GET_PMIC_TEMPERATURE	_IOR('F', 0x32, int32_t)
#define MXCFB_SET_BORDER_MODE		_IOR('F', 0x33, int32_t)
#define MXCFB_SET_EPD_PWR0_CTRL		_IOR('F', 0x34, int32_t)
#define MXCFB_SET_EPD_PWR2_CTRL		_IOR('F', 0x35, int32_t)
#define MXCFB_SET_TEMP_AUTO_UPDATE_PERIOD     _IOR('F', 0x36, int32_t)
#define MXCFB_SET_MERGE_ON_WAVEFORM_MISMATCH	_IOW('F', 0x37, int32_t)

/* IOCTLs for E-ink panel updates, kindle firmware version >= 5.1 */
#define MXCFB_SEND_UPDATE _IOW('F', 0x2E, struct mxcfb_update_data)

#ifdef __KERNEL__

extern struct fb_videomode mxcfb_modedb[];
extern int mxcfb_modedb_sz;

enum {
	MXCFB_REFRESH_OFF,
	MXCFB_REFRESH_AUTO,
	MXCFB_REFRESH_PARTIAL,
};

int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode,
			   struct mxcfb_rect *update_region);

int mxc_elcdif_frame_addr_setup(dma_addr_t phys);
#endif				/* __KERNEL__ */
#endif


================================================
FILE: ffi-cdecl/linux_fb_decl.c
================================================
// standard Linux framebuffer headers
#include <linux/fb.h>

#include <linux/ioctl.h>

#include "cdecl.h"

cdecl_const(FBIOGET_FSCREENINFO)
cdecl_const(FBIOGET_VSCREENINFO)

cdecl_const(FB_TYPE_PACKED_PIXELS)

cdecl_struct(fb_bitfield)
cdecl_struct(fb_fix_screeninfo)
cdecl_struct(fb_var_screeninfo)


================================================
FILE: ffi-cdecl/linux_input_decl.c
================================================
#include <linux/input.h>

#include "cdecl.h"

cdecl_const(EVIOCGRAB)

cdecl_const(EV_SYN)
cdecl_const(EV_KEY)
cdecl_const(EV_REL)
cdecl_const(EV_ABS)
cdecl_const(EV_MSC)
cdecl_const(EV_SW)
cdecl_const(EV_LED)
cdecl_const(EV_SND)
cdecl_const(EV_REP)
cdecl_const(EV_FF)
cdecl_const(EV_PWR)
cdecl_const(EV_FF_STATUS)
cdecl_const(EV_MAX)

cdecl_const(SYN_REPORT)
cdecl_const(SYN_CONFIG)
cdecl_const(SYN_MT_REPORT)
cdecl_const(SYN_DROPPED)

cdecl_const(ABS_MT_SLOT)
cdecl_const(ABS_MT_TOUCH_MAJOR)
cdecl_const(ABS_MT_TOUCH_MINOR)
cdecl_const(ABS_MT_WIDTH_MAJOR)
cdecl_const(ABS_MT_WIDTH_MINOR)
cdecl_const(ABS_MT_ORIENTATION)
cdecl_const(ABS_MT_POSITION_X)
cdecl_const(ABS_MT_POSITION_Y)
cdecl_const(ABS_MT_TOOL_TYPE)
cdecl_const(ABS_MT_BLOB_ID)
cdecl_const(ABS_MT_TRACKING_ID)
cdecl_const(ABS_MT_PRESSURE)
cdecl_const(ABS_MT_DISTANCE)
cdecl_const(ABS_MT_TOOL_X)
cdecl_const(ABS_MT_TOOL_Y)

cdecl_struct(input_event)


================================================
FILE: ffi-cdecl/mxcfb_kindle_decl.c
================================================
// standard Linux framebuffer headers
#include <linux/fb.h>

#include <linux/ioctl.h>
// specialized eink framebuffer headers
typedef unsigned int uint;
#include "include/mxcfb-kindle.h"

#include "cdecl.h"

cdecl_struct(mxcfb_rect)
cdecl_struct(mxcfb_alt_buffer_data)
cdecl_struct(mxcfb_alt_buffer_data_kobo)
cdecl_struct(mxcfb_update_data)
cdecl_struct(mxcfb_update_data_kobo)

cdecl_const(MXCFB_SEND_UPDATE)



================================================
FILE: ffi-cdecl/mxcfb_kobo_decl.c
================================================
// standard Linux framebuffer headers
#include <linux/fb.h>

#include <linux/ioctl.h>
// specialized eink framebuffer headers
typedef unsigned int uint;
#include "include/mxcfb-kobo.h"

#include "cdecl.h"

cdecl_struct(mxcfb_rect)
cdecl_struct(mxcfb_alt_buffer_data)
cdecl_struct(mxcfb_alt_buffer_data_kobo)
cdecl_struct(mxcfb_update_data)
cdecl_struct(mxcfb_update_data_kobo)

cdecl_const(MXCFB_SEND_UPDATE)



================================================
FILE: ffi-cdecl/posix_decl.c
================================================
#include <sys/mman.h>
#include <stropts.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <poll.h>
#include <sys/statvfs.h>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

#include "cdecl.h"

cdecl_type(size_t)
cdecl_type(off_t)

cdecl_struct(timeval)
cdecl_struct(statvfs)

cdecl_func(pipe)
cdecl_func(fork)
cdecl_func(dup)
cdecl_func(dup2)

cdecl_const(O_RDWR)
cdecl_const(O_RDONLY)
cdecl_const(O_NONBLOCK)
cdecl_func(open)
cdecl_func(close)
cdecl_func(fcntl)
cdecl_func(execl)
cdecl_func(execlp)
cdecl_func(execv)
cdecl_func(execvp)
cdecl_func(write)
cdecl_func(read)
cdecl_func(kill)
cdecl_func(waitpid)

cdecl_struct(pollfd)
cdecl_const(POLLIN)
cdecl_const(POLLOUT)
cdecl_const(POLLERR)
cdecl_const(POLLHUP)
cdecl_func(poll)

cdecl_const(PROT_READ)
cdecl_const(PROT_WRITE)
cdecl_const(MAP_SHARED)
cdecl_const(MAP_FAILED)
cdecl_func(mmap)

cdecl_func(ioctl)
cdecl_func(sleep)
cdecl_func(usleep)
cdecl_func(statvfs)
cdecl_func(gettimeofday)
cdecl_func(realpath)

cdecl_func(malloc)
cdecl_func(free)

cdecl_func(strdup)
cdecl_func(strndup)

cdecl_func(fopen)
cdecl_func(fclose)
cdecl_func(printf)
cdecl_func(sprintf)
cdecl_func(fprintf)
cdecl_func(fputc)

cdecl_func(strerror)
cdecl_const(EINTR)


================================================
FILE: ffi-cdecl/rfbclient_decl.c
================================================
#include <rfb/rfbclient.h>

#include "cdecl.h"

cdecl_struct(z_stream_s)
cdecl_struct(rfbClientData)
cdecl_type(rfbClient)
cdecl_type(rfbBool)
cdecl_struct(_rfbClient)
cdecl_func(rfbGetClient)
cdecl_func(rfbInitClient)
cdecl_func(rfbClientLog)
cdecl_func(SendKeyEvent)
cdecl_func(SendPointerEvent)
cdecl_func(SendFramebufferUpdateRequest)
cdecl_func(SendIncrementalFramebufferUpdateRequest)
cdecl_func(SendScaleSetting)
cdecl_func(SetFormatAndEncodings)
cdecl_func(rfbClientCleanup)
cdecl_func(HandleRFBServerMessage)


================================================
FILE: keys.lua
================================================
--[[
    This file contains settings related to key codes

    Copyright (C) 2010 Andy M. aka h1uke	h1ukeguy @ gmail.com
    Copyright (C) 2012 Hans-Werner Hilse <hilse@web.de>

    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 2 of the License, or
    (at your option) 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, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
]]--

KEY_1 = 2
KEY_2 = 3
KEY_3 = 4
KEY_4 = 5
KEY_5 = 6
KEY_6 = 7
KEY_7 = 8
KEY_8 = 9
KEY_9 = 10
KEY_0 = 11
KEY_Q = 16
KEY_W = 17
KEY_E = 18
KEY_R = 19
KEY_T = 20
KEY_Y = 21
KEY_U = 22
KEY_I = 23
KEY_O = 24
KEY_P = 25
KEY_A = 30
KEY_S = 31
KEY_D = 32
KEY_F = 33
KEY_G = 34
KEY_H = 35
KEY_J = 36
KEY_K = 37
KEY_L = 38
KEY_DEL = 14
KEY_Z = 44
KEY_X = 45
KEY_C = 46
KEY_V = 47
KEY_B = 48
KEY_N = 49
KEY_M = 50
KEY_DOT = 52
KEY_SLASH = 53
KEY_ENTER = 28
KEY_SHIFT = 42
KEY_ALT = 56
KEY_SPACE = 57
KEY_AA = 90
KEY_SYM = 94
KEY_VPLUS = 115
KEY_VMINUS = 114
KEY_HOME = 98
KEY_PGBCK = 109
KEY_PGFWD = 124
KEY_MENU = 139
KEY_BACK = 91
KEY_FW_LEFT = 105
KEY_FW_RIGHT = 106
KEY_FW_UP = 122
KEY_FW_DOWN = 123
KEY_FW_PRESS = 92

-- constants from <linux/input.h>
EV_KEY = 1

-- event values
EVENT_VALUE_KEY_PRESS = 1
EVENT_VALUE_KEY_REPEAT = 2
EVENT_VALUE_KEY_RELEASE = 0
 
function set_k3_keycodes()
	KEY_AA = 190
	KEY_SYM = 126
	KEY_HOME = 102
	KEY_BACK = 158
	KEY_PGFWD = 191
	KEY_LPGBCK = 193
	KEY_LPGFWD = 104
	KEY_VPLUS = 115
	KEY_VMINUS = 114
	KEY_FW_UP = 103
	KEY_FW_DOWN = 108
	KEY_FW_PRESS = 194
end



================================================
FILE: kvncviewer.ini
================================================
[Actions]
;; start kvncviewer, connect to 192.168.2.1:1
V U = !/mnt/us/kvncviewer/kvncviewer.sh 192.168.2.1:1 &
;; start kvncviewer, connect to somehostviawifi:1
V W = !/mnt/us/kvncviewer/kvncviewer.sh somehostviawifi:1 &
;; example with a password:
;V W = !/mnt/us/kvncviewer/kvncviewer.sh -password this_is_the_password somehostviawifi:1 &
;; stop kvncviewer
V Q = !killall kvncviewer


================================================
FILE: kvncviewer.sh
================================================
#!/bin/sh
cd $(dirname "$0")
LD_LIBRARY_PATH=.
export LD_LIBRARY_PATH

lipc-set-prop com.lab126.powerd preventScreenSaver 1
./luajit vncviewer -config config.lua "$@"
lipc-set-prop com.lab126.powerd preventScreenSaver 0

# send menu key twice to refresh display
echo "send 139" > /proc/keypad
echo "send 139" > /proc/keypad


================================================
FILE: rfbkeys.lua
================================================
--[[**********************************************************
Copyright (c) 1987, 1994  X Consortium

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of the X Consortium shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the X Consortium.


Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

*****************************************************************]]--

XK_VoidSymbol = 0xFFFFFF	--[[ void symbol ]]--

XK_BackSpace = 0xFF08	--[[ back space, back char ]]--
XK_Tab = 0xFF09
XK_Linefeed = 0xFF0A	--[[ Linefeed, LF ]]--
XK_Clear = 0xFF0B
XK_Return = 0xFF0D	--[[ Return, enter ]]--
XK_Pause = 0xFF13	--[[ Pause, hold ]]--
XK_Scroll_Lock = 0xFF14
XK_Sys_Req = 0xFF15
XK_Escape = 0xFF1B
XK_Delete = 0xFFFF	--[[ Delete, rubout ]]--



--[[ International & multi-key character composition ]]--

XK_Multi_key = 0xFF20  --[[ Multi-key character compose ]]--
XK_SingleCandidate = 0xFF3C
XK_MultipleCandidate = 0xFF3D
XK_PreviousCandidate = 0xFF3E

--[[ Japanese keyboard support ]]--

XK_Kanji = 0xFF21	--[[ Kanji, Kanji convert ]]--
XK_Muhenkan = 0xFF22  --[[ Cancel Conversion ]]--
XK_Henkan_Mode = 0xFF23  --[[ Start/Stop Conversion ]]--
XK_Henkan = 0xFF23  --[[ Alias for Henkan_Mode ]]--
XK_Romaji = 0xFF24  --[[ to Romaji ]]--
XK_Hiragana = 0xFF25  --[[ to Hiragana ]]--
XK_Katakana = 0xFF26  --[[ to Katakana ]]--
XK_Hiragana_Katakana = 0xFF27  --[[ Hiragana/Katakana toggle ]]--
XK_Zenkaku = 0xFF28  --[[ to Zenkaku ]]--
XK_Hankaku = 0xFF29  --[[ to Hankaku ]]--
XK_Zenkaku_Hankaku = 0xFF2A  --[[ Zenkaku/Hankaku toggle ]]--
XK_Touroku = 0xFF2B  --[[ Add to Dictionary ]]--
XK_Massyo = 0xFF2C  --[[ Delete from Dictionary ]]--
XK_Kana_Lock = 0xFF2D  --[[ Kana Lock ]]--
XK_Kana_Shift = 0xFF2E  --[[ Kana Shift ]]--
XK_Eisu_Shift = 0xFF2F  --[[ Alphanumeric Shift ]]--
XK_Eisu_toggle = 0xFF30  --[[ Alphanumeric toggle ]]--
XK_Zen_Koho = 0xFF3D	--[[ Multiple/All Candidate(s) ]]--
XK_Mae_Koho = 0xFF3E	--[[ Previous Candidate ]]--

--[[ 0xFF31 thru 0xFF3F are under XK_KOREAN = ]]--

--[[ Cursor control & motion ]]--

XK_Home = 0xFF50
XK_Left = 0xFF51	--[[ Move left, left arrow ]]--
XK_Up = 0xFF52	--[[ Move up, up arrow ]]--
XK_Right = 0xFF53	--[[ Move right, right arrow ]]--
XK_Down = 0xFF54	--[[ Move down, down arrow ]]--
XK_Prior = 0xFF55	--[[ Prior, previous ]]--
XK_Page_Up = 0xFF55
XK_Next = 0xFF56	--[[ Next ]]--
XK_Page_Down = 0xFF56
XK_End = 0xFF57	--[[ EOL ]]--
XK_Begin = 0xFF58	--[[ BOL ]]--


--[[ Misc Functions ]]--

XK_Select = 0xFF60	--[[ Select, mark ]]--
XK_Print = 0xFF61
XK_Execute = 0xFF62	--[[ Execute, run, do ]]--
XK_Insert = 0xFF63	--[[ Insert, insert here ]]--
XK_Undo = 0xFF65	--[[ Undo, oops ]]--
XK_Redo = 0xFF66	--[[ redo, again ]]--
XK_Menu = 0xFF67
XK_Find = 0xFF68	--[[ Find, search ]]--
XK_Cancel = 0xFF69	--[[ Cancel, stop, abort, exit ]]--
XK_Help = 0xFF6A	--[[ Help ]]--
XK_Break = 0xFF6B
XK_Mode_switch = 0xFF7E	--[[ Character set switch ]]--
XK_script_switch = 0xFF7E  --[[ Alias for mode_switch ]]--
XK_Num_Lock = 0xFF7F

--[[ Keypad Functions, keypad numbers cleverly chosen to map to ascii ]]--

XK_KP_Space = 0xFF80	--[[ space ]]--
XK_KP_Tab = 0xFF89
XK_KP_Enter = 0xFF8D	--[[ enter ]]--
XK_KP_F1 = 0xFF91	--[[ PF1, KP_A, ... ]]--
XK_KP_F2 = 0xFF92
XK_KP_F3 = 0xFF93
XK_KP_F4 = 0xFF94
XK_KP_Home = 0xFF95
XK_KP_Left = 0xFF96
XK_KP_Up = 0xFF97
XK_KP_Right = 0xFF98
XK_KP_Down = 0xFF99
XK_KP_Prior = 0xFF9A
XK_KP_Page_Up = 0xFF9A
XK_KP_Next = 0xFF9B
XK_KP_Page_Down = 0xFF9B
XK_KP_End = 0xFF9C
XK_KP_Begin = 0xFF9D
XK_KP_Insert = 0xFF9E
XK_KP_Delete = 0xFF9F
XK_KP_Equal = 0xFFBD	--[[ equals ]]--
XK_KP_Multiply = 0xFFAA
XK_KP_Add = 0xFFAB
XK_KP_Separator = 0xFFAC	--[[ separator, often comma ]]--
XK_KP_Subtract = 0xFFAD
XK_KP_Decimal = 0xFFAE
XK_KP_Divide = 0xFFAF

XK_KP_0 = 0xFFB0
XK_KP_1 = 0xFFB1
XK_KP_2 = 0xFFB2
XK_KP_3 = 0xFFB3
XK_KP_4 = 0xFFB4
XK_KP_5 = 0xFFB5
XK_KP_6 = 0xFFB6
XK_KP_7 = 0xFFB7
XK_KP_8 = 0xFFB8
XK_KP_9 = 0xFFB9



--[[
 * Auxilliary Functions; note the duplicate definitions for left and right
 * function keys;  Sun keyboards and a few other manufactures have such
 * function key groups on the left and/or right sides of the keyboard.
 * We've not found a keyboard with more than 35 function keys total.
 ]]--

XK_F1 = 0xFFBE
XK_F2 = 0xFFBF
XK_F3 = 0xFFC0
XK_F4 = 0xFFC1
XK_F5 = 0xFFC2
XK_F6 = 0xFFC3
XK_F7 = 0xFFC4
XK_F8 = 0xFFC5
XK_F9 = 0xFFC6
XK_F10 = 0xFFC7
XK_F11 = 0xFFC8
XK_L1 = 0xFFC8
XK_F12 = 0xFFC9
XK_L2 = 0xFFC9
XK_F13 = 0xFFCA
XK_L3 = 0xFFCA
XK_F14 = 0xFFCB
XK_L4 = 0xFFCB
XK_F15 = 0xFFCC
XK_L5 = 0xFFCC
XK_F16 = 0xFFCD
XK_L6 = 0xFFCD
XK_F17 = 0xFFCE
XK_L7 = 0xFFCE
XK_F18 = 0xFFCF
XK_L8 = 0xFFCF
XK_F19 = 0xFFD0
XK_L9 = 0xFFD0
XK_F20 = 0xFFD1
XK_L10 = 0xFFD1
XK_F21 = 0xFFD2
XK_R1 = 0xFFD2
XK_F22 = 0xFFD3
XK_R2 = 0xFFD3
XK_F23 = 0xFFD4
XK_R3 = 0xFFD4
XK_F24 = 0xFFD5
XK_R4 = 0xFFD5
XK_F25 = 0xFFD6
XK_R5 = 0xFFD6
XK_F26 = 0xFFD7
XK_R6 = 0xFFD7
XK_F27 = 0xFFD8
XK_R7 = 0xFFD8
XK_F28 = 0xFFD9
XK_R8 = 0xFFD9
XK_F29 = 0xFFDA
XK_R9 = 0xFFDA
XK_F30 = 0xFFDB
XK_R10 = 0xFFDB
XK_F31 = 0xFFDC
XK_R11 = 0xFFDC
XK_F32 = 0xFFDD
XK_R12 = 0xFFDD
XK_F33 = 0xFFDE
XK_R13 = 0xFFDE
XK_F34 = 0xFFDF
XK_R14 = 0xFFDF
XK_F35 = 0xFFE0
XK_R15 = 0xFFE0

--[[ Modifiers ]]--

XK_Shift_L = 0xFFE1	--[[ Left shift ]]--
XK_Shift_R = 0xFFE2	--[[ Right shift ]]--
XK_Control_L = 0xFFE3	--[[ Left control ]]--
XK_Control_R = 0xFFE4	--[[ Right control ]]--
XK_Caps_Lock = 0xFFE5	--[[ Caps lock ]]--
XK_Shift_Lock = 0xFFE6	--[[ Shift lock ]]--

XK_Meta_L = 0xFFE7	--[[ Left meta ]]--
XK_Meta_R = 0xFFE8	--[[ Right meta ]]--
XK_Alt_L = 0xFFE9	--[[ Left alt ]]--
XK_Alt_R = 0xFFEA	--[[ Right alt ]]--
XK_Super_L = 0xFFEB	--[[ Left super ]]--
XK_Super_R = 0xFFEC	--[[ Right super ]]--
XK_Hyper_L = 0xFFED	--[[ Left hyper ]]--
XK_Hyper_R = 0xFFEE	--[[ Right hyper ]]--

--[[
 * ISO 9995 Function and Modifier Keys
 * Byte 3 = 0xFE
 ]]--

XK_ISO_Lock = 0xFE01
XK_ISO_Level2_Latch = 0xFE02
XK_ISO_Level3_Shift = 0xFE03
XK_ISO_Level3_Latch = 0xFE04
XK_ISO_Level3_Lock = 0xFE05
XK_ISO_Group_Shift = 0xFF7E	--[[ Alias for mode_switch ]]--
XK_ISO_Group_Latch = 0xFE06
XK_ISO_Group_Lock = 0xFE07
XK_ISO_Next_Group = 0xFE08
XK_ISO_Next_Group_Lock = 0xFE09
XK_ISO_Prev_Group = 0xFE0A
XK_ISO_Prev_Group_Lock = 0xFE0B
XK_ISO_First_Group = 0xFE0C
XK_ISO_First_Group_Lock = 0xFE0D
XK_ISO_Last_Group = 0xFE0E
XK_ISO_Last_Group_Lock = 0xFE0F

XK_ISO_Left_Tab = 0xFE20
XK_ISO_Move_Line_Up = 0xFE21
XK_ISO_Move_Line_Down = 0xFE22
XK_ISO_Partial_Line_Up = 0xFE23
XK_ISO_Partial_Line_Down = 0xFE24
XK_ISO_Partial_Space_Left = 0xFE25
XK_ISO_Partial_Space_Right = 0xFE26
XK_ISO_Set_Margin_Left = 0xFE27
XK_ISO_Set_Margin_Right = 0xFE28
XK_ISO_Release_Margin_Left = 0xFE29
XK_ISO_Release_Margin_Right = 0xFE2A
XK_ISO_Release_Both_Margins = 0xFE2B
XK_ISO_Fast_Cursor_Left = 0xFE2C
XK_ISO_Fast_Cursor_Right = 0xFE2D
XK_ISO_Fast_Cursor_Up = 0xFE2E
XK_ISO_Fast_Cursor_Down = 0xFE2F
XK_ISO_Continuous_Underline = 0xFE30
XK_ISO_Discontinuous_Underline = 0xFE31
XK_ISO_Emphasize = 0xFE32
XK_ISO_Center_Object = 0xFE33
XK_ISO_Enter = 0xFE34

XK_dead_grave = 0xFE50
XK_dead_acute = 0xFE51
XK_dead_circumflex = 0xFE52
XK_dead_tilde = 0xFE53
XK_dead_macron = 0xFE54
XK_dead_breve = 0xFE55
XK_dead_abovedot = 0xFE56
XK_dead_diaeresis = 0xFE57
XK_dead_abovering = 0xFE58
XK_dead_doubleacute = 0xFE59
XK_dead_caron = 0xFE5A
XK_dead_cedilla = 0xFE5B
XK_dead_ogonek = 0xFE5C
XK_dead_iota = 0xFE5D
XK_dead_voiced_sound = 0xFE5E
XK_dead_semivoiced_sound = 0xFE5F
XK_dead_belowdot = 0xFE60

XK_First_Virtual_Screen = 0xFED0
XK_Prev_Virtual_Screen = 0xFED1
XK_Next_Virtual_Screen = 0xFED2
XK_Last_Virtual_Screen = 0xFED4
XK_Terminate_Server = 0xFED5

XK_AccessX_Enable = 0xFE70
XK_AccessX_Feedback_Enable = 0xFE71
XK_RepeatKeys_Enable = 0xFE72
XK_SlowKeys_Enable = 0xFE73
XK_BounceKeys_Enable = 0xFE74
XK_StickyKeys_Enable = 0xFE75
XK_MouseKeys_Enable = 0xFE76
XK_MouseKeys_Accel_Enable = 0xFE77
XK_Overlay1_Enable = 0xFE78
XK_Overlay2_Enable = 0xFE79
XK_AudibleBell_Enable = 0xFE7A

XK_Pointer_Left = 0xFEE0
XK_Pointer_Right = 0xFEE1
XK_Pointer_Up = 0xFEE2
XK_Pointer_Down = 0xFEE3
XK_Pointer_UpLeft = 0xFEE4
XK_Pointer_UpRight = 0xFEE5
XK_Pointer_DownLeft = 0xFEE6
XK_Pointer_DownRight = 0xFEE7
XK_Pointer_Button_Dflt = 0xFEE8
XK_Pointer_Button1 = 0xFEE9
XK_Pointer_Button2 = 0xFEEA
XK_Pointer_Button3 = 0xFEEB
XK_Pointer_Button4 = 0xFEEC
XK_Pointer_Button5 = 0xFEED
XK_Pointer_DblClick_Dflt = 0xFEEE
XK_Pointer_DblClick1 = 0xFEEF
XK_Pointer_DblClick2 = 0xFEF0
XK_Pointer_DblClick3 = 0xFEF1
XK_Pointer_DblClick4 = 0xFEF2
XK_Pointer_DblClick5 = 0xFEF3
XK_Pointer_Drag_Dflt = 0xFEF4
XK_Pointer_Drag1 = 0xFEF5
XK_Pointer_Drag2 = 0xFEF6
XK_Pointer_Drag3 = 0xFEF7
XK_Pointer_Drag4 = 0xFEF8
XK_Pointer_Drag5 = 0xFEFD

XK_Pointer_EnableKeys = 0xFEF9
XK_Pointer_Accelerate = 0xFEFA
XK_Pointer_DfltBtnNext = 0xFEFB
XK_Pointer_DfltBtnPrev = 0xFEFC

--[[
 * 3270 Terminal Keys
 * Byte 3 = 0xFD
 ]]--

XK_3270_Duplicate = 0xFD01
XK_3270_FieldMark = 0xFD02
XK_3270_Right2 = 0xFD03
XK_3270_Left2 = 0xFD04
XK_3270_BackTab = 0xFD05
XK_3270_EraseEOF = 0xFD06
XK_3270_EraseInput = 0xFD07
XK_3270_Reset = 0xFD08
XK_3270_Quit = 0xFD09
XK_3270_PA1 = 0xFD0A
XK_3270_PA2 = 0xFD0B
XK_3270_PA3 = 0xFD0C
XK_3270_Test = 0xFD0D
XK_3270_Attn = 0xFD0E
XK_3270_CursorBlink = 0xFD0F
XK_3270_AltCursor = 0xFD10
XK_3270_KeyClick = 0xFD11
XK_3270_Jump = 0xFD12
XK_3270_Ident = 0xFD13
XK_3270_Rule = 0xFD14
XK_3270_Copy = 0xFD15
XK_3270_Play = 0xFD16
XK_3270_Setup = 0xFD17
XK_3270_Record = 0xFD18
XK_3270_ChangeScreen = 0xFD19
XK_3270_DeleteWord = 0xFD1A
XK_3270_ExSelect = 0xFD1B
XK_3270_CursorSelect = 0xFD1C
XK_3270_PrintScreen = 0xFD1D
XK_3270_Enter = 0xFD1E

--[[
 *  Latin 1
 *  Byte 3 = 0
 ]]--
XK_space = 0x020
XK_exclam = 0x021
XK_quotedbl = 0x022
XK_numbersign = 0x023
XK_dollar = 0x024
XK_percent = 0x025
XK_ampersand = 0x026
XK_apostrophe = 0x027
XK_quoteright = 0x027	--[[ deprecated ]]--
XK_parenleft = 0x028
XK_parenright = 0x029
XK_asterisk = 0x02a
XK_plus = 0x02b
XK_comma = 0x02c
XK_minus = 0x02d
XK_period = 0x02e
XK_slash = 0x02f
XK_0 = 0x030
XK_1 = 0x031
XK_2 = 0x032
XK_3 = 0x033
XK_4 = 0x034
XK_5 = 0x035
XK_6 = 0x036
XK_7 = 0x037
XK_8 = 0x038
XK_9 = 0x039
XK_colon = 0x03a
XK_semicolon = 0x03b
XK_less = 0x03c
XK_equal = 0x03d
XK_greater = 0x03e
XK_question = 0x03f
XK_at = 0x040
XK_A = 0x041
XK_B = 0x042
XK_C = 0x043
XK_D = 0x044
XK_E = 0x045
XK_F = 0x046
XK_G = 0x047
XK_H = 0x048
XK_I = 0x049
XK_J = 0x04a
XK_K = 0x04b
XK_L = 0x04c
XK_M = 0x04d
XK_N = 0x04e
XK_O = 0x04f
XK_P = 0x050
XK_Q = 0x051
XK_R = 0x052
XK_S = 0x053
XK_T = 0x054
XK_U = 0x055
XK_V = 0x056
XK_W = 0x057
XK_X = 0x058
XK_Y = 0x059
XK_Z = 0x05a
XK_bracketleft = 0x05b
XK_backslash = 0x05c
XK_bracketright = 0x05d
XK_asciicircum = 0x05e
XK_underscore = 0x05f
XK_grave = 0x060
XK_quoteleft = 0x060	--[[ deprecated ]]--
XK_a = 0x061
XK_b = 0x062
XK_c = 0x063
XK_d = 0x064
XK_e = 0x065
XK_f = 0x066
XK_g = 0x067
XK_h = 0x068
XK_i = 0x069
XK_j = 0x06a
XK_k = 0x06b
XK_l = 0x06c
XK_m = 0x06d
XK_n = 0x06e
XK_o = 0x06f
XK_p = 0x070
XK_q = 0x071
XK_r = 0x072
XK_s = 0x073
XK_t = 0x074
XK_u = 0x075
XK_v = 0x076
XK_w = 0x077
XK_x = 0x078
XK_y = 0x079
XK_z = 0x07a
XK_braceleft = 0x07b
XK_bar = 0x07c
XK_braceright = 0x07d
XK_asciitilde = 0x07e

XK_nobreakspace = 0x0a0
XK_exclamdown = 0x0a1
XK_cent = 0x0a2
XK_sterling = 0x0a3
XK_currency = 0x0a4
XK_yen = 0x0a5
XK_brokenbar = 0x0a6
XK_section = 0x0a7
XK_diaeresis = 0x0a8
XK_copyright = 0x0a9
XK_ordfeminine = 0x0aa
XK_guillemotleft = 0x0ab	--[[ left angle quotation mark ]]--
XK_notsign = 0x0ac
XK_hyphen = 0x0ad
XK_registered = 0x0ae
XK_macron = 0x0af
XK_degree = 0x0b0
XK_plusminus = 0x0b1
XK_twosuperior = 0x0b2
XK_threesuperior = 0x0b3
XK_acute = 0x0b4
XK_mu = 0x0b5
XK_paragraph = 0x0b6
XK_periodcentered = 0x0b7
XK_cedilla = 0x0b8
XK_onesuperior = 0x0b9
XK_masculine = 0x0ba
XK_guillemotright = 0x0bb	--[[ right angle quotation mark ]]--
XK_onequarter = 0x0bc
XK_onehalf = 0x0bd
XK_threequarters = 0x0be
XK_questiondown = 0x0bf
XK_Agrave = 0x0c0
XK_Aacute = 0x0c1
XK_Acircumflex = 0x0c2
XK_Atilde = 0x0c3
XK_Adiaeresis = 0x0c4
XK_Aring = 0x0c5
XK_AE = 0x0c6
XK_Ccedilla = 0x0c7
XK_Egrave = 0x0c8
XK_Eacute = 0x0c9
XK_Ecircumflex = 0x0ca
XK_Ediaeresis = 0x0cb
XK_Igrave = 0x0cc
XK_Iacute = 0x0cd
XK_Icircumflex = 0x0ce
XK_Idiaeresis = 0x0cf
XK_ETH = 0x0d0
XK_Eth = 0x0d0	--[[ deprecated ]]--
XK_Ntilde = 0x0d1
XK_Ograve = 0x0d2
XK_Oacute = 0x0d3
XK_Ocircumflex = 0x0d4
XK_Otilde = 0x0d5
XK_Odiaeresis = 0x0d6
XK_multiply = 0x0d7
XK_Ooblique = 0x0d8
XK_Ugrave = 0x0d9
XK_Uacute = 0x0da
XK_Ucircumflex = 0x0db
XK_Udiaeresis = 0x0dc
XK_Yacute = 0x0dd
XK_THORN = 0x0de
XK_Thorn = 0x0de	--[[ deprecated ]]--
XK_ssharp = 0x0df
XK_agrave = 0x0e0
XK_aacute = 0x0e1
XK_acircumflex = 0x0e2
XK_atilde = 0x0e3
XK_adiaeresis = 0x0e4
XK_aring = 0x0e5
XK_ae = 0x0e6
XK_ccedilla = 0x0e7
XK_egrave = 0x0e8
XK_eacute = 0x0e9
XK_ecircumflex = 0x0ea
XK_ediaeresis = 0x0eb
XK_igrave = 0x0ec
XK_iacute = 0x0ed
XK_icircumflex = 0x0ee
XK_idiaeresis = 0x0ef
XK_eth = 0x0f0
XK_ntilde = 0x0f1
XK_ograve = 0x0f2
XK_oacute = 0x0f3
XK_ocircumflex = 0x0f4
XK_otilde = 0x0f5
XK_odiaeresis = 0x0f6
XK_division = 0x0f7
XK_oslash = 0x0f8
XK_ugrave = 0x0f9
XK_uacute = 0x0fa
XK_ucircumflex = 0x0fb
XK_udiaeresis = 0x0fc
XK_yacute = 0x0fd
XK_thorn = 0x0fe
XK_ydiaeresis = 0x0ff

--[[
 *   Latin 2
 *   Byte 3 = 1
 ]]--

XK_Aogonek = 0x1a1
XK_breve = 0x1a2
XK_Lstroke = 0x1a3
XK_Lcaron = 0x1a5
XK_Sacute = 0x1a6
XK_Scaron = 0x1a9
XK_Scedilla = 0x1aa
XK_Tcaron = 0x1ab
XK_Zacute = 0x1ac
XK_Zcaron = 0x1ae
XK_Zabovedot = 0x1af
XK_aogonek = 0x1b1
XK_ogonek = 0x1b2
XK_lstroke = 0x1b3
XK_lcaron = 0x1b5
XK_sacute = 0x1b6
XK_caron = 0x1b7
XK_scaron = 0x1b9
XK_scedilla = 0x1ba
XK_tcaron = 0x1bb
XK_zacute = 0x1bc
XK_doubleacute = 0x1bd
XK_zcaron = 0x1be
XK_zabovedot = 0x1bf
XK_Racute = 0x1c0
XK_Abreve = 0x1c3
XK_Lacute = 0x1c5
XK_Cacute = 0x1c6
XK_Ccaron = 0x1c8
XK_Eogonek = 0x1ca
XK_Ecaron = 0x1cc
XK_Dcaron = 0x1cf
XK_Dstroke = 0x1d0
XK_Nacute = 0x1d1
XK_Ncaron = 0x1d2
XK_Odoubleacute = 0x1d5
XK_Rcaron = 0x1d8
XK_Uring = 0x1d9
XK_Udoubleacute = 0x1db
XK_Tcedilla = 0x1de
XK_racute = 0x1e0
XK_abreve = 0x1e3
XK_lacute = 0x1e5
XK_cacute = 0x1e6
XK_ccaron = 0x1e8
XK_eogonek = 0x1ea
XK_ecaron = 0x1ec
XK_dcaron = 0x1ef
XK_dstroke = 0x1f0
XK_nacute = 0x1f1
XK_ncaron = 0x1f2
XK_odoubleacute = 0x1f5
XK_udoubleacute = 0x1fb
XK_rcaron = 0x1f8
XK_uring = 0x1f9
XK_tcedilla = 0x1fe
XK_abovedot = 0x1ff

--[[
 *   Latin 3
 *   Byte 3 = 2
 ]]--

XK_Hstroke = 0x2a1
XK_Hcircumflex = 0x2a6
XK_Iabovedot = 0x2a9
XK_Gbreve = 0x2ab
XK_Jcircumflex = 0x2ac
XK_hstroke = 0x2b1
XK_hcircumflex = 0x2b6
XK_idotless = 0x2b9
XK_gbreve = 0x2bb
XK_jcircumflex = 0x2bc
XK_Cabovedot = 0x2c5
XK_Ccircumflex = 0x2c6
XK_Gabovedot = 0x2d5
XK_Gcircumflex = 0x2d8
XK_Ubreve = 0x2dd
XK_Scircumflex = 0x2de
XK_cabovedot = 0x2e5
XK_ccircumflex = 0x2e6
XK_gabovedot = 0x2f5
XK_gcircumflex = 0x2f8
XK_ubreve = 0x2fd
XK_scircumflex = 0x2fe


--[[
 *   Latin 4
 *   Byte 3 = 3
 ]]--

XK_kra = 0x3a2
XK_kappa = 0x3a2	--[[ deprecated ]]--
XK_Rcedilla = 0x3a3
XK_Itilde = 0x3a5
XK_Lcedilla = 0x3a6
XK_Emacron = 0x3aa
XK_Gcedilla = 0x3ab
XK_Tslash = 0x3ac
XK_rcedilla = 0x3b3
XK_itilde = 0x3b5
XK_lcedilla = 0x3b6
XK_emacron = 0x3ba
XK_gcedilla = 0x3bb
XK_tslash = 0x3bc
XK_ENG = 0x3bd
XK_eng = 0x3bf
XK_Amacron = 0x3c0
XK_Iogonek = 0x3c7
XK_Eabovedot = 0x3cc
XK_Imacron = 0x3cf
XK_Ncedilla = 0x3d1
XK_Omacron = 0x3d2
XK_Kcedilla = 0x3d3
XK_Uogonek = 0x3d9
XK_Utilde = 0x3dd
XK_Umacron = 0x3de
XK_amacron = 0x3e0
XK_iogonek = 0x3e7
XK_eabovedot = 0x3ec
XK_imacron = 0x3ef
XK_ncedilla = 0x3f1
XK_omacron = 0x3f2
XK_kcedilla = 0x3f3
XK_uogonek = 0x3f9
XK_utilde = 0x3fd
XK_umacron = 0x3fe

--[[
 * Katakana
 * Byte 3 = 4
 ]]--

XK_overline = 0x47e
XK_kana_fullstop = 0x4a1
XK_kana_openingbracket = 0x4a2
XK_kana_closingbracket = 0x4a3
XK_kana_comma = 0x4a4
XK_kana_conjunctive = 0x4a5
XK_kana_middledot = 0x4a5  --[[ deprecated ]]--
XK_kana_WO = 0x4a6
XK_kana_a = 0x4a7
XK_kana_i = 0x4a8
XK_kana_u = 0x4a9
XK_kana_e = 0x4aa
XK_kana_o = 0x4ab
XK_kana_ya = 0x4ac
XK_kana_yu = 0x4ad
XK_kana_yo = 0x4ae
XK_kana_tsu = 0x4af
XK_kana_tu = 0x4af  --[[ deprecated ]]--
XK_prolongedsound = 0x4b0
XK_kana_A = 0x4b1
XK_kana_I = 0x4b2
XK_kana_U = 0x4b3
XK_kana_E = 0x4b4
XK_kana_O = 0x4b5
XK_kana_KA = 0x4b6
XK_kana_KI = 0x4b7
XK_kana_KU = 0x4b8
XK_kana_KE = 0x4b9
XK_kana_KO = 0x4ba
XK_kana_SA = 0x4bb
XK_kana_SHI = 0x4bc
XK_kana_SU = 0x4bd
XK_kana_SE = 0x4be
XK_kana_SO = 0x4bf
XK_kana_TA = 0x4c0
XK_kana_CHI = 0x4c1
XK_kana_TI = 0x4c1  --[[ deprecated ]]--
XK_kana_TSU = 0x4c2
XK_kana_TU = 0x4c2  --[[ deprecated ]]--
XK_kana_TE = 0x4c3
XK_kana_TO = 0x4c4
XK_kana_NA = 0x4c5
XK_kana_NI = 0x4c6
XK_kana_NU = 0x4c7
XK_kana_NE = 0x4c8
XK_kana_NO = 0x4c9
XK_kana_HA = 0x4ca
XK_kana_HI = 0x4cb
XK_kana_FU = 0x4cc
XK_kana_HU = 0x4cc  --[[ deprecated ]]--
XK_kana_HE = 0x4cd
XK_kana_HO = 0x4ce
XK_kana_MA = 0x4cf
XK_kana_MI = 0x4d0
XK_kana_MU = 0x4d1
XK_kana_ME = 0x4d2
XK_kana_MO = 0x4d3
XK_kana_YA = 0x4d4
XK_kana_YU = 0x4d5
XK_kana_YO = 0x4d6
XK_kana_RA = 0x4d7
XK_kana_RI = 0x4d8
XK_kana_RU = 0x4d9
XK_kana_RE = 0x4da
XK_kana_RO = 0x4db
XK_kana_WA = 0x4dc
XK_kana_N = 0x4dd
XK_voicedsound = 0x4de
XK_semivoicedsound = 0x4df
XK_kana_switch = 0xFF7E  --[[ Alias for mode_switch ]]--

--[[
 *  Arabic
 *  Byte 3 = 5
 ]]--

XK_Arabic_comma = 0x5ac
XK_Arabic_semicolon = 0x5bb
XK_Arabic_question_mark = 0x5bf
XK_Arabic_hamza = 0x5c1
XK_Arabic_maddaonalef = 0x5c2
XK_Arabic_hamzaonalef = 0x5c3
XK_Arabic_hamzaonwaw = 0x5c4
XK_Arabic_hamzaunderalef = 0x5c5
XK_Arabic_hamzaonyeh = 0x5c6
XK_Arabic_alef = 0x5c7
XK_Arabic_beh = 0x5c8
XK_Arabic_tehmarbuta = 0x5c9
XK_Arabic_teh = 0x5ca
XK_Arabic_theh = 0x5cb
XK_Arabic_jeem = 0x5cc
XK_Arabic_hah = 0x5cd
XK_Arabic_khah = 0x5ce
XK_Arabic_dal = 0x5cf
XK_Arabic_thal = 0x5d0
XK_Arabic_ra = 0x5d1
XK_Arabic_zain = 0x5d2
XK_Arabic_seen = 0x5d3
XK_Arabic_sheen = 0x5d4
XK_Arabic_sad = 0x5d5
XK_Arabic_dad = 0x5d6
XK_Arabic_tah = 0x5d7
XK_Arabic_zah = 0x5d8
XK_Arabic_ain = 0x5d9
XK_Arabic_ghain = 0x5da
XK_Arabic_tatweel = 0x5e0
XK_Arabic_feh = 0x5e1
XK_Arabic_qaf = 0x5e2
XK_Arabic_kaf = 0x5e3
XK_Arabic_lam = 0x5e4
XK_Arabic_meem = 0x5e5
XK_Arabic_noon = 0x5e6
XK_Arabic_ha = 0x5e7
XK_Arabic_heh = 0x5e7  --[[ deprecated ]]--
XK_Arabic_waw = 0x5e8
XK_Arabic_alefmaksura = 0x5e9
XK_Arabic_yeh = 0x5ea
XK_Arabic_fathatan = 0x5eb
XK_Arabic_dammatan = 0x5ec
XK_Arabic_kasratan = 0x5ed
XK_Arabic_fatha = 0x5ee
XK_Arabic_damma = 0x5ef
XK_Arabic_kasra = 0x5f0
XK_Arabic_shadda = 0x5f1
XK_Arabic_sukun = 0x5f2
XK_Arabic_switch = 0xFF7E  --[[ Alias for mode_switch ]]--

--[[
 * Cyrillic
 * Byte 3 = 6
 ]]--
XK_Serbian_dje = 0x6a1
XK_Macedonia_gje = 0x6a2
XK_Cyrillic_io = 0x6a3
XK_Ukrainian_ie = 0x6a4
XK_Ukranian_je = 0x6a4  --[[ deprecated ]]--
XK_Macedonia_dse = 0x6a5
XK_Ukrainian_i = 0x6a6
XK_Ukranian_i = 0x6a6  --[[ deprecated ]]--
XK_Ukrainian_yi = 0x6a7
XK_Ukranian_yi = 0x6a7  --[[ deprecated ]]--
XK_Cyrillic_je = 0x6a8
XK_Serbian_je = 0x6a8  --[[ deprecated ]]--
XK_Cyrillic_lje = 0x6a9
XK_Serbian_lje = 0x6a9  --[[ deprecated ]]--
XK_Cyrillic_nje = 0x6aa
XK_Serbian_nje = 0x6aa  --[[ deprecated ]]--
XK_Serbian_tshe = 0x6ab
XK_Macedonia_kje = 0x6ac
XK_Byelorussian_shortu = 0x6ae
XK_Cyrillic_dzhe = 0x6af
XK_Serbian_dze = 0x6af  --[[ deprecated ]]--
XK_numerosign = 0x6b0
XK_Serbian_DJE = 0x6b1
XK_Macedonia_GJE = 0x6b2
XK_Cyrillic_IO = 0x6b3
XK_Ukrainian_IE = 0x6b4
XK_Ukranian_JE = 0x6b4  --[[ deprecated ]]--
XK_Macedonia_DSE = 0x6b5
XK_Ukrainian_I = 0x6b6
XK_Ukranian_I = 0x6b6  --[[ deprecated ]]--
XK_Ukrainian_YI = 0x6b7
XK_Ukranian_YI = 0x6b7  --[[ deprecated ]]--
XK_Cyrillic_JE = 0x6b8
XK_Serbian_JE = 0x6b8  --[[ deprecated ]]--
XK_Cyrillic_LJE = 0x6b9
XK_Serbian_LJE = 0x6b9  --[[ deprecated ]]--
XK_Cyrillic_NJE = 0x6ba
XK_Serbian_NJE = 0x6ba  --[[ deprecated ]]--
XK_Serbian_TSHE = 0x6bb
XK_Macedonia_KJE = 0x6bc
XK_Byelorussian_SHORTU = 0x6be
XK_Cyrillic_DZHE = 0x6bf
XK_Serbian_DZE = 0x6bf  --[[ deprecated ]]--
XK_Cyrillic_yu = 0x6c0
XK_Cyrillic_a = 0x6c1
XK_Cyrillic_be = 0x6c2
XK_Cyrillic_tse = 0x6c3
XK_Cyrillic_de = 0x6c4
XK_Cyrillic_ie = 0x6c5
XK_Cyrillic_ef = 0x6c6
XK_Cyrillic_ghe = 0x6c7
XK_Cyrillic_ha = 0x6c8
XK_Cyrillic_i = 0x6c9
XK_Cyrillic_shorti = 0x6ca
XK_Cyrillic_ka = 0x6cb
XK_Cyrillic_el = 0x6cc
XK_Cyrillic_em = 0x6cd
XK_Cyrillic_en = 0x6ce
XK_Cyrillic_o = 0x6cf
XK_Cyrillic_pe = 0x6d0
XK_Cyrillic_ya = 0x6d1
XK_Cyrillic_er = 0x6d2
XK_Cyrillic_es = 0x6d3
XK_Cyrillic_te = 0x6d4
XK_Cyrillic_u = 0x6d5
XK_Cyrillic_zhe = 0x6d6
XK_Cyrillic_ve = 0x6d7
XK_Cyrillic_softsign = 0x6d8
XK_Cyrillic_yeru = 0x6d9
XK_Cyrillic_ze = 0x6da
XK_Cyrillic_sha = 0x6db
XK_Cyrillic_e = 0x6dc
XK_Cyrillic_shcha = 0x6dd
XK_Cyrillic_che = 0x6de
XK_Cyrillic_hardsign = 0x6df
XK_Cyrillic_YU = 0x6e0
XK_Cyrillic_A = 0x6e1
XK_Cyrillic_BE = 0x6e2
XK_Cyrillic_TSE = 0x6e3
XK_Cyrillic_DE = 0x6e4
XK_Cyrillic_IE = 0x6e5
XK_Cyrillic_EF = 0x6e6
XK_Cyrillic_GHE = 0x6e7
XK_Cyrillic_HA = 0x6e8
XK_Cyrillic_I = 0x6e9
XK_Cyrillic_SHORTI = 0x6ea
XK_Cyrillic_KA = 0x6eb
XK_Cyrillic_EL = 0x6ec
XK_Cyrillic_EM = 0x6ed
XK_Cyrillic_EN = 0x6ee
XK_Cyrillic_O = 0x6ef
XK_Cyrillic_PE = 0x6f0
XK_Cyrillic_YA = 0x6f1
XK_Cyrillic_ER = 0x6f2
XK_Cyrillic_ES = 0x6f3
XK_Cyrillic_TE = 0x6f4
XK_Cyrillic_U = 0x6f5
XK_Cyrillic_ZHE = 0x6f6
XK_Cyrillic_VE = 0x6f7
XK_Cyrillic_SOFTSIGN = 0x6f8
XK_Cyrillic_YERU = 0x6f9
XK_Cyrillic_ZE = 0x6fa
XK_Cyrillic_SHA = 0x6fb
XK_Cyrillic_E = 0x6fc
XK_Cyrillic_SHCHA = 0x6fd
XK_Cyrillic_CHE = 0x6fe
XK_Cyrillic_HARDSIGN = 0x6ff

--[[
 * Greek
 * Byte 3 = 7
 ]]--

XK_Greek_ALPHAaccent = 0x7a1
XK_Greek_EPSILONaccent = 0x7a2
XK_Greek_ETAaccent = 0x7a3
XK_Greek_IOTAaccent = 0x7a4
XK_Greek_IOTAdieresis = 0x7a5
XK_Greek_OMICRONaccent = 0x7a7
XK_Greek_UPSILONaccent = 0x7a8
XK_Greek_UPSILONdieresis = 0x7a9
XK_Greek_OMEGAaccent = 0x7ab
XK_Greek_accentdieresis = 0x7ae
XK_Greek_horizbar = 0x7af
XK_Greek_alphaaccent = 0x7b1
XK_Greek_epsilonaccent = 0x7b2
XK_Greek_etaaccent = 0x7b3
XK_Greek_iotaaccent = 0x7b4
XK_Greek_iotadieresis = 0x7b5
XK_Greek_iotaaccentdieresis = 0x7b6
XK_Greek_omicronaccent = 0x7b7
XK_Greek_upsilonaccent = 0x7b8
XK_Greek_upsilondieresis = 0x7b9
XK_Greek_upsilonaccentdieresis = 0x7ba
XK_Greek_omegaaccent = 0x7bb
XK_Greek_ALPHA = 0x7c1
XK_Greek_BETA = 0x7c2
XK_Greek_GAMMA = 0x7c3
XK_Greek_DELTA = 0x7c4
XK_Greek_EPSILON = 0x7c5
XK_Greek_ZETA = 0x7c6
XK_Greek_ETA = 0x7c7
XK_Greek_THETA = 0x7c8
XK_Greek_IOTA = 0x7c9
XK_Greek_KAPPA = 0x7ca
XK_Greek_LAMDA = 0x7cb
XK_Greek_LAMBDA = 0x7cb
XK_Greek_MU = 0x7cc
XK_Greek_NU = 0x7cd
XK_Greek_XI = 0x7ce
XK_Greek_OMICRON = 0x7cf
XK_Greek_PI = 0x7d0
XK_Greek_RHO = 0x7d1
XK_Greek_SIGMA = 0x7d2
XK_Greek_TAU = 0x7d4
XK_Greek_UPSILON = 0x7d5
XK_Greek_PHI = 0x7d6
XK_Greek_CHI = 0x7d7
XK_Greek_PSI = 0x7d8
XK_Greek_OMEGA = 0x7d9
XK_Greek_alpha = 0x7e1
XK_Greek_beta = 0x7e2
XK_Greek_gamma = 0x7e3
XK_Greek_delta = 0x7e4
XK_Greek_epsilon = 0x7e5
XK_Greek_zeta = 0x7e6
XK_Greek_eta = 0x7e7
XK_Greek_theta = 0x7e8
XK_Greek_iota = 0x7e9
XK_Greek_kappa = 0x7ea
XK_Greek_lamda = 0x7eb
XK_Greek_lambda = 0x7eb
XK_Greek_mu = 0x7ec
XK_Greek_nu = 0x7ed
XK_Greek_xi = 0x7ee
XK_Greek_omicron = 0x7ef
XK_Greek_pi = 0x7f0
XK_Greek_rho = 0x7f1
XK_Greek_sigma = 0x7f2
XK_Greek_finalsmallsigma = 0x7f3
XK_Greek_tau = 0x7f4
XK_Greek_upsilon = 0x7f5
XK_Greek_phi = 0x7f6
XK_Greek_chi = 0x7f7
XK_Greek_psi = 0x7f8
XK_Greek_omega = 0x7f9
XK_Greek_switch = 0xFF7E  --[[ Alias for mode_switch ]]--

--[[
 * Technical
 * Byte 3 = 8
 ]]--

XK_leftradical = 0x8a1
XK_topleftradical = 0x8a2
XK_horizconnector = 0x8a3
XK_topintegral = 0x8a4
XK_botintegral = 0x8a5
XK_vertconnector = 0x8a6
XK_topleftsqbracket = 0x8a7
XK_botleftsqbracket = 0x8a8
XK_toprightsqbracket = 0x8a9
XK_botrightsqbracket = 0x8aa
XK_topleftparens = 0x8ab
XK_botleftparens = 0x8ac
XK_toprightparens = 0x8ad
XK_botrightparens = 0x8ae
XK_leftmiddlecurlybrace = 0x8af
XK_rightmiddlecurlybrace = 0x8b0
XK_topleftsummation = 0x8b1
XK_botleftsummation = 0x8b2
XK_topvertsummationconnector = 0x8b3
XK_botvertsummationconnector = 0x8b4
XK_toprightsummation = 0x8b5
XK_botrightsummation = 0x8b6
XK_rightmiddlesummation = 0x8b7
XK_lessthanequal = 0x8bc
XK_notequal = 0x8bd
XK_greaterthanequal = 0x8be
XK_integral = 0x8bf
XK_therefore = 0x8c0
XK_variation = 0x8c1
XK_infinity = 0x8c2
XK_nabla = 0x8c5
XK_approximate = 0x8c8
XK_similarequal = 0x8c9
XK_ifonlyif = 0x8cd
XK_implies = 0x8ce
XK_identical = 0x8cf
XK_radical = 0x8d6
XK_includedin = 0x8da
XK_includes = 0x8db
XK_intersection = 0x8dc
XK_union = 0x8dd
XK_logicaland = 0x8de
XK_logicalor = 0x8df
XK_partialderivative = 0x8ef
XK_function = 0x8f6
XK_leftarrow = 0x8fb
XK_uparrow = 0x8fc
XK_rightarrow = 0x8fd
XK_downarrow = 0x8fe

--[[
 *  Special
 *  Byte 3 = 9
 ]]--

XK_blank = 0x9df
XK_soliddiamond = 0x9e0
XK_checkerboard = 0x9e1
XK_ht = 0x9e2
XK_ff = 0x9e3
XK_cr = 0x9e4
XK_lf = 0x9e5
XK_nl = 0x9e8
XK_vt = 0x9e9
XK_lowrightcorner = 0x9ea
XK_uprightcorner = 0x9eb
XK_upleftcorner = 0x9ec
XK_lowleftcorner = 0x9ed
XK_crossinglines = 0x9ee
XK_horizlinescan1 = 0x9ef
XK_horizlinescan3 = 0x9f0
XK_horizlinescan5 = 0x9f1
XK_horizlinescan7 = 0x9f2
XK_horizlinescan9 = 0x9f3
XK_leftt = 0x9f4
XK_rightt = 0x9f5
XK_bott = 0x9f6
XK_topt = 0x9f7
XK_vertbar = 0x9f8

--[[
 *  Publishing
 *  Byte 3 = a
 ]]--

XK_emspace = 0xaa1
XK_enspace = 0xaa2
XK_em3space = 0xaa3
XK_em4space = 0xaa4
XK_digitspace = 0xaa5
XK_punctspace = 0xaa6
XK_thinspace = 0xaa7
XK_hairspace = 0xaa8
XK_emdash = 0xaa9
XK_endash = 0xaaa
XK_signifblank = 0xaac
XK_ellipsis = 0xaae
XK_doubbaselinedot = 0xaaf
XK_onethird = 0xab0
XK_twothirds = 0xab1
XK_onefifth = 0xab2
XK_twofifths = 0xab3
XK_threefifths = 0xab4
XK_fourfifths = 0xab5
XK_onesixth = 0xab6
XK_fivesixths = 0xab7
XK_careof = 0xab8
XK_figdash = 0xabb
XK_leftanglebracket = 0xabc
XK_decimalpoint = 0xabd
XK_rightanglebracket = 0xabe
XK_marker = 0xabf
XK_oneeighth = 0xac3
XK_threeeighths = 0xac4
XK_fiveeighths = 0xac5
XK_seveneighths = 0xac6
XK_trademark = 0xac9
XK_signaturemark = 0xaca
XK_trademarkincircle = 0xacb
XK_leftopentriangle = 0xacc
XK_rightopentriangle = 0xacd
XK_emopencircle = 0xace
XK_emopenrectangle = 0xacf
XK_leftsinglequotemark = 0xad0
XK_rightsinglequotemark = 0xad1
XK_leftdoublequotemark = 0xad2
XK_rightdoublequotemark = 0xad3
XK_prescription = 0xad4
XK_minutes = 0xad6
XK_seconds = 0xad7
XK_latincross = 0xad9
XK_hexagram = 0xada
XK_filledrectbullet = 0xadb
XK_filledlefttribullet = 0xadc
XK_filledrighttribullet = 0xadd
XK_emfilledcircle = 0xade
XK_emfilledr
Download .txt
gitextract_35m4v9ie/

├── .gitignore
├── .gitmodules
├── COPYING
├── Makefile
├── README.md
├── Xvnc-start.sh
├── config.lua
├── ffi/
│   ├── SDL.lua
│   ├── SDL1_2_h.lua
│   ├── blitbuffer.lua
│   ├── einkfb_h.lua
│   ├── eventloop.lua
│   ├── framebuffer.lua
│   ├── framebuffer_SDL.lua
│   ├── framebuffer_linux.lua
│   ├── input.lua
│   ├── input_SDL.lua
│   ├── input_kindle.lua
│   ├── linux_fb_h.lua
│   ├── linux_input_h.lua
│   ├── mxcfb_kindle_h.lua
│   ├── mxcfb_kobo_h.lua
│   ├── posix_h.lua
│   ├── rfbclient.lua
│   ├── rfbclient_h.lua
│   └── util.lua
├── ffi-cdecl/
│   ├── SDL1_2_decl.c
│   ├── einkfb_decl.c
│   ├── include/
│   │   ├── README
│   │   ├── einkfb.h
│   │   ├── mxcfb-kindle.h
│   │   ├── mxcfb-kobo.h
│   │   └── mxcfb.h
│   ├── linux_fb_decl.c
│   ├── linux_input_decl.c
│   ├── mxcfb_kindle_decl.c
│   ├── mxcfb_kobo_decl.c
│   ├── posix_decl.c
│   └── rfbclient_decl.c
├── keys.lua
├── kvncviewer.ini
├── kvncviewer.sh
├── rfbkeys.lua
└── vncviewer.lua
Download .txt
SYMBOL INDEX (76 symbols across 7 files)

FILE: ffi-cdecl/einkfb_decl.c
  type u_int (line 6) | typedef unsigned int u_int;
  type u_long (line 7) | typedef unsigned long u_long;

FILE: ffi-cdecl/include/einkfb.h
  type raw_image_t (line 33) | struct raw_image_t
  type raw_image_t (line 41) | typedef struct raw_image_t raw_image_t;
  type image_t (line 43) | struct image_t
  type image_t (line 52) | typedef struct image_t image_t;
  type splash_screen_type (line 56) | enum splash_screen_type
  type splash_screen_type (line 103) | typedef enum splash_screen_type splash_screen_type;
  type power_override_t (line 109) | struct power_override_t
  type power_override_t (line 114) | typedef struct power_override_t power_override_t;
  type fx_type (line 116) | enum fx_type
  type fx_type (line 133) | typedef enum fx_type fx_type;
  type rect_t (line 166) | struct rect_t
  type rect_t (line 174) | typedef struct rect_t rect_t;
  type fx_t (line 179) | struct fx_t
  type fx_t (line 187) | typedef struct fx_t fx_t;
  type update_area_t (line 200) | struct update_area_t
  type update_area_t (line 213) | typedef struct update_area_t update_area_t;
  type progressbar_xy_t (line 217) | struct progressbar_xy_t
  type progressbar_xy_t (line 221) | typedef struct progressbar_xy_t progressbar_xy_t;
  type screen_saver_t (line 223) | enum screen_saver_t
  type screen_saver_t (line 228) | typedef enum screen_saver_t screen_saver_t;
  type orientation_t (line 230) | enum orientation_t
  type orientation_t (line 237) | typedef enum orientation_t orientation_t;
  type einkfb_events_t (line 251) | enum einkfb_events_t
  type einkfb_events_t (line 261) | typedef enum einkfb_events_t einkfb_events_t;
  type einkfb_event_t (line 263) | struct einkfb_event_t
  type einkfb_event_t (line 278) | typedef struct einkfb_event_t einkfb_event_t;
  type reboot_behavior_t (line 280) | enum reboot_behavior_t
  type reboot_behavior_t (line 286) | typedef enum reboot_behavior_t reboot_behavior_t;
  type progressbar_badge_t (line 288) | enum progressbar_badge_t
  type progressbar_badge_t (line 295) | typedef enum progressbar_badge_t progressbar_badge_t;
  type sleep_behavior_t (line 297) | enum sleep_behavior_t
  type sleep_behavior_t (line 302) | typedef enum sleep_behavior_t sleep_behavior_t;

FILE: ffi-cdecl/include/mxcfb-kindle.h
  type mxcfb_gbl_alpha (line 41) | struct mxcfb_gbl_alpha {
  type mxcfb_loc_alpha (line 46) | struct mxcfb_loc_alpha {
  type mxcfb_color_key (line 53) | struct mxcfb_color_key {
  type mxcfb_pos (line 58) | struct mxcfb_pos {
  type mxcfb_gamma (line 63) | struct mxcfb_gamma {
  type mxcfb_rect (line 69) | struct mxcfb_rect {
  type mxcfb_alt_buffer_data (line 109) | struct mxcfb_alt_buffer_data {
  type mxcfb_update_data (line 116) | struct mxcfb_update_data {
  type mxcfb_update_data (line 128) | typedef struct mxcfb_update_data mxcfb_update_data;
  type mxcfb_update_data_50x (line 132) | struct mxcfb_update_data_50x {
  type mxcfb_waveform_modes (line 146) | struct mxcfb_waveform_modes {
  type fb_videomode (line 189) | struct fb_videomode
  type fb_info (line 198) | struct fb_info
  type mxcfb_rect (line 199) | struct mxcfb_rect

FILE: ffi-cdecl/include/mxcfb-kobo.h
  type mxcfb_gbl_alpha (line 35) | struct mxcfb_gbl_alpha {
  type mxcfb_loc_alpha (line 40) | struct mxcfb_loc_alpha {
  type mxcfb_color_key (line 47) | struct mxcfb_color_key {
  type mxcfb_pos (line 52) | struct mxcfb_pos {
  type mxcfb_gamma (line 57) | struct mxcfb_gamma {
  type mxcfb_rect (line 63) | struct mxcfb_rect {
  type mxcfb_alt_buffer_data (line 94) | struct mxcfb_alt_buffer_data {
  type mxcfb_update_data (line 102) | struct mxcfb_update_data {
  type mxcfb_waveform_modes (line 116) | struct mxcfb_waveform_modes {
  type fb_videomode (line 156) | struct fb_videomode
  type fb_info (line 165) | struct fb_info
  type mxcfb_rect (line 166) | struct mxcfb_rect

FILE: ffi-cdecl/include/mxcfb.h
  type mxcfb_gbl_alpha (line 42) | struct mxcfb_gbl_alpha {
  type mxcfb_loc_alpha (line 47) | struct mxcfb_loc_alpha {
  type mxcfb_color_key (line 54) | struct mxcfb_color_key {
  type mxcfb_pos (line 59) | struct mxcfb_pos {
  type mxcfb_gamma (line 64) | struct mxcfb_gamma {
  type mxcfb_rect (line 70) | struct mxcfb_rect {
  type mxcfb_alt_buffer_data (line 110) | struct mxcfb_alt_buffer_data {
  type mxcfb_update_data (line 121) | struct mxcfb_update_data {
  type mxcfb_update_data (line 135) | typedef struct mxcfb_update_data mxcfb_update_data;
  type mxcfb_update_data_50x (line 139) | struct mxcfb_update_data_50x {
  type mxcfb_waveform_modes (line 153) | struct mxcfb_waveform_modes {
  type fb_videomode (line 196) | struct fb_videomode
  type fb_info (line 205) | struct fb_info
  type mxcfb_rect (line 206) | struct mxcfb_rect

FILE: ffi-cdecl/mxcfb_kindle_decl.c
  type uint (line 6) | typedef unsigned int uint;

FILE: ffi-cdecl/mxcfb_kobo_decl.c
  type uint (line 6) | typedef unsigned int uint;
Condensed preview — 44 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (223K chars).
[
  {
    "path": ".gitignore",
    "chars": 76,
    "preview": "version.lua\nlibvncclient.so\ndist/\nlibjpeg-turbo-1.3.0/*\nluajit-2.0/*\nzlib/*\n"
  },
  {
    "path": ".gitmodules",
    "chars": 260,
    "preview": "[submodule \"libvncserver\"]\n\tpath = libvncserver\n\turl = https://github.com/LibVNC/libvncserver.git\n[submodule \"luajit-2.0"
  },
  {
    "path": "COPYING",
    "chars": 18043,
    "preview": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc."
  },
  {
    "path": "Makefile",
    "chars": 2792,
    "preview": "ifdef ARCH\nCC=$(ARCH)-gcc\nCROSS=$(ARCH)-\n# for luajit:\nHOST_CC=\"gcc -m32\"\nSTRIP?=$(ARCH)-strip\nelse\nSTRIP?=strip\nARCH=$("
  },
  {
    "path": "README.md",
    "chars": 1931,
    "preview": "## About\n\nThis is a VNC viewer for eReaders.\nCopyright (c) 2013 Hans-Werner Hilse <hilse@web.de>\n\nIt works on the frameb"
  },
  {
    "path": "Xvnc-start.sh",
    "chars": 442,
    "preview": "#!/bin/sh -xe\n\norientation=`ssh root@192.168.2.2 cat /sys/module/eink_fb_hal_broads/parameters/bs_orientation`\nif [ $ori"
  },
  {
    "path": "config.lua",
    "chars": 6866,
    "preview": "require \"keys\"\nrequire \"rfbkeys\"\n\n-- comment out the following line on a KDX\nset_k3_keycodes()\n\n\n-- variables client_wid"
  },
  {
    "path": "ffi/SDL.lua",
    "chars": 1024,
    "preview": "--[[\nModule for interfacing SDL video/input facilities\n\nThis module is intended to provide input/output facilities on a\n"
  },
  {
    "path": "ffi/SDL1_2_h.lua",
    "chars": 12204,
    "preview": "local ffi = require(\"ffi\")\nffi.cdef[[\ntypedef unsigned int Uint32;\ntypedef int Sint32;\ntypedef short unsigned int Uint16"
  },
  {
    "path": "ffi/blitbuffer.lua",
    "chars": 43998,
    "preview": "--[[\nGeneric blitbuffer/GFX stuff that works on memory buffers\n--]]\n\nlocal ffi = require(\"ffi\")\nlocal util = require(\"ff"
  },
  {
    "path": "ffi/einkfb_h.lua",
    "chars": 1056,
    "preview": "local ffi = require(\"ffi\")\nffi.cdef[[\nenum fx_type {\n  fx_mask = 11,\n  fx_buf_is_mask = 14,\n  fx_none = -1,\n  fx_flash ="
  },
  {
    "path": "ffi/eventloop.lua",
    "chars": 5941,
    "preview": "-- dependencies\nlocal ffi = require(\"ffi\")\nlocal bit = require(\"bit\")\nlocal posix = require(\"ffi/posix_h\")\n\n-- this modu"
  },
  {
    "path": "ffi/framebuffer.lua",
    "chars": 150,
    "preview": "local util = require(\"ffi/util\")\n\nif util.isEmulated() then\n\treturn require(\"ffi/framebuffer_SDL\")\nelse\n\treturn require("
  },
  {
    "path": "ffi/framebuffer_SDL.lua",
    "chars": 1322,
    "preview": "local ffi = require(\"ffi\")\nlocal bit = require(\"bit\")\n-- load common SDL input/video library\nlocal SDL = require(\"ffi/SD"
  },
  {
    "path": "ffi/framebuffer_linux.lua",
    "chars": 10163,
    "preview": "local ffi = require(\"ffi\")\nlocal bit = require(\"bit\")\nlocal BB = require(\"ffi/blitbuffer\")\n\nlocal dummy = require(\"ffi/l"
  },
  {
    "path": "ffi/input.lua",
    "chars": 138,
    "preview": "local util = require(\"ffi/util\")\n\nif util.isEmulated() then\n\treturn require(\"ffi/input_SDL\")\nelse\n\treturn require(\"ffi/i"
  },
  {
    "path": "ffi/input_SDL.lua",
    "chars": 2441,
    "preview": "local ffi = require(\"ffi\")\nlocal evloop = require(\"ffi/eventloop\")\n\nlocal dummy = require(\"ffi/posix_h\")\nlocal dummy = r"
  },
  {
    "path": "ffi/input_kindle.lua",
    "chars": 1201,
    "preview": "local ffi = require(\"ffi\")\nlocal evloop = require(\"ffi/eventloop\")\n\nlocal dummy = require(\"ffi/posix_h\")\nlocal dummy = r"
  },
  {
    "path": "ffi/linux_fb_h.lua",
    "chars": 1493,
    "preview": "local ffi = require(\"ffi\")\nffi.cdef[[\nstatic const int FBIOGET_FSCREENINFO = 17922;\nstatic const int FBIOGET_VSCREENINFO"
  },
  {
    "path": "ffi/linux_input_h.lua",
    "chars": 1319,
    "preview": "local ffi = require(\"ffi\")\nffi.cdef[[\nstatic const int EVIOCGRAB = 1074021776;\nstatic const int EV_SYN = 0;\nstatic const"
  },
  {
    "path": "ffi/mxcfb_kindle_h.lua",
    "chars": 722,
    "preview": "local ffi = require(\"ffi\")\nffi.cdef[[\nstruct mxcfb_rect {\n  unsigned int top;\n  unsigned int left;\n  unsigned int width;"
  },
  {
    "path": "ffi/mxcfb_kobo_h.lua",
    "chars": 663,
    "preview": "local ffi = require(\"ffi\")\nffi.cdef[[\nstruct mxcfb_rect {\n  unsigned int top;\n  unsigned int left;\n  unsigned int width;"
  },
  {
    "path": "ffi/posix_h.lua",
    "chars": 3005,
    "preview": "local ffi = require(\"ffi\")\nffi.cdef[[\ntypedef long unsigned int size_t;\ntypedef long int off_t;\nstruct timeval {\n  long "
  },
  {
    "path": "ffi/rfbclient.lua",
    "chars": 110,
    "preview": "local ffi = require(\"ffi\")\n\nrequire(\"ffi/rfbclient_h\")\n\nlocal rfb = ffi.load(\"./libvncclient.so\")\n\nreturn rfb\n"
  },
  {
    "path": "ffi/rfbclient_h.lua",
    "chars": 5239,
    "preview": "local ffi = require(\"ffi\")\nffi.cdef[[\nstruct z_stream_s {\n  unsigned char *next_in;\n  unsigned int avail_in;\n  long unsi"
  },
  {
    "path": "ffi/util.lua",
    "chars": 1241,
    "preview": "--[[\nModule for various utility functions\n]]\n\nlocal ffi = require \"ffi\"\nlocal bit = require \"bit\"\n\nrequire(\"ffi/posix_h\""
  },
  {
    "path": "ffi-cdecl/SDL1_2_decl.c",
    "chars": 1887,
    "preview": "#include <SDL/SDL.h>\n\n#include \"cdecl.h\"\n\ncdecl_type(Uint32)\ncdecl_type(Sint32)\ncdecl_type(Uint16)\ncdecl_type(Sint16)\ncd"
  },
  {
    "path": "ffi-cdecl/einkfb_decl.c",
    "chars": 542,
    "preview": "// standard Linux framebuffer headers\n#include <linux/fb.h>\n\n#include <linux/ioctl.h>\n// specialized eink framebuffer he"
  },
  {
    "path": "ffi-cdecl/include/README",
    "chars": 284,
    "preview": "The include file \"einkfb.h\" is distributed with Amazons Linux kernel sources\nfor the Kindle. It has no further copyright"
  },
  {
    "path": "ffi-cdecl/include/einkfb.h",
    "chars": 16208,
    "preview": "#ifndef _EINKFB_H\n#define _EINKFB_H\n\n#define EINK_1BPP               1\n#define EINK_2BPP               2\n#define EINK_4B"
  },
  {
    "path": "ffi-cdecl/include/mxcfb-kindle.h",
    "chars": 6115,
    "preview": "/*\n * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.\n *\n * - Modified by houqp, added mxcfb_upda"
  },
  {
    "path": "ffi-cdecl/include/mxcfb-kobo.h",
    "chars": 4628,
    "preview": "/*\n * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.\n *\n * - slightly modified (commented out in"
  },
  {
    "path": "ffi-cdecl/include/mxcfb.h",
    "chars": 6242,
    "preview": "/*\n * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.\n *\n * - Modified by houqp, added mxcfb_upda"
  },
  {
    "path": "ffi-cdecl/linux_fb_decl.c",
    "chars": 300,
    "preview": "// standard Linux framebuffer headers\n#include <linux/fb.h>\n\n#include <linux/ioctl.h>\n\n#include \"cdecl.h\"\n\ncdecl_const(F"
  },
  {
    "path": "ffi-cdecl/linux_input_decl.c",
    "chars": 912,
    "preview": "#include <linux/input.h>\n\n#include \"cdecl.h\"\n\ncdecl_const(EVIOCGRAB)\n\ncdecl_const(EV_SYN)\ncdecl_const(EV_KEY)\ncdecl_cons"
  },
  {
    "path": "ffi-cdecl/mxcfb_kindle_decl.c",
    "chars": 412,
    "preview": "// standard Linux framebuffer headers\n#include <linux/fb.h>\n\n#include <linux/ioctl.h>\n// specialized eink framebuffer he"
  },
  {
    "path": "ffi-cdecl/mxcfb_kobo_decl.c",
    "chars": 410,
    "preview": "// standard Linux framebuffer headers\n#include <linux/fb.h>\n\n#include <linux/ioctl.h>\n// specialized eink framebuffer he"
  },
  {
    "path": "ffi-cdecl/posix_decl.c",
    "chars": 1296,
    "preview": "#include <sys/mman.h>\n#include <stropts.h>\n#include <unistd.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <sys/wa"
  },
  {
    "path": "ffi-cdecl/rfbclient_decl.c",
    "chars": 518,
    "preview": "#include <rfb/rfbclient.h>\n\n#include \"cdecl.h\"\n\ncdecl_struct(z_stream_s)\ncdecl_struct(rfbClientData)\ncdecl_type(rfbClien"
  },
  {
    "path": "keys.lua",
    "chars": 1997,
    "preview": "--[[\n    This file contains settings related to key codes\n\n    Copyright (C) 2010 Andy M. aka h1uke\th1ukeguy @ gmail.com"
  },
  {
    "path": "kvncviewer.ini",
    "chars": 387,
    "preview": "[Actions]\n;; start kvncviewer, connect to 192.168.2.1:1\nV U = !/mnt/us/kvncviewer/kvncviewer.sh 192.168.2.1:1 &\n;; start"
  },
  {
    "path": "kvncviewer.sh",
    "chars": 324,
    "preview": "#!/bin/sh\ncd $(dirname \"$0\")\nLD_LIBRARY_PATH=.\nexport LD_LIBRARY_PATH\n\nlipc-set-prop com.lab126.powerd preventScreenSave"
  },
  {
    "path": "rfbkeys.lua",
    "chars": 36641,
    "preview": "--[[**********************************************************\nCopyright (c) 1987, 1994  X Consortium\n\nPermission is her"
  },
  {
    "path": "vncviewer.lua",
    "chars": 8382,
    "preview": "#!./luajit\nlocal ffi = require(\"ffi\")\nlocal blitbuffer = require(\"ffi/blitbuffer\")\nlocal fb = require(\"ffi/framebuffer\")"
  }
]

About this extraction

This page contains the full source code of the hwhw/kindlevncviewer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 44 files (206.4 KB), approximately 70.6k tokens, and a symbol index with 76 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!