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

📄 devio.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			totlen += isopkt[u].length;		}		if (totlen > 32768) {			kfree(isopkt);			return -EINVAL;		}		uurb.buffer_length = totlen;		break;	case USBDEVFS_URB_TYPE_INTERRUPT:		uurb.number_of_packets = 0;		if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))			return -ENOENT;		if (ps->dev->speed == USB_SPEED_HIGH)			interval = 1 << min (15, ep_desc->bInterval - 1);		else			interval = ep_desc->bInterval;		if (uurb.buffer_length > 16384)			return -EINVAL;		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))			return -EFAULT;		break;	default:		return -EINVAL;	}	if (!(as = alloc_async(uurb.number_of_packets))) {		if (isopkt)			kfree(isopkt);		if (dr)			kfree(dr);		return -ENOMEM;	}	if (!(as->urb->transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {		if (isopkt)			kfree(isopkt);		if (dr)			kfree(dr);		free_async(as);		return -ENOMEM;	}        as->urb->dev = ps->dev;        as->urb->pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);        as->urb->transfer_flags = uurb.flags;	as->urb->transfer_buffer_length = uurb.buffer_length;	as->urb->setup_packet = (unsigned char*)dr;	as->urb->start_frame = uurb.start_frame;	as->urb->number_of_packets = uurb.number_of_packets;	as->urb->interval = interval;        as->urb->context = as;        as->urb->complete = async_completed;	for (totlen = u = 0; u < uurb.number_of_packets; u++) {		as->urb->iso_frame_desc[u].offset = totlen;		as->urb->iso_frame_desc[u].length = isopkt[u].length;		totlen += isopkt[u].length;	}	if (isopkt)		kfree(isopkt);	as->ps = ps;        as->userurb = arg;	if (uurb.endpoint & USB_DIR_IN)		as->userbuffer = uurb.buffer;	else		as->userbuffer = NULL;	as->signr = uurb.signr;	as->ifnum = ifnum;	as->task = current;	if (!(uurb.endpoint & USB_DIR_IN)) {		if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {			free_async(as);			return -EFAULT;		}	}        async_newpending(as);        if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {		dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret);                async_removepending(as);                free_async(as);                return ret;        }        return 0;}static int proc_unlinkurb(struct dev_state *ps, void __user *arg){	struct async *as;	as = async_getpending(ps, arg);	if (!as)		return -EINVAL;	usb_unlink_urb(as->urb);	return 0;}static int processcompl(struct async *as){	struct urb *urb = as->urb;	struct usbdevfs_urb __user *userurb = as->userurb;	unsigned int i;	if (as->userbuffer)		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))			return -EFAULT;	if (put_user(urb->status, &userurb->status))		return -EFAULT;	if (put_user(urb->actual_length, &userurb->actual_length))		return -EFAULT;	if (put_user(urb->error_count, &userurb->error_count))		return -EFAULT;	if (!(usb_pipeisoc(urb->pipe)))		return 0;	for (i = 0; i < urb->number_of_packets; i++) {		if (put_user(urb->iso_frame_desc[i].actual_length,			     &userurb->iso_frame_desc[i].actual_length))			return -EFAULT;		if (put_user(urb->iso_frame_desc[i].status,			     &userurb->iso_frame_desc[i].status))			return -EFAULT;	}	return 0;}static int proc_reapurb(struct dev_state *ps, void __user *arg){        DECLARE_WAITQUEUE(wait, current);	struct async *as = NULL;	void __user *addr;	struct usb_device *dev = ps->dev;	int ret;	add_wait_queue(&ps->wait, &wait);	while (connected(dev)) {		__set_current_state(TASK_INTERRUPTIBLE);		if ((as = async_getcompleted(ps)))			break;		if (signal_pending(current))			break;		up(&dev->serialize);		schedule();		down(&dev->serialize);	}	remove_wait_queue(&ps->wait, &wait);	set_current_state(TASK_RUNNING);	if (as) {		ret = processcompl(as);		addr = as->userurb;		free_async(as);		if (ret)			return ret;		if (put_user(addr, (void __user * __user *)arg))			return -EFAULT;		return 0;	}	if (signal_pending(current))		return -EINTR;	return -EIO;}static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg){	struct async *as;	void __user *addr;	int ret;	if (!(as = async_getcompleted(ps)))		return -EAGAIN;	ret = processcompl(as);	addr = as->userurb;	free_async(as);	if (ret)		return ret;	if (put_user(addr, (void __user * __user *)arg))		return -EFAULT;	return 0;}static int proc_disconnectsignal(struct dev_state *ps, void __user *arg){	struct usbdevfs_disconnectsignal ds;	if (copy_from_user(&ds, arg, sizeof(ds)))		return -EFAULT;	if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX))		return -EINVAL;	ps->discsignr = ds.signr;	ps->disccontext = ds.context;	return 0;}static int proc_claiminterface(struct dev_state *ps, void __user *arg){	unsigned int ifnum;	if (get_user(ifnum, (unsigned int __user *)arg))		return -EFAULT;	return claimintf(ps, ifnum);}static int proc_releaseinterface(struct dev_state *ps, void __user *arg){	unsigned int ifnum;	int ret;	if (get_user(ifnum, (unsigned int __user *)arg))		return -EFAULT;	if ((ret = releaseintf(ps, ifnum)) < 0)		return ret;	destroy_async_on_interface (ps, ifnum);	return 0;}static int proc_ioctl (struct dev_state *ps, void __user *arg){	struct usbdevfs_ioctl	ctrl;	int			size;	void			*buf = NULL;	int			retval = 0;	struct usb_interface    *intf = NULL;	struct usb_driver       *driver = NULL;	/* get input parameters and alloc buffer */	if (copy_from_user(&ctrl, arg, sizeof (ctrl)))		return -EFAULT;	if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {		if ((buf = kmalloc (size, GFP_KERNEL)) == 0)			return -ENOMEM;		if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) {			if (copy_from_user (buf, ctrl.data, size)) {				kfree (buf);				return -EFAULT;			}		} else {			memset (buf, 0, size);		}	}	if (!connected(ps->dev)) {		if (buf)			kfree(buf);		return -ENODEV;	}	if (ps->dev->state != USB_STATE_CONFIGURED)		retval = -ENODEV;	else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno)))               retval = -EINVAL;	else switch (ctrl.ioctl_code) {	/* disconnect kernel driver from interface */	case USBDEVFS_DISCONNECT:		down_write(&usb_bus_type.subsys.rwsem);		if (intf->dev.driver) {			driver = to_usb_driver(intf->dev.driver);			dev_dbg (&intf->dev, "disconnect by usbfs\n");			usb_driver_release_interface(driver, intf);		} else			retval = -ENODATA;		up_write(&usb_bus_type.subsys.rwsem);		break;	/* let kernel drivers try to (re)bind to the interface */	case USBDEVFS_CONNECT:		bus_rescan_devices(intf->dev.bus);		break;	/* talk directly to the interface's driver */	default:		down_read(&usb_bus_type.subsys.rwsem);		if (intf->dev.driver)			driver = to_usb_driver(intf->dev.driver);		if (driver == 0 || driver->ioctl == 0) {			retval = -ENOTTY;		} else {			retval = driver->ioctl (intf, ctrl.ioctl_code, buf);			if (retval == -ENOIOCTLCMD)				retval = -ENOTTY;		}		up_read(&usb_bus_type.subsys.rwsem);	}	/* cleanup and return */	if (retval >= 0			&& (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0			&& size > 0			&& copy_to_user (ctrl.data, buf, size) != 0)		retval = -EFAULT;	if (buf != 0)		kfree (buf);	return retval;}/* * NOTE:  All requests here that have interface numbers as parameters * are assuming that somehow the configuration has been prevented from * changing.  But there's no mechanism to ensure that... */static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct dev_state *ps = (struct dev_state *)file->private_data;	struct usb_device *dev = ps->dev;	void __user *p = (void __user *)arg;	int ret = -ENOTTY;	if (!(file->f_mode & FMODE_WRITE))		return -EPERM;	down(&dev->serialize);	if (!connected(dev)) {		up(&dev->serialize);		return -ENODEV;	}	switch (cmd) {	case USBDEVFS_CONTROL:		snoop(&dev->dev, "%s: CONTROL\n", __FUNCTION__);		ret = proc_control(ps, p);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_BULK:		snoop(&dev->dev, "%s: BULK\n", __FUNCTION__);		ret = proc_bulk(ps, p);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_RESETEP:		snoop(&dev->dev, "%s: RESETEP\n", __FUNCTION__);		ret = proc_resetep(ps, p);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_RESET:		snoop(&dev->dev, "%s: RESET\n", __FUNCTION__);		ret = proc_resetdevice(ps);		break;	case USBDEVFS_CLEAR_HALT:		snoop(&dev->dev, "%s: CLEAR_HALT\n", __FUNCTION__);		ret = proc_clearhalt(ps, p);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_GETDRIVER:		snoop(&dev->dev, "%s: GETDRIVER\n", __FUNCTION__);		ret = proc_getdriver(ps, p);		break;	case USBDEVFS_CONNECTINFO:		snoop(&dev->dev, "%s: CONNECTINFO\n", __FUNCTION__);		ret = proc_connectinfo(ps, p);		break;	case USBDEVFS_SETINTERFACE:		snoop(&dev->dev, "%s: SETINTERFACE\n", __FUNCTION__);		ret = proc_setintf(ps, p);		break;	case USBDEVFS_SETCONFIGURATION:		snoop(&dev->dev, "%s: SETCONFIGURATION\n", __FUNCTION__);		ret = proc_setconfig(ps, p);		break;	case USBDEVFS_SUBMITURB:		snoop(&dev->dev, "%s: SUBMITURB\n", __FUNCTION__);		ret = proc_submiturb(ps, p);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_DISCARDURB:		snoop(&dev->dev, "%s: DISCARDURB\n", __FUNCTION__);		ret = proc_unlinkurb(ps, p);		break;	case USBDEVFS_REAPURB:		snoop(&dev->dev, "%s: REAPURB\n", __FUNCTION__);		ret = proc_reapurb(ps, p);		break;	case USBDEVFS_REAPURBNDELAY:		snoop(&dev->dev, "%s: REAPURBDELAY\n", __FUNCTION__);		ret = proc_reapurbnonblock(ps, p);		break;	case USBDEVFS_DISCSIGNAL:		snoop(&dev->dev, "%s: DISCSIGNAL\n", __FUNCTION__);		ret = proc_disconnectsignal(ps, p);		break;	case USBDEVFS_CLAIMINTERFACE:		snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __FUNCTION__);		ret = proc_claiminterface(ps, p);		break;	case USBDEVFS_RELEASEINTERFACE:		snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __FUNCTION__);		ret = proc_releaseinterface(ps, p);		break;	case USBDEVFS_IOCTL:		snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);		ret = proc_ioctl(ps, p);		break;	}	up(&dev->serialize);	if (ret >= 0)		inode->i_atime = CURRENT_TIME;	return ret;}/* No kernel lock - fine */static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait){	struct dev_state *ps = (struct dev_state *)file->private_data;        unsigned int mask = 0;	poll_wait(file, &ps->wait, wait);	if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))		mask |= POLLOUT | POLLWRNORM;	if (!connected(ps->dev))		mask |= POLLERR | POLLHUP;	return mask;}struct file_operations usbdevfs_device_file_operations = {	.llseek =	usbdev_lseek,	.read =		usbdev_read,	.poll =		usbdev_poll,	.ioctl =	usbdev_ioctl,	.open =		usbdev_open,	.release =	usbdev_release,};

⌨️ 快捷键说明

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