Home | History | Annotate | Download | only in libboot
      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