1/* Copyright (C) 2007-2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10** GNU General Public License for more details.
11*/
12#include "android/hw-events.h"
13#include "android/utils/bufprint.h"
14#include <stdlib.h>
15#include <string.h>
16
17typedef struct {
18    const char*  name;
19    int          value;
20} EventInfo;
21
22#define  EV_TYPE(n,v)   { "EV_" STRINGIFY(n), (v) },
23
24#define  BTN_CODE(n,v)  { "BTN_" STRINGIFY(n), (v) },
25#define  KEY_CODE(n,v)  { "KEY_" STRINGIFY(n), (v) },
26#define  REL_CODE(n,v)  { "REL_" STRINGIFY(n), (v) },
27#define  ABS_CODE(n,v)  { "ABS_" STRINGIFY(n), (v) },
28#define  END_CODE       { NULL, 0 }
29
30static const EventInfo  _ev_types_tab[] =
31{
32    EVENT_TYPE_LIST
33    END_CODE
34};
35
36static const EventInfo _key_codes_list[] =
37{
38    EVENT_KEY_LIST
39    EVENT_BTN_LIST
40    END_CODE
41};
42
43static const EventInfo _rel_codes_list[] =
44{
45    EVENT_REL_LIST
46    END_CODE
47};
48static const EventInfo _abs_codes_list[] =
49{
50    EVENT_ABS_LIST
51    END_CODE
52};
53
54#undef EV_TYPE
55#undef BTN_CODE
56#undef KEY_CODE
57#undef REL_CODE
58#undef ABS_CODE
59
60typedef const EventInfo*  EventList;
61
62typedef struct {
63    int               type;
64    const EventInfo*  table;
65} EventCodeList;
66
67
68static const EventCodeList  _codes[] = {
69    { EV_KEY, _key_codes_list },
70    { EV_REL, _rel_codes_list },
71    { EV_ABS, _abs_codes_list },
72    { -1, NULL }
73};
74
75static EventList
76eventList_findByType( int  type )
77{
78    int  nn;
79
80    for (nn = 0; _codes[nn].type >= 0; nn++) {
81        if (_codes[nn].type == type)
82            return _codes[nn].table;
83    }
84    return NULL;
85}
86
87static int
88eventList_getCount( EventList  list )
89{
90    int  nn;
91
92    if (list == NULL)
93        return 0;
94
95    for (nn = 0; list[nn].name != NULL; nn++) {
96        /* nothing */
97    }
98    return nn;
99}
100
101static int
102eventList_findCodeByName( EventList    list,
103                          const char*  name,
104                          int          namelen )
105{
106    if (namelen <= 0)
107        return -1;
108
109    for ( ; list->name != NULL; list += 1 ) {
110        if ( !memcmp(name, list->name, namelen) &&
111             list->name[namelen] == 0 )
112        {
113            return list->value;
114        }
115    }
116    return -1;
117}
118
119static char*
120eventList_bufprintCode( EventList  list,
121                        int        index,
122                        char*      buf,
123                        char*      bufend )
124{
125    if (list == NULL)
126        return buf;
127
128    return bufprint(buf, bufend, "%s", list[index].name);
129}
130
131
132int
133android_event_from_str( const char*  name,
134                        int         *ptype,
135                        int         *pcode,
136                        int         *pvalue )
137{
138    const char*  p;
139    const char*  pend;
140    const char*  q;
141    EventList    list;
142    char*        end;
143
144    *ptype  = 0;
145    *pcode  = 0;
146    *pvalue = 0;
147
148    p    = name;
149    pend = p + strcspn(p, " \t");
150    q    = strchr(p, ':');
151    if (q == NULL || q > pend)
152        q = pend;
153
154    *ptype = eventList_findCodeByName( _ev_types_tab, p, q-p );
155    if (*ptype < 0) {
156        *ptype = (int) strtol( p, &end, 0 );
157        if (end != q)
158            return -1;
159    }
160
161    if (*q != ':')
162        return 0;
163
164    p = q + 1;
165    q = strchr(p, ':');
166    if (q == NULL || q > pend)
167        q = pend;
168
169    list   = eventList_findByType( *ptype );
170    if (list == NULL) {
171        *pcode = -1;
172    } else {
173        *pcode = eventList_findCodeByName( list, p, q-p );
174    }
175    if (*pcode < 0) {
176        *pcode = (int) strtol( p, &end, 0 );
177        if (end != q)
178            return -2;
179    }
180
181    if (*q != ':')
182        return 0;
183
184    p = q + 1;
185    q = strchr(p, ':');
186    if (q == NULL || q > pend)
187        q = pend;
188
189    *pvalue = (int)strtol( p, &end, 0 );
190    if (end != q)
191        return -3;
192
193    return 0;
194}
195
196int
197android_event_get_type_count( void )
198{
199    return eventList_getCount( _ev_types_tab );
200}
201
202char*
203android_event_bufprint_type_str( char*  buff, char*  end, int  type_index )
204{
205    return eventList_bufprintCode( _ev_types_tab, type_index, buff, end );
206}
207
208/* returns the list of valid event code string aliases for a given event type */
209int
210android_event_get_code_count( int  type )
211{
212    EventList  list = eventList_findByType(type);
213
214    return eventList_getCount(list);
215}
216
217char*
218android_event_bufprint_code_str( char*  buff, char*  end, int  type, int  code_index )
219{
220    EventList  list = eventList_findByType(type);
221
222    return eventList_bufprintCode(list, code_index, buff, end);
223}
224
225