diff options
| author | Cyrill V. Gorcunov <gorcunov@gmail.com> | 2007-02-10 01:29:19 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-02-10 01:29:19 -0500 |
| commit | b350620cc5e8e62782a4d47bf45952442a18a0b0 (patch) | |
| tree | 03850d27686950a0aba6cbd702e70334dc39c24c | |
| parent | ff141a03e1909db719c6afd3230c2f16a4141860 (diff) | |
Input: HIL - handle erros from input_register_device()
Also some whitespace cleanup.
Signed-off-by: Cyrill V. Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
| -rw-r--r-- | drivers/input/keyboard/hilkbd.c | 114 |
1 files changed, 66 insertions, 48 deletions
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 35461eab2faf..255a6ec75a48 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c | |||
| @@ -6,10 +6,10 @@ | |||
| 6 | * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> | 6 | * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> |
| 7 | * | 7 | * |
| 8 | * Very basic HP Human Interface Loop (HIL) driver. | 8 | * Very basic HP Human Interface Loop (HIL) driver. |
| 9 | * This driver handles the keyboard on HP300 (m68k) and on some | 9 | * This driver handles the keyboard on HP300 (m68k) and on some |
| 10 | * HP700 (parisc) series machines. | 10 | * HP700 (parisc) series machines. |
| 11 | * | 11 | * |
| 12 | * | 12 | * |
| 13 | * This file is subject to the terms and conditions of the GNU General Public | 13 | * This file is subject to the terms and conditions of the GNU General Public |
| 14 | * License version 2. See the file COPYING in the main directory of this | 14 | * License version 2. See the file COPYING in the main directory of this |
| 15 | * archive for more details. | 15 | * archive for more details. |
| @@ -64,9 +64,9 @@ MODULE_LICENSE("GPL v2"); | |||
| 64 | #endif | 64 | #endif |
| 65 | 65 | ||
| 66 | 66 | ||
| 67 | 67 | ||
| 68 | /* HIL helper functions */ | 68 | /* HIL helper functions */ |
| 69 | 69 | ||
| 70 | #define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY) | 70 | #define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY) |
| 71 | #define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) | 71 | #define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) |
| 72 | #define hil_status() (hil_readb(HILBASE + HIL_CMD)) | 72 | #define hil_status() (hil_readb(HILBASE + HIL_CMD)) |
| @@ -75,7 +75,7 @@ MODULE_LICENSE("GPL v2"); | |||
| 75 | #define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0) | 75 | #define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0) |
| 76 | 76 | ||
| 77 | /* HIL constants */ | 77 | /* HIL constants */ |
| 78 | 78 | ||
| 79 | #define HIL_BUSY 0x02 | 79 | #define HIL_BUSY 0x02 |
| 80 | #define HIL_DATA_RDY 0x01 | 80 | #define HIL_DATA_RDY 0x01 |
| 81 | 81 | ||
| @@ -86,10 +86,10 @@ MODULE_LICENSE("GPL v2"); | |||
| 86 | #define HIL_INTON 0x5C /* Turn on interrupts. */ | 86 | #define HIL_INTON 0x5C /* Turn on interrupts. */ |
| 87 | #define HIL_INTOFF 0x5D /* Turn off interrupts. */ | 87 | #define HIL_INTOFF 0x5D /* Turn off interrupts. */ |
| 88 | 88 | ||
| 89 | #define HIL_READKBDSADR 0xF9 | 89 | #define HIL_READKBDSADR 0xF9 |
| 90 | #define HIL_WRITEKBDSADR 0xE9 | 90 | #define HIL_WRITEKBDSADR 0xE9 |
| 91 | 91 | ||
| 92 | static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = | 92 | static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = |
| 93 | { HIL_KEYCODES_SET1 }; | 93 | { HIL_KEYCODES_SET1 }; |
| 94 | 94 | ||
| 95 | /* HIL structure */ | 95 | /* HIL structure */ |
| @@ -97,11 +97,11 @@ static struct { | |||
| 97 | struct input_dev *dev; | 97 | struct input_dev *dev; |
| 98 | 98 | ||
| 99 | unsigned int curdev; | 99 | unsigned int curdev; |
| 100 | 100 | ||
| 101 | unsigned char s; | 101 | unsigned char s; |
| 102 | unsigned char c; | 102 | unsigned char c; |
| 103 | int valid; | 103 | int valid; |
| 104 | 104 | ||
| 105 | unsigned char data[16]; | 105 | unsigned char data[16]; |
| 106 | unsigned int ptr; | 106 | unsigned int ptr; |
| 107 | spinlock_t lock; | 107 | spinlock_t lock; |
| @@ -115,7 +115,7 @@ static void poll_finished(void) | |||
| 115 | int down; | 115 | int down; |
| 116 | int key; | 116 | int key; |
| 117 | unsigned char scode; | 117 | unsigned char scode; |
| 118 | 118 | ||
| 119 | switch (hil_dev.data[0]) { | 119 | switch (hil_dev.data[0]) { |
| 120 | case 0x40: | 120 | case 0x40: |
| 121 | down = (hil_dev.data[1] & 1) == 0; | 121 | down = (hil_dev.data[1] & 1) == 0; |
| @@ -127,6 +127,7 @@ static void poll_finished(void) | |||
| 127 | hil_dev.curdev = 0; | 127 | hil_dev.curdev = 0; |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | |||
| 130 | static inline void handle_status(unsigned char s, unsigned char c) | 131 | static inline void handle_status(unsigned char s, unsigned char c) |
| 131 | { | 132 | { |
| 132 | if (c & 0x8) { | 133 | if (c & 0x8) { |
| @@ -143,6 +144,7 @@ static inline void handle_status(unsigned char s, unsigned char c) | |||
| 143 | } | 144 | } |
| 144 | } | 145 | } |
| 145 | 146 | ||
| 147 | |||
| 146 | static inline void handle_data(unsigned char s, unsigned char c) | 148 | static inline void handle_data(unsigned char s, unsigned char c) |
| 147 | { | 149 | { |
| 148 | if (hil_dev.curdev) { | 150 | if (hil_dev.curdev) { |
| @@ -152,13 +154,11 @@ static inline void handle_data(unsigned char s, unsigned char c) | |||
| 152 | } | 154 | } |
| 153 | 155 | ||
| 154 | 156 | ||
| 155 | /* | 157 | /* handle HIL interrupts */ |
| 156 | * Handle HIL interrupts. | ||
| 157 | */ | ||
| 158 | static irqreturn_t hil_interrupt(int irq, void *handle) | 158 | static irqreturn_t hil_interrupt(int irq, void *handle) |
| 159 | { | 159 | { |
| 160 | unsigned char s, c; | 160 | unsigned char s, c; |
| 161 | 161 | ||
| 162 | s = hil_status(); | 162 | s = hil_status(); |
| 163 | c = hil_read_data(); | 163 | c = hil_read_data(); |
| 164 | 164 | ||
| @@ -179,10 +179,8 @@ static irqreturn_t hil_interrupt(int irq, void *handle) | |||
| 179 | return IRQ_HANDLED; | 179 | return IRQ_HANDLED; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | /* | ||
| 183 | * Send a command to the HIL | ||
| 184 | */ | ||
| 185 | 182 | ||
| 183 | /* send a command to the HIL */ | ||
| 186 | static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) | 184 | static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) |
| 187 | { | 185 | { |
| 188 | unsigned long flags; | 186 | unsigned long flags; |
| @@ -200,16 +198,14 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) | |||
| 200 | } | 198 | } |
| 201 | 199 | ||
| 202 | 200 | ||
| 203 | /* | 201 | /* initialise HIL */ |
| 204 | * Initialise HIL. | ||
| 205 | */ | ||
| 206 | |||
| 207 | static int __init | 202 | static int __init |
| 208 | hil_keyb_init(void) | 203 | hil_keyb_init(void) |
| 209 | { | 204 | { |
| 210 | unsigned char c; | 205 | unsigned char c; |
| 211 | unsigned int i, kbid; | 206 | unsigned int i, kbid; |
| 212 | wait_queue_head_t hil_wait; | 207 | wait_queue_head_t hil_wait; |
| 208 | int err; | ||
| 213 | 209 | ||
| 214 | if (hil_dev.dev) { | 210 | if (hil_dev.dev) { |
| 215 | return -ENODEV; /* already initialized */ | 211 | return -ENODEV; /* already initialized */ |
| @@ -219,15 +215,25 @@ hil_keyb_init(void) | |||
| 219 | if (!hil_dev.dev) | 215 | if (!hil_dev.dev) |
| 220 | return -ENOMEM; | 216 | return -ENOMEM; |
| 221 | hil_dev.dev->private = &hil_dev; | 217 | hil_dev.dev->private = &hil_dev; |
| 222 | 218 | ||
| 223 | #if defined(CONFIG_HP300) | 219 | #if defined(CONFIG_HP300) |
| 224 | if (!hwreg_present((void *)(HILBASE + HIL_DATA))) | 220 | if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { |
| 225 | return -ENODEV; | 221 | printk(KERN_ERR "HIL: hardware register was not found\n"); |
| 226 | 222 | err = -ENODEV; | |
| 227 | request_region(HILBASE+HIL_DATA, 2, "hil"); | 223 | goto err1; |
| 224 | } | ||
| 225 | if (!request_region(HILBASE + HIL_DATA, 2, "hil")) { | ||
| 226 | printk(KERN_ERR "HIL: IOPORT region already used\n"); | ||
| 227 | err = -EIO; | ||
| 228 | goto err1; | ||
| 229 | } | ||
| 228 | #endif | 230 | #endif |
| 229 | 231 | ||
| 230 | request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); | 232 | err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); |
| 233 | if (err) { | ||
| 234 | printk(KERN_ERR "HIL: Can't get IRQ\n"); | ||
| 235 | goto err2; | ||
| 236 | } | ||
| 231 | 237 | ||
| 232 | /* Turn on interrupts */ | 238 | /* Turn on interrupts */ |
| 233 | hil_do(HIL_INTON, NULL, 0); | 239 | hil_do(HIL_INTON, NULL, 0); |
| @@ -239,47 +245,63 @@ hil_keyb_init(void) | |||
| 239 | init_waitqueue_head(&hil_wait); | 245 | init_waitqueue_head(&hil_wait); |
| 240 | wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); | 246 | wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); |
| 241 | if (!hil_dev.valid) { | 247 | if (!hil_dev.valid) { |
| 242 | printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n"); | 248 | printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n"); |
| 243 | } | 249 | } |
| 244 | 250 | ||
| 245 | c = hil_dev.c; | 251 | c = hil_dev.c; |
| 246 | hil_dev.valid = 0; | 252 | hil_dev.valid = 0; |
| 247 | if (c == 0) { | 253 | if (c == 0) { |
| 248 | kbid = -1; | 254 | kbid = -1; |
| 249 | printk(KERN_WARNING "HIL: no keyboard present.\n"); | 255 | printk(KERN_WARNING "HIL: no keyboard present\n"); |
| 250 | } else { | 256 | } else { |
| 251 | kbid = ffz(~c); | 257 | kbid = ffz(~c); |
| 252 | /* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */ | 258 | printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); |
| 253 | } | 259 | } |
| 254 | 260 | ||
| 255 | /* set it to raw mode */ | 261 | /* set it to raw mode */ |
| 256 | c = 0; | 262 | c = 0; |
| 257 | hil_do(HIL_WRITEKBDSADR, &c, 1); | 263 | hil_do(HIL_WRITEKBDSADR, &c, 1); |
| 258 | 264 | ||
| 259 | for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) | 265 | for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) |
| 260 | if (hphilkeyb_keycode[i] != KEY_RESERVED) | 266 | if (hphilkeyb_keycode[i] != KEY_RESERVED) |
| 261 | set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); | 267 | set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); |
| 262 | 268 | ||
| 263 | hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 269 | hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
| 264 | hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); | 270 | hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); |
| 265 | hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | 271 | hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; |
| 266 | hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]); | 272 | hil_dev.dev->keycodesize= sizeof(hphilkeyb_keycode[0]); |
| 267 | hil_dev.dev->keycode = hphilkeyb_keycode; | 273 | hil_dev.dev->keycode = hphilkeyb_keycode; |
| 268 | hil_dev.dev->name = "HIL keyboard"; | 274 | hil_dev.dev->name = "HIL keyboard"; |
| 269 | hil_dev.dev->phys = "hpkbd/input0"; | 275 | hil_dev.dev->phys = "hpkbd/input0"; |
| 270 | 276 | ||
| 271 | hil_dev.dev->id.bustype = BUS_HIL; | 277 | hil_dev.dev->id.bustype = BUS_HIL; |
| 272 | hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP; | 278 | hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP; |
| 273 | hil_dev.dev->id.product = 0x0001; | 279 | hil_dev.dev->id.product = 0x0001; |
| 274 | hil_dev.dev->id.version = 0x0010; | 280 | hil_dev.dev->id.version = 0x0010; |
| 275 | 281 | ||
| 276 | input_register_device(hil_dev.dev); | 282 | err = input_register_device(hil_dev.dev); |
| 283 | if (err) { | ||
| 284 | printk(KERN_ERR "HIL: Can't register device\n"); | ||
| 285 | goto err3; | ||
| 286 | } | ||
| 277 | printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", | 287 | printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", |
| 278 | hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); | 288 | hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); |
| 279 | 289 | ||
| 280 | return 0; | 290 | return 0; |
| 291 | |||
| 292 | err3: | ||
| 293 | hil_do(HIL_INTOFF, NULL, 0); | ||
| 294 | disable_irq(HIL_IRQ); | ||
| 295 | free_irq(HIL_IRQ, hil_dev.dev_id); | ||
| 296 | err2: | ||
| 297 | release_region(HILBASE + HIL_DATA, 2); | ||
| 298 | err1: | ||
| 299 | input_free_device(hil_dev.dev); | ||
| 300 | hil_dev.dev = NULL; | ||
| 301 | return err; | ||
| 281 | } | 302 | } |
| 282 | 303 | ||
| 304 | |||
| 283 | #if defined(CONFIG_PARISC) | 305 | #if defined(CONFIG_PARISC) |
| 284 | static int __init | 306 | static int __init |
| 285 | hil_init_chip(struct parisc_device *dev) | 307 | hil_init_chip(struct parisc_device *dev) |
| @@ -292,7 +314,7 @@ hil_init_chip(struct parisc_device *dev) | |||
| 292 | hil_base = dev->hpa.start; | 314 | hil_base = dev->hpa.start; |
| 293 | hil_irq = dev->irq; | 315 | hil_irq = dev->irq; |
| 294 | hil_dev.dev_id = dev; | 316 | hil_dev.dev_id = dev; |
| 295 | 317 | ||
| 296 | printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq); | 318 | printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq); |
| 297 | 319 | ||
| 298 | return hil_keyb_init(); | 320 | return hil_keyb_init(); |
| @@ -313,9 +335,6 @@ static struct parisc_driver hil_driver = { | |||
| 313 | #endif /* CONFIG_PARISC */ | 335 | #endif /* CONFIG_PARISC */ |
| 314 | 336 | ||
| 315 | 337 | ||
| 316 | |||
| 317 | |||
| 318 | |||
| 319 | static int __init hil_init(void) | 338 | static int __init hil_init(void) |
| 320 | { | 339 | { |
| 321 | #if defined(CONFIG_PARISC) | 340 | #if defined(CONFIG_PARISC) |
| @@ -349,4 +368,3 @@ static void __exit hil_exit(void) | |||
| 349 | 368 | ||
| 350 | module_init(hil_init); | 369 | module_init(hil_init); |
| 351 | module_exit(hil_exit); | 370 | module_exit(hil_exit); |
| 352 | |||
