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

📄 devio.c

📁 ep9315平台下USB驱动的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************//* *      devio.c  --  User space communication with USB devices. * *      Copyright (C) 1999-2000  Thomas Sailer (sailer@ife.ee.ethz.ch) * *      This program is free software; you can redistribute it and/or modify *      it under the terms of the GNU General Public License as published by *      the Free Software Foundation; either version 2 of the License, or *      (at your option) any later version. * *      This program is distributed in the hope that it will be useful, *      but WITHOUT ANY WARRANTY; without even the implied warranty of *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *      GNU General Public License for more details. * *      You should have received a copy of the GNU General Public License *      along with this program; if not, write to the Free Software *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *  $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $ * *  This file implements the usbdevfs/x/y files, where *  x is the bus number and y the device number. * *  It allows user space programs/"drivers" to communicate directly *  with USB devices without intervening kernel driver. * *  Revision history *    22.12.1999   0.1   Initial release (split from proc_usb.c) *    04.01.2000   0.2   Turned into its own filesystem *//*****************************************************************************/#include <linux/fs.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/signal.h>#include <linux/poll.h>#include <linux/usb.h>#include <linux/usbdevice_fs.h>#include <asm/uaccess.h>struct async {        struct list_head asynclist;        struct dev_state *ps;	struct task_struct *task;	unsigned int signr;	unsigned int intf;	void *userbuffer;        void *userurb;        struct urb urb;};static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig){	switch (orig) {	case 0:		file->f_pos = offset;		return file->f_pos;	case 1:		file->f_pos += offset;		return file->f_pos;	case 2:		return -EINVAL;	default:		return -EINVAL;	}}static ssize_t usbdev_read(struct file *file, char * buf, size_t nbytes, loff_t *ppos){	struct dev_state *ps = (struct dev_state *)file->private_data;	ssize_t ret = 0;	unsigned len;	loff_t pos;	int i;	pos = *ppos;	down_read(&ps->devsem);	if (!ps->dev) {		ret = -ENODEV;		goto err;	} else if (pos < 0) {		ret = -EINVAL;		goto err;	}	if (pos < sizeof(struct usb_device_descriptor)) {		len = sizeof(struct usb_device_descriptor) - pos;		if (len > nbytes)			len = nbytes;		if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len)) {			ret = -EFAULT;			goto err;		}		*ppos += len;		buf += len;		nbytes -= len;		ret += len;	}	pos = sizeof(struct usb_device_descriptor);	for (i = 0; nbytes && i < ps->dev->descriptor.bNumConfigurations; i++) {		struct usb_config_descriptor *config =			(struct usb_config_descriptor *)ps->dev->rawdescriptors[i];		unsigned int length = le16_to_cpu(config->wTotalLength);		if (*ppos < pos + length) {			len = length - (*ppos - pos);			if (len > nbytes)				len = nbytes;			if (copy_to_user(buf,			    ps->dev->rawdescriptors[i] + (*ppos - pos), len)) {				ret = -EFAULT;				goto err;			}			*ppos += len;			buf += len;			nbytes -= len;			ret += len;		}		pos += length;	}err:	up_read(&ps->devsem);	return ret;}static inline unsigned int ld2(unsigned int x){        unsigned int r = 0;                if (x >= 0x10000) {                x >>= 16;                r += 16;        }        if (x >= 0x100) {                x >>= 8;                r += 8;        }        if (x >= 0x10) {                x >>= 4;                r += 4;        }        if (x >= 4) {                x >>= 2;                r += 2;        }        if (x >= 2)                r++;        return r;}/* * async list handling */static struct async *alloc_async(unsigned int numisoframes){        unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct iso_packet_descriptor);        struct async *as = kmalloc(assize, GFP_KERNEL);        if (!as)                return NULL;        memset(as, 0, assize);        as->urb.number_of_packets = numisoframes;        spin_lock_init(&as->urb.lock);        return as;}static void free_async(struct async *as){        if (as->urb.transfer_buffer)                kfree(as->urb.transfer_buffer);        if (as->urb.setup_packet)                kfree(as->urb.setup_packet);        kfree(as);}static inline void async_newpending(struct async *as){        struct dev_state *ps = as->ps;        unsigned long flags;                spin_lock_irqsave(&ps->lock, flags);        list_add_tail(&as->asynclist, &ps->async_pending);        spin_unlock_irqrestore(&ps->lock, flags);}static inline void async_removepending(struct async *as){        struct dev_state *ps = as->ps;        unsigned long flags;                spin_lock_irqsave(&ps->lock, flags);        list_del_init(&as->asynclist);        spin_unlock_irqrestore(&ps->lock, flags);}static inline struct async *async_getcompleted(struct dev_state *ps){        unsigned long flags;        struct async *as = NULL;        spin_lock_irqsave(&ps->lock, flags);        if (!list_empty(&ps->async_completed)) {                as = list_entry(ps->async_completed.next, struct async, asynclist);                list_del_init(&as->asynclist);        }        spin_unlock_irqrestore(&ps->lock, flags);        return as;}static inline struct async *async_getpending(struct dev_state *ps, void *userurb){        unsigned long flags;        struct async *as;        spin_lock_irqsave(&ps->lock, flags);	list_for_each_entry(as, &ps->async_pending, asynclist)		if (as->userurb == userurb) {			list_del_init(&as->asynclist);			spin_unlock_irqrestore(&ps->lock, flags);			return as;		}        spin_unlock_irqrestore(&ps->lock, flags);        return NULL;}static void async_completed(struct urb *urb){        struct async *as = (struct async *)urb->context;        struct dev_state *ps = as->ps;	struct siginfo sinfo;        spin_lock(&ps->lock);        list_move_tail(&as->asynclist, &ps->async_completed);        spin_unlock(&ps->lock);        wake_up(&ps->wait);	if (as->signr) {		sinfo.si_signo = as->signr;		sinfo.si_errno = as->urb.status;		sinfo.si_code = SI_ASYNCIO;		sinfo.si_addr = as->userurb;		send_sig_info(as->signr, &sinfo, as->task);	}}static void destroy_async (struct dev_state *ps, struct list_head *list){	struct async *as;	unsigned long flags;	spin_lock_irqsave(&ps->lock, flags);	while (!list_empty(list)) {		as = list_entry(list->next, struct async, asynclist);		list_del_init(&as->asynclist);		spin_unlock_irqrestore(&ps->lock, flags);		/* usb_unlink_urb calls the completion handler with status == USB_ST_URB_KILLED */		usb_unlink_urb(&as->urb);		spin_lock_irqsave(&ps->lock, flags);	}	spin_unlock_irqrestore(&ps->lock, flags);	while ((as = async_getcompleted(ps)))		free_async(as);}static void destroy_async_on_interface (struct dev_state *ps, unsigned int intf){	struct list_head *p, *q, hitlist;	unsigned long flags;	INIT_LIST_HEAD(&hitlist);	spin_lock_irqsave(&ps->lock, flags);	list_for_each_safe(p, q, &ps->async_pending)		if (intf == list_entry(p, struct async, asynclist)->intf)			list_move_tail(p, &hitlist);	spin_unlock_irqrestore(&ps->lock, flags);	destroy_async(ps, &hitlist);}static inline void destroy_all_async(struct dev_state *ps){	destroy_async(ps, &ps->async_pending);}/* * interface claims are made only at the request of user level code, * which can also release them (explicitly or by closing files). * they're also undone when devices disconnect. */static void *driver_probe(struct usb_device *dev, unsigned int intf,			  const struct usb_device_id *id){	return NULL;}static void driver_disconnect(struct usb_device *dev, void *context){	struct dev_state *ps = (struct dev_state *)context;	if (!ps)		return;	/* this waits till synchronous requests complete */	down_write (&ps->devsem);	/* prevent new I/O requests */	ps->dev = 0;	ps->ifclaimed = 0;	/* force async requests to complete */	destroy_all_async (ps);	up_write (&ps->devsem);}struct usb_driver usbdevfs_driver = {	name:		"usbdevfs",	probe:		driver_probe,	disconnect:	driver_disconnect,};static int claimintf(struct dev_state *ps, unsigned int intf){	struct usb_device *dev = ps->dev;	struct usb_interface *iface;	int err;	if (intf >= 8*sizeof(ps->ifclaimed) || !dev || intf >= dev->actconfig->bNumInterfaces)		return -EINVAL;	/* already claimed */	if (test_bit(intf, &ps->ifclaimed))		return 0;	iface = &dev->actconfig->interface[intf];	err = -EBUSY;	lock_kernel();	if (!usb_interface_claimed(iface)) {		usb_driver_claim_interface(&usbdevfs_driver, iface, ps);		set_bit(intf, &ps->ifclaimed);		err = 0;	}	unlock_kernel();	return err;}static int releaseintf(struct dev_state *ps, unsigned int intf){	struct usb_device *dev;	struct usb_interface *iface;	int err;	if (intf >= 8*sizeof(ps->ifclaimed))		return -EINVAL;	err = -EINVAL;	lock_kernel();	dev = ps->dev;	if (dev && test_and_clear_bit(intf, &ps->ifclaimed)) {		iface = &dev->actconfig->interface[intf];		usb_driver_release_interface(&usbdevfs_driver, iface);		err = 0;	}	unlock_kernel();	return err;}static int checkintf(struct dev_state *ps, unsigned int intf){	if (intf >= 8*sizeof(ps->ifclaimed))		return -EINVAL;	if (test_bit(intf, &ps->ifclaimed))		return 0;	/* if not yet claimed, claim it for the driver */	printk(KERN_WARNING "usbdevfs: process %d (%s) did not claim interface %u before use\n",	       current->pid, current->comm, intf);	return claimintf(ps, intf);}static int findintfep(struct usb_device *dev, unsigned int ep){	unsigned int i, j, e;        struct usb_interface *iface;	struct usb_interface_descriptor *alts;	struct usb_endpoint_descriptor *endpt;	if (ep & ~(USB_DIR_IN|0xf))		return -EINVAL;	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {		iface = &dev->actconfig->interface[i];		for (j = 0; j < iface->num_altsetting; j++) {                        alts = &iface->altsetting[j];			for (e = 0; e < alts->bNumEndpoints; e++) {				endpt = &alts->endpoint[e];				if (endpt->bEndpointAddress == ep)					return i;			}		}	}	return -ENOENT; }static int findintfif(struct usb_device *dev, unsigned int ifn){	unsigned int i, j;        struct usb_interface *iface;	struct usb_interface_descriptor *alts;

⌨️ 快捷键说明

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