* http://www.berkprod.com/ or http://www.pcwatchdog.com/
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
#ifdef CONFIG_USB_DEBUG
/* Module and Version Information */
-#define DRIVER_VERSION "1.00"
-#define DRIVER_DATE "12 Jun 2004"
+#define DRIVER_VERSION "1.01"
+#define DRIVER_DATE "15 Mar 2005"
#define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
#define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
#define DRIVER_LICENSE "GPL"
module_param(heartbeat, int, 0);
MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-static int nowayout = 1;
-#else
-static int nowayout = 0;
-#endif
-
+static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
#define CMD_ENABLE_WATCHDOG 0x30 /* Enable / Disable Watchdog */
#define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG
-/* Some defines that I like to be somewhere else like include/linux/usb_hid.h */
-#define HID_REQ_SET_REPORT 0x09
-#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
-
/* We can only use 1 card due to the /dev/watchdog restriction */
static int cards_found;
static struct usb_pcwd_private *usb_pcwd_device;
/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX (disconnect_sem);
+static DEFINE_MUTEX(disconnect_mutex);
/* local function prototypes */
static int usb_pcwd_probe (struct usb_interface *interface, const struct usb_device_id *id);
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver usb_pcwd_driver = {
- .owner = THIS_MODULE,
.name = DRIVER_NAME,
.probe = usb_pcwd_probe,
.disconnect = usb_pcwd_disconnect,
};
-static void usb_pcwd_intr_done(struct urb *urb, struct pt_regs *regs)
+static void usb_pcwd_intr_done(struct urb *urb)
{
struct usb_pcwd_private *usb_pcwd = (struct usb_pcwd_private *)urb->context;
unsigned char *data = usb_pcwd->intr_buffer;
if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
HID_REQ_SET_REPORT, HID_DT_REPORT,
0x0200, usb_pcwd->interface_number, buf, sizeof(buf),
- HZ) != sizeof(buf)) {
+ USB_COMMAND_TIMEOUT) != sizeof(buf)) {
dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb);
}
/* wait till the usb card processed the command,
return 0;
}
+static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_left)
+{
+ unsigned char msb, lsb;
+
+ /* Read the time that's left before rebooting */
+ /* Note: if the board is not yet armed then we will read 0xFFFF */
+ usb_pcwd_send_command(usb_pcwd, CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb);
+
+ *time_left = (msb << 8) + lsb;
+
+ return 0;
+}
+
/*
* /dev/watchdog handling
*/
case WDIOC_GETTIMEOUT:
return put_user(heartbeat, p);
+ case WDIOC_GETTIMELEFT:
+ {
+ int time_left;
+
+ if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left))
+ return -EFAULT;
+
+ return put_user(time_left, p);
+ }
+
default:
- return -ENOIOCTLCMD;
+ return -ENOTTY;
}
}
* Kernel Interfaces
*/
-static struct file_operations usb_pcwd_fops = {
+static const struct file_operations usb_pcwd_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = usb_pcwd_write,
.fops = &usb_pcwd_fops,
};
-static struct file_operations usb_pcwd_temperature_fops = {
+static const struct file_operations usb_pcwd_temperature_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = usb_pcwd_temperature_read,
*/
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);
+ 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);
char fw_ver_str[20];
unsigned char option_switches, dummy;
- /* See if the device offered us matches what we can accept */
- if ((udev->descriptor.idVendor != USB_PCWD_VENDOR_ID) ||
- (udev->descriptor.idProduct != USB_PCWD_PRODUCT_ID)) {
- return -ENODEV;
- }
-
cards_found++;
if (cards_found > 1) {
printk(KERN_ERR PFX "This driver only supports 1 device\n");
usb_pcwd->udev = udev;
usb_pcwd->interface = interface;
usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
- usb_pcwd->intr_size = (endpoint->wMaxPacketSize > 8 ? endpoint->wMaxPacketSize : 8);
+ 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))) {
+ if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma))) {
printk(KERN_ERR PFX "Out of memory\n");
goto error;
}
err_out_unregister_reboot:
unregister_reboot_notifier(&usb_pcwd_notifier);
error:
- usb_pcwd_delete (usb_pcwd);
+ if (usb_pcwd)
+ usb_pcwd_delete(usb_pcwd);
usb_pcwd_device = NULL;
return retval;
}
struct usb_pcwd_private *usb_pcwd;
/* prevent races with open() */
- down (&disconnect_sem);
+ mutex_lock(&disconnect_mutex);
usb_pcwd = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
cards_found--;
- up (&disconnect_sem);
+ mutex_unlock(&disconnect_mutex);
printk(KERN_INFO PFX "USB PC Watchdog disconnected\n");
}