This commit is contained in:
parent
bb72f57776
commit
cd5f9f7a12
|
@ -30,10 +30,11 @@
|
||||||
"mpl-lib.h": "c",
|
"mpl-lib.h": "c",
|
||||||
"mpl-core.h": "c",
|
"mpl-core.h": "c",
|
||||||
"mpl.h": "c",
|
"mpl.h": "c",
|
||||||
"mpl-udev.h": "c"
|
"mpl-udev.h": "c",
|
||||||
|
"mpl-args.h": "c",
|
||||||
|
"*.in": "cpp",
|
||||||
|
"signal.h": "c",
|
||||||
|
"stdio.h": "c"
|
||||||
},
|
},
|
||||||
"cmake.configureOnOpen": false,
|
"cmake.configureOnOpen": false
|
||||||
"editor.rulers": [
|
|
||||||
80
|
|
||||||
]
|
|
||||||
}
|
}
|
|
@ -1,6 +1,33 @@
|
||||||
cmake_minimum_required(VERSION 3.18.4)
|
cmake_minimum_required(VERSION 3.18.4)
|
||||||
project(mportlink)
|
project(mportlink)
|
||||||
|
|
||||||
|
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Os")
|
||||||
|
|
||||||
|
set(VERSION_MAJOR 0)
|
||||||
|
set(VERSION_MINOR 1)
|
||||||
|
set(VERSION_PATCH 0)
|
||||||
|
string(TIMESTAMP CURRENT_YEAR "%y" UTC)
|
||||||
|
string(TIMESTAMP DAY_OF_YEAR "%j" UTC)
|
||||||
|
|
||||||
|
string(CONCAT BASEVERSION "${VERSION_MAJOR}" "." "${VERSION_MINOR}" "." "${VERSION_PATCH}")
|
||||||
|
string(CONCAT BUILDVERSION "${BASEVERSION}" "." "${CURRENT_YEAR}" "${DAY_OF_YEAR}")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND git describe HEAD
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_VERSION
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
|
||||||
|
if(GIT_SHORT_HASH STREQUAL "")
|
||||||
|
set(VERSION "${BUILDVERSION}")
|
||||||
|
else()
|
||||||
|
set(VERSION "${GIT_VERSION}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(-DVERSION="${VERSION}")
|
||||||
|
|
||||||
file(GLOB_RECURSE SRC_FILES_LIST src/*.c)
|
file(GLOB_RECURSE SRC_FILES_LIST src/*.c)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
356
src/mpl-core.c
356
src/mpl-core.c
|
@ -5,304 +5,108 @@
|
||||||
* Telegram @alexanderzhirov
|
* Telegram @alexanderzhirov
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "mpl-core.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "mpl-core.h"
|
|
||||||
|
|
||||||
#define LOCKFILE "/run/lock/mportlink.lock"
|
#define LOCKFILE "/run/lock/mportlink.lock"
|
||||||
#define DEV_PATH "/dev/"
|
#define DEV_PATH "/dev/"
|
||||||
#define DONGLE_PATH (DEV_PATH "dongle/")
|
#define DONGLE_PATH (DEV_PATH "dongle/")
|
||||||
|
|
||||||
static void mpl_create_dongle_dir()
|
static int mpl_create_dongle_dir()
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (stat(DONGLE_PATH, &st) == 0) {
|
if (stat(DONGLE_PATH, &st) == 0)
|
||||||
if (!S_ISDIR(st.st_mode)) {
|
{
|
||||||
MPLOG(LOG_WARNING, "%s exists and is not a directory",
|
if (!S_ISDIR(st.st_mode))
|
||||||
DONGLE_PATH);
|
{
|
||||||
exit(EXIT_FAILURE);
|
MPLOG(LOG_WARNING, "%s exists and is not a directory", DONGLE_PATH);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (mkdir(DONGLE_PATH,
|
}
|
||||||
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) {
|
else if (mkdir(DONGLE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
|
||||||
|
{
|
||||||
MPLOG(LOG_ERR, "unable to create a directory %s", DONGLE_PATH);
|
MPLOG(LOG_ERR, "unable to create a directory %s", DONGLE_PATH);
|
||||||
exit(EXIT_FAILURE);
|
return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mpl_init()
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void static mpl_free(MPL *mpl)
|
||||||
{
|
{
|
||||||
openlog(MPL, LOG_PID, LOG_SYSLOG);
|
if (mpl)
|
||||||
|
free(mpl);
|
||||||
int lock_fd = open(LOCKFILE, O_CREAT | O_RDWR, 0644);
|
|
||||||
if (lock_fd < 0) {
|
|
||||||
MPLOG(LOG_ERR, "Unable to create a lockfile");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = flock(lock_fd, LOCK_EX | LOCK_NB);
|
MPL *mpl_init(MPL_PARAMETERS *parameters)
|
||||||
if (rc || errno == EWOULDBLOCK) {
|
|
||||||
MPLOG(LOG_ERR, "Only one instance of %s is allowed", MPL);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
mpl_create_dongle_dir();
|
|
||||||
|
|
||||||
MPLOG(LOG_NOTICE, "Starting the %s daemon", MPL);
|
|
||||||
|
|
||||||
return lock_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mpl_stop(const int lock_fd)
|
|
||||||
{
|
{
|
||||||
flock(lock_fd, LOCK_UN);
|
MPL *mpl = (MPL *)calloc(1, sizeof(MPL));
|
||||||
|
|
||||||
MPLOG(LOG_NOTICE, "Stopping the %s daemon", MPL);
|
if (!mpl)
|
||||||
|
{
|
||||||
|
MPLOG(LOG_ERR, "error getting the MPL structure");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpl->parameters.check_device = parameters->check_device;
|
||||||
|
mpl->cancellable.signal = 0;
|
||||||
|
mpl->cancellable.exit = 0;
|
||||||
|
|
||||||
|
mpl->fd = open(LOCKFILE, O_CREAT | O_RDWR, 0644);
|
||||||
|
if (mpl->fd < 0)
|
||||||
|
{
|
||||||
|
MPLOG(LOG_ERR, "unable to create a lockfile");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = flock(mpl->fd, LOCK_EX | LOCK_NB);
|
||||||
|
if (rc || errno == EWOULDBLOCK)
|
||||||
|
{
|
||||||
|
MPLOG(LOG_ERR, "only one instance of %s is allowed", MPL_NAME);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mpl_create_dongle_dir())
|
||||||
|
{
|
||||||
|
MPLOG(LOG_ERR, "%s will be stopped", MPL_NAME);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mpl_udev_init(&mpl->udev))
|
||||||
|
{
|
||||||
|
MPLOG(LOG_ERR, "%s will be stopped", MPL_NAME);
|
||||||
|
mpl_free(mpl);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
MPLOG(LOG_NOTICE, "starting the %s daemon", MPL_NAME);
|
||||||
|
|
||||||
|
return mpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpl_stop(MPL *mpl)
|
||||||
|
{
|
||||||
|
mpl_udev_free(&mpl->udev);
|
||||||
|
|
||||||
|
flock(mpl->fd, LOCK_UN);
|
||||||
|
|
||||||
|
mpl_free(mpl);
|
||||||
|
|
||||||
|
if (mpl->cancellable.exit)
|
||||||
|
MPLOG(LOG_NOTICE, "stopping the %s daemon", MPL_NAME);
|
||||||
|
else
|
||||||
|
MPLOG(LOG_NOTICE, "successful completion of the process %d", getpid());
|
||||||
closelog();
|
closelog();
|
||||||
}
|
}
|
||||||
|
|
||||||
MPL_UDEV *mpl_new()
|
void mpl_loop(MPL *mpl)
|
||||||
{
|
{
|
||||||
MPL_UDEV *mpl_udev = (MPL_UDEV *)calloc(1, sizeof(MPL_UDEV));
|
if (mpl->parameters.check_device)
|
||||||
|
mpl_udev_check_devices(&mpl->udev);
|
||||||
|
|
||||||
if (mpl_udev == NULL) {
|
mpl_udev_loop(&mpl->udev, &mpl->cancellable);
|
||||||
MPLOG(LOG_ERR, "Error getting the udev structure");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mpl_udev;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mpl_loop(MPL_UDEV *mpl_udev)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// typedef struct
|
|
||||||
// {
|
|
||||||
// const gchar *manufacturer;
|
|
||||||
// const gchar *model;
|
|
||||||
// const gchar *imei;
|
|
||||||
// const gchar *device_identifier;
|
|
||||||
// MMModemPortInfo *ports;
|
|
||||||
// guint n_ports;
|
|
||||||
// } MPLmodem;
|
|
||||||
|
|
||||||
|
|
||||||
// MPLmodem *mpl_get_new_modem()
|
|
||||||
// {
|
|
||||||
// MPLmodem *modem = (MPLmodem *)calloc(1, sizeof(MPLmodem));
|
|
||||||
|
|
||||||
// if (modem == NULL)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_ERR, "mpl_get_new_modem, modem: memory allocation error");
|
|
||||||
// raise(SIGINT);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return modem;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void mpl_free_modem(MPLmodem *modem)
|
|
||||||
// {
|
|
||||||
// if (modem->n_ports && modem->ports)
|
|
||||||
// mm_modem_port_info_array_free(modem->ports, modem->n_ports);
|
|
||||||
// free(modem);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void mpl_print_modem_info(MPLmodem *modem, bool connected)
|
|
||||||
// {
|
|
||||||
// gchar *status;
|
|
||||||
// status = connected ? "Connected" : "Disconnected";
|
|
||||||
|
|
||||||
// g_print("%s %s %s (%s)\n", status, modem->manufacturer, modem->model, modem->device_identifier);
|
|
||||||
// g_print("`-- Count ports: %d\n", modem->n_ports);
|
|
||||||
|
|
||||||
// for (guint i = 0; i < modem->n_ports; i++)
|
|
||||||
// {
|
|
||||||
// if (i + 1 < modem->n_ports)
|
|
||||||
// {
|
|
||||||
// g_print(" |-- Port %d:\n", i);
|
|
||||||
// g_print(" | |-- Name: %s\n", modem->ports[i].name);
|
|
||||||
// g_print(" | `-- Link: %s-%d\n", modem->imei, i);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// g_print(" `-- Port %d:\n", i);
|
|
||||||
// g_print(" |-- Name: %s\n", modem->ports[i].name);
|
|
||||||
// g_print(" `-- Link: %s-%d\n", modem->imei, i);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// MPLmodem *mpl_get_new_modem_info(MMObject *obj)
|
|
||||||
// {
|
|
||||||
// MPLmodem *mpl_modem = NULL;
|
|
||||||
// MMModem *mm_modem = mm_object_get_modem(obj);
|
|
||||||
|
|
||||||
// if (mm_modem == NULL)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_ERR, "mpl_get_new_modem_info, mm_modem: modem does not implement the interface");
|
|
||||||
// return NULL;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// mpl_modem = mpl_get_new_modem();
|
|
||||||
|
|
||||||
// mpl_modem->manufacturer = mm_modem_get_manufacturer(mm_modem);
|
|
||||||
// mpl_modem->model = mm_modem_get_model(mm_modem);
|
|
||||||
// mpl_modem->imei = mm_modem_get_equipment_identifier(mm_modem);
|
|
||||||
// mpl_modem->device_identifier = mm_modem_get_device_identifier(mm_modem);
|
|
||||||
|
|
||||||
// gboolean success = mm_modem_get_ports(mm_modem, &mpl_modem->ports, &mpl_modem->n_ports);
|
|
||||||
|
|
||||||
// g_object_unref(mm_modem);
|
|
||||||
|
|
||||||
// if (success)
|
|
||||||
// return mpl_modem;
|
|
||||||
// else
|
|
||||||
// syslog(LOG_WARNING, "mpl_get_new_modem_info, success: error receiving modem ports");
|
|
||||||
|
|
||||||
// mpl_free_modem(mpl_modem);
|
|
||||||
|
|
||||||
// return NULL;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// char *mpl_get_dst_path(guint index, const gchar *imei)
|
|
||||||
// {
|
|
||||||
// char *dst_path = NULL;
|
|
||||||
|
|
||||||
// guint size_id = snprintf(NULL, 0, "-%d", index);
|
|
||||||
// char *id = (char *)calloc(size_id + 1, sizeof(char));
|
|
||||||
|
|
||||||
// if (id == NULL)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_ERR, "mpl_get_dst_path, id: memory allocation error");
|
|
||||||
// raise(SIGINT);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// sprintf(id, "-%d", index);
|
|
||||||
|
|
||||||
// guint dst_path_size = strlen(DONGLE_PATH) + strlen(imei) + size_id;
|
|
||||||
// dst_path = (char *)calloc(dst_path_size + 1, sizeof(char));
|
|
||||||
|
|
||||||
// if (dst_path == NULL)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_ERR, "mpl_get_dst_path, dst_path: memory allocation error");
|
|
||||||
// raise(SIGINT);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// strcpy(dst_path, DONGLE_PATH);
|
|
||||||
// strcat(dst_path, imei);
|
|
||||||
// strcat(dst_path, id);
|
|
||||||
|
|
||||||
// free(id);
|
|
||||||
|
|
||||||
// return dst_path;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// char *mpl_get_src_path(const gchar *port_name)
|
|
||||||
// {
|
|
||||||
// char *src_path = NULL;
|
|
||||||
|
|
||||||
// guint src_path_size = strlen(DEV_PATH) + strlen(port_name);
|
|
||||||
// src_path = (char *)calloc(src_path_size + 1, sizeof(char));
|
|
||||||
|
|
||||||
// if (src_path == NULL)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_ERR, "mpl_get_src_path, src_path: memory allocation error");
|
|
||||||
// raise(SIGINT);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// strcpy(src_path, DEV_PATH);
|
|
||||||
// strcat(src_path, port_name);
|
|
||||||
|
|
||||||
// return src_path;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void mpl_symlink_ports(MPLmodem *modem)
|
|
||||||
// {
|
|
||||||
// for (guint i = 0; i < modem->n_ports; i++)
|
|
||||||
// {
|
|
||||||
// char *src_path = mpl_get_src_path(modem->ports[i].name);
|
|
||||||
// char *dst_path = mpl_get_dst_path(i, modem->imei);
|
|
||||||
// struct stat st;
|
|
||||||
|
|
||||||
// if (access(src_path, F_OK) == -1)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_ERR, "mpl_symlink_ports, src_path: device file is not available [%s]", src_path);
|
|
||||||
// free(src_path);
|
|
||||||
// free(dst_path);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (lstat(dst_path, &st) == 0)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_WARNING, "mpl_symlink_ports, dst_path: a symbolic link to the device already exists [%s]", dst_path);
|
|
||||||
// if (unlink(dst_path) == -1)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_ERR, "mpl_symlink_ports, dst_path: link could not be deleted [%s]", dst_path);
|
|
||||||
// free(src_path);
|
|
||||||
// free(dst_path);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (symlink(src_path, dst_path) == 0)
|
|
||||||
// syslog(LOG_NOTICE, "mpl_symlink_ports, dst_path: the symbolic link has been successfully created [%s -> %s]", dst_path, src_path);
|
|
||||||
// else
|
|
||||||
// syslog(LOG_ERR, "mpl_symlink_ports, dst_path: error creating a symbolic link [%s -> %s]", dst_path, src_path);
|
|
||||||
|
|
||||||
// free(src_path);
|
|
||||||
// free(dst_path);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void mpl_unlink_ports(MPLmodem *modem)
|
|
||||||
// {
|
|
||||||
// for (guint i = 0; i < modem->n_ports; i++)
|
|
||||||
// {
|
|
||||||
// char *dst_path = mpl_get_dst_path(i, modem->imei);
|
|
||||||
// struct stat st;
|
|
||||||
|
|
||||||
// if (lstat(dst_path, &st) == -1)
|
|
||||||
// {
|
|
||||||
// syslog(LOG_WARNING, "mpl_unlink_ports, dst_path: a symbolic link to the device not exists [%s]", dst_path);
|
|
||||||
// free(dst_path);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (unlink(dst_path) == 0)
|
|
||||||
// syslog(LOG_NOTICE, "mpl_unlink_ports, dst_path: link was successfully deleted [%s]", dst_path);
|
|
||||||
// else
|
|
||||||
// syslog(LOG_ERR, "mpl_unlink_ports, dst_path: link could not be deleted [%s]", dst_path);
|
|
||||||
|
|
||||||
// free(dst_path);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void mpl_device_added(MMManager *manager, MMObject *obj)
|
|
||||||
// {
|
|
||||||
// MPLmodem *modem = mpl_get_new_modem_info(obj);
|
|
||||||
|
|
||||||
// if (modem == NULL)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// // mpl_print_modem_info(modem, true);
|
|
||||||
// mpl_symlink_ports(modem);
|
|
||||||
|
|
||||||
// mpl_free_modem(modem);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void mpl_device_removed(MMManager *manager, MMObject *obj)
|
|
||||||
// {
|
|
||||||
// MPLmodem *modem = mpl_get_new_modem_info(obj);
|
|
||||||
|
|
||||||
// if (modem == NULL)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// // mpl_print_modem_info(modem, false);
|
|
||||||
// mpl_unlink_ports(modem);
|
|
||||||
|
|
||||||
// mpl_free_modem(modem);
|
|
||||||
// }
|
|
||||||
|
|
|
@ -9,11 +9,23 @@
|
||||||
#define MPL_CORE_H_
|
#define MPL_CORE_H_
|
||||||
|
|
||||||
#include "mpl-lib.h"
|
#include "mpl-lib.h"
|
||||||
|
#include "mpl-udev.h"
|
||||||
|
|
||||||
int mpl_init();
|
typedef struct
|
||||||
void mpl_stop(const int lock_fd);
|
{
|
||||||
void mpl_loop(MPL_UDEV *mpl_udev);
|
int check_device;
|
||||||
|
} MPL_PARAMETERS;
|
||||||
|
|
||||||
MPL_UDEV *mpl_new();
|
typedef struct
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
MPL_PARAMETERS parameters;
|
||||||
|
MPL_CANCELLABLE cancellable;
|
||||||
|
MPL_UDEV udev;
|
||||||
|
} MPL;
|
||||||
|
|
||||||
|
MPL *mpl_init(MPL_PARAMETERS *parameters);
|
||||||
|
void mpl_stop(MPL *mpl);
|
||||||
|
void mpl_loop(MPL *mpl);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,24 +15,20 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
#define MPL "mportlink"
|
#define MPL_NAME "mportlink"
|
||||||
|
|
||||||
#define MPLOG(PRIORITY, fmt, ...) do { \
|
#define MPLOG(PRIORITY, fmt, ...) do { \
|
||||||
char buf[256]; \
|
char buf[256]; \
|
||||||
snprintf(buf, sizeof(buf), fmt __VA_OPT__(,) __VA_ARGS__); \
|
snprintf(buf, sizeof(buf), fmt __VA_OPT__(,) __VA_ARGS__); \
|
||||||
PRIORITY < LOG_WARNING ? \
|
PRIORITY < LOG_WARNING && errno ? \
|
||||||
syslog(PRIORITY, "%s(): %s (%s)", __func__, buf, \
|
syslog(PRIORITY, "%s(): %s (%s)", __func__, buf, strerror(errno)) : \
|
||||||
strerror(errno)) : \
|
|
||||||
syslog(PRIORITY, "%s(): %s", __func__, buf); \
|
syslog(PRIORITY, "%s(): %s", __func__, buf); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
typedef struct _MPL_UDEV MPL_UDEV;
|
typedef struct
|
||||||
|
|
||||||
struct _MPL_UDEV
|
|
||||||
{
|
{
|
||||||
struct udev *udev;
|
int signal;
|
||||||
struct udev_monitor *monitor;
|
int exit;
|
||||||
int udev_fd;
|
} MPL_CANCELLABLE;
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
167
src/mpl-udev.c
167
src/mpl-udev.c
|
@ -5,48 +5,54 @@
|
||||||
* Telegram @alexanderzhirov
|
* Telegram @alexanderzhirov
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mpl-lib.h"
|
|
||||||
#include "mpl-udev.h"
|
#include "mpl-udev.h"
|
||||||
#include <libudev.h>
|
|
||||||
|
|
||||||
void mpl_udev_init(MPL_UDEV *mpl_udev)
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
int mpl_udev_init(MPL_UDEV *udev)
|
||||||
{
|
{
|
||||||
mpl_udev->udev = udev_new();
|
udev->context = udev_new();
|
||||||
if (mpl_udev->udev == NULL) {
|
if (udev->context == NULL)
|
||||||
MPLOG(LOG_ERR, "Error creating udev context");
|
{
|
||||||
exit(EXIT_FAILURE);
|
MPLOG(LOG_ERR, "error creating udev context");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpl_udev->monitor = udev_monitor_new_from_netlink(mpl_udev->udev, "udev");
|
udev->monitor = udev_monitor_new_from_netlink(udev->context, "udev");
|
||||||
if (mpl_udev->monitor == NULL) {
|
if (udev->monitor == NULL)
|
||||||
MPLOG(LOG_ERR, "Error creating udev monitor");
|
{
|
||||||
udev_unref(mpl_udev->udev);
|
MPLOG(LOG_ERR, "error creating udev monitor");
|
||||||
exit(EXIT_FAILURE);
|
mpl_udev_free(udev);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
udev_monitor_filter_add_match_subsystem_devtype(mpl_udev->monitor,
|
udev_monitor_filter_add_match_subsystem_devtype(udev->monitor, "usb", NULL);
|
||||||
"usb", NULL);
|
udev_monitor_enable_receiving(udev->monitor);
|
||||||
udev_monitor_enable_receiving(mpl_udev->monitor);
|
|
||||||
|
|
||||||
mpl_udev->udev_fd = udev_monitor_get_fd(mpl_udev->monitor);
|
udev->fd = udev_monitor_get_fd(udev->monitor);
|
||||||
if (mpl_udev->udev_fd < 0) {
|
if (udev->fd < 0)
|
||||||
MPLOG(LOG_ERR, "Error creating udev monitor descriptor");
|
{
|
||||||
udev_unref(mpl_udev->udev);
|
MPLOG(LOG_ERR, "error creating udev monitor descriptor");
|
||||||
exit(EXIT_FAILURE);
|
mpl_udev_free(udev);
|
||||||
}
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mpl_udev_check_devices(MPL_UDEV *mpl_udev)
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mpl_udev_check_devices(MPL_UDEV *udev)
|
||||||
{
|
{
|
||||||
struct udev_device *dev;
|
struct udev_device *dev;
|
||||||
struct udev_enumerate *enumerate;
|
struct udev_enumerate *enumerate;
|
||||||
struct udev_list_entry *devices, *dev_list_entry;
|
struct udev_list_entry *devices, *dev_list_entry;
|
||||||
|
|
||||||
enumerate = udev_enumerate_new(mpl_udev->udev);
|
enumerate = udev_enumerate_new(udev->context);
|
||||||
|
|
||||||
if (enumerate == NULL) {
|
if (enumerate == NULL)
|
||||||
MPLOG(LOG_ERR, "Error creating udev enumerate");
|
{
|
||||||
exit(EXIT_FAILURE);
|
MPLOG(LOG_ERR, "error creating udev enumerate");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
udev_enumerate_add_match_subsystem(enumerate, "usb");
|
udev_enumerate_add_match_subsystem(enumerate, "usb");
|
||||||
|
@ -54,14 +60,16 @@ void mpl_udev_check_devices(MPL_UDEV *mpl_udev)
|
||||||
|
|
||||||
devices = udev_enumerate_get_list_entry(enumerate);
|
devices = udev_enumerate_get_list_entry(enumerate);
|
||||||
|
|
||||||
if (devices == NULL) {
|
if (devices == NULL)
|
||||||
MPLOG(LOG_ERR, "Error get udev devices");
|
{
|
||||||
exit(EXIT_FAILURE);
|
MPLOG(LOG_ERR, "error get udev devices");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
udev_list_entry_foreach(dev_list_entry, devices) {
|
udev_list_entry_foreach(dev_list_entry, devices)
|
||||||
|
{
|
||||||
const char *syspath = udev_list_entry_get_name(dev_list_entry);
|
const char *syspath = udev_list_entry_get_name(dev_list_entry);
|
||||||
dev = udev_device_new_from_syspath(mpl_udev->udev, syspath);
|
dev = udev_device_new_from_syspath(udev->context, syspath);
|
||||||
|
|
||||||
const char *devtype = udev_device_get_devtype(dev);
|
const char *devtype = udev_device_get_devtype(dev);
|
||||||
if (!(strcmp(devtype, "usb_interface") == 0))
|
if (!(strcmp(devtype, "usb_interface") == 0))
|
||||||
|
@ -71,8 +79,7 @@ void mpl_udev_check_devices(MPL_UDEV *mpl_udev)
|
||||||
if (!(strcmp(driver, "option") == 0))
|
if (!(strcmp(driver, "option") == 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const char *sysattr_value = udev_device_get_sysattr_value(dev,
|
const char *sysattr_value = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
|
||||||
"bInterfaceNumber");
|
|
||||||
printf("Номер порта: %s\n", sysattr_value);
|
printf("Номер порта: %s\n", sysattr_value);
|
||||||
|
|
||||||
// int num = atoi(sysattr_value);
|
// int num = atoi(sysattr_value);
|
||||||
|
@ -85,10 +92,98 @@ void mpl_udev_check_devices(MPL_UDEV *mpl_udev)
|
||||||
}
|
}
|
||||||
|
|
||||||
udev_enumerate_unref(enumerate);
|
udev_enumerate_unref(enumerate);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpl_udev_free(MPL_UDEV *mpl_udev)
|
void mpl_udev_free(MPL_UDEV *udev)
|
||||||
{
|
{
|
||||||
udev_monitor_unref(mpl_udev->monitor);
|
if (udev->monitor)
|
||||||
udev_unref(mpl_udev->udev);
|
{
|
||||||
|
udev_monitor_unref(udev->monitor);
|
||||||
|
udev->monitor = NULL;
|
||||||
|
}
|
||||||
|
if (udev->context)
|
||||||
|
{
|
||||||
|
udev_unref(udev->context);
|
||||||
|
udev->context = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable)
|
||||||
|
{
|
||||||
|
const char *path_to_device = NULL;
|
||||||
|
int port_number = -1;
|
||||||
|
int status = -1;
|
||||||
|
pid_t pid = -1;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(udev->fd, &fds);
|
||||||
|
|
||||||
|
if (select(udev->fd + 1, &fds, NULL, NULL, NULL) <= 0)
|
||||||
|
{
|
||||||
|
if (cancellable->exit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MPLOG(LOG_ERR, "file selection error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct udev_device *dev = udev_monitor_receive_device(udev->monitor);
|
||||||
|
if (dev)
|
||||||
|
{
|
||||||
|
const char *action = udev_device_get_property_value(dev, "ACTION");
|
||||||
|
if (!(strcmp(action, "bind") == 0))
|
||||||
|
{
|
||||||
|
udev_device_unref(dev);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *devtype = udev_device_get_devtype(dev);
|
||||||
|
if (!(strcmp(devtype, "usb_interface") == 0))
|
||||||
|
{
|
||||||
|
udev_device_unref(dev);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *driver = udev_device_get_driver(dev);
|
||||||
|
if (!(strcmp(driver, "option") == 0))
|
||||||
|
{
|
||||||
|
udev_device_unref(dev);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sysattr_value = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
|
||||||
|
if (sysattr_value == NULL)
|
||||||
|
{
|
||||||
|
udev_device_unref(dev);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
port_number = atoi(sysattr_value);
|
||||||
|
path_to_device = udev_device_get_syspath(dev);
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
udev_device_unref(dev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wait(&status);
|
||||||
|
|
||||||
|
udev_device_unref(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mpl_udev_free(udev);
|
||||||
|
|
||||||
|
if (cancellable->exit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sleep(5);
|
||||||
|
printf("exit");
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,22 @@
|
||||||
* Telegram @alexanderzhirov
|
* Telegram @alexanderzhirov
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef MPL_UDEV_H_
|
||||||
|
#define MPL_UDEV_H_
|
||||||
|
|
||||||
|
#include <libudev.h>
|
||||||
#include "mpl-lib.h"
|
#include "mpl-lib.h"
|
||||||
|
|
||||||
void mpl_udev_init(MPL_UDEV *mpl_udev);
|
typedef struct
|
||||||
void mpl_udev_check_devices(MPL_UDEV *mpl_udev);
|
{
|
||||||
|
struct udev *context;
|
||||||
|
struct udev_monitor *monitor;
|
||||||
|
int fd;
|
||||||
|
} MPL_UDEV;
|
||||||
|
|
||||||
|
int mpl_udev_init(MPL_UDEV *udev);
|
||||||
|
void mpl_udev_free(MPL_UDEV *udev);
|
||||||
|
int mpl_udev_check_devices(MPL_UDEV *udev);
|
||||||
|
void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
65
src/mpl.c
65
src/mpl.c
|
@ -5,25 +5,74 @@
|
||||||
* Telegram @alexanderzhirov
|
* Telegram @alexanderzhirov
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#include "mpl.h"
|
#include "mpl.h"
|
||||||
|
|
||||||
|
static MPL *mpl;
|
||||||
|
|
||||||
|
const char *const short_options = "hcv";
|
||||||
|
|
||||||
|
const struct option long_options[] = {
|
||||||
|
{"help", 0, NULL, 'h'},
|
||||||
|
{"check-devices", 0, NULL, 'c'},
|
||||||
|
{"version", 0, NULL, 'v'},
|
||||||
|
{NULL, 0, NULL, 0}};
|
||||||
|
|
||||||
|
[[noreturn]] void static print_usage_and_exit(int code)
|
||||||
|
{
|
||||||
|
printf("Usage: %s [OPTION]...\n\n", MPL_NAME);
|
||||||
|
puts(" -c, --check-devices checking connected devices at startup");
|
||||||
|
puts(" -h, --help display this help text and exit");
|
||||||
|
puts(" -v, --version display version information and exit\n");
|
||||||
|
exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void static print_version_and_exit()
|
||||||
|
{
|
||||||
|
printf("%s version %s\n", MPL_NAME, VERSION);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
static void signals_handler(int signum)
|
static void signals_handler(int signum)
|
||||||
{
|
{
|
||||||
MPLOG(LOG_WARNING, "cancelling the main loop (%d)", signum);
|
MPLOG(LOG_WARNING, "cancelling the mportlink loop (%d)", signum);
|
||||||
|
mpl->cancellable.signal = signum;
|
||||||
|
mpl->cancellable.exit = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int lock_fd = mpl_init();
|
int c;
|
||||||
|
|
||||||
MPL_UDEV *mpl = mpl_new();
|
MPL_PARAMETERS parameters =
|
||||||
mpl_udev_init(mpl);
|
{
|
||||||
|
.check_device = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1)
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'c':
|
||||||
|
parameters.check_device = 1;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
print_version_and_exit();
|
||||||
|
case 'h':
|
||||||
|
print_usage_and_exit(0);
|
||||||
|
case '?':
|
||||||
|
print_usage_and_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpl = mpl_init(¶meters);
|
||||||
|
|
||||||
signal(SIGINT, signals_handler);
|
|
||||||
signal(SIGHUP, signals_handler);
|
signal(SIGHUP, signals_handler);
|
||||||
|
signal(SIGINT, signals_handler);
|
||||||
signal(SIGTERM, signals_handler);
|
signal(SIGTERM, signals_handler);
|
||||||
|
|
||||||
mpl_stop(lock_fd);
|
mpl_loop(mpl);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
mpl_stop(mpl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue