drivers/usb/misc/iowarrior.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/misc/iowarrior.c
Extension
.c
Size
25869 bytes
Lines
934
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 iowarrior_fops = {
	.owner = THIS_MODULE,
	.write = iowarrior_write,
	.read = iowarrior_read,
	.unlocked_ioctl = iowarrior_ioctl,
	.open = iowarrior_open,
	.release = iowarrior_release,
	.poll = iowarrior_poll,
	.llseek = noop_llseek,
};

static char *iowarrior_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 devfs and the driver core
 */
static struct usb_class_driver iowarrior_class = {
	.name = "iowarrior%d",
	.devnode = iowarrior_devnode,
	.fops = &iowarrior_fops,
	.minor_base = IOWARRIOR_MINOR_BASE,
};

/*---------------------------------*/
/*  probe and disconnect functions */
/*---------------------------------*/
/*
 *	iowarrior_probe
 *
 *	Called by the usb core when a new device is connected that it thinks
 *	this driver might be interested in.
 */
static int iowarrior_probe(struct usb_interface *interface,
			   const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(interface);
	struct iowarrior *dev = NULL;
	struct usb_host_interface *iface_desc;
	int retval = -ENOMEM;
	int res;
	int minor;

	/* allocate memory for our device state and initialize it */
	dev = kzalloc_obj(struct iowarrior);
	if (!dev)
		return retval;

	mutex_init(&dev->mutex);

	atomic_set(&dev->intr_idx, 0);
	atomic_set(&dev->read_idx, 0);
	atomic_set(&dev->overflow_flag, 0);
	init_waitqueue_head(&dev->read_wait);
	atomic_set(&dev->write_busy, 0);
	init_waitqueue_head(&dev->write_wait);

	dev->udev = udev;
	dev->interface = usb_get_intf(interface);

	iface_desc = interface->cur_altsetting;
	dev->product_id = le16_to_cpu(udev->descriptor.idProduct);

	init_usb_anchor(&dev->submitted);

	res = usb_find_last_int_in_endpoint(iface_desc, &dev->int_in_endpoint);
	if (res) {
		dev_err(&interface->dev, "no interrupt-in endpoint found\n");
		retval = res;
		goto error;
	}

	if ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) ||
	    (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) ||
	    (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) ||
	    (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) ||
	    (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100)) {
		res = usb_find_last_int_out_endpoint(iface_desc,
				&dev->int_out_endpoint);
		if (res) {
			dev_err(&interface->dev, "no interrupt-out endpoint found\n");
			retval = res;
			goto error;
		}
	}

	/* we have to check the report_size often, so remember it in the endianness suitable for our machine */

Annotation

Implementation Notes