diff options
Diffstat (limited to 'drivers/watchdog/pcwd_usb.c')
-rw-r--r-- | drivers/watchdog/pcwd_usb.c | 175 |
1 files changed, 109 insertions, 66 deletions
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index afb089695da8..052fe451851f 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c | |||
@@ -51,12 +51,11 @@ | |||
51 | 51 | ||
52 | /* Use our own dbg macro */ | 52 | /* Use our own dbg macro */ |
53 | #undef dbg | 53 | #undef dbg |
54 | #define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG PFX format "\n" , ## arg); } while (0) | 54 | #define dbg(format, arg...) \ |
55 | 55 | do { if (debug) printk(KERN_DEBUG PFX format "\n" , ## arg); } while (0) | |
56 | 56 | ||
57 | /* Module and Version Information */ | 57 | /* Module and Version Information */ |
58 | #define DRIVER_VERSION "1.02" | 58 | #define DRIVER_VERSION "1.02" |
59 | #define DRIVER_DATE "21 Jan 2007" | ||
60 | #define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>" | 59 | #define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>" |
61 | #define DRIVER_DESC "Berkshire USB-PC Watchdog driver" | 60 | #define DRIVER_DESC "Berkshire USB-PC Watchdog driver" |
62 | #define DRIVER_LICENSE "GPL" | 61 | #define DRIVER_LICENSE "GPL" |
@@ -73,14 +72,18 @@ MODULE_ALIAS_MISCDEV(TEMP_MINOR); | |||
73 | module_param(debug, int, 0); | 72 | module_param(debug, int, 0); |
74 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 73 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
75 | 74 | ||
76 | #define WATCHDOG_HEARTBEAT 0 /* default heartbeat = delay-time from dip-switches */ | 75 | #define WATCHDOG_HEARTBEAT 0 /* default heartbeat = |
76 | delay-time from dip-switches */ | ||
77 | static int heartbeat = WATCHDOG_HEARTBEAT; | 77 | static int heartbeat = WATCHDOG_HEARTBEAT; |
78 | module_param(heartbeat, int, 0); | 78 | module_param(heartbeat, int, 0); |
79 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 79 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. " |
80 | "(0<heartbeat<65536 or 0=delay-time from dip-switches, default=" | ||
81 | __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | ||
80 | 82 | ||
81 | static int nowayout = WATCHDOG_NOWAYOUT; | 83 | static int nowayout = WATCHDOG_NOWAYOUT; |
82 | module_param(nowayout, int, 0); | 84 | module_param(nowayout, int, 0); |
83 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 85 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
86 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
84 | 87 | ||
85 | /* The vendor and product id's for the USB-PC Watchdog card */ | 88 | /* The vendor and product id's for the USB-PC Watchdog card */ |
86 | #define USB_PCWD_VENDOR_ID 0x0c98 | 89 | #define USB_PCWD_VENDOR_ID 0x0c98 |
@@ -91,20 +94,21 @@ static struct usb_device_id usb_pcwd_table[] = { | |||
91 | { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) }, | 94 | { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) }, |
92 | { } /* Terminating entry */ | 95 | { } /* Terminating entry */ |
93 | }; | 96 | }; |
94 | MODULE_DEVICE_TABLE (usb, usb_pcwd_table); | 97 | MODULE_DEVICE_TABLE(usb, usb_pcwd_table); |
95 | 98 | ||
96 | /* according to documentation max. time to process a command for the USB | 99 | /* according to documentation max. time to process a command for the USB |
97 | * watchdog card is 100 or 200 ms, so we give it 250 ms to do it's job */ | 100 | * watchdog card is 100 or 200 ms, so we give it 250 ms to do it's job */ |
98 | #define USB_COMMAND_TIMEOUT 250 | 101 | #define USB_COMMAND_TIMEOUT 250 |
99 | 102 | ||
100 | /* Watchdog's internal commands */ | 103 | /* Watchdog's internal commands */ |
101 | #define CMD_READ_TEMP 0x02 /* Read Temperature; Re-trigger Watchdog */ | 104 | #define CMD_READ_TEMP 0x02 /* Read Temperature; |
105 | Re-trigger Watchdog */ | ||
102 | #define CMD_TRIGGER CMD_READ_TEMP | 106 | #define CMD_TRIGGER CMD_READ_TEMP |
103 | #define CMD_GET_STATUS 0x04 /* Get Status Information */ | 107 | #define CMD_GET_STATUS 0x04 /* Get Status Information */ |
104 | #define CMD_GET_FIRMWARE_VERSION 0x08 /* Get Firmware Version */ | 108 | #define CMD_GET_FIRMWARE_VERSION 0x08 /* Get Firmware Version */ |
105 | #define CMD_GET_DIP_SWITCH_SETTINGS 0x0c /* Get Dip Switch Settings */ | 109 | #define CMD_GET_DIP_SWITCH_SETTINGS 0x0c /* Get Dip Switch Settings */ |
106 | #define CMD_READ_WATCHDOG_TIMEOUT 0x18 /* Read Current Watchdog Time */ | 110 | #define CMD_READ_WATCHDOG_TIMEOUT 0x18 /* Read Current Watchdog Time */ |
107 | #define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 /* Write Current Watchdog Time */ | 111 | #define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 /* Write Current WatchdogTime */ |
108 | #define CMD_ENABLE_WATCHDOG 0x30 /* Enable / Disable Watchdog */ | 112 | #define CMD_ENABLE_WATCHDOG 0x30 /* Enable / Disable Watchdog */ |
109 | #define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG | 113 | #define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG |
110 | 114 | ||
@@ -129,23 +133,36 @@ static char expect_release; | |||
129 | 133 | ||
130 | /* Structure to hold all of our device specific stuff */ | 134 | /* Structure to hold all of our device specific stuff */ |
131 | struct usb_pcwd_private { | 135 | struct usb_pcwd_private { |
132 | struct usb_device *udev; /* save off the usb device pointer */ | 136 | /* save off the usb device pointer */ |
133 | struct usb_interface *interface; /* the interface for this device */ | 137 | struct usb_device *udev; |
134 | 138 | /* the interface for this device */ | |
135 | unsigned int interface_number; /* the interface number used for cmd's */ | 139 | struct usb_interface *interface; |
136 | 140 | ||
137 | unsigned char *intr_buffer; /* the buffer to intr data */ | 141 | /* the interface number used for cmd's */ |
138 | dma_addr_t intr_dma; /* the dma address for the intr buffer */ | 142 | unsigned int interface_number; |
139 | size_t intr_size; /* the size of the intr buffer */ | 143 | |
140 | struct urb *intr_urb; /* the urb used for the intr pipe */ | 144 | /* the buffer to intr data */ |
141 | 145 | unsigned char *intr_buffer; | |
142 | unsigned char cmd_command; /* The command that is reported back */ | 146 | /* the dma address for the intr buffer */ |
143 | unsigned char cmd_data_msb; /* The data MSB that is reported back */ | 147 | dma_addr_t intr_dma; |
144 | unsigned char cmd_data_lsb; /* The data LSB that is reported back */ | 148 | /* the size of the intr buffer */ |
145 | atomic_t cmd_received; /* true if we received a report after a command */ | 149 | size_t intr_size; |
146 | 150 | /* the urb used for the intr pipe */ | |
147 | int exists; /* Wether or not the device exists */ | 151 | struct urb *intr_urb; |
148 | struct mutex mtx; /* locks this structure */ | 152 | |
153 | /* The command that is reported back */ | ||
154 | unsigned char cmd_command; | ||
155 | /* The data MSB that is reported back */ | ||
156 | unsigned char cmd_data_msb; | ||
157 | /* The data LSB that is reported back */ | ||
158 | unsigned char cmd_data_lsb; | ||
159 | /* true if we received a report after a command */ | ||
160 | atomic_t cmd_received; | ||
161 | |||
162 | /* Wether or not the device exists */ | ||
163 | int exists; | ||
164 | /* locks this structure */ | ||
165 | struct mutex mtx; | ||
149 | }; | 166 | }; |
150 | static struct usb_pcwd_private *usb_pcwd_device; | 167 | static struct usb_pcwd_private *usb_pcwd_device; |
151 | 168 | ||
@@ -153,7 +170,8 @@ static struct usb_pcwd_private *usb_pcwd_device; | |||
153 | static DEFINE_MUTEX(disconnect_mutex); | 170 | static DEFINE_MUTEX(disconnect_mutex); |
154 | 171 | ||
155 | /* local function prototypes */ | 172 | /* local function prototypes */ |
156 | static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id); | 173 | static int usb_pcwd_probe(struct usb_interface *interface, |
174 | const struct usb_device_id *id); | ||
157 | static void usb_pcwd_disconnect(struct usb_interface *interface); | 175 | static void usb_pcwd_disconnect(struct usb_interface *interface); |
158 | 176 | ||
159 | /* usb specific object needed to register this driver with the usb subsystem */ | 177 | /* usb specific object needed to register this driver with the usb subsystem */ |
@@ -167,7 +185,8 @@ static struct usb_driver usb_pcwd_driver = { | |||
167 | 185 | ||
168 | static void usb_pcwd_intr_done(struct urb *urb) | 186 | static void usb_pcwd_intr_done(struct urb *urb) |
169 | { | 187 | { |
170 | struct usb_pcwd_private *usb_pcwd = (struct usb_pcwd_private *)urb->context; | 188 | struct usb_pcwd_private *usb_pcwd = |
189 | (struct usb_pcwd_private *)urb->context; | ||
171 | unsigned char *data = usb_pcwd->intr_buffer; | 190 | unsigned char *data = usb_pcwd->intr_buffer; |
172 | int retval; | 191 | int retval; |
173 | 192 | ||
@@ -178,11 +197,13 @@ static void usb_pcwd_intr_done(struct urb *urb) | |||
178 | case -ENOENT: | 197 | case -ENOENT: |
179 | case -ESHUTDOWN: | 198 | case -ESHUTDOWN: |
180 | /* this urb is terminated, clean up */ | 199 | /* this urb is terminated, clean up */ |
181 | dbg("%s - urb shutting down with status: %d", __func__, urb->status); | 200 | dbg("%s - urb shutting down with status: %d", __func__, |
201 | urb->status); | ||
182 | return; | 202 | return; |
183 | /* -EPIPE: should clear the halt */ | 203 | /* -EPIPE: should clear the halt */ |
184 | default: /* error */ | 204 | default: /* error */ |
185 | dbg("%s - nonzero urb status received: %d", __func__, urb->status); | 205 | dbg("%s - nonzero urb status received: %d", __func__, |
206 | urb->status); | ||
186 | goto resubmit; | 207 | goto resubmit; |
187 | } | 208 | } |
188 | 209 | ||
@@ -199,22 +220,23 @@ static void usb_pcwd_intr_done(struct urb *urb) | |||
199 | resubmit: | 220 | resubmit: |
200 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 221 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
201 | if (retval) | 222 | if (retval) |
202 | printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n", | 223 | printk(KERN_ERR PFX "can't resubmit intr, " |
203 | retval); | 224 | "usb_submit_urb failed with result %d\n", retval); |
204 | } | 225 | } |
205 | 226 | ||
206 | static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned char cmd, | 227 | static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, |
207 | unsigned char *msb, unsigned char *lsb) | 228 | unsigned char cmd, unsigned char *msb, unsigned char *lsb) |
208 | { | 229 | { |
209 | int got_response, count; | 230 | int got_response, count; |
210 | unsigned char buf[6]; | 231 | unsigned char buf[6]; |
211 | 232 | ||
212 | /* We will not send any commands if the USB PCWD device does not exist */ | 233 | /* We will not send any commands if the USB PCWD device does |
234 | * not exist */ | ||
213 | if ((!usb_pcwd) || (!usb_pcwd->exists)) | 235 | if ((!usb_pcwd) || (!usb_pcwd->exists)) |
214 | return -1; | 236 | return -1; |
215 | 237 | ||
216 | /* The USB PC Watchdog uses a 6 byte report format. The board currently uses | 238 | /* The USB PC Watchdog uses a 6 byte report format. |
217 | * only 3 of the six bytes of the report. */ | 239 | * The board currently uses only 3 of the six bytes of the report. */ |
218 | buf[0] = cmd; /* Byte 0 = CMD */ | 240 | buf[0] = cmd; /* Byte 0 = CMD */ |
219 | buf[1] = *msb; /* Byte 1 = Data MSB */ | 241 | buf[1] = *msb; /* Byte 1 = Data MSB */ |
220 | buf[2] = *lsb; /* Byte 2 = Data LSB */ | 242 | buf[2] = *lsb; /* Byte 2 = Data LSB */ |
@@ -229,12 +251,14 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha | |||
229 | HID_REQ_SET_REPORT, HID_DT_REPORT, | 251 | HID_REQ_SET_REPORT, HID_DT_REPORT, |
230 | 0x0200, usb_pcwd->interface_number, buf, sizeof(buf), | 252 | 0x0200, usb_pcwd->interface_number, buf, sizeof(buf), |
231 | USB_COMMAND_TIMEOUT) != sizeof(buf)) { | 253 | USB_COMMAND_TIMEOUT) != sizeof(buf)) { |
232 | dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb); | 254 | dbg("usb_pcwd_send_command: error in usb_control_msg for " |
255 | "cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb); | ||
233 | } | 256 | } |
234 | /* wait till the usb card processed the command, | 257 | /* wait till the usb card processed the command, |
235 | * with a max. timeout of USB_COMMAND_TIMEOUT */ | 258 | * with a max. timeout of USB_COMMAND_TIMEOUT */ |
236 | got_response = 0; | 259 | got_response = 0; |
237 | for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) { | 260 | for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); |
261 | count++) { | ||
238 | mdelay(1); | 262 | mdelay(1); |
239 | if (atomic_read(&usb_pcwd->cmd_received)) | 263 | if (atomic_read(&usb_pcwd->cmd_received)) |
240 | got_response = 1; | 264 | got_response = 1; |
@@ -256,10 +280,12 @@ static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd) | |||
256 | int retval; | 280 | int retval; |
257 | 281 | ||
258 | /* Enable Watchdog */ | 282 | /* Enable Watchdog */ |
259 | retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG, &msb, &lsb); | 283 | retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG, |
284 | &msb, &lsb); | ||
260 | 285 | ||
261 | if ((retval == 0) || (lsb == 0)) { | 286 | if ((retval == 0) || (lsb == 0)) { |
262 | printk(KERN_ERR PFX "Card did not acknowledge enable attempt\n"); | 287 | printk(KERN_ERR PFX |
288 | "Card did not acknowledge enable attempt\n"); | ||
263 | return -1; | 289 | return -1; |
264 | } | 290 | } |
265 | 291 | ||
@@ -273,10 +299,12 @@ static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd) | |||
273 | int retval; | 299 | int retval; |
274 | 300 | ||
275 | /* Disable Watchdog */ | 301 | /* Disable Watchdog */ |
276 | retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG, &msb, &lsb); | 302 | retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG, |
303 | &msb, &lsb); | ||
277 | 304 | ||
278 | if ((retval == 0) || (lsb != 0)) { | 305 | if ((retval == 0) || (lsb != 0)) { |
279 | printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); | 306 | printk(KERN_ERR PFX |
307 | "Card did not acknowledge disable attempt\n"); | ||
280 | return -1; | 308 | return -1; |
281 | } | 309 | } |
282 | 310 | ||
@@ -308,7 +336,8 @@ static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t) | |||
308 | return 0; | 336 | return 0; |
309 | } | 337 | } |
310 | 338 | ||
311 | static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temperature) | 339 | static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, |
340 | int *temperature) | ||
312 | { | 341 | { |
313 | unsigned char msb, lsb; | 342 | unsigned char msb, lsb; |
314 | 343 | ||
@@ -323,7 +352,8 @@ static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temp | |||
323 | return 0; | 352 | return 0; |
324 | } | 353 | } |
325 | 354 | ||
326 | static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_left) | 355 | static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, |
356 | int *time_left) | ||
327 | { | 357 | { |
328 | unsigned char msb, lsb; | 358 | unsigned char msb, lsb; |
329 | 359 | ||
@@ -341,7 +371,7 @@ static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_le | |||
341 | */ | 371 | */ |
342 | 372 | ||
343 | static ssize_t usb_pcwd_write(struct file *file, const char __user *data, | 373 | static ssize_t usb_pcwd_write(struct file *file, const char __user *data, |
344 | size_t len, loff_t *ppos) | 374 | size_t len, loff_t *ppos) |
345 | { | 375 | { |
346 | /* See if we got the magic character 'V' and reload the timer */ | 376 | /* See if we got the magic character 'V' and reload the timer */ |
347 | if (len) { | 377 | if (len) { |
@@ -352,7 +382,8 @@ static ssize_t usb_pcwd_write(struct file *file, const char __user *data, | |||
352 | * five months ago... */ | 382 | * five months ago... */ |
353 | expect_release = 0; | 383 | expect_release = 0; |
354 | 384 | ||
355 | /* scan to see whether or not we got the magic character */ | 385 | /* scan to see whether or not we got the |
386 | * magic character */ | ||
356 | for (i = 0; i != len; i++) { | 387 | for (i = 0; i != len; i++) { |
357 | char c; | 388 | char c; |
358 | if (get_user(c, data + i)) | 389 | if (get_user(c, data + i)) |
@@ -431,7 +462,7 @@ static long usb_pcwd_ioctl(struct file *file, unsigned int cmd, | |||
431 | return -EFAULT; | 462 | return -EFAULT; |
432 | 463 | ||
433 | if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) | 464 | if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) |
434 | return -EINVAL; | 465 | return -EINVAL; |
435 | 466 | ||
436 | usb_pcwd_keepalive(usb_pcwd_device); | 467 | usb_pcwd_keepalive(usb_pcwd_device); |
437 | /* Fall */ | 468 | /* Fall */ |
@@ -475,7 +506,8 @@ static int usb_pcwd_release(struct inode *inode, struct file *file) | |||
475 | if (expect_release == 42) { | 506 | if (expect_release == 42) { |
476 | usb_pcwd_stop(usb_pcwd_device); | 507 | usb_pcwd_stop(usb_pcwd_device); |
477 | } else { | 508 | } else { |
478 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 509 | printk(KERN_CRIT PFX |
510 | "Unexpected close, not stopping watchdog!\n"); | ||
479 | usb_pcwd_keepalive(usb_pcwd_device); | 511 | usb_pcwd_keepalive(usb_pcwd_device); |
480 | } | 512 | } |
481 | expect_release = 0; | 513 | expect_release = 0; |
@@ -515,7 +547,8 @@ static int usb_pcwd_temperature_release(struct inode *inode, struct file *file) | |||
515 | * Notify system | 547 | * Notify system |
516 | */ | 548 | */ |
517 | 549 | ||
518 | static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 550 | static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, |
551 | void *unused) | ||
519 | { | 552 | { |
520 | if (code == SYS_DOWN || code == SYS_HALT) | 553 | if (code == SYS_DOWN || code == SYS_HALT) |
521 | usb_pcwd_stop(usb_pcwd_device); /* Turn the WDT off */ | 554 | usb_pcwd_stop(usb_pcwd_device); /* Turn the WDT off */ |
@@ -578,7 +611,8 @@ static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd) | |||
578 | * Called by the usb core when a new device is connected that it thinks | 611 | * Called by the usb core when a new device is connected that it thinks |
579 | * this driver might be interested in. | 612 | * this driver might be interested in. |
580 | */ | 613 | */ |
581 | static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id) | 614 | static int usb_pcwd_probe(struct usb_interface *interface, |
615 | const struct usb_device_id *id) | ||
582 | { | 616 | { |
583 | struct usb_device *udev = interface_to_usbdev(interface); | 617 | struct usb_device *udev = interface_to_usbdev(interface); |
584 | struct usb_host_interface *iface_desc; | 618 | struct usb_host_interface *iface_desc; |
@@ -602,16 +636,15 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
602 | 636 | ||
603 | /* check out that we have a HID device */ | 637 | /* check out that we have a HID device */ |
604 | if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) { | 638 | if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) { |
605 | printk(KERN_ERR PFX "The device isn't a Human Interface Device\n"); | 639 | printk(KERN_ERR PFX |
640 | "The device isn't a Human Interface Device\n"); | ||
606 | return -ENODEV; | 641 | return -ENODEV; |
607 | } | 642 | } |
608 | 643 | ||
609 | /* check out the endpoint: it has to be Interrupt & IN */ | 644 | /* check out the endpoint: it has to be Interrupt & IN */ |
610 | endpoint = &iface_desc->endpoint[0].desc; | 645 | endpoint = &iface_desc->endpoint[0].desc; |
611 | 646 | ||
612 | if (!((endpoint->bEndpointAddress & USB_DIR_IN) && | 647 | if (!usb_endpoint_is_int_in(endpoint)) { |
613 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
614 | == USB_ENDPOINT_XFER_INT))) { | ||
615 | /* we didn't find a Interrupt endpoint with direction IN */ | 648 | /* we didn't find a Interrupt endpoint with direction IN */ |
616 | printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n"); | 649 | printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n"); |
617 | return -ENODEV; | 650 | return -ENODEV; |
@@ -634,10 +667,12 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
634 | usb_pcwd->udev = udev; | 667 | usb_pcwd->udev = udev; |
635 | usb_pcwd->interface = interface; | 668 | usb_pcwd->interface = interface; |
636 | usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber; | 669 | usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber; |
637 | usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8); | 670 | usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? |
671 | le16_to_cpu(endpoint->wMaxPacketSize) : 8); | ||
638 | 672 | ||
639 | /* set up the memory buffer's */ | 673 | /* set up the memory buffer's */ |
640 | usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma); | 674 | usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, |
675 | GFP_ATOMIC, &usb_pcwd->intr_dma); | ||
641 | if (!usb_pcwd->intr_buffer) { | 676 | if (!usb_pcwd->intr_buffer) { |
642 | printk(KERN_ERR PFX "Out of memory\n"); | 677 | printk(KERN_ERR PFX "Out of memory\n"); |
643 | goto error; | 678 | goto error; |
@@ -671,7 +706,8 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
671 | usb_pcwd_stop(usb_pcwd); | 706 | usb_pcwd_stop(usb_pcwd); |
672 | 707 | ||
673 | /* Get the Firmware Version */ | 708 | /* Get the Firmware Version */ |
674 | got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); | 709 | got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, |
710 | &fw_rev_major, &fw_rev_minor); | ||
675 | if (got_fw_rev) | 711 | if (got_fw_rev) |
676 | sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); | 712 | sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); |
677 | else | 713 | else |
@@ -681,9 +717,11 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
681 | fw_ver_str); | 717 | fw_ver_str); |
682 | 718 | ||
683 | /* Get switch settings */ | 719 | /* Get switch settings */ |
684 | usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, &option_switches); | 720 | usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, |
721 | &option_switches); | ||
685 | 722 | ||
686 | printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", | 723 | printk(KERN_INFO PFX "Option switches (0x%02x): " |
724 | "Temperature Reset Enable=%s, Power On Delay=%s\n", | ||
687 | option_switches, | 725 | option_switches, |
688 | ((option_switches & 0x10) ? "ON" : "OFF"), | 726 | ((option_switches & 0x10) ? "ON" : "OFF"), |
689 | ((option_switches & 0x08) ? "ON" : "OFF")); | 727 | ((option_switches & 0x08) ? "ON" : "OFF")); |
@@ -692,30 +730,35 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
692 | if (heartbeat == 0) | 730 | if (heartbeat == 0) |
693 | heartbeat = heartbeat_tbl[(option_switches & 0x07)]; | 731 | heartbeat = heartbeat_tbl[(option_switches & 0x07)]; |
694 | 732 | ||
695 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 733 | /* Check that the heartbeat value is within it's range ; |
734 | * if not reset to the default */ | ||
696 | if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) { | 735 | if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) { |
697 | usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT); | 736 | usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT); |
698 | printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n", | 737 | printk(KERN_INFO PFX |
738 | "heartbeat value must be 0<heartbeat<65536, using %d\n", | ||
699 | WATCHDOG_HEARTBEAT); | 739 | WATCHDOG_HEARTBEAT); |
700 | } | 740 | } |
701 | 741 | ||
702 | retval = register_reboot_notifier(&usb_pcwd_notifier); | 742 | retval = register_reboot_notifier(&usb_pcwd_notifier); |
703 | if (retval != 0) { | 743 | if (retval != 0) { |
704 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 744 | printk(KERN_ERR PFX |
745 | "cannot register reboot notifier (err=%d)\n", | ||
705 | retval); | 746 | retval); |
706 | goto error; | 747 | goto error; |
707 | } | 748 | } |
708 | 749 | ||
709 | retval = misc_register(&usb_pcwd_temperature_miscdev); | 750 | retval = misc_register(&usb_pcwd_temperature_miscdev); |
710 | if (retval != 0) { | 751 | if (retval != 0) { |
711 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 752 | printk(KERN_ERR PFX |
753 | "cannot register miscdev on minor=%d (err=%d)\n", | ||
712 | TEMP_MINOR, retval); | 754 | TEMP_MINOR, retval); |
713 | goto err_out_unregister_reboot; | 755 | goto err_out_unregister_reboot; |
714 | } | 756 | } |
715 | 757 | ||
716 | retval = misc_register(&usb_pcwd_miscdev); | 758 | retval = misc_register(&usb_pcwd_miscdev); |
717 | if (retval != 0) { | 759 | if (retval != 0) { |
718 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 760 | printk(KERN_ERR PFX |
761 | "cannot register miscdev on minor=%d (err=%d)\n", | ||
719 | WATCHDOG_MINOR, retval); | 762 | WATCHDOG_MINOR, retval); |
720 | goto err_out_misc_deregister; | 763 | goto err_out_misc_deregister; |
721 | } | 764 | } |
@@ -801,7 +844,7 @@ static int __init usb_pcwd_init(void) | |||
801 | return result; | 844 | return result; |
802 | } | 845 | } |
803 | 846 | ||
804 | printk(KERN_INFO PFX DRIVER_DESC " v" DRIVER_VERSION " (" DRIVER_DATE ")\n"); | 847 | printk(KERN_INFO PFX DRIVER_DESC " v" DRIVER_VERSION "\n"); |
805 | return 0; | 848 | return 0; |
806 | } | 849 | } |
807 | 850 | ||