/* * 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); } }