RDK Documentation (Open Sourced RDK Components)
uinput.c
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2018 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 /*
20  * Reference implementation to dispatch IR events into /dev/uinput
21  * May switch to use libevdev in the future.
22  */
23 
24 #include <linux/uinput.h>
25 #include <linux/input.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30 
31 #include "irMgrInternal.h"
32 #if defined _SKQ_KEY_MAP_1_
33  #include "IrInputRemoteKeyCodes_SkyQ.h"
34 #else
35  #include "IrInputRemoteKeyCodes.h"
36 #endif /*End of _SKQ_KEY_MAP_1_*/
37 
38 #define UINPUT_SETUP_ID(uidev) \
39 do {\
40  memset(&uidev, 0, sizeof(uidev));\
41  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-remote");\
42  uidev.id.bustype = BUS_USB;\
43  uidev.id.vendor = 0x1234;\
44  uidev.id.product = 0xfedc;\
45  uidev.id.version = 1;\
46 } while(0)
47 
48 #define UINPUT_SETUP_ID_SKY_KEYSIM(uidev) \
49 do {\
50  memset(&uidev, 0, sizeof(uidev));\
51  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "key-simulator");\
52  uidev.id.bustype = BUS_USB;\
53  uidev.id.vendor = 0xbeef;\
54  uidev.id.product = 0xfedc;\
55  uidev.id.version = 1;\
56 } while(0)
57 
58 
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 static int devFd = -1;
63 static uint32_t getKeyCode(uint32_t keycode, uint32_t *uCode, uint32_t *uModi)
64 {
65  unsigned char i;
66 
67  printf("%s %d uinput received Key code %d 0x%x \r\n", __FUNCTION__, __LINE__, keycode, keycode);
68  for (i=0; i < (sizeof(kcodesMap_IARM2Linux)/sizeof(kcodesMap_IARM2Linux[0])); i++)
69  {
70  if (kcodesMap_IARM2Linux[i].iCode == keycode)
71  {
72  *uCode = kcodesMap_IARM2Linux[i].uCode;
73  *uModi = kcodesMap_IARM2Linux[i].uModi;
74  return kcodesMap_IARM2Linux[i].uCode;
75  }
76  }
77 
78  printf("UNrecognized Key code %d \r\n", keycode);
79  return KED_UNDEFINEDKEY;
80 }
81 
82 
83 static uint32_t getKeyValue(uint32_t keyType)
84 {
85  switch (keyType)
86  {
87  case KET_KEYDOWN:
88  return 1;
89  case KET_KEYUP:
90  return 0;
91  case KET_KEYREPEAT:
92  return 2;
93  default:
94  printf("UNrecognized Key type %d \r\n", keyType);
95  }
96 
97  return 0;
98 }
99 
100 static void udispatcher_internal(int code, int value)
101 {
102  int ret = -1;
103  struct input_event ev;
104  memset(&ev, 0, sizeof(ev));
105  gettimeofday(&ev.time, NULL);
106  ev.type = EV_KEY;
107  ev.code = code;
108  ev.value = value;
109  ret = write(devFd, &ev, sizeof(ev));
110  if (ret == sizeof(ev)) {
111  /* reuse same timestamp */
112  ev.type = EV_SYN;
113  ev.code = SYN_REPORT;
114  ev.value = 0;
115  ret = write(devFd, &ev, sizeof(ev));
116  }
117  else {
118  perror("uinput write key failed\r\n");
119  UINPUT_term();
120  }
121 }
122 
123 #if defined _SKQ_KEY_MAP_1_
124 static void udispatcherScancode_internal(int scancode, int code, int value)
125 {
126  int ret = -1;
127  struct input_event ev;
128  memset(&ev, 0, sizeof(ev));
129  gettimeofday(&ev.time, NULL);
130  ev.type = EV_MSC;
131  ev.code = MSC_SCAN;
132  ev.value = scancode;
133  ret = write(devFd, &ev, sizeof(ev));
134  if (ret == sizeof(ev)) {
135  ev.type = EV_KEY;
136  ev.code = code;
137  ev.value = value;
138  ret = write(devFd, &ev, sizeof(ev));
139  if (ret == sizeof(ev)) {
140  /* reuse same timestamp */
141  ev.type = EV_SYN;
142  ev.code = SYN_REPORT;
143  ev.value = 0;
144  ret = write(devFd, &ev, sizeof(ev));
145  }
146  else {
147  perror("uinput write key failed\r\n");
148  UINPUT_term();
149  }
150  }
151  else
152  {
153  perror("uinput write key failed\r\n");
154  UINPUT_term();
155  }
156 }
157 #endif /*End of _SKQ_KEY_MAP_1_*/
158 
159 static void udispatcher (int keyCode, int keyType, int source)
160 {
161  printf("%s %d uinput received Key code= %d 0x%x keyType= %d 0x%x \r\n", __FUNCTION__, __LINE__, keyCode, keyCode, keyType, keyType);
162  if (devFd >= 0) {
163  static const char * type2str[] = {"KEY_UP", "KEY_DOWN", "KEY_REPEAT"};
164  uint32_t uCode = _KEY_INVALID;
165  uint32_t uModi = _KEY_INVALID;
166  uint32_t value = 0;
167 
168  getKeyCode(keyCode, &uCode, &uModi);
169  value = getKeyValue(keyType);
170  printf("IR-Keyboard Regular Key: IR=%x key=%x Modifier=%x val=%x [%s]\r\n", keyCode, uCode, uModi, value, type2str[value]);
171  /*
172  * Send Modifier KEY_DOWN and KEY_UP event
173  * along with keycode's DOWN and UP event.
174  *
175  * Do not send Modifier on REPEAT event.
176  */
177  if ((keyType == KET_KEYDOWN)) {
178  if (uModi != _KEY_INVALID) {
179  udispatcher_internal(uModi, value);
180  }
181  }
182  udispatcher_internal((int)uCode, (int)value);
183  if ((keyType == KET_KEYUP)) {
184  if (uModi != _KEY_INVALID) {
185  udispatcher_internal(uModi, value);
186  }
187  }
188  }
189 }
190 
191 #if defined _SKQ_KEY_MAP_1_
192 static void udispatcherScancode (int scanCode, int keyCode, int keyType, int source)
193 {
194  printf("%s %d uinput received Key code= %d 0x%x keyType= %d 0x%x \r\n", __FUNCTION__, __LINE__, keyCode, keyCode, keyType, keyType);
195  if (devFd >= 0) {
196  static const char * type2str[] = {"KEY_UP", "KEY_DOWN", "KEY_REPEAT"};
197  uint32_t uCode = _KEY_INVALID;
198  uint32_t uModi = _KEY_INVALID;
199  uint32_t value = 0;
200 
201  getKeyCode(keyCode, &uCode, &uModi);
202  value = getKeyValue(keyType);
203  printf("IR-Keyboard Regular Key: IR=%x key=%x Modifier=%x val=%x [%s]\r\n", keyCode, uCode, uModi, value, type2str[value]);
204  /*
205  * Send Modifier KEY_DOWN and KEY_UP event
206  * along with keycode's DOWN and UP event.
207  *
208  * Do not send Modifier on REPEAT event.
209  */
210  if ((keyType == KET_KEYDOWN)) {
211  if (uModi != _KEY_INVALID) {
212  udispatcherScancode_internal(scanCode, uModi, value);
213  }
214  }
215  udispatcherScancode_internal(scanCode, (int)uCode, (int)value);
216  if ((keyType == KET_KEYUP)) {
217  if (uModi != _KEY_INVALID) {
218  udispatcherScancode_internal(scanCode, uModi, value);
219  }
220  }
221  }
222 }
223 #endif /*End of _SKQ_KEY_MAP_1_*/
224 
226 {
227  return UINPUT_init_src (IRMGR_UINPUT_SRC_IRMGR);
228 }
229 
230 int UINPUT_init_src(IRMg_UINPUT_Src_t eSrc)
231 {
232 #ifndef UINPUT_VERSION
233 #define UINPUT_VERSION (0)
234 #endif
235 
236  int fd = -1;
237  int ret = -1;
238  fd = open("/dev/uinput", O_WRONLY|O_SYNC);
239  if (fd >= 0) {
240  printf("Linux uinput version [%d] is built-in with kernel\r\n", UINPUT_VERSION);
241  /* Fist setup input capabilities*/
242  {
243  //Add event types
244  ret = ioctl(fd, UI_SET_EVBIT, EV_KEY);
245  ret = ioctl(fd, UI_SET_EVBIT, EV_SYN);
246 #if defined _SKQ_KEY_MAP_1_
247  ret = ioctl(fd, UI_SET_EVBIT, EV_MSC);
248  ret = ioctl(fd, UI_SET_MSCBIT, MSC_SCAN);
249 #endif /*End of _SKQ_KEY_MAP_1_*/
250  }
251 
252  if (ret == 0)
253  {
254  //Add keycodes
255  for (size_t i = 0; i < sizeof(kcodesMap_IARM2Linux)/sizeof(kcodesMap_IARM2Linux[0]); i++) {
256  ret = ioctl(fd, UI_SET_KEYBIT, kcodesMap_IARM2Linux[i].uCode);
257  if (kcodesMap_IARM2Linux[i].uModi != _KEY_INVALID) {
258  ret = ioctl(fd, UI_SET_KEYBIT, kcodesMap_IARM2Linux[i].uModi);
259  }
260  }
261  }
262  /* Then setup input id*/
263 #if defined UINPUT_VERSION && (UINPUT_VERSION >= 5)
264  if (ret == 0)
265  {
266  struct uinput_setup usetup;
267  if (IRMGR_UINPUT_SRC_KEYSIM == eSrc) {
268 #if defined _SKQ_KEY_MAP_1_
269  UINPUT_SETUP_ID_SKY_KEYSIM(usetup);
270 #else
271  UINPUT_SETUP_ID(usetup);
272 #endif /*End of _SKQ_KEY_MAP_1_*/
273  }
274  else {
275  UINPUT_SETUP_ID(usetup);
276  }
277  ret = ioctl(fd, UI_DEV_SETUP, &usetup);
278  }
279 #else
280  if (ret == 0)
281  {
282  /* Legacy uinput appraoch */
283  struct uinput_user_dev uidev;
284  if (IRMGR_UINPUT_SRC_KEYSIM == eSrc) {
285 #if defined _SKQ_KEY_MAP_1_
286  UINPUT_SETUP_ID_SKY_KEYSIM(uidev);
287 #else
288  UINPUT_SETUP_ID(uidev);
289 #endif /*End of _SKQ_KEY_MAP_1_*/
290  }
291  else {
292  UINPUT_SETUP_ID(uidev);
293  }
294  ret = write(fd, &uidev, sizeof(uidev));
295  printf("write uinput_user_dev return %d vs %d\r\n", ret, sizeof(uidev));
296  ret = ((ret == sizeof(uidev)) ? 0 : -1);
297  }
298 #endif
299  /* Now setup complete, create the device*/
300  if (ret == 0)
301  {
302  ret = ioctl(fd, UI_DEV_CREATE, 0);
303  }
304 
305  if (ret != 0)
306  {
307  perror("uinput setup failed\r\n");
308  if (fd >= 0) {
309  ret = ioctl(fd, UI_DEV_DESTROY, 0);
310  close(fd);
311  }
312  fd = -1;
313  }
314  else {
315  }
316  }
317  else {
318  printf("Linux uinput is not built-in with kernel\r\n");
319  }
320 
321  devFd = fd;
322  return 0;
323 }
324 
325 uinput_dispatcher_t UINPUT_GetDispatcher(void)
326 {
327  if (devFd >= 0) return udispatcher;
328  else return NULL;
329 }
330 
331 #if defined _SKQ_KEY_MAP_1_
332 uinput_dispatcherScancode_t UINPUT_GetDispatcherScancode(void)
333 {
334  if (devFd >= 0) return udispatcherScancode;
335  else return NULL;
336 }
337 #endif
338 
340 {
341  if (devFd >= 0)
342  {
343  ioctl(devFd, UI_DEV_DESTROY);
344  close(devFd);
345  }
346 
347  devFd = -1;
348  return 0;
349 }
350 #ifdef __cplusplus
351 }
352 #endif
UINPUT_init
int UINPUT_init()
uinput module init.
Definition: uinput.c:225
irMgrInternal.h
IARM-Bus IR Manager Internal API.
IrInputRemoteKeyCodes.h
Map IR Remote Keys to standard Linux Input Keys.
UINPUT_GetDispatcher
uinput_dispatcher_t UINPUT_GetDispatcher(void)
get the dispather that will listen for IARM IR
Definition: uinput.c:325
keyType
Definition: reset.c:85
UINPUT_term
int UINPUT_term()
uinput module term.
Definition: uinput.c:339