struct usb_device
{
int devnum; /* Address on USB bus */
char devpath[16]; /* Use in messages: /port/port/... */
enum
{
USB_SPEED_UNKNOWN = 0, /* enumerating */
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
USB_SPEED_HIGH /* usb 2.0 */
} speed;
struct usb_tt *tt; /* low/full speed dev, highspeed hub */
int ttport; /* device port on that tt hub */
atomic_t refcnt; /* Reference count */
struct semaphore serialize;
/*
* This is our custom open-coded lock, similar to r/w locks in concept.
* It prevents drivers and /proc access from simultaneous access.
* Type:
* 0 - unlocked
* 1 - locked for reads
* 2 - locked for writes
* 3 - locked for everything
*/
wait_queue_head_t excl_wait;
spinlock_t excl_lock;
unsigned excl_type;
unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1]
= OUT) */
unsigned int halted[2]; /* endpoint halts; one bit per endpoint # &
direction; */
/* [0] = IN, [1] = OUT */
int epmaxpacketin[16]; /* INput endpoint specific maximums */
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
struct usb_device *parent;
struct usb_bus *bus; /* Bus we're part of */
struct usb_device_descriptor descriptor; /* Descriptor */
struct usb_config_descriptor *config; /* All of the configs */
struct usb_config_descriptor *actconfig; /* the active
configuration */
char **rawdescriptors; /* Raw descriptors for each config */
int have_langid; /* whether string_langid is valid yet */
int string_langid; /* language ID for strings */
void *hcpriv; /* Host Controller private data */
/* usbdevfs inode list */
struct list_head inodes;
struct list_head filelist;
/*
* Child devices - these can be either new devices
* (if this is a hub device), or different instances
* of this same device.
*
* Each instance needs its own set of data structures.
*/
int maxchild; /* Number of ports if hub */
struct usb_device *children[USB_MAXCHILDREN];
};
struct usb_bus
{
int busnum; /* Bus number (in order of reg) */
char *bus_name; /* stable id (PCI slot_name etc) */
#ifdef DEVNUM_ROUND_ROBIN
int devnum_next; /* Next open device number in round-robin
allocation */
#endif /* DEVNUM_ROUND_ROBIN */
struct usb_devmap devmap; /* Device map */
struct usb_operations *op; /* Operations (specific to the HC) */
struct usb_device *root_hub; /* Root hub */
struct list_head bus_list;
void *hcpriv; /* Host Controller private data */
int bandwidth_allocated; /* on this Host Controller; */
/* applies to Int. and Isoc. pipes; */
/* measured in microseconds/frame; */
/* range is 0..900, where 900 = */
/* 90% of a 1-millisecond frame */
int bandwidth_int_reqs; /* number of Interrupt requesters */
int bandwidth_isoc_reqs; /* number of Isoc. requesters */
/* usbdevfs inode list */
struct list_head inodes;
atomic_t refcnt;
};
struct usb_driver
{
struct module *owner;
const char *name;
void *(*probe)(struct usb_device *dev, /* the device */
unsigned intf, /* what interface */
const struct usb_device_id *id /* from id_table */
);
void(*disconnect)(struct usb_device *, void*);
struct list_head driver_list;
struct file_operations *fops;
int minor;
struct semaphore serialize;
int(*ioctl)(struct usb_device *dev, unsigned int code, void *buf);
const struct usb_device_id *id_table;
};
struct urb;
typedef void(*usb_complete_t)(struct urb*);
struct urb
{
spinlock_t lock; // lock for the URB
void *hcpriv; // private data for host controller
struct list_head urb_list; // list pointer to all active urbs
struct urb *next; // pointer to next URB
struct usb_device *dev; // pointer to associated USB device
unsigned int pipe; // pipe information
int status; // returned status
unsigned int transfer_flags;
// USB_DISABLE_SPD | USB_ISO_ASAP | etc.
void *transfer_buffer; // associated data buffer
dma_addr_t transfer_dma; // dma addr for transfer_buffer
int transfer_buffer_length; // data buffer length
int actual_length; // actual data buffer length
int bandwidth; // bandwidth for this transfer request (INT or ISO)
unsigned char *setup_packet; // setup packet (control only)
dma_addr_t setup_dma; // dma addr for setup_packet
//
int start_frame; // start frame (iso/irq only)
int number_of_packets; // number of packets in this request (iso)
int interval; // polling interval (irq only)
int error_count; // number of errors in this transfer (iso only)
int timeout; // timeout (in jiffies)
//
void *context; // context for completion routine
usb_complete_t complete; // pointer to completion routine
//
struct iso_packet_descriptor iso_frame_desc[0];
};
/*
* urb->transfer_flags:
*/
#define USB_DISABLE_SPD 0x0001
#define URB_SHORT_NOT_OK USB_DISABLE_SPD
#define USB_ISO_ASAP 0x0002
#define USB_ASYNC_UNLINK 0x0008
#define USB_QUEUE_BULK 0x0010
#define USB_NO_FSBR 0x0020
#define USB_ZERO_PACKET 0x0040
// Finish bulk OUTs always with zero length packet
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt
needed */
/* ... less overhead for QUEUE_BULK */
#define USB_TIMEOUT_KILLED 0x1000 // only set by HCD!
10.3.4 USB内核函数接口分析
int usb_register(struct usb_driver *new_driver)
{
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);
init_MUTEX(&new_driver->serialize);
/*将新驱动添加到驱动列表*/
list_add_tail(&new_driver->driver_list, &usb_driver_list);
/*深度优先搜索设备,使驱动程序驱动它们的接口*/
usb_scan_devices();
return 0;
}
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;
/* 从双向链表中摘下来 */
list_del(&driver->driver_list);
down(&usb_bus_list_lock);
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);
} up(&usb_bus_list_lock);
}
int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
unsigned char type, unsigned char id, void *buf, int size)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
(type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);
}
int usb_get_protocol(struct usb_device *dev, int ifnum)
{
unsigned char type;
int ret;
if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, ifnum, &type, 1, HZ * GET_TIMEOUT)) < 0)
return ret;
return type;
}
int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
protocol, ifnum, NULL, 0, HZ * SET_TIMEOUT);
}
int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
(type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);
}
int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFAC