drivers/usb/misc/legousbtower.c

Source file repositories/reference/linux-study-clean/drivers/usb/misc/legousbtower.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/misc/legousbtower.c
Extension
.c
Size
24772 bytes
Lines
880
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations tower_fops = {
	.owner =	THIS_MODULE,
	.read  =	tower_read,
	.write =	tower_write,
	.open =		tower_open,
	.release =	tower_release,
	.poll =		tower_poll,
	.llseek =	tower_llseek,
};

static char *legousbtower_devnode(const struct device *dev, umode_t *mode)
{
	return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev));
}

/*
 * usb class driver info in order to get a minor number from the usb core,
 * and to have the device registered with the driver core
 */
static struct usb_class_driver tower_class = {
	.name =		"legousbtower%d",
	.devnode = 	legousbtower_devnode,
	.fops =		&tower_fops,
	.minor_base =	LEGO_USB_TOWER_MINOR_BASE,
};


/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver tower_driver = {
	.name =		"legousbtower",
	.probe =	tower_probe,
	.disconnect =	tower_disconnect,
	.id_table =	tower_table,
};


/*
 *	lego_usb_tower_debug_data
 */
static inline void lego_usb_tower_debug_data(struct device *dev,
					     const char *function, int size,
					     const unsigned char *data)
{
	dev_dbg(dev, "%s - length = %d, data = %*ph\n",
		function, size, size, data);
}


/*
 *	tower_delete
 */
static inline void tower_delete(struct lego_usb_tower *dev)
{
	/* free data structures */
	usb_free_urb(dev->interrupt_in_urb);
	usb_free_urb(dev->interrupt_out_urb);
	kfree(dev->read_buffer);
	kfree(dev->interrupt_in_buffer);
	kfree(dev->interrupt_out_buffer);
	usb_put_dev(dev->udev);
	kfree(dev);
}


/*
 *	tower_open
 */
static int tower_open(struct inode *inode, struct file *file)
{
	struct lego_usb_tower *dev = NULL;
	int subminor;
	int retval = 0;
	struct usb_interface *interface;
	struct tower_reset_reply reset_reply;
	int result;

	nonseekable_open(inode, file);
	subminor = iminor(inode);

	interface = usb_find_interface(&tower_driver, subminor);
	if (!interface) {
		pr_err("error, can't find device for minor %d\n", subminor);
		retval = -ENODEV;
		goto exit;
	}

	dev = usb_get_intfdata(interface);
	if (!dev) {
		retval = -ENODEV;
		goto exit;

Annotation

Implementation Notes