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

📄 iowarrior.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	usb_free_urb(int_out_urb);error_no_urb:	atomic_dec(&dev->write_busy);	wake_up_interruptible(&dev->write_wait);exit:	mutex_unlock(&dev->mutex);	return retval;}/** *	iowarrior_ioctl */static int iowarrior_ioctl(struct inode *inode, struct file *file,			   unsigned int cmd, unsigned long arg){	struct iowarrior *dev = NULL;	__u8 *buffer;	__u8 __user *user_buffer;	int retval;	int io_res;		/* checks for bytes read/written and copy_to/from_user results */	dev = (struct iowarrior *)file->private_data;	if (dev == NULL) {		return -ENODEV;	}	buffer = kzalloc(dev->report_size, GFP_KERNEL);	if (!buffer)		return -ENOMEM;	/* lock this object */	mutex_lock(&dev->mutex);	/* verify that the device wasn't unplugged */	if (!dev->present) {		retval = -ENODEV;		goto error_out;	}	dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd,	    arg);	retval = 0;	io_res = 0;	switch (cmd) {	case IOW_WRITE:		if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 ||		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 ||		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 ||		    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) {			user_buffer = (__u8 __user *)arg;			io_res = copy_from_user(buffer, user_buffer,						dev->report_size);			if (io_res) {				retval = -EFAULT;			} else {				io_res = usb_set_report(dev->interface, 2, 0,							buffer,							dev->report_size);				if (io_res < 0)					retval = io_res;			}		} else {			retval = -EINVAL;			dev_err(&dev->interface->dev,				"ioctl 'IOW_WRITE' is not supported for product=0x%x.\n",				dev->product_id);		}		break;	case IOW_READ:		user_buffer = (__u8 __user *)arg;		io_res = usb_get_report(dev->udev,					dev->interface->cur_altsetting, 1, 0,					buffer, dev->report_size);		if (io_res < 0)			retval = io_res;		else {			io_res = copy_to_user(user_buffer, buffer, dev->report_size);			if (io_res < 0)				retval = -EFAULT;		}		break;	case IOW_GETINFO:		{			/* Report available information for the device */			struct iowarrior_info info;			/* needed for power consumption */			struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc;			/* directly from the descriptor */			info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);			info.product = dev->product_id;			info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice);			/* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */			info.speed = le16_to_cpu(dev->udev->speed);			info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber;			info.report_size = dev->report_size;			/* serial number string has been read earlier 8 chars or empty string */			memcpy(info.serial, dev->chip_serial,			       sizeof(dev->chip_serial));			if (cfg_descriptor == NULL) {				info.power = -1;	/* no information available */			} else {				/* the MaxPower is stored in units of 2mA to make it fit into a byte-value */				info.power = cfg_descriptor->bMaxPower * 2;			}			io_res = copy_to_user((struct iowarrior_info __user *)arg, &info,					 sizeof(struct iowarrior_info));			if (io_res < 0)				retval = -EFAULT;			break;		}	default:		/* return that we did not understand this ioctl call */		retval = -ENOTTY;		break;	}error_out:	/* unlock the device */	mutex_unlock(&dev->mutex);	kfree(buffer);	return retval;}/** *	iowarrior_open */static int iowarrior_open(struct inode *inode, struct file *file){	struct iowarrior *dev = NULL;	struct usb_interface *interface;	int subminor;	int retval = 0;	dbg("%s", __func__);	subminor = iminor(inode);	interface = usb_find_interface(&iowarrior_driver, subminor);	if (!interface) {		err("%s - error, can't find device for minor %d", __FUNCTION__,		    subminor);		return -ENODEV;	}	mutex_lock(&iowarrior_open_disc_lock);	dev = usb_get_intfdata(interface);	if (!dev) {		mutex_unlock(&iowarrior_open_disc_lock);		return -ENODEV;	}	mutex_lock(&dev->mutex);	mutex_unlock(&iowarrior_open_disc_lock);	/* Only one process can open each device, no sharing. */	if (dev->opened) {		retval = -EBUSY;		goto out;	}	/* setup interrupt handler for receiving values */	if ((retval = usb_submit_urb(dev->int_in_urb, GFP_KERNEL)) < 0) {		dev_err(&interface->dev, "Error %d while submitting URB\n", retval);		retval = -EFAULT;		goto out;	}	/* increment our usage count for the driver */	++dev->opened;	/* save our object in the file's private structure */	file->private_data = dev;	retval = 0;out:	mutex_unlock(&dev->mutex);	return retval;}/** *	iowarrior_release */static int iowarrior_release(struct inode *inode, struct file *file){	struct iowarrior *dev;	int retval = 0;	dev = (struct iowarrior *)file->private_data;	if (dev == NULL) {		return -ENODEV;	}	dbg("%s - minor %d", __func__, dev->minor);	/* lock our device */	mutex_lock(&dev->mutex);	if (dev->opened <= 0) {		retval = -ENODEV;	/* close called more than once */		mutex_unlock(&dev->mutex);	} else {		dev->opened = 0;	/* we're closeing now */		retval = 0;		if (dev->present) {			/*			   The device is still connected so we only shutdown			   pending read-/write-ops.			 */			usb_kill_urb(dev->int_in_urb);			wake_up_interruptible(&dev->read_wait);			wake_up_interruptible(&dev->write_wait);			mutex_unlock(&dev->mutex);		} else {			/* The device was unplugged, cleanup resources */			mutex_unlock(&dev->mutex);			iowarrior_delete(dev);		}	}	return retval;}static unsigned iowarrior_poll(struct file *file, poll_table * wait){	struct iowarrior *dev = file->private_data;	unsigned int mask = 0;	if (!dev->present)		return POLLERR | POLLHUP;	poll_wait(file, &dev->read_wait, wait);	poll_wait(file, &dev->write_wait, wait);	if (!dev->present)		return POLLERR | POLLHUP;	if (read_index(dev) != -1)		mask |= POLLIN | POLLRDNORM;	if (atomic_read(&dev->write_busy) < MAX_WRITES_IN_FLIGHT)		mask |= POLLOUT | POLLWRNORM;	return mask;}/* * File operations needed when we register this driver. * This assumes that this driver NEEDS file operations, * of course, which means that the driver is expected * to have a node in the /dev directory. If the USB * device were for a network interface then the driver * would use "struct net_driver" instead, and a serial * device would use "struct tty_driver". */static struct file_operations iowarrior_fops = {	.owner = THIS_MODULE,	.write = iowarrior_write,	.read = iowarrior_read,	.ioctl = iowarrior_ioctl,	.open = iowarrior_open,	.release = iowarrior_release,	.poll = iowarrior_poll,};/* * usb class driver info in order to get a minor number from the usb core, * and to have the device registered with devfs and the driver core */static struct usb_class_driver iowarrior_class = {	.name = "iowarrior%d",	.fops = &iowarrior_fops,	.minor_base = IOWARRIOR_MINOR_BASE,};/*---------------------------------*//*  probe and disconnect functions *//*---------------------------------*//** *	iowarrior_probe * *	Called by the usb core when a new device is connected that it thinks *	this driver might be interested in. */static int iowarrior_probe(struct usb_interface *interface,			   const struct usb_device_id *id){	struct usb_device *udev = interface_to_usbdev(interface);	struct iowarrior *dev = NULL;	struct usb_host_interface *iface_desc;	struct usb_endpoint_descriptor *endpoint;	int i;	int retval = -ENOMEM;	/* allocate memory for our device state and intialize it */	dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL);	if (dev == NULL) {		dev_err(&interface->dev, "Out of memory\n");		return retval;	}	mutex_init(&dev->mutex);	atomic_set(&dev->intr_idx, 0);	atomic_set(&dev->read_idx, 0);	spin_lock_init(&dev->intr_idx_lock);	atomic_set(&dev->overflow_flag, 0);	init_waitqueue_head(&dev->read_wait);	atomic_set(&dev->write_busy, 0);	init_waitqueue_head(&dev->write_wait);	dev->udev = udev;	dev->interface = interface;	iface_desc = interface->cur_altsetting;	dev->product_id = le16_to_cpu(udev->descriptor.idProduct);	/* set up the endpoint information */	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {		endpoint = &iface_desc->endpoint[i].desc;		if (usb_endpoint_is_int_in(endpoint))			dev->int_in_endpoint = endpoint;		if (usb_endpoint_is_int_out(endpoint))			/* this one will match for the IOWarrior56 only */			dev->int_out_endpoint = endpoint;	}	/* we have to check the report_size often, so remember it in the endianess suitable for our machine */	dev->report_size = le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize);	if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&	    (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56))		/* IOWarrior56 has wMaxPacketSize different from report size */		dev->report_size = 7;	/* create the urb and buffer for reading */	dev->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);	if (!dev->int_in_urb) {		dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n");		goto error;	}	dev->int_in_buffer = kmalloc(dev->report_size, GFP_KERNEL);	if (!dev->int_in_buffer) {		dev_err(&interface->dev, "Couldn't allocate int_in_buffer\n");		goto error;	}	usb_fill_int_urb(dev->int_in_urb, dev->udev,			 usb_rcvintpipe(dev->udev,					dev->int_in_endpoint->bEndpointAddress),			 dev->int_in_buffer, dev->report_size,			 iowarrior_callback, dev,			 dev->int_in_endpoint->bInterval);	/* create an internal buffer for interrupt data from the device */	dev->read_queue =	    kmalloc(((dev->report_size + 1) * MAX_INTERRUPT_BUFFER),		    GFP_KERNEL);	if (!dev->read_queue) {		dev_err(&interface->dev, "Couldn't allocate read_queue\n");		goto error;	}	/* Get the serial-number of the chip */	memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial));	usb_string(udev, udev->descriptor.iSerialNumber, dev->chip_serial,		   sizeof(dev->chip_serial));	if (strlen(dev->chip_serial) != 8)		memset(dev->chip_serial, 0x00, sizeof(dev->chip_serial));	/* Set the idle timeout to 0, if this is interface 0 */	if (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) {	    usb_control_msg(udev, usb_sndctrlpipe(udev, 0),			    0x0A,			    USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,			    0, NULL, 0, USB_CTRL_SET_TIMEOUT);	}	/* allow device read and ioctl */	dev->present = 1;	/* we can register the device now, as it is ready */	usb_set_intfdata(interface, dev);	retval = usb_register_dev(interface, &iowarrior_class);	if (retval) {		/* something prevented us from registering this driver */		dev_err(&interface->dev, "Not able to get a minor for this device.\n");		usb_set_intfdata(interface, NULL);		goto error;	}	dev->minor = interface->minor;	/* let the user know what node this device is now attached to */	dev_info(&interface->dev, "IOWarrior product=0x%x, serial=%s interface=%d "		 "now attached to iowarrior%d\n", dev->product_id, dev->chip_serial,		 iface_desc->desc.bInterfaceNumber, dev->minor - IOWARRIOR_MINOR_BASE);	return retval;error:	iowarrior_delete(dev);	return retval;}/** *	iowarrior_disconnect * *	Called by the usb core when the device is removed from the system. */static void iowarrior_disconnect(struct usb_interface *interface){	struct iowarrior *dev;	int minor;	dev = usb_get_intfdata(interface);	mutex_lock(&iowarrior_open_disc_lock);	usb_set_intfdata(interface, NULL);	minor = dev->minor;	/* give back our minor */	usb_deregister_dev(interface, &iowarrior_class);	mutex_lock(&dev->mutex);	/* prevent device read, write and ioctl */	dev->present = 0;	mutex_unlock(&dev->mutex);	mutex_unlock(&iowarrior_open_disc_lock);	if (dev->opened) {		/* There is a process that holds a filedescriptor to the device ,		   so we only shutdown read-/write-ops going on.		   Deleting the device is postponed until close() was called.		 */		usb_kill_urb(dev->int_in_urb);		wake_up_interruptible(&dev->read_wait);		wake_up_interruptible(&dev->write_wait);	} else {		/* no process is using the device, cleanup now */		iowarrior_delete(dev);	}	dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",		 minor - IOWARRIOR_MINOR_BASE);}/* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver iowarrior_driver = {	.name = "iowarrior",	.probe = iowarrior_probe,	.disconnect = iowarrior_disconnect,	.id_table = iowarrior_ids,};static int __init iowarrior_init(void){	return usb_register(&iowarrior_driver);}static void __exit iowarrior_exit(void){	usb_deregister(&iowarrior_driver);}module_init(iowarrior_init);module_exit(iowarrior_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -