1 |
1275 |
phoenix |
/*
|
2 |
|
|
* printer.c Version 0.11
|
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 |
|
|
# Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
|
9 |
|
|
# Copyright (c) 2001 David Paschal <paschal@rcsis.com>
|
10 |
|
|
*
|
11 |
|
|
* USB Printer Device Class driver for USB printers and printer cables
|
12 |
|
|
*
|
13 |
|
|
* Sponsored by SuSE
|
14 |
|
|
*
|
15 |
|
|
* ChangeLog:
|
16 |
|
|
* v0.1 - thorough cleaning, URBification, almost a rewrite
|
17 |
|
|
* v0.2 - some more cleanups
|
18 |
|
|
* v0.3 - cleaner again, waitqueue fixes
|
19 |
|
|
* v0.4 - fixes in unidirectional mode
|
20 |
|
|
* v0.5 - add DEVICE_ID string support
|
21 |
|
|
* v0.6 - never time out
|
22 |
|
|
* v0.7 - fixed bulk-IN read and poll (David Paschal)
|
23 |
|
|
* v0.8 - add devfs support
|
24 |
|
|
* v0.9 - fix unplug-while-open paths
|
25 |
|
|
* v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
|
26 |
|
|
* v0.11 - add proto_bias option (Pete Zaitcev)
|
27 |
|
|
* v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
|
28 |
|
|
* v0.13 - alloc space for statusbuf (<status> not on stack);
|
29 |
|
|
* use usb_buffer_alloc() for read buf & write buf;
|
30 |
|
|
*/
|
31 |
|
|
|
32 |
|
|
/*
|
33 |
|
|
* This program is free software; you can redistribute it and/or modify
|
34 |
|
|
* it under the terms of the GNU General Public License as published by
|
35 |
|
|
* the Free Software Foundation; either version 2 of the License, or
|
36 |
|
|
* (at your option) any later version.
|
37 |
|
|
*
|
38 |
|
|
* This program is distributed in the hope that it will be useful,
|
39 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
40 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
41 |
|
|
* GNU General Public License for more details.
|
42 |
|
|
*
|
43 |
|
|
* You should have received a copy of the GNU General Public License
|
44 |
|
|
* along with this program; if not, write to the Free Software
|
45 |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
46 |
|
|
*/
|
47 |
|
|
|
48 |
|
|
#include <linux/module.h>
|
49 |
|
|
#include <linux/kernel.h>
|
50 |
|
|
#include <linux/sched.h>
|
51 |
|
|
#include <linux/smp_lock.h>
|
52 |
|
|
#include <linux/signal.h>
|
53 |
|
|
#include <linux/poll.h>
|
54 |
|
|
#include <linux/init.h>
|
55 |
|
|
#include <linux/slab.h>
|
56 |
|
|
#include <linux/lp.h>
|
57 |
|
|
#include <linux/devfs_fs_kernel.h>
|
58 |
|
|
#undef DEBUG
|
59 |
|
|
#include <linux/usb.h>
|
60 |
|
|
|
61 |
|
|
/*
|
62 |
|
|
* Version Information
|
63 |
|
|
*/
|
64 |
|
|
#define DRIVER_VERSION "v0.13"
|
65 |
|
|
#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
|
66 |
|
|
#define DRIVER_DESC "USB Printer Device Class driver"
|
67 |
|
|
|
68 |
|
|
#define USBLP_BUF_SIZE 8192
|
69 |
|
|
#define USBLP_DEVICE_ID_SIZE 1024
|
70 |
|
|
|
71 |
|
|
/* ioctls: */
|
72 |
|
|
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
|
73 |
|
|
#define IOCNR_GET_DEVICE_ID 1
|
74 |
|
|
#define IOCNR_GET_PROTOCOLS 2
|
75 |
|
|
#define IOCNR_SET_PROTOCOL 3
|
76 |
|
|
#define IOCNR_HP_SET_CHANNEL 4
|
77 |
|
|
#define IOCNR_GET_BUS_ADDRESS 5
|
78 |
|
|
#define IOCNR_GET_VID_PID 6
|
79 |
|
|
/* Get device_id string: */
|
80 |
|
|
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
|
81 |
|
|
/* The following ioctls were added for http://hpoj.sourceforge.net: */
|
82 |
|
|
/* Get two-int array:
|
83 |
|
|
* [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
|
84 |
|
|
* [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
|
85 |
|
|
#define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
|
86 |
|
|
/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
|
87 |
|
|
#define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
|
88 |
|
|
/* Set channel number (HP Vendor-specific command): */
|
89 |
|
|
#define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
|
90 |
|
|
/* Get two-int array: [0]=bus number, [1]=device address: */
|
91 |
|
|
#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
|
92 |
|
|
/* Get two-int array: [0]=vendor ID, [1]=product ID: */
|
93 |
|
|
#define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
|
94 |
|
|
|
95 |
|
|
/*
|
96 |
|
|
* A DEVICE_ID string may include the printer's serial number.
|
97 |
|
|
* It should end with a semi-colon (';').
|
98 |
|
|
* An example from an HP 970C DeskJet printer is (this is one long string,
|
99 |
|
|
* with the serial number changed):
|
100 |
|
|
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: ;
|
101 |
|
|
*/
|
102 |
|
|
|
103 |
|
|
/*
|
104 |
|
|
* USB Printer Requests
|
105 |
|
|
*/
|
106 |
|
|
|
107 |
|
|
#define USBLP_REQ_GET_ID 0x00
|
108 |
|
|
#define USBLP_REQ_GET_STATUS 0x01
|
109 |
|
|
#define USBLP_REQ_RESET 0x02
|
110 |
|
|
#define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST 0x00 /* HP Vendor-specific */
|
111 |
|
|
|
112 |
|
|
#define USBLP_MINORS 16
|
113 |
|
|
#define USBLP_MINOR_BASE 0
|
114 |
|
|
|
115 |
|
|
#define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */
|
116 |
|
|
|
117 |
|
|
#define USBLP_FIRST_PROTOCOL 1
|
118 |
|
|
#define USBLP_LAST_PROTOCOL 3
|
119 |
|
|
#define USBLP_MAX_PROTOCOLS (USBLP_LAST_PROTOCOL+1)
|
120 |
|
|
|
121 |
|
|
/*
|
122 |
|
|
* some arbitrary status buffer size;
|
123 |
|
|
* need a status buffer that is allocated via kmalloc(), not on stack
|
124 |
|
|
*/
|
125 |
|
|
#define STATUS_BUF_SIZE 8
|
126 |
|
|
|
127 |
|
|
struct usblp {
|
128 |
|
|
struct usb_device *dev; /* USB device */
|
129 |
|
|
devfs_handle_t devfs; /* devfs device */
|
130 |
|
|
struct semaphore sem; /* locks this struct, especially "dev" */
|
131 |
|
|
char *writebuf; /* write transfer_buffer */
|
132 |
|
|
char *readbuf; /* read transfer_buffer */
|
133 |
|
|
char *statusbuf; /* status transfer_buffer */
|
134 |
|
|
struct urb *readurb, *writeurb; /* The urbs */
|
135 |
|
|
wait_queue_head_t wait; /* Zzzzz ... */
|
136 |
|
|
int readcount; /* Counter for reads */
|
137 |
|
|
int ifnum; /* Interface number */
|
138 |
|
|
/* Alternate-setting numbers and endpoints for each protocol
|
139 |
|
|
* (7/1/{index=1,2,3}) that the device supports: */
|
140 |
|
|
struct {
|
141 |
|
|
int alt_setting;
|
142 |
|
|
struct usb_endpoint_descriptor *epwrite;
|
143 |
|
|
struct usb_endpoint_descriptor *epread;
|
144 |
|
|
} protocol[USBLP_MAX_PROTOCOLS];
|
145 |
|
|
int current_protocol;
|
146 |
|
|
int minor; /* minor number of device */
|
147 |
|
|
int wcomplete; /* writing is completed */
|
148 |
|
|
int rcomplete; /* reading is completed */
|
149 |
|
|
unsigned int quirks; /* quirks flags */
|
150 |
|
|
unsigned char used; /* True if open */
|
151 |
|
|
unsigned char present; /* True if not disconnected */
|
152 |
|
|
unsigned char bidir; /* interface is bidirectional */
|
153 |
|
|
unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */
|
154 |
|
|
/* first 2 bytes are (big-endian) length */
|
155 |
|
|
};
|
156 |
|
|
|
157 |
|
|
#ifdef DEBUG
|
158 |
|
|
static void usblp_dump(struct usblp *usblp) {
|
159 |
|
|
int p;
|
160 |
|
|
|
161 |
|
|
dbg("usblp=0x%p", usblp);
|
162 |
|
|
dbg("dev=0x%p", usblp->dev);
|
163 |
|
|
dbg("present=%d", usblp->present);
|
164 |
|
|
dbg("readbuf=0x%p", usblp->readbuf);
|
165 |
|
|
dbg("writebuf=0x%p", usblp->writebuf);
|
166 |
|
|
dbg("readurb=0x%p", usblp->readurb);
|
167 |
|
|
dbg("writeurb=0x%p", usblp->writeurb);
|
168 |
|
|
dbg("readcount=%d", usblp->readcount);
|
169 |
|
|
dbg("ifnum=%d", usblp->ifnum);
|
170 |
|
|
for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
|
171 |
|
|
dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
|
172 |
|
|
dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
|
173 |
|
|
dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
|
174 |
|
|
}
|
175 |
|
|
dbg("current_protocol=%d", usblp->current_protocol);
|
176 |
|
|
dbg("minor=%d", usblp->minor);
|
177 |
|
|
dbg("wcomplete=%d", usblp->wcomplete);
|
178 |
|
|
dbg("rcomplete=%d", usblp->rcomplete);
|
179 |
|
|
dbg("quirks=%d", usblp->quirks);
|
180 |
|
|
dbg("used=%d", usblp->used);
|
181 |
|
|
dbg("bidir=%d", usblp->bidir);
|
182 |
|
|
dbg("device_id_string=\"%s\"",
|
183 |
|
|
usblp->device_id_string ?
|
184 |
|
|
usblp->device_id_string + 2 :
|
185 |
|
|
(unsigned char *)"(null)");
|
186 |
|
|
}
|
187 |
|
|
#endif
|
188 |
|
|
|
189 |
|
|
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
|
190 |
|
|
|
191 |
|
|
static struct usblp *usblp_table[USBLP_MINORS];
|
192 |
|
|
|
193 |
|
|
/* Quirks: various printer quirks are handled by this table & its flags. */
|
194 |
|
|
|
195 |
|
|
struct quirk_printer_struct {
|
196 |
|
|
__u16 vendorId;
|
197 |
|
|
__u16 productId;
|
198 |
|
|
unsigned int quirks;
|
199 |
|
|
};
|
200 |
|
|
|
201 |
|
|
#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */
|
202 |
|
|
#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
|
203 |
|
|
|
204 |
|
|
static struct quirk_printer_struct quirk_printers[] = {
|
205 |
|
|
{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
|
206 |
|
|
{ 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
|
207 |
|
|
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
|
208 |
|
|
{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
|
209 |
|
|
{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
|
210 |
|
|
{ 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */
|
211 |
|
|
{ 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */
|
212 |
|
|
{ 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */
|
213 |
|
|
{ 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */
|
214 |
|
|
{ 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
|
215 |
|
|
{ 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
|
216 |
|
|
{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
|
217 |
|
|
{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
|
218 |
|
|
{ 0, 0 }
|
219 |
|
|
};
|
220 |
|
|
|
221 |
|
|
static int usblp_select_alts(struct usblp *usblp);
|
222 |
|
|
static int usblp_set_protocol(struct usblp *usblp, int protocol);
|
223 |
|
|
static int usblp_cache_device_id_string(struct usblp *usblp);
|
224 |
|
|
|
225 |
|
|
|
226 |
|
|
/*
|
227 |
|
|
* Functions for usblp control messages.
|
228 |
|
|
*/
|
229 |
|
|
|
230 |
|
|
static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
|
231 |
|
|
{
|
232 |
|
|
int retval = usb_control_msg(usblp->dev,
|
233 |
|
|
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
|
234 |
|
|
request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
|
235 |
|
|
dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
|
236 |
|
|
request, !!dir, recip, value, len, retval);
|
237 |
|
|
return retval < 0 ? retval : 0;
|
238 |
|
|
}
|
239 |
|
|
|
240 |
|
|
#define usblp_read_status(usblp, status)\
|
241 |
|
|
usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
|
242 |
|
|
#define usblp_get_id(usblp, config, id, maxlen)\
|
243 |
|
|
usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
|
244 |
|
|
#define usblp_reset(usblp)\
|
245 |
|
|
usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
|
246 |
|
|
|
247 |
|
|
#define usblp_hp_channel_change_request(usblp, channel, buffer) \
|
248 |
|
|
usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
|
249 |
|
|
|
250 |
|
|
/*
|
251 |
|
|
* See the description for usblp_select_alts() below for the usage
|
252 |
|
|
* explanation. Look into your /proc/bus/usb/devices and dmesg in
|
253 |
|
|
* case of any trouble.
|
254 |
|
|
*/
|
255 |
|
|
static int proto_bias = -1;
|
256 |
|
|
|
257 |
|
|
/*
|
258 |
|
|
* URB callback.
|
259 |
|
|
*/
|
260 |
|
|
|
261 |
|
|
static void usblp_bulk_read(struct urb *urb)
|
262 |
|
|
{
|
263 |
|
|
struct usblp *usblp = urb->context;
|
264 |
|
|
|
265 |
|
|
if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
|
266 |
|
|
return;
|
267 |
|
|
|
268 |
|
|
if (unlikely(urb->status))
|
269 |
|
|
warn("usblp%d: nonzero read/write bulk status received: %d",
|
270 |
|
|
usblp->minor, urb->status);
|
271 |
|
|
usblp->rcomplete = 1;
|
272 |
|
|
wake_up_interruptible(&usblp->wait);
|
273 |
|
|
}
|
274 |
|
|
|
275 |
|
|
static void usblp_bulk_write(struct urb *urb)
|
276 |
|
|
{
|
277 |
|
|
struct usblp *usblp = urb->context;
|
278 |
|
|
|
279 |
|
|
if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
|
280 |
|
|
return;
|
281 |
|
|
|
282 |
|
|
if (unlikely(urb->status))
|
283 |
|
|
warn("usblp%d: nonzero read/write bulk status received: %d",
|
284 |
|
|
usblp->minor, urb->status);
|
285 |
|
|
usblp->wcomplete = 1;
|
286 |
|
|
wake_up_interruptible(&usblp->wait);
|
287 |
|
|
}
|
288 |
|
|
|
289 |
|
|
/*
|
290 |
|
|
* Get and print printer errors.
|
291 |
|
|
*/
|
292 |
|
|
|
293 |
|
|
static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
|
294 |
|
|
|
295 |
|
|
static int usblp_check_status(struct usblp *usblp, int err)
|
296 |
|
|
{
|
297 |
|
|
unsigned char status, newerr = 0;
|
298 |
|
|
int error;
|
299 |
|
|
|
300 |
|
|
error = usblp_read_status (usblp, usblp->statusbuf);
|
301 |
|
|
if (error < 0) {
|
302 |
|
|
err("usblp%d: error %d reading printer status",
|
303 |
|
|
usblp->minor, error);
|
304 |
|
|
return 0;
|
305 |
|
|
}
|
306 |
|
|
|
307 |
|
|
status = *usblp->statusbuf;
|
308 |
|
|
|
309 |
|
|
if (~status & LP_PERRORP)
|
310 |
|
|
newerr = 3;
|
311 |
|
|
if (status & LP_POUTPA)
|
312 |
|
|
newerr = 1;
|
313 |
|
|
if (~status & LP_PSELECD)
|
314 |
|
|
newerr = 2;
|
315 |
|
|
|
316 |
|
|
if (newerr != err)
|
317 |
|
|
info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
|
318 |
|
|
|
319 |
|
|
return newerr;
|
320 |
|
|
}
|
321 |
|
|
|
322 |
|
|
/*
|
323 |
|
|
* File op functions.
|
324 |
|
|
*/
|
325 |
|
|
|
326 |
|
|
static int usblp_open(struct inode *inode, struct file *file)
|
327 |
|
|
{
|
328 |
|
|
int minor = MINOR(inode->i_rdev) - USBLP_MINOR_BASE;
|
329 |
|
|
struct usblp *usblp;
|
330 |
|
|
int retval;
|
331 |
|
|
|
332 |
|
|
if (minor < 0 || minor >= USBLP_MINORS)
|
333 |
|
|
return -ENODEV;
|
334 |
|
|
|
335 |
|
|
lock_kernel();
|
336 |
|
|
usblp = usblp_table[minor];
|
337 |
|
|
|
338 |
|
|
retval = -ENODEV;
|
339 |
|
|
if (!usblp || !usblp->dev || !usblp->present)
|
340 |
|
|
goto out;
|
341 |
|
|
|
342 |
|
|
retval = -EBUSY;
|
343 |
|
|
if (usblp->used)
|
344 |
|
|
goto out;
|
345 |
|
|
|
346 |
|
|
/*
|
347 |
|
|
* TODO: need to implement LP_ABORTOPEN + O_NONBLOCK as in drivers/char/lp.c ???
|
348 |
|
|
* This is #if 0-ed because we *don't* want to fail an open
|
349 |
|
|
* just because the printer is off-line.
|
350 |
|
|
*/
|
351 |
|
|
#if 0
|
352 |
|
|
if ((retval = usblp_check_status(usblp, 0))) {
|
353 |
|
|
retval = retval > 1 ? -EIO : -ENOSPC;
|
354 |
|
|
goto out;
|
355 |
|
|
}
|
356 |
|
|
#else
|
357 |
|
|
retval = 0;
|
358 |
|
|
#endif
|
359 |
|
|
|
360 |
|
|
usblp->used = 1;
|
361 |
|
|
file->private_data = usblp;
|
362 |
|
|
|
363 |
|
|
usblp->writeurb->transfer_buffer_length = 0;
|
364 |
|
|
usblp->wcomplete = 1; /* we begin writeable */
|
365 |
|
|
usblp->rcomplete = 0;
|
366 |
|
|
|
367 |
|
|
if (usblp->bidir) {
|
368 |
|
|
usblp->readcount = 0;
|
369 |
|
|
usblp->readurb->dev = usblp->dev;
|
370 |
|
|
if (usb_submit_urb(usblp->readurb) < 0) {
|
371 |
|
|
retval = -EIO;
|
372 |
|
|
usblp->used = 0;
|
373 |
|
|
file->private_data = NULL;
|
374 |
|
|
}
|
375 |
|
|
}
|
376 |
|
|
out:
|
377 |
|
|
unlock_kernel();
|
378 |
|
|
return retval;
|
379 |
|
|
}
|
380 |
|
|
|
381 |
|
|
static void usblp_cleanup (struct usblp *usblp)
|
382 |
|
|
{
|
383 |
|
|
devfs_unregister (usblp->devfs);
|
384 |
|
|
usblp_table [usblp->minor] = NULL;
|
385 |
|
|
info("usblp%d: removed", usblp->minor);
|
386 |
|
|
|
387 |
|
|
kfree (usblp->writebuf);
|
388 |
|
|
kfree (usblp->readbuf);
|
389 |
|
|
kfree (usblp->device_id_string);
|
390 |
|
|
kfree (usblp->statusbuf);
|
391 |
|
|
usb_free_urb(usblp->writeurb);
|
392 |
|
|
usb_free_urb(usblp->readurb);
|
393 |
|
|
kfree (usblp);
|
394 |
|
|
}
|
395 |
|
|
|
396 |
|
|
static void usblp_unlink_urbs(struct usblp *usblp)
|
397 |
|
|
{
|
398 |
|
|
usb_unlink_urb(usblp->writeurb);
|
399 |
|
|
if (usblp->bidir)
|
400 |
|
|
usb_unlink_urb(usblp->readurb);
|
401 |
|
|
}
|
402 |
|
|
|
403 |
|
|
static int usblp_release(struct inode *inode, struct file *file)
|
404 |
|
|
{
|
405 |
|
|
struct usblp *usblp = file->private_data;
|
406 |
|
|
|
407 |
|
|
down (&usblp->sem);
|
408 |
|
|
lock_kernel();
|
409 |
|
|
usblp->used = 0;
|
410 |
|
|
if (usblp->present) {
|
411 |
|
|
usblp_unlink_urbs(usblp);
|
412 |
|
|
up(&usblp->sem);
|
413 |
|
|
} else /* finish cleanup from disconnect */
|
414 |
|
|
usblp_cleanup (usblp);
|
415 |
|
|
unlock_kernel();
|
416 |
|
|
return 0;
|
417 |
|
|
}
|
418 |
|
|
|
419 |
|
|
/* No kernel lock - fine */
|
420 |
|
|
static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
|
421 |
|
|
{
|
422 |
|
|
struct usblp *usblp = file->private_data;
|
423 |
|
|
poll_wait(file, &usblp->wait, wait);
|
424 |
|
|
return ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN | POLLRDNORM)
|
425 |
|
|
| (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
|
426 |
|
|
}
|
427 |
|
|
|
428 |
|
|
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
|
429 |
|
|
{
|
430 |
|
|
struct usblp *usblp = file->private_data;
|
431 |
|
|
int length, err, i;
|
432 |
|
|
unsigned char newChannel;
|
433 |
|
|
int status;
|
434 |
|
|
int twoints[2];
|
435 |
|
|
int retval = 0;
|
436 |
|
|
|
437 |
|
|
down (&usblp->sem);
|
438 |
|
|
if (!usblp->present) {
|
439 |
|
|
retval = -ENODEV;
|
440 |
|
|
goto done;
|
441 |
|
|
}
|
442 |
|
|
|
443 |
|
|
if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */
|
444 |
|
|
|
445 |
|
|
switch (_IOC_NR(cmd)) {
|
446 |
|
|
|
447 |
|
|
case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
|
448 |
|
|
if (_IOC_DIR(cmd) != _IOC_READ) {
|
449 |
|
|
retval = -EINVAL;
|
450 |
|
|
goto done;
|
451 |
|
|
}
|
452 |
|
|
|
453 |
|
|
length = usblp_cache_device_id_string(usblp);
|
454 |
|
|
if (length < 0) {
|
455 |
|
|
retval = length;
|
456 |
|
|
goto done;
|
457 |
|
|
}
|
458 |
|
|
if (length > _IOC_SIZE(cmd))
|
459 |
|
|
length = _IOC_SIZE(cmd); /* truncate */
|
460 |
|
|
|
461 |
|
|
if (copy_to_user((unsigned char *) arg,
|
462 |
|
|
usblp->device_id_string,
|
463 |
|
|
(unsigned long) length)) {
|
464 |
|
|
retval = -EFAULT;
|
465 |
|
|
goto done;
|
466 |
|
|
}
|
467 |
|
|
|
468 |
|
|
break;
|
469 |
|
|
|
470 |
|
|
case IOCNR_GET_PROTOCOLS:
|
471 |
|
|
if (_IOC_DIR(cmd) != _IOC_READ ||
|
472 |
|
|
_IOC_SIZE(cmd) < sizeof(twoints)) {
|
473 |
|
|
retval = -EINVAL;
|
474 |
|
|
goto done;
|
475 |
|
|
}
|
476 |
|
|
|
477 |
|
|
twoints[0] = usblp->current_protocol;
|
478 |
|
|
twoints[1] = 0;
|
479 |
|
|
for (i = USBLP_FIRST_PROTOCOL;
|
480 |
|
|
i <= USBLP_LAST_PROTOCOL; i++) {
|
481 |
|
|
if (usblp->protocol[i].alt_setting >= 0)
|
482 |
|
|
twoints[1] |= (1<<i);
|
483 |
|
|
}
|
484 |
|
|
|
485 |
|
|
if (copy_to_user((unsigned char *)arg,
|
486 |
|
|
(unsigned char *)twoints,
|
487 |
|
|
sizeof(twoints))) {
|
488 |
|
|
retval = -EFAULT;
|
489 |
|
|
goto done;
|
490 |
|
|
}
|
491 |
|
|
|
492 |
|
|
break;
|
493 |
|
|
|
494 |
|
|
case IOCNR_SET_PROTOCOL:
|
495 |
|
|
if (_IOC_DIR(cmd) != _IOC_WRITE) {
|
496 |
|
|
retval = -EINVAL;
|
497 |
|
|
goto done;
|
498 |
|
|
}
|
499 |
|
|
|
500 |
|
|
#ifdef DEBUG
|
501 |
|
|
if (arg == -10) {
|
502 |
|
|
usblp_dump(usblp);
|
503 |
|
|
break;
|
504 |
|
|
}
|
505 |
|
|
#endif
|
506 |
|
|
|
507 |
|
|
usblp_unlink_urbs(usblp);
|
508 |
|
|
retval = usblp_set_protocol(usblp, arg);
|
509 |
|
|
if (retval < 0) {
|
510 |
|
|
usblp_set_protocol(usblp,
|
511 |
|
|
usblp->current_protocol);
|
512 |
|
|
}
|
513 |
|
|
break;
|
514 |
|
|
|
515 |
|
|
case IOCNR_HP_SET_CHANNEL:
|
516 |
|
|
if (_IOC_DIR(cmd) != _IOC_WRITE ||
|
517 |
|
|
usblp->dev->descriptor.idVendor != 0x03F0 ||
|
518 |
|
|
usblp->quirks & USBLP_QUIRK_BIDIR) {
|
519 |
|
|
retval = -EINVAL;
|
520 |
|
|
goto done;
|
521 |
|
|
}
|
522 |
|
|
|
523 |
|
|
err = usblp_hp_channel_change_request(usblp,
|
524 |
|
|
arg, &newChannel);
|
525 |
|
|
if (err < 0) {
|
526 |
|
|
err("usblp%d: error = %d setting "
|
527 |
|
|
"HP channel",
|
528 |
|
|
usblp->minor, err);
|
529 |
|
|
retval = -EIO;
|
530 |
|
|
goto done;
|
531 |
|
|
}
|
532 |
|
|
|
533 |
|
|
dbg("usblp%d requested/got HP channel %ld/%d",
|
534 |
|
|
usblp->minor, arg, newChannel);
|
535 |
|
|
break;
|
536 |
|
|
|
537 |
|
|
case IOCNR_GET_BUS_ADDRESS:
|
538 |
|
|
if (_IOC_DIR(cmd) != _IOC_READ ||
|
539 |
|
|
_IOC_SIZE(cmd) < sizeof(twoints)) {
|
540 |
|
|
retval = -EINVAL;
|
541 |
|
|
goto done;
|
542 |
|
|
}
|
543 |
|
|
|
544 |
|
|
twoints[0] = usblp->dev->bus->busnum;
|
545 |
|
|
twoints[1] = usblp->dev->devnum;
|
546 |
|
|
if (copy_to_user((unsigned char *)arg,
|
547 |
|
|
(unsigned char *)twoints,
|
548 |
|
|
sizeof(twoints))) {
|
549 |
|
|
retval = -EFAULT;
|
550 |
|
|
goto done;
|
551 |
|
|
}
|
552 |
|
|
|
553 |
|
|
dbg("usblp%d is bus=%d, device=%d",
|
554 |
|
|
usblp->minor, twoints[0], twoints[1]);
|
555 |
|
|
break;
|
556 |
|
|
|
557 |
|
|
case IOCNR_GET_VID_PID:
|
558 |
|
|
if (_IOC_DIR(cmd) != _IOC_READ ||
|
559 |
|
|
_IOC_SIZE(cmd) < sizeof(twoints)) {
|
560 |
|
|
retval = -EINVAL;
|
561 |
|
|
goto done;
|
562 |
|
|
}
|
563 |
|
|
|
564 |
|
|
twoints[0] = usblp->dev->descriptor.idVendor;
|
565 |
|
|
twoints[1] = usblp->dev->descriptor.idProduct;
|
566 |
|
|
if (copy_to_user((unsigned char *)arg,
|
567 |
|
|
(unsigned char *)twoints,
|
568 |
|
|
sizeof(twoints))) {
|
569 |
|
|
retval = -EFAULT;
|
570 |
|
|
goto done;
|
571 |
|
|
}
|
572 |
|
|
|
573 |
|
|
dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
|
574 |
|
|
usblp->minor, twoints[0], twoints[1]);
|
575 |
|
|
break;
|
576 |
|
|
|
577 |
|
|
default:
|
578 |
|
|
retval = -ENOTTY;
|
579 |
|
|
}
|
580 |
|
|
else /* old-style ioctl value */
|
581 |
|
|
switch (cmd) {
|
582 |
|
|
|
583 |
|
|
case LPGETSTATUS:
|
584 |
|
|
if (usblp_read_status(usblp, usblp->statusbuf)) {
|
585 |
|
|
err("usblp%d: failed reading printer status", usblp->minor);
|
586 |
|
|
retval = -EIO;
|
587 |
|
|
goto done;
|
588 |
|
|
}
|
589 |
|
|
status = *usblp->statusbuf;
|
590 |
|
|
if (copy_to_user ((int *)arg, &status, sizeof(int)))
|
591 |
|
|
retval = -EFAULT;
|
592 |
|
|
break;
|
593 |
|
|
|
594 |
|
|
default:
|
595 |
|
|
retval = -ENOTTY;
|
596 |
|
|
}
|
597 |
|
|
|
598 |
|
|
done:
|
599 |
|
|
up (&usblp->sem);
|
600 |
|
|
return retval;
|
601 |
|
|
}
|
602 |
|
|
|
603 |
|
|
static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
|
604 |
|
|
{
|
605 |
|
|
DECLARE_WAITQUEUE(wait, current);
|
606 |
|
|
struct usblp *usblp = file->private_data;
|
607 |
|
|
int timeout, err = 0, transfer_length = 0;
|
608 |
|
|
size_t writecount = 0;
|
609 |
|
|
|
610 |
|
|
while (writecount < count) {
|
611 |
|
|
if (!usblp->wcomplete) {
|
612 |
|
|
barrier();
|
613 |
|
|
if (file->f_flags & O_NONBLOCK) {
|
614 |
|
|
writecount += transfer_length;
|
615 |
|
|
return writecount ? writecount : -EAGAIN;
|
616 |
|
|
}
|
617 |
|
|
|
618 |
|
|
timeout = USBLP_WRITE_TIMEOUT;
|
619 |
|
|
add_wait_queue(&usblp->wait, &wait);
|
620 |
|
|
while ( 1==1 ) {
|
621 |
|
|
|
622 |
|
|
if (signal_pending(current)) {
|
623 |
|
|
remove_wait_queue(&usblp->wait, &wait);
|
624 |
|
|
return writecount ? writecount : -EINTR;
|
625 |
|
|
}
|
626 |
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
627 |
|
|
if (timeout && !usblp->wcomplete) {
|
628 |
|
|
timeout = schedule_timeout(timeout);
|
629 |
|
|
} else {
|
630 |
|
|
set_current_state(TASK_RUNNING);
|
631 |
|
|
break;
|
632 |
|
|
}
|
633 |
|
|
}
|
634 |
|
|
remove_wait_queue(&usblp->wait, &wait);
|
635 |
|
|
}
|
636 |
|
|
|
637 |
|
|
down (&usblp->sem);
|
638 |
|
|
if (!usblp->present) {
|
639 |
|
|
up (&usblp->sem);
|
640 |
|
|
return -ENODEV;
|
641 |
|
|
}
|
642 |
|
|
|
643 |
|
|
if (usblp->writeurb->status != 0) {
|
644 |
|
|
if (usblp->quirks & USBLP_QUIRK_BIDIR) {
|
645 |
|
|
if (!usblp->wcomplete)
|
646 |
|
|
err("usblp%d: error %d writing to printer",
|
647 |
|
|
usblp->minor, usblp->writeurb->status);
|
648 |
|
|
err = usblp->writeurb->status;
|
649 |
|
|
} else
|
650 |
|
|
err = usblp_check_status(usblp, err);
|
651 |
|
|
up (&usblp->sem);
|
652 |
|
|
|
653 |
|
|
/* if the fault was due to disconnect, let khubd's
|
654 |
|
|
* call to usblp_disconnect() grab usblp->sem ...
|
655 |
|
|
*/
|
656 |
|
|
schedule ();
|
657 |
|
|
continue;
|
658 |
|
|
}
|
659 |
|
|
|
660 |
|
|
/* We must increment writecount here, and not at the
|
661 |
|
|
* end of the loop. Otherwise, the final loop iteration may
|
662 |
|
|
* be skipped, leading to incomplete printer output.
|
663 |
|
|
*/
|
664 |
|
|
writecount += transfer_length;
|
665 |
|
|
if (writecount == count) {
|
666 |
|
|
up (&usblp->sem);
|
667 |
|
|
break;
|
668 |
|
|
}
|
669 |
|
|
|
670 |
|
|
transfer_length = count - writecount;
|
671 |
|
|
if(transfer_length > USBLP_BUF_SIZE)
|
672 |
|
|
transfer_length = USBLP_BUF_SIZE;
|
673 |
|
|
|
674 |
|
|
usblp->writeurb->transfer_buffer_length = transfer_length;
|
675 |
|
|
|
676 |
|
|
if (copy_from_user(usblp->writeurb->transfer_buffer,
|
677 |
|
|
buffer + writecount, transfer_length)) {
|
678 |
|
|
up(&usblp->sem);
|
679 |
|
|
return writecount ? writecount : -EFAULT;
|
680 |
|
|
}
|
681 |
|
|
|
682 |
|
|
usblp->writeurb->dev = usblp->dev;
|
683 |
|
|
usblp->wcomplete = 0;
|
684 |
|
|
err = usb_submit_urb(usblp->writeurb);
|
685 |
|
|
if (err) {
|
686 |
|
|
if (err != -ENOMEM)
|
687 |
|
|
count = -EIO;
|
688 |
|
|
else
|
689 |
|
|
count = writecount ? writecount : -ENOMEM;
|
690 |
|
|
up (&usblp->sem);
|
691 |
|
|
break;
|
692 |
|
|
}
|
693 |
|
|
up (&usblp->sem);
|
694 |
|
|
}
|
695 |
|
|
|
696 |
|
|
return count;
|
697 |
|
|
}
|
698 |
|
|
|
699 |
|
|
static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
|
700 |
|
|
{
|
701 |
|
|
struct usblp *usblp = file->private_data;
|
702 |
|
|
DECLARE_WAITQUEUE(wait, current);
|
703 |
|
|
|
704 |
|
|
if (!usblp->bidir)
|
705 |
|
|
return -EINVAL;
|
706 |
|
|
|
707 |
|
|
down (&usblp->sem);
|
708 |
|
|
if (!usblp->present) {
|
709 |
|
|
count = -ENODEV;
|
710 |
|
|
goto done;
|
711 |
|
|
}
|
712 |
|
|
|
713 |
|
|
if (!usblp->rcomplete) {
|
714 |
|
|
barrier();
|
715 |
|
|
|
716 |
|
|
if (file->f_flags & O_NONBLOCK) {
|
717 |
|
|
count = -EAGAIN;
|
718 |
|
|
goto done;
|
719 |
|
|
}
|
720 |
|
|
|
721 |
|
|
add_wait_queue(&usblp->wait, &wait);
|
722 |
|
|
while (1==1) {
|
723 |
|
|
if (signal_pending(current)) {
|
724 |
|
|
count = -EINTR;
|
725 |
|
|
remove_wait_queue(&usblp->wait, &wait);
|
726 |
|
|
goto done;
|
727 |
|
|
}
|
728 |
|
|
up (&usblp->sem);
|
729 |
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
730 |
|
|
if (!usblp->rcomplete) {
|
731 |
|
|
schedule();
|
732 |
|
|
} else {
|
733 |
|
|
set_current_state(TASK_RUNNING);
|
734 |
|
|
break;
|
735 |
|
|
}
|
736 |
|
|
down (&usblp->sem);
|
737 |
|
|
}
|
738 |
|
|
remove_wait_queue(&usblp->wait, &wait);
|
739 |
|
|
}
|
740 |
|
|
|
741 |
|
|
if (!usblp->present) {
|
742 |
|
|
count = -ENODEV;
|
743 |
|
|
goto done;
|
744 |
|
|
}
|
745 |
|
|
|
746 |
|
|
if (usblp->readurb->status) {
|
747 |
|
|
err("usblp%d: error %d reading from printer",
|
748 |
|
|
usblp->minor, usblp->readurb->status);
|
749 |
|
|
usblp->readurb->dev = usblp->dev;
|
750 |
|
|
usblp->readcount = 0;
|
751 |
|
|
if (usb_submit_urb(usblp->readurb) < 0)
|
752 |
|
|
dbg("error submitting urb");
|
753 |
|
|
count = -EIO;
|
754 |
|
|
goto done;
|
755 |
|
|
}
|
756 |
|
|
|
757 |
|
|
count = count < usblp->readurb->actual_length - usblp->readcount ?
|
758 |
|
|
count : usblp->readurb->actual_length - usblp->readcount;
|
759 |
|
|
|
760 |
|
|
if (copy_to_user(buffer, usblp->readurb->transfer_buffer + usblp->readcount, count)) {
|
761 |
|
|
count = -EFAULT;
|
762 |
|
|
goto done;
|
763 |
|
|
}
|
764 |
|
|
|
765 |
|
|
if ((usblp->readcount += count) == usblp->readurb->actual_length) {
|
766 |
|
|
usblp->readcount = 0;
|
767 |
|
|
usblp->readurb->dev = usblp->dev;
|
768 |
|
|
usblp->rcomplete = 0;
|
769 |
|
|
if (usb_submit_urb(usblp->readurb)) {
|
770 |
|
|
count = -EIO;
|
771 |
|
|
goto done;
|
772 |
|
|
}
|
773 |
|
|
}
|
774 |
|
|
|
775 |
|
|
done:
|
776 |
|
|
up (&usblp->sem);
|
777 |
|
|
return count;
|
778 |
|
|
}
|
779 |
|
|
|
780 |
|
|
/*
|
781 |
|
|
* Checks for printers that have quirks, such as requiring unidirectional
|
782 |
|
|
* communication but reporting bidirectional; currently some HP printers
|
783 |
|
|
* have this flaw (HP 810, 880, 895, etc.), or needing an init string
|
784 |
|
|
* sent at each open (like some Epsons).
|
785 |
|
|
* Returns 1 if found, 0 if not found.
|
786 |
|
|
*
|
787 |
|
|
* HP recommended that we use the bidirectional interface but
|
788 |
|
|
* don't attempt any bulk IN transfers from the IN endpoint.
|
789 |
|
|
* Here's some more detail on the problem:
|
790 |
|
|
* The problem is not that it isn't bidirectional though. The problem
|
791 |
|
|
* is that if you request a device ID, or status information, while
|
792 |
|
|
* the buffers are full, the return data will end up in the print data
|
793 |
|
|
* buffer. For example if you make sure you never request the device ID
|
794 |
|
|
* while you are sending print data, and you don't try to query the
|
795 |
|
|
* printer status every couple of milliseconds, you will probably be OK.
|
796 |
|
|
*/
|
797 |
|
|
static unsigned int usblp_quirks (__u16 vendor, __u16 product)
|
798 |
|
|
{
|
799 |
|
|
int i;
|
800 |
|
|
|
801 |
|
|
for (i = 0; quirk_printers[i].vendorId; i++) {
|
802 |
|
|
if (vendor == quirk_printers[i].vendorId &&
|
803 |
|
|
product == quirk_printers[i].productId)
|
804 |
|
|
return quirk_printers[i].quirks;
|
805 |
|
|
}
|
806 |
|
|
return 0;
|
807 |
|
|
}
|
808 |
|
|
|
809 |
|
|
static struct file_operations usblp_fops = {
|
810 |
|
|
owner: THIS_MODULE,
|
811 |
|
|
read: usblp_read,
|
812 |
|
|
write: usblp_write,
|
813 |
|
|
poll: usblp_poll,
|
814 |
|
|
ioctl: usblp_ioctl,
|
815 |
|
|
open: usblp_open,
|
816 |
|
|
release: usblp_release,
|
817 |
|
|
};
|
818 |
|
|
|
819 |
|
|
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
|
820 |
|
|
const struct usb_device_id *id)
|
821 |
|
|
{
|
822 |
|
|
struct usblp *usblp = 0;
|
823 |
|
|
int protocol;
|
824 |
|
|
char name[6];
|
825 |
|
|
|
826 |
|
|
/* Malloc and start initializing usblp structure so we can use it
|
827 |
|
|
* directly. */
|
828 |
|
|
if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
|
829 |
|
|
err("out of memory for usblp");
|
830 |
|
|
goto abort;
|
831 |
|
|
}
|
832 |
|
|
memset(usblp, 0, sizeof(struct usblp));
|
833 |
|
|
usblp->dev = dev;
|
834 |
|
|
init_MUTEX (&usblp->sem);
|
835 |
|
|
init_waitqueue_head(&usblp->wait);
|
836 |
|
|
usblp->ifnum = ifnum;
|
837 |
|
|
|
838 |
|
|
/* Look for a free usblp_table entry. */
|
839 |
|
|
while (usblp_table[usblp->minor]) {
|
840 |
|
|
usblp->minor++;
|
841 |
|
|
if (usblp->minor >= USBLP_MINORS) {
|
842 |
|
|
err("no more free usblp devices");
|
843 |
|
|
goto abort;
|
844 |
|
|
}
|
845 |
|
|
}
|
846 |
|
|
|
847 |
|
|
usblp->writeurb = usb_alloc_urb(0);
|
848 |
|
|
if (!usblp->writeurb) {
|
849 |
|
|
err("out of memory");
|
850 |
|
|
goto abort;
|
851 |
|
|
}
|
852 |
|
|
usblp->readurb = usb_alloc_urb(0);
|
853 |
|
|
if (!usblp->readurb) {
|
854 |
|
|
err("out of memory");
|
855 |
|
|
goto abort;
|
856 |
|
|
}
|
857 |
|
|
|
858 |
|
|
/* Malloc device ID string buffer to the largest expected length,
|
859 |
|
|
* since we can re-query it on an ioctl and a dynamic string
|
860 |
|
|
* could change in length. */
|
861 |
|
|
if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
|
862 |
|
|
err("out of memory for device_id_string");
|
863 |
|
|
goto abort;
|
864 |
|
|
}
|
865 |
|
|
|
866 |
|
|
usblp->writebuf = usblp->readbuf = NULL;
|
867 |
|
|
/* Malloc write & read buffers. We somewhat wastefully
|
868 |
|
|
* malloc both regardless of bidirectionality, because the
|
869 |
|
|
* alternate setting can be changed later via an ioctl. */
|
870 |
|
|
if (!(usblp->writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL))) {
|
871 |
|
|
err("out of memory for write buf");
|
872 |
|
|
goto abort;
|
873 |
|
|
}
|
874 |
|
|
if (!(usblp->readbuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL))) {
|
875 |
|
|
err("out of memory for read buf");
|
876 |
|
|
goto abort;
|
877 |
|
|
}
|
878 |
|
|
|
879 |
|
|
/* Allocate buffer for printer status */
|
880 |
|
|
usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
|
881 |
|
|
if (!usblp->statusbuf) {
|
882 |
|
|
err("out of memory for statusbuf");
|
883 |
|
|
goto abort;
|
884 |
|
|
}
|
885 |
|
|
|
886 |
|
|
/* Lookup quirks for this printer. */
|
887 |
|
|
usblp->quirks = usblp_quirks(
|
888 |
|
|
dev->descriptor.idVendor,
|
889 |
|
|
dev->descriptor.idProduct);
|
890 |
|
|
|
891 |
|
|
/* Analyze and pick initial alternate settings and endpoints. */
|
892 |
|
|
protocol = usblp_select_alts(usblp);
|
893 |
|
|
if (protocol < 0) {
|
894 |
|
|
dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
|
895 |
|
|
dev->descriptor.idVendor,
|
896 |
|
|
dev->descriptor.idProduct);
|
897 |
|
|
goto abort;
|
898 |
|
|
}
|
899 |
|
|
|
900 |
|
|
/* Setup the selected alternate setting and endpoints. */
|
901 |
|
|
if (usblp_set_protocol(usblp, protocol) < 0)
|
902 |
|
|
goto abort;
|
903 |
|
|
|
904 |
|
|
/* Retrieve and store the device ID string. */
|
905 |
|
|
usblp_cache_device_id_string(usblp);
|
906 |
|
|
|
907 |
|
|
#ifdef DEBUG
|
908 |
|
|
usblp_check_status(usblp, 0);
|
909 |
|
|
#endif
|
910 |
|
|
|
911 |
|
|
usblp_table[usblp->minor] = usblp;
|
912 |
|
|
/* If we have devfs, create with perms=660. */
|
913 |
|
|
sprintf(name, "lp%d", usblp->minor);
|
914 |
|
|
usblp->devfs = devfs_register(usb_devfs_handle, name,
|
915 |
|
|
DEVFS_FL_DEFAULT, USB_MAJOR,
|
916 |
|
|
USBLP_MINOR_BASE + usblp->minor,
|
917 |
|
|
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
|
918 |
|
|
S_IWGRP, &usblp_fops, NULL);
|
919 |
|
|
|
920 |
|
|
info("usblp%d: USB %sdirectional printer dev %d "
|
921 |
|
|
"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
|
922 |
|
|
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
|
923 |
|
|
usblp->ifnum,
|
924 |
|
|
usblp->protocol[usblp->current_protocol].alt_setting,
|
925 |
|
|
usblp->current_protocol, usblp->dev->descriptor.idVendor,
|
926 |
|
|
usblp->dev->descriptor.idProduct);
|
927 |
|
|
|
928 |
|
|
usblp->present = 1;
|
929 |
|
|
|
930 |
|
|
return usblp;
|
931 |
|
|
|
932 |
|
|
abort:
|
933 |
|
|
if (usblp) {
|
934 |
|
|
if (usblp->writebuf)
|
935 |
|
|
kfree (usblp->writebuf);
|
936 |
|
|
if (usblp->readbuf)
|
937 |
|
|
kfree (usblp->readbuf);
|
938 |
|
|
kfree(usblp->statusbuf);
|
939 |
|
|
kfree(usblp->device_id_string);
|
940 |
|
|
usb_free_urb(usblp->writeurb);
|
941 |
|
|
usb_free_urb(usblp->readurb);
|
942 |
|
|
kfree(usblp);
|
943 |
|
|
}
|
944 |
|
|
return NULL;
|
945 |
|
|
}
|
946 |
|
|
|
947 |
|
|
/*
|
948 |
|
|
* We are a "new" style driver with usb_device_id table,
|
949 |
|
|
* but our requirements are too intricate for simple match to handle.
|
950 |
|
|
*
|
951 |
|
|
* The "proto_bias" option may be used to specify the preferred protocol
|
952 |
|
|
* for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3). If the device
|
953 |
|
|
* supports the preferred protocol, then we bind to it.
|
954 |
|
|
*
|
955 |
|
|
* The best interface for us is 7/1/2, because it is compatible
|
956 |
|
|
* with a stream of characters. If we find it, we bind to it.
|
957 |
|
|
*
|
958 |
|
|
* Note that the people from hpoj.sourceforge.net need to be able to
|
959 |
|
|
* bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
|
960 |
|
|
*
|
961 |
|
|
* Failing 7/1/2, we look for 7/1/3, even though it's probably not
|
962 |
|
|
* stream-compatible, because this matches the behaviour of the old code.
|
963 |
|
|
*
|
964 |
|
|
* If nothing else, we bind to 7/1/1 - the unidirectional interface.
|
965 |
|
|
*/
|
966 |
|
|
static int usblp_select_alts(struct usblp *usblp)
|
967 |
|
|
{
|
968 |
|
|
struct usb_interface *if_alt;
|
969 |
|
|
struct usb_interface_descriptor *ifd;
|
970 |
|
|
struct usb_endpoint_descriptor *epd, *epwrite, *epread;
|
971 |
|
|
int p, i, e;
|
972 |
|
|
|
973 |
|
|
if_alt = &usblp->dev->actconfig->interface[usblp->ifnum];
|
974 |
|
|
|
975 |
|
|
for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
|
976 |
|
|
usblp->protocol[p].alt_setting = -1;
|
977 |
|
|
|
978 |
|
|
/* Find out what we have. */
|
979 |
|
|
for (i = 0; i < if_alt->num_altsetting; i++) {
|
980 |
|
|
ifd = &if_alt->altsetting[i];
|
981 |
|
|
|
982 |
|
|
if (ifd->bInterfaceClass != 7 || ifd->bInterfaceSubClass != 1)
|
983 |
|
|
continue;
|
984 |
|
|
|
985 |
|
|
if (ifd->bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
|
986 |
|
|
ifd->bInterfaceProtocol > USBLP_LAST_PROTOCOL)
|
987 |
|
|
continue;
|
988 |
|
|
|
989 |
|
|
/* Look for bulk OUT and IN endpoints. */
|
990 |
|
|
epwrite = epread = 0;
|
991 |
|
|
for (e = 0; e < ifd->bNumEndpoints; e++) {
|
992 |
|
|
epd = &ifd->endpoint[e];
|
993 |
|
|
|
994 |
|
|
if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
|
995 |
|
|
USB_ENDPOINT_XFER_BULK)
|
996 |
|
|
continue;
|
997 |
|
|
|
998 |
|
|
if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
|
999 |
|
|
if (!epwrite) epwrite=epd;
|
1000 |
|
|
|
1001 |
|
|
} else {
|
1002 |
|
|
if (!epread) epread=epd;
|
1003 |
|
|
}
|
1004 |
|
|
}
|
1005 |
|
|
|
1006 |
|
|
/* Ignore buggy hardware without the right endpoints. */
|
1007 |
|
|
if (!epwrite || (ifd->bInterfaceProtocol > 1 && !epread))
|
1008 |
|
|
continue;
|
1009 |
|
|
|
1010 |
|
|
/* Turn off reads for 7/1/1 (unidirectional) interfaces
|
1011 |
|
|
* and buggy bidirectional printers. */
|
1012 |
|
|
if (ifd->bInterfaceProtocol == 1) {
|
1013 |
|
|
epread = NULL;
|
1014 |
|
|
} else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
|
1015 |
|
|
info("Disabling reads from problem bidirectional "
|
1016 |
|
|
"printer on usblp%d", usblp->minor);
|
1017 |
|
|
epread = NULL;
|
1018 |
|
|
}
|
1019 |
|
|
|
1020 |
|
|
usblp->protocol[ifd->bInterfaceProtocol].alt_setting = i;
|
1021 |
|
|
usblp->protocol[ifd->bInterfaceProtocol].epwrite = epwrite;
|
1022 |
|
|
usblp->protocol[ifd->bInterfaceProtocol].epread = epread;
|
1023 |
|
|
}
|
1024 |
|
|
|
1025 |
|
|
/* If our requested protocol is supported, then use it. */
|
1026 |
|
|
if (proto_bias >= USBLP_FIRST_PROTOCOL &&
|
1027 |
|
|
proto_bias <= USBLP_LAST_PROTOCOL &&
|
1028 |
|
|
usblp->protocol[proto_bias].alt_setting != -1)
|
1029 |
|
|
return proto_bias;
|
1030 |
|
|
|
1031 |
|
|
/* Ordering is important here. */
|
1032 |
|
|
if (usblp->protocol[2].alt_setting != -1) return 2;
|
1033 |
|
|
if (usblp->protocol[1].alt_setting != -1) return 1;
|
1034 |
|
|
if (usblp->protocol[3].alt_setting != -1) return 3;
|
1035 |
|
|
|
1036 |
|
|
/* If nothing is available, then don't bind to this device. */
|
1037 |
|
|
return -1;
|
1038 |
|
|
}
|
1039 |
|
|
|
1040 |
|
|
static int usblp_set_protocol(struct usblp *usblp, int protocol)
|
1041 |
|
|
{
|
1042 |
|
|
int r, alts;
|
1043 |
|
|
|
1044 |
|
|
if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
|
1045 |
|
|
return -EINVAL;
|
1046 |
|
|
|
1047 |
|
|
alts = usblp->protocol[protocol].alt_setting;
|
1048 |
|
|
if (alts < 0) return -EINVAL;
|
1049 |
|
|
r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
|
1050 |
|
|
if (r < 0) {
|
1051 |
|
|
err("can't set desired altsetting %d on interface %d",
|
1052 |
|
|
alts, usblp->ifnum);
|
1053 |
|
|
return r;
|
1054 |
|
|
}
|
1055 |
|
|
|
1056 |
|
|
usb_fill_bulk_urb(usblp->writeurb, usblp->dev,
|
1057 |
|
|
usb_sndbulkpipe(usblp->dev,
|
1058 |
|
|
usblp->protocol[protocol].epwrite->bEndpointAddress),
|
1059 |
|
|
usblp->writebuf, 0,
|
1060 |
|
|
usblp_bulk_write, usblp);
|
1061 |
|
|
|
1062 |
|
|
usblp->bidir = (usblp->protocol[protocol].epread != 0);
|
1063 |
|
|
if (usblp->bidir)
|
1064 |
|
|
usb_fill_bulk_urb(usblp->readurb, usblp->dev,
|
1065 |
|
|
usb_rcvbulkpipe(usblp->dev,
|
1066 |
|
|
usblp->protocol[protocol].epread->bEndpointAddress),
|
1067 |
|
|
usblp->readbuf, USBLP_BUF_SIZE,
|
1068 |
|
|
usblp_bulk_read, usblp);
|
1069 |
|
|
|
1070 |
|
|
usblp->current_protocol = protocol;
|
1071 |
|
|
dbg("usblp%d set protocol %d", usblp->minor, protocol);
|
1072 |
|
|
return 0;
|
1073 |
|
|
}
|
1074 |
|
|
|
1075 |
|
|
/* Retrieves and caches device ID string.
|
1076 |
|
|
* Returns length, including length bytes but not null terminator.
|
1077 |
|
|
* On error, returns a negative errno value. */
|
1078 |
|
|
static int usblp_cache_device_id_string(struct usblp *usblp)
|
1079 |
|
|
{
|
1080 |
|
|
int err, length;
|
1081 |
|
|
|
1082 |
|
|
err = usblp_get_id(usblp, 0, usblp->device_id_string, USBLP_DEVICE_ID_SIZE - 1);
|
1083 |
|
|
if (err < 0) {
|
1084 |
|
|
dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
|
1085 |
|
|
usblp->minor, err);
|
1086 |
|
|
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
|
1087 |
|
|
return -EIO;
|
1088 |
|
|
}
|
1089 |
|
|
|
1090 |
|
|
/* First two bytes are length in big-endian.
|
1091 |
|
|
* They count themselves, and we copy them into
|
1092 |
|
|
* the user's buffer. */
|
1093 |
|
|
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
|
1094 |
|
|
if (length < 2)
|
1095 |
|
|
length = 2;
|
1096 |
|
|
else if (length >= USBLP_DEVICE_ID_SIZE)
|
1097 |
|
|
length = USBLP_DEVICE_ID_SIZE - 1;
|
1098 |
|
|
usblp->device_id_string[length] = '\0';
|
1099 |
|
|
|
1100 |
|
|
dbg("usblp%d Device ID string [len=%d]=\"%s\"",
|
1101 |
|
|
usblp->minor, length, &usblp->device_id_string[2]);
|
1102 |
|
|
|
1103 |
|
|
return length;
|
1104 |
|
|
}
|
1105 |
|
|
|
1106 |
|
|
static void usblp_disconnect(struct usb_device *dev, void *ptr)
|
1107 |
|
|
{
|
1108 |
|
|
struct usblp *usblp = ptr;
|
1109 |
|
|
|
1110 |
|
|
if (!usblp || !usblp->dev) {
|
1111 |
|
|
err("bogus disconnect");
|
1112 |
|
|
BUG ();
|
1113 |
|
|
}
|
1114 |
|
|
|
1115 |
|
|
down (&usblp->sem);
|
1116 |
|
|
lock_kernel();
|
1117 |
|
|
usblp->present = 0;
|
1118 |
|
|
|
1119 |
|
|
usblp_unlink_urbs(usblp);
|
1120 |
|
|
|
1121 |
|
|
if (!usblp->used)
|
1122 |
|
|
usblp_cleanup (usblp);
|
1123 |
|
|
else /* cleanup later, on release */
|
1124 |
|
|
up (&usblp->sem);
|
1125 |
|
|
unlock_kernel();
|
1126 |
|
|
}
|
1127 |
|
|
|
1128 |
|
|
static struct usb_device_id usblp_ids [] = {
|
1129 |
|
|
{ USB_DEVICE_INFO(7, 1, 1) },
|
1130 |
|
|
{ USB_DEVICE_INFO(7, 1, 2) },
|
1131 |
|
|
{ USB_DEVICE_INFO(7, 1, 3) },
|
1132 |
|
|
{ USB_INTERFACE_INFO(7, 1, 1) },
|
1133 |
|
|
{ USB_INTERFACE_INFO(7, 1, 2) },
|
1134 |
|
|
{ USB_INTERFACE_INFO(7, 1, 3) },
|
1135 |
|
|
{ } /* Terminating entry */
|
1136 |
|
|
};
|
1137 |
|
|
|
1138 |
|
|
MODULE_DEVICE_TABLE (usb, usblp_ids);
|
1139 |
|
|
|
1140 |
|
|
static struct usb_driver usblp_driver = {
|
1141 |
|
|
name: "usblp",
|
1142 |
|
|
probe: usblp_probe,
|
1143 |
|
|
disconnect: usblp_disconnect,
|
1144 |
|
|
fops: &usblp_fops,
|
1145 |
|
|
minor: USBLP_MINOR_BASE,
|
1146 |
|
|
id_table: usblp_ids,
|
1147 |
|
|
};
|
1148 |
|
|
|
1149 |
|
|
static int __init usblp_init(void)
|
1150 |
|
|
{
|
1151 |
|
|
if (usb_register(&usblp_driver))
|
1152 |
|
|
return -1;
|
1153 |
|
|
info(DRIVER_VERSION ": " DRIVER_DESC);
|
1154 |
|
|
return 0;
|
1155 |
|
|
}
|
1156 |
|
|
|
1157 |
|
|
static void __exit usblp_exit(void)
|
1158 |
|
|
{
|
1159 |
|
|
usb_deregister(&usblp_driver);
|
1160 |
|
|
}
|
1161 |
|
|
|
1162 |
|
|
module_init(usblp_init);
|
1163 |
|
|
module_exit(usblp_exit);
|
1164 |
|
|
|
1165 |
|
|
MODULE_AUTHOR( DRIVER_AUTHOR );
|
1166 |
|
|
MODULE_DESCRIPTION( DRIVER_DESC );
|
1167 |
|
|
MODULE_PARM(proto_bias, "i");
|
1168 |
|
|
MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
|
1169 |
|
|
MODULE_LICENSE("GPL");
|