Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  Berkshire USB-PC Watchdog Card Driver
0004  *
0005  *  (c) Copyright 2004-2007 Wim Van Sebroeck <wim@iguana.be>.
0006  *
0007  *  Based on source code of the following authors:
0008  *    Ken Hollis <kenji@bitgate.com>,
0009  *    Alan Cox <alan@lxorguk.ukuu.org.uk>,
0010  *    Matt Domsch <Matt_Domsch@dell.com>,
0011  *    Rob Radez <rob@osinvestor.com>,
0012  *    Greg Kroah-Hartman <greg@kroah.com>
0013  *
0014  *  Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
0015  *  provide warranty for any of this software. This material is
0016  *  provided "AS-IS" and at no charge.
0017  *
0018  *  Thanks also to Simon Machell at Berkshire Products Inc. for
0019  *  providing the test hardware. More info is available at
0020  *  http://www.berkprod.com/ or http://www.pcwatchdog.com/
0021  */
0022 
0023 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0024 
0025 #include <linux/module.h>   /* For module specific items */
0026 #include <linux/moduleparam.h>  /* For new moduleparam's */
0027 #include <linux/types.h>    /* For standard types (like size_t) */
0028 #include <linux/errno.h>    /* For the -ENODEV/... values */
0029 #include <linux/kernel.h>   /* For printk/panic/... */
0030 #include <linux/delay.h>    /* For mdelay function */
0031 #include <linux/miscdevice.h>   /* For struct miscdevice */
0032 #include <linux/watchdog.h> /* For the watchdog specific items */
0033 #include <linux/notifier.h> /* For notifier support */
0034 #include <linux/reboot.h>   /* For reboot_notifier stuff */
0035 #include <linux/init.h>     /* For __init/__exit/... */
0036 #include <linux/fs.h>       /* For file operations */
0037 #include <linux/usb.h>      /* For USB functions */
0038 #include <linux/slab.h>     /* For kmalloc, ... */
0039 #include <linux/mutex.h>    /* For mutex locking */
0040 #include <linux/hid.h>      /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
0041 #include <linux/uaccess.h>  /* For copy_to_user/put_user/... */
0042 
0043 
0044 /* Module and Version Information */
0045 #define DRIVER_VERSION "1.02"
0046 #define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
0047 #define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
0048 #define DRIVER_NAME "pcwd_usb"
0049 
0050 MODULE_AUTHOR(DRIVER_AUTHOR);
0051 MODULE_DESCRIPTION(DRIVER_DESC);
0052 MODULE_LICENSE("GPL");
0053 
0054 #define WATCHDOG_HEARTBEAT 0    /* default heartbeat =
0055                         delay-time from dip-switches */
0056 static int heartbeat = WATCHDOG_HEARTBEAT;
0057 module_param(heartbeat, int, 0);
0058 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
0059     "(0<heartbeat<65536 or 0=delay-time from dip-switches, default="
0060                 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
0061 
0062 static bool nowayout = WATCHDOG_NOWAYOUT;
0063 module_param(nowayout, bool, 0);
0064 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
0065                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0066 
0067 /* The vendor and product id's for the USB-PC Watchdog card */
0068 #define USB_PCWD_VENDOR_ID  0x0c98
0069 #define USB_PCWD_PRODUCT_ID 0x1140
0070 
0071 /* table of devices that work with this driver */
0072 static const struct usb_device_id usb_pcwd_table[] = {
0073     { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) },
0074     { }                 /* Terminating entry */
0075 };
0076 MODULE_DEVICE_TABLE(usb, usb_pcwd_table);
0077 
0078 /* according to documentation max. time to process a command for the USB
0079  * watchdog card is 100 or 200 ms, so we give it 250 ms to do it's job */
0080 #define USB_COMMAND_TIMEOUT 250
0081 
0082 /* Watchdog's internal commands */
0083 #define CMD_READ_TEMP           0x02    /* Read Temperature;
0084                             Re-trigger Watchdog */
0085 #define CMD_TRIGGER         CMD_READ_TEMP
0086 #define CMD_GET_STATUS          0x04    /* Get Status Information */
0087 #define CMD_GET_FIRMWARE_VERSION    0x08    /* Get Firmware Version */
0088 #define CMD_GET_DIP_SWITCH_SETTINGS 0x0c    /* Get Dip Switch Settings */
0089 #define CMD_READ_WATCHDOG_TIMEOUT   0x18    /* Read Current Watchdog Time */
0090 #define CMD_WRITE_WATCHDOG_TIMEOUT  0x19    /* Write Current WatchdogTime */
0091 #define CMD_ENABLE_WATCHDOG     0x30    /* Enable / Disable Watchdog */
0092 #define CMD_DISABLE_WATCHDOG        CMD_ENABLE_WATCHDOG
0093 
0094 /* Watchdog's Dip Switch heartbeat values */
0095 static const int heartbeat_tbl[] = {
0096     5,  /* OFF-OFF-OFF  =  5 Sec  */
0097     10, /* OFF-OFF-ON   = 10 Sec  */
0098     30, /* OFF-ON-OFF   = 30 Sec  */
0099     60, /* OFF-ON-ON    =  1 Min  */
0100     300,    /* ON-OFF-OFF   =  5 Min  */
0101     600,    /* ON-OFF-ON    = 10 Min  */
0102     1800,   /* ON-ON-OFF    = 30 Min  */
0103     3600,   /* ON-ON-ON =  1 hour */
0104 };
0105 
0106 /* We can only use 1 card due to the /dev/watchdog restriction */
0107 static int cards_found;
0108 
0109 /* some internal variables */
0110 static unsigned long is_active;
0111 static char expect_release;
0112 
0113 /* Structure to hold all of our device specific stuff */
0114 struct usb_pcwd_private {
0115     /* save off the usb device pointer */
0116     struct usb_device   *udev;
0117     /* the interface for this device */
0118     struct usb_interface    *interface;
0119 
0120     /* the interface number used for cmd's */
0121     unsigned int        interface_number;
0122 
0123     /* the buffer to intr data */
0124     unsigned char       *intr_buffer;
0125     /* the dma address for the intr buffer */
0126     dma_addr_t      intr_dma;
0127     /* the size of the intr buffer */
0128     size_t          intr_size;
0129     /* the urb used for the intr pipe */
0130     struct urb      *intr_urb;
0131 
0132     /* The command that is reported back */
0133     unsigned char       cmd_command;
0134     /* The data MSB that is reported back */
0135     unsigned char       cmd_data_msb;
0136     /* The data LSB that is reported back */
0137     unsigned char       cmd_data_lsb;
0138     /* true if we received a report after a command */
0139     atomic_t        cmd_received;
0140 
0141     /* Wether or not the device exists */
0142     int         exists;
0143     /* locks this structure */
0144     struct mutex        mtx;
0145 };
0146 static struct usb_pcwd_private *usb_pcwd_device;
0147 
0148 /* prevent races between open() and disconnect() */
0149 static DEFINE_MUTEX(disconnect_mutex);
0150 
0151 /* local function prototypes */
0152 static int usb_pcwd_probe(struct usb_interface *interface,
0153                         const struct usb_device_id *id);
0154 static void usb_pcwd_disconnect(struct usb_interface *interface);
0155 
0156 /* usb specific object needed to register this driver with the usb subsystem */
0157 static struct usb_driver usb_pcwd_driver = {
0158     .name =     DRIVER_NAME,
0159     .probe =    usb_pcwd_probe,
0160     .disconnect =   usb_pcwd_disconnect,
0161     .id_table = usb_pcwd_table,
0162 };
0163 
0164 
0165 static void usb_pcwd_intr_done(struct urb *urb)
0166 {
0167     struct usb_pcwd_private *usb_pcwd =
0168                 (struct usb_pcwd_private *)urb->context;
0169     unsigned char *data = usb_pcwd->intr_buffer;
0170     struct device *dev = &usb_pcwd->interface->dev;
0171     int retval;
0172 
0173     switch (urb->status) {
0174     case 0:         /* success */
0175         break;
0176     case -ECONNRESET:   /* unlink */
0177     case -ENOENT:
0178     case -ESHUTDOWN:
0179         /* this urb is terminated, clean up */
0180         dev_dbg(dev, "%s - urb shutting down with status: %d",
0181             __func__, urb->status);
0182         return;
0183     /* -EPIPE:  should clear the halt */
0184     default:        /* error */
0185         dev_dbg(dev, "%s - nonzero urb status received: %d",
0186             __func__, urb->status);
0187         goto resubmit;
0188     }
0189 
0190     dev_dbg(dev, "received following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
0191         data[0], data[1], data[2]);
0192 
0193     usb_pcwd->cmd_command  = data[0];
0194     usb_pcwd->cmd_data_msb = data[1];
0195     usb_pcwd->cmd_data_lsb = data[2];
0196 
0197     /* notify anyone waiting that the cmd has finished */
0198     atomic_set(&usb_pcwd->cmd_received, 1);
0199 
0200 resubmit:
0201     retval = usb_submit_urb(urb, GFP_ATOMIC);
0202     if (retval)
0203         pr_err("can't resubmit intr, usb_submit_urb failed with result %d\n",
0204                retval);
0205 }
0206 
0207 static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd,
0208         unsigned char cmd, unsigned char *msb, unsigned char *lsb)
0209 {
0210     int got_response, count;
0211     unsigned char *buf;
0212 
0213     /* We will not send any commands if the USB PCWD device does
0214      * not exist */
0215     if ((!usb_pcwd) || (!usb_pcwd->exists))
0216         return -1;
0217 
0218     buf = kmalloc(6, GFP_KERNEL);
0219     if (buf == NULL)
0220         return 0;
0221 
0222     /* The USB PC Watchdog uses a 6 byte report format.
0223      * The board currently uses only 3 of the six bytes of the report. */
0224     buf[0] = cmd;           /* Byte 0 = CMD */
0225     buf[1] = *msb;          /* Byte 1 = Data MSB */
0226     buf[2] = *lsb;          /* Byte 2 = Data LSB */
0227     buf[3] = buf[4] = buf[5] = 0;   /* All other bytes not used */
0228 
0229     dev_dbg(&usb_pcwd->interface->dev,
0230         "sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
0231         buf[0], buf[1], buf[2]);
0232 
0233     atomic_set(&usb_pcwd->cmd_received, 0);
0234 
0235     if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
0236             HID_REQ_SET_REPORT, HID_DT_REPORT,
0237             0x0200, usb_pcwd->interface_number, buf, 6,
0238             USB_COMMAND_TIMEOUT) != 6) {
0239         dev_dbg(&usb_pcwd->interface->dev,
0240             "usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n",
0241             cmd, *msb, *lsb);
0242     }
0243     /* wait till the usb card processed the command,
0244      * with a max. timeout of USB_COMMAND_TIMEOUT */
0245     got_response = 0;
0246     for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response);
0247                                 count++) {
0248         mdelay(1);
0249         if (atomic_read(&usb_pcwd->cmd_received))
0250             got_response = 1;
0251     }
0252 
0253     if ((got_response) && (cmd == usb_pcwd->cmd_command)) {
0254         /* read back response */
0255         *msb = usb_pcwd->cmd_data_msb;
0256         *lsb = usb_pcwd->cmd_data_lsb;
0257     }
0258 
0259     kfree(buf);
0260 
0261     return got_response;
0262 }
0263 
0264 static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd)
0265 {
0266     unsigned char msb = 0x00;
0267     unsigned char lsb = 0x00;
0268     int retval;
0269 
0270     /* Enable Watchdog */
0271     retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG,
0272                                 &msb, &lsb);
0273 
0274     if ((retval == 0) || (lsb == 0)) {
0275         pr_err("Card did not acknowledge enable attempt\n");
0276         return -1;
0277     }
0278 
0279     return 0;
0280 }
0281 
0282 static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd)
0283 {
0284     unsigned char msb = 0xA5;
0285     unsigned char lsb = 0xC3;
0286     int retval;
0287 
0288     /* Disable Watchdog */
0289     retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG,
0290                                 &msb, &lsb);
0291 
0292     if ((retval == 0) || (lsb != 0)) {
0293         pr_err("Card did not acknowledge disable attempt\n");
0294         return -1;
0295     }
0296 
0297     return 0;
0298 }
0299 
0300 static int usb_pcwd_keepalive(struct usb_pcwd_private *usb_pcwd)
0301 {
0302     unsigned char dummy;
0303 
0304     /* Re-trigger Watchdog */
0305     usb_pcwd_send_command(usb_pcwd, CMD_TRIGGER, &dummy, &dummy);
0306 
0307     return 0;
0308 }
0309 
0310 static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t)
0311 {
0312     unsigned char msb = t / 256;
0313     unsigned char lsb = t % 256;
0314 
0315     if ((t < 0x0001) || (t > 0xFFFF))
0316         return -EINVAL;
0317 
0318     /* Write new heartbeat to watchdog */
0319     usb_pcwd_send_command(usb_pcwd, CMD_WRITE_WATCHDOG_TIMEOUT, &msb, &lsb);
0320 
0321     heartbeat = t;
0322     return 0;
0323 }
0324 
0325 static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd,
0326                             int *temperature)
0327 {
0328     unsigned char msb, lsb;
0329 
0330     usb_pcwd_send_command(usb_pcwd, CMD_READ_TEMP, &msb, &lsb);
0331 
0332     /*
0333      * Convert celsius to fahrenheit, since this was
0334      * the decided 'standard' for this return value.
0335      */
0336     *temperature = (lsb * 9 / 5) + 32;
0337 
0338     return 0;
0339 }
0340 
0341 static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd,
0342                                 int *time_left)
0343 {
0344     unsigned char msb, lsb;
0345 
0346     /* Read the time that's left before rebooting */
0347     /* Note: if the board is not yet armed then we will read 0xFFFF */
0348     usb_pcwd_send_command(usb_pcwd, CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);
0349 
0350     *time_left = (msb << 8) + lsb;
0351 
0352     return 0;
0353 }
0354 
0355 /*
0356  *  /dev/watchdog handling
0357  */
0358 
0359 static ssize_t usb_pcwd_write(struct file *file, const char __user *data,
0360                         size_t len, loff_t *ppos)
0361 {
0362     /* See if we got the magic character 'V' and reload the timer */
0363     if (len) {
0364         if (!nowayout) {
0365             size_t i;
0366 
0367             /* note: just in case someone wrote the magic character
0368              * five months ago... */
0369             expect_release = 0;
0370 
0371             /* scan to see whether or not we got the
0372              * magic character */
0373             for (i = 0; i != len; i++) {
0374                 char c;
0375                 if (get_user(c, data + i))
0376                     return -EFAULT;
0377                 if (c == 'V')
0378                     expect_release = 42;
0379             }
0380         }
0381 
0382         /* someone wrote to us, we should reload the timer */
0383         usb_pcwd_keepalive(usb_pcwd_device);
0384     }
0385     return len;
0386 }
0387 
0388 static long usb_pcwd_ioctl(struct file *file, unsigned int cmd,
0389                         unsigned long arg)
0390 {
0391     void __user *argp = (void __user *)arg;
0392     int __user *p = argp;
0393     static const struct watchdog_info ident = {
0394         .options =      WDIOF_KEEPALIVEPING |
0395                     WDIOF_SETTIMEOUT |
0396                     WDIOF_MAGICCLOSE,
0397         .firmware_version = 1,
0398         .identity =     DRIVER_NAME,
0399     };
0400 
0401     switch (cmd) {
0402     case WDIOC_GETSUPPORT:
0403         return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
0404 
0405     case WDIOC_GETSTATUS:
0406     case WDIOC_GETBOOTSTATUS:
0407         return put_user(0, p);
0408 
0409     case WDIOC_GETTEMP:
0410     {
0411         int temperature;
0412 
0413         if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
0414             return -EFAULT;
0415 
0416         return put_user(temperature, p);
0417     }
0418 
0419     case WDIOC_SETOPTIONS:
0420     {
0421         int new_options, retval = -EINVAL;
0422 
0423         if (get_user(new_options, p))
0424             return -EFAULT;
0425 
0426         if (new_options & WDIOS_DISABLECARD) {
0427             usb_pcwd_stop(usb_pcwd_device);
0428             retval = 0;
0429         }
0430 
0431         if (new_options & WDIOS_ENABLECARD) {
0432             usb_pcwd_start(usb_pcwd_device);
0433             retval = 0;
0434         }
0435 
0436         return retval;
0437     }
0438 
0439     case WDIOC_KEEPALIVE:
0440         usb_pcwd_keepalive(usb_pcwd_device);
0441         return 0;
0442 
0443     case WDIOC_SETTIMEOUT:
0444     {
0445         int new_heartbeat;
0446 
0447         if (get_user(new_heartbeat, p))
0448             return -EFAULT;
0449 
0450         if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
0451             return -EINVAL;
0452 
0453         usb_pcwd_keepalive(usb_pcwd_device);
0454     }
0455         fallthrough;
0456 
0457     case WDIOC_GETTIMEOUT:
0458         return put_user(heartbeat, p);
0459 
0460     case WDIOC_GETTIMELEFT:
0461     {
0462         int time_left;
0463 
0464         if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
0465             return -EFAULT;
0466 
0467         return put_user(time_left, p);
0468     }
0469 
0470     default:
0471         return -ENOTTY;
0472     }
0473 }
0474 
0475 static int usb_pcwd_open(struct inode *inode, struct file *file)
0476 {
0477     /* /dev/watchdog can only be opened once */
0478     if (test_and_set_bit(0, &is_active))
0479         return -EBUSY;
0480 
0481     /* Activate */
0482     usb_pcwd_start(usb_pcwd_device);
0483     usb_pcwd_keepalive(usb_pcwd_device);
0484     return stream_open(inode, file);
0485 }
0486 
0487 static int usb_pcwd_release(struct inode *inode, struct file *file)
0488 {
0489     /*
0490      *      Shut off the timer.
0491      */
0492     if (expect_release == 42) {
0493         usb_pcwd_stop(usb_pcwd_device);
0494     } else {
0495         pr_crit("Unexpected close, not stopping watchdog!\n");
0496         usb_pcwd_keepalive(usb_pcwd_device);
0497     }
0498     expect_release = 0;
0499     clear_bit(0, &is_active);
0500     return 0;
0501 }
0502 
0503 /*
0504  *  /dev/temperature handling
0505  */
0506 
0507 static ssize_t usb_pcwd_temperature_read(struct file *file, char __user *data,
0508                 size_t len, loff_t *ppos)
0509 {
0510     int temperature;
0511 
0512     if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
0513         return -EFAULT;
0514 
0515     if (copy_to_user(data, &temperature, 1))
0516         return -EFAULT;
0517 
0518     return 1;
0519 }
0520 
0521 static int usb_pcwd_temperature_open(struct inode *inode, struct file *file)
0522 {
0523     return stream_open(inode, file);
0524 }
0525 
0526 static int usb_pcwd_temperature_release(struct inode *inode, struct file *file)
0527 {
0528     return 0;
0529 }
0530 
0531 /*
0532  *  Notify system
0533  */
0534 
0535 static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code,
0536                                 void *unused)
0537 {
0538     if (code == SYS_DOWN || code == SYS_HALT)
0539         usb_pcwd_stop(usb_pcwd_device); /* Turn the WDT off */
0540 
0541     return NOTIFY_DONE;
0542 }
0543 
0544 /*
0545  *  Kernel Interfaces
0546  */
0547 
0548 static const struct file_operations usb_pcwd_fops = {
0549     .owner =    THIS_MODULE,
0550     .llseek =   no_llseek,
0551     .write =    usb_pcwd_write,
0552     .unlocked_ioctl = usb_pcwd_ioctl,
0553     .compat_ioctl = compat_ptr_ioctl,
0554     .open =     usb_pcwd_open,
0555     .release =  usb_pcwd_release,
0556 };
0557 
0558 static struct miscdevice usb_pcwd_miscdev = {
0559     .minor =    WATCHDOG_MINOR,
0560     .name =     "watchdog",
0561     .fops =     &usb_pcwd_fops,
0562 };
0563 
0564 static const struct file_operations usb_pcwd_temperature_fops = {
0565     .owner =    THIS_MODULE,
0566     .llseek =   no_llseek,
0567     .read =     usb_pcwd_temperature_read,
0568     .open =     usb_pcwd_temperature_open,
0569     .release =  usb_pcwd_temperature_release,
0570 };
0571 
0572 static struct miscdevice usb_pcwd_temperature_miscdev = {
0573     .minor =    TEMP_MINOR,
0574     .name =     "temperature",
0575     .fops =     &usb_pcwd_temperature_fops,
0576 };
0577 
0578 static struct notifier_block usb_pcwd_notifier = {
0579     .notifier_call =    usb_pcwd_notify_sys,
0580 };
0581 
0582 /**
0583  *  usb_pcwd_delete
0584  */
0585 static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd)
0586 {
0587     usb_free_urb(usb_pcwd->intr_urb);
0588     usb_free_coherent(usb_pcwd->udev, usb_pcwd->intr_size,
0589               usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
0590     kfree(usb_pcwd);
0591 }
0592 
0593 /**
0594  *  usb_pcwd_probe
0595  *
0596  *  Called by the usb core when a new device is connected that it thinks
0597  *  this driver might be interested in.
0598  */
0599 static int usb_pcwd_probe(struct usb_interface *interface,
0600                         const struct usb_device_id *id)
0601 {
0602     struct usb_device *udev = interface_to_usbdev(interface);
0603     struct usb_host_interface *iface_desc;
0604     struct usb_endpoint_descriptor *endpoint;
0605     struct usb_pcwd_private *usb_pcwd = NULL;
0606     int pipe;
0607     int retval = -ENOMEM;
0608     int got_fw_rev;
0609     unsigned char fw_rev_major, fw_rev_minor;
0610     char fw_ver_str[20];
0611     unsigned char option_switches, dummy;
0612 
0613     cards_found++;
0614     if (cards_found > 1) {
0615         pr_err("This driver only supports 1 device\n");
0616         return -ENODEV;
0617     }
0618 
0619     /* get the active interface descriptor */
0620     iface_desc = interface->cur_altsetting;
0621 
0622     /* check out that we have a HID device */
0623     if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
0624         pr_err("The device isn't a Human Interface Device\n");
0625         return -ENODEV;
0626     }
0627 
0628     if (iface_desc->desc.bNumEndpoints < 1)
0629         return -ENODEV;
0630 
0631     /* check out the endpoint: it has to be Interrupt & IN */
0632     endpoint = &iface_desc->endpoint[0].desc;
0633 
0634     if (!usb_endpoint_is_int_in(endpoint)) {
0635         /* we didn't find a Interrupt endpoint with direction IN */
0636         pr_err("Couldn't find an INTR & IN endpoint\n");
0637         return -ENODEV;
0638     }
0639 
0640     /* get a handle to the interrupt data pipe */
0641     pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
0642 
0643     /* allocate memory for our device and initialize it */
0644     usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
0645     if (usb_pcwd == NULL)
0646         goto error;
0647 
0648     usb_pcwd_device = usb_pcwd;
0649 
0650     mutex_init(&usb_pcwd->mtx);
0651     usb_pcwd->udev = udev;
0652     usb_pcwd->interface = interface;
0653     usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
0654     usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ?
0655                 le16_to_cpu(endpoint->wMaxPacketSize) : 8);
0656 
0657     /* set up the memory buffer's */
0658     usb_pcwd->intr_buffer = usb_alloc_coherent(udev, usb_pcwd->intr_size,
0659                     GFP_KERNEL, &usb_pcwd->intr_dma);
0660     if (!usb_pcwd->intr_buffer) {
0661         pr_err("Out of memory\n");
0662         goto error;
0663     }
0664 
0665     /* allocate the urb's */
0666     usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
0667     if (!usb_pcwd->intr_urb)
0668         goto error;
0669 
0670     /* initialise the intr urb's */
0671     usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe,
0672             usb_pcwd->intr_buffer, usb_pcwd->intr_size,
0673             usb_pcwd_intr_done, usb_pcwd, endpoint->bInterval);
0674     usb_pcwd->intr_urb->transfer_dma = usb_pcwd->intr_dma;
0675     usb_pcwd->intr_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
0676 
0677     /* register our interrupt URB with the USB system */
0678     if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
0679         pr_err("Problem registering interrupt URB\n");
0680         retval = -EIO; /* failure */
0681         goto error;
0682     }
0683 
0684     /* The device exists and can be communicated with */
0685     usb_pcwd->exists = 1;
0686 
0687     /* disable card */
0688     usb_pcwd_stop(usb_pcwd);
0689 
0690     /* Get the Firmware Version */
0691     got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION,
0692                         &fw_rev_major, &fw_rev_minor);
0693     if (got_fw_rev)
0694         sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
0695     else
0696         sprintf(fw_ver_str, "<card no answer>");
0697 
0698     pr_info("Found card (Firmware: %s) with temp option\n", fw_ver_str);
0699 
0700     /* Get switch settings */
0701     usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy,
0702                             &option_switches);
0703 
0704     pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
0705         option_switches,
0706         ((option_switches & 0x10) ? "ON" : "OFF"),
0707         ((option_switches & 0x08) ? "ON" : "OFF"));
0708 
0709     /* If heartbeat = 0 then we use the heartbeat from the dip-switches */
0710     if (heartbeat == 0)
0711         heartbeat = heartbeat_tbl[(option_switches & 0x07)];
0712 
0713     /* Check that the heartbeat value is within it's range ;
0714      * if not reset to the default */
0715     if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
0716         usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
0717         pr_info("heartbeat value must be 0<heartbeat<65536, using %d\n",
0718             WATCHDOG_HEARTBEAT);
0719     }
0720 
0721     retval = register_reboot_notifier(&usb_pcwd_notifier);
0722     if (retval != 0) {
0723         pr_err("cannot register reboot notifier (err=%d)\n", retval);
0724         goto error;
0725     }
0726 
0727     retval = misc_register(&usb_pcwd_temperature_miscdev);
0728     if (retval != 0) {
0729         pr_err("cannot register miscdev on minor=%d (err=%d)\n",
0730                TEMP_MINOR, retval);
0731         goto err_out_unregister_reboot;
0732     }
0733 
0734     retval = misc_register(&usb_pcwd_miscdev);
0735     if (retval != 0) {
0736         pr_err("cannot register miscdev on minor=%d (err=%d)\n",
0737                WATCHDOG_MINOR, retval);
0738         goto err_out_misc_deregister;
0739     }
0740 
0741     /* we can register the device now, as it is ready */
0742     usb_set_intfdata(interface, usb_pcwd);
0743 
0744     pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
0745         heartbeat, nowayout);
0746 
0747     return 0;
0748 
0749 err_out_misc_deregister:
0750     misc_deregister(&usb_pcwd_temperature_miscdev);
0751 err_out_unregister_reboot:
0752     unregister_reboot_notifier(&usb_pcwd_notifier);
0753 error:
0754     if (usb_pcwd)
0755         usb_pcwd_delete(usb_pcwd);
0756     usb_pcwd_device = NULL;
0757     return retval;
0758 }
0759 
0760 
0761 /**
0762  *  usb_pcwd_disconnect
0763  *
0764  *  Called by the usb core when the device is removed from the system.
0765  *
0766  *  This routine guarantees that the driver will not submit any more urbs
0767  *  by clearing dev->udev.
0768  */
0769 static void usb_pcwd_disconnect(struct usb_interface *interface)
0770 {
0771     struct usb_pcwd_private *usb_pcwd;
0772 
0773     /* prevent races with open() */
0774     mutex_lock(&disconnect_mutex);
0775 
0776     usb_pcwd = usb_get_intfdata(interface);
0777     usb_set_intfdata(interface, NULL);
0778 
0779     mutex_lock(&usb_pcwd->mtx);
0780 
0781     /* Stop the timer before we leave */
0782     if (!nowayout)
0783         usb_pcwd_stop(usb_pcwd);
0784 
0785     /* We should now stop communicating with the USB PCWD device */
0786     usb_pcwd->exists = 0;
0787 
0788     /* Deregister */
0789     misc_deregister(&usb_pcwd_miscdev);
0790     misc_deregister(&usb_pcwd_temperature_miscdev);
0791     unregister_reboot_notifier(&usb_pcwd_notifier);
0792 
0793     mutex_unlock(&usb_pcwd->mtx);
0794 
0795     /* Delete the USB PCWD device */
0796     usb_pcwd_delete(usb_pcwd);
0797 
0798     cards_found--;
0799 
0800     mutex_unlock(&disconnect_mutex);
0801 
0802     pr_info("USB PC Watchdog disconnected\n");
0803 }
0804 
0805 module_usb_driver(usb_pcwd_driver);