printer.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:20k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * printer.c  Version 0.8
  3.  *
  4.  * Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
  5.  * Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
  6.  * Copyright (c) 2000 Randy Dunlap <randy.dunlap@intel.com>
  7.  * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
  8.  *
  9.  * USB Printer Device Class driver for USB printers and printer cables
  10.  *
  11.  * Sponsored by SuSE
  12.  *
  13.  * ChangeLog:
  14.  * v0.1 - thorough cleaning, URBification, almost a rewrite
  15.  * v0.2 - some more cleanups
  16.  * v0.3 - cleaner again, waitqueue fixes
  17.  * v0.4 - fixes in unidirectional mode
  18.  * v0.5 - add DEVICE_ID string support
  19.  * v0.6 - never time out
  20.  * v0.7 - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com)
  21.  * v0.8 - add devfs support
  22.  * v0.9 - fix unplug-while-open paths
  23.  */
  24. /*
  25.  * This program is free software; you can redistribute it and/or modify
  26.  * it under the terms of the GNU General Public License as published by
  27.  * the Free Software Foundation; either version 2 of the License, or
  28.  * (at your option) any later version.
  29.  *
  30.  * This program is distributed in the hope that it will be useful,
  31.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  32.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  33.  * GNU General Public License for more details.
  34.  *
  35.  * You should have received a copy of the GNU General Public License
  36.  * along with this program; if not, write to the Free Software
  37.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  38.  */
  39. #include <linux/module.h>
  40. #include <linux/kernel.h>
  41. #include <linux/sched.h>
  42. #include <linux/smp_lock.h>
  43. #include <linux/signal.h>
  44. #include <linux/poll.h>
  45. #include <linux/init.h>
  46. #include <linux/slab.h>
  47. #include <linux/lp.h>
  48. #include <linux/devfs_fs_kernel.h>
  49. #undef DEBUG
  50. #include <linux/usb.h>
  51. /*
  52.  * Version Information
  53.  */
  54. #define DRIVER_VERSION "v0.8"
  55. #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap"
  56. #define DRIVER_DESC "USB Printer Device Class driver"
  57. #define USBLP_BUF_SIZE 8192
  58. #define DEVICE_ID_SIZE 1024
  59. #define IOCNR_GET_DEVICE_ID 1
  60. #define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) /* get device_id string */
  61. #define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
  62. /*
  63.  * A DEVICE_ID string may include the printer's serial number.
  64.  * It should end with a semi-colon (';').
  65.  * An example from an HP 970C DeskJet printer is (this is one long string,
  66.  * with the serial number changed):
  67. MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:Hewlett-Packard DeskJet 970C;SERN:US970CSEPROF;VSTATUS:$HB0$NC0,ff,DN,IDLE,CUT,K1,C0,DP,NR,KP000,CP027;VP:0800,FL,B0;VJ:                    ;
  68.  */
  69. /*
  70.  * USB Printer Requests
  71.  */
  72. #define USBLP_REQ_GET_ID 0x00
  73. #define USBLP_REQ_GET_STATUS 0x01
  74. #define USBLP_REQ_RESET 0x02
  75. #define USBLP_MINORS 16
  76. #define USBLP_MINOR_BASE 0
  77. #define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */
  78. struct usblp {
  79. struct usb_device  *dev; /* USB device */
  80. devfs_handle_t devfs; /* devfs device */
  81. struct semaphore sem; /* locks this struct, especially "dev" */
  82. struct urb readurb, writeurb; /* The urbs */
  83. wait_queue_head_t wait; /* Zzzzz ... */
  84. int readcount; /* Counter for reads */
  85. int ifnum; /* Interface number */
  86. int minor; /* minor number of device */
  87. unsigned int quirks; /* quirks flags */
  88. unsigned char used; /* True if open */
  89. unsigned char bidir; /* interface is bidirectional */
  90. unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */
  91. /* first 2 bytes are (big-endian) length */
  92. };
  93. extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
  94. static struct usblp *usblp_table[USBLP_MINORS];
  95. /* Quirks: various printer quirks are handled by this table & its flags. */
  96. struct quirk_printer_struct {
  97. __u16 vendorId;
  98. __u16 productId;
  99. unsigned int quirks;
  100. };
  101. #define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */
  102. #define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
  103. static struct quirk_printer_struct quirk_printers[] = {
  104. { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
  105. { 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
  106. { 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
  107. { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
  108. { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
  109. { 0, 0 }
  110. };
  111. /*
  112.  * Functions for usblp control messages.
  113.  */
  114. static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, int value, void *buf, int len)
  115. {
  116. int retval = usb_control_msg(usblp->dev,
  117. dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
  118. request, USB_TYPE_CLASS | dir | recip, value, usblp->ifnum, buf, len, HZ * 5);
  119. dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
  120. request, !!dir, recip, value, len, retval);
  121. return retval < 0 ? retval : 0;
  122. }
  123. #define usblp_read_status(usblp, status)
  124. usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
  125. #define usblp_get_id(usblp, config, id, maxlen)
  126. usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
  127. #define usblp_reset(usblp)
  128. usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
  129. /*
  130.  * URB callback.
  131.  */
  132. static void usblp_bulk(struct urb *urb)
  133. {
  134. struct usblp *usblp = urb->context;
  135. if (!usblp || !usblp->dev || !usblp->used)
  136. return;
  137. if (urb->status)
  138. warn("usblp%d: nonzero read/write bulk status received: %d",
  139. usblp->minor, urb->status);
  140. wake_up_interruptible(&usblp->wait);
  141. }
  142. /*
  143.  * Get and print printer errors.
  144.  */
  145. static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
  146. static int usblp_check_status(struct usblp *usblp, int err)
  147. {
  148. unsigned char status, newerr = 0;
  149. int error;
  150. error = usblp_read_status (usblp, &status);
  151. if (error < 0) {
  152. err("usblp%d: error %d reading printer status",
  153. usblp->minor, error);
  154. return 0;
  155. }
  156. if (~status & LP_PERRORP) {
  157. newerr = 3;
  158. if (status & LP_POUTPA) newerr = 1;
  159. if (~status & LP_PSELECD) newerr = 2;
  160. }
  161. if (newerr != err)
  162. info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
  163. return newerr;
  164. }
  165. /*
  166.  * File op functions.
  167.  */
  168. static int usblp_open(struct inode *inode, struct file *file)
  169. {
  170. int minor = MINOR(inode->i_rdev) - USBLP_MINOR_BASE;
  171. struct usblp *usblp;
  172. int retval;
  173. if (minor < 0 || minor >= USBLP_MINORS)
  174. return -ENODEV;
  175. lock_kernel();
  176. usblp  = usblp_table[minor];
  177. retval = -ENODEV;
  178. if (!usblp || !usblp->dev)
  179. goto out;
  180. retval = -EBUSY;
  181. if (usblp->used)
  182. goto out;
  183. /*
  184.  * TODO: need to implement LP_ABORTOPEN + O_NONBLOCK as in drivers/char/lp.c ???
  185.  * This is #if 0-ed because we *don't* want to fail an open
  186.  * just because the printer is off-line.
  187.  */
  188. #if 0
  189. if ((retval = usblp_check_status(usblp, 0))) {
  190. retval = retval > 1 ? -EIO : -ENOSPC;
  191. goto out;
  192. }
  193. #else
  194. retval = 0;
  195. #endif
  196. usblp->used = 1;
  197. file->private_data = usblp;
  198. usblp->writeurb.transfer_buffer_length = 0;
  199. usblp->writeurb.status = 0;
  200. if (usblp->bidir) {
  201. usblp->readcount = 0;
  202. usblp->readurb.dev = usblp->dev;
  203. if (usb_submit_urb(&usblp->readurb) < 0) {
  204. retval = -EIO;
  205. usblp->used = 0;
  206. file->private_data = NULL;
  207. }
  208. }
  209. out:
  210. unlock_kernel();
  211. return retval;
  212. }
  213. static void usblp_cleanup (struct usblp *usblp)
  214. {
  215. devfs_unregister (usblp->devfs);
  216. usblp_table [usblp->minor] = NULL;
  217. info ("usblp%d: removed", usblp->minor);
  218. kfree (usblp->writeurb.transfer_buffer);
  219. kfree (usblp->device_id_string);
  220. kfree (usblp);
  221. }
  222. static int usblp_release(struct inode *inode, struct file *file)
  223. {
  224. struct usblp *usblp = file->private_data;
  225. down (&usblp->sem);
  226. lock_kernel();
  227. usblp->used = 0;
  228. if (usblp->dev) {
  229. if (usblp->bidir)
  230. usb_unlink_urb(&usblp->readurb);
  231. usb_unlink_urb(&usblp->writeurb);
  232. up(&usblp->sem);
  233. } else  /* finish cleanup from disconnect */
  234. usblp_cleanup (usblp);
  235. unlock_kernel();
  236. return 0;
  237. }
  238. /* No kernel lock - fine */
  239. static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
  240. {
  241. struct usblp *usblp = file->private_data;
  242. poll_wait(file, &usblp->wait, wait);
  243.   return ((!usblp->bidir || usblp->readurb.status  == -EINPROGRESS) ? 0 : POLLIN  | POLLRDNORM)
  244.          | (usblp->writeurb.status == -EINPROGRESS  ? 0 : POLLOUT | POLLWRNORM);
  245. }
  246. static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  247. {
  248. struct usblp *usblp = file->private_data;
  249. int length, err;
  250. unsigned char status;
  251. int retval = 0;
  252. down (&usblp->sem);
  253. if (!usblp->dev) {
  254. retval = -ENODEV;
  255. goto done;
  256. }
  257. if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */
  258. switch (_IOC_NR(cmd)) {
  259. case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
  260. if (_IOC_DIR(cmd) != _IOC_READ) {
  261. retval = -EINVAL;
  262. goto done;
  263. }
  264. err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
  265. if (err < 0) {
  266. dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string",
  267. usblp->minor, err);
  268. usblp->device_id_string[0] = usblp->device_id_string[1] = '';
  269. retval = -EIO;
  270. goto done;
  271. }
  272. length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
  273. if (length < DEVICE_ID_SIZE)
  274. usblp->device_id_string[length] = '';
  275. else
  276. usblp->device_id_string[DEVICE_ID_SIZE - 1] = '';
  277. dbg ("usblp%d Device ID string [%d/max %d]='%s'",
  278. usblp->minor, length, _IOC_SIZE(cmd), &usblp->device_id_string[2]);
  279. if (length > _IOC_SIZE(cmd)) length = _IOC_SIZE(cmd); /* truncate */
  280. if (copy_to_user((unsigned char *) arg,
  281. usblp->device_id_string, (unsigned long) length)) {
  282. retval = -EFAULT;
  283. goto done;
  284. }
  285. break;
  286. default:
  287. retval = -EINVAL;
  288. }
  289. else /* old-style ioctl value */
  290. switch (cmd) {
  291. case LPGETSTATUS:
  292. if (usblp_read_status(usblp, &status)) {
  293. err("usblp%d: failed reading printer status", usblp->minor);
  294. retval = -EIO;
  295. goto done;
  296. }
  297. if (copy_to_user ((unsigned char *)arg, &status, 1))
  298. retval = -EFAULT;
  299. break;
  300. default:
  301. retval = -EINVAL;
  302. }
  303. done:
  304. up (&usblp->sem);
  305. return retval;
  306. }
  307. static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
  308. {
  309. struct usblp *usblp = file->private_data;
  310. int timeout, err = 0, writecount = 0;
  311. while (writecount < count) {
  312. // FIXME:  only use urb->status inside completion
  313. // callbacks; this way is racey...
  314. if (usblp->writeurb.status == -EINPROGRESS) {
  315. if (file->f_flags & O_NONBLOCK)
  316. return -EAGAIN;
  317. timeout = USBLP_WRITE_TIMEOUT;
  318. while (timeout && usblp->writeurb.status == -EINPROGRESS) {
  319. if (signal_pending(current))
  320. return writecount ? writecount : -EINTR;
  321. timeout = interruptible_sleep_on_timeout(&usblp->wait, timeout);
  322. }
  323. }
  324. down (&usblp->sem);
  325. if (!usblp->dev) {
  326. up (&usblp->sem);
  327. return -ENODEV;
  328. }
  329. if (usblp->writeurb.status != 0) {
  330. if (usblp->quirks & USBLP_QUIRK_BIDIR) {
  331. if (usblp->writeurb.status != -EINPROGRESS)
  332. err("usblp%d: error %d writing to printer",
  333. usblp->minor, usblp->writeurb.status);
  334. err = usblp->writeurb.status;
  335. } else
  336. err = usblp_check_status(usblp, err);
  337. up (&usblp->sem);
  338. /* if the fault was due to disconnect, let khubd's
  339.  * call to usblp_disconnect() grab usblp->sem ...
  340.  */
  341. schedule ();
  342. continue;
  343. }
  344. writecount += usblp->writeurb.transfer_buffer_length;
  345. usblp->writeurb.transfer_buffer_length = 0;
  346. if (writecount == count) {
  347. up (&usblp->sem);
  348. break;
  349. }
  350. usblp->writeurb.transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
  351.  (count - writecount) : USBLP_BUF_SIZE;
  352. if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount,
  353. usblp->writeurb.transfer_buffer_length)) return -EFAULT;
  354. usblp->writeurb.dev = usblp->dev;
  355. usb_submit_urb(&usblp->writeurb);
  356. up (&usblp->sem);
  357. }
  358. return count;
  359. }
  360. static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
  361. {
  362. struct usblp *usblp = file->private_data;
  363. if (!usblp->bidir)
  364. return -EINVAL;
  365. down (&usblp->sem);
  366. if (!usblp->dev) {
  367. count = -ENODEV;
  368. goto done;
  369. }
  370. if (usblp->readurb.status == -EINPROGRESS) {
  371. if (file->f_flags & O_NONBLOCK) {
  372. count = -EAGAIN;
  373. goto done;
  374. }
  375. // FIXME:  only use urb->status inside completion
  376. // callbacks; this way is racey...
  377. while (usblp->readurb.status == -EINPROGRESS) {
  378. if (signal_pending(current)) {
  379. count = -EINTR;
  380. goto done;
  381. }
  382. up (&usblp->sem);
  383. interruptible_sleep_on(&usblp->wait);
  384. down (&usblp->sem);
  385. }
  386. }
  387. if (!usblp->dev) {
  388. count = -ENODEV;
  389. goto done;
  390. }
  391. if (usblp->readurb.status) {
  392. err("usblp%d: error %d reading from printer",
  393. usblp->minor, usblp->readurb.status);
  394. usblp->readurb.dev = usblp->dev;
  395.   usblp->readcount = 0;
  396. usb_submit_urb(&usblp->readurb);
  397. count = -EIO;
  398. goto done;
  399. }
  400. count = count < usblp->readurb.actual_length - usblp->readcount ?
  401. count : usblp->readurb.actual_length - usblp->readcount;
  402. if (copy_to_user(buffer, usblp->readurb.transfer_buffer + usblp->readcount, count)) {
  403. count = -EFAULT;
  404. goto done;
  405. }
  406. if ((usblp->readcount += count) == usblp->readurb.actual_length) {
  407. usblp->readcount = 0;
  408. usblp->readurb.dev = usblp->dev;
  409. usb_submit_urb(&usblp->readurb);
  410. }
  411. done:
  412. up (&usblp->sem);
  413. return count;
  414. }
  415. /*
  416.  * Checks for printers that have quirks, such as requiring unidirectional
  417.  * communication but reporting bidirectional; currently some HP printers
  418.  * have this flaw (HP 810, 880, 895, etc.), or needing an init string
  419.  * sent at each open (like some Epsons).
  420.  * Returns 1 if found, 0 if not found.
  421.  *
  422.  * HP recommended that we use the bidirectional interface but
  423.  * don't attempt any bulk IN transfers from the IN endpoint.
  424.  * Here's some more detail on the problem:
  425.  * The problem is not that it isn't bidirectional though. The problem
  426.  * is that if you request a device ID, or status information, while
  427.  * the buffers are full, the return data will end up in the print data
  428.  * buffer. For example if you make sure you never request the device ID
  429.  * while you are sending print data, and you don't try to query the
  430.  * printer status every couple of milliseconds, you will probably be OK.
  431.  */
  432. static unsigned int usblp_quirks (__u16 vendor, __u16 product)
  433. {
  434. int i;
  435. for (i = 0; quirk_printers[i].vendorId; i++) {
  436. if (vendor == quirk_printers[i].vendorId &&
  437.     product == quirk_printers[i].productId)
  438. return quirk_printers[i].quirks;
  439.   }
  440. return 0;
  441. }
  442. static struct file_operations usblp_fops = {
  443. owner: THIS_MODULE,
  444. read: usblp_read,
  445. write: usblp_write,
  446. poll: usblp_poll,
  447. ioctl: usblp_ioctl,
  448. open: usblp_open,
  449. release: usblp_release,
  450. };
  451. static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
  452.  const struct usb_device_id *id)
  453. {
  454. struct usb_interface_descriptor *interface;
  455. struct usb_endpoint_descriptor *epread, *epwrite;
  456. struct usblp *usblp;
  457. int minor, i, bidir = 0, quirks;
  458. int alts = dev->actconfig->interface[ifnum].act_altsetting;
  459. int length, err;
  460. char *buf;
  461. char name[6];
  462. /* If a bidirectional interface exists, use it. */
  463. for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) {
  464. interface = &dev->actconfig->interface[ifnum].altsetting[i];
  465. if (interface->bInterfaceClass != 7 || interface->bInterfaceSubClass != 1 ||
  466.     interface->bInterfaceProtocol < 1 || interface->bInterfaceProtocol > 3 ||
  467.    (interface->bInterfaceProtocol > 1 && interface->bNumEndpoints < 2))
  468. continue;
  469. if (interface->bInterfaceProtocol > 1) {
  470. bidir = 1;
  471. alts = i;
  472. break;
  473. }
  474. }
  475. interface = &dev->actconfig->interface[ifnum].altsetting[alts];
  476. if (usb_set_interface(dev, ifnum, alts))
  477. err("can't set desired altsetting %d on interface %d", alts, ifnum);
  478. epwrite = interface->endpoint + 0;
  479. epread = bidir ? interface->endpoint + 1 : NULL;
  480. if ((epwrite->bEndpointAddress & 0x80) == 0x80) {
  481. if (interface->bNumEndpoints == 1)
  482. return NULL;
  483. epwrite = interface->endpoint + 1;
  484. epread = bidir ? interface->endpoint + 0 : NULL;
  485. }
  486. if ((epwrite->bEndpointAddress & 0x80) == 0x80)
  487. return NULL;
  488. if (bidir && (epread->bEndpointAddress & 0x80) != 0x80)
  489. return NULL;
  490. for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
  491. if (usblp_table[minor]) {
  492. err("no more free usblp devices");
  493. return NULL;
  494. }
  495. if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
  496. err("out of memory");
  497. return NULL;
  498. }
  499. memset(usblp, 0, sizeof(struct usblp));
  500. init_MUTEX (&usblp->sem);
  501. /* lookup quirks for this printer */
  502. quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
  503. if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
  504. bidir = 0;
  505. epread = NULL;
  506. info ("Disabling reads from problem bidirectional printer on usblp%d",
  507. minor);
  508. }
  509. usblp->dev = dev;
  510. usblp->ifnum = ifnum;
  511. usblp->minor = minor;
  512. usblp->bidir = bidir;
  513. usblp->quirks = quirks;
  514. init_waitqueue_head(&usblp->wait);
  515. if (!(buf = kmalloc(USBLP_BUF_SIZE * (bidir ? 2 : 1), GFP_KERNEL))) {
  516. err("out of memory");
  517. kfree(usblp);
  518. return NULL;
  519. }
  520. if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
  521. err("out of memory");
  522. kfree(usblp);
  523. kfree(buf);
  524. return NULL;
  525. }
  526. FILL_BULK_URB(&usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
  527. buf, 0, usblp_bulk, usblp);
  528. if (bidir)
  529. FILL_BULK_URB(&usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
  530. buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp);
  531. /* Get the device_id string if possible. FIXME: Could make this kmalloc(length). */
  532. err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
  533. if (err >= 0) {
  534. length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
  535. if (length < DEVICE_ID_SIZE)
  536. usblp->device_id_string[length] = '';
  537. else
  538. usblp->device_id_string[DEVICE_ID_SIZE - 1] = '';
  539. dbg ("usblp%d Device ID string [%d]=%s",
  540. minor, length, &usblp->device_id_string[2]);
  541. }
  542. else {
  543. err ("usblp%d: error = %d reading IEEE-1284 Device ID string",
  544. minor, err);
  545. usblp->device_id_string[0] = usblp->device_id_string[1] = '';
  546. }
  547. #ifdef DEBUG
  548. usblp_check_status(usblp, 0);
  549. #endif
  550. sprintf(name, "lp%d", minor);
  551. /* if we have devfs, create with perms=660 */
  552. usblp->devfs = devfs_register(usb_devfs_handle, name,
  553.       DEVFS_FL_DEFAULT, USB_MAJOR,
  554.       USBLP_MINOR_BASE + minor,
  555.       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
  556.       S_IWGRP, &usblp_fops, NULL);
  557. info("usblp%d: USB %sdirectional printer dev %d if %d alt %d",
  558. minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
  559. return usblp_table[minor] = usblp;
  560. }
  561. static void usblp_disconnect(struct usb_device *dev, void *ptr)
  562. {
  563. struct usblp *usblp = ptr;
  564. if (!usblp || !usblp->dev) {
  565. err("bogus disconnect");
  566. BUG ();
  567. }
  568. down (&usblp->sem);
  569. lock_kernel();
  570. usblp->dev = NULL;
  571. usb_unlink_urb(&usblp->writeurb);
  572. if (usblp->bidir)
  573. usb_unlink_urb(&usblp->readurb);
  574. if (!usblp->used)
  575. usblp_cleanup (usblp);
  576. else  /* cleanup later, on close */
  577. up (&usblp->sem);
  578. unlock_kernel();
  579. }
  580. static struct usb_device_id usblp_ids [] = {
  581. { USB_DEVICE_INFO(7, 1, 1) },
  582. { USB_DEVICE_INFO(7, 1, 2) },
  583. { USB_DEVICE_INFO(7, 1, 3) },
  584. { USB_INTERFACE_INFO(7, 1, 1) },
  585. { USB_INTERFACE_INFO(7, 1, 2) },
  586. { USB_INTERFACE_INFO(7, 1, 3) },
  587. { } /* Terminating entry */
  588. };
  589. MODULE_DEVICE_TABLE (usb, usblp_ids);
  590. static struct usb_driver usblp_driver = {
  591. name: "usblp",
  592. probe: usblp_probe,
  593. disconnect: usblp_disconnect,
  594. fops: &usblp_fops,
  595. minor: USBLP_MINOR_BASE,
  596. id_table: usblp_ids,
  597. };
  598. static int __init usblp_init(void)
  599. {
  600. if (usb_register(&usblp_driver))
  601. return -1;
  602. info(DRIVER_VERSION ":" DRIVER_DESC);
  603. return 0;
  604. }
  605. static void __exit usblp_exit(void)
  606. {
  607. usb_deregister(&usblp_driver);
  608. }
  609. module_init(usblp_init);
  610. module_exit(usblp_exit);
  611. MODULE_AUTHOR( DRIVER_AUTHOR );
  612. MODULE_DESCRIPTION( DRIVER_DESC );
  613. MODULE_LICENSE("GPL");