patch-2.3.35 linux/drivers/usb/printer.c

Next file: linux/drivers/usb/proc_usb.c
Previous file: linux/drivers/usb/mouse.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.34/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
@@ -1,4 +1,3 @@
-
 /* Driver for USB Printers
  * 
  * Copyright 1999 Michael Gee (michael@linuxspecific.com)
@@ -22,10 +21,21 @@
 
 #include "usb.h"
 
+/* Define IEEE_DEVICE_ID if you want to see the IEEE-1284 Device ID string.
+ * This may include the printer's serial number.
+ * An example from an HP 970C DeskJet printer is (this is one long string,
+ * with the serial number changed):
+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:                    ;
+ */
+#define IEEE_DEVICE_ID
+
 #define NAK_TIMEOUT (HZ)				/* stall wait for printer */
 #define MAX_RETRY_COUNT ((60*60*HZ)/NAK_TIMEOUT)	/* should not take 1 minute a page! */
 
 #define BIG_BUF_SIZE			8192
+#define SUBCLASS_PRINTERS		1
+#define PROTOCOL_UNIDIRECTIONAL		1
+#define PROTOCOL_BIDIRECTIONAL		2
 
 /*
  * USB Printer Requests
@@ -59,12 +69,16 @@
 static unsigned char printer_read_status(struct pp_usb_data *p)
 {
 	__u8 status;
+	int err;
 	struct usb_device *dev = p->pusb_dev;
 
-	if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
+	err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
 		USB_PRINTER_REQ_GET_PORT_STATUS,
 		USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
-		0, 0, &status, 1, HZ)) {
+		0, 0, &status, sizeof(status), HZ);
+	if (err < 0) {
+		printk(KERN_ERR "usblp%d: read_status control_msg error = %d\n",
+			p->minor, err);
  		return 0;
 	}
 	return status;
@@ -81,36 +95,39 @@
 	else if ((status & LP_POUTPA)) {
 		if (last != LP_POUTPA) {
 			last = LP_POUTPA;
-			printk(KERN_INFO "usblp%d out of paper\n", p->minor);
+			printk(KERN_INFO "usblp%d out of paper (%x)\n", p->minor, status);
 		}
 	} else if (!(status & LP_PSELECD)) {
 		if (last != LP_PSELECD) {
 			last = LP_PSELECD;
-			printk(KERN_INFO "usblp%d off-line\n", p->minor);
+			printk(KERN_INFO "usblp%d off-line (%x)\n", p->minor, status);
 		}
 	} else {
 		if (last != LP_PERRORP) {
 			last = LP_PERRORP;
-			printk(KERN_INFO "usblp%d on fire\n", p->minor);
+			printk(KERN_INFO "usblp%d on fire (%x)\n", p->minor, status);
 		}
 	}
 
 	p->last_error = last;
-
 	return status;
 }
 
 static void printer_reset(struct pp_usb_data *p)
 {
 	struct usb_device *dev = p->pusb_dev;
+	int err;
 
-	usb_control_msg(dev, usb_sndctrlpipe(dev,0),
+	err = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
 		USB_PRINTER_REQ_SOFT_RESET,
 		USB_TYPE_CLASS | USB_RECIP_OTHER,
 		0, 0, NULL, 0, HZ);
+	if (err < 0)
+		printk(KERN_ERR "usblp%d: reset control_msg error = %d\n",
+			p->minor, err);
 }
 
-static int open_printer(struct inode * inode, struct file * file)
+static int open_printer(struct inode *inode, struct file *file)
 {
 	struct pp_usb_data *p;
 
@@ -123,10 +140,14 @@
 	p->minor = MINOR(inode->i_rdev);
 
 	if (p->isopen++) {
+		printk(KERN_ERR "usblp%d: printer is already open\n",
+			p->minor);
 		return -EBUSY;
 	}
 	if (!(p->obuf = (char *)__get_free_page(GFP_KERNEL))) {
 		p->isopen = 0;
+		printk(KERN_ERR "usblp%d: cannot allocate memory\n",
+			p->minor);
 		return -ENOMEM;
 	}
 
@@ -140,7 +161,7 @@
 	return 0;
 }
 
-static int close_printer(struct inode * inode, struct file * file)
+static int close_printer(struct inode *inode, struct file *file)
 {
 	struct pp_usb_data *p = file->private_data;
 
@@ -156,8 +177,8 @@
 	return 0;
 }
 
-static ssize_t write_printer(struct file * file,
-       const char * buffer, size_t count, loff_t *ppos)
+static ssize_t write_printer(struct file *file,
+       const char *buffer, size_t count, loff_t *ppos)
 {
 	struct pp_usb_data *p = file->private_data;
 	unsigned long copy_size;
@@ -174,6 +195,7 @@
 		if (copy_from_user(p->obuf, buffer, copy_size))
 			return -EFAULT;
 		maxretry = MAX_RETRY_COUNT;
+
 		while (thistime) {
 			if (!p->pusb_dev)
 				return -ENODEV;
@@ -212,8 +234,8 @@
 	return bytes_written ? bytes_written : -EIO;
 }
 
-static ssize_t read_printer(struct file * file,
-       char * buffer, size_t count, loff_t *ppos)
+static ssize_t read_printer(struct file *file,
+       char *buffer, size_t count, loff_t *ppos)
 {
 	struct pp_usb_data *p = file->private_data;
 	int read_count = 0;
@@ -231,11 +253,14 @@
 		}
 		if (!p->pusb_dev)
 			return -ENODEV;
-		this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
 
+		this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
 		result = usb_bulk_msg(p->pusb_dev,
 			  usb_rcvbulkpipe(p->pusb_dev, p->bulk_in_ep),
 			  buf, this_read, &partial, HZ*20);
+		if (result < 0)
+			printk(KERN_ERR "usblp%d read_printer bulk_msg error = %d\n",
+				p->minor, result);
 
 		/* unlike writes, we don't retry a NAK, just stop now */
 		if (!result & partial)
