254 lines
10 KiB
C
254 lines
10 KiB
C
/*------------------------------------------------------------------------
|
|
* Copyright 2019 (c) Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
|
|
*
|
|
* This file is part of the ZBar Bar Code Reader.
|
|
*
|
|
* The ZBar Bar Code Reader is free software; you can redistribute it
|
|
* and/or modify it under the terms of the GNU Lesser Public License as
|
|
* published by the Free Software Foundation; either version 2.1 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* The ZBar Bar Code Reader is distributed in the hope that it will be
|
|
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser Public License for more details.
|
|
*------------------------------------------------------------------------*/
|
|
|
|
#include <argp.h>
|
|
#include <dbus/dbus.h>
|
|
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#define ZBAR_INTERFACE "org.linuxtv.Zbar1.Code"
|
|
#define ZBAR_SIGNAL_CODE "Code"
|
|
#define ZBAR_SIGNAL_TYPE "Type"
|
|
#define ZBAR_SIGNAL_DATA "Data"
|
|
#define ZBAR_SIGNAL_BINARY_DATA "BinaryData"
|
|
|
|
#define PROGRAM_NAME "test_dbus"
|
|
|
|
static const char doc[] = "\nTest if ZBar is sending codes via D-Bus\n";
|
|
|
|
static const struct argp_option options[] = {
|
|
{ "count", 'c', "#codes", 0, "Stop after received #codes", 0 },
|
|
{ "time", 't', "#seconds", 0, "Stop after #seconds", 0 },
|
|
{ "log", 'l', "#file", 0, "Write log to #file", 0 },
|
|
{ "bin-log", 'b', "#file", 0, "Write binary log to #file", 0 },
|
|
{ "help", '?', 0, 0, "Give this help list", -1 },
|
|
{ "usage", -3, 0, 0, "Give a short usage message", 0 },
|
|
{ 0 }
|
|
};
|
|
|
|
static int max_msg = 0;
|
|
static int timeout = 0;
|
|
static FILE *log = NULL;
|
|
static FILE *bin_log = NULL;
|
|
|
|
static error_t parse_opt(int k, char *optarg, struct argp_state *state)
|
|
{
|
|
switch (k) {
|
|
case 'c':
|
|
max_msg = strtoul(optarg, NULL, 0);
|
|
break;
|
|
case 't':
|
|
timeout = strtoul(optarg, NULL, 0);
|
|
break;
|
|
case 'l':
|
|
log = fopen(optarg, "wb");
|
|
break;
|
|
case 'b':
|
|
bin_log = fopen(optarg, "wb");
|
|
break;
|
|
case '?':
|
|
argp_state_help(state, state->out_stream,
|
|
ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC);
|
|
exit(0);
|
|
case -3:
|
|
argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
|
|
exit(0);
|
|
default:
|
|
return ARGP_ERR_UNKNOWN;
|
|
};
|
|
return 0;
|
|
}
|
|
|
|
static const struct argp argp = {
|
|
.options = options,
|
|
.parser = parse_opt,
|
|
.doc = doc,
|
|
};
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
DBusMessage *msg;
|
|
DBusMessageIter args, entry, dict, val;
|
|
DBusConnection *conn;
|
|
DBusError err;
|
|
char *str, *property;
|
|
int count = 0, length = 0;
|
|
|
|
if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, 0, 0)) {
|
|
argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
|
|
return -1;
|
|
}
|
|
|
|
if (!log)
|
|
log = fdopen(dup(fileno(stderr)), "w+");
|
|
|
|
if (!bin_log)
|
|
bin_log = fdopen(dup(fileno(stderr)), "w+");
|
|
|
|
// initialise the error value
|
|
dbus_error_init(&err);
|
|
|
|
// connect to the DBUS system bus, and check for errors
|
|
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
|
|
if (dbus_error_is_set(&err)) {
|
|
fprintf(stderr, "Connection Error (%s)\n", err.message);
|
|
dbus_error_free(&err);
|
|
}
|
|
if (!conn) {
|
|
fprintf(stderr, "Connection Null\n");
|
|
return -1;
|
|
}
|
|
|
|
dbus_bus_add_match(conn, "type='signal',interface='" ZBAR_INTERFACE "'",
|
|
&err);
|
|
dbus_connection_flush(conn);
|
|
if (dbus_error_is_set(&err)) {
|
|
fprintf(stderr, "Match Error (%s)\n", err.message);
|
|
exit(1);
|
|
}
|
|
|
|
if (timeout)
|
|
alarm(timeout);
|
|
|
|
/* loop listening for signals being emitted */
|
|
fprintf(stderr, "Waiting for Zbar events\n");
|
|
while (true) {
|
|
// non blocking read of the next available message
|
|
dbus_connection_read_write(conn, 0);
|
|
msg = dbus_connection_pop_message(conn);
|
|
|
|
// loop again if we haven't read a message
|
|
if (NULL == msg) {
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
|
|
// check if the message is a signal from the correct interface and with the correct name
|
|
if (dbus_message_is_signal(msg, ZBAR_INTERFACE, ZBAR_SIGNAL_CODE)) {
|
|
// read the parameters
|
|
if (!dbus_message_iter_init(msg, &args))
|
|
fprintf(stderr, "Message has no arguments!\n");
|
|
else if (DBUS_TYPE_ARRAY != dbus_message_iter_get_arg_type(&args))
|
|
fprintf(stderr, "Argument is not array!\n");
|
|
else {
|
|
while (dbus_message_iter_get_arg_type(&args) !=
|
|
DBUS_TYPE_INVALID) {
|
|
dbus_message_iter_recurse(&args, &entry);
|
|
if (DBUS_TYPE_DICT_ENTRY !=
|
|
dbus_message_iter_get_arg_type(&entry)) {
|
|
fprintf(stderr, "Element is not dict entry!\n");
|
|
} else {
|
|
while (dbus_message_iter_get_arg_type(&entry) !=
|
|
DBUS_TYPE_INVALID) {
|
|
dbus_message_iter_recurse(&entry, &dict);
|
|
if (DBUS_TYPE_STRING !=
|
|
dbus_message_iter_get_arg_type(&dict)) {
|
|
fprintf(stderr,
|
|
"Dict Entry key is not string!\n");
|
|
} else {
|
|
dbus_message_iter_get_basic(&dict, &property);
|
|
dbus_message_iter_next(&dict);
|
|
if (DBUS_TYPE_VARIANT !=
|
|
dbus_message_iter_get_arg_type(&dict)) {
|
|
fprintf(
|
|
stderr,
|
|
"Dict Entry value is not variant!\n");
|
|
} else {
|
|
dbus_message_iter_recurse(&dict, &val);
|
|
if (strcmp(property, ZBAR_SIGNAL_TYPE) ==
|
|
0) {
|
|
if (DBUS_TYPE_STRING !=
|
|
dbus_message_iter_get_arg_type(
|
|
&val)) {
|
|
fprintf(
|
|
stderr,
|
|
"Dict Entry value for barcode type is not string!\n");
|
|
} else {
|
|
dbus_message_iter_get_basic(&val,
|
|
&str);
|
|
fprintf(stderr, "Type = %s\n", str);
|
|
}
|
|
} else if (strcmp(property,
|
|
ZBAR_SIGNAL_DATA) == 0) {
|
|
if (DBUS_TYPE_STRING !=
|
|
dbus_message_iter_get_arg_type(
|
|
&val)) {
|
|
fprintf(
|
|
stderr,
|
|
"Dict Entry value for barcode text data is not string!\n");
|
|
} else {
|
|
dbus_message_iter_get_basic(&val,
|
|
&str);
|
|
fprintf(stderr, "Value = %s\n",
|
|
str);
|
|
fprintf(log, "%s\n", str);
|
|
}
|
|
} else if (strcmp(property,
|
|
ZBAR_SIGNAL_BINARY_DATA) ==
|
|
0) {
|
|
if (DBUS_TYPE_ARRAY !=
|
|
dbus_message_iter_get_arg_type(
|
|
&val)) {
|
|
fprintf(
|
|
stderr,
|
|
"Dict Entry value for barcode binary data is not array!\n");
|
|
} else {
|
|
dbus_message_iter_recurse(&val,
|
|
&val);
|
|
if (DBUS_TYPE_BYTE !=
|
|
dbus_message_iter_get_arg_type(
|
|
&val)) {
|
|
fprintf(
|
|
stderr,
|
|
"Dict Entry value for barcode binary data is not array of bytes!\n");
|
|
} else {
|
|
dbus_message_iter_get_fixed_array(
|
|
&val, &str, &length);
|
|
fprintf(stderr,
|
|
"BinaryData[%d]\n",
|
|
length);
|
|
fwrite(str, sizeof(*str),
|
|
length, bin_log);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
dbus_message_iter_next(&entry);
|
|
}
|
|
/* If max_msg > 0, stops after receiving 'count' messages */
|
|
if (++count == max_msg) {
|
|
dbus_message_unref(msg);
|
|
return 0;
|
|
}
|
|
}
|
|
dbus_message_iter_next(&args);
|
|
}
|
|
}
|
|
}
|
|
// free the message
|
|
dbus_message_unref(msg);
|
|
}
|
|
|
|
fclose(log);
|
|
fclose(bin_log);
|
|
|
|
return 0;
|
|
}
|