Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcwd_usb.c
Go to the documentation of this file.
1 /*
2  * Berkshire USB-PC Watchdog Card Driver
3  *
4  * (c) Copyright 2004-2007 Wim Van Sebroeck <[email protected]>.
5  *
6  * Based on source code of the following authors:
7  * Ken Hollis <[email protected]>,
8  * Alan Cox <[email protected]>,
9  * Matt Domsch <[email protected]>,
10  * Rob Radez <[email protected]>,
11  * Greg Kroah-Hartman <[email protected]>
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version
16  * 2 of the License, or (at your option) any later version.
17  *
18  * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
19  * provide warranty for any of this software. This material is
20  * provided "AS-IS" and at no charge.
21  *
22  * Thanks also to Simon Machell at Berkshire Products Inc. for
23  * providing the test hardware. More info is available at
24  * http://www.berkprod.com/ or http://www.pcwatchdog.com/
25  */
26 
27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28 
29 #include <linux/module.h> /* For module specific items */
30 #include <linux/moduleparam.h> /* For new moduleparam's */
31 #include <linux/types.h> /* For standard types (like size_t) */
32 #include <linux/errno.h> /* For the -ENODEV/... values */
33 #include <linux/kernel.h> /* For printk/panic/... */
34 #include <linux/delay.h> /* For mdelay function */
35 #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
36 #include <linux/watchdog.h> /* For the watchdog specific items */
37 #include <linux/notifier.h> /* For notifier support */
38 #include <linux/reboot.h> /* For reboot_notifier stuff */
39 #include <linux/init.h> /* For __init/__exit/... */
40 #include <linux/fs.h> /* For file operations */
41 #include <linux/usb.h> /* For USB functions */
42 #include <linux/slab.h> /* For kmalloc, ... */
43 #include <linux/mutex.h> /* For mutex locking */
44 #include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
45 #include <linux/uaccess.h> /* For copy_to_user/put_user/... */
46 
47 #ifdef CONFIG_USB_DEBUG
48 static int debug = 1;
49 #else
50 static int debug;
51 #endif
52 
53 /* Use our own dbg macro */
54 
55 #undef dbg
56 #ifndef DEBUG
57 #define DEBUG
58 #endif
59 #define dbg(format, ...) \
60 do { \
61  if (debug) \
62  pr_debug(format "\n", ##__VA_ARGS__); \
63 } while (0)
64 
65 /* Module and Version Information */
66 #define DRIVER_VERSION "1.02"
67 #define DRIVER_AUTHOR "Wim Van Sebroeck <[email protected]>"
68 #define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
69 #define DRIVER_LICENSE "GPL"
70 #define DRIVER_NAME "pcwd_usb"
71 
77 
78 /* Module Parameters */
79 module_param(debug, int, 0);
80 MODULE_PARM_DESC(debug, "Debug enabled or not");
81 
82 #define WATCHDOG_HEARTBEAT 0 /* default heartbeat =
83  delay-time from dip-switches */
84 static int heartbeat = WATCHDOG_HEARTBEAT;
85 module_param(heartbeat, int, 0);
86 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
87  "(0<heartbeat<65536 or 0=delay-time from dip-switches, default="
89 
90 static bool nowayout = WATCHDOG_NOWAYOUT;
91 module_param(nowayout, bool, 0);
92 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
94 
95 /* The vendor and product id's for the USB-PC Watchdog card */
96 #define USB_PCWD_VENDOR_ID 0x0c98
97 #define USB_PCWD_PRODUCT_ID 0x1140
98 
99 /* table of devices that work with this driver */
100 static struct usb_device_id usb_pcwd_table[] = {
101  { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) },
102  { } /* Terminating entry */
103 };
104 MODULE_DEVICE_TABLE(usb, usb_pcwd_table);
105 
106 /* according to documentation max. time to process a command for the USB
107  * watchdog card is 100 or 200 ms, so we give it 250 ms to do it's job */
108 #define USB_COMMAND_TIMEOUT 250
109 
110 /* Watchdog's internal commands */
111 #define CMD_READ_TEMP 0x02 /* Read Temperature;
112  Re-trigger Watchdog */
113 #define CMD_TRIGGER CMD_READ_TEMP
114 #define CMD_GET_STATUS 0x04 /* Get Status Information */
115 #define CMD_GET_FIRMWARE_VERSION 0x08 /* Get Firmware Version */
116 #define CMD_GET_DIP_SWITCH_SETTINGS 0x0c /* Get Dip Switch Settings */
117 #define CMD_READ_WATCHDOG_TIMEOUT 0x18 /* Read Current Watchdog Time */
118 #define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 /* Write Current WatchdogTime */
119 #define CMD_ENABLE_WATCHDOG 0x30 /* Enable / Disable Watchdog */
120 #define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG
121 
122 /* Watchdog's Dip Switch heartbeat values */
123 static const int heartbeat_tbl[] = {
124  5, /* OFF-OFF-OFF = 5 Sec */
125  10, /* OFF-OFF-ON = 10 Sec */
126  30, /* OFF-ON-OFF = 30 Sec */
127  60, /* OFF-ON-ON = 1 Min */
128  300, /* ON-OFF-OFF = 5 Min */
129  600, /* ON-OFF-ON = 10 Min */
130  1800, /* ON-ON-OFF = 30 Min */
131  3600, /* ON-ON-ON = 1 hour */
132 };
133 
134 /* We can only use 1 card due to the /dev/watchdog restriction */
135 static int cards_found;
136 
137 /* some internal variables */
138 static unsigned long is_active;
139 static char expect_release;
141 /* Structure to hold all of our device specific stuff */
143  /* save off the usb device pointer */
144  struct usb_device *udev;
145  /* the interface for this device */
146  struct usb_interface *interface;
148  /* the interface number used for cmd's */
149  unsigned int interface_number;
151  /* the buffer to intr data */
152  unsigned char *intr_buffer;
153  /* the dma address for the intr buffer */
155  /* the size of the intr buffer */
156  size_t intr_size;
157  /* the urb used for the intr pipe */
158  struct urb *intr_urb;
160  /* The command that is reported back */
161  unsigned char cmd_command;
162  /* The data MSB that is reported back */
163  unsigned char cmd_data_msb;
164  /* The data LSB that is reported back */
165  unsigned char cmd_data_lsb;
166  /* true if we received a report after a command */
169  /* Wether or not the device exists */
170  int exists;
171  /* locks this structure */
172  struct mutex mtx;
173 };
174 static struct usb_pcwd_private *usb_pcwd_device;
175 
176 /* prevent races between open() and disconnect() */
177 static DEFINE_MUTEX(disconnect_mutex);
178 
179 /* local function prototypes */
180 static int usb_pcwd_probe(struct usb_interface *interface,
181  const struct usb_device_id *id);
182 static void usb_pcwd_disconnect(struct usb_interface *interface);
183 
184 /* usb specific object needed to register this driver with the usb subsystem */
185 static struct usb_driver usb_pcwd_driver = {
186  .name = DRIVER_NAME,
187  .probe = usb_pcwd_probe,
188  .disconnect = usb_pcwd_disconnect,
189  .id_table = usb_pcwd_table,
190 };
191 
192 
193 static void usb_pcwd_intr_done(struct urb *urb)
194 {
195  struct usb_pcwd_private *usb_pcwd =
196  (struct usb_pcwd_private *)urb->context;
197  unsigned char *data = usb_pcwd->intr_buffer;
198  int retval;
199 
200  switch (urb->status) {
201  case 0: /* success */
202  break;
203  case -ECONNRESET: /* unlink */
204  case -ENOENT:
205  case -ESHUTDOWN:
206  /* this urb is terminated, clean up */
207  dbg("%s - urb shutting down with status: %d", __func__,
208  urb->status);
209  return;
210  /* -EPIPE: should clear the halt */
211  default: /* error */
212  dbg("%s - nonzero urb status received: %d", __func__,
213  urb->status);
214  goto resubmit;
215  }
216 
217  dbg("received following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
218  data[0], data[1], data[2]);
219 
220  usb_pcwd->cmd_command = data[0];
221  usb_pcwd->cmd_data_msb = data[1];
222  usb_pcwd->cmd_data_lsb = data[2];
223 
224  /* notify anyone waiting that the cmd has finished */
225  atomic_set(&usb_pcwd->cmd_received, 1);
226 
227 resubmit:
229  if (retval)
230  pr_err("can't resubmit intr, usb_submit_urb failed with result %d\n",
231  retval);
232 }
233 
234 static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd,
235  unsigned char cmd, unsigned char *msb, unsigned char *lsb)
236 {
237  int got_response, count;
238  unsigned char buf[6];
239 
240  /* We will not send any commands if the USB PCWD device does
241  * not exist */
242  if ((!usb_pcwd) || (!usb_pcwd->exists))
243  return -1;
244 
245  /* The USB PC Watchdog uses a 6 byte report format.
246  * The board currently uses only 3 of the six bytes of the report. */
247  buf[0] = cmd; /* Byte 0 = CMD */
248  buf[1] = *msb; /* Byte 1 = Data MSB */
249  buf[2] = *lsb; /* Byte 2 = Data LSB */
250  buf[3] = buf[4] = buf[5] = 0; /* All other bytes not used */
251 
252  dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
253  buf[0], buf[1], buf[2]);
254 
255  atomic_set(&usb_pcwd->cmd_received, 0);
256 
257  if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
259  0x0200, usb_pcwd->interface_number, buf, sizeof(buf),
260  USB_COMMAND_TIMEOUT) != sizeof(buf)) {
261  dbg("usb_pcwd_send_command: error in usb_control_msg for "
262  "cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb);
263  }
264  /* wait till the usb card processed the command,
265  * with a max. timeout of USB_COMMAND_TIMEOUT */
266  got_response = 0;
267  for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response);
268  count++) {
269  mdelay(1);
270  if (atomic_read(&usb_pcwd->cmd_received))
271  got_response = 1;
272  }
273 
274  if ((got_response) && (cmd == usb_pcwd->cmd_command)) {
275  /* read back response */
276  *msb = usb_pcwd->cmd_data_msb;
277  *lsb = usb_pcwd->cmd_data_lsb;
278  }
279 
280  return got_response;
281 }
282 
283 static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd)
284 {
285  unsigned char msb = 0x00;
286  unsigned char lsb = 0x00;
287  int retval;
288 
289  /* Enable Watchdog */
290  retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG,
291  &msb, &lsb);
292 
293  if ((retval == 0) || (lsb == 0)) {
294  pr_err("Card did not acknowledge enable attempt\n");
295  return -1;
296  }
297 
298  return 0;
299 }
300 
301 static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd)
302 {
303  unsigned char msb = 0xA5;
304  unsigned char lsb = 0xC3;
305  int retval;
306 
307  /* Disable Watchdog */
308  retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG,
309  &msb, &lsb);
310 
311  if ((retval == 0) || (lsb != 0)) {
312  pr_err("Card did not acknowledge disable attempt\n");
313  return -1;
314  }
315 
316  return 0;
317 }
318 
319 static int usb_pcwd_keepalive(struct usb_pcwd_private *usb_pcwd)
320 {
321  unsigned char dummy;
322 
323  /* Re-trigger Watchdog */
324  usb_pcwd_send_command(usb_pcwd, CMD_TRIGGER, &dummy, &dummy);
325 
326  return 0;
327 }
328 
329 static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t)
330 {
331  unsigned char msb = t / 256;
332  unsigned char lsb = t % 256;
333 
334  if ((t < 0x0001) || (t > 0xFFFF))
335  return -EINVAL;
336 
337  /* Write new heartbeat to watchdog */
338  usb_pcwd_send_command(usb_pcwd, CMD_WRITE_WATCHDOG_TIMEOUT, &msb, &lsb);
339 
340  heartbeat = t;
341  return 0;
342 }
343 
344 static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd,
345  int *temperature)
346 {
347  unsigned char msb, lsb;
348 
349  usb_pcwd_send_command(usb_pcwd, CMD_READ_TEMP, &msb, &lsb);
350 
351  /*
352  * Convert celsius to fahrenheit, since this was
353  * the decided 'standard' for this return value.
354  */
355  *temperature = (lsb * 9 / 5) + 32;
356 
357  return 0;
358 }
359 
360 static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd,
361  int *time_left)
362 {
363  unsigned char msb, lsb;
364 
365  /* Read the time that's left before rebooting */
366  /* Note: if the board is not yet armed then we will read 0xFFFF */
367  usb_pcwd_send_command(usb_pcwd, CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);
368 
369  *time_left = (msb << 8) + lsb;
370 
371  return 0;
372 }
373 
374 /*
375  * /dev/watchdog handling
376  */
377 
378 static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
379  size_t len, loff_t *ppos)
380 {
381  /* See if we got the magic character 'V' and reload the timer */
382  if (len) {
383  if (!nowayout) {
384  size_t i;
385 
386  /* note: just in case someone wrote the magic character
387  * five months ago... */
388  expect_release = 0;
389 
390  /* scan to see whether or not we got the
391  * magic character */
392  for (i = 0; i != len; i++) {
393  char c;
394  if (get_user(c, data + i))
395  return -EFAULT;
396  if (c == 'V')
397  expect_release = 42;
398  }
399  }
400 
401  /* someone wrote to us, we should reload the timer */
402  usb_pcwd_keepalive(usb_pcwd_device);
403  }
404  return len;
405 }
406 
407 static long usb_pcwd_ioctl(struct file *file, unsigned int cmd,
408  unsigned long arg)
409 {
410  void __user *argp = (void __user *)arg;
411  int __user *p = argp;
412  static const struct watchdog_info ident = {
413  .options = WDIOF_KEEPALIVEPING |
416  .firmware_version = 1,
417  .identity = DRIVER_NAME,
418  };
419 
420  switch (cmd) {
421  case WDIOC_GETSUPPORT:
422  return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
423 
424  case WDIOC_GETSTATUS:
425  case WDIOC_GETBOOTSTATUS:
426  return put_user(0, p);
427 
428  case WDIOC_GETTEMP:
429  {
430  int temperature;
431 
432  if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
433  return -EFAULT;
434 
435  return put_user(temperature, p);
436  }
437 
438  case WDIOC_SETOPTIONS:
439  {
440  int new_options, retval = -EINVAL;
441 
442  if (get_user(new_options, p))
443  return -EFAULT;
444 
445  if (new_options & WDIOS_DISABLECARD) {
446  usb_pcwd_stop(usb_pcwd_device);
447  retval = 0;
448  }
449 
450  if (new_options & WDIOS_ENABLECARD) {
451  usb_pcwd_start(usb_pcwd_device);
452  retval = 0;
453  }
454 
455  return retval;
456  }
457 
458  case WDIOC_KEEPALIVE:
459  usb_pcwd_keepalive(usb_pcwd_device);
460  return 0;
461 
462  case WDIOC_SETTIMEOUT:
463  {
464  int new_heartbeat;
465 
466  if (get_user(new_heartbeat, p))
467  return -EFAULT;
468 
469  if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
470  return -EINVAL;
471 
472  usb_pcwd_keepalive(usb_pcwd_device);
473  /* Fall */
474  }
475 
476  case WDIOC_GETTIMEOUT:
477  return put_user(heartbeat, p);
478 
479  case WDIOC_GETTIMELEFT:
480  {
481  int time_left;
482 
483  if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
484  return -EFAULT;
485 
486  return put_user(time_left, p);
487  }
488 
489  default:
490  return -ENOTTY;
491  }
492 }
493 
494 static int usb_pcwd_open(struct inode *inode, struct file *file)
495 {
496  /* /dev/watchdog can only be opened once */
497  if (test_and_set_bit(0, &is_active))
498  return -EBUSY;
499 
500  /* Activate */
501  usb_pcwd_start(usb_pcwd_device);
502  usb_pcwd_keepalive(usb_pcwd_device);
503  return nonseekable_open(inode, file);
504 }
505 
506 static int usb_pcwd_release(struct inode *inode, struct file *file)
507 {
508  /*
509  * Shut off the timer.
510  */
511  if (expect_release == 42) {
512  usb_pcwd_stop(usb_pcwd_device);
513  } else {
514  pr_crit("Unexpected close, not stopping watchdog!\n");
515  usb_pcwd_keepalive(usb_pcwd_device);
516  }
517  expect_release = 0;
518  clear_bit(0, &is_active);
519  return 0;
520 }
521 
522 /*
523  * /dev/temperature handling
524  */
525 
526 static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data,
527  size_t len, loff_t *ppos)
528 {
529  int temperature;
530 
531  if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
532  return -EFAULT;
533 
534  if (copy_to_user(data, &temperature, 1))
535  return -EFAULT;
536 
537  return 1;
538 }
539 
540 static int usb_pcwd_temperature_open(struct inode *inode, struct file *file)
541 {
542  return nonseekable_open(inode, file);
543 }
544 
545 static int usb_pcwd_temperature_release(struct inode *inode, struct file *file)
546 {
547  return 0;
548 }
549 
550 /*
551  * Notify system
552  */
553 
554 static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code,
555  void *unused)
556 {
557  if (code == SYS_DOWN || code == SYS_HALT)
558  usb_pcwd_stop(usb_pcwd_device); /* Turn the WDT off */
559 
560  return NOTIFY_DONE;
561 }
562 
563 /*
564  * Kernel Interfaces
565  */
566 
567 static const struct file_operations usb_pcwd_fops = {
568  .owner = THIS_MODULE,
569  .llseek = no_llseek,
570  .write = usb_pcwd_write,
571  .unlocked_ioctl = usb_pcwd_ioctl,
572  .open = usb_pcwd_open,
573  .release = usb_pcwd_release,
574 };
575 
576 static struct miscdevice usb_pcwd_miscdev = {
577  .minor = WATCHDOG_MINOR,
578  .name = "watchdog",
579  .fops = &usb_pcwd_fops,
580 };
581 
582 static const struct file_operations usb_pcwd_temperature_fops = {
583  .owner = THIS_MODULE,
584  .llseek = no_llseek,
585  .read = usb_pcwd_temperature_read,
586  .open = usb_pcwd_temperature_open,
587  .release = usb_pcwd_temperature_release,
588 };
589 
590 static struct miscdevice usb_pcwd_temperature_miscdev = {
591  .minor = TEMP_MINOR,
592  .name = "temperature",
593  .fops = &usb_pcwd_temperature_fops,
594 };
595 
596 static struct notifier_block usb_pcwd_notifier = {
597  .notifier_call = usb_pcwd_notify_sys,
598 };
599 
603 static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd)
604 {
605  usb_free_urb(usb_pcwd->intr_urb);
606  if (usb_pcwd->intr_buffer != NULL)
607  usb_free_coherent(usb_pcwd->udev, usb_pcwd->intr_size,
608  usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
609  kfree(usb_pcwd);
610 }
611 
618 static int usb_pcwd_probe(struct usb_interface *interface,
619  const struct usb_device_id *id)
620 {
621  struct usb_device *udev = interface_to_usbdev(interface);
622  struct usb_host_interface *iface_desc;
624  struct usb_pcwd_private *usb_pcwd = NULL;
625  int pipe, maxp;
626  int retval = -ENOMEM;
627  int got_fw_rev;
628  unsigned char fw_rev_major, fw_rev_minor;
629  char fw_ver_str[20];
630  unsigned char option_switches, dummy;
631 
632  cards_found++;
633  if (cards_found > 1) {
634  pr_err("This driver only supports 1 device\n");
635  return -ENODEV;
636  }
637 
638  /* get the active interface descriptor */
639  iface_desc = interface->cur_altsetting;
640 
641  /* check out that we have a HID device */
642  if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
643  pr_err("The device isn't a Human Interface Device\n");
644  return -ENODEV;
645  }
646 
647  /* check out the endpoint: it has to be Interrupt & IN */
648  endpoint = &iface_desc->endpoint[0].desc;
649 
650  if (!usb_endpoint_is_int_in(endpoint)) {
651  /* we didn't find a Interrupt endpoint with direction IN */
652  pr_err("Couldn't find an INTR & IN endpoint\n");
653  return -ENODEV;
654  }
655 
656  /* get a handle to the interrupt data pipe */
657  pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
658  maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
659 
660  /* allocate memory for our device and initialize it */
661  usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
662  if (usb_pcwd == NULL) {
663  pr_err("Out of memory\n");
664  goto error;
665  }
666 
667  usb_pcwd_device = usb_pcwd;
668 
669  mutex_init(&usb_pcwd->mtx);
670  usb_pcwd->udev = udev;
671  usb_pcwd->interface = interface;
672  usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
673  usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ?
674  le16_to_cpu(endpoint->wMaxPacketSize) : 8);
675 
676  /* set up the memory buffer's */
677  usb_pcwd->intr_buffer = usb_alloc_coherent(udev, usb_pcwd->intr_size,
678  GFP_ATOMIC, &usb_pcwd->intr_dma);
679  if (!usb_pcwd->intr_buffer) {
680  pr_err("Out of memory\n");
681  goto error;
682  }
683 
684  /* allocate the urb's */
685  usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
686  if (!usb_pcwd->intr_urb) {
687  pr_err("Out of memory\n");
688  goto error;
689  }
690 
691  /* initialise the intr urb's */
692  usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe,
693  usb_pcwd->intr_buffer, usb_pcwd->intr_size,
694  usb_pcwd_intr_done, usb_pcwd, endpoint->bInterval);
695  usb_pcwd->intr_urb->transfer_dma = usb_pcwd->intr_dma;
696  usb_pcwd->intr_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
697 
698  /* register our interrupt URB with the USB system */
699  if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
700  pr_err("Problem registering interrupt URB\n");
701  retval = -EIO; /* failure */
702  goto error;
703  }
704 
705  /* The device exists and can be communicated with */
706  usb_pcwd->exists = 1;
707 
708  /* disable card */
709  usb_pcwd_stop(usb_pcwd);
710 
711  /* Get the Firmware Version */
712  got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION,
713  &fw_rev_major, &fw_rev_minor);
714  if (got_fw_rev)
715  sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
716  else
717  sprintf(fw_ver_str, "<card no answer>");
718 
719  pr_info("Found card (Firmware: %s) with temp option\n", fw_ver_str);
720 
721  /* Get switch settings */
722  usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy,
723  &option_switches);
724 
725  pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
726  option_switches,
727  ((option_switches & 0x10) ? "ON" : "OFF"),
728  ((option_switches & 0x08) ? "ON" : "OFF"));
729 
730  /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
731  if (heartbeat == 0)
732  heartbeat = heartbeat_tbl[(option_switches & 0x07)];
733 
734  /* Check that the heartbeat value is within it's range ;
735  * if not reset to the default */
736  if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
737  usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
738  pr_info("heartbeat value must be 0<heartbeat<65536, using %d\n",
740  }
741 
742  retval = register_reboot_notifier(&usb_pcwd_notifier);
743  if (retval != 0) {
744  pr_err("cannot register reboot notifier (err=%d)\n", retval);
745  goto error;
746  }
747 
748  retval = misc_register(&usb_pcwd_temperature_miscdev);
749  if (retval != 0) {
750  pr_err("cannot register miscdev on minor=%d (err=%d)\n",
751  TEMP_MINOR, retval);
752  goto err_out_unregister_reboot;
753  }
754 
755  retval = misc_register(&usb_pcwd_miscdev);
756  if (retval != 0) {
757  pr_err("cannot register miscdev on minor=%d (err=%d)\n",
758  WATCHDOG_MINOR, retval);
759  goto err_out_misc_deregister;
760  }
761 
762  /* we can register the device now, as it is ready */
763  usb_set_intfdata(interface, usb_pcwd);
764 
765  pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
766  heartbeat, nowayout);
767 
768  return 0;
769 
770 err_out_misc_deregister:
771  misc_deregister(&usb_pcwd_temperature_miscdev);
772 err_out_unregister_reboot:
773  unregister_reboot_notifier(&usb_pcwd_notifier);
774 error:
775  if (usb_pcwd)
776  usb_pcwd_delete(usb_pcwd);
777  usb_pcwd_device = NULL;
778  return retval;
779 }
780 
781 
790 static void usb_pcwd_disconnect(struct usb_interface *interface)
791 {
792  struct usb_pcwd_private *usb_pcwd;
793 
794  /* prevent races with open() */
795  mutex_lock(&disconnect_mutex);
796 
797  usb_pcwd = usb_get_intfdata(interface);
798  usb_set_intfdata(interface, NULL);
799 
800  mutex_lock(&usb_pcwd->mtx);
801 
802  /* Stop the timer before we leave */
803  if (!nowayout)
804  usb_pcwd_stop(usb_pcwd);
805 
806  /* We should now stop communicating with the USB PCWD device */
807  usb_pcwd->exists = 0;
808 
809  /* Deregister */
810  misc_deregister(&usb_pcwd_miscdev);
811  misc_deregister(&usb_pcwd_temperature_miscdev);
812  unregister_reboot_notifier(&usb_pcwd_notifier);
813 
814  mutex_unlock(&usb_pcwd->mtx);
815 
816  /* Delete the USB PCWD device */
817  usb_pcwd_delete(usb_pcwd);
818 
819  cards_found--;
820 
821  mutex_unlock(&disconnect_mutex);
822 
823  pr_info("USB PC Watchdog disconnected\n");
824 }
825 
826 module_usb_driver(usb_pcwd_driver);