| /* Copyright (C) 2007-2008 The Android Open Source Project |
| ** |
| ** This software is licensed under the terms of the GNU General Public |
| ** License version 2, as published by the Free Software Foundation, and |
| ** may be copied, distributed, and modified under those terms. |
| ** |
| ** This program is distributed in the hope that it will be useful, |
| ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
| ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| ** GNU General Public License for more details. |
| */ |
| #include "android/hw-events.h" |
| #include "android/utils/bufprint.h" |
| #include <stdlib.h> |
| #include <string.h> |
| |
| typedef struct { |
| const char* name; |
| int value; |
| } EventInfo; |
| |
| #define EV_TYPE(n,v) { "EV_" STRINGIFY(n), (v) }, |
| |
| #define BTN_CODE(n,v) { "BTN_" STRINGIFY(n), (v) }, |
| #define KEY_CODE(n,v) { "KEY_" STRINGIFY(n), (v) }, |
| #define REL_CODE(n,v) { "REL_" STRINGIFY(n), (v) }, |
| #define ABS_CODE(n,v) { "ABS_" STRINGIFY(n), (v) }, |
| #define END_CODE { NULL, 0 } |
| |
| static const EventInfo _ev_types_tab[] = |
| { |
| EVENT_TYPE_LIST |
| END_CODE |
| }; |
| |
| static const EventInfo _key_codes_list[] = |
| { |
| EVENT_KEY_LIST |
| EVENT_BTN_LIST |
| END_CODE |
| }; |
| |
| static const EventInfo _rel_codes_list[] = |
| { |
| EVENT_REL_LIST |
| END_CODE |
| }; |
| static const EventInfo _abs_codes_list[] = |
| { |
| EVENT_ABS_LIST |
| END_CODE |
| }; |
| |
| #undef EV_TYPE |
| #undef BTN_CODE |
| #undef KEY_CODE |
| #undef REL_CODE |
| #undef ABS_CODE |
| |
| typedef const EventInfo* EventList; |
| |
| typedef struct { |
| int type; |
| const EventInfo* table; |
| } EventCodeList; |
| |
| |
| static const EventCodeList _codes[] = { |
| { EV_KEY, _key_codes_list }, |
| { EV_REL, _rel_codes_list }, |
| { EV_ABS, _abs_codes_list }, |
| { -1, NULL } |
| }; |
| |
| static EventList |
| eventList_findByType( int type ) |
| { |
| int nn; |
| |
| for (nn = 0; _codes[nn].type >= 0; nn++) { |
| if (_codes[nn].type == type) |
| return _codes[nn].table; |
| } |
| return NULL; |
| } |
| |
| static int |
| eventList_getCount( EventList list ) |
| { |
| int nn; |
| |
| if (list == NULL) |
| return 0; |
| |
| for (nn = 0; list[nn].name != NULL; nn++) { |
| /* nothing */ |
| } |
| return nn; |
| } |
| |
| static int |
| eventList_findCodeByName( EventList list, |
| const char* name, |
| int namelen ) |
| { |
| if (namelen <= 0) |
| return -1; |
| |
| for ( ; list->name != NULL; list += 1 ) { |
| if ( !memcmp(name, list->name, namelen) && |
| list->name[namelen] == 0 ) |
| { |
| return list->value; |
| } |
| } |
| return -1; |
| } |
| |
| static char* |
| eventList_bufprintCode( EventList list, |
| int index, |
| char* buf, |
| char* bufend ) |
| { |
| if (list == NULL) |
| return buf; |
| |
| return bufprint(buf, bufend, "%s", list[index].name); |
| } |
| |
| |
| int |
| android_event_from_str( const char* name, |
| int *ptype, |
| int *pcode, |
| int *pvalue ) |
| { |
| const char* p; |
| const char* pend; |
| const char* q; |
| EventList list; |
| char* end; |
| |
| *ptype = 0; |
| *pcode = 0; |
| *pvalue = 0; |
| |
| p = name; |
| pend = p + strcspn(p, " \t"); |
| q = strchr(p, ':'); |
| if (q == NULL || q > pend) |
| q = pend; |
| |
| *ptype = eventList_findCodeByName( _ev_types_tab, p, q-p ); |
| if (*ptype < 0) { |
| *ptype = (int) strtol( p, &end, 0 ); |
| if (end != q) |
| return -1; |
| } |
| |
| if (*q != ':') |
| return 0; |
| |
| p = q + 1; |
| q = strchr(p, ':'); |
| if (q == NULL || q > pend) |
| q = pend; |
| |
| list = eventList_findByType( *ptype ); |
| if (list == NULL) { |
| *pcode = -1; |
| } else { |
| *pcode = eventList_findCodeByName( list, p, q-p ); |
| } |
| if (*pcode < 0) { |
| *pcode = (int) strtol( p, &end, 0 ); |
| if (end != q) |
| return -2; |
| } |
| |
| if (*q != ':') |
| return 0; |
| |
| p = q + 1; |
| q = strchr(p, ':'); |
| if (q == NULL || q > pend) |
| q = pend; |
| |
| *pvalue = (int)strtol( p, &end, 0 ); |
| if (end != q) |
| return -3; |
| |
| return 0; |
| } |
| |
| int |
| android_event_get_type_count( void ) |
| { |
| return eventList_getCount( _ev_types_tab ); |
| } |
| |
| char* |
| android_event_bufprint_type_str( char* buff, char* end, int type_index ) |
| { |
| return eventList_bufprintCode( _ev_types_tab, type_index, buff, end ); |
| } |
| |
| /* returns the list of valid event code string aliases for a given event type */ |
| int |
| android_event_get_code_count( int type ) |
| { |
| EventList list = eventList_findByType(type); |
| |
| return eventList_getCount(list); |
| } |
| |
| char* |
| android_event_bufprint_code_str( char* buff, char* end, int type, int code_index ) |
| { |
| EventList list = eventList_findByType(type); |
| |
| return eventList_bufprintCode(list, code_index, buff, end); |
| } |
| |