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

📄 devio.c

📁 基于S3CEB2410平台LINUX操作系统下 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;	void *userbuffer;        void *userurb;        urb_t 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;}extern 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(iso_packet_descriptor_t);        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);}extern __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);}extern __inline__ void async_removepending(struct async *as){        struct dev_state *ps = as->ps;        unsigned long flags;                spin_lock_irqsave(&ps->lock, flags);        list_del(&as->asynclist);        INIT_LIST_HEAD(&as->asynclist);        spin_unlock_irqrestore(&ps->lock, flags);}extern __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(&as->asynclist);                INIT_LIST_HEAD(&as->asynclist);        }        spin_unlock_irqrestore(&ps->lock, flags);        return as;}extern __inline__ struct async *async_getpending(struct dev_state *ps, void *userurb){        unsigned long flags;        struct async *as;        struct list_head *p;        spin_lock_irqsave(&ps->lock, flags);        for (p = ps->async_pending.next; p != &ps->async_pending; ) {                as = list_entry(p, struct async, asynclist);                p = p->next;                if (as->userurb != userurb)                        continue;                list_del(&as->asynclist);                INIT_LIST_HEAD(&as->asynclist);                spin_unlock_irqrestore(&ps->lock, flags);                return as;        }        spin_unlock_irqrestore(&ps->lock, flags);        return NULL;}static void async_completed(purb_t urb){        struct async *as = (struct async *)urb->context;        struct dev_state *ps = as->ps;	struct siginfo sinfo;        spin_lock(&ps->lock);        list_del(&as->asynclist);        list_add_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_all_async(struct dev_state *ps){        struct async *as;        unsigned long flags;        spin_lock_irqsave(&ps->lock, flags);        while (!list_empty(&ps->async_pending)) {                as = list_entry(ps->async_pending.next, struct async, asynclist);                list_del(&as->asynclist);                INIT_LIST_HEAD(&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);}/* * interface claiming */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;	ps->ifclaimed = 0;}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;	if (ifn & ~0xff)		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];			if (alts->bInterfaceNumber == ifn)				return i;		}	}	return -ENOENT; }extern struct list_head usb_driver_list;

⌨️ 快捷键说明

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