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

📄 usb.c

📁 Usb1.1驱动c语言源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * drivers/usb/usb.c * * (C) Copyright Linus Torvalds 1999 * (C) Copyright Johannes Erdfelt 1999 * (C) Copyright Andreas Gal 1999 * (C) Copyright Gregory P. Smith 1999 * (C) Copyright Deti Fliegl 1999 (new USB architecture) * * NOTE! This is not actually a driver at all, rather this is * just a collection of helper routines that implement the * generic USB things that the real drivers can use.. * * Think of this as a "USB library" rather than anything else. * It should be considered a slave, with no callbacks. Callbacks * are evil. * * $Id: usb.c,v 1.58 2000/03/13 16:44:45 acher Exp $ */#include <linux/config.h>#include <linux/module.h>#include <linux/string.h>#include <linux/bitops.h>#include <linux/malloc.h>#include <linux/interrupt.h>  /* for in_interrupt() */#define DEBUG#include <linux/usb.h>/* * Prototypes for the device driver probing/loading functions */static void usb_find_drivers(struct usb_device *);static int  usb_find_interface_driver(struct usb_device *, unsigned int);static void usb_check_support(struct usb_device *);/* * We have a per-interface "registered driver" list. */LIST_HEAD(usb_driver_list);LIST_HEAD(usb_bus_list);static struct usb_busmap busmap;static struct usb_driver *usb_minors[16];int usb_register(struct usb_driver *new_driver){	struct list_head *tmp;	if (new_driver->fops != NULL) {		if (usb_minors[new_driver->minor/16]) {			 err("error registering %s driver", new_driver->name);			return -EINVAL;		}		usb_minors[new_driver->minor/16] = new_driver;	}	info("registered new driver %s", new_driver->name);	/* Add it to the list of known drivers */	list_add(&new_driver->driver_list, &usb_driver_list);	/*	 * We go through all existing devices, and see if any of them would	 * be acceptable to the new driver.. This is done using a depth-first	 * search for devices without a registered driver already, then 	 * running 'probe' with each of the drivers registered on every one 	 * of these.	 */	tmp = usb_bus_list.next;	while (tmp != &usb_bus_list) {		struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);		tmp = tmp->next;		usb_check_support(bus->root_hub);	}	return 0;}/* * This function is part of a depth-first search down the device tree, * removing any instances of a device driver. */static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev){	int i;	if (!dev) {		err("null device being purged!!!");		return;	}	for (i=0; i<USB_MAXCHILDREN; i++)		if (dev->children[i])			usb_drivers_purge(driver, dev->children[i]);	if (!dev->actconfig)		return;				for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {		struct usb_interface *interface = &dev->actconfig->interface[i];				if (interface->driver == driver) {			driver->disconnect(dev, interface->private_data);			usb_driver_release_interface(driver, interface);			/*			 * This will go through the list looking for another			 * driver that can handle the device			 */			usb_find_interface_driver(dev, i);		}	}}/* * Unlink a driver from the driver list when it is unloaded */void usb_deregister(struct usb_driver *driver){	struct list_head *tmp;	info("deregistering driver %s", driver->name);	if (driver->fops != NULL)		usb_minors[driver->minor/16] = NULL;	/*	 * first we remove the driver, to be sure it doesn't get used by	 * another thread while we are stepping through removing entries	 */	list_del(&driver->driver_list);	tmp = usb_bus_list.next;	while (tmp != &usb_bus_list) {		struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);		tmp = tmp->next;		usb_drivers_purge(driver, bus->root_hub);	}}/* * calc_bus_time: * * returns (approximate) USB bus time in nanoseconds for a USB transaction. */static long calc_bus_time (int low_speed, int input_dir, int isoc, int bytecount){	unsigned long	tmp;	if (low_speed)		/* no isoc. here */	{		if (input_dir)		{			tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L;			return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);		}		else		{			tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L;			return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);		}	}	/* for full-speed: */	if (!isoc)		/* Input or Output */	{		tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;		return (9107L + BW_HOST_DELAY + tmp);	} /* end not Isoc */	/* for isoc: */	tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;	return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);} /* end calc_bus_time *//* * check_bandwidth_alloc(): * * old_alloc is from host_controller->bandwidth_allocated in microseconds; * bustime is from calc_bus_time(), but converted to microseconds. * * returns 0 if successful, * -1 if bandwidth request fails. * * FIXME: * This initial implementation does not use Endpoint.bInterval * in managing bandwidth allocation. * It probably needs to be expanded to use Endpoint.bInterval. * This can be done as a later enhancement (correction). * This will also probably require some kind of * frame allocation tracking...meaning, for example, * that if multiple drivers request interrupts every 10 USB frames, * they don't all have to be allocated at * frame numbers N, N+10, N+20, etc.  Some of them could be at * N+11, N+21, N+31, etc., and others at * N+12, N+22, N+32, etc. * However, this first cut at USB bandwidth allocation does not * contain any frame allocation tracking. */static int check_bandwidth_alloc (unsigned int old_alloc, long bustime){	unsigned int	new_alloc;	new_alloc = old_alloc + bustime;		/* what new total allocated bus time would be */	dbg("usb-bandwidth-alloc: was: %u, new: %u, "		"bustime = %ld us, Pipe allowed: %s",		old_alloc, new_alloc, bustime,		(new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ?			"yes" : "no");	return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? 0 : -1;} /* end check_bandwidth_alloc *//* * New functions for (de)registering a controller */struct usb_bus *usb_alloc_bus(struct usb_operations *op){	struct usb_bus *bus;	bus = kmalloc(sizeof(*bus), GFP_KERNEL);	if (!bus)		return NULL;	memset(&bus->devmap, 0, sizeof(struct usb_devmap));	bus->op = op;	bus->root_hub = NULL;	bus->hcpriv = NULL;	bus->busnum = -1;	bus->bandwidth_allocated = 0;	bus->bandwidth_int_reqs  = 0;	bus->bandwidth_isoc_reqs = 0;	INIT_LIST_HEAD(&bus->bus_list);        INIT_LIST_HEAD(&bus->inodes);	return bus;}void usb_free_bus(struct usb_bus *bus){	if (!bus)		return;	kfree(bus);}void usb_register_bus(struct usb_bus *bus){	int busnum;	busnum = find_next_zero_bit(busmap.busmap, USB_MAXBUS, 1);	if (busnum < USB_MAXBUS) {		set_bit(busnum, busmap.busmap);		bus->busnum = busnum;	} else		warn("too many buses");	/* Add it to the list of buses */	list_add(&bus->bus_list, &usb_bus_list);	usbdevfs_add_bus(bus);	info("new USB bus registered, assigned bus number %d", bus->busnum);}void usb_deregister_bus(struct usb_bus *bus){	info("USB bus %d deregistered", bus->busnum);	/*	 * NOTE: make sure that all the devices are removed by the	 * controller code, as well as having it call this when cleaning	 * itself up	 */	list_del(&bus->bus_list);        usbdevfs_remove_bus(bus);	clear_bit(bus->busnum, busmap.busmap);}/* * This function is for doing a depth-first search for devices which * have support, for dynamic loading of driver modules. */static void usb_check_support(struct usb_device *dev){	int i;	if (!dev) {		err("null device being checked!!!");		return;	}	for (i=0; i<USB_MAXCHILDREN; i++)		if (dev->children[i])			usb_check_support(dev->children[i]);	if (!dev->actconfig)		return;	/* now we check this device */	if (dev->devnum > 0)		for (i = 0; i < dev->actconfig->bNumInterfaces; i++)			usb_find_interface_driver(dev, i);}/* * This is intended to be used by usb device drivers that need to * claim more than one interface on a device at once when probing * (audio and acm are good examples).  No device driver should have * to mess with the internal usb_interface or usb_device structure * members. */void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv){	if (!iface || !driver)		return;	dbg("%s driver claimed interface %p", driver->name, iface);	iface->driver = driver;	iface->private_data = priv;} /* usb_driver_claim_interface() *//* * This should be used by drivers to check other interfaces to see if * they are available or not. */int usb_interface_claimed(struct usb_interface *iface){	if (!iface)		return 0;	return (iface->driver != NULL);} /* usb_interface_claimed() *//* * This should be used by drivers to release their claimed interfaces */void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface){	/* this should never happen, don't release something that's not ours */	if (iface->driver != driver || !iface)		return;	iface->driver = NULL;	iface->private_data = NULL;}/* * This entrypoint gets called for each new device. * * We now walk the list of registered USB drivers, * looking for one that will accept this interface. * * The probe return value is changed to be a private pointer.  This way * the drivers don't have to dig around in our structures to set the * private pointer if they only need one interface.  * * Returns: 0 if a driver accepted the interface, -1 otherwise */static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum){	struct list_head *tmp = usb_driver_list.next;	struct usb_interface *interface;		if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {		err("bad find_interface_driver params");		return -1;	}	interface = dev->actconfig->interface + ifnum;	if (usb_interface_claimed(interface))		return -1;	while (tmp != &usb_driver_list) {		void *private;		struct usb_driver *driver = list_entry(tmp, struct usb_driver,		  				       driver_list);					tmp = tmp->next;		if (!(private = driver->probe(dev, ifnum)))			continue;		usb_driver_claim_interface(driver, interface, private);		return 0;	}		return -1;}/* * This entrypoint gets called for each new device. * * All interfaces are scanned for matching drivers. */static void usb_find_drivers(struct usb_device *dev){	unsigned ifnum;	unsigned rejected = 0;	unsigned claimed = 0;	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {		/* if this interface hasn't already been claimed */		if (!usb_interface_claimed(dev->actconfig->interface + ifnum)) {			if (usb_find_interface_driver(dev, ifnum))				rejected++;			else				claimed++;		}	} 	if (rejected)		dbg("unhandled interfaces on device");	if (!claimed) {		warn("This device is not recognized by any installed USB driver.");#ifdef DEBUG		usb_show_device(dev);#endif	}}/* * Only HC's should call usb_alloc_dev and usb_free_dev directly * Anybody may use usb_inc_dev_use or usb_dec_dev_use */struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus){	struct usb_device *dev;	dev = kmalloc(sizeof(*dev), GFP_KERNEL);	if (!dev)		return NULL;	memset(dev, 0, sizeof(*dev));	dev->bus = bus;	dev->parent = parent;	atomic_set(&dev->refcnt, 1);        INIT_LIST_HEAD(&dev->inodes);        INIT_LIST_HEAD(&dev->filelist);	dev->bus->op->allocate(dev);	return dev;}void usb_free_dev(struct usb_device *dev){	if (atomic_dec_and_test(&dev->refcnt)) {		usb_destroy_configuration(dev);		dev->bus->op->deallocate(dev);		kfree(dev);	}}

⌨️ 快捷键说明

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