@@ -251,14 +276,16 @@
 			buffer += this_read;
 		}
 	}
+
 	return read_count;
 }
 
-static void * printer_probe(struct usb_device *dev, unsigned int ifnum)
+static void *printer_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_interface_descriptor *interface;
 	struct pp_usb_data *pp;
 	int i;
+	__u8 status;
 
 	/*
 	 * FIXME - this will not cope with combined printer/scanners
@@ -274,8 +301,9 @@
 
 	/* Let's be paranoid (for the moment). */
 	if (interface->bInterfaceClass != USB_CLASS_PRINTER ||
-	    interface->bInterfaceSubClass != 1 ||
-	    (interface->bInterfaceProtocol != 2 && interface->bInterfaceProtocol != 1) ||
+	    interface->bInterfaceSubClass != SUBCLASS_PRINTERS ||
+	    (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL &&
+	    interface->bInterfaceProtocol != PROTOCOL_UNIDIRECTIONAL) ||
 	    interface->bNumEndpoints > 2) {
 		return NULL;
 	}
@@ -308,75 +336,89 @@
 			break;
 	}
 	if (i >= MAX_PRINTERS) {
-		printk("No minor table space available for USB Printer\n");
+		printk(KERN_ERR "No minor table space available for new USB printer\n");
 		return NULL;
 	}
 
