⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcwd_usb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
				retval = 0;			}			if (new_options & WDIOS_ENABLECARD) {				usb_pcwd_start(usb_pcwd_device);				retval = 0;			}			return retval;		}		case WDIOC_SETTIMEOUT:		{			int new_heartbeat;			if (get_user(new_heartbeat, p))				return -EFAULT;			if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))			    return -EINVAL;			usb_pcwd_keepalive(usb_pcwd_device);			/* Fall */		}		case WDIOC_GETTIMEOUT:			return put_user(heartbeat, p);		default:			return -ENOIOCTLCMD;	}}static int usb_pcwd_open(struct inode *inode, struct file *file){	/* /dev/watchdog can only be opened once */	if (test_and_set_bit(0, &is_active))		return -EBUSY;	/* Activate */	usb_pcwd_start(usb_pcwd_device);	usb_pcwd_keepalive(usb_pcwd_device);	return nonseekable_open(inode, file);}static int usb_pcwd_release(struct inode *inode, struct file *file){	/*	 *      Shut off the timer.	 */	if (expect_release == 42) {		usb_pcwd_stop(usb_pcwd_device);	} else {		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");		usb_pcwd_keepalive(usb_pcwd_device);	}	expect_release = 0;	clear_bit(0, &is_active);	return 0;}/* *	/dev/temperature handling */static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data,				size_t len, loff_t *ppos){	int temperature;	if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))		return -EFAULT;	if (copy_to_user(data, &temperature, 1))		return -EFAULT;	return 1;}static int usb_pcwd_temperature_open(struct inode *inode, struct file *file){	return nonseekable_open(inode, file);}static int usb_pcwd_temperature_release(struct inode *inode, struct file *file){	return 0;}/* *	Notify system */static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused){	if (code==SYS_DOWN || code==SYS_HALT) {		/* Turn the WDT off */		usb_pcwd_stop(usb_pcwd_device);	}	return NOTIFY_DONE;}/* *	Kernel Interfaces */static struct file_operations usb_pcwd_fops = {	.owner =	THIS_MODULE,	.llseek =	no_llseek,	.write =	usb_pcwd_write,	.ioctl =	usb_pcwd_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 struct file_operations usb_pcwd_temperature_fops = {	.owner =	THIS_MODULE,	.llseek =	no_llseek,	.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){	if (usb_pcwd->intr_urb != NULL)		usb_free_urb (usb_pcwd->intr_urb);	if (usb_pcwd->intr_buffer != NULL)		usb_buffer_free(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, maxp;	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) {		printk(KERN_ERR PFX "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)) {		printk(KERN_ERR PFX "The device isn't a Human Interface Device\n");		return -ENODEV;	}	/* check out the endpoint: it has to be Interrupt & IN */	endpoint = &iface_desc->endpoint[0].desc;	if (!((endpoint->bEndpointAddress & USB_DIR_IN) &&	     ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)				== USB_ENDPOINT_XFER_INT))) {		/* we didn't find a Interrupt endpoint with direction IN */		printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n");		return -ENODEV;	}	/* get a handle to the interrupt data pipe */	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));	/* allocate memory for our device and initialize it */	usb_pcwd = kmalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL);	if (usb_pcwd == NULL) {		printk(KERN_ERR PFX "Out of memory\n");		goto error;	}	memset (usb_pcwd, 0x00, sizeof (*usb_pcwd));	usb_pcwd_device = usb_pcwd;	init_MUTEX (&usb_pcwd->sem);	usb_pcwd->udev = udev;	usb_pcwd->interface = interface;	usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;	usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8);	/* set up the memory buffer's */	if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, SLAB_ATOMIC, &usb_pcwd->intr_dma))) {		printk(KERN_ERR PFX "Out of memory\n");		goto error;	}	/* allocate the urb's */	usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);	if (!usb_pcwd->intr_urb) {		printk(KERN_ERR PFX "Out of memory\n");		goto error;	}	/* initialise the intr urb's */	usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe,			usb_pcwd->intr_buffer, usb_pcwd->intr_size,			usb_pcwd_intr_done, usb_pcwd, endpoint->bInterval);	usb_pcwd->intr_urb->transfer_dma = usb_pcwd->intr_dma;	usb_pcwd->intr_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;	/* register our interrupt URB with the USB system */	if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {		printk(KERN_ERR PFX "Problem registering interrupt URB\n");		retval = -EIO; /* failure */		goto error;	}	/* The device exists and can be communicated with */	usb_pcwd->exists = 1;	/* disable card */	usb_pcwd_stop(usb_pcwd);	/* Get the Firmware Version */	got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);	if (got_fw_rev) {		sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);	} else {		sprintf(fw_ver_str, "<card no answer>");	}	printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n",		fw_ver_str);	/* Get switch settings */	usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, &option_switches);	printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",		option_switches,		((option_switches & 0x10) ? "ON" : "OFF"),		((option_switches & 0x08) ? "ON" : "OFF"));	/* Check that the heartbeat value is within it's range ; if not reset to the default */	if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {		usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);		printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",			WATCHDOG_HEARTBEAT);	}	retval = register_reboot_notifier(&usb_pcwd_notifier);	if (retval != 0) {		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",			retval);		goto error;	}	retval = misc_register(&usb_pcwd_temperature_miscdev);	if (retval != 0) {		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",			TEMP_MINOR, retval);		goto err_out_unregister_reboot;	}	retval = misc_register(&usb_pcwd_miscdev);	if (retval != 0) {		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",			WATCHDOG_MINOR, retval);		goto err_out_misc_deregister;	}	/* we can register the device now, as it is ready */	usb_set_intfdata (interface, usb_pcwd);	printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",		heartbeat, nowayout);	return 0;err_out_misc_deregister:	misc_deregister(&usb_pcwd_temperature_miscdev);err_out_unregister_reboot:	unregister_reboot_notifier(&usb_pcwd_notifier);error:	usb_pcwd_delete (usb_pcwd);	usb_pcwd_device = NULL;	return retval;}/** *	usb_pcwd_disconnect * *	Called by the usb core when the device is removed from the system. * *	This routine guarantees that the driver will not submit any more urbs *	by clearing dev->udev. */static void usb_pcwd_disconnect(struct usb_interface *interface){	struct usb_pcwd_private *usb_pcwd;	/* prevent races with open() */	down (&disconnect_sem);	usb_pcwd = usb_get_intfdata (interface);	usb_set_intfdata (interface, NULL);	down (&usb_pcwd->sem);	/* Stop the timer before we leave */	if (!nowayout)		usb_pcwd_stop(usb_pcwd);	/* We should now stop communicating with the USB PCWD device */	usb_pcwd->exists = 0;	/* Deregister */	misc_deregister(&usb_pcwd_miscdev);	misc_deregister(&usb_pcwd_temperature_miscdev);	unregister_reboot_notifier(&usb_pcwd_notifier);	up (&usb_pcwd->sem);	/* Delete the USB PCWD device */	usb_pcwd_delete(usb_pcwd);	cards_found--;	up (&disconnect_sem);	printk(KERN_INFO PFX "USB PC Watchdog disconnected\n");}/** *	usb_pcwd_init */static int __init usb_pcwd_init(void){	int result;	/* register this driver with the USB subsystem */	result = usb_register(&usb_pcwd_driver);	if (result) {		printk(KERN_ERR PFX "usb_register failed. Error number %d\n",		    result);		return result;	}	printk(KERN_INFO PFX DRIVER_DESC " v" DRIVER_VERSION " (" DRIVER_DATE ")\n");	return 0;}/** *	usb_pcwd_exit */static void __exit usb_pcwd_exit(void){	/* deregister this driver with the USB subsystem */	usb_deregister(&usb_pcwd_driver);}module_init (usb_pcwd_init);module_exit (usb_pcwd_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -