示例#1
0
static int usblp_check_status(struct usblp *usblp, int err)
{
	unsigned char status, newerr = 0;
	int error;

	mutex_lock(&usblp->mut);
	if ((error = usblp_read_status(usblp, usblp->statusbuf)) < 0) {
		mutex_unlock(&usblp->mut);
		if (printk_ratelimit())
			printk(KERN_ERR
				"usblp%d: error %d reading printer status\n",
				usblp->minor, error);
		return 0;
	}
	status = *usblp->statusbuf;
	mutex_unlock(&usblp->mut);

	if (~status & LP_PERRORP)
		newerr = 3;
	if (status & LP_POUTPA)
		newerr = 1;
	if (~status & LP_PSELECD)
		newerr = 2;

	if (newerr != err) {
		printk(KERN_INFO "usblp%d: %s\n",
		   usblp->minor, usblp_messages[newerr]);
	}

	return newerr;
}
static int usblp_check_status(struct usblp *usblp, int errno )
{
	unsigned char status, newerr = 0;
	int error;

	error = usblp_read_status (usblp, &status);
	if (error < 0) {
//{{MARK_DEBUG
//		err("usblp%d: error %d reading printer status",
//			usblp->minor, error);
//}}MARK_DEBUG
		return 0;
	}

	if (~status & LP_PERRORP) {
		newerr = 3;
		if (status & LP_POUTPA) newerr = 1;
		if (~status & LP_PSELECD) newerr = 2;
	}

//{{MARK_DEBUG
//	if (newerr != errno)
//		dbg("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
//}}MARK_DEBUG

	return newerr;
}
示例#3
0
static int usblp_check_status(struct usblp *usblp, int err)
{
	unsigned char status, newerr = 0;
	int error;

	error = usblp_read_status (usblp, usblp->statusbuf);
	if (error < 0) {
		err("usblp%d: error %d reading printer status",
			usblp->minor, error);
		return 0;
	}

	status = *usblp->statusbuf;

	if (~status & LP_PERRORP)
		newerr = 3;
	if (status & LP_POUTPA)
		newerr = 1;
	if (~status & LP_PSELECD)
		newerr = 2;

	if (newerr != err)
		info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);

	return newerr;
}
示例#4
0
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	struct usblp *usblp = file->private_data;
	int length, err;
	unsigned char status;

	if (_IOC_TYPE(cmd) == 'P')	/* new-style ioctl number */
	
		switch (_IOC_NR(cmd)) {

			case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
				if (_IOC_DIR(cmd) != _IOC_READ)
					return -EINVAL;

				err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
				if (err < 0) {
					dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string",
						usblp->minor, err);
					usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
					return -EIO;
				}

				length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
				if (length < DEVICE_ID_SIZE)
					usblp->device_id_string[length] = '\0';
				else
					usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';

				dbg ("usblp%d Device ID string [%d/max %d]='%s'",
					usblp->minor, length, _IOC_SIZE(cmd), &usblp->device_id_string[2]);

				if (length > _IOC_SIZE(cmd)) length = _IOC_SIZE(cmd); /* truncate */

				if (copy_to_user((unsigned char *) arg, usblp->device_id_string, (unsigned long) length))
					return -EFAULT;

				break;

			default:
				return -EINVAL;
		}
	else	/* old-style ioctl value */
		switch (cmd) {

			case LPGETSTATUS:
				if (usblp_read_status(usblp, &status)) {
					err("usblp%d: failed reading printer status", usblp->minor);
					return -EIO;
				}
				if (copy_to_user ((unsigned char *)arg, &status, 1))
					return -EFAULT;
				break;

			default:
				return -EINVAL;
		}

	return 0;
}
示例#5
0
static int usblp_check_status(struct usblp *usblp, int err)
{
    unsigned char status, newerr = 0;

    if (usblp_read_status(usblp, &status)) {
        err("usblp%d: failed reading printer status", usblp->minor);
        return 0;
    }

    if (~status & LP_PERRORP) {
        newerr = 3;
        if (status & LP_POUTPA) newerr = 1;
        if (~status & LP_PSELECD) newerr = 2;
    }

    if (newerr != err)
        info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);

    return newerr;
}
示例#6
0
文件: usblp.c 项目: Mr-Aloof/wl500g
/*
 * Wait for the write path to come idle.
 * This is called under the ->wmut, so the idle path stays idle.
 *
 * Our write path has a peculiar property: it does not buffer like a tty,
 * but waits for the write to succeed. This allows our ->release to bug out
 * without waiting for writes to drain. But it obviously does not work
 * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use
 * select(2) or poll(2) to wait for the buffer to drain before closing.
 * Alternatively, set blocking mode with fcntl and issue a zero-size write.
 */
