📄 scanner.c
字号:
/* -*- linux-c -*- *//* * Driver for USB Scanners (linux-2.4.0test1-ac7) * * Copyright (C) 1999, 2000 David E. Nelson * * Portions may be copyright Brad Keryan and Michael Gee. * * David E. Nelson (dnelson@jump.net) * * 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. * * Originally based upon mouse.c (Brad Keryan) and printer.c (Michael Gee). * * History * * 0.1 8/31/1999 * * Developed/tested using linux-2.3.15 with minor ohci.c changes to * support short packes during bulk xfer mode. Some testing was * done with ohci-hcd but the performace was low. Very limited * testing was performed with uhci but I was unable to get it to * work. Initial relase to the linux-usb development effort. * * * 0.2 10/16/1999 * * - Device can't be opened unless a scanner is plugged into the USB. * - Finally settled on a reasonable value for the I/O buffer's. * - Cleaned up write_scanner() * - Disabled read/write stats * - A little more code cleanup * * * 0.3 10/18/1999 * * - Device registration changed to reflect new device * allocation/registration for linux-2.3.22+. * - Adopted David Brownell's <david-b@pacbell.net> technique for * assigning bulk endpoints. * - Removed unnessesary #include's * - Scanner model now reported via syslog INFO after being detected * *and* configured. * - Added user specified vendor:product USB ID's which can be passed * as module parameters. * * * 0.3.1 * * - Applied patches for linux-2.3.25. * - Error number reporting changed to reflect negative return codes. * * * 0.3.2 * * - Applied patches for linux-2.3.26 to scanner_init(). * - Debug read/write stats now report values as signed decimal. * * * 0.3.3 * * - Updated the bulk_msg() calls to usb usb_bulk_msg(). * - Added a small delay in the write_scanner() method to aid in * avoiding NULL data reads on HP scanners. We'll see how this works. * - Return values from usb_bulk_msg() now ignore positive values for * use with the ohci driver. * - Added conditional debugging instead of commenting/uncommenting * all over the place. * - kfree()'d the pointer after using usb_string() as documented in * linux-usb-api.txt. * - Added usb_set_configuration(). It got lost in version 0.3 -- ack! * - Added the HP 5200C USB Vendor/Product ID's. * * * 0.3.4 1/23/2000 * * - Added Greg K-H's <greg@kroah.com> patch for better handling of * Product/Vendor detection. * - The driver now autoconfigures its endpoints including interrupt * endpoints if one is detected. The concept was originally based * upon David Brownell's method. * - Added some Seiko/Epson ID's. Thanks to Karl Heinz * Kremer <khk@khk.net>. * - Added some preliminary ioctl() calls for the PV8630 which is used * by the HP4200. The ioctl()'s still have to be registered. Thanks * to Adrian Perez Jorge <adrianpj@easynews.com>. * - Moved/migrated stuff to scanner.h * - Removed the usb_set_configuration() since this is handled by * the usb_new_device() routine in usb.c. * - Added the HP 3300C. Thanks to Bruce Tenison. * - Changed user specified vendor/product id so that root hub doesn't * get falsely attached to. Thanks to Greg K-H. * - Added some Mustek ID's. Thanks to Gernot Hoyler * <Dr.Hoyler@t-online.de>. * - Modified the usb_string() reporting. See kfree() comment above. * - Added Umax Astra 2000U. Thanks to Doug Alcorn <doug@lathi.net>. * - Updated the printk()'s to use the info/warn/dbg macros. * - Updated usb_bulk_msg() argument types to fix gcc warnings. * * * 0.4 2/4/2000 * * - Removed usb_string() from probe_scanner since the core now does a * good job of reporting what was connnected. * - Finally, simultaneous multiple device attachment! * - Fixed some potential memory freeing issues should memory allocation * fail in probe_scanner(); * - Some fixes to disconnect_scanner(). * - Added interrupt endpoint support. * - Added Agfa SnapScan Touch. Thanks to Jan Van den Bergh * <jan.vandenbergh@cs.kuleuven.ac.be>. * - Added Umax 1220U ID's. Thanks to Maciek Klimkowski * <mac@nexus.carleton.ca>. * - Fixed bug in write_scanner(). The buffer was not being properly * updated for writes larger than OBUF_SIZE. Thanks to Henrik * Johansson <henrikjo@post.utfors.se> for identifying it. * - Added Microtek X6 ID's. Thanks to Oliver Neukum * <Oliver.Neukum@lrz.uni-muenchen.de>. * * * 0.4.1 2/15/2000 * * - Fixed 'count' bug in read_scanner(). Thanks to Henrik * Johansson <henrikjo@post.utfors.se> for identifying it. Amazing * it has worked this long. * - Fixed '>=' bug in both read/write_scanner methods. * - Cleaned up both read/write_scanner() methods so that they are * a little more readable. * - Added a lot of Microtek ID's. Thanks to Adrian Perez Jorge. * - Adopted the __initcall(). * - Added #include <linux/init.h> to scanner.h for __initcall(). * - Added one liner in irq_scanner() to keep gcc from complaining * about an unused variable (data) if debugging was disabled * in scanner.c. * - Increased the timeout parameter in read_scanner() to 120 Secs. * * * 0.4.2 3/23/2000 * * - Added Umax 1236U ID. Thanks to Philipp Baer <ph_baer@npw.net>. * - Added Primax, ReadyScan, Visioneer, Colorado, and Genius ID's. * Thanks to Adrian Perez Jorge <adrianpj@easynews.com>. * - Fixed error number reported for non-existant devices. Thanks to * Spyridon Papadimitriou <Spyridon_Papadimitriou@gs91.sp.cs.cmu.edu>. * - Added Acer Prisascan 620U ID's. Thanks to Joao <joey@knoware.nl>. * - Replaced __initcall() with module_init()/module_exit(). Updates * from patch-2.3.48. * - Replaced file_operations structure with new syntax. Updates * from patch-2.3.49. * - Changed #include "usb.h" to #include <linux/usb.h> * - Added #define SCN_IOCTL to exclude development areas * since 2.4.x is about to be released. This mainly affects the * ioctl() stuff. See scanner.h for more details. * - Changed the return value for signal_pending() from -ERESTARTSYS to * -EINTR. * * * 0.4.3 4/30/2000 * * - Added Umax Astra 2200 ID. Thanks to Flynn Marquardt * <flynn@isr.uni-stuttgart.de>. * - Added iVina 1200U ID. Thanks to Dyson Lin <dyson@avision.com.tw>. * - Added access time update for the device file courtesy of Paul * Mackerras <paulus@linuxcare.com>. This allows a user space daemon * to turn the lamp off for a Umax 1220U scanner after a prescribed * time. * - Fixed HP S20 ID's. Thanks to Ruud Linders <rlinders@xs4all.nl>. * - Added Acer ScanPrisa 620U ID. Thanks to Oliver * Schwartz <Oliver.Schwartz@gmx.de> via sane-devel mail list. * - Fixed bug in read_scanner for copy_to_user() function. The returned * value should be 'partial' not 'this_read'. * - Fixed bug in read_scanner. 'count' should be decremented * by 'this_read' and not by 'partial'. This resulted in twice as many * calls to read_scanner() for small amounts of data and possibly * unexpected returns of '0'. Thanks to Karl Heinz * Kremer <khk@khk.net> and Alain Knaff <Alain.Knaff@ltnb.lu> * for discovering this. * - Integrated Randy Dunlap's <randy.dunlap@intel.com> patch for a * scanner lookup/ident table. Thanks Randy. * - Documentation updates. * - Added wait queues to read_scanner(). * * * 0.4.3.1 * * - Fixed HP S20 ID's...again..sigh. Thanks to Ruud * Linders <rlinders@xs4all.nl>. * * 0.4.4 * - Added addtional Mustek ID's (BearPaw 1200, 600 CU, 1200 USB, * and 1200 UB. Thanks to Henning Meier-Geinitz <henningmg@gmx.de>. * - Added the Vuego Scan Brisa 340U ID's. Apparently this scanner is * marketed by Acer Peripherals as a cheap 300 dpi model. Thanks to * David Gundersen <gundersd@paradise.net.nz>. * - Added the Epson Expression1600 ID's. Thanks to Karl Heinz * Kremer <khk@khk.net>. * * TODO * * - Performance * - Select/poll methods * - More testing * - Proper registry/assignment for LM9830 ioctl's * * * Thanks to: * * - All the folks on the linux-usb list who put up with me. :) This * has been a great learning experience for me. * - To Linus Torvalds for this great OS. * - The GNU folks. * - The folks that forwarded Vendor:Product ID's to me. * - Johannes Erdfelt for the loaning of a USB analyzer for tracking an * issue with HP-4100 and uhci. * - Adolfo Montero for his assistance. * - All the folks who chimed in with reports and suggestions. * - All the developers that are working on USB SANE backends or other * applications to use USB scanners. * * Performance: * * System: Pentium 120, 80 MB RAM, OHCI, Linux 2.3.23, HP 4100C USB Scanner * 300 dpi scan of the entire bed * 24 Bit Color ~ 70 secs - 3.6 Mbit/sec * 8 Bit Gray ~ 17 secs - 4.2 Mbit/sec *//* * Scanner definitions, macros, module info, * debug/ioctl/data_dump enable, and other constants. */ #include "scanner.h"/* Table of scanners that may work with this driver */static struct usb_device_id scanner_device_ids [] = { /* Acer */ { USB_DEVICE(0x04a5, 0x2060) }, /* Prisa Acerscan 620U & 640U (!)*/ { USB_DEVICE(0x04a5, 0x2040) }, /* Prisa AcerScan 620U (!) */ { USB_DEVICE(0x04a5, 0x2022) }, /* Vuego Scan Brisa 340U */ /* Agfa */ { USB_DEVICE(0x06bd, 0x0001) }, /* SnapScan 1212U */ { USB_DEVICE(0x06bd, 0x0002) }, /* SnapScan 1236U */ { USB_DEVICE(0x06bd, 0x2061) }, /* Another SnapScan 1212U (?)*/ { USB_DEVICE(0x06bd, 0x0100) }, /* SnapScan Touch */ /* Colorado -- See Primax/Colorado below */ /* Epson -- See Seiko/Epson below */ /* Genius */ { USB_DEVICE(0x0458, 0x2001) }, /* ColorPage-Vivid Pro */ /* Hewlett Packard */ { USB_DEVICE(0x03f0, 0x0205) }, /* 3300C */ { USB_DEVICE(0x03f0, 0x0101) }, /* 4100C */ { USB_DEVICE(0x03f0, 0x0105) }, /* 4200C */ { USB_DEVICE(0x03f0, 0x0102) }, /* PhotoSmart S20 */ { USB_DEVICE(0x03f0, 0x0401) }, /* 5200C */ { USB_DEVICE(0x03f0, 0x0701) }, /* 5300C */ { USB_DEVICE(0x03f0, 0x0201) }, /* 6200C */ { USB_DEVICE(0x03f0, 0x0601) }, /* 6300C */ /* iVina */ { USB_DEVICE(0x0638, 0x0268) }, /* 1200U */ /* Microtek */ { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */ { USB_DEVICE(0x05da, 0x0094) }, /* Phantom 336CX - C3 */ { USB_DEVICE(0x05da, 0x00a0) }, /* Phantom 336CX - C3 #2 */ { USB_DEVICE(0x05da, 0x009a) }, /* Phantom C6 */ { USB_DEVICE(0x05da, 0x00a3) }, /* ScanMaker V6USL */ { USB_DEVICE(0x05da, 0x80a3) }, /* ScanMaker V6USL #2 */ { USB_DEVICE(0x05da, 0x80ac) }, /* ScanMaker V6UL - SpicyU */ /* Mustek */ { USB_DEVICE(0x055f, 0x0001) }, /* 1200 CU */ { USB_DEVICE(0x0400, 0x1000) }, /* BearPaw 1200 */ { USB_DEVICE(0x055f, 0x0002) }, /* 600 CU */ { USB_DEVICE(0x055f, 0x0003) }, /* 1200 USB */ { USB_DEVICE(0x055f, 0x0006) }, /* 1200 UB */ /* Primax/Colorado */ { USB_DEVICE(0x0461, 0x0300) }, /* G2-300 #1 */ { USB_DEVICE(0x0461, 0x0380) }, /* G2-600 #1 */ { USB_DEVICE(0x0461, 0x0301) }, /* G2E-300 #1 */ { USB_DEVICE(0x0461, 0x0381) }, /* ReadyScan 636i */ { USB_DEVICE(0x0461, 0x0302) }, /* G2-300 #2 */ { USB_DEVICE(0x0461, 0x0382) }, /* G2-600 #2 */ { USB_DEVICE(0x0461, 0x0303) }, /* G2E-300 #2 */ { USB_DEVICE(0x0461, 0x0383) }, /* G2E-600 */ { USB_DEVICE(0x0461, 0x0340) }, /* Colorado USB 9600 */ { USB_DEVICE(0x0461, 0x0360) }, /* Colorado USB 19200 */ { USB_DEVICE(0x0461, 0x0341) }, /* Colorado 600u */ { USB_DEVICE(0x0461, 0x0361) }, /* Colorado 1200u */ /* Seiko/Epson Corp. */ { USB_DEVICE(0x04b8, 0x0101) }, /* Perfection 636U and 636Photo */ { USB_DEVICE(0x04b8, 0x0103) }, /* Perfection 610 */ { USB_DEVICE(0x04b8, 0x0104) }, /* Perfection 1200U and 1200Photo*/ { USB_DEVICE(0x04b8, 0x0106) }, /* Stylus Scan 2500 */ { USB_DEVICE(0x04b8, 0x0107) }, /* Expression 1600 */ /* Umax */ { USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */ { USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */ { USB_DEVICE(0x1606, 0x0230) }, /* Astra 2200U */ /* Visioneer */ { USB_DEVICE(0x04a7, 0x0221) }, /* OneTouch 5300 USB */ { USB_DEVICE(0x04a7, 0x0211) }, /* OneTouch 7600 USB */ { USB_DEVICE(0x04a7, 0x0231) }, /* 6100 USB */ { USB_DEVICE(0x04a7, 0x0311) }, /* 6200 EPP/USB */ { USB_DEVICE(0x04a7, 0x0321) }, /* OneTouch 8100 EPP/USB */ { USB_DEVICE(0x04a7, 0x0331) }, /* OneTouch 8600 EPP/USB */ { } /* Terminating entry */};MODULE_DEVICE_TABLE (usb, scanner_device_ids);static voidirq_scanner(struct urb *urb){/* * For the meantime, this is just a placeholder until I figure out what * all I want to do with it -- or somebody else for that matter. */ struct scn_usb_data *scn = urb->context; unsigned char *data = &scn->button; data += 0; /* Keep gcc from complaining about unused var */ if (urb->status) { return; } dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data); return;}static intopen_scanner(struct inode * inode, struct file * file){ struct scn_usb_data *scn; struct usb_device *dev; kdev_t scn_minor; int err=0; lock_kernel(); scn_minor = USB_SCN_MINOR(inode); dbg("open_scanner: scn_minor:%d", scn_minor); if (!p_scn_table[scn_minor]) { err("open_scanner(%d): Unable to access minor data", scn_minor); err = -ENODEV; goto out_error; } scn = p_scn_table[scn_minor]; dev = scn->scn_dev; if (!dev) { err("open_scanner(%d): Scanner device not present", scn_minor); err = -ENODEV; goto out_error; } if (!scn->present) { err("open_scanner(%d): Scanner is not present", scn_minor); err = -ENODEV; goto out_error; } if (scn->isopen) { err("open_scanner(%d): Scanner device is already open", scn_minor); err = -EBUSY; goto out_error; } init_waitqueue_head(&scn->rd_wait_q); scn->isopen = 1; file->private_data = scn; /* Used by the read and write metheds */ MOD_INC_USE_COUNT;out_error: unlock_kernel(); return err;}static intclose_scanner(struct inode * inode, struct file * file){ struct scn_usb_data *scn; kdev_t scn_minor; scn_minor = USB_SCN_MINOR (inode); dbg("close_scanner: scn_minor:%d", scn_minor); if (!p_scn_table[scn_minor]) { err("close_scanner(%d): invalid scn_minor", scn_minor); return -ENODEV; } scn = p_scn_table[scn_minor]; scn->isopen = 0; file->private_data = NULL; MOD_DEC_USE_COUNT; return 0;}static ssize_twrite_scanner(struct file * file, const char * buffer, size_t count, loff_t *ppos){ struct scn_usb_data *scn; struct usb_device *dev; ssize_t bytes_written = 0; /* Overall count of bytes written */ ssize_t ret = 0; kdev_t scn_minor; int this_write; /* Number of bytes to write */ int partial; /* Number of bytes successfully written */ int result = 0; char *obuf; scn = file->private_data; scn_minor = scn->scn_minor; obuf = scn->obuf; dev = scn->scn_dev; file->f_dentry->d_inode->i_atime = CURRENT_TIME; down(&(scn->gen_lock)); while (count > 0) { if (signal_pending(current)) { ret = -EINTR; break; } this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count; if (copy_from_user(scn->obuf, buffer, this_write)) { ret = -EFAULT; break; } result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, scn->bulk_out_ep), obuf, this_write, &partial, 60*HZ); dbg("write stats(%d): result:%d this_write:%d partial:%d", scn_minor, result, this_write, partial); if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */ warn("write_scanner: NAK recieved."); ret = -ETIME; break; } else if (result < 0) { /* We should not get any I/O errors */ warn("write_scanner(%d): funky result: %d. Please notify the maintainer.", scn_minor, result); ret = -EIO; break; }#ifdef WR_DATA_DUMP if (partial) { unsigned char cnt, cnt_max; cnt_max = (partial > 24) ? 24 : partial; printk(KERN_DEBUG "dump(%d): ", scn_minor);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -