2003-09-30 Here are a few rules and tips that should help writing a SANE-conforming backend and including it into the SANE package: GETTING STARTED --------------- * You will need information about the protocol the scanner (or other image application device) is using. The easiest way is to ask the manufacturer about it. You should mention that the code will be open-source, however. * Read the SANE standard. * One approach is to write a stand-alone scanning program first. Debugging this program is usually easier than using the SANE libraries. However, keep in mind what you learned from the SANE standard. * Once your program works basically, insert its functions into a basically empty SANE backend. You can get one by removing everything but the SANE includes and SANE API function definitions from an existing backend (e.g. test.c). * If you have any information about the scanner you want to support that is not already mentioned in one of the .desc files, please contact the sane-devel mailing list. Especially if you have written code (e.g. a test program) or started writing a backend, contact us. * Keep other users informed about what you did and want to do. This way no work is done twice and you may get volunteers for coding or testing. Set up a website or at least write to sane-devel. * When you have a working backend but you don't want to have it included in the SANE distribution yet, at least the .desc file can be included (see below for details). So people will find a link to your backend at the SANE webpage. PROGRAMMING ----------- * Please follow the GNU coding standards. It's clear that the style outlined there is nobody's favorite, but it's much easier to maintain SANE if everybody follows more or less the same coding style. It also looks more professional. The GNU standards can be found at: http://www.gnu.org/prep/standards_toc.html ftp://ftp.gnu.org/pub/gnu/standards/standards.text Note that GNU emacs supports automatic indentation according to this standard. The command "indent -gnu" can be used to reformat existing sources according to this standard. * Please be courteous to programmer's with terminals that are 80 characters wide. It's not difficult to avoid long lines, so please do so. Note that in ANSI C you can split long strings into pieces separated by white space. For example, "this is an awfully long string" can be written as "this is an " "awfully long string". * Use only ANSI C for your backend. * Please do not depend on compiler specific features or, if you do, make the dependency conditional so other compilers will still be able to compile the files. In particular: - do not use C++ style comments (//-line comments) - do not declare dynamically sized automatic arrays; instead, use alloca() after including "../include/lalloca.h". For example: void func (int n) { char buf[n]; } should be re-written as: #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" : void func (int n) { char *buf = alloca (n); } - Don't use any #pragma directives---they're completely compiler-dependent. * If you use headers or libraries that may not be available on all systems, write a check for configure.in and include it conditionally. If your backend depends on these libraries or headers, compile the backend only if they are available (see pint for an example). * Use #include ".../include/sane/..." to include the sane header files instead of #include . Otherwise problems with different installed SANE versions may occur. Also this makes clear that the local files are used. * Don't forget to #include ".../include/sane/config.h" in your backend before any other includes. If you use lalloca.h see above for the correct includes. * Include sanei_backend.h after the other includes. * It's no longer necessary to #define PATH_MAX (now in sanei_backend.h). If you define it, do so *after* the system includes. * Please use sanei functions whenever possible (e.g. sanei_config_read()). This makes porting to other os/platforms much easier. Most of these functions are documented in their respective header files in include/sane/sanei_*.h. For most of them there is also documentation in doxygen format: http://www.sane-project.org/sanei/. These HTML pages can be generated by calling "doxygen sanei-doxygen.conf" in the doc/ directory. * Initialize global variables explicitly in sane_init. Keep in mind that sane_init can be called more than once (if sane_exit is called everytime after sane_init). Therefore don't depend on automatic initialization to 0 / NULL. * Do make sure that your code is byte-order independent. This is particularly important for networking-related code and when dealing with non-textual data files. * Don't use printf, fprintf or perror to output debug or error messages. Use the DBG macro instead. If your backend can't detect a scanner for whatever reason it shouldn't output anything as long as SANE_DEBUG_BACKENDNAME isn't set. So don't use DBG(0, ...) in this case. * Please do not assume that `size_t' is `unsigned int'. On some systems, it's `unsigned long' and the size of this type may be bigger than that of an int (this is true for practically any of the 64-bit systems). To print a variable of type size_t portably, cast the variable to u_long and print it with the %lu specifier. E.g.: size_t len; DBG(3, "len=%lu\n", (u_long) len); * Please do not assume that `void *' has the same size as `int'. On some systems, it's `long' and the size of this type may be bigger than that of an int (this is true for practically any of the 64-bit systems). Where this comes up is with opaque handles. For example: int OpaqueHandle; MyScanner *s = (MyScanner *)OpaqueHandle; will FAIL on most 64 bit systems. Please use `void *' or better `SANE_Handle'. * Don't use exit() in your backend. You will exit the whole program, not only your backend. * If you use wait() or waitpid() in your backend, check its return value. This is important, if the status value is checked for e.g. WIFEXITED after the call of wait() or waitpid(). Both functions may fail if the frontend already did a wait for the children. * Please try to avoid compilation warnings. At least with "--disable-warnings" there shouldn't be warnings when compiling backends. It's not necessary to fix every "unused parameter" warning but take care that no warnings pointing to really existing problems or ambiguities are missed. Some programming techniques generating warnings on gcc may lead to errors on other systems. * To support translation of SANE options, please mark the descriptions (desc) and title of options with SANE_I18N(). See po/README for details. * Please check for TL_X < BR_X and TL_Y < BR_Y to avoid segfaults or even scanner damage. This should NOT be done in sane_control_option, it should be possible to temporary set TL_X > BR_X or TL_ > BR, otherwise it is hard for a frontend to set the correct values. TESTING ------- * Please test a backend with "scanimage -T" (plus other options, as appropriate/necessary) as this will make sure that sane_read() always returns the correct amount of data etc. * You can also test a backend with tstbackend. tstbackend is not compiled nor installed by default. To do that, cd into frontend and edit the Makefile. Add "tstbackend" to BINPROGS. "tstbackend --help" gives a short help. * Please test a backend not just with scanimage and xscanimage (+ other frontends), but also with saned. Based on past experience, it is often the case that remote scanning can uncover subtle bugs. Note that you don't have to use two different machines to test "remote" scanning---you can use one and the same machine to test a backend via saned (just be sure to enable the "net" backend in dll.conf and follow the steps described in saned(1)). * Please test on every available platform/os. Even if no scanner is attached to this system, test compilation and running scanimage. If you don't have access to other platforms, ask sane-devel. * Please make sure that all global symbols exported from a SANE backend start with the prefix "sane" or "sanei" to avoid clashes with exported symbols of other backends. Make sure, the sanei_* symbols are unique, e.g. by using sanei_backendname_*. Only export symbols that are absolutely necessary. You can verify this by running GNU "nm" on the static library. For example: nm -g backend/.libs/libsane-hp.a would list all global symbols in the HP backend. "./configure --disable-shared; make; make libcheck" in the sane-backends root directory will name all backend libraries, that contain "illegal" symbols. DOCUMENTATION ------------- * Even if you haven't written a man-page for your backend yet, you *must* create a .desc file which describes it. Anytime you submit source code for your backend, you should include an update to the .desc file which reflects the new state of the backend. The .desc files are used to create the HTML lists of supported devices. These lists are updated automatically when you change a .desc file in CVS. See e.g. http://www.sane-project.org/lists/sane-mfgs-cvs.html for the results. * The .desc files are located in the directories "doc/descriptions" and "doc/descriptions-external" (for included and external backends). * "doc/descriptions.txt" describes the format of the ".desc" files. There is also a template for new .desc files: "template.desc.". The format of the files in the two directories is very similar. If you'd like to try parsing your creation to recreate the sane-backends webpages, cd into "tools/" and enter "make sane-desc". You can either use sane-desc directly (try "./sane-desc -h") or use "make html-pages" in "doc/". * For external backends, you don't need to supply :manpage and :version. The manpage link won't work anyway and version will be outdated soon. * When your backend is included in the SANE distribution, add an entry to doc/sane.man, AUTHORS and sane-backends.lsm. The sane.man entry should point to your documentation (man-page, website, readme). Also move your .desc file from "doc/descriptions-external" to "doc/descriptions" and update them. * In your manual page (backend.man), use @LIBDIR@ and the other macros for path names to the libraries, config files and documentation. Don't use fixed paths as they will be wrong if SANE is installed with a different prefix (e.g. /usr instead of /usr/local). * If you want to include READMEs, HTML files or other documentation, please create your own directory (doc/backendname) and store your files in this directory. If you only have a manual page a subdirectory isn't necessary. * Please keep your manpages and .desc files up-to-date especially regarding version numbers. CHECKLIST: SUBMITTING A NEW BACKEND ----------------------------------- In sane-backends/ * Add the author(s) name(s) to AUTHORS * Correct any related entries in the bug-tracking system In sane-backends/backend/ * Use the command "indent -gnu" to reformat your code according to the standard. * Add the backend name to dll.conf * Check that the SANE license is in the backend source files. * Add the source file names and the .conf file to DISTFILES in Makefile.in In sane-backends/doc/ * Add an entry for the man page in sane.man * Add the man page file in doc/Makefile.in * Move the description file from descriptions-external/ to doc/descriptions/ * Check that the description file is correct: "cd doc; make html-pages" and check the html pages result with a browser. * Check that the backend version is the same in the source and in the description file. INCLUDING INTO CVS ------------------ * If you want to include your backend into CVS use the latest CVS to make patches. Check the mailing list and the bug-tracking system for information about bugs to avoid. * If your backend isn't included yet in the SANE CVS tree, write an email to the SANE mailing list (sane-devel) and ask for inclusion. Usually one of the developers will check the backend for common mistakes and test compilation. If everything is ok the backend will be added to the CVS tree.