⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scanner.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- 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 + -