blob: 2832c315d55bc244f6fdce0e95d7a070a697ea34 [file] [log] [blame]
diff --git a/include/evemu.h b/include/evemu.h
index e4ce667..05cef0f 100644
--- a/include/evemu.h
+++ b/include/evemu.h
@@ -282,10 +282,25 @@ int evemu_read_event_realtime(FILE *fp, struct input_event *ev,
int evemu_record(FILE *fp, int fd, int ms);
/**
+ * insert_slot0() - insert a slot0 event
+ * @fp: file pointer to read the event from
+ * @ev: pointer to the kernel event to be filled
+ * @evtime: pointer to a timeval struct
+ *
+ * Read events until an EV_SYN/SYN_REPORT event is reached, and insert a slot0
+ * event. However, if a slot0 event exists already, do not insert anything.
+ *
+ * Returns 1 if a slot0 event is created and inserted, 0 if a slot0 event
+ * exists already.
+ */
+int insert_slot0(FILE *fp, struct input_event *ev, struct timeval *evtime);
+
+/**
* evemu_play() - replay events from file to kernel device in realtime
* @fp: file pointer to read the events from
* @fd: file descriptor of kernel device to write to
* @fp_time: file descriptor for keeping playback timing information
+ * @flag_slot0: flag indicating whether to insert a slot 0 event or not
*
* Contiuously reads events from the file and writes them to the
* kernel device, in realtime. The function terminates when end of
@@ -293,7 +308,7 @@ int evemu_record(FILE *fp, int fd, int ms);
*
* Returns zero if successful, negative error otherwise.
*/
-int evemu_play(FILE *fp, int fd, FILE *fp_time);
+int evemu_play(FILE *fp, int fd, FILE *fp_time, int flag_slot0);
/**
* evemu_create() - create a kernel device from the evemu configuration
diff --git a/src/evemu.c b/src/evemu.c
index 02377f1..9d34101 100644
--- a/src/evemu.c
+++ b/src/evemu.c
@@ -65,6 +65,14 @@
#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
+/* To determine if this is a synchronization event */
+#define EVENT_SYN(type, code, value) \
+ (type == EV_SYN && code == SYN_REPORT && value == 0)
+
+/* To determine if this is a slot n event */
+#define EVENT_SLOT(type, code, value, n) \
+ (type == EV_ABS && code == ABS_MT_SLOT && value == n)
+
static void copy_bits(unsigned char *mask, const unsigned long *bits, int bytes)
{
int i;
@@ -378,16 +386,57 @@ int evemu_read_event_realtime(FILE *fp, struct input_event *ev,
return ret;
}
-int evemu_play(FILE *fp, int fd, FILE *fp_time)
+int insert_slot0(FILE *fp, struct input_event *ev, struct timeval *evtime)
+{
+ int flag_ev0_time = 1;
+
+ while (evemu_read_event(fp, ev) > 0) {
+ if (flag_ev0_time) {
+ *evtime = ev->time;
+ flag_ev0_time = 0;
+ }
+ if (EVENT_SLOT(ev->type, ev->code, ev->value, 0)) {
+ rewind(fp);
+ return 0;
+ } else if (EVENT_SYN(ev->type, ev->code, ev->value)) {
+ break;
+ }
+ }
+
+ if (evtime->tv_usec > 0) {
+ evtime->tv_usec--;
+ } else if (evtime->tv_sec > 0) {
+ evtime->tv_usec = 999999;
+ evtime->tv_sec--;
+ } else {
+ evtime->tv_usec = 0;
+ evtime->tv_sec = 0;
+ }
+ ev->time = *evtime;
+ ev->type = EV_ABS;
+ ev->code = ABS_MT_SLOT;
+ ev->value = 0;
+ rewind(fp);
+
+ return 1;
+}
+
+int evemu_play(FILE *fp, int fd, FILE *fp_time, int flag_slot0)
{
struct input_event ev;
struct timeval evtime;
struct timespec curr_tp;
int ret;
+ int flag_slot0_inserted = 0;
char *time_format = "E: %lu.%06u %04x %04x %-4d -- playback %lu.%09u\n";
memset(&evtime, 0, sizeof(evtime));
- while (evemu_read_event_realtime(fp, &ev, &evtime) > 0) {
+ if (flag_slot0) {
+ flag_slot0_inserted = insert_slot0(fp, &ev, &evtime);
+ }
+
+ while (flag_slot0_inserted ||
+ evemu_read_event_realtime(fp, &ev, &evtime) > 0) {
if (fp_time != NULL) {
clock_gettime(CLOCK_MONOTONIC, &curr_tp);
fprintf(fp_time, time_format,
@@ -396,6 +445,7 @@ int evemu_play(FILE *fp, int fd, FILE *fp_time)
curr_tp.tv_sec, curr_tp.tv_nsec);
}
SYSCALL(ret = write(fd, &ev, sizeof(ev)));
+ flag_slot0_inserted = 0;
}
return 0;
diff --git a/tools/evemu-play.c b/tools/evemu-play.c
index f66275e..c2aef3e 100644
--- a/tools/evemu-play.c
+++ b/tools/evemu-play.c
@@ -50,9 +50,12 @@ int main(int argc, char *argv[])
{
int fd;
FILE *fp_time = NULL;
- if (argc < 2 || argc > 3) {
- fprintf(stderr, "Usage: %s <device> [output_file]\n", argv[0]);
+ char *output_filename = NULL;
+ int flag_slot0 = 0;
+ if (argc < 2 || argc > 4) {
+ fprintf(stderr, "Usage: %s <device> [--insert-slot0] [output_file]\n", argv[0]);
fprintf(stderr, "\n");
+ fprintf(stderr, "--insert-slot0: insert a slot 0 event if missing in the very first packet.\n");
fprintf(stderr, "Event data is read from standard input.\n");
return -1;
}
@@ -61,15 +64,25 @@ int main(int argc, char *argv[])
fprintf(stderr, "error: could not open device\n");
return -1;
}
- if (argc == 3) {
- fp_time = fopen(argv[2], "w");
- if (fp_time == NULL) {
- fprintf(stderr, "error: could not open output file %s.\n",
- argv[2]);
- return -1;
+ if (argc >= 3) {
+ if (strcmp(argv[2], "--insert-slot0") == 0) {
+ flag_slot0 = 1;
+ if (argc == 4) {
+ output_filename = argv[3];
+ }
+ } else {
+ output_filename = argv[2];
+ }
+ if (output_filename != NULL) {
+ fp_time = fopen(output_filename, "w");
+ if (fp_time == NULL) {
+ fprintf(stderr, "error: could not open output file %s.\n",
+ output_filename);
+ return -1;
+ }
}
}
- if (evemu_play(stdin, fd, fp_time)) {
+ if (evemu_play(stdin, fd, fp_time, flag_slot0)) {
fprintf(stderr, "error: could not describe device\n");
}
if (fp_time != NULL) {