diff options
Diffstat (limited to 'firmware/drivers/button.c')
-rw-r--r-- | firmware/drivers/button.c | 139 |
1 files changed, 135 insertions, 4 deletions
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 654852c516..5098cbe556 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c | |||
@@ -61,7 +61,8 @@ static bool flipped; /* buttons can be flipped to match the LCD flip */ | |||
61 | #define REPEAT_INTERVAL_FINISH 5 | 61 | #define REPEAT_INTERVAL_FINISH 5 |
62 | 62 | ||
63 | /* the power-off button and number of repeated keys before shutting off */ | 63 | /* the power-off button and number of repeated keys before shutting off */ |
64 | #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) | 64 | #if (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) ||\ |
65 | (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) | ||
65 | #define POWEROFF_BUTTON BUTTON_PLAY | 66 | #define POWEROFF_BUTTON BUTTON_PLAY |
66 | #define POWEROFF_COUNT 40 | 67 | #define POWEROFF_COUNT 40 |
67 | #else | 68 | #else |
@@ -220,7 +221,132 @@ void ipod_4g_button_int(void) | |||
220 | CPU_HI_INT_EN = I2C_MASK; | 221 | CPU_HI_INT_EN = I2C_MASK; |
221 | } | 222 | } |
222 | #endif | 223 | #endif |
224 | #if CONFIG_KEYPAD == IPOD_3G_PAD | ||
225 | /* Variable to use for setting button status in interrupt handler */ | ||
226 | int int_btn = BUTTON_NONE; | ||
223 | 227 | ||
228 | /** | ||
229 | * | ||
230 | * | ||
231 | */ | ||
232 | void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) | ||
233 | { | ||
234 | int wheel_keycode = BUTTON_NONE; | ||
235 | static int prev_scroll = -1; | ||
236 | static int scroll_state[4][4] = { | ||
237 | {0, 1, -1, 0}, | ||
238 | {-1, 0, 0, 1}, | ||
239 | {1, 0, 0, -1}, | ||
240 | {0, -1, 1, 0} | ||
241 | }; | ||
242 | |||
243 | if ( prev_scroll == -1 ) { | ||
244 | prev_scroll = new_scroll; | ||
245 | } | ||
246 | else if (!was_hold) { | ||
247 | switch (scroll_state[prev_scroll][new_scroll]) { | ||
248 | case 1: | ||
249 | if (reverse) { | ||
250 | /* 'r' keypress */ | ||
251 | wheel_keycode = BUTTON_SCROLL_FWD; | ||
252 | } | ||
253 | else { | ||
254 | /* 'l' keypress */ | ||
255 | wheel_keycode = BUTTON_SCROLL_BACK; | ||
256 | } | ||
257 | break; | ||
258 | case -1: | ||
259 | if (reverse) { | ||
260 | /* 'l' keypress */ | ||
261 | wheel_keycode = BUTTON_SCROLL_BACK; | ||
262 | } | ||
263 | else { | ||
264 | /* 'r' keypress */ | ||
265 | wheel_keycode = BUTTON_SCROLL_FWD; | ||
266 | break; | ||
267 | default: | ||
268 | /* only happens if we get out of sync */ | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | if (wheel_keycode != BUTTON_NONE) | ||
274 | queue_post(&button_queue, wheel_keycode, NULL); | ||
275 | prev_scroll = new_scroll; | ||
276 | } | ||
277 | |||
278 | static int ipod_3g_button_read(void) | ||
279 | { | ||
280 | unsigned char source, state; | ||
281 | static int was_hold = 0; | ||
282 | int btn = BUTTON_NONE; | ||
283 | /* | ||
284 | * we need some delay for g3, cause hold generates several interrupts, | ||
285 | * some of them delayed | ||
286 | */ | ||
287 | udelay(250); | ||
288 | |||
289 | /* get source of interupts */ | ||
290 | source = inb(0xcf000040); | ||
291 | if (source) { | ||
292 | |||
293 | /* get current keypad status */ | ||
294 | state = inb(0xcf000030); | ||
295 | outb(~state, 0xcf000060); | ||
296 | |||
297 | if (was_hold && source == 0x40 && state == 0xbf) { | ||
298 | /* ack any active interrupts */ | ||
299 | outb(source, 0xcf000070); | ||
300 | return BUTTON_NONE; | ||
301 | } | ||
302 | was_hold = 0; | ||
303 | |||
304 | |||
305 | if ( source & 0x20 ) { | ||
306 | /* 3g hold switch is active low */ | ||
307 | btn |= BUTTON_HOLD; | ||
308 | was_hold = 1; | ||
309 | /* hold switch on 3g causes all outputs to go low */ | ||
310 | /* we shouldn't interpret these as key presses */ | ||
311 | goto done; | ||
312 | } | ||
313 | if (source & 0x1) { | ||
314 | btn |= BUTTON_RIGHT; | ||
315 | } | ||
316 | if (source & 0x2) { | ||
317 | btn |= BUTTON_SELECT; | ||
318 | } | ||
319 | if (source & 0x4) { | ||
320 | btn |= BUTTON_PLAY; | ||
321 | } | ||
322 | if (source & 0x8) { | ||
323 | btn |= BUTTON_LEFT; | ||
324 | } | ||
325 | if (source & 0x10) { | ||
326 | btn |= BUTTON_MENU; | ||
327 | } | ||
328 | |||
329 | if (source & 0xc0) { | ||
330 | handle_scroll_wheel((state & 0xc0) >> 6, was_hold, 0); | ||
331 | } | ||
332 | done: | ||
333 | |||
334 | /* ack any active interrupts */ | ||
335 | outb(source, 0xcf000070); | ||
336 | } | ||
337 | return btn; | ||
338 | } | ||
339 | |||
340 | void ipod_3g_button_int(void) | ||
341 | { | ||
342 | /** | ||
343 | * Theire is other things to do but for now ... | ||
344 | * TODO: implement this function in a better way | ||
345 | **/ | ||
346 | int_btn = ipod_3g_button_read(); | ||
347 | |||
348 | } | ||
349 | #endif | ||
224 | static void button_tick(void) | 350 | static void button_tick(void) |
225 | { | 351 | { |
226 | static int tick = 0; | 352 | static int tick = 0; |
@@ -404,8 +530,13 @@ void button_init(void) | |||
404 | GPIOA_INT_EN = 0x20; | 530 | GPIOA_INT_EN = 0x20; |
405 | CPU_INT_EN = 0x40000000; | 531 | CPU_INT_EN = 0x40000000; |
406 | CPU_HI_INT_EN = I2C_MASK; | 532 | CPU_HI_INT_EN = I2C_MASK; |
407 | #endif /* CONFIG_KEYPAD */ | ||
408 | 533 | ||
534 | #elif CONFIG_KEYPAD == IPOD_3G_PAD | ||
535 | outb(~inb(GPIOA_INPUT_VAL), GPIOA_INT_LEV); | ||
536 | outb(inb(GPIOA_INT_STAT), GPIOA_INT_CLR); | ||
537 | outb(0xff, GPIOA_INT_EN); | ||
538 | |||
539 | #endif /* CONFIG_KEYPAD */ | ||
409 | queue_init(&button_queue); | 540 | queue_init(&button_queue); |
410 | button_read(); | 541 | button_read(); |
411 | lastbtn = button_read(); | 542 | lastbtn = button_read(); |
@@ -418,7 +549,7 @@ void button_init(void) | |||
418 | } | 549 | } |
419 | 550 | ||
420 | #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ | 551 | #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ |
421 | #if (CONFIG_KEYPAD != IPOD_4G_PAD) | 552 | #if (CONFIG_KEYPAD != IPOD_3G_PAD) && (CONFIG_KEYPAD != IPOD_4G_PAD) |
422 | /* | 553 | /* |
423 | * helper function to swap UP/DOWN, LEFT/RIGHT (and F1/F3 for Recorder) | 554 | * helper function to swap UP/DOWN, LEFT/RIGHT (and F1/F3 for Recorder) |
424 | */ | 555 | */ |
@@ -883,7 +1014,7 @@ static int button_read(void) | |||
883 | if (data & 0x01) | 1014 | if (data & 0x01) |
884 | btn |= BUTTON_ON; | 1015 | btn |= BUTTON_ON; |
885 | 1016 | ||
886 | #elif CONFIG_KEYPAD == IPOD_4G_PAD | 1017 | #elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) |
887 | (void)data; | 1018 | (void)data; |
888 | /* The int_btn variable is set in the button interrupt handler */ | 1019 | /* The int_btn variable is set in the button interrupt handler */ |
889 | btn = int_btn; | 1020 | btn = int_btn; |