static int usblp_wwait(struct usblp *usblp, int nonblock)
{
	DECLARE_WAITQUEUE(waita, current);
	int rc;
	int err = 0;

	add_wait_queue(&usblp->wwait, &waita);
	for (;;) {
		if (mutex_lock_interruptible(&usblp->mut)) {
			rc = -EINTR;
			break;
		}
		set_current_state(TASK_INTERRUPTIBLE);
		rc = usblp_wtest(usblp, nonblock);
		mutex_unlock(&usblp->mut);
		if (rc <= 0)
			break;

		if (schedule_timeout(msecs_to_jiffies(1500)) == 0) {
			mutex_lock(&usblp->mut);
			if (usblp->flags & LP_ABORT) {
				err = usblp_check_status(usblp, err);
				mutex_unlock(&usblp->mut);
				if (err == 1) {	/* Paper out */
					rc = -ENOSPC;
					break;
				}
			} else {
				/* Prod the printer, Gentoo#251237. */
				usblp_read_status(usblp, usblp->statusbuf);
				mutex_unlock(&usblp->mut);
			}
		}
	}
	set_current_state(TASK_RUNNING);
	remove_wait_queue(&usblp->wwait, &waita);
	return rc;
}
示例#7
0
static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct usblp *usblp = file->private_data;
	int length, err, i;
	unsigned char newChannel;
	int status;
	int twoints[2];
	int retval = 0;

	mutex_lock (&usblp->mut);
	if (!usblp->present) {
		retval = -ENODEV;
		goto done;
	}

	if (usblp->sleeping) {
		retval = -ENODEV;
		goto done;
	}

	dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd),
		_IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) );

	if (_IOC_TYPE(cmd) == 'P')	/* new-style ioctl number */

		switch (_IOC_NR(cmd)) {

			case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
				if (_IOC_DIR(cmd) != _IOC_READ) {
					retval = -EINVAL;
					goto done;
				}

				length = usblp_cache_device_id_string(usblp);
				if (length < 0) {
					retval = length;
					goto done;
				}
				if (length > _IOC_SIZE(cmd))
					length = _IOC_SIZE(cmd); /* truncate */

				if (copy_to_user((void __user *) arg,
						usblp->device_id_string,
						(unsigned long) length)) {
					retval = -EFAULT;
					goto done;
				}

				break;

			case IOCNR_GET_PROTOCOLS:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = usblp->current_protocol;
				twoints[1] = 0;
				for (i = USBLP_FIRST_PROTOCOL;
				     i <= USBLP_LAST_PROTOCOL; i++) {
					if (usblp->protocol[i].alt_setting >= 0)
						twoints[1] |= (1<<i);
				}

				if (copy_to_user((void __user *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				break;

			case IOCNR_SET_PROTOCOL:
				if (_IOC_DIR(cmd) != _IOC_WRITE) {
					retval = -EINVAL;
					goto done;
				}

#ifdef DEBUG
				if (arg == -10) {
					usblp_dump(usblp);
					break;
				}
#endif

				usblp_unlink_urbs(usblp);
				retval = usblp_set_protocol(usblp, arg);
				if (retval < 0) {
					usblp_set_protocol(usblp,
						usblp->current_protocol);
				}
				break;

			case IOCNR_HP_SET_CHANNEL:
				if (_IOC_DIR(cmd) != _IOC_WRITE ||
				    le16_to_cpu(usblp->dev->descriptor.idVendor) != 0x03F0 ||
				    usblp->quirks & USBLP_QUIRK_BIDIR) {
					retval = -EINVAL;
					goto done;
				}

				err = usblp_hp_channel_change_request(usblp,
					arg, &newChannel);
				if (err < 0) {
					dev_err(&usblp->dev->dev,
						"usblp%d: error = %d setting "
						"HP channel\n",
						usblp->minor, err);
					retval = -EIO;
					goto done;
				}

				dbg("usblp%d requested/got HP channel %ld/%d",
					usblp->minor, arg, newChannel);
				break;

			case IOCNR_GET_BUS_ADDRESS:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = usblp->dev->bus->busnum;
				twoints[1] = usblp->dev->devnum;
				if (copy_to_user((void __user *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				dbg("usblp%d is bus=%d, device=%d",
					usblp->minor, twoints[0], twoints[1]);
				break;

			case IOCNR_GET_VID_PID:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = le16_to_cpu(usblp->dev->descriptor.idVendor);
				twoints[1] = le16_to_cpu(usblp->dev->descriptor.idProduct);
				if (copy_to_user((void __user *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
					usblp->minor, twoints[0], twoints[1]);
				break;

			case IOCNR_SOFT_RESET:
				if (_IOC_DIR(cmd) != _IOC_NONE) {
					retval = -EINVAL;
					goto done;
				}
				retval = usblp_reset(usblp);
				break;
			default:
				retval = -ENOTTY;
		}
	else	/* old-style ioctl value */
		switch (cmd) {

			case LPGETSTATUS:
				if ((retval = usblp_read_status(usblp, usblp->statusbuf))) {
					if (printk_ratelimit())
						printk(KERN_ERR "usblp%d:"
						    "failed reading printer status (%d)\n",
						    usblp->minor, retval);
					retval = -EIO;
					goto done;
				}
				status = *usblp->statusbuf;
				if (copy_to_user ((void __user *)arg, &status, sizeof(int)))
					retval = -EFAULT;
				break;

			case LPABORT:
				if (arg)
					usblp->flags |= LP_ABORT;
				else
					usblp->flags &= ~LP_ABORT;
				break;

			default:
				retval = -ENOTTY;
		}

done:
	mutex_unlock (&usblp->mut);
	return retval;
}
示例#8
0
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	struct usblp *usblp = file->private_data;
	struct parport_splink_device_info prn_info_tmp, *prn_info; // Added by PaN
	struct print_buffer user_buf_tmp, *user_buf; // Added by PaN
	char *strtmp, *str_dev_id, *strunknown="unknown"; // Added by PaN
	//int i, unk=0; // Added by PaN
	int unk=0; // Added by PaN ---remove declaration of i for i is declared below: JY
	int length, err, i;
	unsigned char lpstatus, newChannel;
	int status;
	int twoints[2];
	int retval = 0;
	prn_info= &prn_info_tmp; // Added by PaN

	down (&usblp->sem);
	if (!usblp->dev) {
		retval = -ENODEV;
		goto done;
	}

	if (_IOC_TYPE(cmd) == 'P')	/* new-style ioctl number */

		switch (_IOC_NR(cmd)) {

			case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
				if (_IOC_DIR(cmd) != _IOC_READ) {
					retval = -EINVAL;
					goto done;
				}

				length = usblp_cache_device_id_string(usblp);
				if (length < 0) {
					retval = length;
					goto done;
				}
				if (length > _IOC_SIZE(cmd))
					length = _IOC_SIZE(cmd); /* truncate */

				if (copy_to_user((unsigned char *) arg,
						usblp->device_id_string,
						(unsigned long) length)) {
					retval = -EFAULT;
					goto done;
				}

				break;

			case IOCNR_GET_PROTOCOLS:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = usblp->current_protocol;
				twoints[1] = 0;
				for (i = USBLP_FIRST_PROTOCOL;
				     i <= USBLP_LAST_PROTOCOL; i++) {
					if (usblp->protocol[i].alt_setting >= 0)
						twoints[1] |= (1<<i);
				}

				if (copy_to_user((unsigned char *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				break;

			case IOCNR_SET_PROTOCOL:
				if (_IOC_DIR(cmd) != _IOC_WRITE) {
					retval = -EINVAL;
					goto done;
				}

#ifdef DEBUG
				if (arg == -10) {
					usblp_dump(usblp);
					break;
				}
#endif

				usblp_unlink_urbs(usblp);
				retval = usblp_set_protocol(usblp, arg);
				if (retval < 0) {
					usblp_set_protocol(usblp,
						usblp->current_protocol);
				}
				break;

			case IOCNR_HP_SET_CHANNEL:
				if (_IOC_DIR(cmd) != _IOC_WRITE ||
				    usblp->dev->descriptor.idVendor != 0x03F0 ||
				    usblp->quirks & USBLP_QUIRK_BIDIR) {
					retval = -EINVAL;
					goto done;
				}

				err = usblp_hp_channel_change_request(usblp,
					arg, &newChannel);
				if (err < 0) {
					err("usblp%d: error = %d setting "
						"HP channel",
						usblp->minor, err);
					retval = -EIO;
					goto done;
				}

				dbg("usblp%d requested/got HP channel %ld/%d",
					usblp->minor, arg, newChannel);
				break;

			case IOCNR_GET_BUS_ADDRESS:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = usblp->dev->bus->busnum;
				twoints[1] = usblp->dev->devnum;
				if (copy_to_user((unsigned char *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				dbg("usblp%d is bus=%d, device=%d",
					usblp->minor, twoints[0], twoints[1]);
				break;

			case IOCNR_GET_VID_PID:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = usblp->dev->descriptor.idVendor;
				twoints[1] = usblp->dev->descriptor.idProduct;
				if (copy_to_user((unsigned char *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
					usblp->minor, twoints[0], twoints[1]);
				break;

			default:
				retval = -EINVAL;
		}
	else	/* old-style ioctl value */
		switch (cmd) {
/*=================================================================================== PaN */
			case LPGETID: /* get the DEVICE_ID string */
				err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
				if (err < 0) {
					dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string",
						usblp->minor, err);
					usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
					retval = -EIO;
					goto done;
				}

				length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
				if (length < DEVICE_ID_SIZE)
					usblp->device_id_string[length] = '\0';
				else
					usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';

				dbg ("usblp%d Device ID string [%d/max %d]='%s'",
					usblp->minor, length, cmd, &usblp->device_id_string[2]);
				info ("usblp%d Device ID string [%d/max %d]='%s'",
					usblp->minor, length, cmd, &usblp->device_id_string[2]);

				str_dev_id = &usblp->device_id_string[2];	
				if ( (strtmp = strstr(str_dev_id, "MFG:")) == NULL) {
					if ( (strtmp = strstr(str_dev_id, "MANUFACTURE:")) == NULL) {
						for (i=0; i<7; i++) {
							prn_info->mfr[i]= strunknown[i];
							usblpid_info.mfr[i] = strunknown[i];
						}
						prn_info->mfr[i]= '\0';
						usblpid_info.mfr[i]='\0';
						unk=1;
					}
					else 
						strtmp+=12;
				}
				else
					strtmp+=4;
					
				i=0;
				while (strtmp[i] != ';' && unk==0) {
					prn_info->mfr[i]= strtmp[i];
					usblpid_info.mfr[i] = strtmp[i];
					i++;
				}
				prn_info->mfr[i]= '\0';
				usblpid_info.mfr[i]='\0';
				unk=0;

				if ( (strtmp = strstr(str_dev_id, "MDL:")) == NULL) {
					if ( (strtmp = strstr(str_dev_id, "MODEL:")) == NULL) {
						for (i=0; i<7; i++) {
							prn_info->model[i]= strunknown[i];
							usblpid_info.model[i] = strunknown[i];
						}
						prn_info->model[i]= '\0';
						usblpid_info.model[i]='\0';
						unk=1;
					}
					else
						strtmp+=6;
				}
				else 
					strtmp+=4;
				
				i=0;
				while (strtmp[i] != ';' && unk==0) {
					prn_info->model[i]= strtmp[i];
					usblpid_info.model[i] = strtmp[i];
					i++;
				}		
				prn_info->model[i]= '\0';
				usblpid_info.model[i]='\0';
				unk=0;
				
				if ( (strtmp = strstr(str_dev_id, "CLS:")) == NULL) {
					if ( (strtmp = strstr(str_dev_id, "CLASS:")) == NULL) {
						for (i=0; i<7; i++) {
							prn_info->class_name[i]= strunknown[i];
							usblpid_info.class_name[i] = strunknown[i];
						}
						prn_info->class_name[i]= '\0';
						usblpid_info.class_name[i]='\0';
						unk=1;
					}
					else
						strtmp+=6;
				}
				else 
					strtmp+=4;
				
				i=0;
				while (strtmp[i] != ';' && unk==0) {
					prn_info->class_name[i]= strtmp[i];
					usblpid_info.class_name[i]= strtmp[i];
					i++;
				}		
				prn_info->class_name[i]= '\0';
				usblpid_info.class_name[i]='\0';
				unk=0;
				
				if ( (strtmp = strstr(str_dev_id, "DES:")) == NULL) {
					if ( (strtmp = strstr(str_dev_id, "DESCRIPTION:")) == NULL) {
						for (i=0; i<7; i++) {
							prn_info->description[i]= strunknown[i];
							usblpid_info.description[i] = strunknown[i];
						}
						prn_info->description[i]= '\0';
						usblpid_info.description[i]='\0';
						unk=1;
					}
					else
						strtmp+=12;
				}
				else
					strtmp+=4;
				
				i=0;
				while (strtmp[i] != ';' && unk==0) {
					prn_info->description[i]= strtmp[i];
					usblpid_info.description[i]= strtmp[i];
					i++;
				}		
				prn_info->description[i]= '\0';
				usblpid_info.description[i]='\0';
				
				info("Parsing USBLPID...");
				if (copy_to_user((unsigned char *) arg,
						prn_info, (unsigned long) length)) {
					retval = -EFAULT;
					goto done;
				}
				break;

			case LPREADDATA:
			        up (&usblp->sem);
				user_buf = (struct print_buffer *)arg;
				retval = usblp_read(file, user_buf->buf, user_buf->len, NULL);
				down (&usblp->sem);
	                        break;
										

			case LPWRITEDATA:
			        up (&usblp->sem);
				user_buf = (struct print_buffer *)arg;
				retval = usblp_write(file, user_buf->buf, user_buf->len, NULL);
				down (&usblp->sem);
	                        break;
										 
			case LPRESET:
                                usblp_reset(usblp);
				break;

			case LPGETSTATUS:
				/* OLD USB Code Removed by PaN for Printer Server 
				if (usblp_read_status(usblp, &status)) {
					err("usblp%d: failed reading printer status", usblp->minor);
					retval = -EIO;
					goto done;
				}
				if (copy_to_user ((int *)arg, &status, 2))
					retval = -EFAULT;
				*/
                                status = usblp_check_status(usblp, 0);
#if 0
				info("start=%s", usblpid_info.mfr);
				for (i=0; i< MAX_STATUS_TYPE; i++) {
				info("compare=%s", usblp_status_type[i]);
					if ( !( strcmp(usblpid_info.mfr, usblp_status_type[i]) ) )
						break;
				}
				info("%d=%s", i, usblp_status_type[i]);
				status=usblp_status_maping[i][status];
				info("STATUS=%x", status);
#endif
				status=0;
				if (copy_to_user ((int *)arg, &status, 2))
					retval = -EFAULT;
				break;
				
/*=================================================================== PaN for Printer Server */

/* Marked by JY 20031118*/
#if 0
			case LPGETSTATUS:
				if (usblp_read_status(usblp, &lpstatus)) {
					err("usblp%d: failed reading printer status", usblp->minor);
					retval = -EIO;
					goto done;
				}
				status = lpstatus;
				if (copy_to_user ((int *)arg, &status, sizeof(int)))
					retval = -EFAULT;
				break;
#endif
/* Marked by JY 20031118*/

			default:
				retval = -EINVAL;
		}

done:
	up (&usblp->sem);
	return retval;
}
示例#9
0
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	struct usblp *usblp = file->private_data;
	int length, err, i;
	unsigned char lpstatus, newChannel;
	int status;
	int twoints[2];
	int retval = 0;

	down (&usblp->sem);
	if (!usblp->dev) {
		retval = -ENODEV;
		goto done;
	}

	if (_IOC_TYPE(cmd) == 'P')	/* new-style ioctl number */

		switch (_IOC_NR(cmd)) {

			case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
				if (_IOC_DIR(cmd) != _IOC_READ) {
					retval = -EINVAL;
					goto done;
				}

				length = usblp_cache_device_id_string(usblp);
				if (length < 0) {
					retval = length;
					goto done;
				}
				if (length > _IOC_SIZE(cmd))
					length = _IOC_SIZE(cmd); /* truncate */

				if (copy_to_user((unsigned char *) arg,
						usblp->device_id_string,
						(unsigned long) length)) {
					retval = -EFAULT;
					goto done;
				}

				break;

			case IOCNR_GET_PROTOCOLS:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = usblp->current_protocol;
				twoints[1] = 0;
				for (i = USBLP_FIRST_PROTOCOL;
				     i <= USBLP_LAST_PROTOCOL; i++) {
					if (usblp->protocol[i].alt_setting >= 0)
						twoints[1] |= (1<<i);
				}

				if (copy_to_user((unsigned char *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				break;

			case IOCNR_SET_PROTOCOL:
				if (_IOC_DIR(cmd) != _IOC_WRITE) {
					retval = -EINVAL;
					goto done;
				}

#ifdef DEBUG
				if (arg == -10) {
					usblp_dump(usblp);
					break;
				}
#endif

				usblp_unlink_urbs(usblp);
				retval = usblp_set_protocol(usblp, arg);
				if (retval < 0) {
					usblp_set_protocol(usblp,
						usblp->current_protocol);
				}
				break;

			case IOCNR_HP_SET_CHANNEL:
				if (_IOC_DIR(cmd) != _IOC_WRITE ||
				    usblp->dev->descriptor.idVendor != 0x03F0 ||
				    usblp->quirks & USBLP_QUIRK_BIDIR) {
					retval = -EINVAL;
					goto done;
				}

				err = usblp_hp_channel_change_request(usblp,
					arg, &newChannel);
				if (err < 0) {
					err("usblp%d: error = %d setting "
						"HP channel",
						usblp->minor, err);
					retval = -EIO;
					goto done;
				}

				dbg("usblp%d requested/got HP channel %ld/%d",
					usblp->minor, arg, newChannel);
				break;

			case IOCNR_GET_BUS_ADDRESS:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = usblp->dev->bus->busnum;
				twoints[1] = usblp->dev->devnum;
				if (copy_to_user((unsigned char *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				dbg("usblp%d is bus=%d, device=%d",
					usblp->minor, twoints[0], twoints[1]);
				break;

			case IOCNR_GET_VID_PID:
				if (_IOC_DIR(cmd) != _IOC_READ ||
				    _IOC_SIZE(cmd) < sizeof(twoints)) {
					retval = -EINVAL;
					goto done;
				}

				twoints[0] = usblp->dev->descriptor.idVendor;
				twoints[1] = usblp->dev->descriptor.idProduct;
				if (copy_to_user((unsigned char *)arg,
						(unsigned char *)twoints,
						sizeof(twoints))) {
					retval = -EFAULT;
					goto done;
				}

				dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
					usblp->minor, twoints[0], twoints[1]);
				break;

			default:
				retval = -EINVAL;
		}
	else	/* old-style ioctl value */
		switch (cmd) {

			case LPGETSTATUS:
				if (usblp_read_status(usblp, &lpstatus)) {
					err("usblp%d: failed reading printer status", usblp->minor);
					retval = -EIO;
					goto done;
				}
				status = lpstatus;
				if (copy_to_user ((int *)arg, &status, sizeof(int)))
					retval = -EFAULT;
				break;

			default:
				retval = -EINVAL;
		}

done:
	up (&usblp->sem);
	return retval;
}