0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/delay.h>
0014 #include <linux/sched.h>
0015 #include <linux/slab.h>
0016 #include <linux/module.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/input.h>
0019 #include <linux/serio.h>
0020 #include <linux/workqueue.h>
0021
0022 #define DRIVER_DESC "Sun keyboard driver"
0023
0024 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0025 MODULE_DESCRIPTION(DRIVER_DESC);
0026 MODULE_LICENSE("GPL");
0027
0028 static unsigned char sunkbd_keycode[128] = {
0029 0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,112,
0030 65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106, 1, 2, 3,
0031 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
0032 116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
0033 26, 27,111,127, 71, 72, 73, 74,134,135,107, 0, 29, 30, 31, 32,
0034 33, 34, 35, 36, 37, 38, 39, 40, 43, 28, 96, 75, 76, 77, 82,136,
0035 104,137, 69, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,101,
0036 79, 80, 81, 0, 0, 0,138, 58,125, 57,126,109, 86, 78
0037 };
0038
0039 #define SUNKBD_CMD_RESET 0x1
0040 #define SUNKBD_CMD_BELLON 0x2
0041 #define SUNKBD_CMD_BELLOFF 0x3
0042 #define SUNKBD_CMD_CLICK 0xa
0043 #define SUNKBD_CMD_NOCLICK 0xb
0044 #define SUNKBD_CMD_SETLED 0xe
0045 #define SUNKBD_CMD_LAYOUT 0xf
0046
0047 #define SUNKBD_RET_RESET 0xff
0048 #define SUNKBD_RET_ALLUP 0x7f
0049 #define SUNKBD_RET_LAYOUT 0xfe
0050
0051 #define SUNKBD_LAYOUT_5_MASK 0x20
0052 #define SUNKBD_RELEASE 0x80
0053 #define SUNKBD_KEY 0x7f
0054
0055
0056
0057
0058
0059 struct sunkbd {
0060 unsigned char keycode[ARRAY_SIZE(sunkbd_keycode)];
0061 struct input_dev *dev;
0062 struct serio *serio;
0063 struct work_struct tq;
0064 wait_queue_head_t wait;
0065 char name[64];
0066 char phys[32];
0067 char type;
0068 bool enabled;
0069 volatile s8 reset;
0070 volatile s8 layout;
0071 };
0072
0073
0074
0075
0076
0077
0078 static irqreturn_t sunkbd_interrupt(struct serio *serio,
0079 unsigned char data, unsigned int flags)
0080 {
0081 struct sunkbd *sunkbd = serio_get_drvdata(serio);
0082
0083 if (sunkbd->reset <= -1) {
0084
0085
0086
0087
0088 sunkbd->reset = data;
0089 wake_up_interruptible(&sunkbd->wait);
0090 goto out;
0091 }
0092
0093 if (sunkbd->layout == -1) {
0094 sunkbd->layout = data;
0095 wake_up_interruptible(&sunkbd->wait);
0096 goto out;
0097 }
0098
0099 switch (data) {
0100
0101 case SUNKBD_RET_RESET:
0102 if (sunkbd->enabled)
0103 schedule_work(&sunkbd->tq);
0104 sunkbd->reset = -1;
0105 break;
0106
0107 case SUNKBD_RET_LAYOUT:
0108 sunkbd->layout = -1;
0109 break;
0110
0111 case SUNKBD_RET_ALLUP:
0112 break;
0113
0114 default:
0115 if (!sunkbd->enabled)
0116 break;
0117
0118 if (sunkbd->keycode[data & SUNKBD_KEY]) {
0119 input_report_key(sunkbd->dev,
0120 sunkbd->keycode[data & SUNKBD_KEY],
0121 !(data & SUNKBD_RELEASE));
0122 input_sync(sunkbd->dev);
0123 } else {
0124 printk(KERN_WARNING
0125 "sunkbd.c: Unknown key (scancode %#x) %s.\n",
0126 data & SUNKBD_KEY,
0127 data & SUNKBD_RELEASE ? "released" : "pressed");
0128 }
0129 }
0130 out:
0131 return IRQ_HANDLED;
0132 }
0133
0134
0135
0136
0137
0138 static int sunkbd_event(struct input_dev *dev,
0139 unsigned int type, unsigned int code, int value)
0140 {
0141 struct sunkbd *sunkbd = input_get_drvdata(dev);
0142
0143 switch (type) {
0144
0145 case EV_LED:
0146
0147 serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
0148 serio_write(sunkbd->serio,
0149 (!!test_bit(LED_CAPSL, dev->led) << 3) |
0150 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
0151 (!!test_bit(LED_COMPOSE, dev->led) << 1) |
0152 !!test_bit(LED_NUML, dev->led));
0153 return 0;
0154
0155 case EV_SND:
0156
0157 switch (code) {
0158
0159 case SND_CLICK:
0160 serio_write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value);
0161 return 0;
0162
0163 case SND_BELL:
0164 serio_write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value);
0165 return 0;
0166 }
0167
0168 break;
0169 }
0170
0171 return -1;
0172 }
0173
0174
0175
0176
0177
0178
0179 static int sunkbd_initialize(struct sunkbd *sunkbd)
0180 {
0181 sunkbd->reset = -2;
0182 serio_write(sunkbd->serio, SUNKBD_CMD_RESET);
0183 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
0184 if (sunkbd->reset < 0)
0185 return -1;
0186
0187 sunkbd->type = sunkbd->reset;
0188
0189 if (sunkbd->type == 4) {
0190 sunkbd->layout = -2;
0191 serio_write(sunkbd->serio, SUNKBD_CMD_LAYOUT);
0192 wait_event_interruptible_timeout(sunkbd->wait,
0193 sunkbd->layout >= 0, HZ / 4);
0194 if (sunkbd->layout < 0)
0195 return -1;
0196 if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK)
0197 sunkbd->type = 5;
0198 }
0199
0200 return 0;
0201 }
0202
0203
0204
0205
0206
0207
0208 static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd)
0209 {
0210 serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
0211 serio_write(sunkbd->serio,
0212 (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) |
0213 (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) |
0214 (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) |
0215 !!test_bit(LED_NUML, sunkbd->dev->led));
0216 serio_write(sunkbd->serio,
0217 SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd));
0218 serio_write(sunkbd->serio,
0219 SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
0220 }
0221
0222
0223
0224
0225
0226
0227
0228 static void sunkbd_reinit(struct work_struct *work)
0229 {
0230 struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
0231
0232
0233
0234
0235
0236
0237 wait_event_interruptible_timeout(sunkbd->wait,
0238 sunkbd->reset >= 0 || !sunkbd->enabled,
0239 HZ);
0240
0241 if (sunkbd->reset >= 0 && sunkbd->enabled)
0242 sunkbd_set_leds_beeps(sunkbd);
0243 }
0244
0245 static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
0246 {
0247 serio_pause_rx(sunkbd->serio);
0248 sunkbd->enabled = enable;
0249 serio_continue_rx(sunkbd->serio);
0250
0251 if (!enable) {
0252 wake_up_interruptible(&sunkbd->wait);
0253 cancel_work_sync(&sunkbd->tq);
0254 }
0255 }
0256
0257
0258
0259
0260
0261
0262 static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
0263 {
0264 struct sunkbd *sunkbd;
0265 struct input_dev *input_dev;
0266 int err = -ENOMEM;
0267 int i;
0268
0269 sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
0270 input_dev = input_allocate_device();
0271 if (!sunkbd || !input_dev)
0272 goto fail1;
0273
0274 sunkbd->serio = serio;
0275 sunkbd->dev = input_dev;
0276 init_waitqueue_head(&sunkbd->wait);
0277 INIT_WORK(&sunkbd->tq, sunkbd_reinit);
0278 snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys);
0279
0280 serio_set_drvdata(serio, sunkbd);
0281
0282 err = serio_open(serio, drv);
0283 if (err)
0284 goto fail2;
0285
0286 if (sunkbd_initialize(sunkbd) < 0) {
0287 err = -ENODEV;
0288 goto fail3;
0289 }
0290
0291 snprintf(sunkbd->name, sizeof(sunkbd->name),
0292 "Sun Type %d keyboard", sunkbd->type);
0293 memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
0294
0295 input_dev->name = sunkbd->name;
0296 input_dev->phys = sunkbd->phys;
0297 input_dev->id.bustype = BUS_RS232;
0298 input_dev->id.vendor = SERIO_SUNKBD;
0299 input_dev->id.product = sunkbd->type;
0300 input_dev->id.version = 0x0100;
0301 input_dev->dev.parent = &serio->dev;
0302
0303 input_set_drvdata(input_dev, sunkbd);
0304
0305 input_dev->event = sunkbd_event;
0306
0307 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
0308 BIT_MASK(EV_SND) | BIT_MASK(EV_REP);
0309 input_dev->ledbit[0] = BIT_MASK(LED_CAPSL) | BIT_MASK(LED_COMPOSE) |
0310 BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_NUML);
0311 input_dev->sndbit[0] = BIT_MASK(SND_CLICK) | BIT_MASK(SND_BELL);
0312
0313 input_dev->keycode = sunkbd->keycode;
0314 input_dev->keycodesize = sizeof(unsigned char);
0315 input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
0316 for (i = 0; i < ARRAY_SIZE(sunkbd_keycode); i++)
0317 __set_bit(sunkbd->keycode[i], input_dev->keybit);
0318 __clear_bit(KEY_RESERVED, input_dev->keybit);
0319
0320 sunkbd_enable(sunkbd, true);
0321
0322 err = input_register_device(sunkbd->dev);
0323 if (err)
0324 goto fail4;
0325
0326 return 0;
0327
0328 fail4: sunkbd_enable(sunkbd, false);
0329 fail3: serio_close(serio);
0330 fail2: serio_set_drvdata(serio, NULL);
0331 fail1: input_free_device(input_dev);
0332 kfree(sunkbd);
0333 return err;
0334 }
0335
0336
0337
0338
0339
0340 static void sunkbd_disconnect(struct serio *serio)
0341 {
0342 struct sunkbd *sunkbd = serio_get_drvdata(serio);
0343
0344 sunkbd_enable(sunkbd, false);
0345 input_unregister_device(sunkbd->dev);
0346 serio_close(serio);
0347 serio_set_drvdata(serio, NULL);
0348 kfree(sunkbd);
0349 }
0350
0351 static const struct serio_device_id sunkbd_serio_ids[] = {
0352 {
0353 .type = SERIO_RS232,
0354 .proto = SERIO_SUNKBD,
0355 .id = SERIO_ANY,
0356 .extra = SERIO_ANY,
0357 },
0358 {
0359 .type = SERIO_RS232,
0360 .proto = SERIO_UNKNOWN,
0361 .id = SERIO_ANY,
0362 .extra = SERIO_ANY,
0363 },
0364 { 0 }
0365 };
0366
0367 MODULE_DEVICE_TABLE(serio, sunkbd_serio_ids);
0368
0369 static struct serio_driver sunkbd_drv = {
0370 .driver = {
0371 .name = "sunkbd",
0372 },
0373 .description = DRIVER_DESC,
0374 .id_table = sunkbd_serio_ids,
0375 .interrupt = sunkbd_interrupt,
0376 .connect = sunkbd_connect,
0377 .disconnect = sunkbd_disconnect,
0378 };
0379
0380 module_serio_driver(sunkbd_drv);