aboutsummaryrefslogtreecommitdiff
path: root/libboot/gpio_keypad.c
diff options
context:
space:
mode:
Diffstat (limited to 'libboot/gpio_keypad.c')
-rw-r--r--libboot/gpio_keypad.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/libboot/gpio_keypad.c b/libboot/gpio_keypad.c
new file mode 100644
index 0000000..b1ec7c2
--- /dev/null
+++ b/libboot/gpio_keypad.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <boot/boot.h>
+#include <boot/gpio.h>
+#include <boot/gpio_keypad.h>
+
+int gpio_keypad_init(gpio_keypad_info *keypad)
+{
+ unsigned i;
+ for(i = 0; i < keypad->noutputs; i++) {
+ gpio_set(keypad->output_gpios[i], keypad->polarity ^ keypad->drive_inactive_outputs);
+ gpio_dir(keypad->output_gpios[i], keypad->drive_inactive_outputs);
+ }
+ for(i = 0; i < keypad->ninputs; i++) {
+ gpio_dir(keypad->input_gpios[i], 0);
+ }
+ keypad->state = 0;
+ return 0;
+}
+
+void gpio_keypad_scan_keys(gpio_keypad_info *keypad)
+{
+ unsigned out, in;
+ unsigned long long keys;
+ unsigned npolarity = !keypad->polarity;
+ unsigned int shift;
+
+ keys = 0;
+ out = keypad->noutputs;
+ shift = keypad->noutputs * keypad->ninputs;
+ while(out > 0) {
+ out--;
+ if(keypad->drive_inactive_outputs)
+ gpio_set(keypad->output_gpios[out], !npolarity);
+ else
+ gpio_dir(keypad->output_gpios[out], 1);
+ udelay(keypad->settle_time);
+ in = keypad->ninputs;
+ while(in > 0) {
+ in--;
+ shift--;
+ keys = (keys << 1) | (gpio_get(keypad->input_gpios[in]) ^ npolarity);
+ if(((unsigned)(keypad->state >> shift) ^ (unsigned)keys) & 1) {
+ unsigned int mapped_key = 0;
+ if(keypad->key_map)
+ mapped_key = keypad->key_map[shift];
+ //dprintf("gpio_keypad_scan_keys: %d-%d (%d-%d) %d (%d): %d\n", out, in,
+ // keypad->output_gpios[out], keypad->input_gpios[in],
+ // shift, mapped_key, keys & 1);
+ if(mapped_key && key_changed)
+ key_changed(mapped_key, keys & 1);
+ }
+ }
+ if(keypad->drive_inactive_outputs)
+ gpio_set(keypad->output_gpios[out], npolarity);
+ else
+ gpio_dir(keypad->output_gpios[out], 0);
+ }
+ if(keys != keypad->state) {
+ keypad->state = keys;
+ //dprintf("gpio_keypad_scan_keys: %x %x\n", (unsigned long)(keys >> 32), (unsigned long)keys);
+ }
+}
+