2 * Copyright © 2013 TOYOTA MOTOR CORPORATION.
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * @brief System Test Tool for send device input event
35 #include <sys/ioctl.h>
39 #include <sys/types.h>
43 #include <linux/input.h>
44 #include <linux/uinput.h>
45 #include <linux/joystick.h>
49 #define SPECIALTYPE_XY 9991
58 { "X", DEV_TOUCH, EV_ABS, ABS_X, -1 },
59 { "Y", DEV_TOUCH, EV_ABS, ABS_Y, -1 },
60 { "Down", DEV_TOUCH, EV_KEY, BTN_TOUCH, 1 },
61 { "Up", DEV_TOUCH, EV_KEY, BTN_TOUCH, 0 },
62 { "Touch", DEV_TOUCH, EV_KEY, BTN_TOUCH, -1 },
63 { "XY", DEV_TOUCH, SPECIALTYPE_XY, 0, -1 },
64 { "SYN", DEV_TOUCH, 0, 0, 0 },
65 { "Button", DEV_TOUCH, EV_KEY, BTN_LEFT, -1 },
66 { "ButtonOn", DEV_TOUCH, EV_KEY, BTN_LEFT, 1 },
67 { "ButtonOff", DEV_TOUCH, EV_KEY, BTN_LEFT, 0 },
69 { "UpDown", DEV_JS, 2, 3, 1 },
70 { "UD", DEV_JS, 2, 3, 1 },
71 { "LeftRight", DEV_JS, 2, 2, 2 },
72 { "LR", DEV_JS, 2, 2, 2 },
73 { "Cross", DEV_JS, 1, 0, 3 },
74 { "Squere", DEV_JS, 1, 1, 4 },
75 { "Circle", DEV_JS, 1, 2, 5 },
76 { "Triangle", DEV_JS, 1, 3, 6 },
77 { "\0", 0, 0, 0, 0 } };
81 static int mDebug = 0;
83 static int mTouch = 1;
84 static int mWidth = 1080;
85 static int mHeight = 1920;
86 static int mConvert = 0;
88 static void print_log(const char *fmt, ...);
91 term_signal(const int signo)
97 init_mq(const int mqkey)
105 mqid = msgget(mqkey, 0);
107 mqid = msgget(mqkey, IPC_CREAT);
110 print_log("Can not create message queue(%d(0x%x))[%d]",
111 mqkey, mqkey, errno);
115 while (msgrcv(mqid, dummy, sizeof(dummy)-sizeof(long), 0, IPC_NOWAIT) > 0) ;
120 init_device(const char *device)
126 struct uinput_user_dev uinputDevice;
127 uifd = open("/dev/uinput", O_RDWR);
130 print_log("/dev/uinput open error[%d]", errno);
135 memset(&uinputDevice, 0, sizeof(uinputDevice));
136 strncpy(uinputDevice.name, device, UINPUT_MAX_NAME_SIZE-1);
137 uinputDevice.absmax[ABS_X] = mHeight;
138 uinputDevice.absmax[ABS_Y] = mWidth;
140 /* uinput device configuration */
141 if (write(uifd, &uinputDevice, sizeof(uinputDevice)) < (int)sizeof(uinputDevice)) {
142 print_log("/dev/uinput regist error[%d]", errno);
148 /* uinput set event bits */
149 ioctl(uifd, UI_SET_EVBIT, EV_SYN);
151 if ((mTouch != 0) && (mTouch != 3)) {
152 ioctl(uifd, UI_SET_EVBIT, EV_ABS);
153 ioctl(uifd, UI_SET_ABSBIT, ABS_X);
154 ioctl(uifd, UI_SET_ABSBIT, ABS_Y);
155 ioctl(uifd, UI_SET_EVBIT, EV_KEY);
157 ioctl(uifd, UI_SET_KEYBIT, BTN_LEFT);
160 ioctl(uifd, UI_SET_KEYBIT, BTN_TOUCH);
161 ioctl(uifd, UI_SET_KEYBIT, BTN_TOOL_PEN);
165 ioctl(uifd, UI_SET_EVBIT, EV_REL);
166 ioctl(uifd, UI_SET_RELBIT, REL_X);
167 ioctl(uifd, UI_SET_RELBIT, REL_Y);
168 ioctl(uifd, UI_SET_RELBIT, REL_Z);
169 ioctl(uifd, UI_SET_RELBIT, REL_RX);
170 ioctl(uifd, UI_SET_RELBIT, REL_RY);
171 ioctl(uifd, UI_SET_RELBIT, REL_RZ);
172 ioctl(uifd, UI_SET_EVBIT, EV_KEY);
173 ioctl(uifd, UI_SET_KEYBIT, KEY_RESERVED);
174 ioctl(uifd, UI_SET_KEYBIT, KEY_ESC);
175 ioctl(uifd, UI_SET_KEYBIT, KEY_1);
176 ioctl(uifd, UI_SET_KEYBIT, KEY_2);
177 ioctl(uifd, UI_SET_KEYBIT, KEY_3);
178 ioctl(uifd, UI_SET_KEYBIT, KEY_4);
179 ioctl(uifd, UI_SET_KEYBIT, KEY_5);
180 ioctl(uifd, UI_SET_KEYBIT, KEY_6);
181 ioctl(uifd, UI_SET_KEYBIT, KEY_7);
182 ioctl(uifd, UI_SET_KEYBIT, KEY_8);
183 ioctl(uifd, UI_SET_KEYBIT, KEY_9);
184 ioctl(uifd, UI_SET_KEYBIT, KEY_0);
187 ioctl(uifd, UI_SET_EVBIT, EV_MSC);
188 ioctl(uifd, UI_SET_MSCBIT, MSC_SCAN);
190 /* create event device */
191 if (ioctl(uifd, UI_DEV_CREATE, NULL) < 0) {
192 print_log("/dev/uinput create error[%d]", errno);
197 print_log("## created event device %s", device);
199 for (ii = 0; ii < 16; ii++) {
200 snprintf(devFile, 64, "/dev/input/event%d", ii);
201 fd = open(devFile, O_RDONLY);
202 if (fd < 0) continue;
204 memset(devName, 0, sizeof(devName));
205 ioctl(fd, EVIOCGNAME(sizeof(devName)), devName);
207 print_log("%d.event device(%s) is %s", ii+1, devFile, devName);
213 convert_value(const char *value, char **errp, int base)
217 for (i = 0; value[i]; i++) {
218 if ((value[i] == ',') || (value[i] == ';') ||
219 (value[i] == ';') || (value[i] == ' ')) {
224 *errp = (char *)&value[i];
227 if ((strncasecmp(value, "on", i) == 0) ||
228 (strncasecmp(value, "true", i) == 0) ||
229 (strncasecmp(value, "push", i) == 0) ||
230 (strncasecmp(value, "down", i) == 0) ||
231 (strncasecmp(value, "right", i) == 0)) {
234 else if ((strncasecmp(value, "off", i) == 0) ||
235 (strncasecmp(value, "false", i) == 0) ||
236 (strncasecmp(value, "pop", i) == 0) ||
237 (strncasecmp(value, "up", i) == 0) ||
238 (strncasecmp(value, "left", i) == 0)) {
241 return strtol(value, (char **)0, 0);
245 send_event(const char *cmd)
253 struct input_event event;
257 for (i = 0; cmd[i]; i++) {
258 if ((cmd[i] == '=') || (cmd[i] == ' ')) break;
259 if (j < (int)(sizeof(prop)-1)) {
267 for (i++; cmd[i]; i++) {
268 if (cmd[i] == ' ') continue;
269 if (j < (int)(sizeof(value)-1)) {
276 if (strcasecmp(prop, "sleep") == 0) {
279 for (i = 0; value[i]; i++) {
280 if (value[i] == '.') break;
281 sec = sec * 10 + (value[i] & 0x0f);
283 if (value[i] == '.') {
286 msec = (value[i] & 0x0f) * 100;
290 msec = msec + (value[i] & 0x0f) * 10;
294 msec = msec + (value[i] & 0x0f);
297 if (sec > 0) sleep(sec);
298 if (msec > 0) usleep(msec * 1000);
303 for (key = 0; event_key[key].prop[0]; key++) {
304 if (strcasecmp(prop, event_key[key].prop) == 0) break;
306 if (! event_key[key].prop[0]) {
307 print_log("UnKnown Event name[%s]", prop);
312 memset(&event, 0, sizeof(event));
313 gettimeofday(&event.time, NULL);
314 if (event_key[key].type == SPECIALTYPE_XY) {
316 if (mConvert) event.code = ABS_Y;
317 else event.code = ABS_X;
318 event.value = convert_value(value, &errp, 0);
320 print_log("Send Event ABS_%c=%d\t# %d.%03d", mConvert ? 'Y' : 'X',
322 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
325 if (write(uifd, &event, sizeof(struct input_event)) < 0) {
326 print_log("event write error 1[%d]", errno);
330 if (mConvert) event.code = ABS_X;
331 else event.code = ABS_Y;
333 event.value = convert_value(errp + 1, (char **)0, 0);
339 event.value = mHeight - event.value - 1;
341 event.time.tv_usec += 200;
342 if (event.time.tv_usec >= 1000000) {
343 event.time.tv_sec ++;
344 event.time.tv_usec -= 1000000;
347 print_log("Send Event ABS_%c=%d\t# %d.%03d", mConvert ? 'X' : 'Y',
349 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
354 event.type = event_key[key].type;
356 if (event_key[key].code == -1) {
357 event.code = convert_value(value, (char **)0, 0);
360 event.code = event_key[key].code;
362 event.value = event_key[key].value;
365 event.value = convert_value(value, (char **)0, 0);
369 if ((event.type == EV_ABS) && (event.code == ABS_X)) {
370 print_log("Send Event X=%d\t# %d.%03d", event.value,
371 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
373 else if ((event.type == EV_ABS) && (event.code == ABS_Y)) {
374 print_log("Send Event Y=%d\t %d.%03d", event.value,
375 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
377 else if ((event.type == EV_KEY) &&
378 (event.code == BTN_TOUCH) && (event.value == 1)) {
379 print_log("Send Event BTN_TOUCH=Down\t# %d.%03d",
380 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
382 else if ((event.type == EV_KEY) &&
383 (event.code == BTN_TOUCH) && (event.value == 0)) {
384 print_log("Send Event BTN_TOUCH=Up\t# %d.%03d",
385 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
387 else if ((event.type == EV_KEY) &&
388 (event.code == BTN_LEFT) && (event.value == 1)) {
389 print_log("Send Event BTN_LEFT=Down\t# %d.%03d",
390 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
392 else if ((event.type == EV_KEY) &&
393 (event.code == BTN_LEFT) && (event.value == 0)) {
394 print_log("Send Event BTN_LEFT=Up\t# %d.%03d",
395 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
398 if ((event.type == EV_REL) && (event.value == 0)) {
401 else if ((event.type == EV_KEY) && (event.code == 0)) {
404 print_log("Send Event type=%d code=%d value=%d\t# %d.%03d",
405 event.type, event.code, event.value,
406 (int)event.time.tv_sec, (int)(event.time.tv_usec/1000));
411 if (write(uifd, &event, sizeof(struct input_event)) < 0) {
412 print_log("event write error 2[%d]", errno);
417 memset(&event, 0, sizeof(event));
418 gettimeofday(&event.time, NULL);
420 event.code = SYN_REPORT;
421 if (write(uifd, &event, sizeof(struct input_event)) < 0) {
422 print_log("syn event write error 3[%d]", errno);
427 memset(&js, 0, sizeof(js));
428 gettimeofday(&event.time, NULL);
429 js.time = (event.time.tv_sec * 1000) + (event.time.tv_usec / 1000);
430 js.type = event_key[key].type;
431 js.number = event_key[key].code;
432 js.value = convert_value(value, (char **)0, 0);
434 print_log("Send Event JS=%d,%d,%d\t# %d",
435 (int)js.type, (int)js.number, (int)js.value, (int)js.time);
437 if (write(uifd, &js, sizeof(struct js_event)) < 0) {
438 print_log("event write error 4[%d]", errno);
445 print_log(const char *fmt, ...)
449 struct timeval NowTime;
450 extern long timezone;
451 static int sTimeZone = (99*60*60);
454 vsnprintf(log, sizeof(log)-2, fmt, ap);
457 gettimeofday( &NowTime, (struct timezone *)0 );
458 if( sTimeZone > (24*60*60) ) {
460 sTimeZone = timezone;
462 NowTime.tv_sec -= sTimeZone;
463 fprintf(stderr, "[%02d:%02d:%02d.%03d@%d] %s\n", (int)((NowTime.tv_sec/3600) % 24),
464 (int)((NowTime.tv_sec/60) % 60), (int)(NowTime.tv_sec % 60),
465 (int)NowTime.tv_usec/1000, getpid(), log);
469 usage(const char *prog)
471 fprintf(stderr, "Usage: %s [-device=device] [-w=w] [-h=h] [-c] [{-m/-t/-j/-J}] "
472 "[-mq[=key]] [-d] [event[=value]] [event[=value]] ...\n", prog);
477 main(int argc, char *argv[])
490 strcpy(buf, "ico_test_device");
491 for (i = 1; i < argc; i++) {
492 if (argv[i][0] == '-') {
493 if (strncasecmp(argv[i], "-device=", 8) == 0) {
494 strcpy(buf, &argv[i][8]);
496 else if (strncasecmp(argv[i], "-w=", 3) == 0) {
497 mWidth = strtol(&argv[i][3], (char **)0, 0);
499 else if (strncasecmp(argv[i], "-h=", 3) == 0) {
500 mHeight = strtol(&argv[i][3], (char **)0, 0);
502 else if (strcasecmp(argv[i], "-c") == 0) {
503 mConvert = 1; /* Convert logical to physical */
505 else if (strcasecmp(argv[i], "-m") == 0) {
506 mTouch = 1; /* Simulate mouse */
508 else if (strcasecmp(argv[i], "-t") == 0) {
509 mTouch = 2; /* Simulate touch-panel */
511 else if (strcmp(argv[i], "-j") == 0) {
512 mTouch = 0; /* Simulate joystick */
514 else if (strcmp(argv[i], "-J") == 0) {
515 mTouch = 3; /* Simulate joystick, but event is mouse */
517 else if (strncasecmp(argv[i], "-mq", 3) == 0) {
518 if (argv[i][3] == '=') {
519 mqkey = strtol(&argv[i][4], (char **)0, 0);
522 mqkey = 55551; /* default message queue key */
525 else if (strcasecmp(argv[i], "-d") == 0) {
543 signal(SIGTERM, term_signal);
544 signal(SIGINT, term_signal);
548 memset(&mqbuf, 0, sizeof(mqbuf));
549 if (msgrcv(mqid, &mqbuf, sizeof(mqbuf)-sizeof(long), 0, 0) < 0) {
550 if (errno == EINTR) continue;
551 print_log("ico_send_inputevent: mq(%d) receive error[%d]",
558 for (i = 0; mqbuf.buf[i]; i++) {
559 if ((mqbuf.buf[i] == '#') || (mqbuf.buf[i] == '\n')
560 || (mqbuf.buf[i] == '\r')) break;
561 if (mqbuf.buf[i] == '\t') buf[k++] = ' ';
562 else buf[k++] = mqbuf.buf[i];
563 if ((j < 0) && (mqbuf.buf[i] != ' ')) j = i;
569 msgctl(mqid, IPC_RMID, NULL);
572 while ((mRun != 0) && (fgets(buf, sizeof(buf), stdin) != NULL)) {
574 for (i = 0; buf[i]; i++) {
575 if ((buf[i] == '#') || (buf[i] == '\n') || (buf[i] == '\r')) break;
576 if (buf[i] == '\t') buf[i] = ' ';
577 if ((j < 0) && (buf[i] != ' ')) j = i;
585 for (i = 1; i < argc; i++) {
586 if (argv[i][0] == '-') continue;
587 if (mRun == 0) break;