diff options
Diffstat (limited to 'drivers/input/keyboard/sunkbd.c')
-rw-r--r-- | drivers/input/keyboard/sunkbd.c | 142 |
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 | ||
75 | struct sunkbd { | 75 | struct 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 { | |||
94 | static irqreturn_t sunkbd_interrupt(struct serio *serio, | 94 | static 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 | } |
137 | out: | 145 | out: |
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 | ||
145 | static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 153 | static 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 | |||
183 | static int sunkbd_initialize(struct sunkbd *sunkbd) | 194 | static 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 | ||
223 | static void sunkbd_enable(struct sunkbd *sunkbd, int enable) | 241 | static 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 | ||
234 | static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | 253 | static 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); |