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.c142
1 files changed, 81 insertions, 61 deletions
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 9fce6d1e29b2..472b56639cdb 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -73,7 +73,7 @@ static unsigned char sunkbd_keycode[128] = {
73 */ 73 */
74 74
75struct sunkbd { 75struct sunkbd {
76 unsigned char keycode[128]; 76 unsigned char keycode[ARRAY_SIZE(sunkbd_keycode)];
77 struct input_dev *dev; 77 struct input_dev *dev;
78 struct serio *serio; 78 struct serio *serio;
79 struct work_struct tq; 79 struct work_struct tq;
@@ -81,7 +81,7 @@ struct sunkbd {
81 char name[64]; 81 char name[64];
82 char phys[32]; 82 char phys[32];
83 char type; 83 char type;
84 unsigned char enabled; 84 bool enabled;
85 volatile s8 reset; 85 volatile s8 reset;
86 volatile s8 layout; 86 volatile s8 layout;
87}; 87};
@@ -94,10 +94,14 @@ struct sunkbd {
94static irqreturn_t sunkbd_interrupt(struct serio *serio, 94static irqreturn_t sunkbd_interrupt(struct serio *serio,
95 unsigned char data, unsigned int flags) 95 unsigned char data, unsigned int flags)
96{ 96{
97 struct sunkbd* sunkbd = serio_get_drvdata(serio); 97 struct sunkbd *sunkbd = serio_get_drvdata(serio);
98 98
99 if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */ 99 if (sunkbd->reset <= -1) {
100 sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */ 100 /*
101 * If cp[i] is 0xff, sunkbd->reset will stay -1.
102 * The keyboard sends 0xff 0xff 0xID on powerup.
103 */
104 sunkbd->reset = data;
101 wake_up_interruptible(&sunkbd->wait); 105 wake_up_interruptible(&sunkbd->wait);
102 goto out; 106 goto out;
103 } 107 }
@@ -110,29 +114,33 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
110 114
111 switch (data) { 115 switch (data) {
112 116
113 case SUNKBD_RET_RESET: 117 case SUNKBD_RET_RESET:
114 schedule_work(&sunkbd->tq); 118 schedule_work(&sunkbd->tq);
115 sunkbd->reset = -1; 119 sunkbd->reset = -1;
116 break; 120 break;
117 121
118 case SUNKBD_RET_LAYOUT: 122 case SUNKBD_RET_LAYOUT:
119 sunkbd->layout = -1; 123 sunkbd->layout = -1;
120 break; 124 break;
125
126 case SUNKBD_RET_ALLUP: /* All keys released */
127 break;
121 128
122 case SUNKBD_RET_ALLUP: /* All keys released */ 129 default:
130 if (!sunkbd->enabled)
123 break; 131 break;
124 132
125 default: 133 if (sunkbd->keycode[data & SUNKBD_KEY]) {
126 if (!sunkbd->enabled) 134 input_report_key(sunkbd->dev,
127 break; 135 sunkbd->keycode[data & SUNKBD_KEY],
128 136 !(data & SUNKBD_RELEASE));
129 if (sunkbd->keycode[data & SUNKBD_KEY]) { 137 input_sync(sunkbd->dev);
130 input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE)); 138 } else {
131 input_sync(sunkbd->dev); 139 printk(KERN_WARNING
132 } else { 140 "sunkbd.c: Unknown key (scancode %#x) %s.\n",
133 printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n", 141 data & SUNKBD_KEY,
134 data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed"); 142 data & SUNKBD_RELEASE ? "released" : "pressed");
135 } 143 }
136 } 144 }
137out: 145out:
138 return IRQ_HANDLED; 146 return IRQ_HANDLED;
@@ -142,34 +150,37 @@ out:
142 * sunkbd_event() handles events from the input module. 150 * sunkbd_event() handles events from the input module.
143 */ 151 */
144 152
145static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 153static int sunkbd_event(struct input_dev *dev,
154 unsigned int type, unsigned int code, int value)
146{ 155{
147 struct sunkbd *sunkbd = input_get_drvdata(dev); 156 struct sunkbd *sunkbd = input_get_drvdata(dev);
148 157
149 switch (type) { 158 switch (type) {
150 159
151 case EV_LED: 160 case EV_LED:
152 161
153 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); 162 serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
154 sunkbd->serio->write(sunkbd->serio, 163 serio_write(sunkbd->serio,
155 (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) | 164 (!!test_bit(LED_CAPSL, dev->led) << 3) |
156 (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led)); 165 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
157 return 0; 166 (!!test_bit(LED_COMPOSE, dev->led) << 1) |
167 !!test_bit(LED_NUML, dev->led));
168 return 0;
158 169
159 case EV_SND: 170 case EV_SND:
160 171
161 switch (code) { 172 switch (code) {
162 173
163 case SND_CLICK: 174 case SND_CLICK:
164 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); 175 serio_write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value);
165 return 0; 176 return 0;
166 177
167 case SND_BELL: 178 case SND_BELL:
168 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); 179 serio_write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value);
169 return 0; 180 return 0;
170 } 181 }
171 182
172 break; 183 break;
173 } 184 }
174 185
175 return -1; 186 return -1;
@@ -183,7 +194,7 @@ static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int c
183static int sunkbd_initialize(struct sunkbd *sunkbd) 194static int sunkbd_initialize(struct sunkbd *sunkbd)
184{ 195{
185 sunkbd->reset = -2; 196 sunkbd->reset = -2;
186 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET); 197 serio_write(sunkbd->serio, SUNKBD_CMD_RESET);
187 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); 198 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
188 if (sunkbd->reset < 0) 199 if (sunkbd->reset < 0)
189 return -1; 200 return -1;
@@ -192,10 +203,13 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
192 203
193 if (sunkbd->type == 4) { /* Type 4 keyboard */ 204 if (sunkbd->type == 4) { /* Type 4 keyboard */
194 sunkbd->layout = -2; 205 sunkbd->layout = -2;
195 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT); 206 serio_write(sunkbd->serio, SUNKBD_CMD_LAYOUT);
196 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4); 207 wait_event_interruptible_timeout(sunkbd->wait,
197 if (sunkbd->layout < 0) return -1; 208 sunkbd->layout >= 0, HZ / 4);
198 if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5; 209 if (sunkbd->layout < 0)
210 return -1;
211 if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK)
212 sunkbd->type = 5;
199 } 213 }
200 214
201 return 0; 215 return 0;
@@ -212,15 +226,19 @@ static void sunkbd_reinit(struct work_struct *work)
212 226
213 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); 227 wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
214 228
215 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); 229 serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
216 sunkbd->serio->write(sunkbd->serio, 230 serio_write(sunkbd->serio,
217 (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | 231 (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) |
218 (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led)); 232 (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) |
219 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); 233 (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) |
220 sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); 234 !!test_bit(LED_NUML, sunkbd->dev->led));
235 serio_write(sunkbd->serio,
236 SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd));
237 serio_write(sunkbd->serio,
238 SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
221} 239}
222 240
223static void sunkbd_enable(struct sunkbd *sunkbd, int enable) 241static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
224{ 242{
225 serio_pause_rx(sunkbd->serio); 243 serio_pause_rx(sunkbd->serio);
226 sunkbd->enabled = enable; 244 sunkbd->enabled = enable;
@@ -228,7 +246,8 @@ static void sunkbd_enable(struct sunkbd *sunkbd, int enable)
228} 246}
229 247
230/* 248/*
231 * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures. 249 * sunkbd_connect() probes for a Sun keyboard and fills the necessary
250 * structures.
232 */ 251 */
233 252
234static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) 253static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
@@ -260,7 +279,8 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
260 goto fail3; 279 goto fail3;
261 } 280 }
262 281
263 snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type); 282 snprintf(sunkbd->name, sizeof(sunkbd->name),
283 "Sun Type %d keyboard", sunkbd->type);
264 memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); 284 memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
265 285
266 input_dev->name = sunkbd->name; 286 input_dev->name = sunkbd->name;
@@ -284,11 +304,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
284 input_dev->keycode = sunkbd->keycode; 304 input_dev->keycode = sunkbd->keycode;
285 input_dev->keycodesize = sizeof(unsigned char); 305 input_dev->keycodesize = sizeof(unsigned char);
286 input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode); 306 input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode);
287 for (i = 0; i < 128; i++) 307 for (i = 0; i < ARRAY_SIZE(sunkbd_keycode); i++)
288 set_bit(sunkbd->keycode[i], input_dev->keybit); 308 __set_bit(sunkbd->keycode[i], input_dev->keybit);
289 clear_bit(0, input_dev->keybit); 309 __clear_bit(KEY_RESERVED, input_dev->keybit);
290 310
291 sunkbd_enable(sunkbd, 1); 311 sunkbd_enable(sunkbd, true);
292 312
293 err = input_register_device(sunkbd->dev); 313 err = input_register_device(sunkbd->dev);
294 if (err) 314 if (err)
@@ -296,7 +316,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
296 316
297 return 0; 317 return 0;
298 318
299 fail4: sunkbd_enable(sunkbd, 0); 319 fail4: sunkbd_enable(sunkbd, false);
300 fail3: serio_close(serio); 320 fail3: serio_close(serio);
301 fail2: serio_set_drvdata(serio, NULL); 321 fail2: serio_set_drvdata(serio, NULL);
302 fail1: input_free_device(input_dev); 322 fail1: input_free_device(input_dev);
@@ -312,7 +332,7 @@ static void sunkbd_disconnect(struct serio *serio)
312{ 332{
313 struct sunkbd *sunkbd = serio_get_drvdata(serio); 333 struct sunkbd *sunkbd = serio_get_drvdata(serio);
314 334
315 sunkbd_enable(sunkbd, 0); 335 sunkbd_enable(sunkbd, false);
316 input_unregister_device(sunkbd->dev); 336 input_unregister_device(sunkbd->dev);
317 serio_close(serio); 337 serio_close(serio);
318 serio_set_drvdata(serio, NULL); 338 serio_set_drvdata(serio, NULL);