drivers/watchdog/pcwd_usb.c

Source file repositories/reference/linux-study-clean/drivers/watchdog/pcwd_usb.c

File Facts

System
Linux kernel
Corpus path
drivers/watchdog/pcwd_usb.c
Extension
.c
Size
21384 bytes
Lines
806
Domain
Driver Families
Bucket
drivers/watchdog
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_pcwd_fops = {
	.owner =	THIS_MODULE,
	.write =	usb_pcwd_write,
	.unlocked_ioctl = usb_pcwd_ioctl,
	.compat_ioctl = compat_ptr_ioctl,
	.open =		usb_pcwd_open,
	.release =	usb_pcwd_release,
};

static struct miscdevice usb_pcwd_miscdev = {
	.minor =	WATCHDOG_MINOR,
	.name =		"watchdog",
	.fops =		&usb_pcwd_fops,
};

static const struct file_operations usb_pcwd_temperature_fops = {
	.owner =	THIS_MODULE,
	.read =		usb_pcwd_temperature_read,
	.open =		usb_pcwd_temperature_open,
	.release =	usb_pcwd_temperature_release,
};

static struct miscdevice usb_pcwd_temperature_miscdev = {
	.minor =	TEMP_MINOR,
	.name =		"temperature",
	.fops =		&usb_pcwd_temperature_fops,
};

static struct notifier_block usb_pcwd_notifier = {
	.notifier_call =	usb_pcwd_notify_sys,
};

/*
 *	usb_pcwd_delete
 */
static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd)
{
	usb_free_urb(usb_pcwd->intr_urb);
	usb_free_coherent(usb_pcwd->udev, usb_pcwd->intr_size,
			  usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
	kfree(usb_pcwd);
}

/*
 *	usb_pcwd_probe
 *
 *	Called by the usb core when a new device is connected that it thinks
 *	this driver might be interested in.
 */
static int usb_pcwd_probe(struct usb_interface *interface,
						const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(interface);
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	struct usb_pcwd_private *usb_pcwd = NULL;
	int pipe;
	int retval = -ENOMEM;
	int got_fw_rev;
	unsigned char fw_rev_major, fw_rev_minor;
	char fw_ver_str[20];
	unsigned char option_switches, dummy;

	cards_found++;
	if (cards_found > 1) {
		pr_err("This driver only supports 1 device\n");
		return -ENODEV;
	}

	/* get the active interface descriptor */
	iface_desc = interface->cur_altsetting;

	/* check out that we have a HID device */
	if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
		pr_err("The device isn't a Human Interface Device\n");
		return -ENODEV;
	}

	if (iface_desc->desc.bNumEndpoints < 1)
		return -ENODEV;

	/* check out the endpoint: it has to be Interrupt & IN */
	endpoint = &iface_desc->endpoint[0].desc;

	if (!usb_endpoint_is_int_in(endpoint)) {
		/* we didn't find a Interrupt endpoint with direction IN */
		pr_err("Couldn't find an INTR & IN endpoint\n");
		return -ENODEV;
	}

Annotation

Implementation Notes