-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathmysendevent.c
136 lines (111 loc) · 4.42 KB
/
mysendevent.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/ioctl.h>
//#include <linux/input.h> // this does not compile
#include <unistd.h>
#include <errno.h>
// from <linux/input.h>
typedef uint32_t __u32;
typedef uint16_t __u16;
typedef __signed__ int __s32;
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__u32 value;
};
#define MICROSEC 1000000
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */
#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */
#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */
#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */
#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */
#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global keystate */
#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */
#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch states */
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event bits */
#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, struct input_absinfo) /* get abs value/limits */
#define EVIOCSABS(abs) _IOW('E', 0xc0 + abs, struct input_absinfo) /* set abs value/limits */
#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) /* send a force effect to a force feedback device */
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
// end <linux/input.h>
void remove_specific_chars(char* str, char c1, char c2) {
char *pr = str, *pw = str;
while (*pr) {
*pw = *pr++;
pw += (*pw != c1 && *pw != c2);
}
*pw = '\0';
}
int main(int argc, char *argv[])
{
int i;
int fd;
int ret;
int version;
struct input_event event;
if(argc != 3) {
fprintf(stderr, "use: %s input_device input_events\n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDWR);
if(fd < 0) {
fprintf(stderr, "could not open %s, %s\n", argv[optind], strerror(errno));
return 1;
}
if (ioctl(fd, EVIOCGVERSION, &version)) {
fprintf(stderr, "could not get driver version for %s, %s\n", argv[optind], strerror(errno));
return 1;
}
FILE * fd_in = fopen(argv[2], "r");
if (fd_in == NULL) {
fprintf(stderr, "could not open input file: %s\n", argv[2]);
return 1;
}
char line[128];
unsigned int sleep_time;
double timestamp_previous = -1.0;
double timestamp_now;
char type[32];
char code[32];
char value[32];
while (fgets(line, sizeof(line), fd_in) != NULL) {
// remove the characters [ and ] surrounding the timestamp
remove_specific_chars(line, '[', ']');
sscanf(line, "%lf %s %s %s", ×tamp_now, type, code, value);
// write the event to the appropriate input device
memset(&event, 0, sizeof(event));
event.type = (int) strtol(type, NULL, 16);
event.code = (int) strtol(code, NULL, 16);
event.value = (uint32_t) strtoll(value, NULL, 16);
ret = write(fd, &event, sizeof(event));
if(ret < sizeof(event)) {
fprintf(stderr, "write event failed, %s\n", strerror(errno));
return -1;
}
if(timestamp_previous != -1.0)
{
// In order to playback the same gestures the code sleeps accordingly to the timestamps from the inputed recording
sleep_time = (unsigned int) ((timestamp_now - timestamp_previous) * MICROSEC);
// we don't care about the value of a single event's timestamp but the difference between two sequential events
usleep(sleep_time); // sleep_time is in MICROSECONDS
}
timestamp_previous = timestamp_now;
// Clear temporary buffers
memset(line, 0, sizeof(line));
memset(type, 0, sizeof(type));
memset(code, 0, sizeof(code));
memset(value, 0, sizeof(value));
}
fclose(fd_in);
close(fd);
return 0;
}