drivers/usb/core/devio.c

Source file repositories/reference/linux-study-clean/drivers/usb/core/devio.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/core/devio.c
Extension
.c
Size
73077 bytes
Lines
2931
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

const struct file_operations usbdev_file_operations = {
	.owner =	  THIS_MODULE,
	.llseek =	  no_seek_end_llseek,
	.read =		  usbdev_read,
	.poll =		  usbdev_poll,
	.unlocked_ioctl = usbdev_ioctl,
	.compat_ioctl =   compat_ptr_ioctl,
	.mmap =           usbdev_mmap,
	.open =		  usbdev_open,
	.release =	  usbdev_release,
};

static void usbdev_remove(struct usb_device *udev)
{
	struct usb_dev_state *ps;

	/* Protect against simultaneous resume */
	mutex_lock(&usbfs_mutex);
	while (!list_empty(&udev->filelist)) {
		ps = list_entry(udev->filelist.next, struct usb_dev_state, list);
		destroy_all_async(ps);
		wake_up_all(&ps->wait);
		WRITE_ONCE(ps->not_yet_resumed, 0);
		wake_up_all(&ps->wait_for_resume);
		list_del_init(&ps->list);
		if (ps->discsignr)
			kill_pid_usb_asyncio(ps->discsignr, EPIPE, ps->disccontext,
					     ps->disc_pid, ps->cred);
	}
	mutex_unlock(&usbfs_mutex);
}

static int usbdev_notify(struct notifier_block *self,
			       unsigned long action, void *dev)
{
	switch (action) {
	case USB_DEVICE_ADD:
		break;
	case USB_DEVICE_REMOVE:
		usbdev_remove(dev);
		break;
	}
	return NOTIFY_OK;
}

static struct notifier_block usbdev_nb = {
	.notifier_call =	usbdev_notify,
};

static struct cdev usb_device_cdev;

int __init usb_devio_init(void)
{
	int retval;

	retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
					"usb_device");
	if (retval) {
		printk(KERN_ERR "Unable to register minors for usb_device\n");
		goto out;
	}
	cdev_init(&usb_device_cdev, &usbdev_file_operations);
	retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
	if (retval) {
		printk(KERN_ERR "Unable to get usb_device major %d\n",
		       USB_DEVICE_MAJOR);
		goto error_cdev;
	}
	usb_register_notify(&usbdev_nb);
out:
	return retval;

error_cdev:
	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
	goto out;
}

void usb_devio_cleanup(void)
{
	usb_unregister_notify(&usbdev_nb);
	cdev_del(&usb_device_cdev);
	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
}

Annotation

Implementation Notes