1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <boot/boot.h> 30 #include <boot/gpio.h> 31 #include <boot/gpio_keypad.h> 32 33 int gpio_keypad_init(gpio_keypad_info *keypad) 34 { 35 unsigned i; 36 for(i = 0; i < keypad->noutputs; i++) { 37 gpio_set(keypad->output_gpios[i], keypad->polarity ^ keypad->drive_inactive_outputs); 38 gpio_dir(keypad->output_gpios[i], keypad->drive_inactive_outputs); 39 } 40 for(i = 0; i < keypad->ninputs; i++) { 41 gpio_dir(keypad->input_gpios[i], 0); 42 } 43 keypad->state = 0; 44 return 0; 45 } 46 47 void gpio_keypad_scan_keys(gpio_keypad_info *keypad) 48 { 49 unsigned out, in; 50 unsigned long long keys; 51 unsigned npolarity = !keypad->polarity; 52 unsigned int shift; 53 54 keys = 0; 55 out = keypad->noutputs; 56 shift = keypad->noutputs * keypad->ninputs; 57 while(out > 0) { 58 out--; 59 if(keypad->drive_inactive_outputs) 60 gpio_set(keypad->output_gpios[out], !npolarity); 61 else 62 gpio_dir(keypad->output_gpios[out], 1); 63 udelay(keypad->settle_time); 64 in = keypad->ninputs; 65 while(in > 0) { 66 in--; 67 shift--; 68 keys = (keys << 1) | (gpio_get(keypad->input_gpios[in]) ^ npolarity); 69 if(((unsigned)(keypad->state >> shift) ^ (unsigned)keys) & 1) { 70 unsigned int mapped_key = 0; 71 if(keypad->key_map) 72 mapped_key = keypad->key_map[shift]; 73 //dprintf("gpio_keypad_scan_keys: %d-%d (%d-%d) %d (%d): %d\n", out, in, 74 // keypad->output_gpios[out], keypad->input_gpios[in], 75 // shift, mapped_key, keys & 1); 76 if(mapped_key && key_changed) 77 key_changed(mapped_key, keys & 1); 78 } 79 } 80 if(keypad->drive_inactive_outputs) 81 gpio_set(keypad->output_gpios[out], npolarity); 82 else 83 gpio_dir(keypad->output_gpios[out], 0); 84 } 85 if(keys != keypad->state) { 86 keypad->state = keys; 87 //dprintf("gpio_keypad_scan_keys: %x %x\n", (unsigned long)(keys >> 32), (unsigned long)keys); 88 } 89 } 90 91