-	printk(KERN_INFO "USB Printer found at address %d\n", dev->devnum);
+	printk(KERN_INFO "USB printer found at address %d\n", dev->devnum);
 
 	if (!(pp = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
-		printk(KERN_DEBUG "usb_printer: no memory!\n");
+		printk(KERN_DEBUG "USB printer: no memory!\n");
 		return NULL;
 	}
 
 	memset(pp, 0, sizeof(struct pp_usb_data));
 	minor_data[i] = PPDATA(pp);
-	minor_data[i]->minor = i;
-	minor_data[i]->pusb_dev = dev;
-	minor_data[i]->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
-	if (interface->bInterfaceProtocol != 2)		/* if not bidirectional */
-		minor_data[i]->noinput = 1;
 
-	minor_data[i]->bulk_out_index =
+	pp->minor = i;
+	pp->pusb_dev = dev;
+	pp->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
+	if (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL)
+		pp->noinput = 1;
+
+	pp->bulk_out_index =
 		((interface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
 		  == USB_DIR_OUT) ? 0 : 1;
-	minor_data[i]->bulk_in_index = minor_data[i]->noinput ? -1 :
-		(minor_data[i]->bulk_out_index == 0) ? 1 : 0;
-	minor_data[i]->bulk_in_ep = minor_data[i]->noinput ? -1 :
-		interface->endpoint[minor_data[i]->bulk_in_index].bEndpointAddress &
+	pp->bulk_in_index = pp->noinput ? -1 :
+		(pp->bulk_out_index == 0) ? 1 : 0;
+	pp->bulk_in_ep = pp->noinput ? -1 :
+		interface->endpoint[pp->bulk_in_index].bEndpointAddress &
 		USB_ENDPOINT_NUMBER_MASK;
-	minor_data[i]->bulk_out_ep =
-		interface->endpoint[minor_data[i]->bulk_out_index].bEndpointAddress &
+	pp->bulk_out_ep =
+		interface->endpoint[pp->bulk_out_index].bEndpointAddress &
 		USB_ENDPOINT_NUMBER_MASK;
-	if (interface->bInterfaceProtocol == 2) {	/* if bidirectional */
-		minor_data[i]->maxin =
-			interface->endpoint[minor_data[i]->bulk_in_index].wMaxPacketSize;
+	if (interface->bInterfaceProtocol == PROTOCOL_BIDIRECTIONAL) {
+		pp->maxin =
+			interface->endpoint[pp->bulk_in_index].wMaxPacketSize;
 	}
 
-	printk(KERN_INFO "USB Printer Summary:\n");
-	printk(KERN_INFO "index=%d, maxout=%d, noinput=%d\n",
-		i, minor_data[i]->maxout, minor_data[i]->noinput);
+	printk(KERN_INFO "usblp%d Summary:\n", pp->minor);
+	printk(KERN_INFO "index=%d, maxout=%d, noinput=%d, maxin=%d\n",
+		i, pp->maxout, pp->noinput, pp->maxin);
 	printk(KERN_INFO "bulk_in_ix=%d, bulk_in_ep=%d, bulk_out_ix=%d, bulk_out_ep=%d\n",
-		minor_data[i]->bulk_in_index,
-		minor_data[i]->bulk_in_ep,
-		minor_data[i]->bulk_out_index,
-		minor_data[i]->bulk_out_ep);
+		pp->bulk_in_index,
+		pp->bulk_in_ep,
+		pp->bulk_out_index,
+		pp->bulk_out_ep);
 
-#if 0
+#ifdef IEEE_DEVICE_ID
 	{
-		__u8 status;
-		__u8 ieee_id[64];
+		__u8 ieee_id[64]; /* first 2 bytes are (big-endian) length */
+				/* This string space may be too short. */
+		int length = (ieee_id[0] << 8) + ieee_id[1]; /* high-low */
+				/* This calc. or be16_to_cpu() both get
+				 * some weird results for <length>. */
+		int err;
 
 		/* Let's get the device id if possible. */
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
+		err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
 		    USB_PRINTER_REQ_GET_DEVICE_ID,
 		    USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
 		    0, 0, ieee_id,
-		    sizeof(ieee_id)-1, HZ) == 0) {
+		    sizeof(ieee_id)-1, HZ);
+		if (err >= 0) {
 			if (ieee_id[1] < sizeof(ieee_id) - 1)
 				ieee_id[ieee_id[1]+2] = '\0';
 			else
 				ieee_id[sizeof(ieee_id)-1] = '\0';
-			printk(KERN_INFO "  USB Printer ID is %s\n",
-				&ieee_id[2]);
+			printk(KERN_INFO "usblp%d Device ID length=%d [%x:%x]\n",
+				pp->minor, length, ieee_id[0], ieee_id[1]);
+			printk(KERN_INFO "usblp%d Device ID=%s\n",
+				pp->minor, &ieee_id[2]);
 		}
-		status = printer_read_status(PPDATA(pp));
-		printk(KERN_INFO "  Status is %s,%s,%s\n",
-		       (status & LP_PSELECD) ? "Selected" : "Not Selected",
-		       (status & LP_POUTPA)  ? "No Paper" : "Paper",
-		       (status & LP_PERRORP) ? "No Error" : "Error");
+		else
+			printk(KERN_INFO "usblp%d: error = %d reading IEEE-1284 Device ID\n",
+				pp->minor, err);
 	}
 #endif
+
+	status = printer_read_status(PPDATA(pp));
+	printk(KERN_INFO "usblp%d probe status is %x: %s,%s,%s\n",
+		pp->minor, status,
+		(status & LP_PSELECD) ? "Selected" : "Not Selected",
+		(status & LP_POUTPA)  ? "No Paper" : "Paper",
+		(status & LP_PERRORP) ? "No Error" : "Error");
+
 	return pp;
 }
 
@@ -422,7 +464,7 @@
 	if (usb_register(&printer_driver))
 		return -1;
 
-	printk(KERN_INFO "USB Printer support registered.\n");
+	printk(KERN_INFO "USB Printer driver registered.\n");
 	return 0;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)