static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer) { int i; int pressed; struct gpio_input_state *ds = container_of(timer, struct gpio_input_state, timer); unsigned gpio_flags = ds->info->flags; unsigned npolarity; int nkeys = ds->info->keymap_size; const struct gpio_event_direct_entry *key_entry; struct gpio_key_state *key_state; unsigned long irqflags; uint8_t debounce; bool sync_needed; #if 0 key_entry = kp->keys_info->keymap; key_state = kp->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, gpio_read_detect_status(key_entry->gpio)); #endif key_entry = ds->info->keymap; key_state = ds->key_state; sync_needed = false; spin_lock_irqsave(&ds->irq_lock, irqflags); for (i = 0; i < nkeys; i++, key_entry++, key_state++) { debounce = key_state->debounce; if (debounce & DEBOUNCE_WAIT_IRQ) continue; if (key_state->debounce & DEBOUNCE_UNSTABLE) { debounce = key_state->debounce = DEBOUNCE_UNKNOWN; enable_irq(gpio_to_irq(key_entry->gpio)); KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) continue debounce\n", ds->info->type, key_entry->code, i, key_entry->gpio); } npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH); pressed = gpio_get_value_cansleep(key_entry->gpio) ^ npolarity; if (debounce & DEBOUNCE_POLL) { if (pressed == !(debounce & DEBOUNCE_PRESSED)) { ds->debounce_count++; key_state->debounce = DEBOUNCE_UNKNOWN; if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-" "%x, %d (%d) start debounce\n", ds->info->type, key_entry->code, i, key_entry->gpio); } continue; } if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) { if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) debounce pressed 1\n", ds->info->type, key_entry->code, i, key_entry->gpio); key_state->debounce = DEBOUNCE_PRESSED; continue; } if (!pressed && (debounce & DEBOUNCE_PRESSED)) { if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) debounce pressed 0\n", ds->info->type, key_entry->code, i, key_entry->gpio); key_state->debounce = DEBOUNCE_NOTPRESSED; continue; } /* key is stable */ ds->debounce_count--; if (ds->use_irq) key_state->debounce |= DEBOUNCE_WAIT_IRQ; else key_state->debounce |= DEBOUNCE_POLL; if (gpio_flags & GPIOEDF_PRINT_KEYS) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d (%d) " "changed to %d\n", ds->info->type, key_entry->code, i, key_entry->gpio, pressed); #ifdef CONFIG_POWER_KEY_LED handle_power_key_led(key_entry->code, pressed); #endif input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, key_entry->code, pressed); sync_needed = true; } if (sync_needed) { for (i = 0; i < ds->input_devs->count; i++) input_sync(ds->input_devs->dev[i]); } #if 0 key_entry = kp->keys_info->keymap; key_state = kp->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, gpio_read_detect_status(key_entry->gpio)); } #endif if (ds->debounce_count) hrtimer_start(timer, ds->info->debounce_time, HRTIMER_MODE_REL); else if (!ds->use_irq) hrtimer_start(timer, ds->info->poll_time, HRTIMER_MODE_REL); else wake_unlock(&ds->wake_lock); spin_unlock_irqrestore(&ds->irq_lock, irqflags); return HRTIMER_NORESTART; }
static void gpio_event_input_delayed_func(struct work_struct *key_work) { int i; int pressed; struct gpio_input_state *ds = container_of((struct delayed_work *)key_work, struct gpio_key_state, key_work)->ds; unsigned npolarity; unsigned gpio_flags = ds->info->flags; int nkeys = ds->info->keymap_size; const struct gpio_event_direct_entry *key_entry; struct gpio_key_state *key_state; unsigned long irqflags; uint8_t debounce; bool sync_needed; key_entry = ds->info->keymap; key_state = ds->key_state; npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH); for (i = 0; i < nkeys; i++, key_entry++, key_state++) { key_state->keyValue = gpio_get_value(key_entry->gpio) ^ npolarity; key_state->irq_enable_needed = 0; key_state->need_queue = 0; } #ifdef KEYPAD_DEBUG KEY_LOGD("Before process: \n"); print_key_ds(ds); #endif key_entry = ds->info->keymap; key_state = ds->key_state; sync_needed = false; spin_lock_irqsave(&ds->irq_lock, irqflags); for (i = 0; i < nkeys; i++, key_entry++, key_state++) { debounce = key_state->debounce; if (debounce & DEBOUNCE_WAIT_IRQ) continue; if (key_state->debounce & DEBOUNCE_UNSTABLE) { debounce = key_state->debounce = DEBOUNCE_UNKNOWN; key_state->irq_enable_needed = 1; if (gpio_flags & GPIOEDF_PRINT_KEY_UNSTABLE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) continue debounce," #ifdef KEYPAD_DEBUG " enable irq#%d\n" #endif , ds->info->type, key_entry->code, i, key_entry->gpio #ifdef KEYPAD_DEBUG , gpio_to_irq(key_entry->gpio) #endif ); } pressed = key_state->keyValue; if (debounce & DEBOUNCE_POLL) { if (pressed == !(debounce & DEBOUNCE_PRESSED)) { ds->debounce_count++; key_state->need_queue = 1; key_state->debounce = DEBOUNCE_UNKNOWN; if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-" "%x, %d (%d) start debounce\n", ds->info->type, key_entry->code, i, key_entry->gpio); } continue; } if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) { if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) debounce pressed 1\n", ds->info->type, key_entry->code, i, key_entry->gpio); key_state->debounce = DEBOUNCE_PRESSED; key_state->need_queue = 1; continue; } if (!pressed && (debounce & DEBOUNCE_PRESSED)) { if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d " "(%d) debounce pressed 0\n", ds->info->type, key_entry->code, i, key_entry->gpio); key_state->debounce = DEBOUNCE_NOTPRESSED; key_state->need_queue = 1; continue; } /* key is stable */ ds->debounce_count--; if (ds->use_irq) key_state->debounce |= DEBOUNCE_WAIT_IRQ; else key_state->debounce |= DEBOUNCE_POLL; if (gpio_flags & GPIOEDF_PRINT_KEYS) KEY_LOGD("gpio_keys_scan_keys: key %x-%x, %d (%d) " "changed to %d\n", ds->info->type, key_entry->code, i, key_entry->gpio, pressed); #ifdef CONFIG_POWER_KEY_LED handle_power_key_led(key_entry->code, pressed); #endif input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, key_entry->code, pressed); sync_needed = true; } if (sync_needed) { for (i = 0; i < ds->input_devs->count; i++) input_sync(ds->input_devs->dev[i]); } #if 0 key_entry = kp->keys_info->keymap; key_state = kp->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, gpio_read_detect_status(key_entry->gpio)); } #endif if (ds->debounce_count) { key_entry = ds->info->keymap; key_state = ds->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { if (key_state->need_queue) if (!queue_delayed_work(ki_queue, &(key_state->key_work), KTIME_TO_JIFFIES(ds->info->debounce_time))) KEY_LOGI("Keycode: 0x%X has been queued already.\n", key_entry->code); } } else if (!ds->use_irq) { key_entry = ds->info->keymap; key_state = ds->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) { if (key_state->need_queue) if (!queue_delayed_work(ki_queue, &(key_state->key_work), KTIME_TO_JIFFIES(ds->info->poll_time))) KEY_LOGI("Keycode: 0x%X has been queued already.\n", key_entry->code); } } else wake_unlock(&ds->wake_lock); spin_unlock_irqrestore(&ds->irq_lock, irqflags); #if 0 key_entry = ds->info->keymap; key_state = ds->key_state; for (i = 0; i < nkeys; i++, key_entry++, key_state++) if (key_state->irq_enable_needed) enable_irq(gpio_to_irq(key_entry->gpio)); #endif #ifdef KEYPAD_DEBUG KEY_LOGD("After process:\n"); print_key_ds(ds); #endif }