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. Copyright (C) 19yy 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. , 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 ' > $(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 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/" 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 #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 #include // 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 #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 #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 #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 #include #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 #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 #include // 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 #include // 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 #include #include #include #include #include #include #include #include #include #include #include #include #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 #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 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 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_emfilledrect = 0xadf XK_enopencircbullet = 0xae0 XK_enopensquarebullet = 0xae1 XK_openrectbullet = 0xae2 XK_opentribulletup = 0xae3 XK_opentribulletdown = 0xae4 XK_openstar = 0xae5 XK_enfilledcircbullet = 0xae6 XK_enfilledsqbullet = 0xae7 XK_filledtribulletup = 0xae8 XK_filledtribulletdown = 0xae9 XK_leftpointer = 0xaea XK_rightpointer = 0xaeb XK_club = 0xaec XK_diamond = 0xaed XK_heart = 0xaee XK_maltesecross = 0xaf0 XK_dagger = 0xaf1 XK_doubledagger = 0xaf2 XK_checkmark = 0xaf3 XK_ballotcross = 0xaf4 XK_musicalsharp = 0xaf5 XK_musicalflat = 0xaf6 XK_malesymbol = 0xaf7 XK_femalesymbol = 0xaf8 XK_telephone = 0xaf9 XK_telephonerecorder = 0xafa XK_phonographcopyright = 0xafb XK_caret = 0xafc XK_singlelowquotemark = 0xafd XK_doublelowquotemark = 0xafe XK_cursor = 0xaff --[[ * APL * Byte 3 = b ]]-- XK_leftcaret = 0xba3 XK_rightcaret = 0xba6 XK_downcaret = 0xba8 XK_upcaret = 0xba9 XK_overbar = 0xbc0 XK_downtack = 0xbc2 XK_upshoe = 0xbc3 XK_downstile = 0xbc4 XK_underbar = 0xbc6 XK_jot = 0xbca XK_quad = 0xbcc XK_uptack = 0xbce XK_circle = 0xbcf XK_upstile = 0xbd3 XK_downshoe = 0xbd6 XK_rightshoe = 0xbd8 XK_leftshoe = 0xbda XK_lefttack = 0xbdc XK_righttack = 0xbfc --[[ * Hebrew * Byte 3 = c ]]-- XK_hebrew_doublelowline = 0xcdf XK_hebrew_aleph = 0xce0 XK_hebrew_bet = 0xce1 XK_hebrew_beth = 0xce1 --[[ deprecated ]]-- XK_hebrew_gimel = 0xce2 XK_hebrew_gimmel = 0xce2 --[[ deprecated ]]-- XK_hebrew_dalet = 0xce3 XK_hebrew_daleth = 0xce3 --[[ deprecated ]]-- XK_hebrew_he = 0xce4 XK_hebrew_waw = 0xce5 XK_hebrew_zain = 0xce6 XK_hebrew_zayin = 0xce6 --[[ deprecated ]]-- XK_hebrew_chet = 0xce7 XK_hebrew_het = 0xce7 --[[ deprecated ]]-- XK_hebrew_tet = 0xce8 XK_hebrew_teth = 0xce8 --[[ deprecated ]]-- XK_hebrew_yod = 0xce9 XK_hebrew_finalkaph = 0xcea XK_hebrew_kaph = 0xceb XK_hebrew_lamed = 0xcec XK_hebrew_finalmem = 0xced XK_hebrew_mem = 0xcee XK_hebrew_finalnun = 0xcef XK_hebrew_nun = 0xcf0 XK_hebrew_samech = 0xcf1 XK_hebrew_samekh = 0xcf1 --[[ deprecated ]]-- XK_hebrew_ayin = 0xcf2 XK_hebrew_finalpe = 0xcf3 XK_hebrew_pe = 0xcf4 XK_hebrew_finalzade = 0xcf5 XK_hebrew_finalzadi = 0xcf5 --[[ deprecated ]]-- XK_hebrew_zade = 0xcf6 XK_hebrew_zadi = 0xcf6 --[[ deprecated ]]-- XK_hebrew_qoph = 0xcf7 XK_hebrew_kuf = 0xcf7 --[[ deprecated ]]-- XK_hebrew_resh = 0xcf8 XK_hebrew_shin = 0xcf9 XK_hebrew_taw = 0xcfa XK_hebrew_taf = 0xcfa --[[ deprecated ]]-- XK_Hebrew_switch = 0xFF7E --[[ Alias for mode_switch ]]-- --[[ * Thai * Byte 3 = d ]]-- XK_Thai_kokai = 0xda1 XK_Thai_khokhai = 0xda2 XK_Thai_khokhuat = 0xda3 XK_Thai_khokhwai = 0xda4 XK_Thai_khokhon = 0xda5 XK_Thai_khorakhang = 0xda6 XK_Thai_ngongu = 0xda7 XK_Thai_chochan = 0xda8 XK_Thai_choching = 0xda9 XK_Thai_chochang = 0xdaa XK_Thai_soso = 0xdab XK_Thai_chochoe = 0xdac XK_Thai_yoying = 0xdad XK_Thai_dochada = 0xdae XK_Thai_topatak = 0xdaf XK_Thai_thothan = 0xdb0 XK_Thai_thonangmontho = 0xdb1 XK_Thai_thophuthao = 0xdb2 XK_Thai_nonen = 0xdb3 XK_Thai_dodek = 0xdb4 XK_Thai_totao = 0xdb5 XK_Thai_thothung = 0xdb6 XK_Thai_thothahan = 0xdb7 XK_Thai_thothong = 0xdb8 XK_Thai_nonu = 0xdb9 XK_Thai_bobaimai = 0xdba XK_Thai_popla = 0xdbb XK_Thai_phophung = 0xdbc XK_Thai_fofa = 0xdbd XK_Thai_phophan = 0xdbe XK_Thai_fofan = 0xdbf XK_Thai_phosamphao = 0xdc0 XK_Thai_moma = 0xdc1 XK_Thai_yoyak = 0xdc2 XK_Thai_rorua = 0xdc3 XK_Thai_ru = 0xdc4 XK_Thai_loling = 0xdc5 XK_Thai_lu = 0xdc6 XK_Thai_wowaen = 0xdc7 XK_Thai_sosala = 0xdc8 XK_Thai_sorusi = 0xdc9 XK_Thai_sosua = 0xdca XK_Thai_hohip = 0xdcb XK_Thai_lochula = 0xdcc XK_Thai_oang = 0xdcd XK_Thai_honokhuk = 0xdce XK_Thai_paiyannoi = 0xdcf XK_Thai_saraa = 0xdd0 XK_Thai_maihanakat = 0xdd1 XK_Thai_saraaa = 0xdd2 XK_Thai_saraam = 0xdd3 XK_Thai_sarai = 0xdd4 XK_Thai_saraii = 0xdd5 XK_Thai_saraue = 0xdd6 XK_Thai_sarauee = 0xdd7 XK_Thai_sarau = 0xdd8 XK_Thai_sarauu = 0xdd9 XK_Thai_phinthu = 0xdda XK_Thai_maihanakat_maitho = 0xdde XK_Thai_baht = 0xddf XK_Thai_sarae = 0xde0 XK_Thai_saraae = 0xde1 XK_Thai_sarao = 0xde2 XK_Thai_saraaimaimuan = 0xde3 XK_Thai_saraaimaimalai = 0xde4 XK_Thai_lakkhangyao = 0xde5 XK_Thai_maiyamok = 0xde6 XK_Thai_maitaikhu = 0xde7 XK_Thai_maiek = 0xde8 XK_Thai_maitho = 0xde9 XK_Thai_maitri = 0xdea XK_Thai_maichattawa = 0xdeb XK_Thai_thanthakhat = 0xdec XK_Thai_nikhahit = 0xded XK_Thai_leksun = 0xdf0 XK_Thai_leknung = 0xdf1 XK_Thai_leksong = 0xdf2 XK_Thai_leksam = 0xdf3 XK_Thai_leksi = 0xdf4 XK_Thai_lekha = 0xdf5 XK_Thai_lekhok = 0xdf6 XK_Thai_lekchet = 0xdf7 XK_Thai_lekpaet = 0xdf8 XK_Thai_lekkao = 0xdf9 --[[ * Korean * Byte 3 = e ]]-- XK_Hangul = 0xff31 --[[ Hangul start/stop(toggle) ]]-- XK_Hangul_Start = 0xff32 --[[ Hangul start ]]-- XK_Hangul_End = 0xff33 --[[ Hangul end, English start ]]-- XK_Hangul_Hanja = 0xff34 --[[ Start Hangul->Hanja Conversion ]]-- XK_Hangul_Jamo = 0xff35 --[[ Hangul Jamo mode ]]-- XK_Hangul_Romaja = 0xff36 --[[ Hangul Romaja mode ]]-- XK_Hangul_Codeinput = 0xff37 --[[ Hangul code input mode ]]-- XK_Hangul_Jeonja = 0xff38 --[[ Jeonja mode ]]-- XK_Hangul_Banja = 0xff39 --[[ Banja mode ]]-- XK_Hangul_PreHanja = 0xff3a --[[ Pre Hanja conversion ]]-- XK_Hangul_PostHanja = 0xff3b --[[ Post Hanja conversion ]]-- XK_Hangul_SingleCandidate = 0xff3c --[[ Single candidate ]]-- XK_Hangul_MultipleCandidate = 0xff3d --[[ Multiple candidate ]]-- XK_Hangul_PreviousCandidate = 0xff3e --[[ Previous candidate ]]-- XK_Hangul_Special = 0xff3f --[[ Special symbols ]]-- XK_Hangul_switch = 0xFF7E --[[ Alias for mode_switch ]]-- --[[ Hangul Consonant Characters ]]-- XK_Hangul_Kiyeog = 0xea1 XK_Hangul_SsangKiyeog = 0xea2 XK_Hangul_KiyeogSios = 0xea3 XK_Hangul_Nieun = 0xea4 XK_Hangul_NieunJieuj = 0xea5 XK_Hangul_NieunHieuh = 0xea6 XK_Hangul_Dikeud = 0xea7 XK_Hangul_SsangDikeud = 0xea8 XK_Hangul_Rieul = 0xea9 XK_Hangul_RieulKiyeog = 0xeaa XK_Hangul_RieulMieum = 0xeab XK_Hangul_RieulPieub = 0xeac XK_Hangul_RieulSios = 0xead XK_Hangul_RieulTieut = 0xeae XK_Hangul_RieulPhieuf = 0xeaf XK_Hangul_RieulHieuh = 0xeb0 XK_Hangul_Mieum = 0xeb1 XK_Hangul_Pieub = 0xeb2 XK_Hangul_SsangPieub = 0xeb3 XK_Hangul_PieubSios = 0xeb4 XK_Hangul_Sios = 0xeb5 XK_Hangul_SsangSios = 0xeb6 XK_Hangul_Ieung = 0xeb7 XK_Hangul_Jieuj = 0xeb8 XK_Hangul_SsangJieuj = 0xeb9 XK_Hangul_Cieuc = 0xeba XK_Hangul_Khieuq = 0xebb XK_Hangul_Tieut = 0xebc XK_Hangul_Phieuf = 0xebd XK_Hangul_Hieuh = 0xebe --[[ Hangul Vowel Characters ]]-- XK_Hangul_A = 0xebf XK_Hangul_AE = 0xec0 XK_Hangul_YA = 0xec1 XK_Hangul_YAE = 0xec2 XK_Hangul_EO = 0xec3 XK_Hangul_E = 0xec4 XK_Hangul_YEO = 0xec5 XK_Hangul_YE = 0xec6 XK_Hangul_O = 0xec7 XK_Hangul_WA = 0xec8 XK_Hangul_WAE = 0xec9 XK_Hangul_OE = 0xeca XK_Hangul_YO = 0xecb XK_Hangul_U = 0xecc XK_Hangul_WEO = 0xecd XK_Hangul_WE = 0xece XK_Hangul_WI = 0xecf XK_Hangul_YU = 0xed0 XK_Hangul_EU = 0xed1 XK_Hangul_YI = 0xed2 XK_Hangul_I = 0xed3 --[[ Hangul syllable-final (JongSeong) Characters ]]-- XK_Hangul_J_Kiyeog = 0xed4 XK_Hangul_J_SsangKiyeog = 0xed5 XK_Hangul_J_KiyeogSios = 0xed6 XK_Hangul_J_Nieun = 0xed7 XK_Hangul_J_NieunJieuj = 0xed8 XK_Hangul_J_NieunHieuh = 0xed9 XK_Hangul_J_Dikeud = 0xeda XK_Hangul_J_Rieul = 0xedb XK_Hangul_J_RieulKiyeog = 0xedc XK_Hangul_J_RieulMieum = 0xedd XK_Hangul_J_RieulPieub = 0xede XK_Hangul_J_RieulSios = 0xedf XK_Hangul_J_RieulTieut = 0xee0 XK_Hangul_J_RieulPhieuf = 0xee1 XK_Hangul_J_RieulHieuh = 0xee2 XK_Hangul_J_Mieum = 0xee3 XK_Hangul_J_Pieub = 0xee4 XK_Hangul_J_PieubSios = 0xee5 XK_Hangul_J_Sios = 0xee6 XK_Hangul_J_SsangSios = 0xee7 XK_Hangul_J_Ieung = 0xee8 XK_Hangul_J_Jieuj = 0xee9 XK_Hangul_J_Cieuc = 0xeea XK_Hangul_J_Khieuq = 0xeeb XK_Hangul_J_Tieut = 0xeec XK_Hangul_J_Phieuf = 0xeed XK_Hangul_J_Hieuh = 0xeee --[[ Ancient Hangul Consonant Characters ]]-- XK_Hangul_RieulYeorinHieuh = 0xeef XK_Hangul_SunkyeongeumMieum = 0xef0 XK_Hangul_SunkyeongeumPieub = 0xef1 XK_Hangul_PanSios = 0xef2 XK_Hangul_KkogjiDalrinIeung = 0xef3 XK_Hangul_SunkyeongeumPhieuf = 0xef4 XK_Hangul_YeorinHieuh = 0xef5 --[[ Ancient Hangul Vowel Characters ]]-- XK_Hangul_AraeA = 0xef6 XK_Hangul_AraeAE = 0xef7 --[[ Ancient Hangul syllable-final (JongSeong) Characters ]]-- XK_Hangul_J_PanSios = 0xef8 XK_Hangul_J_KkogjiDalrinIeung = 0xef9 XK_Hangul_J_YeorinHieuh = 0xefa --[[ Korean currency symbol ]]-- XK_Korean_Won = 0xeff --[[ Euro currency symbol ]]-- XK_EuroSign = 0x20ac ================================================ FILE: vncviewer.lua ================================================ #!./luajit local ffi = require("ffi") local blitbuffer = require("ffi/blitbuffer") local fb = require("ffi/framebuffer").open("/dev/fb0") local evloop = require("ffi/eventloop") local input = require("ffi/input") local posix = require("ffi/posix_h") local rfb = require("ffi/rfbclient") local password = nil local client = nil local rfbFramebuffer = nil local configfile = "config.lua" local waitRefresh = 250 local rotateFB = 0 local reconnecting = false local debug = false local blitfunc = nil local update_x1 = nil local update_x2 = 0 local update_y1 = 0 local update_y2 = 0 local refresh_full_every_256th_pxup = 512 local refresh_full_ctr = 0 -- this is just an ID value local TIMER_REFRESH = 10 -- constants for screen updates local WAVEFORM_MODE_INIT = 0x0 -- Screen goes to white (clears) local WAVEFORM_MODE_DU = 0x1 -- Grey->white/grey->black local WAVEFORM_MODE_GC16 = 0x2 -- High fidelity (flashing) local WAVEFORM_MODE_GC4 = WAVEFORM_MODE_GC16 -- For compatibility local WAVEFORM_MODE_GC16_FAST = 0x3 -- Medium fidelity local WAVEFORM_MODE_A2 = 0x4 -- Faster but even lower fidelity local WAVEFORM_MODE_GL16 = 0x5 -- High fidelity from white transition local WAVEFORM_MODE_GL16_FAST = 0x6 -- Medium fidelity from white transition local WAVEFORM_MODE_AUTO = 0x101 local waveform_default_fast = WAVEFORM_MODE_GC16 local waveform_default_slow = WAVEFORM_MODE_GC16 -- this is a "public" API to be used by a "config" file function SendKeyEvent(key, pressed) rfb.SendKeyEvent(client, key, pressed) end function SendPointerEvent(x, y, buttonMask) rfb.SendPointerEvent(client, x, y, buttonMask) end function Quit() os.exit(0) end local function do_refresh_full(w, h) -- return false when full refresh is disabled if refresh_full_every_256th_pxup == 0 then return false end -- otherwise count number of pixels updated refresh_full_ctr = refresh_full_ctr + w*h if refresh_full_ctr >= bit.rshift(fb.bb:getWidth() * fb.bb:getHeight() * refresh_full_every_256th_pxup, 8) then refresh_full_ctr = 0 return true end return false end local function refreshTimerFunc() -- not sure how this could happen but it does. -- TODO: find race condition --if not update_x1 then return end local x = update_x1 local y = update_y1 local w = update_x2 - update_x1 local h = update_y2 - update_y1 if debug then io.stdout:write( "eink update ", x, ",", y, " ", w, "x", h, "\n") end fb.bb:blitFrom(rfbFramebuffer, x, y, x, y, w, h, blitfunc) if do_refresh_full(w, h) then if debug then io.stdout:write("slow eink refresh\n") end fb:refresh(1, waveform_default_slow) else if debug then io.stdout:write("fast eink refresh\n") end fb:refresh(0, waveform_default_fast, x, y, w, h) end update_x1 = nil end local function updateFromRFB(client, x, y, w, h) -- this would reset the timer, which we probably do not -- want since this might hold a eink refresh -- indefinitely: --evloop.unregister_timer(TIMER_REFRESH) if debug then io.stdout:write( "RFB update ", x, ",", y, " ", w, "x", h, "\n") end if not update_x1 then update_x1 = x update_x2 = x+w update_y1 = y update_y2 = y+h else if update_x1 > x then update_x1 = x end if update_x2 < x+w then update_x2 = x+w end if update_y1 > y then update_y1 = y end if update_y2 < y+h then update_y2 = y+h end end if not evloop.timer_running(TIMER_REFRESH) then evloop.register_timer_in_ms(waitRefresh, refreshTimerFunc, TIMER_REFRESH) end end local function passwordCallback(client) if password then -- we need a copy that libvncclient can free() return ffi.C.strndup(ffi.cast("char*", password), 8192) end io.stderr:write("got request for password, but no password was configured.\n") return nil end local function connect() local client = rfb.rfbGetClient(8,3,4) -- 24bpp client.GetPassword = passwordCallback client.canHandleNewFBSize = 0 client.GotFrameBufferUpdate = updateFromRFB local argc = ffi.new("int[1]") argc[0] = #arg + 1 local argv = ffi.new("char*[?]", #arg+1) argv[0] = ffi.cast("char*", "kindlevncviewer") for k, v in ipairs(arg) do argv[k] = ffi.cast("char*", v) end assert(rfb.rfbInitClient(client,argc,argv) ~= 0, "cannot initialize client") -- set "public" configuration parameters: client_width = client.width client_height = client.height rfbFramebuffer = blitbuffer.new( client.width, client.height, blitbuffer.TYPE_BBBGR32, client.frameBuffer) rfbFramebuffer:invert() return client end local function usage() io.stderr:write([[ kVNCViewer A VNC viewer for e-ink devices This is free software (GPLv2) (c) 2013 Hans-Werner Hilse Usage: luajit kindlevncviewer.lua [options...] : Server is the VNC server's domain name or its IP address Display is the VNC display number (i.e. not the TCP port number) Available options: -password specify a password -config load configuration from . Default is "config.lua". -rotateFB rotate local framebuffer by degrees (multiple of 90) -waitRefresh wait specified number of milliseconds after receiving an update before refreshing the screen. Default value is 150. -refreshFullAfterPixels after updating times the screen's pixels, a full eink refresh is issued. Default is 2.0 If you specify 0 here, it won't do a full refresh at all. -dither_bw dither to black/white (speeds up display on eink, but looks ugly) -medium a bit lower quality, but also a tad bit faster -fast low quality but fast -debug output some debug information -reconnecting always try to reconnect when we get connection errors -version output version number (and some more that stem from libvncclient, to be documented) ]]) os.exit(1) end local function try_open_input(device) local ok, err = pcall(input.open, device) if not ok then io.stderr:write("could not open input device ", device, " (possibly harmless)\n") end end if #arg == 0 then usage() end for i,value in ipairs(arg) do if value == "-h" or value == "-?" or value == "--help" then usage() end if value == "-password" and arg[i+1] then password = arg[i+1] arg[i+1] = "" elseif value == "-config" and arg[i+1] then configfile = arg[i+1] arg[i+1] = "" elseif value == "-rotateFB" and arg[i+1] then rotateFB = tonumber(arg[i+1]) arg[i+1] = "" elseif value == "-waitRefresh" and arg[i+1] then waitRefresh = tonumber(arg[i+1]) arg[i+1] = "" elseif value == "-refreshFullAfterPixels" and arg[i+1] then refresh_full_every_256th_pxup = 256 * tonumber(arg[i+1]) arg[i+1] = "" elseif value == "-fast" then local waveform_default_fast = WAVEFORM_MODE_A2 local waveform_default_slow = WAVEFORM_MODE_GL16 elseif value == "-medium" then local waveform_default_fast = WAVEFORM_MODE_GL16 local waveform_default_slow = WAVEFORM_MODE_GL16 elseif value == "-dither_bw" then blitfunc = fb.bb.setPixelDithered elseif value == "-debug" then debug = true elseif value == "-reconnecting" then reconnecting = true elseif value == "-version" then io.stdout:write("KindleVNCviewer version ", require("version"), "\n", "see http://github.com/hwhw/kindlevncviewer for source code\n") os.exit(0) end end -- open the "config" file dofile(configfile) fb.bb:rotate(rotateFB) try_open_input("/dev/input/event0") try_open_input("/dev/input/event1") try_open_input("/dev/input/event2") repeat client = connect() local running = true -- register socket handlers evloop.register_fd(client.sock, { read = function() assert(rfb.HandleRFBServerMessage(client) ~= 0, "Error handling RFB server message.") end, err = function() if not reconnecting then io.stderr:write("connection error, quitting.\n") os.exit(1) else io.stderr:write("connection error, retrying in 1s...\n") running = false end end, hup = function() if not reconnecting then io.stderr:write("remote party hung up, quitting.\n") os.exit(1) else io.stderr:write("remote party hung up, retrying in 1s...\n") running = false end end }) while running do local event = input.waitForEvent() handleInput(0, event.type, event.code, event.value) end ffi.C.sleep(1) -- so we don't hammer when the connection is down until not reconnecting