aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard/sunkbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard/sunkbd.c')
-rw-r--r--drivers/input/keyboard/sunkbd.c117
1 files changed, 62 insertions, 55 deletions
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 4bae5d89348d..b15b6d8d4f83 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -76,13 +76,14 @@ static unsigned char sunkbd_keycode[128] = {
76 76
77struct sunkbd { 77struct sunkbd {
78 unsigned char keycode[128]; 78 unsigned char keycode[128];
79 struct input_dev dev; 79 struct input_dev *dev;
80 struct serio *serio; 80 struct serio *serio;
81 struct work_struct tq; 81 struct work_struct tq;
82 wait_queue_head_t wait; 82 wait_queue_head_t wait;
83 char name[64]; 83 char name[64];
84 char phys[32]; 84 char phys[32];
85 char type; 85 char type;
86 unsigned char enabled;
86 volatile s8 reset; 87 volatile s8 reset;
87 volatile s8 layout; 88 volatile s8 layout;
88}; 89};
@@ -124,10 +125,13 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
124 break; 125 break;
125 126
126 default: 127 default:
128 if (!sunkbd->enabled)
129 break;
130
127 if (sunkbd->keycode[data & SUNKBD_KEY]) { 131 if (sunkbd->keycode[data & SUNKBD_KEY]) {
128 input_regs(&sunkbd->dev, regs); 132 input_regs(sunkbd->dev, regs);
129 input_report_key(&sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE)); 133 input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE));
130 input_sync(&sunkbd->dev); 134 input_sync(sunkbd->dev);
131 } else { 135 } else {
132 printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n", 136 printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n",
133 data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed"); 137 data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed");
@@ -184,7 +188,7 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
184 sunkbd->reset = -2; 188 sunkbd->reset = -2;
185 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET); 189 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
186 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); 190 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
187 if (sunkbd->reset <0) 191 if (sunkbd->reset < 0)
188 return -1; 192 return -1;
189 193
190 sunkbd->type = sunkbd->reset; 194 sunkbd->type = sunkbd->reset;
@@ -213,10 +217,17 @@ static void sunkbd_reinit(void *data)
213 217
214 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); 218 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
215 sunkbd->serio->write(sunkbd->serio, 219 sunkbd->serio->write(sunkbd->serio,
216 (!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) | 220 (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) |
217 (!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led)); 221 (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led));
218 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd)); 222 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd));
219 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev.snd)); 223 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
224}
225
226static void sunkbd_enable(struct sunkbd *sunkbd, int enable)
227{
228 serio_pause_rx(sunkbd->serio);
229 sunkbd->enabled = 1;
230 serio_continue_rx(sunkbd->serio);
220} 231}
221 232
222/* 233/*
@@ -226,70 +237,64 @@ static void sunkbd_reinit(void *data)
226static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) 237static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
227{ 238{
228 struct sunkbd *sunkbd; 239 struct sunkbd *sunkbd;
240 struct input_dev *input_dev;
241 int err = -ENOMEM;
229 int i; 242 int i;
230 int err;
231
232 if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
233 return -ENOMEM;
234 243
235 memset(sunkbd, 0, sizeof(struct sunkbd)); 244 sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
236 245 input_dev = input_allocate_device();
237 init_input_dev(&sunkbd->dev); 246 if (!sunkbd || !input_dev)
238 init_waitqueue_head(&sunkbd->wait); 247 goto fail;
239
240 sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
241 sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
242 sunkbd->dev.sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
243 248
244 sunkbd->serio = serio; 249 sunkbd->serio = serio;
245 250 sunkbd->dev = input_dev;
251 init_waitqueue_head(&sunkbd->wait);
246 INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd); 252 INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd);
247 253 snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys);
248 sunkbd->dev.keycode = sunkbd->keycode;
249 sunkbd->dev.keycodesize = sizeof(unsigned char);
250 sunkbd->dev.keycodemax = ARRAY_SIZE(sunkbd_keycode);
251
252 sunkbd->dev.event = sunkbd_event;
253 sunkbd->dev.private = sunkbd;
254 254
255 serio_set_drvdata(serio, sunkbd); 255 serio_set_drvdata(serio, sunkbd);
256 256
257 err = serio_open(serio, drv); 257 err = serio_open(serio, drv);
258 if (err) { 258 if (err)
259 serio_set_drvdata(serio, NULL); 259 goto fail;
260 kfree(sunkbd);
261 return err;
262 }
263 260
264 if (sunkbd_initialize(sunkbd) < 0) { 261 if (sunkbd_initialize(sunkbd) < 0) {
265 serio_close(serio); 262 serio_close(serio);
266 serio_set_drvdata(serio, NULL); 263 goto fail;
267 kfree(sunkbd);
268 return -ENODEV;
269 } 264 }
270 265
271 sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type); 266 sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
272
273 memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); 267 memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
274 for (i = 0; i < 128; i++)
275 set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
276 clear_bit(0, sunkbd->dev.keybit);
277
278 sprintf(sunkbd->phys, "%s/input0", serio->phys);
279
280 sunkbd->dev.name = sunkbd->name;
281 sunkbd->dev.phys = sunkbd->phys;
282 sunkbd->dev.id.bustype = BUS_RS232;
283 sunkbd->dev.id.vendor = SERIO_SUNKBD;
284 sunkbd->dev.id.product = sunkbd->type;
285 sunkbd->dev.id.version = 0x0100;
286 sunkbd->dev.dev = &serio->dev;
287 268
288 input_register_device(&sunkbd->dev); 269 input_dev->name = sunkbd->name;
289 270 input_dev->phys = sunkbd->phys;
290 printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys); 271 input_dev->id.bustype = BUS_RS232;
272 input_dev->id.vendor = SERIO_SUNKBD;
273 input_dev->id.product = sunkbd->type;
274 input_dev->id.version = 0x0100;
275 input_dev->cdev.dev = &serio->dev;
276 input_dev->private = sunkbd;
277 input_dev->event = sunkbd_event;
278
279 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
280 input_dev->ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
281 input_dev->sndbit[0] = BIT(SND_CLICK) | BIT(SND_BELL);
282
283 input_dev->keycode = sunkbd->keycode;
284 input_dev->keycodesize = sizeof(unsigned char);
285 input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
286 for (i = 0; i < 128; i++)
287 set_bit(sunkbd->keycode[i], input_dev->keybit);
288 clear_bit(0, input_dev->keybit);
291 289
290 sunkbd_enable(sunkbd, 1);
291 input_register_device(sunkbd->dev);
292 return 0; 292 return 0;
293
294 fail: serio_set_drvdata(serio, NULL);
295 input_free_device(input_dev);
296 kfree(sunkbd);
297 return err;
293} 298}
294 299
295/* 300/*
@@ -299,7 +304,9 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
299static void sunkbd_disconnect(struct serio *serio) 304static void sunkbd_disconnect(struct serio *serio)
300{ 305{
301 struct sunkbd *sunkbd = serio_get_drvdata(serio); 306 struct sunkbd *sunkbd = serio_get_drvdata(serio);
302 input_unregister_device(&sunkbd->dev); 307
308 sunkbd_enable(sunkbd, 0);
309 input_unregister_device(sunkbd->dev);
303 serio_close(serio); 310 serio_close(serio);
304 serio_set_drvdata(serio, NULL); 311 serio_set_drvdata(serio, NULL);
305 kfree(sunkbd); 312 kfree(sunkbd);