summaryrefslogtreecommitdiff
path: root/firmware/drivers/button.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/button.c')
-rw-r--r--firmware/drivers/button.c139
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 */
226int int_btn = BUTTON_NONE;
223 227
228/**
229 *
230 *
231 */
232void 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
278static int ipod_3g_button_read(void)
279{
280 unsigned char source, state;
281 static int was_hold = 0;
282int 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
340void 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
224static void button_tick(void) 350static 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;