drivers/usb/misc/sisusbvga/sisusbvga.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/misc/sisusbvga/sisusbvga.c
Extension
.c
Size
71020 bytes
Lines
2970
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 usb_sisusb_fops = {
	.owner =	THIS_MODULE,
	.open =		sisusb_open,
	.release =	sisusb_release,
	.read =		sisusb_read,
	.write =	sisusb_write,
	.llseek =	sisusb_lseek,
#ifdef CONFIG_COMPAT
	.compat_ioctl = sisusb_compat_ioctl,
#endif
	.unlocked_ioctl = sisusb_ioctl
};

static struct usb_class_driver usb_sisusb_class = {
	.name =		"sisusbvga%d",
	.fops =		&usb_sisusb_fops,
	.minor_base =	SISUSB_MINOR
};

static int sisusb_probe(struct usb_interface *intf,
		const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct sisusb_usb_data *sisusb;
	int retval = 0, i;
	static const u8 ep_addresses[] = {
		SISUSB_EP_GFX_IN | USB_DIR_IN,
		SISUSB_EP_GFX_OUT | USB_DIR_OUT,
		SISUSB_EP_GFX_BULK_OUT | USB_DIR_OUT,
		SISUSB_EP_GFX_LBULK_OUT | USB_DIR_OUT,
		SISUSB_EP_BRIDGE_IN | USB_DIR_IN,
		SISUSB_EP_BRIDGE_OUT | USB_DIR_OUT,
		0};

	/* Are the expected endpoints present? */
	if (!usb_check_bulk_endpoints(intf, ep_addresses)) {
		dev_err(&intf->dev, "Invalid USB2VGA device\n");
		return -EINVAL;
	}

	dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
			dev->devnum);

	/* Allocate memory for our private */
	sisusb = kzalloc_obj(*sisusb);
	if (!sisusb)
		return -ENOMEM;

	kref_init(&sisusb->kref);

	mutex_init(&(sisusb->lock));

	sisusb->sisusb_dev = dev;
	sisusb->vrambase   = SISUSB_PCI_MEMBASE;
	sisusb->mmiobase   = SISUSB_PCI_MMIOBASE;
	sisusb->mmiosize   = SISUSB_PCI_MMIOSIZE;
	sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
	/* Everything else is zero */

	/* Register device */
	retval = usb_register_dev(intf, &usb_sisusb_class);
	if (retval) {
		dev_err(&sisusb->sisusb_dev->dev,
				"Failed to get a minor for device %d\n",
				dev->devnum);
		retval = -ENODEV;
		goto error_1;
	}

	sisusb->minor = intf->minor;

	/* Allocate buffers */
	sisusb->ibufsize = SISUSB_IBUF_SIZE;
	sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL);
	if (!sisusb->ibuf) {
		retval = -ENOMEM;
		goto error_2;
	}

	sisusb->numobufs = 0;
	sisusb->obufsize = SISUSB_OBUF_SIZE;
	for (i = 0; i < NUMOBUFS; i++) {
		sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL);
		if (!sisusb->obuf[i]) {
			if (i == 0) {
				retval = -ENOMEM;
				goto error_3;
			}
			break;
		}

Annotation

Implementation Notes