scanbuttond-0.2.3.cvs20090713.orig/0000755000175000017500000000000011226646321014544 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/ChangeLog0000644000175000017500000000202210375204673016316 0ustar pdmpdm0.2.3, released Feb 17, 2006 ---------------------------- * fixed snapscan backend (protocol sync) * added mustek and plustek_umax backends * support for some new scanners * Switched to autoconf/automake * Changed directory/file layout 0.2.2, released Jun 6, 2005 --------------------------- * added snapscan backend * added niash backend * support for scanner initialization script * lots of bugs fixed * command line option support * libusb wrapper moved into own dynamic library * scanbuttond now uses dynamic backend loading 0.2.1, released Mar 14, 2005 ---------------------------- * added plustek and meta backend * added support for more scanners to the epson backend * SIGSEGV bug fixed, scanner hotplugging seems to work now * using /etc/scanbuttond as config file directory 0.2, released Dec 31, 2004 -------------------------- * new, modular architecture * support for multiple scanners * several bugfixes 0.1, released Oct 17, 2004 -------------------------- * first public version scanbuttond-0.2.3.cvs20090713.orig/AUTHORS0000644000175000017500000000143011206757111015610 0ustar pdmpdmPeople behind this project -------------------------- * Bernhard Stiftner (main author, project admin) * Dirk Wriedt (niash backend) * J. Javier Maestro (sniffing snapscan buttons) * Hans Verkuil (plustek backend) * James Gilliland (Epson CX3200 support/testing) * "tsuet" (testing) * Oliver Edelmann (Canon N650U support) * Christian Bucher (CanoScan LIDE 20 support, helped demystifying the plustek protocol) * David Froehlich (Epson Perfection 1260 support/testing) * Milan Zamazal (snapscan testing) * Rene Bredlau (genesys backend) * "Carlos" (Genius Colorpage-HR6 V2) * Jonathan Bravo Lopez (hp3900 backend) * Jan Michaelis (hp3500 backend) * Ilia Sotnikov (hp5590 backend) * Avner Shapiro (gt68xx backend) scanbuttond-0.2.3.cvs20090713.orig/BUGS0000644000175000017500000000562410422430403015223 0ustar pdmpdmOpen Bugs --------- * Some backends report a button press multiple times. This only applies to those backends which were implemented using information from "sniffing" and/or reverse engineering, i.e. plustek, snapscan and niash. I would be glad if someone would volunteer to gather additional info about the scanner communication protocol and fix these backends. Open, but Resolvable Issues --------------------------- * I got a few reports that scanbuttond is not initializing the scanner correctly in some cases. If scanbuttond seems to have troubles accessing the hardware, please have a look at "/etc/scanbuttond/initscanner.sh". This is the scanner initialization script which will be executed before scanbuttond tries to talk to your scanner. Sometimes it is necessary to let a SANE program initialize the scanner before it can be accessed by scanbuttond. Usually, putting something like "scanimage -n" in the initscanner.sh script should solve the problem. * If you are still using Linux 2.4.x: Note that the scanner can be accessed by either the scanner kernel module or from userspace by libusb - but you can't use both at the same time! Scanbuttond only supports libusb, so it won't work when the scanner kernel module is loaded. In this case, I'd suggest to get rid of the kernel module and switching to libusb (or even better: get a 2.6.x kernel since there is no scanner kernel module anymore). * Note that scanbuttond won't work without installation! It expects scripts and configuration files to be installed in /etc/scanbuttond as well as the dynamically loadable backend modules to be present in /usr/local/lib/scanbuttond. * People often complain that scanbuttond produces too many log messages on their systems. Actually, scanbuttond sends quite a lot of DEBUG messages to the logging daemon. However, on a properly configured system, these messages should not congest important logfiles, either because DEBUG messages are generally ignored, or because they are written to separate logfiles dedicated for less important or debugging messages. So, please configure your logging system correctly. I am sorry that I can't tell you how to do that exactly, since there are a lot of different logging systems around (on Linux, for example, there exists klogd, syslog-ng, metalog, ...) and every logger has to be configured in a different way. You should find out which logger your system is using and consult its documentation. Fixed Bugs ---------- * Disconnectiong USB scanners caused older versions of scanbuttond to crash (SIGSEGV). This problem should be fixed as of version 0.2.1. * Be careful when using USB 2.0 with the linux ehci-hcd module. There seems to be a memory leak which makes your computer run out of free RAM after running scanbuttond for several days. The only workaround known to me is not to load ehci-hcd and using USB 1.x (uhci-hcd or ohci-hcd) instead. Update: This problem seems to be fixed in Linux 2.6.10. scanbuttond-0.2.3.cvs20090713.orig/COPYING0000644000175000017500000004311010133742105015567 0ustar pdmpdm 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 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) 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) year 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. scanbuttond-0.2.3.cvs20090713.orig/Makefile.am0000644000175000017500000000053310422425365016601 0ustar pdmpdmSUBDIRS = contrib interface backends scripts . pkgsysconfdir = $(sysconfdir)/$(PACKAGE) INCLUDES = $(all_includes) -I$(top_builddir)/include -I. bin_PROGRAMS = scanbuttond scanbuttond_SOURCES = scanbuttond.c lib/loader.c include/scanbuttond/backend.h include/scanbuttond/scanbuttond.h include/scanbuttond/common.h scanbuttond_LDADD = @LIBDL@ scanbuttond-0.2.3.cvs20090713.orig/INSTALL0000644000175000017500000002243210434223071015571 0ustar pdmpdmInstallation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. (Caching is disabled by default to prevent problems with accidental use of stale cache files.) If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not support the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Here is a another example: /bin/bash ./configure CONFIG_SHELL=/bin/bash Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent configuration-related scripts to be executed by `/bin/bash'. `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. scanbuttond-0.2.3.cvs20090713.orig/configure.in0000644000175000017500000000075310434223071017053 0ustar pdmpdmAC_INIT([scanbuttond], [0.2.3.1], [root84@users.soureforge.net]) AC_CONFIG_HEADERS([include/scanbuttond/config.h]) AM_INIT_AUTOMAKE AC_DISABLE_STATIC AC_LANG_C AC_PROG_CC AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL AC_CHECK_HEADERS(errno.h string.h syslog.h unistd.h dlfcn.h usb.h) CFLAGS="${CFLAGS} -DCFG_DIR=\$(pkgsysconfdir) -DLIB_DIR=\$(libdir)" AC_CHECK_LIB(dl, dlopen, LIBDL=-ldl) AC_SUBST(LIBDL) AC_OUTPUT(Makefile contrib/Makefile interface/Makefile backends/Makefile scripts/Makefile) scanbuttond-0.2.3.cvs20090713.orig/NEWS0000644000175000017500000000000010232774260015231 0ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/README0000644000175000017500000001653511206757111015434 0ustar pdmpdmScanner Button Daemon (scanbuttond), Version 0.2.3 ================================================== First things first ------------------ This software is in its very early stages of development. Although this daemon seems to work for most people, there may still be lots of critical bugs. Be prepared for the worst! Introduction ------------ Modern scanners usually have several front panel buttons which are intended to trigger certain actions like copying, faxing or mailing the scanned document. This daemon monitors the scanner's buttons and runs a shell script whenever one of these buttons has been pressed. Because it is accessing the scanner directly via libusb, there should be no conflicts with SANE or other scanner drivers: scanbuttond simply won't touch the scanner hardware while you are using SANE. Requirements ------------ * Scanner: see "supported scanners" below * Operating system: Linux (and perhaps other Unix-like systems) * Connection: USB (using libusb, the scanner kernel module is currently unsupported) Compilation & Installation -------------------------- Since version 0.2.3, scanbuttond uses the GNU autotools for compilation & installation. Please see the file INSTALL for generic instructions on using them. If you are using a CVS version instead of a release, you may have to bootstrap the package. This can be done by running: "aclocal; autoconf; autoheader; automake -a; libtoolize". You should now be able to run ./configure and make. After you have installed scanbuttond, you should run "ldconfig" to update the cache of the dynamic linker. If you forget to do that, scanbuttond probably won't be able to load the backend modules or resolve the dependencies between them! Please do not forget to set up your configuration files if you have installed scanbuttond for the first time. They are usually located in the directory "/usr/local/etc/scanbuttond". To get started, rename "buttonpressed.sh.example" to "buttonpressed.sh" and "initscanner.sh.example" to "initscanner.sh". Usage ----- If you just want to try out scanbuttond, type > scanbuttond If everyhing works, scanbuttond will fork() to background. To see what scanbuttond is doing, you can have a look at your system log, for example /var/log/everything/current (for Gentoo Linux systems running metalog). To terminate scanbuttond, type > killall scanbuttond That should do the job. Scanbuttond installs a signal handler which should ensure a clean shutdown even when it's killed. If you intend to use scanbuttond seriously, you would probably want to write a distribution-specific init-script for starting and stopping the daemon. Supported scanners ------------------ Supported by the epson backend (via libusb): * Epson Expression 1600 (expected to work) * Epson Expression 1680 (expected to work) * Epson Perfection 610 (expected to work) * Epson Perfection 636U (expected to work) * Epson Perfection 640 (expected to work) * Epson Perfection 1200U (expected to work) * Epson Perfection 1240 (working, tested) * Epson Perfection 1640 (expected to work) * Epson Perfection 1650 (working, tested) * Epson Perfection 1660 (working, tested) * Epson Perfection 2400 (working, tested) * Epson Perfection 2450 (expected to work) * Epson Perfection 3200 (expected to work) * Epson CX3200 (working, tested) * Epson Stylus Scan 2500 (working, tested) Supported by the hp3500 backend (via libusb): * HP ScanJet 3500C (expected to work) * HP ScanJet 3530C (expected to work) * HP ScanJet 3570C (expected to work) Supported by the hp3900 backend (via libusb): * HP ScanJet 3800 (working, tested) * HP ScanJet 3970 (working, tested) * HP ScanJet 4070 (working, tested) * HP ScanJet 4370 (working, tested) * HP ScanJet G2710 (working, tested) * HP ScanJet G3010 (working, tested) * HP ScanJet G3110 (working, tested) * Umax Astra 4900/4950 (expected to work) Supported by the hp5590 backend (via libusb): * HP Scanjet 4570 (expected to work) * HP Scanjet 5550 (expected to work) * HP Scanjet 5590 (expected to work) * HP Scanjet 7650 (expected to work) Supported by the mustek backend (via libusb): * Mustek BearPaw 2448TA (experimental) Supported by the niash backend (via libusb): * Agfa Snapscan Touch (expected to work) * HP Scanjet 3300c (expected to work) * HP Scanjet 3400c (expected to work) * HP Scanjet 4300c (expected to work) Supported by the plustek backend (via libusb): * Canon CanoScan N1220U (expected to work) * Canon CanoScan D660U (expected to work) * Canon CanoScan N650U (expected to work) * Canon CanoScan LiDE 20 (experimental) * Canon CanoScan LiDE 25 (experimental) * Canon CanoScan LiDE 30 (experimental) * Epson Perfection 1260 (working, tested) * Hewlett-Packard ScanJet 2200c (experimental) * Genius (KYE) ColorPage-HR6 V2 (experimental) Supported by the plustek_umax backend (via libusb): * UMAX Astra 3400/3450 (experimental) Supported by the snapscan backend (via libusb): * Epson Perfection 2480 (expected to work) * Epson Perfection 2580 (expected to work) * Epson Perfection 1670 (working, tested) * Epson Perfection 3490 (working, tested) * Epson Perfection 3590 (working, tested) * Epson Perfection 1270 (working, tested) Supported by the gt68xx backend (via libusb): * Genius Colorpage Vivid4 (working, experimental) Note: the mustek, niash, plustek, plustek_umax, gt68xx and snapscan backends were implemented using information gathered by "sniffing" the communication between the Windows driver and the scanner, because there is no technical documentation available for these devices! This means that there may be some weird issues (e.g. button press events reported twice). How to link actions to buttons ------------------------------ Whenever a scanner button has been pressed, scanbuttond starts a shell script and passes it the button number and the SANE scanner name as command line arguments. By default, this shell script is installed as "/usr/local/etc/scanbuttond/buttonpressed.sh". Please modify it to fit your purposes. Scanner initialization ---------------------- Note: this only applies to some scanners supported by the non-epson backends. All scanners supported by the epson backend do not need special initialization. Some scanners require a special initialization procedure (firmware uploading, for example) before they can be used by scanbuttond. Since the scanbuttond backend modules cannot yet handle such operations, the initialization has to be performed by external programs, for example by "scanimage" which is part of SANE. You can customize the initialization procedure by editing the scanner initialization script, which is by default installed at "/usr/local/etc/scanbuttond/initscanner.sh". This script will be executed whenever a new device has to be initialized. In most cases, it should be sufficient to put something like "scanimage -n" into this script. How to contribute to this project --------------------------------- The development of scanbuttond should not be dependent on one single person, but a community effort. You could help by ... * adding or enhancing a scanner backend * adding or enhancing a connection interface * doing some extensive testing * sending patches * sending bug reports * mailing ideas how to enhance scanbuttond * ... If you want to help, please send me an email (see below). Contact ------- Any suggestions, criticism, bug reports/fixes, patches, ... are appreciated. Feel free to contact me via email: Bernhard Stiftner scanbuttond-0.2.3.cvs20090713.orig/backends/0000755000175000017500000000000011226646321016316 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/backends/Makefile.am0000644000175000017500000000665211206757111020361 0ustar pdmpdmlib_LTLIBRARIES = libscanbtnd-backend_artec_eplus48u.la \ libscanbtnd-backend_epson.la \ libscanbtnd-backend_genesys.la \ libscanbtnd-backend_meta.la \ libscanbtnd-backend_mustek.la \ libscanbtnd-backend_niash.la \ libscanbtnd-backend_plustek.la \ libscanbtnd-backend_plustek_umax.la \ libscanbtnd-backend_snapscan.la \ libscanbtnd-backend_hp3500.la \ libscanbtnd-backend_hp3900.la \ libscanbtnd-backend_hp5590.la \ libscanbtnd-backend_gt68xx.la libscanbtnd_backend_epson_la_SOURCES = epson.c epson.h libscanbtnd_backend_epson_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_epson_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_meta_la_SOURCES = meta.c meta.h ../lib/loader.c ../include/scanbuttond/loader.h ../include/scanbuttond/common.h libscanbtnd_backend_meta_la_LIBADD = ../interface/libscanbtnd-interface_usb.la @LIBDL@ libscanbtnd_backend_meta_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_mustek_la_SOURCES = mustek.c mustek.h libscanbtnd_backend_mustek_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_mustek_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_niash_la_SOURCES = niash.c niash.h libscanbtnd_backend_niash_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_niash_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_plustek_la_SOURCES = plustek.c plustek.h libscanbtnd_backend_plustek_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_plustek_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_plustek_umax_la_SOURCES = plustek_umax.c plustek_umax.h libscanbtnd_backend_plustek_umax_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_plustek_umax_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_snapscan_la_SOURCES = snapscan.c snapscan.h libscanbtnd_backend_snapscan_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_snapscan_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_artec_eplus48u_la_SOURCES = artec_eplus48u.c artec_eplus48u.h libscanbtnd_backend_artec_eplus48u_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_artec_eplus48u_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_hp3900_la_SOURCES = hp3900.c hp3900.h libscanbtnd_backend_hp3900_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_hp3900_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_hp3500_la_SOURCES = hp3500.c hp3500.h libscanbtnd_backend_hp3500_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_hp3500_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_hp5590_la_SOURCES = hp5590.c hp5590.h libscanbtnd_backend_hp5590_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_hp5590_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_genesys_la_SOURCES = genesys.c genesys.h libscanbtnd_backend_genesys_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_genesys_la_LDFLAGS = -module -version-info 1:0:0 libscanbtnd_backend_gt68xx_la_SOURCES = gt68xx.c gt68xx.h libscanbtnd_backend_gt68xx_la_LIBADD = ../interface/libscanbtnd-interface_usb.la libscanbtnd_backend_gt68xx_la_LDFLAGS = -module -version-info 1:0:0 pkgsysconfdir = $(sysconfdir)/$(PACKAGE) pkgsysconf_DATA = meta.conf EXTRA_DIST = $(pkgsysconf_DATA) INCLUDES = $(all_includes) -I$(top_builddir)/include -I. scanbuttond-0.2.3.cvs20090713.orig/backends/artec_eplus48u.c0000644000175000017500000001460510434223072021331 0ustar pdmpdm// artec_eplus48u.c : scanbuttond backend for Artec E+48U scanners // This file is part of scanbuttond. // Copyleft )c( 2006 by Joel Fuster // // Built primarily from "niash" scanbuttond backend. // Scanner button interface details from SANE backend "artec_eplus48u" // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. // #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "artec_eplus48u.h" static char* backend_name = "Artec E+48U USB"; #define NUM_SUPPORTED_USB_DEVICES 1 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x05d8, 0x4003, 4 } // Artec E+48u }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Artec", "E+48U"} }; static libusb_handle_t* libusb_handle; static scanner_t* artec_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int artec_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void artec_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "artec_eplus48u:libusb:"; int index = artec_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = artec_scanners; artec_scanners = scanner; } void artec_detach_scanners(void) { scanner_t* next; while (artec_scanners != NULL) { next = artec_scanners->next; free(artec_scanners->sane_device); free(artec_scanners); artec_scanners = next; } } void artec_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = artec_match_libusb_scanner(device); if (index >= 0) artec_attach_libusb_scanner(device); device = device->next; } } int artec_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); artec_scan_devices(devices); return 0; } int artec_control_msg(scanner_t* scanner, int requesttype, int request, int value, int index, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_control_msg((libusb_device_t*)scanner->internal_dev_ptr, requesttype, request, value, index, buffer, bytecount); break; } return -1; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { artec_scanners = NULL; syslog(LOG_INFO, "artec_eplus48u-backend: init"); return artec_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t *devices; artec_detach_scanners(); artec_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); artec_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return artec_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int scanbtnd_get_button(scanner_t* scanner) { unsigned char bytes[64]; int num_bytes; const unsigned char request_packet[64] = { 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; if (!scanner->is_open) return -EINVAL; // Send request num_bytes = artec_control_msg(scanner, 0x40, 0x01, 0x2012, 0x3f40, (void *)request_packet, 64); if (num_bytes < 0) return 0; // Get response num_bytes = artec_control_msg(scanner, 0xc0, 0x01, 0x2013, 0x3f00, (void *)bytes, 64); if (num_bytes < 0) return 0; switch (bytes[2]) { case 0x08: // scan return 1; case 0x02: // copy return 2; case 0x04: // ocr return 3; case 0x01: // email return 4; } return 0; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "artec_eplus48u-backend: exit"); artec_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/artec_eplus48u.h0000644000175000017500000000167410434223072021340 0ustar pdmpdm// artec_eplus48u.h : scanbuttond backend for mustek/gt68xx devices // This file is part of scanbuttond. // Copyleft )c( 2006 by Joel Fuster // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __ARTEC_EPLUS48U_H_INCLUDED #define __ARTEC_EPLUS48U_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/epson.c0000644000175000017500000001737510563732105017622 0ustar pdmpdm// epson.c: Epson ESC/I device backend // This file is part of scanbuttond. // Copyleft )c( 2004-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. // // Thanks to: // - James Gilliland (Epson CX3200 support) #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "epson.h" #define ESC 0x1B /* ASCII value for ESC */ static char* backend_name = "Epson USB"; #define NUM_SUPPORTED_USB_DEVICES 15 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x04B8, 0x0107, 1 }, // Epson Expression 1600 { 0x04B8, 0x010E, 1 }, // Epson Expression 1680 { 0x04B8, 0x0103, 1 }, // Epson Perfection 610 { 0x04B8, 0x0101, 3 }, // Epson Perfection 636U { 0x04B8, 0x010C, 3 }, // Epson Perfection 640 { 0x04B8, 0x0104, 1 }, // Epson Perfection 1200U { 0x04B8, 0x010B, 3 }, // Epson Perfection 1240 { 0x04B8, 0x010A, 1 }, // Epson Perfection 1640 { 0x04B8, 0x0110, 4 }, // Epson Perfection 1650 { 0x04B8, 0x011E, 4 }, // Epson Perfection 1660 { 0x04B8, 0x011B, 4 }, // Epson Perfection 2400 { 0x04B8, 0x0112, 1 }, // Epson Perfection 2450 { 0x04B8, 0x011C, 1 }, // Epson Perfection 3200 { 0x04B8, 0x0802, 1 }, // Epson CX3200 (note: is the button number // really correct?) { 0x04B8, 0x0106, 1 } // Epson Stylus Scan 2500 }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Epson", "Expression 1600"}, { "Epson", "Expression 1680"}, { "Epson", "Perfection 610"}, { "Epson", "Perfection 636U"}, { "Epson", "Perfection 640"}, { "Epson", "Perfection 1200U"}, { "Epson", "Perfection 1240"}, { "Epson", "Perfection 1640"}, { "Epson", "Perfection 1650"}, { "Epson", "Perfection 1660"}, { "Epson", "Perfection 2400"}, { "Epson", "Perfection 2450"}, { "Epson", "Perfection 3200"}, { "Epson", "Stylus CX3200"}, { "Epson", "Stylus Scan 2500"} }; static libusb_handle_t* libusb_handle; static scanner_t* epson_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int epson_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void epson_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "epson:libusb:"; int index = epson_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = epson_scanners; epson_scanners = scanner; } void epson_detach_scanners(void) { scanner_t* next; while (epson_scanners != NULL) { next = epson_scanners->next; free(epson_scanners->sane_device); free(epson_scanners); epson_scanners = next; } } void epson_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = epson_match_libusb_scanner(device); if (index >= 0) epson_attach_libusb_scanner(device); device = device->next; } } int epson_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); epson_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { epson_scanners = NULL; syslog(LOG_INFO, "epson-backend: init"); return epson_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t *devices; epson_detach_scanners(); epson_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); epson_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return epson_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int epson_read(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_read((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } int epson_write(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_write((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } void epson_flush(scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush((libusb_device_t*)scanner->internal_dev_ptr); break; } } int scanbtnd_get_button(scanner_t* scanner) { #define BUFFER_SIZE 16 unsigned char bytes[BUFFER_SIZE]; int rcv_len; int num_bytes; bytes[0] = ESC; bytes[1] = '!'; bytes[2] = '\0'; if (!scanner->is_open) return -EINVAL; num_bytes = epson_write(scanner, (void*)bytes, 2); if (num_bytes != 2) { syslog(LOG_WARNING, "epson-backend: communication error: " "write length:%d (expected:%d)", num_bytes, 2); epson_flush(scanner); return 0; } num_bytes = epson_read(scanner, (void*)bytes, 4); if (num_bytes != 4) { syslog(LOG_WARNING, "epson-backend: communication error: " "read length:%d (expected:%d)", num_bytes, 4); epson_flush(scanner); return 0; } rcv_len = bytes[3] << 8 | bytes[2]; num_bytes = epson_read(scanner, (void*)bytes, MAX(rcv_len, BUFFER_SIZE)); if (num_bytes != rcv_len) { syslog(LOG_WARNING, "epson-backend: communication error: " "read length:%d (expected:%d)", num_bytes, MAX(rcv_len, BUFFER_SIZE)); epson_flush(scanner); return 0; } return bytes[0]; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "epson-backend: exit"); epson_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/epson.h0000644000175000017500000000163010374656614017624 0ustar pdmpdm// epson.h: Epson ESC/I device backend // This file is part of scanbuttond. // Copyleft )c( 2004-2005 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __EPSON_H_INCLUDED #define __EPSON_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/genesys.c0000644000175000017500000001710610563732105020143 0ustar pdmpdm// genesys.c: Genesys device backend // This file is part of scanbuttond. // Copyleft )c( 2005 by Hans Verkuil // Copyleft )c( 2005-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "genesys.h" static char* backend_name = "Genesys USB"; #define NUM_SUPPORTED_USB_DEVICES 2 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x04a9, 0x221c, 15 }, // CanoScan LiDE 60 (15 includes combined buttons - only 4 real buttons) { 0x04a9, 0x2213, 15 } // CanoScan LiDE 35 (15 includes combined buttons - only 4 real buttons) }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Canon", "CanoScan LiDE 60" }, { "Canon", "CanoScan LiDE 35" } }; static libusb_handle_t* libusb_handle; static scanner_t* genesys_scanners = NULL; // Button Map for CanonScan LiDE 60 // button 1 = 0x08 copy // button 2 = 0x01 scan // button 3 = 0x02 pdf // button 4 = 0x04 mail // all others are combinations of the above (if pressed together) static char button_map_lide60[256] = { 0, 2, 3, 5, 4, 6, 7, 8, 1, 9, 10, 11, 12, 13, 14, 15}; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int genesys_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void genesys_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "genesys:libusb:"; int index = genesys_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = genesys_scanners; genesys_scanners = scanner; } void genesys_detach_scanners(void) { scanner_t* next; while (genesys_scanners != NULL) { next = genesys_scanners->next; free(genesys_scanners->sane_device); free(genesys_scanners); genesys_scanners = next; } } void genesys_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = genesys_match_libusb_scanner(device); if (index >= 0) genesys_attach_libusb_scanner(device); device = device->next; } } int genesys_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); genesys_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { genesys_scanners = NULL; syslog(LOG_INFO, "genesys-backend: init"); return genesys_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t* devices; genesys_detach_scanners(); genesys_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); genesys_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return genesys_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int scanbtnd_get_button(scanner_t* scanner) { unsigned char bytes[2]; int num_bytes; int button = 0; // current_button_map should be select according to the current scanner // there is no space left inside scanner_t to store some additional data (for example a pointer) // currently we only support one type of scanner and so this one can be hardcoded char *current_button_map = button_map_lide60; if (!scanner->is_open) return -EINVAL; // every time we want to read the key currently pressed we need to send // some specific data to the scanner first // 40 0c 83 00 00 00 01 00 -> 0x6d bytes[0] = 0x6d; bytes[1] = 0x00; // not really needed, but just to be sure ;-) num_bytes = libusb_control_msg((libusb_device_t*)scanner->internal_dev_ptr, 0x40, 0x0c, 0x0083, 0x0000, (void *)bytes, 0x0001); if (num_bytes != 1) { syslog(LOG_WARNING, "genesys-backend: communication error: " "read length:%d (expected:%d)", num_bytes, 1); return 0; } // now we can ask for the current state // only the currently pressed keys are reported, if some key was pressed _and_ release between // the last an the current query it is not reported here, depending on the query frequence // the key needs to be holded for some time to be recognised // c0 0c 84 00 00 00 01 00 // returns 1f xored with the keys pressed // - this mean any key that is pressed gets it bit removed from 0x1f // - if multiple keys are pressed at the same time multiple bits will be removed num_bytes = libusb_control_msg((libusb_device_t*)scanner->internal_dev_ptr, 0xc0, 0x0c, 0x0084, 0x0000, (void *)bytes, 0x0001); if (num_bytes != 1) { syslog(LOG_WARNING, "genesys-backend: communication error: " "could not read status register"); return 0; } // xor with mask and use only lower 4 bit // lookup button in button map and return return current_button_map[(bytes[0] ^ 0x1f) & 0x0f]; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "genesys-backend: exit"); genesys_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/genesys.h0000644000175000017500000000167210510044450020140 0ustar pdmpdm// plustek.h: Plustek device backend // This file is part of scanbuttond. // Copyleft )c( 2005 by Hans Verkuil // Copyleft )c( 2005 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __GENESYS_H_INCLUDED #define __GENESYS_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/gt68xx.c0000644000175000017500000001465611206757111017644 0ustar pdmpdm// gt68xx.c: gt68xx device backend // This file is part of scanbuttond. // Copyleft )c( 2005 by Hans Verkuil // Copyleft )c( 2005-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. // essentialy most of these files are just copies of each other apart of the // device name. the only real changes are in the parsing routines. #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "gt68xx.h" static char* backend_name = "gt68xx USB"; #define NUM_SUPPORTED_USB_DEVICES 1 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x0458, 0x2014, 5 } }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Genius", "Colorpage Vivid4" } }; libusb_handle_t* libusb_handle; scanner_t* gt68xx_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int gt68xx_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void gt68xx_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "gt68xx:libusb:"; int index = gt68xx_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = gt68xx_scanners; gt68xx_scanners = scanner; } void gt68xx_detach_scanners(void) { scanner_t* next; while (gt68xx_scanners != NULL) { next = gt68xx_scanners->next; free(gt68xx_scanners->sane_device); free(gt68xx_scanners); gt68xx_scanners = next; } } void gt68xx_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = gt68xx_match_libusb_scanner(device); if (index >= 0) gt68xx_attach_libusb_scanner(device); device = device->next; } } int gt68xx_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); gt68xx_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { gt68xx_scanners = NULL; syslog(LOG_INFO, "gt68xx-backend: init"); return gt68xx_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t* devices; gt68xx_detach_scanners(); gt68xx_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); gt68xx_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return gt68xx_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int gt68xx_read(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_control_msg((libusb_device_t*)scanner->internal_dev_ptr, 0xc0, 0x04, 0x2011, 0x3f00, buffer, bytecount); break; } return -1; } int gt68xx_write(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_control_msg((libusb_device_t*)scanner->internal_dev_ptr, 0x40, 0x04, 0x2010, 0x3f40, buffer, bytecount); break; } return -1; } void gt68xx_flush(scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush((libusb_device_t*)scanner->internal_dev_ptr); break; } } int scanbtnd_get_button(scanner_t* scanner) { unsigned char bytes[255] = {}; int num_bytes; int button = 0; bytes[0] = 0x29; bytes[1] = 0x01; bytes[2] = 0xa8; bytes[3] = 0x61; bytes[0x38] = 0x2e; if (!scanner->is_open) return -EINVAL; if (gt68xx_write(scanner, (void*)bytes, 0x40) < 0) return 0; if ((num_bytes = gt68xx_read(scanner, (void*)bytes, 0x40)) < 0) return 0; if (bytes[0] != 0x00 || bytes[1] != 0x29) return 0; if (bytes[2] & 0x02) button = 1; // scan if (bytes[2] & 0x01) button = 2; // copy if (bytes[2] & 0x04) button = 3; // ocr if (bytes[2] & 0x08) button = 4; // mail if (bytes[2] & 0x10) button = 5; // fax return button; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "gt68xx-backend: exit"); gt68xx_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/gt68xx.h0000644000175000017500000000166611206757111017646 0ustar pdmpdm// gt68xx.h: gt68xx device backend // This file is part of scanbuttond. // Copyleft )c( 2005 by Hans Verkuil // Copyleft )c( 2005 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __GT68XX_H_INCLUDED #define __GT68XX_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/hp3500.c0000644000175000017500000001741111053136340017376 0ustar pdmpdm// hp3500.c: RTS8801C2 chipset based devices backend // This file is part of scanbuttond. // Copyleft )c( 2008 by Jan Michaelis // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "hp3500.h" static char* backend_name = "HP3500 USB"; #define NUM_SUPPORTED_USB_DEVICES 1 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x03f0, 0x2205, 3 } // HP ScanJet 3500C //{ 0x03f0, 0x2005, 4 } // HP ScanJet 3530C //{ 0x03f0, 0x2005, 4 } // HP ScanJet 3570C }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Hewlett-Packard", "ScanJet 3500C" } //{ "Hewlett-Packard", "ScanJet 3530C" } //{ "Hewlett-Packard", "Scanjet 3570C" } }; /* Notes for HP ScanJet 3530C and 3570C: Since i've no information about the button status register on these devices, i cannot implement them now, but i think that their structure of the status register is mostly the same. Its address is 0xD0 too and there is just one button more, which i'm expecting at bit 5. If you got one of this devices, feel free to add some lines of code to finally support them. */ libusb_handle_t* libusb_handle; scanner_t* hp3500_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int hp3500_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void hp3500_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "hp3500:libusb:"; int index = hp3500_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = hp3500_scanners; hp3500_scanners = scanner; } void hp3500_detach_scanners(void) { scanner_t* next; while (hp3500_scanners != NULL) { next = hp3500_scanners->next; free(hp3500_scanners->sane_device); free(hp3500_scanners); hp3500_scanners = next; } } void hp3500_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = hp3500_match_libusb_scanner(device); if (index >= 0) hp3500_attach_libusb_scanner(device); device = device->next; } } int hp3500_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); hp3500_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { hp3500_scanners = NULL; syslog(LOG_INFO, "hp3500-backend: init"); return hp3500_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t* devices; hp3500_detach_scanners(); hp3500_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); hp3500_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return hp3500_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int hp3500_read(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_read((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } int hp3500_write(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_write((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } void hp3500_flush(scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush((libusb_device_t*)scanner->internal_dev_ptr); break; } } int scanbtnd_get_button(scanner_t* scanner) { #define BUFFER_SIZE 4 unsigned char bytes[BUFFER_SIZE]; int num_bytes; bytes[0] = 0x80; //Command: "Read one or more registers" bytes[1] = 0xD0; //The Register containing button status bytes[2] = 0x00; //Count HH bytes[3] = 0x01; //Count LL /* Very detailled informations about the "RTS8801C2" chip can be found at: http://projects.troy.rollo.name/rt-scanners/chip.html */ if (!scanner->is_open) return -EINVAL; num_bytes = hp3500_write(scanner, (void*)bytes, 4); if (num_bytes != 4) { syslog(LOG_WARNING, "hp3500-backend: communication error: " "write length:%d (expected:%d)", num_bytes, 4); hp3500_flush(scanner); return 0; } num_bytes = hp3500_read(scanner, (void*)bytes, 1); if (num_bytes != 1) { syslog(LOG_WARNING, "hp3500-backend: communication error: " "read length:%d (expected:%d)", num_bytes, 1); hp3500_flush(scanner); return 0; } /* If none button is pressed, register 0xD0 contains 0xFF. One button is pressed when its bit is 0 in that register. Current button state register 0xD0 Bit Bit value Button 0 0x01 Clear if transparency adapter (TA) is present 2 0x04 Copy 3 0x08 Scan 4 0x10 Mail I decided to implement the following behaviour: You can only press one button at one time (even if it would be possible to press more simultaneously). If more than one button is pressed, this case its treated as if no button is pressed at all. */ bytes[0] = bytes[0] & 0x1C; //Ignore other bits that are not 2,3,4 if(bytes[0] == 0x18) //Copy pressed return 1; else if(bytes[0] == 0x14) //Scan pressed return 2; else if(bytes[0] == 0x0C) //Mail pressed return 3; return 0; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "hp3500-backend: exit"); hp3500_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/hp3500.h0000644000175000017500000000163711053136340017406 0ustar pdmpdm// hp3500.h: RTS8801C2 chipset based devices backend // This file is part of scanbuttond. // Copyleft )c( 2008 by Jan Michaelis // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __HP3500_H_INCLUDED #define __HP3500_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/hp3900.c0000644000175000017500000001545511206757111017415 0ustar pdmpdm// hp3900.c: RTS8822 & RTS8823 chipset based devices backend // This file is part of scanbuttond. // Copyleft )c( 2007 by Jonathan Bravo Lopez // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "hp3900.h" static char* backend_name = "HP3900 USB"; #define NUM_SUPPORTED_USB_DEVICES 9 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x03f0, 0x2605, 3 }, // HP Scanjet 3800 { 0x03f0, 0x2305, 4 }, // HP Scanjet 3970 { 0x03f0, 0x2405, 4 }, // HP Scanjet 4070 { 0x03f0, 0x4105, 4 }, // HP Scanjet 4370 { 0x03f0, 0x2805, 3 }, // HP Scanjet G2710 { 0x03f0, 0x4205, 4 }, // HP Scanjet G3010 { 0x03f0, 0x4305, 4 }, // HP Scanjet G3110 { 0x06dc, 0x0020, 4 }, // Umax Astra 4900/4950 { 0x04a5, 0x2211, 3 } // BenQ 5550T }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Hewlett-Packard", "ScanJet 3800" }, { "Hewlett-Packard", "ScanJet 3970" }, { "Hewlett-Packard", "Scanjet 4070 Photosmart" }, { "Hewlett-Packard", "Scanjet 4370" }, { "Hewlett-Packard", "ScanJet G2710" }, { "Hewlett-Packard", "Scanjet G3010" }, { "Hewlett-Packard", "Scanjet G3110" }, { "UMAX", "Astra 4900/4950" }, { "BenQ", "5550T" } }; libusb_handle_t* libusb_handle; scanner_t* hp3900_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int hp3900_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void hp3900_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "hp3900:libusb:"; int index = hp3900_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = hp3900_scanners; hp3900_scanners = scanner; } void hp3900_detach_scanners(void) { scanner_t* next; while (hp3900_scanners != NULL) { next = hp3900_scanners->next; free(hp3900_scanners->sane_device); free(hp3900_scanners); hp3900_scanners = next; } } void hp3900_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = hp3900_match_libusb_scanner(device); if (index >= 0) hp3900_attach_libusb_scanner(device); device = device->next; } } int hp3900_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); hp3900_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { hp3900_scanners = NULL; syslog(LOG_INFO, "hp3900-backend: init"); return hp3900_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t* devices; hp3900_detach_scanners(); hp3900_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); hp3900_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return hp3900_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int hp3900_read(scanner_t* scanner, void* buffer) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_control_msg((libusb_device_t*)scanner->internal_dev_ptr, 0xc0, 0x04, 0xe968, 0x0100, (void *)buffer, 0x0002); break; } return -1; } void hp3900_flush(scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush((libusb_device_t*)scanner->internal_dev_ptr); break; } } int scanbtnd_get_button(scanner_t* scanner) { unsigned char bytes[2]; int num_bytes; int button = 0; int c; int mask; bytes[2] = 0; if (!scanner->is_open) return -EINVAL; /* Lets read RTS8822 register 0xe968 */ num_bytes = hp3900_read(scanner, bytes); if (num_bytes != 2) { syslog(LOG_WARNING, "hp3900-backend: communication error: " "read length:%d (expected:%d)", num_bytes, 2); hp3900_flush(scanner); return 0; } /* If none button is pressed, register 0xe968 contains 0x3F. RTS8822 seems to support 6 buttons and more than one button can be pressed at the same time. One button is pressed when its bit is 0 in that register. */ mask = 1; for (c = 0; c < scanner->num_buttons; c++) { if ((bytes[0] & mask) == 0) { button = c + 1; break; } mask = mask << 1; } return button; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "hp3900-backend: exit"); hp3900_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/hp3900.h0000644000175000017500000000167010434717066017423 0ustar pdmpdm// hp3900.h: RTS8822 chipset based devices backend // This file is part of scanbuttond. // Copyleft )c( 2006 by Jonathan Bravo Lopez // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __HP3900_H_INCLUDED #define __HP3900_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/hp5590.c0000644000175000017500000004622311064761303017421 0ustar pdmpdm/* hp5590.c: HP4570/5550/5590/7650 backend * This file is part of scanbuttond. * Copyleft )c( 2008 by Ilia Sotnikov * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include /* For htons() */ #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "hp5590.h" static char* backend_name = "HP5590 USB"; #define NUM_SUPPORTED_USB_DEVICES 4 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { /* vendor, product, num_buttons */ { 0x03f0, 0x1305, 5 }, /* HP Scanjet 4570 */ { 0x03f0, 0x1305, 5 }, /* HP Scanjet 5550 */ { 0x03f0, 0x1705, 5 }, /* HP Scanjet 5590 */ { 0x03f0, 0x1805, 5 }, /* HP Scanjet 7650 */ }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Hewlett-Packard", "ScanJet 4570" }, { "Hewlett-Packard", "ScanJet 5550" }, { "Hewlett-Packard", "Scanjet 5590" }, { "Hewlett-Packard", "Scanjet 7650" }, }; static libusb_handle_t* libusb_handle; static scanner_t* hp5590_scanners = NULL; /* returns -1 if the scanner is unsupported, or the index of the * corresponding vendor-product pair in the supported_usb_devices array. */ static int hp5590_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) break; } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } static void hp5590_attach_libusb_scanner (libusb_device_t* device) { const char* descriptor_prefix = "hp5590:libusb:"; int index; index = hp5590_match_libusb_scanner(device); /* Unsupported */ if (index < 0) return; scanner_t* scanner = (scanner_t*) malloc (sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*) device; scanner->lastbutton = 0; scanner->sane_device = (char*) malloc (strlen (device->location) + strlen (descriptor_prefix) + 1); strcpy (scanner->sane_device, descriptor_prefix); strcat (scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = hp5590_scanners; hp5590_scanners = scanner; } static void hp5590_detach_scanners (void) { scanner_t* next; while (hp5590_scanners != NULL) { next = hp5590_scanners->next; free (hp5590_scanners->sane_device); free (hp5590_scanners); hp5590_scanners = next; } } static void hp5590_scan_devices (libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = hp5590_match_libusb_scanner (device); if (index >= 0) hp5590_attach_libusb_scanner (device); device = device->next; } } static int hp5590_init_libusb (void) { libusb_device_t* devices; libusb_handle = libusb_init (); devices = libusb_get_devices (libusb_handle); hp5590_scan_devices (devices); return 0; } static void hp5590_flush (scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush ((libusb_device_t*) scanner->internal_dev_ptr); break; } } const char* scanbtnd_get_backend_name (void) { return backend_name; } int scanbtnd_init (void) { hp5590_scanners = NULL; syslog (LOG_INFO, "hp5590-backend: init"); return hp5590_init_libusb (); } int scanbtnd_rescan (void) { libusb_device_t* devices; hp5590_detach_scanners (); hp5590_scanners = NULL; libusb_rescan (libusb_handle); devices = libusb_get_devices (libusb_handle); hp5590_scan_devices (devices); return 0; } const scanner_t* scanbtnd_get_supported_devices (void) { return hp5590_scanners; } int scanbtnd_open (scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: /* if devices have been added/removed, return -ENODEV to * make scanbuttond update its device list */ if (libusb_get_changed_device_count () != 0) return -ENODEV; result = libusb_open ((libusb_device_t*) scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close ((libusb_device_t*) scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } /* Taken from sane-backends/include/sane/sanei_usb.h */ #define USB_DIR_OUT 0x00 #define USB_DIR_IN 0x80 /* Taken from sane-backends/backends/hp5590_cmds.c */ /* Button flags */ #define BUTTON_FLAG_EMAIL 1 << 15 #define BUTTON_FLAG_COPY 1 << 14 #define BUTTON_FLAG_DOWN 1 << 13 #define BUTTON_FLAG_MODE 1 << 12 #define BUTTON_FLAG_UP 1 << 11 #define BUTTON_FLAG_FILE 1 << 9 #define BUTTON_FLAG_POWER 1 << 5 #define BUTTON_FLAG_SCAN 1 << 2 #define BUTTON_FLAG_COLLECT 1 << 1 #define BUTTON_FLAG_CANCEL 1 << 0 #define CMD_BUTTON_STATUS 0x0020 /* Taken from sane-backends/backends/hp5590_low.c */ /* Flags for hp5590_cmd() */ #define CMD_IN 1 << 0 /* Indicates IN direction, otherwise - OUT */ #define CMD_VERIFY 1 << 1 /* Requests last command verification */ /* Core flags for hp5590_cmd() - they indicate so called CORE commands */ #define CORE_NONE 0 /* No CORE operation */ #define CORE_DATA 1 << 0 /* Operate on CORE data */ /* CORE status flag - ready or not */ #define CORE_FLAG_NOT_READY 1 << 1 /* Structure describing control URB */ struct usb_in_usb_ctrl_setup { u_int8_t bRequestType; u_int8_t bRequest; u_int16_t wValue; u_int16_t wIndex; u_int16_t wLength; } __attribute__ ((packed)); static int hp5590_get_ack (scanner_t *scanner) { u_int8_t status; int ret; /* Check if USB-in-USB operation was accepted */ ret = libusb_control_msg ((libusb_device_t *) scanner->internal_dev_ptr, USB_DIR_IN | USB_TYPE_VENDOR, 0x0c, 0x8e, 0x20, &status, sizeof (status)); if (ret <= 0) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: error getting acknowledge"); return -1; } /* Check if we received correct acknowledgement */ if (status != 0x01) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: not accepted (status %u)", status); return -1; } return 0; } static int hp5590_control_msg (scanner_t *scanner, int requesttype, int request, int value, int index, unsigned char *bytes, int size, int core_flags) { struct usb_in_usb_ctrl_setup ctrl; int ret; unsigned int len; unsigned char *ptr; u_int8_t ack; u_int8_t response; /* IN (read) operation will be performed */ if (requesttype & USB_DIR_IN) { /* Prepare USB-in-USB control message */ memset (&ctrl, 0, sizeof (ctrl)); ctrl.bRequestType = 0xc0; ctrl.bRequest = request; ctrl.wValue = htons (value); ctrl.wIndex = htons (index); ctrl.wLength = size; /* Send USB-in-USB control message */ ret = libusb_control_msg ((libusb_device_t *) scanner->internal_dev_ptr, USB_DIR_OUT | USB_TYPE_VENDOR, 0x04, 0x8f, 0x00, (unsigned char *) &ctrl, sizeof (ctrl)); if (ret <= 0) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: error sending control message"); return -1; } ret = hp5590_get_ack (scanner); if (ret != 0) return ret; len = size; ptr = bytes; /* Data is read in 8 byte portions */ while (len) { unsigned int next_packet_size; next_packet_size = 8; if (len < 8) next_packet_size = len; /* Read USB-in-USB data */ ret = libusb_control_msg ((libusb_device_t *) scanner->internal_dev_ptr, USB_DIR_IN | USB_TYPE_VENDOR, core_flags & CORE_DATA ? 0x0c : 0x04, 0x90, 0x00, ptr, next_packet_size); if (ret <= 0) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: error reading data"); return -1; } ptr += next_packet_size; len -= next_packet_size; } /* Confirm data reception */ ack = 0; ret = libusb_control_msg ((libusb_device_t *) scanner->internal_dev_ptr, USB_DIR_OUT | USB_TYPE_VENDOR, 0x0c, 0x8f, 0x00, &ack, sizeof (ack)); if (ret <= 0) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: error confirming data reception"); return -1; } ret = hp5590_get_ack (scanner); if (ret != 0) return ret; } /* OUT (write) operation will be performed */ if (!(requesttype & USB_DIR_IN)) { /* Prepare USB-in-USB control message */ memset (&ctrl, 0, sizeof (ctrl)); ctrl.bRequestType = 0x40; ctrl.bRequest = request; ctrl.wValue = htons (value); ctrl.wIndex = htons (index); ctrl.wLength = size; /* Send USB-in-USB control message */ ret = libusb_control_msg ((libusb_device_t *) scanner->internal_dev_ptr, USB_DIR_OUT | USB_TYPE_VENDOR, 0x04, 0x8f, 0x00, (unsigned char *) &ctrl, sizeof (ctrl)); if (ret <= 0) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: error sending control message"); return -1; } ret = hp5590_get_ack (scanner); if (ret != 0) return ret; len = size; ptr = bytes; /* Data is sent in 8 byte portions */ while (len) { unsigned int next_packet_size; next_packet_size = 8; if (len < 8) next_packet_size = len; /* Send USB-in-USB data */ ret = libusb_control_msg ((libusb_device_t *) scanner->internal_dev_ptr, USB_DIR_OUT | USB_TYPE_VENDOR, core_flags & CORE_DATA ? 0x04 : 0x0c, 0x8f, 0x00, ptr, next_packet_size); if (ret <= 0) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: error sending data"); return -1; } /* CORE data is acknowledged packet by packet */ if (core_flags & CORE_DATA) { ret = hp5590_get_ack (scanner); if (ret != 0) return ret; } ptr += next_packet_size; len -= next_packet_size; } /* Normal (non-CORE) data is acknowledged after its full transmission */ if (!(core_flags & CORE_DATA)) { ret = hp5590_get_ack (scanner); if (ret != 0) return ret; } /* Getting response after data transmission */ ret = libusb_control_msg ((libusb_device_t *) scanner->internal_dev_ptr, USB_DIR_IN | USB_TYPE_VENDOR, 0x0c, 0x90, 0x00, &response, sizeof (response)); if (ret <= 0) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: error getting response"); return -1; } /* Necessary response after normal (non-CORE) data is 0x00 */ if (response != 0x00) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: invalid response received " "(needed 0x00, got %04x)", response); return -1; } } return 0; } static int hp5590_verify_last_cmd (scanner_t *scanner, unsigned int cmd) { u_int16_t verify_cmd; unsigned int last_cmd; unsigned int core_status; int ret; /* Read last command along with CORE status */ ret = hp5590_control_msg (scanner, USB_DIR_IN, 0x04, 0xc5, 0x00, (unsigned char *) &verify_cmd, sizeof (verify_cmd), CORE_NONE); if (ret != 0) return ret; /* Last command - minor byte */ last_cmd = verify_cmd & 0xff; /* CORE status - major byte */ core_status = (verify_cmd & 0xff00) >> 8; /* Verify last command */ if ((cmd & 0x00ff) != last_cmd) { syslog (LOG_ERR, "hp5590-backend: USB-in-USB: command verification failed: " "expected 0x%04x, got 0x%04x", cmd, last_cmd); return -1; } /* Return value depends on CORE status */ return core_status & CORE_FLAG_NOT_READY ? -1 : 0; } static int hp5590_cmd (scanner_t *scanner, unsigned int flags, unsigned int cmd, unsigned char *data, unsigned int size, unsigned int core_flags) { int ret; ret = hp5590_control_msg (scanner, flags & CMD_IN ? USB_DIR_IN : USB_DIR_OUT, 0x04, cmd, 0x00, data, size, core_flags); if (ret != 0) return ret; ret = 0; /* Verify last command if requested */ if (flags & CMD_VERIFY) ret = hp5590_verify_last_cmd (scanner, cmd); return ret; } int scanbtnd_get_button(scanner_t* scanner) { int button = 0; u_int16_t button_status; int ret; if (!scanner->is_open) return -EINVAL; ret = hp5590_cmd (scanner, CMD_IN | CMD_VERIFY, CMD_BUTTON_STATUS, (unsigned char *) &button_status, sizeof (button_status), CORE_NONE); if (ret != 0) { hp5590_flush (scanner); return 0; } /* Network order */ button_status = ntohs (button_status); if (button_status & BUTTON_FLAG_SCAN) button = 1; if (button_status & BUTTON_FLAG_COLLECT) button = 2; if (button_status & BUTTON_FLAG_FILE) button = 3; if (button_status & BUTTON_FLAG_EMAIL) button = 4; if (button_status & BUTTON_FLAG_COPY) button = 5; return button; } const char* scanbtnd_get_sane_device_descriptor (scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit (void) { syslog (LOG_INFO, "hp5590-backend: exit"); hp5590_detach_scanners (); libusb_exit (libusb_handle); return 0; }scanbuttond-0.2.3.cvs20090713.orig/backends/hp5590.h0000644000175000017500000000165411064761303017425 0ustar pdmpdm/* hp5590.c: HP4570/5550/5590/7650 backend * This file is part of scanbuttond. * Copyleft )c( 2008 by Ilia Sotnikov * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __HP5590_H_INCLUDED #define __HP5590_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/meta.c0000644000175000017500000001543210422430654017412 0ustar pdmpdm// meta.c: meta backend ("dynamic backend loader") // This file is part of scanbuttond. // Copyleft )c( 2005-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include #include "scanbuttond/common.h" #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "meta.h" #define MAX_CONFIG_LINE 255 #define MAX_SCANNERS_PER_BACKEND 16 static char* backend_name = "Dynamic Module Loader"; static char* config_file = STRINGIFY(CFG_DIR) "/meta.conf"; static libusb_handle_t* libusb_handle; static scanner_t* meta_scanners = NULL; static backend_t* meta_backends = NULL; const char* scanbtnd_get_backend_name(void) { return backend_name; } void meta_attach_scanner(scanner_t* scanner, backend_t* backend) { scanner_t* dev = (scanner_t*)malloc(sizeof(scanner_t)); dev->vendor = scanner->vendor; dev->product = scanner->product; dev->connection = scanner->connection; dev->internal_dev_ptr = scanner->internal_dev_ptr; dev->sane_device = scanner->sane_device; dev->meta_info = (void*)backend; dev->lastbutton = scanner->lastbutton; dev->num_buttons = scanner->num_buttons; dev->is_open = scanner->is_open; dev->next = meta_scanners; meta_scanners = dev; syslog(LOG_INFO, "meta-backend: attached scanner \"%s %s\"", scanner->vendor, scanner->product); } void meta_attach_scanners(scanner_t* devices, backend_t* backend) { scanner_t* dev = devices; int count = 0; while (dev != NULL) { if (count >= MAX_SCANNERS_PER_BACKEND) { syslog(LOG_WARNING, "meta-backend: refusing to attach scanner \"%s %s\": Too many scanners!", dev->vendor, dev->product); return; } meta_attach_scanner(dev, backend); dev = dev->next; count++; } } void meta_detach_scanner(scanner_t* scanner, scanner_t* prev_scanner) { syslog(LOG_INFO, "meta-backend: detaching scanner: \"%s %s\"", scanner->vendor, scanner->product); if (prev_scanner != NULL) prev_scanner->next = scanner->next; else if (scanner == meta_scanners) meta_scanners = scanner->next; else syslog(LOG_WARNING, "meta-backend: detach scanner: invalid arguments!"); free(scanner); } void meta_detach_scanners(void) { while (meta_scanners != NULL) { meta_detach_scanner(meta_scanners, NULL); } } int meta_attach_backend(backend_t* backend) { // don't load another meta backend if (strcmp(backend->scanbtnd_get_backend_name(), scanbtnd_get_backend_name())==0) { syslog(LOG_WARNING, "meta-backend: refusing to load another meta backend!"); return -1; } syslog(LOG_INFO, "meta-backend: attaching backend: %s", backend->scanbtnd_get_backend_name()); backend->next = meta_backends; meta_backends = backend; backend->scanbtnd_init(); return 0; } void meta_detach_backend(backend_t* backend, backend_t* prev_backend) { if (prev_backend != NULL) prev_backend->next = backend->next; else if (backend == meta_backends) meta_backends = backend->next; else syslog(LOG_WARNING, "meta-backend: detach backend: invalid arguments!"); backend->scanbtnd_exit(); scanbtnd_unload_backend(backend); } void meta_detach_backends(void) { while (meta_backends != NULL) { meta_detach_backend(meta_backends, NULL); } } backend_t* meta_lookup_backend(scanner_t* scanner) { return (backend_t*)scanner->meta_info; } void meta_strip_newline(char* str) { int len = strlen(str); if (len == 0) return; if (str[len-1] != '\n') return; str[len-1] = 0; } int scanbtnd_init(void) { int error; meta_scanners = NULL; meta_backends = NULL; syslog(LOG_INFO, "meta-backend: init"); error = scanbtnd_loader_init(); if (error != 0) { syslog(LOG_ERR, "meta-backend: could not init module loader!"); return error; } libusb_handle = libusb_init(); if (!libusb_handle) { syslog(LOG_ERR, "meta-backend: could not init libusb!"); scanbtnd_loader_exit(); return 1; } // read config file char lib[MAX_CONFIG_LINE]; backend_t* backend; FILE* f = fopen(config_file, "r"); if (f == NULL) { syslog(LOG_ERR, "meta-backend: config file \"%s\" not found.", config_file); return -1; } while (fgets(lib, MAX_CONFIG_LINE, f)) { meta_strip_newline(lib); if (strlen(lib)==0) continue; /* char* libpath = (char*)malloc(strlen(lib) + strlen(lib_dir) + 2); strcpy(libpath, lib_dir); strcat(libpath, "/"); strcat(libpath, lib); backend = load_backend(libpath); free(libpath); */ backend = scanbtnd_load_backend(lib); if (backend == NULL) { syslog(LOG_ERR, "meta-backend: could not load '%s'", lib); } else if (meta_attach_backend(backend)==0) { meta_attach_scanners( backend->scanbtnd_get_supported_devices(), backend); } } fclose(f); return 0; } int scanbtnd_rescan(void) { backend_t* backend; meta_detach_scanners(); meta_scanners = NULL; backend = meta_backends; while (backend != NULL) { backend->scanbtnd_rescan(); meta_attach_scanners(backend->scanbtnd_get_supported_devices(), backend); backend = backend->next; } return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return meta_scanners; } int scanbtnd_open(scanner_t* scanner) { // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) { return -ENODEV; } backend_t* backend = meta_lookup_backend(scanner); if (backend == NULL) return -1; return backend->scanbtnd_open(scanner); } int scanbtnd_close(scanner_t* scanner) { backend_t* backend = meta_lookup_backend(scanner); if (backend == NULL) return -1; return backend->scanbtnd_close(scanner); } int scanbtnd_get_button(scanner_t* scanner) { backend_t* backend = meta_lookup_backend(scanner); if (backend == NULL) return 0; return backend->scanbtnd_get_button(scanner); } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { backend_t* backend = meta_lookup_backend(scanner); if (backend == NULL) return NULL; return backend->scanbtnd_get_sane_device_descriptor(scanner); } int scanbtnd_exit(void) { syslog(LOG_INFO, "meta-backend: exit"); meta_detach_scanners(); meta_detach_backends(); libusb_exit(libusb_handle); scanbtnd_loader_exit(); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/meta.conf0000644000175000017500000000052411206757111020112 0ustar pdmpdmlibscanbtnd-backend_artec_eplus48u libscanbtnd-backend_epson libscanbtnd-backend_genesys libscanbtnd-backend_hp3500 libscanbtnd-backend_hp3900 libscanbtnd-backend_hp5590 libscanbtnd-backend_mustek libscanbtnd-backend_niash libscanbtnd-backend_plustek libscanbtnd-backend_plustek_umax libscanbtnd-backend_snapscan libscanbtnd-backend_gt68xx scanbuttond-0.2.3.cvs20090713.orig/backends/meta.h0000644000175000017500000000167510374656614017437 0ustar pdmpdm// meta.h: meta backend ("dynamic backend loader") // This file is part of scanbuttond. // Copyleft )c( 2005 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __META_H_INCLUDED #define __META_H_INCLUDED #include "scanbuttond/backend.h" #include "scanbuttond/loader.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/mustek.c0000644000175000017500000001457710563732105020007 0ustar pdmpdm// mustek.c : scanbuttond backend for mustek/gt68xx devices // This file is part of scanbuttond. // Copyleft )c( 2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. // #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "mustek.h" static char* backend_name = "Mustek USB"; #define NUM_SUPPORTED_USB_DEVICES 1 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x055f, 0x0409, 5 } // Mustek BearPaw 2448TA }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Mustek", "BearPaw 2448TA"} }; static libusb_handle_t* libusb_handle; static scanner_t* mustek_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int mustek_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void mustek_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "mustek:libusb:"; int index = mustek_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = mustek_scanners; mustek_scanners = scanner; } void mustek_detach_scanners(void) { scanner_t* next; while (mustek_scanners != NULL) { next = mustek_scanners->next; free(mustek_scanners->sane_device); free(mustek_scanners); mustek_scanners = next; } } void mustek_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = mustek_match_libusb_scanner(device); if (index >= 0) mustek_attach_libusb_scanner(device); device = device->next; } } int mustek_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); mustek_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { mustek_scanners = NULL; syslog(LOG_INFO, "mustek-backend: init"); return mustek_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t *devices; mustek_detach_scanners(); mustek_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); mustek_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return mustek_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int mustek_read(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_read((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } int mustek_write(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_write((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } void mustek_flush(scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush((libusb_device_t*)scanner->internal_dev_ptr); break; } } int scanbtnd_get_button(scanner_t* scanner) { unsigned char bytes[8]; int num_bytes; bytes[0] = 0x74; // check function key if (!scanner->is_open) return -EINVAL; num_bytes = mustek_write(scanner, (void*)bytes, 1); if (num_bytes != 1) { syslog(LOG_WARNING, "mustek-backend: communication error: " "write length:%d (expected:%d)", num_bytes, 1); mustek_flush(scanner); return 0; } num_bytes = mustek_read(scanner, (void*)bytes, 8); if (num_bytes != 8) { syslog(LOG_WARNING, "mustek-backend: communication error: " "read length:%d (expected:%d)", num_bytes, 8); mustek_flush(scanner); return 0; } switch (bytes[2]) { case 0x10: // scan button return 1; case 0x14: // copy return 2; case 0x12: // fax return 3; case 0x18: // email return 4; case 0x11: // panel return 5; } return 0; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "mustek-backend: exit"); mustek_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/mustek.h0000644000175000017500000000165210374656614020014 0ustar pdmpdm// mustek.h : scanbuttond backend for mustek/gt68xx devices // This file is part of scanbuttond. // Copyleft )c( 2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __MUSTEK_H_INCLUDED #define __MUSTEK_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/niash.c0000644000175000017500000001644210563732105017572 0ustar pdmpdm// niash.c: Niash device backend // This file is part of scanbuttond. // Copyleft )c( 2005 by Bernhard Stiftner // Copyleft )c( 2005 by Dirk Wriedt // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "niash.h" static char* backend_name = "Niash USB"; #define NUM_SUPPORTED_USB_DEVICES 5 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x06bd, 0x0100, 4 }, // Agfa Snapscan Touch { 0x03f0, 0x0205, 2 }, // HP Scanjet 3300c { 0x03f0, 0x0405, 3 }, // HP Scanjet 3400c { 0x03f0, 0x0305, 3 }, // HP Scanjet 4300c { 0x047b, 0x1002, 3 }, // HP Scanjet 4300c }; // TODO: check if this backend really works on the Epson 2580 too... static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Agfa", "Snapscan Touch" }, { "Hewlett-Packard", "Scanjet 3300c" }, { "Hewlett-Packard", "Scanjet 3400c" }, { "Hewlett-Packard", "Scanjet 4300c" }, { "Hewlett-Packard", "Scanjet 4300c" } }; static libusb_handle_t* libusb_handle; static scanner_t* niash_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int niash_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } // TODO: check if the descriptor matches the SANE device name! void niash_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "niash:libusb:"; int index = niash_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = niash_scanners; niash_scanners = scanner; } void niash_detach_scanners(void) { scanner_t* next; while (niash_scanners != NULL) { next = niash_scanners->next; free(niash_scanners->sane_device); free(niash_scanners); niash_scanners = next; } } void niash_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = niash_match_libusb_scanner(device); if (index >= 0) niash_attach_libusb_scanner(device); device = device->next; } } int niash_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); niash_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { niash_scanners = NULL; syslog(LOG_INFO, "niash-backend: init"); return niash_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t* devices; niash_detach_scanners(); niash_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); niash_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return niash_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int niash_control_msg(scanner_t* scanner, int requesttype, int request, int value, int index, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_control_msg((libusb_device_t*)scanner->internal_dev_ptr, requesttype, request, value, index, buffer, bytecount); break; } return -1; } int scanbtnd_get_button(scanner_t* scanner) { unsigned char bytes[255]; int value[255]; int requesttype[255]; int num_bytes; int button; int i; if (!scanner->is_open) return -EINVAL; /* The button status seems to be held in Register 0x2e of the scanner's USB - IEEE1284 bridge I checked the usb sniffer logs against hp3300c_xfer.h (hp3300 sane backend) and learned that the requests being submitted by the windows driver for my Agfa Snapscan Touch seem to follow this schema: request value data datasize 0x40 SPP_CONTROL (0x87) 0x14 1 0x40 EPP_ADDR (0x83) 0x2e 1 0x40 SPP_CONTROL (0x87) 0x34 1 0xc0 EPP_DATA_READ (0x84) returned 1 0x40 SPP_CONTROL (0x87) 0x14 1 The register can be read by setting the address with an EPP_ADDR call, then issuing an EPP_DATA_READ call. I don't know what the last request is for. */ requesttype[0]=0x40; bytes[0] = 0x14; value[0]=0x87; /* SPP_CONTROL */ requesttype[1]=0x40; bytes[1] = 0x2e; value[1]=0x83; /* EPP_ADDR */ requesttype[2]=0x40; bytes[2] = 0x34; value[2]=0x87; /* SPP_CONTROL */ requesttype[3]=0xc0; bytes[3] = 0xff; value[3]=0x84; /* EPP_DATA_READ */ requesttype[4]=0x40; bytes[4] = 0x14; value[4]=0x87; /* SPP_CONTROL */ for(i=0;i<5;i++) { num_bytes=niash_control_msg(scanner, requesttype[i], 0x0c, value[i], 0, (void*)&bytes + i, 0x01); if (num_bytes < 0 ) return 0; } switch (bytes[3]) { case 0x02: button = 1; break; case 0x04: button = 2; break; case 0x08: button = 3; break; case 0x10: button = 4; break; default: button = 0; break; }; return button; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "niash-backend: exit"); niash_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/niash.h0000644000175000017500000000172610374656614017610 0ustar pdmpdm// niash.h: Niash device backend // This file is part of scanbuttond. // This file is part of scanbuttond. // Copyleft )c( 2005 by Bernhard Stiftner // Copyleft )c( 2005 by Dirk Wriedt // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __NIASH_H_INCLUDED #define __NIASH_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/plustek.c0000644000175000017500000002211510563732105020151 0ustar pdmpdm// plustek.c: Plustek device backend // This file is part of scanbuttond. // Copyleft )c( 2005 by Hans Verkuil // Copyleft )c( 2005-2007 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "plustek.h" static char* backend_name = "Plustek USB"; #define NUM_SUPPORTED_USB_DEVICES 9 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x04a9, 0x2207, 1 }, // CanoScan N1220U { 0x04a9, 0x2208, 1 }, // CanoScan CanoScan D660U { 0x04a9, 0x2206, 1 }, // CanoScan N650U { 0x04a9, 0x220d, 3 }, // CanoScan LiDE 20 { 0x04a9, 0x2220, 3 }, // CanoScan LiDE 25 { 0x04a9, 0x220e, 3 }, // CanoScan LiDE 30 { 0x04b8, 0x011d, 4 }, // Epson Perfection 1260 { 0x03f0, 0x0605, 2 }, // HP ScanJet 2200c (maybe only 1 button?) { 0x0458, 0x2007, 5 } // Genius (KYE) ColorPage-HR6 V2 (5 buttons) }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Canon", "CanoScan N1220U" }, { "Canon", "CanoScan D660U" }, { "Canon", "CanoScan N650U" }, { "Canon", "CanoScan LiDE 20" }, { "Canon", "CanoScan LiDE 25" }, { "Canon", "CanoScan LiDE 30" }, { "Epson", "Perfection 1260" }, { "Hewlett-Packard", "ScanJet 2200c" }, { "Genius (KYE)", "ColorPage-HR6 V2" } }; static libusb_handle_t* libusb_handle; static scanner_t* plustek_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int plustek_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void plustek_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "plustek:libusb:"; int index = plustek_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = plustek_scanners; plustek_scanners = scanner; } void plustek_detach_scanners(void) { scanner_t* next; while (plustek_scanners != NULL) { next = plustek_scanners->next; free(plustek_scanners->sane_device); free(plustek_scanners); plustek_scanners = next; } } void plustek_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = plustek_match_libusb_scanner(device); if (index >= 0) plustek_attach_libusb_scanner(device); device = device->next; } } int plustek_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); plustek_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { plustek_scanners = NULL; syslog(LOG_INFO, "plustek-backend: init"); return plustek_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t* devices; plustek_detach_scanners(); plustek_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); plustek_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return plustek_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int plustek_read(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_read((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } int plustek_write(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_write((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } void plustek_flush(scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush((libusb_device_t*)scanner->internal_dev_ptr); break; } } int scanbtnd_get_button(scanner_t* scanner) { /* Note 1: I strongly suspect that the command 0x01 0x69 0x00 0x01 will return a button bitmask. For my Canon N1220U it returns 0x04, which happens to be the bit I have to test against to see if the scanner button was pressed. However, this has to be tested on other scanners to see if this is true. UPDATE by BS: The LIDE 20 also returns 0x04, but it has three buttons! So this guess is probably wrong. (Thanks to Christian Bucher for this info) Note 2: This works on my Canon N1220U. Whether this is Canon specific or if it works for all 'plustek usb' type scanners is something I don't know. Note 3: You must have run sane-find-scanner once. Sane apparently initializes something on the scanner allowing this to work. Otherwise all you get is 0x00. Note 4: by /cbx On my CanoScan LIDE20, the default value is $62 and the bits for the buttons are as follows: Scan: $72 ==> 0x10 Copy: $6a ==> 0x08 Mail: $66 ==> 0x04 */ unsigned char bytes[4]; int num_bytes; int button = 0; bytes[0] = 1; bytes[1] = 2; bytes[2] = 0; bytes[3] = 1; if (!scanner->is_open) return -EINVAL; num_bytes = plustek_write(scanner, (void*)bytes, 4); if (num_bytes != 4) { syslog(LOG_WARNING, "plustek-backend: communication error: " "write length:%d (expected:%d)", num_bytes, 4); plustek_flush(scanner); return 0; } num_bytes = plustek_read(scanner, (void*)bytes, 1); if (num_bytes != 1) { syslog(LOG_WARNING, "plustek-backend: communication error: " "read length:%d (expected:%d)", num_bytes, 1); plustek_flush(scanner); return 0; } // by BS: This is my first attempt to get rid of the // hardcoded button bitmask. Note that I do not own any device // supported by this backend, so this code is based on guessing. // Tested on the LIDE 20, should work for 1-button devices, too. switch (scanner->num_buttons) { case 1: if ((bytes[0] & 0x04) != 0) button = 1; break; case 2: if ((bytes[0] & 0x08) != 0) button = 1; if ((bytes[0] & 0x04) != 0) button = 2; break; case 3: if ((bytes[0] & 0x10) != 0) button = 1; if ((bytes[0] & 0x08) != 0) button = 2; if ((bytes[0] & 0x04) != 0) button = 3; break; case 4: // only tested for the Epson Perfection 1260... // seems to be a bit odd compared to the other cases... if ((bytes[0] & 0x08) != 0) button = 1; if ((bytes[0] & 0x10) != 0) button = 2; if ((bytes[0] & 0x20) != 0) button = 3; if ((bytes[0] & 0x40) != 0) button = 4; break; case 5: // only tested for the Genius ColorPage-HR6 V2... // seems to be really different compared to the other cases... if ((bytes[0] & 0x04) == 0x04) button = 1; if ((bytes[0] & 0x08) == 0x08) button = 2; if ((bytes[0] & 0x10) == 0x10) button = 3; if ((bytes[0] & 0x0c) == 0x0c) button = 4; if ((bytes[0] & 0x18) == 0x18) button = 5; break; } return button; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "plustek-backend: exit"); plustek_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/plustek.h0000644000175000017500000000167210374656614020175 0ustar pdmpdm// plustek.h: Plustek device backend // This file is part of scanbuttond. // Copyleft )c( 2005 by Hans Verkuil // Copyleft )c( 2005 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __PLUSTEK_H_INCLUDED #define __PLUSTEK_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/plustek_umax.c0000644000175000017500000001564110563732105021211 0ustar pdmpdm// plustek_umax.c: Plustek device backend for UMAX models // This file is part of scanbuttond. // Copyleft )c( 2005 by Hans Verkuil // Copyleft )c( 2005-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "plustek_umax.h" static char* backend_name = "Plustek USB for UMAX"; #define NUM_SUPPORTED_USB_DEVICES 1 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { // vendor, product, num_buttons { 0x1606, 0x0060, 4 } // UMAX Astra 3400 (3450?) }; static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "UMAX", "Astra 3400/3450" } }; static libusb_handle_t* libusb_handle; static scanner_t* plustek_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int plustek_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void plustek_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "plustek:libusb:"; int index = plustek_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = plustek_scanners; plustek_scanners = scanner; } void plustek_detach_scanners(void) { scanner_t* next; while (plustek_scanners != NULL) { next = plustek_scanners->next; free(plustek_scanners->sane_device); free(plustek_scanners); plustek_scanners = next; } } void plustek_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = plustek_match_libusb_scanner(device); if (index >= 0) plustek_attach_libusb_scanner(device); device = device->next; } } int plustek_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); plustek_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { plustek_scanners = NULL; syslog(LOG_INFO, "plustek-umax-backend: init"); return plustek_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t* devices; plustek_detach_scanners(); plustek_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); plustek_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return plustek_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int plustek_read(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_read((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } int plustek_write(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_write((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } void plustek_flush(scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush((libusb_device_t*)scanner->internal_dev_ptr); break; } } int scanbtnd_get_button(scanner_t* scanner) { unsigned char bytes[4]; int num_bytes; int button = 0; bytes[0] = 1; bytes[1] = 2; bytes[2] = 0; bytes[3] = 1; if (!scanner->is_open) return -EINVAL; num_bytes = plustek_write(scanner, (void*)bytes, 4); if (num_bytes != 4) { syslog(LOG_WARNING, "plustek_umax-backend: communication error: " "write length:%d (expected:%d)", num_bytes, 4); plustek_flush(scanner); return 0; } num_bytes = plustek_read(scanner, (void*)bytes, 1); if (num_bytes != 1) { syslog(LOG_WARNING, "plustek_umax-backend: communication error: " "read length:%d (expected:%d)", num_bytes, 1); plustek_flush(scanner); return 0; } switch (scanner->num_buttons) { case 1: // not tested if ((bytes[0] & 0x04) != 0) button = 1; break; case 2: // not tested if ((bytes[0] & 0x08) != 0) button = 1; if ((bytes[0] & 0x04) != 0) button = 2; break; case 3: // not tested if ((bytes[0] & 0x10) != 0) button = 1; if ((bytes[0] & 0x08) != 0) button = 2; if ((bytes[0] & 0x04) != 0) button = 3; break; case 4: // only tested on UMAX Astra 3400 if ((bytes[0] & 0x04) != 0) button = 1; if ((bytes[0] & 0x08) != 0) button = 2; if ((bytes[0] & 0x40) != 0) button = 3; if ((bytes[0] & 0x20) != 0) button = 4; break; } return button; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "plustek-umax-backend: exit"); plustek_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/plustek_umax.h0000644000175000017500000000173110374656614021223 0ustar pdmpdm// plustek_umax.h: Plustek device backend for UMAX models // This file is part of scanbuttond. // Copyleft )c( 2005 by Hans Verkuil // Copyleft )c( 2005 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __PLUSTEK_UMAX_H_INCLUDED #define __PLUSTEK_UMAX_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/backends/snapscan.c0000644000175000017500000001711210563732105020271 0ustar pdmpdm// snapscan.c: Snapscan device backend // This file is part of scanbuttond. // Copyleft )c( 2005-2006 by Bernhard Stiftner // Thanks to J. Javier Maestro for sniffing the button codes ;-) // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include "scanbuttond/scanbuttond.h" #include "scanbuttond/libusbi.h" #include "snapscan.h" static char* backend_name = "Snapscan USB"; #define NUM_SUPPORTED_USB_DEVICES 4 static int supported_usb_devices[NUM_SUPPORTED_USB_DEVICES][3] = { { 0x04b8, 0x0121, 4 }, // Epson Perfection 2480 { 0x04b8, 0x011f, 4 }, // Epson Perfection 1670 { 0x04b8, 0x0122, 4 }, // Epson Perfection 3490 { 0x04b8, 0x0120, 4 } // Epson Perfection 1270 }; // TODO: check if this backend really works on the Epson 2580 too... static char* usb_device_descriptions[NUM_SUPPORTED_USB_DEVICES][2] = { { "Epson", "Perfection 2480 / 2580" }, { "Epson", "Perfection 1670" }, { "Epson", "Perfection 3490 / 3590" }, { "Epson", "Perfection 1270" } }; static libusb_handle_t* libusb_handle; static scanner_t* snapscan_scanners = NULL; // returns -1 if the scanner is unsupported, or the index of the // corresponding vendor-product pair in the supported_usb_devices array. int snapscan_match_libusb_scanner(libusb_device_t* device) { int index; for (index = 0; index < NUM_SUPPORTED_USB_DEVICES; index++) { if (supported_usb_devices[index][0] == device->vendorID && supported_usb_devices[index][1] == device->productID) { break; } } if (index >= NUM_SUPPORTED_USB_DEVICES) return -1; return index; } void snapscan_attach_libusb_scanner(libusb_device_t* device) { const char* descriptor_prefix = "snapscan:libusb:"; int index = snapscan_match_libusb_scanner(device); if (index < 0) return; // unsupported scanner_t* scanner = (scanner_t*)malloc(sizeof(scanner_t)); scanner->vendor = usb_device_descriptions[index][0]; scanner->product = usb_device_descriptions[index][1]; scanner->connection = CONNECTION_LIBUSB; scanner->internal_dev_ptr = (void*)device; scanner->lastbutton = 0; scanner->sane_device = (char*)malloc(strlen(device->location) + strlen(descriptor_prefix) + 1); strcpy(scanner->sane_device, descriptor_prefix); strcat(scanner->sane_device, device->location); scanner->num_buttons = supported_usb_devices[index][2]; scanner->is_open = 0; scanner->next = snapscan_scanners; snapscan_scanners = scanner; } void snapscan_detach_scanners(void) { scanner_t* next; while (snapscan_scanners != NULL) { next = snapscan_scanners->next; free(snapscan_scanners->sane_device); free(snapscan_scanners); snapscan_scanners = next; } } void snapscan_scan_devices(libusb_device_t* devices) { int index; libusb_device_t* device = devices; while (device != NULL) { index = snapscan_match_libusb_scanner(device); if (index >= 0) snapscan_attach_libusb_scanner(device); device = device->next; } } int snapscan_init_libusb(void) { libusb_device_t* devices; libusb_handle = libusb_init(); devices = libusb_get_devices(libusb_handle); snapscan_scan_devices(devices); return 0; } const char* scanbtnd_get_backend_name(void) { return backend_name; } int scanbtnd_init(void) { snapscan_scanners = NULL; syslog(LOG_INFO, "snapscan-backend: init"); return snapscan_init_libusb(); } int scanbtnd_rescan(void) { libusb_device_t* devices; snapscan_detach_scanners(); snapscan_scanners = NULL; libusb_rescan(libusb_handle); devices = libusb_get_devices(libusb_handle); snapscan_scan_devices(devices); return 0; } const scanner_t* scanbtnd_get_supported_devices(void) { return snapscan_scanners; } int scanbtnd_open(scanner_t* scanner) { int result = -ENOSYS; if (scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: // if devices have been added/removed, return -ENODEV to // make scanbuttond update its device list if (libusb_get_changed_device_count() != 0) return -ENODEV; result = libusb_open((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 1; return result; } int scanbtnd_close(scanner_t* scanner) { int result = -ENOSYS; if (!scanner->is_open) return -EINVAL; switch (scanner->connection) { case CONNECTION_LIBUSB: result = libusb_close((libusb_device_t*)scanner->internal_dev_ptr); break; } if (result == 0) scanner->is_open = 0; return result; } int snapscan_read(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_read((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } int snapscan_write(scanner_t* scanner, void* buffer, int bytecount) { switch (scanner->connection) { case CONNECTION_LIBUSB: return libusb_write((libusb_device_t*)scanner->internal_dev_ptr, buffer, bytecount); break; } return -1; } void snapscan_flush(scanner_t* scanner) { switch (scanner->connection) { case CONNECTION_LIBUSB: libusb_flush((libusb_device_t*)scanner->internal_dev_ptr); break; } } int scanbtnd_get_button(scanner_t* scanner) { unsigned char bytes[20]; int num_bytes; int button = 0; bytes[0] = 0x03; bytes[1] = 0x00; bytes[2] = 0x00; bytes[3] = 0x00; bytes[4] = 0x14; bytes[5] = 0x00; if (!scanner->is_open) return -EINVAL; num_bytes = snapscan_write(scanner, (void*)bytes, 6); if (num_bytes != 6) { syslog(LOG_WARNING, "snapscan-backend: communication error: " "write length:%d (expected:%d)", num_bytes, 6); snapscan_flush(scanner); return 0; } num_bytes = snapscan_read(scanner, (void*)bytes, 8); if (num_bytes != 8 || bytes[0] != 0xF9) { syslog(LOG_WARNING, "snapscan-backend: communication error: " "read length:%d (expected:%d), " "byte[0]:%x (expected:%x)", num_bytes, 8, bytes[0], 0xF9); snapscan_flush(scanner); return 0; } num_bytes = snapscan_read(scanner, (void*)bytes, 20); if (num_bytes != 20 || bytes[0] != 0xF0) { syslog(LOG_WARNING, "snapscan-backend: communication error: " "read length:%d (expected:%d), " "byte[0]:%x (expected:%x)", num_bytes, 20, bytes[0], 0xF0); snapscan_flush(scanner); return 0; } if (bytes[2] == 0x06) { switch (bytes[18] & 0xF0) { case 0x10: button = 1; break; case 0x20: button = 2; break; case 0x40: button = 3; break; case 0x80: button = 4; break; default: button = 0; break; } } num_bytes = snapscan_read(scanner, (void*)bytes, 8); if (num_bytes != 8 || bytes[0] != 0xFB) { syslog(LOG_WARNING, "snapscan-backend: communication error: " "read length:%d (expected:%d), " "byte[0]:%x (expected:%x)", num_bytes, 8, bytes[0], 0xFB); snapscan_flush(scanner); return 0; } return button; } const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner) { return scanner->sane_device; } int scanbtnd_exit(void) { syslog(LOG_INFO, "snapscan-backend: exit"); snapscan_detach_scanners(); libusb_exit(libusb_handle); return 0; } scanbuttond-0.2.3.cvs20090713.orig/backends/snapscan.h0000644000175000017500000000173210374656614020311 0ustar pdmpdm// snapscan.h: Snapscan device backend // This file is part of scanbuttond. // Copyleft )c( 2005 by Bernhard Stiftner // Thanks to J. Javier Maestro for sniffing the button codes ;-) // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __SNAPSCAN_H_INCLUDED #define __SNAPSCAN_H_INCLUDED #include "scanbuttond/backend.h" #endif scanbuttond-0.2.3.cvs20090713.orig/architecture.fig0000644000175000017500000000713610321053372017715 0ustar pdmpdm#FIG 3.2 Landscape Center Inches A4 223.00 Single -2 1200 2 6 3600 5550 5100 6000 6 3600 5550 5100 6000 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 9 3600 5700 4200 5700 4200 5550 4500 5550 4500 5700 5100 5700 5100 6000 3600 6000 3600 5700 -6 4 1 0 50 -1 0 12 0.0000 4 135 930 4350 5925 scanbuttond\001 -6 6 5400 5550 6900 6000 6 5400 5550 6900 6000 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 9 5400 5700 6000 5700 6000 5550 6300 5550 6300 5700 6900 5700 6900 6000 5400 6000 5400 5700 -6 4 1 0 50 -1 0 12 0.0000 4 135 930 6150 5925 kscanbutton\001 -6 6 3750 3300 4650 3750 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 8 3750 3750 3750 3300 4650 3300 4650 3750 4350 3750 4200 3600 4050 3750 3750 3750 4 1 0 50 -1 0 12 0.0000 4 135 450 4200 3525 epson\001 -6 6 4350 4350 6150 4950 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 12 4350 4500 5100 4500 5250 4350 5400 4500 6150 4500 6150 4950 5400 4950 5400 4800 5100 4800 5100 4950 4350 4950 4350 4500 4 1 0 50 -1 0 12 0.0000 4 135 1380 5250 4725 scanbutton-server\001 -6 6 5850 3150 6750 3750 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 12 5850 3750 5850 3300 6150 3300 6150 3150 6450 3150 6450 3300 6750 3300 6750 3750 6450 3750 6300 3600 6150 3750 5850 3750 4 1 0 50 -1 0 12 0.0000 4 180 375 6300 3525 relay\001 -6 6 4275 2100 5175 2550 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 8 4275 2100 5175 2100 5175 2550 4875 2550 4725 2400 4575 2550 4275 2550 4275 2100 4 1 0 50 -1 0 12 0.0000 4 180 870 4725 2325 (backend1)\001 -6 6 5325 2100 6225 2550 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 8 5325 2100 6225 2100 6225 2550 5925 2550 5775 2400 5625 2550 5325 2550 5325 2100 4 1 0 50 -1 0 12 0.0000 4 180 870 5775 2325 (backend2)\001 -6 6 4800 3150 5700 3750 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 13 4800 3750 4800 3300 4950 3300 5100 3150 5250 3300 5400 3150 5550 3300 5700 3300 5700 3750 5400 3750 5250 3600 5100 3750 4800 3750 4 1 0 50 -1 0 12 0.0000 4 105 375 5250 3525 meta\001 -6 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 3600 5250 8700 5250 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 3600 4050 8700 4050 2 2 0 1 7 7 40 -1 20 0.000 0 0 -1 0 0 5 4950 5250 5550 5250 5550 5325 4950 5325 4950 5250 2 2 0 1 7 7 40 -1 20 0.000 0 0 -1 0 0 5 4800 4050 5700 4050 5700 4125 4800 4125 4800 4050 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 4 1 1 1.00 60.00 120.00 4350 5475 4350 5325 5100 5325 5100 5025 0.000 1.000 1.000 0.000 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 4 1 1 1.00 60.00 120.00 5400 3075 5400 2850 5775 2850 5775 2625 0.000 1.000 1.000 0.000 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 4 1 1 1.00 60.00 120.00 5100 3075 5100 2850 4725 2850 4725 2625 0.000 1.000 1.000 0.000 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 6 1 1 1.00 60.00 120.00 6300 3075 6300 2850 7050 2850 7050 5100 5550 5250 5400 5025 0.000 1.000 1.000 1.000 1.000 0.000 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 4 1 1 1.00 60.00 120.00 6150 5475 6150 5325 5250 5325 5250 5025 0.000 1.000 1.000 0.000 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 4 1 1 1.00 60.00 120.00 5100 4275 5100 4050 4200 4050 4200 3825 0.000 1.000 1.000 0.000 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 2 1 1 1.00 60.00 120.00 5250 4275 5250 3825 0.000 0.000 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 4 1 1 1.00 60.00 120.00 5400 4275 5400 4050 6300 4050 6300 3825 0.000 1.000 1.000 0.000 4 0 0 50 -1 0 12 0.0000 4 90 480 7650 4725 server\001 4 0 0 50 -1 0 12 0.0000 4 135 720 7650 3525 backends\001 4 0 0 50 -1 0 12 0.0000 4 135 720 7650 5925 frontends\001 4 1 0 50 -1 0 6 0.0000 4 75 585 7125 2925 network / socket\001 4 1 0 40 -1 0 6 0.0000 4 90 810 5250 4125 dynamic loading/linking\001 4 1 0 40 -1 0 6 0.0000 4 75 555 5250 5325 network/socket\001 4 1 0 50 -1 0 6 0.0000 4 90 810 5250 2775 dynamic loading/linking\001 scanbuttond-0.2.3.cvs20090713.orig/architecture.png0000644000175000017500000003025410321053372017731 0ustar pdmpdm‰PNG  IHDRúGn)e) pHYs M MÒέNtEXtSoftwareESP Ghostscript 7.07¦¼ž§ IDATxœíÝݺ›,»Pó^=ÿSÎÚȪŸEETTxc§‰?DTî šÏ÷ûâúótúóù|ž.ÿ8ÙÕiƒ|*wŽp"nG­¤¢N›"€uý÷t®%îÁ‰;@p✸'îÁ‰;@p✸'îÁ‰;@p✸'îÁýyºa}>Ÿa¾ßïøÿñÏ{V}ÛêΔdº•’×/üœ:Í—d|kq‚6ëx ½;—Xlï\uû>ŸO¦¨ßï·µ¢Nóæ…œ§Ÿ.>’¸S_Òcñý~ïüR{óêò2:›ålªuT§£Å’ŒÛ')ªÄ4BܹD;S›Ê·O;­£:]3¯ùmÕNï!îTæT^Ñ#WŽæ/@ÖO#u ¼¸SÓÚÀ[ú¥N7Ù8@ûÜ™u·üÝ+ó §)YNá2ó«KnÙNœ¿Ùª–.F{¨Ó]º¨S q§š’3øâÝ+ó¦(i·§I&Ëßå;60ó{ƒ7W7Ÿ²p²ÅÏ{ÌS÷0«Óµžç¾tàN.fU¶yß¼{¥pi%]É[ùvqXjÒß-ˆNŒöL¨S¦ˆ;·:[‘ߟå-Ö›³¿¶yS§‡—p³ž4İøe½pQ‹¯o¶XFQÔ¥N[(@BÜiÑô¡mgZŽÍK!ƒ¯àwyO¾¶Ÿh™‹YÍ©ØZT^Ê1ï©SYh“¸Ó–’_W]Ùu“3½§Ne YâNe]§83{¾? üÅ3eèš:-ŸLÖÚ$îTsàDŸ¹—xs-Éd›ä‘åuºku‹›ë÷¡K×°ÉPå[M­–o!_É7¢%¤›`:föüe‘ÅU$Ë?œZ¦N× ¿¶êöëˆÇƒMwË? vWƒ—¬Üwýÿ™–¬°-)ÿ±ønùÚ§­ïvq(ÈIUΫNÏÔéfñ6Ÿ…8W¥ZFÎ)»n9 ñ¸Ãâp?cw*sŽ®¨‘œñx"i¤N·wê;ù9~šjÕiMÕ)ð*âÎ%´Ž'5Ø.ªÓ“¬Sà=Ä«hOj°]T§'5X§ÀKˆ;rr?¬ÙM×lÁÚgÓw€àÄ 8qNÜ‚w^Ê7Æ£NÖˆ;o´ö+’ôKdˆ;¯“4‡ZÇÔ)@ž¸ó.Óß²^ûmú¢N6‰;/2m“ÿh;¥NJˆ;o1o“?µŽÝQ§…ÄWXk“µŽQ§åÄøòíbò–Ö± ê`q'¸’v1™@ëØ8u °—¸Yy»˜L¦ul–:8@Ü ko»˜L¬ul:8F܉éX»˜Ì¢ulŠ:8LÜ èL»˜Ì¨ul„:8C܉æ|»˜Ì®u|œ:8IÜ ¥V»˜,Dëø u pž¸GÝv1Y”Öñê  q'ˆ+ÚÅdZÇ›©S€ZÄ®k“Åjo£N*wºwu»˜,\ëxu P—¸Ó·{ÚÅdZÇK©S€êÄŽÝÙ.&+Ò:^D\AÜéÕýíb²:­cuêà"âN—žj“•j+R§×ù€M✸'î¼ÎâµD:¥6Jˆ;”ºç( Wq¸$ÓOqf!ÓÙ7—#”ËùÏ[¾„’n³Å)%$€9qç]îéc˜Y™þgq(ÌüÅdÕ‹)-3Y2fíS,fšÅÿ/nºÌ›µ– ´¶ÝÖÖ¾¸–Ç/Û4ÈxF†a«ƒ'3Wøý'“·ZXû±Šxcw8(vÖ™æŒû?fáÚe€B‘[,vÙÕv¾¡¡}öÆ®’ëhkowø-h/ž½ÄÐq‡hGÛ§ŽöwHiM›¥jŽwXÐÔóˆÔÀ9â9ù¼äR6>@-âE4½·ñä@€êÄöY|X°½èŒÍ_hà$q‡ã´ÓÇØn7w¨É…˜5zÅ$îp ¶@;Äîðª‘ίú°„Tò‹xU~5/öOïÑ”?O€WÏh¿(ò)2RNÖ:á6½¼~ź#îp«$÷ !Λ!Ó[Tç/2Î#û®Ù¯àPZõsq3q‡gLsO¿?M*èô¢â úéŒÓÔ~r±yót•ì{ÓöûóW’éÁ•¼8-ðï­y°(?6Ë3]Åâzç+Ê®ÍbÀq‡‡MÏh}Îü‚Uû®¾Up}®k˜ç¡! 4…GP€¦sÍ#Èâ×^_L'ã*’3 <ö¹ ï¿§ Ã÷û]< ¶l<;7+é'¸º²¦ËÿüuѺÆT±xem:ÍôÏy¬Él…ÿ­â·ÌÅU,¾8]QÉç‚côîЊß׸.¾ÉéZo܃o‹£ò/*Ff±ÉU¡¹!YBáôUVäÈâ zwhH}<F:Þæ=÷—aÚÝ’¼^¾„Åe.Nœ|ä’¥(#îÀ¾€¶©µŽ·ê¡g>,f­'ÙÉ…¤qÞ|@ɼ>Ÿl,Ìâ*ÖÊ<]BÉç‚c:¸pÀÛ´ÖbMµ\6¯/±zw€ÚïxüÚ¼™¸CsÁã«y˯ÍÑ-ÀEÄ(¥}jVã—±ÜOÜúÖWÖù™>kJèˆ;´¨¯¦ ŽÑÍ·whWƒm€Öš»v¦$¸‡¸E´F\Dâˆ;@ßúíÚIV_/¬å~ä«Ü¤k³çûxª´zå3FjûŽ;án˜]}—žçÇ:ê´ 8Ü«z~ˆ(lÊܾf-»TâãdU¨Ë¡ÊÃÒø©é[ÉÄŸÙCçûkþy ÉS¡döÞC¦/.¾¢ÞOšoí]••Yìâ+±%Â¥ Oû…û^ù¾=Ÿ•§ež¿Ôµ¸ŠÅQÉîÉú©ö1Ù"%ÍØ|®’l¾¹¨Â žºþZ¥:žÝËçõ²x×ÃÚ‹‹ ÉŸªçš×ãSÛ¤ë:=p$n§‡ë«©ØzO4õ‘{‘Ùå§Éì{™}»°o¦ðœ¶·š¿•œ ÛÇ.ôw6½ö ïºid‘:­¥© îÀ=º»@ž âð"ÆuÂ;õ:T Pk0î§wxYÞ)lïÎôûÜüÖà…^~hjŒ6Ü,lÜqT?΀‹Y@p✸'îÁ…ª|ŒG­Ç£Nãq¯%°—ÞÿYû±Yú¥NãY|Æ›DC^NÜùc@æg`é‹:'©ÓAµeÄa˜]ïÐ: NãY¬ÓAµÄå±ZÇ®©Óx2u:¨V`ËÛãNf«Ö±Sê4žÍ:Tk[‰×zuÜÙ¼gGëØuOaªX÷Þ¸Sx²Ö±#ê4ž]u:¨V`ÅKãήg±h» Nã9P§ƒj–¼1îxîœÖ±qê4žÃu:¨V`æuqçð3vµŽÍR§ñœ¬ÓAµÿzWÜ9ù{ZÇ©ÓxªÔé Z‰Å*¿¤ulŠ:§bªøë-q§âïDj¡Nã©^§ƒj†axIÜ©þ›ØZÇÇ©Óx.ªÓAµoˆ;ÕÏ¡?ZÇ©Óx.­ÓAµÂë;C´ŽP§ñÜP§ƒj…w‹w.=‡þho¦Nã¹­N‡×Wë¥6îÜpýÑ:ÞFÆssªÞ*fܹíú£u¼:ç‘:T+¼RÀ¸só9ôGëx)uσu:¨VxŸhqç‘sèÖñ"ê4žÇëtP­ð2ŸZgœvÎÏÇ‹´"}–3"m‡HŸåŒv¶Ãpï¦ø|ªó¡/v}€·wx­h³âœ¸'îÁ‰;@p✸'îÁ‰;@p✸“jêÇt¨B¼œ¸Cp²N<êØKÜYàd s»ˆ;@OàqçΤQ©Y€7w–icPÁ¨PàqNÜYå{$4Å! &îðK€×wr4]S}‘¨Mà qNÜÙà;%<Îaœ$îð"ZM€ww¶i#{¤ÖÂP•µØ’¼™¸'îñ­áЪwxÍ'À ‰;¥4“QY1¨G qNÜ‚wr¾ýþÔµƒzìKrðq)4¶‘¶Xw>ûygnWømU›”wÒ»SJÜCÖªwvxàj²p…?O 3¿SðçóÑ- u :ÀuÄ#¾ßïïÔì '%}¥%à âÎAc7ÏïO¹v™_vì×wN™æ™žÄ¾ajqЛÃäN¶6¯%îÔ1=‰,FŸÁ‰†÷YÔïXn&îÔ—œÊ×ÒÏâÄЩüíŠösàYâÎåOôù ´6TÉXhú<…ÍÇÅ·Z8¬y«ý3çZn.FÈmÛø[6àà'B_ÂwúÔ#‡y0 Ù‘x3³Ø°xŠ,oþyèä-E›«˜ÿ'Yéã'ú†=°FïÇ•4áù.œ‹TYiÝ¡Ù{—vÏÀp€—лÆü¥ŸK{MvÝ!_eQÉ,ß¿¦¯ì]αbÌׇ‰Î î3³«©NþœŽ¡™¾;ª’¼¸¹êÅɦÑd>g¾¨ù’“’ä?ûbù×^Yû¤™?÷nyÉqoE;aýžµF2Z^HïÕÊ:7t`»’õûOþrÒE…/\;… U戺cx‡ï!oÁÚ öS×u½”¬€râG\Ô·–x2ï^}™©í€‹Y4¡ÓÖ½ÓbóBöU^NÜ¡÷?žç0?ú"îÐŽôƒ¸{éÚ莸C[tðP¸;èÚ葸Cs„ êwhTƒ×³títJÜNFq‡5{vn¶`dˆ;´«©ëYM ÙoáGÜ‚wh”ËFÔ"îд¦ºâ%0€N‰;°­©ÔÀ^â@dz%aw€ðÄÚÕÔ·Ò¦ %\„…‘¸÷ñ $¿ò#½;aÉ:ð#îÁ‰;§ S✸'îÁ‰;1¹- Fâ@4Æ)CBÜ‚wîóùø¦ ðrâ‘AGâx3q‡°’ˆ#ñð*Æ)Ô¸CLc¸ù~¿ãy_âá ìç0'îÐ4ë$ÿѼ¸C4ó¬“ü)ñ¼¸C(kY'yQâ!6w !îG>ë$oI<„ddžEâA”dd ÀKˆ;DPžu’É$€7wèÞÞ¬“L,ñŒ;0'îзcY'™Eâ!{2¬wèØ™¬“̨LÜ¡Wç³N2»Ä•¸C—jed!½3p‰;ô§nÖI%ñÐ)».dˆ;t抬“,P³Œ¸CO®Ë:Éb%€HĺquÖI.ñБßîjà¬wèÃ=Y'Y…ă¸CîÌ:ÉŠ$€ÄZwÖIV'ñÐW² CÜ¡iOed¥-³¦?O §žêüÚúý~ªZ+ÒÜLܹ„³y$j³.Áñ öRÈs1  câ#”w€àÄ€¾¹’›Ä€^¹’…Ä 8q c®dA q K®dA9qNÜèϯkÇ•,($îÁ‰;@pâ@g\É‚½Ä 8q 'ºvà€?O€PÆ8н;Tã¡g´IÜ¡šï÷«S.åJ#îе~#ýI”wh¬?ºvà0qÎYA$]óï{'H¦In¹šN¼ö]3³ÆÅÙç/N_™`íõ’Uû,å WŸ`^°µ¹6·dùZô4N×ÎÍËÁˆ;Ý›ïâɲ8Áçó™çƒd É4ó)7'K^'[<¬…ùY~íõµÏ²XÂòÏR¨°"Ö6òZ­ ÙsÙþ’ÅX ðãXÉŬ 6é’D’™xž66Wúý«dµä³Ñô•äÿµ¾åûºW=¾5}e×mnkçǺkáAºvîçXFÜ b­9_I‹k~ËÁ¸˜Ç® 1‹hº¨jÅú»üûZ¯½|®$b–G®c¥Ê§IÝÚÁèÚyŠc9q§{Ó¶üäiqÚGê0Û+Sµ†~W†i×] ¼œc9$q'‚dxʱñ¶¾AÎíÝU*¢ÄuK¦5ÌG8–ã1v'ŽÌ àÍ®šH#Ýï—Ú;uѺbT´Ã±‰¸Ó½d<]ùq’ôÖrRIE,nê]ÛÞ©~ÅZh„®G8–Cw‚[;¢æÌ¥‡Pæ¬]q½å7Ž>¨âÓ22ŸÈ39àjŽå¾»AáÕßä8)¹ àpP˜is!%ë]ûŒó[>ŸÏ®µW”©ˆùàÇé[åËIuÝZx\S1ýmËñØFõݼç--ùËóA'£7,“ói†lßlÉÍœÉ2‡"­}®]Ÿw×g)w²"JfO&.¼EöðZ.âÔ\HÜyŠc9$çúœÍ!ÃRBÖºŒÝ‚wÚ¢kªw"ëÀÄ 8q ºvà"â@½;—ð»Çñ¨SÉ:Ð…CàA:âbÀn²ôEÜØGÖî»PJÐNéÝ("ë@¿ôîlt wzwrd@ïÀ2AÂwRÓ§JÊ:€¸ð:±;4­‘Ÿnh¤\íóùŒ¿j.ë@$âñ+ßïwl iZ¿‚Äãbì0~õº Tc˜¼Ÿ¥]U²EůìÚÅ`T(¼‡ÞZ÷ù´ÊuótMзwhTƒe~#x¦¯=Ýtà Uæ-ªä§Å²ÁdÆ\2YÖWÑ»èæiVFÕ¼S‹£" buEk—ïÎqL5BÐFzw 2==3@Hˆ;°Û|Ìò\›7”Ŧ;XãŒLsæIâð^ºJjíó%#”_7r€Mzwè@§=%=–¹#c1ž¸C[n¸©»Vx*¹¤Åtç{‰;pc–+Ò—œ!îÀq‹Ýwx6€ëˆ;\åp/H€î“ ’?O€86Ûød‚ùÏ8|¿ßߟã}cOÌôNߋɌã*¦sM×›Ã?]õ|ó“Åæ?B~›pq‡SÖ"ÎZ3Ÿ‰󈳹ÞqÆd–$ëdþ\L'ã““Ì׸ë#pq‡2ý7ÇZ÷iÔVFÕ,æ•é‹IÿJa“…¯-púââbK>B2—$p3q‡›)¡nƒYZeöމÉ$¡ñÝãlæ‹ÝµAæk€.%î¼Úͱæ°dOòâ®Ù“Y¦‹-é[*|kÑâПùÿ g œ¸߮ދ{ÚÔéeiÿJ2âx:MRµ‡=©e>Ä8Y`f-ÓÅn~„E™w«¬‘µÜ·žIDAT°¥"€9*ûvàâÎE%áfÇîu·ï$ît ¼aS›$b€AÜiaÜÌe2 ß_a‘à)✸s W² âNe:ê!Ãõ,à~"N'îÁ‰;@p✸'îÁ‰;@p✸÷çé´¥Ÿòñã´É1ôHÜIµpm§E9Çг€àÄ 8qNÜ‚w€àÄ 8qNÜ‚w€àÄ 8qNÜ‚w€àÄ 8qNÜ‚w€àÄ 8qNÜ‚û3 Ãçóyº¤TÊèûý>]ÕÑ"•2jáÆýùýãhiŠêµÓ¤©”¦¨ŽQ;Ç´ÌÅ, 8qNÜ‚w€àÄ 8qNÜ‚w€àÄ 8qNÜ‚w€àÄ 8qrüì|ž.@Æýûý>[’ë¼á3FÒi}uZl^kšr~ÿ¿ë>HÅ B=­étŸì´Ø¼ÜØêÛ{çbÖ†ï÷/äνá3†Ñé>Ùi±y­$ß¼dï ü1ÅÇ,~Wðör(qû£€Ý¸"qçNÐP…C‰¨ìÆu‰;@pMUÞ¼tºw‚dšdútâµNËÌgŸ¿8ê¿¶Š¤ ù{þ³ÐµÂ]}þÖ± Ö–ÿÎC‰H’ÝcmÇKvòíd[Ü·3«X{·p.l zÌôù~¿ŸÏ§µrÏ+8)äâÃR•Ïw µ‘öå»ï|®µ•–-óbæ³l`™[ 77N#Ù9)ÆÔ®jp(e?Ë™Céq îœ1ä÷_Ó9ýsq®3;ØÚn\ñx,YÚÚ*ºÛëš¾˜µ¹5K¾ƒf&ž¾2þ?¿Òï_%k¬e¾Óç3ûægY[ ýÊ?Ä¡4]EÅC‰W™î±¿ö~3gWßÁ2gïŤ’_Å®¶ ÷£ é¸³¶‹,žÙ«Â¹Éùf,ߥy`ôh³NJÇo6ÓLÓÔ–_ÅÞ¶ ÷ »MÇaç¾ùYûÒïŽÏÖw{W(Á|/œß]2Ÿfȶ"%ÏWH–¹xásóÅÅ”lüq’¼•YõƒÙ9)ÆOáygq˜¾µ¶@‡RùgiAS;g kGMÉÑ4Ÿý̶¶_±ŠñõùJ ?xã;ðÓÈÎÙH1`ÎÎ %Ú½˜P…¸'îÁ‰;@p✸'îÁ‰;@p✸÷ç÷O€_ÿ‚K9FúåÇV€àþͲ:M@IEND®B`‚‰PNG  IHDRúGn)e) pHYs M MÒέNtEXtSoftwareESP Ghostscript 7.07¦¼ž§ IDATxœíÖA À0À¿çC!YZ{nÏÌè:¿Þ²;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»ÄÙ Îîqvˆ³;@œÝâìgw€8»Ä]{(‹=bJIEND®B`‚scanbuttond-0.2.3.cvs20090713.orig/scanbuttond.c0000644000175000017500000002363210622573002017234 0ustar pdmpdm// scanbuttond.c: the actual daemon ("frontend") // This file is part of scanbuttond. // Copyleft )c( 2004-2007 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include #include #include #include #include #include "scanbuttond/config.h" #include "scanbuttond/common.h" #include "scanbuttond/scanbuttond.h" #include "scanbuttond/loader.h" #define DEF_BACKEND_FILENAME "libscanbtnd-backend_meta" #define DEF_BUTTONPRESSED_SCRIPT STRINGIFY(CFG_DIR) "/buttonpressed.sh" #define DEF_INITSCANNER_SCRIPT STRINGIFY(CFG_DIR) "/initscanner.sh" #define DEF_POLL_DELAY 333000L #define MIN_POLL_DELAY 1000L #define DEF_RETRY_DELAY 2000000L #define MIN_RETRY_DELAY 10000L #define BUF_SIZE 256 static char* connection_names[NUM_CONNECTIONS] = { "none", "libusb" }; static struct option const long_opts[] = { {"foreground", no_argument, NULL, 'f'}, {"backend", required_argument, NULL, 'b'}, {"buttonscript", required_argument, NULL, 's'}, {"initscript", required_argument, NULL, 'S'}, {"pollingdelay", required_argument, NULL, 'p'}, {"retrydelay", required_argument, NULL, 'r'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0} }; static char* buttonpressed_script; static char* initscanner_script; static char* backend_filename; static backend_t* backend; static long poll_delay; static long retry_delay; static int daemonize; static int killed = 0; static char* path; char* scanbtnd_get_connection_name(int connection) { return connection_names[connection]; } void shutdown(void) { syslog(LOG_INFO, "shutting down..."); backend->scanbtnd_exit(); scanbtnd_unload_backend(backend); scanbtnd_loader_exit(); syslog(LOG_DEBUG, "shutdown complete"); closelog(); } // Ensures a graceful exit on SIGHUP/SIGTERM/SIGINT/SIGSEGV void sighandler(int i) { killed = 1; syslog(LOG_INFO, "received signal %d", i); shutdown(); exit(i == SIGTERM ? EXIT_SUCCESS : EXIT_FAILURE); } // Executes an external program and wait until it terminates void execute_and_wait(const char* program) { system(program); } void list_devices(scanner_t* devices) { scanner_t* dev = devices; while (dev != NULL) { syslog(LOG_INFO, "found scanner: vendor=\"%s\", product=\"%s\", connection=\"%s\", sane_name=\"%s\"", dev->vendor, dev->product, scanbtnd_get_connection_name(dev->connection), backend->scanbtnd_get_sane_device_descriptor(dev)); dev = dev->next; } } void show_version(void) { printf("This is scanbuttond, version %s\n", VERSION); printf("Copyleft )c( 2004-2006 by Bernhard Stiftner and contributors.\n"); printf("Scanbuttond comes with ABSOLUTELY NO WARRANTY!\n"); printf("This is free software, and you are welcome to redistribute it\n"); printf("under certain conditions; see the file COPYING for details.\n"); } void show_usage(void) { printf("Usage: scanbuttond [OPTION]...\n\n"); printf("Starts a script when a button on a scanner has been pressed.\n\n"); printf("Options:\n"); printf(" -f, --foreground Run in foreground instead of background\n"); printf(" -b, --backend=FILE Use the specified backend library file\n"); printf(" default: %s\n", DEF_BACKEND_FILENAME); printf(" -s, --buttonscript=SCRIPT The name of the script to be run when a button has been pressed\n"); printf(" default: %s\n", DEF_BUTTONPRESSED_SCRIPT); printf(" -S, --initscript=SCRIPT The name of the script to be run to initialize the scanners\n"); printf(" default: %s\n", DEF_INITSCANNER_SCRIPT); printf(" -p, --pollingdelay=DELAY The polling interval in microseconds, default: %ld\n", DEF_POLL_DELAY); printf(" -r, --retrydelay=DELAY The retry delay (ms), default: %ld\n", DEF_RETRY_DELAY); printf(" -h, --help Shows this screen\n"); printf(" -v, --version Shows the version\n"); } void process_options(int argc, char** argv) { int c; buttonpressed_script = NULL; initscanner_script = NULL; poll_delay = -1; retry_delay = -1; daemonize = 1; while ((c = getopt_long (argc, argv, "fb:s:S:p:r:hv", long_opts, NULL)) != -1) { switch (c) { case 'f': daemonize = 0; break; case 'b': backend_filename = optarg; break; case 's': buttonpressed_script = optarg; break; case 'S': initscanner_script = optarg; break; case 'p': poll_delay = atol(optarg); if (poll_delay < MIN_POLL_DELAY) { printf("Invalid polling delay (%ld). Must be at least %ld.\n", poll_delay, MIN_POLL_DELAY); exit(EXIT_FAILURE); } break; case 'r': retry_delay = atol(optarg); if (retry_delay < MIN_RETRY_DELAY) { printf("Invalid retry delay (%ld). Must be at least %ld.\n", retry_delay, MIN_RETRY_DELAY); exit(EXIT_FAILURE); } break; case 'h': show_usage(); exit(EXIT_SUCCESS); break; case 'v': show_version(); exit(EXIT_SUCCESS); break; } } if (backend_filename == NULL) backend_filename = DEF_BACKEND_FILENAME; if (buttonpressed_script == NULL) buttonpressed_script = DEF_BUTTONPRESSED_SCRIPT; if (initscanner_script == NULL) initscanner_script = DEF_INITSCANNER_SCRIPT; if (poll_delay == -1) poll_delay = DEF_POLL_DELAY; if (retry_delay == -1) retry_delay = DEF_RETRY_DELAY; } int main(int argc, char** argv) { int button; int result; pid_t pid, sid; scanner_t* scanners; scanner_t* scanner; process_options(argc, argv); if (scanbtnd_loader_init() != 0) { printf("Could not initialize module loader!\n"); exit(EXIT_FAILURE); } backend = scanbtnd_load_backend(backend_filename); if (!backend) { printf("Unable to load backend library \"%s\"!\n", backend_filename); scanbtnd_loader_exit(); exit(EXIT_FAILURE); } // daemonize if (daemonize) { pid = fork(); if (pid < 0) { printf("Can't fork!\n"); exit(EXIT_FAILURE); } else if (pid > 0) { exit(EXIT_SUCCESS); } } umask(0); openlog(NULL, 0, LOG_DAEMON); // create a new session for the child process if (daemonize) { sid = setsid(); if (sid < 0) { syslog(LOG_ERR, "Could not create a new SID! Terminating."); exit(EXIT_FAILURE); } } // Change the current working directory if ((chdir("/")) < 0) { syslog(LOG_WARNING, "Could not chdir to /. Hmmm, strange... "\ "Trying to continue."); } // close standard file descriptors if (daemonize) { close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); } // setup the environment char* oldpath = getenv("PATH"); char* dir = dirname(argv[0]); path = (char*)malloc(strlen(oldpath) + strlen(dir) + 1); strcpy(path, oldpath); strcat(path, ":"); strcat(path, dir); setenv("PATH", path, 1); free(path); syslog(LOG_DEBUG, "running scanner initialization script..."); execute_and_wait(initscanner_script); syslog(LOG_DEBUG, "initialization script executed."); if (backend->scanbtnd_init() != 0) { syslog(LOG_ERR, "Error initializing backend. Terminating."); exit(EXIT_FAILURE); } scanners = backend->scanbtnd_get_supported_devices(); if (scanners == NULL) { syslog(LOG_WARNING, "no known scanner found yet, " \ "waiting for device to be attached"); } list_devices(scanners); signal(SIGTERM, &sighandler); signal(SIGHUP, &sighandler); signal(SIGINT, &sighandler); signal(SIGSEGV, &sighandler); signal(SIGCHLD, SIG_IGN); syslog(LOG_INFO, "scanbuttond started"); // main loop while (killed == 0) { if (scanners == NULL) { syslog(LOG_DEBUG, "rescanning devices..."); backend->scanbtnd_rescan(); scanners = backend->scanbtnd_get_supported_devices(); if (scanners == NULL) { syslog(LOG_DEBUG, "no supported devices found. rescanning in a few seconds..."); usleep(retry_delay); continue; } syslog(LOG_DEBUG, "found supported devices. running scanner initialization script..."); execute_and_wait(initscanner_script); syslog(LOG_DEBUG, "initialization script executed."); scanners = backend->scanbtnd_get_supported_devices(); continue; } scanner = scanners; while (scanner != NULL) { result = backend->scanbtnd_open(scanner); if (result != 0) { syslog(LOG_WARNING, "scanbtnd_open failed, error code: %d", result); if (result == -ENODEV) { // device has been disconnected, force re-scan syslog(LOG_INFO, "scanbtnd_open returned -ENODEV, device rescan will be performed"); scanners = NULL; usleep(retry_delay); break; } usleep(retry_delay); break; } button = backend->scanbtnd_get_button(scanner); backend->scanbtnd_close(scanner); if ((button > 0) && (button != scanner->lastbutton)) { syslog(LOG_INFO, "button %d has been pressed.", button); scanner->lastbutton = button; char cmd[BUF_SIZE]; snprintf(cmd, BUF_SIZE, "%s %d %s", buttonpressed_script, button, backend->scanbtnd_get_sane_device_descriptor(scanner)); execute_and_wait(cmd); } if ((button == 0) && (scanner->lastbutton > 0)) { syslog(LOG_INFO, "button %d has been released.", scanner->lastbutton); scanner->lastbutton = button; } scanner = scanner->next; } usleep(poll_delay); } syslog(LOG_WARNING, "exited main loop!?!"); shutdown(); exit(EXIT_SUCCESS); } scanbuttond-0.2.3.cvs20090713.orig/contrib/0000755000175000017500000000000011226646321016204 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/contrib/Makefile.am0000644000175000017500000000003710375175621020244 0ustar pdmpdmEXTRA_DIST = initscript.gentoo scanbuttond-0.2.3.cvs20090713.orig/contrib/initscript.gentoo0000755000175000017500000000100110375175621021610 0ustar pdmpdm#!/sbin/runscript # scanbuttond init script for Gentoo # copy it to /etc/init.d/scanbuttond # # Copyright 2005 by Bernhard Stiftner # Distributed under the terms of the GNU General Public License v2 depend() { need hotplug } start() { ebegin "Starting scanner button daemon" start-stop-daemon --chuid scanner:scanner --start --quiet --exec /usr/local/bin/scanbuttond eend $? } stop() { ebegin "Stopping scanner button daemon" start-stop-daemon --stop --quiet --exec /usr/local/bin/scanbuttond eend $? } scanbuttond-0.2.3.cvs20090713.orig/doc/0000755000175000017500000000000011226646321015311 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/doc/epson.txt0000644000175000017500000000017110375164476017207 0ustar pdmpdmTechnical documentation for Epson ESC/I scanners is available at http://www.epsondevelopers.com/guides/download_guide/60 scanbuttond-0.2.3.cvs20090713.orig/doc/snapscan.txt0000644000175000017500000000275610375164476017704 0ustar pdmpdmThanks to J. Javier Maestro for reporting this: The Windows driver is CONSTANTLY doing some sort of polling,         Normal Check:         -----------------------------------------------          * PUT 0x6 bytes to the device:            03 00 00 00 14 00                     * GET 0x8 bytes from the device:            F9 00 00 00 00 00 00 00                   * GET 0x14 bytes from the device:            F0 00 00 00 00 00 00 0B            00 00 00 00 00 00 00 00            00 00 00 00                   * GET 0x8 bytes from the device:            FB 00 00 00 00 00 00 00 Now, when I press a button, the next polling, the second GET changes to one of the following, according to the button I press :=)  (the rest of the GETs remain the same)         Returning Button 1:         -----------------------------------------------         F0 00 06 00 00 00 00 0B         00 00 00 00 00 00 00 00         00 F0 10 00         Returning Button 2:         -----------------------------------------------         F0 00 06 00 00 00 00 0B         00 00 00 00 00 00 00 00         00 F0 20 00         Returning Button 3:         -----------------------------------------------         F0 00 06 00 00 00 00 0B         00 00 00 00 00 00 00 00         00 F0 40 00         Returning Button 'P': (looks like a power-on button, it has a green                                light, etc)         -----------------------------------------------         F0 00 06 00 00 00 00 0B         00 00 00 00 00 00 00 00         00 F0 80 00 scanbuttond-0.2.3.cvs20090713.orig/include/0000755000175000017500000000000011226646321016167 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/include/scanbuttond/0000755000175000017500000000000011226646321020513 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/include/scanbuttond/backend.h0000644000175000017500000001023610374656710022263 0ustar pdmpdm// backend.h: specification of the mandatory backend functions // This file is part of scanbuttond. // Copyleft )c( 2004-2005 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __BACKEND_H_INCLUDED #define __BACKEND_H_INCLUDED #include "scanbuttond/scanbuttond.h" /** * \file backend.h * \brief Backend function specification. * * This file specifies which functions a scanbuttond backend has to * provide and how it is supposed to interact with with the rest * of the system. */ /** * Gets the name of this backend. * \return the backend name */ const char* scanbtnd_get_backend_name(void); /** * Initializes the backend. * This function makes the backend ready to operate and searches for supported * devices (see scanbtnd_get_supported_devices()). * \return 0 if successful, <0 otherwise */ int scanbtnd_init(void); /** * Refreshes the list of supported devices. * After this function has been called, scanbtnd_get_supported_devices() * should only return devices which are currently present on this system. * \return 0 if successful, <0 otherwise */ int scanbtnd_rescan(void); /** * Returns a list of devices which are currently driven by this backend. * The devices are stored in a single-linked list. * Note that the device list does not automagically refresh after pluggin in or * unplugging a device. You have to explicitly call scanbtnd_rescan() to do * that. * \return a linked list of supported scanner devices */ const scanner_t* scanbtnd_get_supported_devices(void); /** * Opens the given scanner device. * This function must be called before using scanbtnd_get_button(). * After calling this function, it is usually not possible for another process * to access the scanner until scanbtnd_close() is called. * \param scanner the scanner device to be opened * \return 0 if successful, <0 otherwise * \retval -ENODEV if the device is no longer present (or the device list has to * be refreshed). In this case, call scanbtnd_rescan() and try again. * \retval -EBUSY if the device is currently used by another process. * \retval -EINVAL if the device is already open * \retval -ENOSYS if there is no connection method to communicate with the device */ int scanbtnd_open(scanner_t* scanner); /** * Closes the given scanner device. * This function must be called when you've finished querying the scanner button * status using scanbtnd_get_button(). * After calling this function, other processes may access the device again. * \param scanner the scanner device to be closed * \return 0 if successful, <0 otherwise * \retval -EINVAL if the device is already closed * \retval -ENOSYS if there is no connection method to communicate with the device */ int scanbtnd_close(scanner_t* scanner); /** * Queries the scanner's button status. * \param scanner the scanner device * \return the number of the currently pressed button, 0 if no button is currently * pressed, or <0 if there was an error. * \retval -EINVAL if the scanner device has not been opened before */ int scanbtnd_get_button(scanner_t* scanner); /** * Gets the SANE device name of this scanner. * The returned string should look like "epson:libusb:003:017". * \param scanner the scanner device * \return the SANE device name, or NULL if the SANE device name cannot be determined. */ const char* scanbtnd_get_sane_device_descriptor(scanner_t* scanner); /** * Shuts down this backend. * Cleans up some internal data structures and frees some memory. * \return 0 if successful, <0 otherwise */ int scanbtnd_exit(void); #endif scanbuttond-0.2.3.cvs20090713.orig/include/scanbuttond/common.h0000644000175000017500000000171010375164546022163 0ustar pdmpdm// common.h: useful stuff // This file is part of scanbuttond. // Copyleft )c( 2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __COMMON_H_INCLUDED #define __COMMON_H_INCLUDED #define STRINGIFY1(x) #x #define STRINGIFY(x) STRINGIFY1(x) #endif scanbuttond-0.2.3.cvs20090713.orig/include/scanbuttond/config.h.in0000644000175000017500000000324310374656710022546 0ustar pdmpdm/* include/scanbuttond/config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_USB_H /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION scanbuttond-0.2.3.cvs20090713.orig/include/scanbuttond/libusbi.h0000644000175000017500000000437710375173764022342 0ustar pdmpdm// libusbi.h: libusb wrapper // This file is part of scanbuttond. // Copyleft )c( 2004-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __LIBUSBI_H_INCLUDED #define __LIBUSBI_H_INCLUDED #include #include "scanbuttond/scanbuttond.h" struct libusb_device; typedef struct libusb_device libusb_device_t; struct libusb_device { int vendorID; int productID; char* location; // bus number + ":" + device number struct usb_device* device; struct usb_dev_handle* handle; // automatically set by libusb_open(...) int interface; int out_endpoint; int in_endpoint; libusb_device_t* next; }; struct libusb_handle; typedef struct libusb_handle libusb_handle_t; struct libusb_handle { libusb_device_t* devices; // rescanning info, timestamps??? }; libusb_handle_t* libusb_init(void); // GLOBAL number of changed devices (does not require a handle!) int libusb_get_changed_device_count(void); void libusb_rescan(libusb_handle_t* handle); libusb_device_t* libusb_get_devices(libusb_handle_t* handle); // returns 0 on success, -EBUSY if the scanner is currently in use, // or -ENODEV if the scanner does no longer exist int libusb_open(libusb_device_t* device); int libusb_close(libusb_device_t* device); int libusb_read(libusb_device_t* device, void* buffer, int bytecount); int libusb_write(libusb_device_t* device, void* buffer, int bytecount); // flush bulk read queue void libusb_flush(libusb_device_t* device); int libusb_control_msg(libusb_device_t* device, int requesttype, int request, int value, int index, void* bytes, int size); void libusb_exit(libusb_handle_t* handle); #endif scanbuttond-0.2.3.cvs20090713.orig/include/scanbuttond/loader.h0000644000175000017500000000327710422426216022137 0ustar pdmpdm// loader.h: dynamic backend library loader // This file is part of scanbuttond. // Copyleft )c( 2005-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __LOADER_H_INCLUDED #define __LOADER_H_INCLUDED #include "scanbuttond/scanbuttond.h" #ifndef MODULE_PATH_ENV # define MODULE_PATH_ENV "SCANBUTTOND_MODULE_PATH" #endif struct backend; typedef struct backend backend_t; struct backend { char* (*scanbtnd_get_backend_name)(void); int (*scanbtnd_init)(void); int (*scanbtnd_rescan)(void); scanner_t* (*scanbtnd_get_supported_devices)(void); int (*scanbtnd_open)(scanner_t* scanner); int (*scanbtnd_close)(scanner_t* scanner); int (*scanbtnd_get_button)(scanner_t* scanner); char* (*scanbtnd_get_sane_device_descriptor)(scanner_t* scanner); int (*scanbtnd_exit)(void); void* handle; // handle for dlopen/dlsym/dlclose backend_t* next; }; int scanbtnd_loader_init(void); void scanbtnd_loader_exit(void); backend_t* scanbtnd_load_backend(const char* filename); void scanbtnd_unload_backend(backend_t* backend); #endif scanbuttond-0.2.3.cvs20090713.orig/include/scanbuttond/scanbuttond.h0000644000175000017500000000274510374656710023226 0ustar pdmpdm// scanbuttond.h: fundamental data types, constants, ... // This file is part of scanbuttond. // Copyleft )c( 2004-2005 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef SCANBUTTOND_H_INCLUDED #define SCANBUTTOND_H_INCLUDED /** * \file scanbuttond.h * \brief Fundamental data types, macros, functions, ... * * This header defines some fundamental things which are used * throughout the whole project. */ // connection types #define NUM_CONNECTIONS 2 #define CONNECTION_NONE 0 #define CONNECTION_LIBUSB 1 struct scanner; typedef struct scanner scanner_t; struct scanner { char* vendor; char* product; int connection; void* internal_dev_ptr; char* sane_device; void* meta_info; int lastbutton; int is_open; int num_buttons; scanner_t* next; }; char* scanbtnd_get_connection_name(int connection); #endif scanbuttond-0.2.3.cvs20090713.orig/interface/0000755000175000017500000000000011226646321016504 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/interface/Makefile.am0000644000175000017500000000040410422431202020521 0ustar pdmpdmlib_LTLIBRARIES = libscanbtnd-interface_usb.la libscanbtnd_interface_usb_la_SOURCES = libusbi.c ../include/scanbuttond/libusbi.h libscanbtnd_interface_usb_la_LDFLAGS = -module -lusb -version-info 1:0:0 INCLUDES = $(all_includes) -I$(top_builddir)/include -I. scanbuttond-0.2.3.cvs20090713.orig/interface/libusbi.c0000644000175000017500000002150210422431543020274 0ustar pdmpdm// libusbi.h: libusb wrapper // This file is part of scanbuttond. // Copyleft )c( 2004-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include #include "scanbuttond/libusbi.h" #define TIMEOUT 10 * 1000 /* 10 seconds */ int invocation_count = 0; libusb_handle_t* libusb_init(void) { libusb_handle_t* handle; invocation_count++; if (invocation_count == 1) { syslog(LOG_INFO, "libusbi: initializing..."); usb_init(); } handle = (libusb_handle_t*)malloc(sizeof(libusb_handle_t)); handle->devices = NULL; libusb_rescan(handle); return handle; } static int libusb_search_interface(struct usb_device* device) { int found = 0; int interface; for (interface = 0; interface < device->config[0].bNumInterfaces && !found; interface++) { switch (device->descriptor.bDeviceClass) { case USB_CLASS_VENDOR_SPEC: found = 1; break; case USB_CLASS_PER_INTERFACE: switch (device->config[0].interface[interface].altsetting[0].bInterfaceClass) { case USB_CLASS_VENDOR_SPEC: case USB_CLASS_PER_INTERFACE: case 16: /* data? */ found = 1; break; } break; } } interface--; if (!found) return -1; return interface; } static int libusb_search_in_endpoint(struct usb_device* device) { int usb_in_ep = 0; int usb_out_ep = 0; struct usb_interface_descriptor *interface; interface = &device->config[0].interface->altsetting[0]; int num; for (num = 0; num < interface->bNumEndpoints; num++) { struct usb_endpoint_descriptor *endpoint; int address, direction, transfer_type; endpoint = &interface->endpoint[num]; address = endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK; direction = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK; transfer_type = endpoint->bmAttributes & USB_ENDPOINT_TYPE_MASK; if (transfer_type == USB_ENDPOINT_TYPE_BULK) { if (direction) { /* in */ if (!usb_in_ep) usb_in_ep = endpoint->bEndpointAddress; } else { /* out */ if (!usb_out_ep) usb_out_ep = endpoint->bEndpointAddress; } } } return usb_in_ep; } static int libusb_search_out_endpoint(struct usb_device* device) { int usb_in_ep = 0; int usb_out_ep = 0; struct usb_interface_descriptor *interface; interface = &device->config[0].interface->altsetting[0]; int num; for (num = 0; num < interface->bNumEndpoints; num++) { struct usb_endpoint_descriptor *endpoint; int address, direction, transfer_type; endpoint = &interface->endpoint[num]; address = endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK; direction = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK; transfer_type = endpoint->bmAttributes & USB_ENDPOINT_TYPE_MASK; if (transfer_type == USB_ENDPOINT_TYPE_BULK) { if (direction) { /* in */ if (!usb_in_ep) usb_in_ep = endpoint->bEndpointAddress; } else { /* out */ if (!usb_out_ep) usb_out_ep = endpoint->bEndpointAddress; } } } return usb_out_ep; } static void libusb_attach_device(struct usb_device* device, libusb_handle_t* handle) { libusb_device_t* libusb_device = (libusb_device_t*)malloc(sizeof(libusb_device_t)); libusb_device->vendorID = device->descriptor.idVendor; libusb_device->productID = device->descriptor.idProduct; // the location string consists of bus number, followed by a colon (":"), and the device number libusb_device->location = (char*)malloc(strlen(device->bus->dirname) + strlen(device->filename) + 2); strcpy(libusb_device->location, device->bus->dirname); strcat(libusb_device->location, ":"); strcat(libusb_device->location, device->filename); libusb_device->device = device; libusb_device->handle = NULL; libusb_device->interface = libusb_search_interface(device); if (libusb_device->interface < 0) { free(libusb_device->location); free(libusb_device); return; } libusb_device->out_endpoint = libusb_search_out_endpoint(device); if (libusb_device->out_endpoint < 0) { free(libusb_device->location); free(libusb_device); return; } libusb_device->in_endpoint = libusb_search_in_endpoint(device); if (libusb_device->in_endpoint < 0) { free(libusb_device->location); free(libusb_device); return; } libusb_device->next = handle->devices; handle->devices = libusb_device; } static void libusb_detach_devices(libusb_handle_t* handle) { libusb_device_t* next; while (handle->devices != NULL) { next = handle->devices->next; free(handle->devices->location); free(handle->devices); handle->devices = next; } } void libusb_rescan(libusb_handle_t* handle) { struct usb_bus *bus; struct usb_device *device; libusb_detach_devices(handle); usb_find_busses(); usb_find_devices(); handle->devices = NULL; bus = usb_busses; while (bus != NULL) { device = bus->devices; while (device != NULL) { libusb_attach_device(device, handle); device = device->next; } bus = bus->next; } } int libusb_get_changed_device_count(void) { usb_find_busses(); return usb_find_devices(); } libusb_device_t* libusb_get_devices(libusb_handle_t* handle) { return handle->devices; } int libusb_open(libusb_device_t* device) { int result; if (!device || !device->device) return -ENODEV; device->handle = usb_open(device->device); if (device->handle == NULL) { syslog(LOG_ERR, "libusbi: could not open device %s", device->location); return -ENODEV; } // Calling usb_set_configuration should not be necessary. // It is even considered harmful, since it may disturb other processes // which are currently communicating with the scanner! // // usb_set_configuration(device->handle, // usb_device(device->handle)->config[0].bConfigurationValue); result = usb_claim_interface(device->handle, device->interface); switch (result) { case 0: return 0; case -ENOMEM: syslog(LOG_ERR, "libusbi: could not claim interface for device %s. (ENOMEM)", device->location); usb_close(device->handle); return -ENODEV; case -EBUSY: syslog(LOG_ERR, "libusbi: could not claim interface for device %s. (EBUSY)", device->location); usb_close(device->handle); return -EBUSY; default: syslog(LOG_ERR, "libusbi: could not claim interface for device %s. (code=%d)", device->location, result); usb_close(device->handle); return -ENODEV; } } int libusb_close(libusb_device_t* device) { int result; result = usb_release_interface(device->handle, device->interface); if (result < 0) { syslog(LOG_ERR, "libusbi: could not release interface, error code=%d, device=%s", result, device->location); return result; } result = usb_close(device->handle); if (result < 0) { syslog(LOG_ERR, "libusbi: could not close usb device, error code=%d, device=%s", result, device->location); return result; } return 0; } int libusb_read(libusb_device_t* device, void* buffer, int bytecount) { int num_bytes = usb_bulk_read(device->handle, device->in_endpoint, buffer, bytecount, TIMEOUT); if (num_bytes<0) { usb_clear_halt(device->handle, device->in_endpoint); return 0; } return num_bytes; } int libusb_write(libusb_device_t* device, void* buffer, int bytecount) { int num_bytes = usb_bulk_write(device->handle, device->out_endpoint, buffer, bytecount, TIMEOUT); if (num_bytes<0) { usb_clear_halt(device->handle, device->in_endpoint); return 0; } return num_bytes; } void libusb_flush(libusb_device_t* device) { char buffer[16]; while (usb_bulk_read(device->handle, device->in_endpoint, buffer, 16, 500) > 0) {}; } int libusb_control_msg(libusb_device_t* device, int requesttype, int request, int value, int index, void* bytes, int size) { int num_bytes = usb_control_msg(device->handle, requesttype, request, value, index, bytes, size, TIMEOUT); if (num_bytes<0) { // Doesn't seem to be needed... (bs, Jun 07 2005) // usb_clear_halt(device->handle, device->in_endpoint); return 0; } return num_bytes; } void libusb_exit(libusb_handle_t* handle) { invocation_count--; if (invocation_count < 0) { syslog(LOG_WARNING, "libusbi: libusb_exit called more often than libusb_init!!!"); } libusb_detach_devices(handle); free(handle); if (invocation_count == 0) { syslog(LOG_INFO, "libusbi: shutting down..."); } } scanbuttond-0.2.3.cvs20090713.orig/lib/0000755000175000017500000000000011226646321015312 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/lib/loader.c0000644000175000017500000001120310563744124016724 0ustar pdmpdm// loader.h: dynamic backend library loader // This file is part of scanbuttond. // Copyleft )c( 2005-2006 by Bernhard Stiftner // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include #include #include #include #include #include #include "scanbuttond/common.h" #include "scanbuttond/loader.h" static char* lib_dir = STRINGIFY(LIB_DIR); int scanbtnd_loader_init(void) { /* int error = lt_dlinit(); if (!error) { error = lt_dlsetsearchpath(module_search_path); const char *env_path = getenv(MODULE_PATH_ENV); if (env_path != NULL) { error = lt_dladdsearchdir(env_path); } } return error;*/ return 0; } void scanbtnd_loader_exit(void) { /* lt_dlexit();*/ } backend_t* scanbtnd_load_backend(const char* filename) { const char* error; void* dll_handle; char* dll_path = (char*)malloc(strlen(lib_dir) + strlen(filename) + 5); strcpy(dll_path, filename); strcat(dll_path, ".so"); dll_handle = dlopen(dll_path, RTLD_NOW|RTLD_LOCAL); if (!dll_handle) { strcpy(dll_path, lib_dir); strcat(dll_path, "/"); strcat(dll_path, filename); strcat(dll_path, ".so"); dll_handle = dlopen(dll_path, RTLD_NOW|RTLD_LOCAL); if (!dll_handle) { syslog(LOG_ERR, "loader: failed to load \"%s\". Error message: \"%s\"", filename, dlerror()); free(dll_path); return NULL; } } dlerror(); // Clear any existing error backend_t* backend = (backend_t*)malloc(sizeof(backend_t)); backend->handle = (void*)dll_handle; backend->scanbtnd_get_backend_name = dlsym(dll_handle, "scanbtnd_get_backend_name"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } backend->scanbtnd_init = dlsym(dll_handle, "scanbtnd_init"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } backend->scanbtnd_rescan = dlsym(dll_handle, "scanbtnd_rescan"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } backend->scanbtnd_get_supported_devices = dlsym(dll_handle, "scanbtnd_get_supported_devices"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } backend->scanbtnd_open = dlsym(dll_handle, "scanbtnd_open"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } backend->scanbtnd_close = dlsym(dll_handle, "scanbtnd_close"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } backend->scanbtnd_get_button = dlsym(dll_handle, "scanbtnd_get_button"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } backend->scanbtnd_get_sane_device_descriptor = dlsym(dll_handle, "scanbtnd_get_sane_device_descriptor"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } backend->scanbtnd_exit = dlsym(dll_handle, "scanbtnd_exit"); if ((error = dlerror()) != NULL) { syslog(LOG_ERR, "loader: dlsym failed! Error message \"%s\"", error); dlclose(dll_handle); free(backend); free(dll_path); return NULL; } free(dll_path); return backend; } void scanbtnd_unload_backend(backend_t* backend) { if (backend->handle != NULL) { dlclose(backend->handle); backend->handle = NULL; free(backend); } } scanbuttond-0.2.3.cvs20090713.orig/scripts/0000755000175000017500000000000011226646321016233 5ustar pdmpdmscanbuttond-0.2.3.cvs20090713.orig/scripts/Makefile.am0000644000175000017500000000022210541264207020261 0ustar pdmpdmpkgsysconfdir = $(sysconfdir)/$(PACKAGE) pkgsysconf_SCRIPTS = buttonpressed.sh.example initscanner.sh.example EXTRA_DIST = $(pkgsysconf_SCRIPTS) scanbuttond-0.2.3.cvs20090713.orig/scripts/buttonpressed.sh.example0000755000175000017500000000337010563731645023137 0ustar pdmpdm#!/bin/sh # This script is started by scanbuttond whenever a scanner button has been pressed. # Scanbuttond passes the following parameters to us: # $1 ... the button number # $2 ... the scanner's SANE device name, which comes in handy if there are two or # more scanners. In this case we can pass the device name to SANE programs # like scanimage. TMPFILE="/tmp/scan.tiff" LOCKFILE="/tmp/copy.lock" case $1 in 1) echo "button 1 has been pressed on $2" # This example turns your scanner+printer into a photocopier. # Fine-tuned for the Epson Perfection 2400, the HP LaserJet 1200 and # ISO A4 paper size so that the scanned document matches the printer # output as closely as possible. # The festival speech synthesizer is used to inform the user about # the progress of the operation. # # # if [ -f $LOCKFILE ]; then # echo "Error: Another scanning operation is currently in progress" | festival --tts # exit # fi # touch $LOCKFILE # rm -f $TMPFILE # echo "Copying" | festival --tts # scanimage --device-name $2 --format tiff --mode Gray --quick-format A4 \ # --resolution 300 --sharpness 0 --brightness -3 \ # --gamma-correction "High contrast printing" > $TMPFILE # if [ $? != 0 ]; then # echo "Scanning failed" | festival --tts # rm $LOCKFILE # exit # fi # echo "Submitting print job" | festival --tts # tiff2ps -z -w 8.27 -h 11.69 $TMPFILE | lpr # if [ $? != 0 ]; then # echo "Printing failed" | festival --tts # rm $LOCKFILE # exit # fi # echo "The print job has been submitted" | festival --tts # rm -f $LOCKFILE # ;; 2) echo "button 2 has been pressed on $2" ;; 3) echo "button 3 has been pressed on $2" ;; 4) echo "button 4 has been pressed on $2" ;; esac scanbuttond-0.2.3.cvs20090713.orig/scripts/initscanner.sh.example0000755000175000017500000000042510563731645022551 0ustar pdmpdm#!/bin/sh # This script is executed whenever scanbuttond # finds new devices. # If your scanner needs a firmware upload or any other kind # of special action to be taken on initialization, put # the apropriate command here. # Example: # scanimage -n # or # sane-find-scanner