aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/pcwd_usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/pcwd_usb.c')
-rw-r--r--drivers/watchdog/pcwd_usb.c168
1 files changed, 82 insertions, 86 deletions
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
index bf443d077a1e..c1685c942de6 100644
--- a/drivers/watchdog/pcwd_usb.c
+++ b/drivers/watchdog/pcwd_usb.c
@@ -40,8 +40,7 @@
40#include <linux/slab.h> /* For kmalloc, ... */ 40#include <linux/slab.h> /* For kmalloc, ... */
41#include <linux/mutex.h> /* For mutex locking */ 41#include <linux/mutex.h> /* For mutex locking */
42#include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */ 42#include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
43 43#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
44#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
45 44
46 45
47#ifdef CONFIG_USB_DEBUG 46#ifdef CONFIG_USB_DEBUG
@@ -88,7 +87,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _
88#define USB_PCWD_PRODUCT_ID 0x1140 87#define USB_PCWD_PRODUCT_ID 0x1140
89 88
90/* table of devices that work with this driver */ 89/* table of devices that work with this driver */
91static struct usb_device_id usb_pcwd_table [] = { 90static struct usb_device_id usb_pcwd_table[] = {
92 { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) }, 91 { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) },
93 { } /* Terminating entry */ 92 { } /* Terminating entry */
94}; 93};
@@ -110,7 +109,7 @@ MODULE_DEVICE_TABLE (usb, usb_pcwd_table);
110#define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG 109#define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG
111 110
112/* Watchdog's Dip Switch heartbeat values */ 111/* Watchdog's Dip Switch heartbeat values */
113static const int heartbeat_tbl [] = { 112static const int heartbeat_tbl[] = {
114 5, /* OFF-OFF-OFF = 5 Sec */ 113 5, /* OFF-OFF-OFF = 5 Sec */
115 10, /* OFF-OFF-ON = 10 Sec */ 114 10, /* OFF-OFF-ON = 10 Sec */
116 30, /* OFF-ON-OFF = 30 Sec */ 115 30, /* OFF-ON-OFF = 30 Sec */
@@ -130,15 +129,15 @@ static char expect_release;
130 129
131/* Structure to hold all of our device specific stuff */ 130/* Structure to hold all of our device specific stuff */
132struct usb_pcwd_private { 131struct usb_pcwd_private {
133 struct usb_device * udev; /* save off the usb device pointer */ 132 struct usb_device *udev; /* save off the usb device pointer */
134 struct usb_interface * interface; /* the interface for this device */ 133 struct usb_interface *interface; /* the interface for this device */
135 134
136 unsigned int interface_number; /* the interface number used for cmd's */ 135 unsigned int interface_number; /* the interface number used for cmd's */
137 136
138 unsigned char * intr_buffer; /* the buffer to intr data */ 137 unsigned char *intr_buffer; /* the buffer to intr data */
139 dma_addr_t intr_dma; /* the dma address for the intr buffer */ 138 dma_addr_t intr_dma; /* the dma address for the intr buffer */
140 size_t intr_size; /* the size of the intr buffer */ 139 size_t intr_size; /* the size of the intr buffer */
141 struct urb * intr_urb; /* the urb used for the intr pipe */ 140 struct urb *intr_urb; /* the urb used for the intr pipe */
142 141
143 unsigned char cmd_command; /* The command that is reported back */ 142 unsigned char cmd_command; /* The command that is reported back */
144 unsigned char cmd_data_msb; /* The data MSB that is reported back */ 143 unsigned char cmd_data_msb; /* The data MSB that is reported back */
@@ -154,8 +153,8 @@ static struct usb_pcwd_private *usb_pcwd_device;
154static DEFINE_MUTEX(disconnect_mutex); 153static DEFINE_MUTEX(disconnect_mutex);
155 154
156/* local function prototypes */ 155/* local function prototypes */
157static int usb_pcwd_probe (struct usb_interface *interface, const struct usb_device_id *id); 156static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id);
158static void usb_pcwd_disconnect (struct usb_interface *interface); 157static void usb_pcwd_disconnect(struct usb_interface *interface);
159 158
160/* usb specific object needed to register this driver with the usb subsystem */ 159/* usb specific object needed to register this driver with the usb subsystem */
161static struct usb_driver usb_pcwd_driver = { 160static struct usb_driver usb_pcwd_driver = {
@@ -195,10 +194,10 @@ static void usb_pcwd_intr_done(struct urb *urb)
195 usb_pcwd->cmd_data_lsb = data[2]; 194 usb_pcwd->cmd_data_lsb = data[2];
196 195
197 /* notify anyone waiting that the cmd has finished */ 196 /* notify anyone waiting that the cmd has finished */
198 atomic_set (&usb_pcwd->cmd_received, 1); 197 atomic_set(&usb_pcwd->cmd_received, 1);
199 198
200resubmit: 199resubmit:
201 retval = usb_submit_urb (urb, GFP_ATOMIC); 200 retval = usb_submit_urb(urb, GFP_ATOMIC);
202 if (retval) 201 if (retval)
203 printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n", 202 printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n",
204 retval); 203 retval);
@@ -224,7 +223,7 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha
224 dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x", 223 dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
225 buf[0], buf[1], buf[2]); 224 buf[0], buf[1], buf[2]);
226 225
227 atomic_set (&usb_pcwd->cmd_received, 0); 226 atomic_set(&usb_pcwd->cmd_received, 0);
228 227
229 if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0), 228 if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
230 HID_REQ_SET_REPORT, HID_DT_REPORT, 229 HID_REQ_SET_REPORT, HID_DT_REPORT,
@@ -237,7 +236,7 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha
237 got_response = 0; 236 got_response = 0;
238 for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) { 237 for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) {
239 mdelay(1); 238 mdelay(1);
240 if (atomic_read (&usb_pcwd->cmd_received)) 239 if (atomic_read(&usb_pcwd->cmd_received))
241 got_response = 1; 240 got_response = 1;
242 } 241 }
243 242
@@ -356,7 +355,7 @@ static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
356 /* scan to see whether or not we got the magic character */ 355 /* scan to see whether or not we got the magic character */
357 for (i = 0; i != len; i++) { 356 for (i = 0; i != len; i++) {
358 char c; 357 char c;
359 if(get_user(c, data+i)) 358 if (get_user(c, data + i))
360 return -EFAULT; 359 return -EFAULT;
361 if (c == 'V') 360 if (c == 'V')
362 expect_release = 42; 361 expect_release = 42;
@@ -369,8 +368,8 @@ static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
369 return len; 368 return len;
370} 369}
371 370
372static int usb_pcwd_ioctl(struct inode *inode, struct file *file, 371static long usb_pcwd_ioctl(struct file *file, unsigned int cmd,
373 unsigned int cmd, unsigned long arg) 372 unsigned long arg)
374{ 373{
375 void __user *argp = (void __user *)arg; 374 void __user *argp = (void __user *)arg;
376 int __user *p = argp; 375 int __user *p = argp;
@@ -383,77 +382,76 @@ static int usb_pcwd_ioctl(struct inode *inode, struct file *file,
383 }; 382 };
384 383
385 switch (cmd) { 384 switch (cmd) {
386 case WDIOC_GETSUPPORT: 385 case WDIOC_GETSUPPORT:
387 return copy_to_user(argp, &ident, 386 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
388 sizeof (ident)) ? -EFAULT : 0;
389 387
390 case WDIOC_GETSTATUS: 388 case WDIOC_GETSTATUS:
391 case WDIOC_GETBOOTSTATUS: 389 case WDIOC_GETBOOTSTATUS:
392 return put_user(0, p); 390 return put_user(0, p);
393 391
394 case WDIOC_GETTEMP: 392 case WDIOC_GETTEMP:
395 { 393 {
396 int temperature; 394 int temperature;
397 395
398 if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) 396 if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
399 return -EFAULT; 397 return -EFAULT;
400 398
401 return put_user(temperature, p); 399 return put_user(temperature, p);
402 } 400 }
403 401
404 case WDIOC_KEEPALIVE: 402 case WDIOC_SETOPTIONS:
405 usb_pcwd_keepalive(usb_pcwd_device); 403 {
406 return 0; 404 int new_options, retval = -EINVAL;
407 405
408 case WDIOC_SETOPTIONS: 406 if (get_user(new_options, p))
409 { 407 return -EFAULT;
410 int new_options, retval = -EINVAL;
411 408
412 if (get_user (new_options, p)) 409 if (new_options & WDIOS_DISABLECARD) {
413 return -EFAULT; 410 usb_pcwd_stop(usb_pcwd_device);
411 retval = 0;
412 }
414 413
415 if (new_options & WDIOS_DISABLECARD) { 414 if (new_options & WDIOS_ENABLECARD) {
416 usb_pcwd_stop(usb_pcwd_device); 415 usb_pcwd_start(usb_pcwd_device);
417 retval = 0; 416 retval = 0;
418 } 417 }
419 418
420 if (new_options & WDIOS_ENABLECARD) { 419 return retval;
421 usb_pcwd_start(usb_pcwd_device); 420 }
422 retval = 0;
423 }
424 421
425 return retval; 422 case WDIOC_KEEPALIVE:
426 } 423 usb_pcwd_keepalive(usb_pcwd_device);
424 return 0;
427 425
428 case WDIOC_SETTIMEOUT: 426 case WDIOC_SETTIMEOUT:
429 { 427 {
430 int new_heartbeat; 428 int new_heartbeat;
431 429
432 if (get_user(new_heartbeat, p)) 430 if (get_user(new_heartbeat, p))
433 return -EFAULT; 431 return -EFAULT;
434 432
435 if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) 433 if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
436 return -EINVAL; 434 return -EINVAL;
437 435
438 usb_pcwd_keepalive(usb_pcwd_device); 436 usb_pcwd_keepalive(usb_pcwd_device);
439 /* Fall */ 437 /* Fall */
440 } 438 }
441 439
442 case WDIOC_GETTIMEOUT: 440 case WDIOC_GETTIMEOUT:
443 return put_user(heartbeat, p); 441 return put_user(heartbeat, p);
444 442
445 case WDIOC_GETTIMELEFT: 443 case WDIOC_GETTIMELEFT:
446 { 444 {
447 int time_left; 445 int time_left;
448 446
449 if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left)) 447 if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
450 return -EFAULT; 448 return -EFAULT;
451 449
452 return put_user(time_left, p); 450 return put_user(time_left, p);
453 } 451 }
454 452
455 default: 453 default:
456 return -ENOTTY; 454 return -ENOTTY;
457 } 455 }
458} 456}
459 457
@@ -519,10 +517,8 @@ static int usb_pcwd_temperature_release(struct inode *inode, struct file *file)
519 517
520static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) 518static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
521{ 519{
522 if (code==SYS_DOWN || code==SYS_HALT) { 520 if (code == SYS_DOWN || code == SYS_HALT)
523 /* Turn the WDT off */ 521 usb_pcwd_stop(usb_pcwd_device); /* Turn the WDT off */
524 usb_pcwd_stop(usb_pcwd_device);
525 }
526 522
527 return NOTIFY_DONE; 523 return NOTIFY_DONE;
528} 524}
@@ -535,7 +531,7 @@ static const struct file_operations usb_pcwd_fops = {
535 .owner = THIS_MODULE, 531 .owner = THIS_MODULE,
536 .llseek = no_llseek, 532 .llseek = no_llseek,
537 .write = usb_pcwd_write, 533 .write = usb_pcwd_write,
538 .ioctl = usb_pcwd_ioctl, 534 .unlocked_ioctl = usb_pcwd_ioctl,
539 .open = usb_pcwd_open, 535 .open = usb_pcwd_open,
540 .release = usb_pcwd_release, 536 .release = usb_pcwd_release,
541}; 537};
@@ -567,13 +563,13 @@ static struct notifier_block usb_pcwd_notifier = {
567/** 563/**
568 * usb_pcwd_delete 564 * usb_pcwd_delete
569 */ 565 */
570static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd) 566static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd)
571{ 567{
572 usb_free_urb(usb_pcwd->intr_urb); 568 usb_free_urb(usb_pcwd->intr_urb);
573 if (usb_pcwd->intr_buffer != NULL) 569 if (usb_pcwd->intr_buffer != NULL)
574 usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size, 570 usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size,
575 usb_pcwd->intr_buffer, usb_pcwd->intr_dma); 571 usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
576 kfree (usb_pcwd); 572 kfree(usb_pcwd);
577} 573}
578 574
579/** 575/**
@@ -626,7 +622,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
626 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); 622 maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
627 623
628 /* allocate memory for our device and initialize it */ 624 /* allocate memory for our device and initialize it */
629 usb_pcwd = kzalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL); 625 usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
630 if (usb_pcwd == NULL) { 626 if (usb_pcwd == NULL) {
631 printk(KERN_ERR PFX "Out of memory\n"); 627 printk(KERN_ERR PFX "Out of memory\n");
632 goto error; 628 goto error;
@@ -641,7 +637,8 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
641 usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8); 637 usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8);
642 638
643 /* set up the memory buffer's */ 639 /* set up the memory buffer's */
644 if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma))) { 640 usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma);
641 if (!usb_pcwd->intr_buffer) {
645 printk(KERN_ERR PFX "Out of memory\n"); 642 printk(KERN_ERR PFX "Out of memory\n");
646 goto error; 643 goto error;
647 } 644 }
@@ -675,11 +672,10 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
675 672
676 /* Get the Firmware Version */ 673 /* Get the Firmware Version */
677 got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); 674 got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
678 if (got_fw_rev) { 675 if (got_fw_rev)
679 sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); 676 sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
680 } else { 677 else
681 sprintf(fw_ver_str, "<card no answer>"); 678 sprintf(fw_ver_str, "<card no answer>");
682 }
683 679
684 printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n", 680 printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n",
685 fw_ver_str); 681 fw_ver_str);
@@ -725,7 +721,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
725 } 721 }
726 722
727 /* we can register the device now, as it is ready */ 723 /* we can register the device now, as it is ready */
728 usb_set_intfdata (interface, usb_pcwd); 724 usb_set_intfdata(interface, usb_pcwd);
729 725
730 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", 726 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
731 heartbeat, nowayout); 727 heartbeat, nowayout);
@@ -759,8 +755,8 @@ static void usb_pcwd_disconnect(struct usb_interface *interface)
759 /* prevent races with open() */ 755 /* prevent races with open() */
760 mutex_lock(&disconnect_mutex); 756 mutex_lock(&disconnect_mutex);
761 757
762 usb_pcwd = usb_get_intfdata (interface); 758 usb_pcwd = usb_get_intfdata(interface);
763 usb_set_intfdata (interface, NULL); 759 usb_set_intfdata(interface, NULL);
764 760
765 mutex_lock(&usb_pcwd->mtx); 761 mutex_lock(&usb_pcwd->mtx);
766 762
@@ -820,5 +816,5 @@ static void __exit usb_pcwd_exit(void)
820} 816}
821 817
822 818
823module_init (usb_pcwd_init); 819module_init(usb_pcwd_init);
824module_exit (usb_pcwd_exit); 820module_exit(usb_pcwd_exit);