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

📄 devio.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			return -EFAULT;		break;	case USBDEVFS_URB_TYPE_ISO:		/* arbitrary limit */		if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)			return -EINVAL;		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))			return -ENOMEM;		if (copy_from_user(isopkt, &((struct usbdevfs_urb *)arg)->iso_frame_desc, isofrmlen)) {			kfree(isopkt);			return -EFAULT;		}		for (totlen = u = 0; u < uurb.number_of_packets; u++) {			if (isopkt[u].length > 1023) {				kfree(isopkt);				return -EINVAL;			}			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 (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.next = NULL;        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.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->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))) {		printk(KERN_DEBUG "usbdevfs: 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 *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){	unsigned int i;	if (as->userbuffer)		if (copy_to_user(as->userbuffer, as->urb.transfer_buffer, as->urb.transfer_buffer_length))			return -EFAULT;	if (put_user(as->urb.status,		     &((struct usbdevfs_urb *)as->userurb)->status))		return -EFAULT;	if (put_user(as->urb.actual_length,		     &((struct usbdevfs_urb *)as->userurb)->actual_length))		return -EFAULT;	if (put_user(as->urb.error_count,		     &((struct usbdevfs_urb *)as->userurb)->error_count))		return -EFAULT;	if (!(usb_pipeisoc(as->urb.pipe)))		return 0;	for (i = 0; i < as->urb.number_of_packets; i++) {		if (put_user(as->urb.iso_frame_desc[i].actual_length, 			     &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length))			return -EFAULT;		if (put_user(as->urb.iso_frame_desc[i].status, 			     &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status))			return -EFAULT;	}	return 0;}static int proc_reapurb(struct dev_state *ps, void *arg){        DECLARE_WAITQUEUE(wait, current);	struct async *as = NULL;	void *addr;	int ret;	add_wait_queue(&ps->wait, &wait);	while (ps->dev) {		__set_current_state(TASK_INTERRUPTIBLE);		if ((as = async_getcompleted(ps)))			break;		if (signal_pending(current))			break;		up_read(&ps->devsem);		schedule();		down_read(&ps->devsem);	}	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 **)arg))			return -EFAULT;		return 0;	}	if (signal_pending(current))		return -EINTR;	return -EIO;}static int proc_reapurbnonblock(struct dev_state *ps, void *arg){	struct async *as;	void *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 **)arg))		return -EFAULT;	return 0;}static int proc_disconnectsignal(struct dev_state *ps, void *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 *arg){	unsigned int intf;	int ret;	if (get_user(intf, (unsigned int *)arg))		return -EFAULT;	if ((ret = findintfif(ps->dev, intf)) < 0)		return ret;	return claimintf(ps, ret);}static int proc_releaseinterface(struct dev_state *ps, void *arg){	unsigned int intf;	int ret;	if (get_user(intf, (unsigned int *)arg))		return -EFAULT;	if ((ret = findintfif(ps->dev, intf)) < 0)		return ret;	return releaseintf(ps, intf);}static int proc_ioctl (struct dev_state *ps, void *arg){	struct usbdevfs_ioctl	ctrl;	int			size;	void			*buf = 0;	int			retval = 0;	/* get input parameters and alloc buffer */	if (copy_from_user(&ctrl, (void *) 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);		}	}	/* ioctl to device */	if (ctrl.ifno < 0) {		switch (ctrl.ioctl_code) {		/* access/release token for issuing control messages		 * ask a particular driver to bind/unbind, ... etc		 */		}		retval = -ENOSYS;	/* ioctl to the driver which has claimed a given interface */	} else {		struct usb_interface	*ifp = 0;		if (!ps->dev)			retval = -ENODEV;		else if (ctrl.ifno >= ps->dev->actconfig->bNumInterfaces)			retval = -EINVAL;		else {			if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))				retval = -EINVAL;			else if (ifp->driver == 0 || ifp->driver->ioctl == 0)				retval = -ENOSYS;		}		if (retval == 0)			/* ifno might usefully be passed ... */			retval = ifp->driver->ioctl (ps->dev, ctrl.ioctl_code, buf);			/* size = min_t(int, size, retval)? */	}	/* 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;}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;	int ret = -ENOIOCTLCMD;	if (!(file->f_mode & FMODE_WRITE))		return -EPERM;	down_read(&ps->devsem);	if (!ps->dev) {		up_read(&ps->devsem);		return -ENODEV;	}	switch (cmd) {	case USBDEVFS_CONTROL:		ret = proc_control(ps, (void *)arg);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_BULK:		ret = proc_bulk(ps, (void *)arg);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_RESETEP:		ret = proc_resetep(ps, (void *)arg);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_RESET:		ret = proc_resetdevice(ps);		break;		case USBDEVFS_CLEAR_HALT:		ret = proc_clearhalt(ps, (void *)arg);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_GETDRIVER:		ret = proc_getdriver(ps, (void *)arg);		break;	case USBDEVFS_CONNECTINFO:		ret = proc_connectinfo(ps, (void *)arg);		break;	case USBDEVFS_SETINTERFACE:		ret = proc_setintf(ps, (void *)arg);		break;	case USBDEVFS_SETCONFIGURATION:		ret = proc_setconfig(ps, (void *)arg);		break;	case USBDEVFS_SUBMITURB:		ret = proc_submiturb(ps, (void *)arg);		if (ret >= 0)			inode->i_mtime = CURRENT_TIME;		break;	case USBDEVFS_DISCARDURB:		ret = proc_unlinkurb(ps, (void *)arg);		break;	case USBDEVFS_REAPURB:		ret = proc_reapurb(ps, (void *)arg);		break;	case USBDEVFS_REAPURBNDELAY:		ret = proc_reapurbnonblock(ps, (void *)arg);		break;	case USBDEVFS_DISCSIGNAL:		ret = proc_disconnectsignal(ps, (void *)arg);		break;	case USBDEVFS_CLAIMINTERFACE:		ret = proc_claiminterface(ps, (void *)arg);		break;	case USBDEVFS_RELEASEINTERFACE:		ret = proc_releaseinterface(ps, (void *)arg);		break;	case USBDEVFS_IOCTL:		ret = proc_ioctl(ps, (void *) arg);		break;	}	up_read(&ps->devsem);	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 (!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 + -