The code is rewritten from scratch, based on udev
This commit is contained in:
parent
f2fce3463d
commit
78e8b7e491
|
@ -19,7 +19,14 @@
|
||||||
"cstdint": "c",
|
"cstdint": "c",
|
||||||
"fcntl.h": "c",
|
"fcntl.h": "c",
|
||||||
"file.h": "c",
|
"file.h": "c",
|
||||||
"dir.h": "c"
|
"dir.h": "c",
|
||||||
|
"mportlink-core.h": "c",
|
||||||
|
"mportlink.h": "c",
|
||||||
|
"mportlink-lib.h": "c",
|
||||||
|
"errno.h": "c"
|
||||||
},
|
},
|
||||||
"cmake.configureOnOpen": false
|
"cmake.configureOnOpen": false,
|
||||||
|
"editor.rulers": [
|
||||||
|
80
|
||||||
|
]
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
"-fdiagnostics-color=always",
|
"-fdiagnostics-color=always",
|
||||||
"-g",
|
"-g",
|
||||||
"*.c",
|
"*.c",
|
||||||
"`pkg-config", "--libs", "--cflags", "mm-glib`",
|
"`pkg-config", "--libs", "udev`",
|
||||||
"-o",
|
"-o",
|
||||||
"${workspaceFolder}/bin/mportlink"
|
"${workspaceFolder}/bin/mportlink"
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [0.2.0](https://github.com/AlexanderZhirov/MPortLink/compare/0.1.0...v0.2.0)
|
## [Unreleased]
|
||||||
|
### Changed
|
||||||
|
- The code is rewritten from scratch, based on `udev`
|
||||||
|
|
||||||
|
## [0.2.0](https://github.com/AlexanderZhirov/MPortLink/compare/0.1.0...0.2.0)
|
||||||
### Changed
|
### Changed
|
||||||
- Creation of links to ports has been moved to the directory `/dev/dongle`
|
- Creation of links to ports has been moved to the directory `/dev/dongle`
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ file(GLOB_RECURSE SRC_FILES_LIST src/*.c)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
pkg_search_module(MM REQUIRED mm-glib)
|
pkg_search_module(UDEV REQUIRED udev)
|
||||||
|
|
||||||
include_directories(${MM_INCLUDE_DIRS})
|
include_directories(${UDEV_INCLUDE_DIRS})
|
||||||
link_directories(${MM_LIBRARY_DIRS})
|
link_directories(${UDEV_LIBRARY_DIRS})
|
||||||
add_definitions(${MM_CFLAGS_OTHER})
|
add_definitions(${UDEV_CFLAGS_OTHER})
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SRC_FILES_LIST})
|
add_executable(${PROJECT_NAME} ${SRC_FILES_LIST})
|
||||||
target_link_libraries(${PROJECT_NAME} ${MM_LIBRARIES})
|
target_link_libraries(${PROJECT_NAME} ${UDEV_LIBRARIES})
|
||||||
|
|
32
README.md
32
README.md
|
@ -1,42 +1,24 @@
|
||||||
# MPortLink
|
# MPortLink
|
||||||
|
|
||||||
|
[![license](https://img.shields.io/github/license/AlexanderZhirov/mportlink.svg?sort=semver&style=for-the-badge&color=green)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
|
||||||
|
[![main](https://img.shields.io/badge/dynamic/json.svg?label=git.zhirov.kz&style=for-the-badge&url=https://git.zhirov.kz/api/v1/repos/alexander/MPortLink/tags&query=$[0].name&color=violet&logo=C)](https://git.zhirov.kz/alexander/MPortLink)
|
||||||
|
[![githab](https://img.shields.io/github/v/tag/AlexanderZhirov/mportlink.svg?sort=semver&style=for-the-badge&color=blue&label=github&logo=C)](https://github.com/AlexanderZhirov/mportlink)
|
||||||
|
[![linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)](https://www.linux.org/)
|
||||||
|
|
||||||
**MPortLink** (*modem port link*) is designed to track connected USB modems and create permanent symbolic links to ports.
|
**MPortLink** (*modem port link*) is designed to track connected USB modems and create permanent symbolic links to ports.
|
||||||
|
|
||||||
MPortLink was developed for direct use of several USB modems when connected to Asterisk telephony, the ports of which were randomly determined by the operating system. The utility allows you to create permanent symbolic links to devices, regardless of the order in which the ports of the USB modem device were defined.
|
MPortLink was developed for direct use of several USB modems when connected to Asterisk telephony, the ports of which were randomly determined by the operating system. The utility allows you to create permanent symbolic links to devices, regardless of the order in which the ports of the USB modem device were defined.
|
||||||
|
|
||||||
Based on [ModemManager](https://gitlab.freedesktop.org/mobile-broadband/ModemManager).
|
|
||||||
|
|
||||||
## Dependency
|
|
||||||
|
|
||||||
The installed `modemmanager` is required for use.
|
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
`libmm-glib` library is required for the build. It is called differently in different distributions, for example: `libmm-glib-dev` or `libmm-glib-devel`.
|
Just need to run the script `build.sh `and `mportlink` will be built in the `build` project directory.
|
||||||
|
|
||||||
After installing the dependencies, you just need to run the script `build.sh `and `mportlink` will be built in the `build` project directory.
|
|
||||||
|
|
||||||
### Manually
|
### Manually
|
||||||
|
|
||||||
```
|
```
|
||||||
gcc -Werror -Wall -Os src/*.c `pkg-config --libs --cflags mm-glib` -o mportlink
|
gcc -Werror -Wall -Os src/*.c `pkg-config --libs libudev` -o mportlink
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using
|
## Using
|
||||||
|
|
||||||
Superuser rights are required to work. Start the daemon and connect your USB modem. In `journalctl` you will see his work. Links to the ports of the connected modem will be created in the `/dev/dongle` directory.
|
Superuser rights are required to work. Start the daemon and connect your USB modem. In `journalctl` you will see his work. Links to the ports of the connected modem will be created in the `/dev/dongle` directory.
|
||||||
|
|
||||||
```
|
|
||||||
Dec 21 13:51:02 solus mportlink[17764]: main: starting the mportlink daemon
|
|
||||||
Dec 21 13:51:26 solus mportlink[17764]: mpl_symlink_ports, dst_path: the symbolic link has been successfully created [/dev/dongle/358**********26-0 -> /dev/ttyUSB0]
|
|
||||||
Dec 21 13:51:26 solus mportlink[17764]: mpl_symlink_ports, dst_path: the symbolic link has been successfully created [/dev/dongle/358**********26-1 -> /dev/ttyUSB1]
|
|
||||||
Dec 21 13:51:41 solus mportlink[17764]: mpl_unlink_ports, dst_path: link was successfully deleted [/dev/dongle/358**********26-0]
|
|
||||||
Dec 21 13:51:41 solus mportlink[17764]: mpl_unlink_ports, dst_path: link was successfully deleted [/dev/dongle/358**********26-1]
|
|
||||||
Dec 21 13:51:48 solus mportlink[17764]: signals_handler: cancelling the operation...
|
|
||||||
Dec 21 13:51:48 solus mportlink[17764]: signals_handler: cancelling the main loop...
|
|
||||||
Dec 21 13:51:48 solus mportlink[17764]: main: stopping the mportlink daemon
|
|
||||||
```
|
|
||||||
|
|
||||||
## To-Do
|
|
||||||
|
|
||||||
Currently, the utility is linked to the ModemManager server, through which the connected modems are identified. It is planned to disconnect from this server, as there is a problem with the capture of the device and the unavailability of using Asterisk.
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Modem Port Link
|
Description=Modem Port Link
|
||||||
After=ModemManager.service
|
After=
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=/usr/bin/mportlink
|
ExecStart=/usr/bin/mportlink
|
||||||
|
|
41
src/mm.c
41
src/mm.c
|
@ -1,41 +0,0 @@
|
||||||
#include "mportlink.h"
|
|
||||||
|
|
||||||
MMManager *mmcli_get_manager_finish(GAsyncResult *res)
|
|
||||||
{
|
|
||||||
return g_task_propagate_pointer(G_TASK(res), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void manager_new_ready(GDBusConnection *connection, GAsyncResult *res, GTask *task)
|
|
||||||
{
|
|
||||||
MMManager *manager;
|
|
||||||
gchar *name_owner;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
manager = mm_manager_new_finish(res, &error);
|
|
||||||
if (!manager)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "manager_new_ready, manager: couldn't create manager: %s\n", error ? error->message : "unknown error");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
name_owner = g_dbus_object_manager_client_get_name_owner(G_DBUS_OBJECT_MANAGER_CLIENT(manager));
|
|
||||||
if (!name_owner)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "manager_new_ready, name_owner: couldn't find the ModemManager process in the bus");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free(name_owner);
|
|
||||||
|
|
||||||
g_task_return_pointer(task, manager, g_object_unref);
|
|
||||||
g_object_unref(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mmcli_get_manager(GDBusConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
|
|
||||||
{
|
|
||||||
GTask *task;
|
|
||||||
|
|
||||||
task = g_task_new(connection, cancellable, callback, user_data);
|
|
||||||
|
|
||||||
mm_manager_new(connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, cancellable, (GAsyncReadyCallback)manager_new_ready, task);
|
|
||||||
}
|
|
11
src/mm.h
11
src/mm.h
|
@ -1,11 +0,0 @@
|
||||||
#include <libmm-glib.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
MMManager *manager;
|
|
||||||
GCancellable *cancellable;
|
|
||||||
} Context;
|
|
||||||
|
|
||||||
MMManager *mmcli_get_manager_finish(GAsyncResult *res);
|
|
||||||
void mmcli_get_manager(GDBusConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
|
|
|
@ -1,253 +1,317 @@
|
||||||
#include "mportlink.h"
|
/*
|
||||||
#include <stdbool.h>
|
* mportlink-core.c
|
||||||
#include <stdio.h>
|
*
|
||||||
#include <unistd.h>
|
* by Alexander Zhirov (alexander@zhirov.kz)
|
||||||
|
* Telegram @alexanderzhirov
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "mportlink-lib.h"
|
||||||
|
#include "mportlink-core.h"
|
||||||
|
|
||||||
|
#define LOCKFILE "/run/lock/mportlink.lock"
|
||||||
#define DEV_PATH "/dev/"
|
#define DEV_PATH "/dev/"
|
||||||
#define DONGLE_PATH "/dev/dongle/"
|
#define DONGLE_PATH (DEV_PATH "dongle/")
|
||||||
|
|
||||||
typedef struct
|
#define MPLOG(PRIORITY, fmt, ...) do { \
|
||||||
|
char buf[256]; \
|
||||||
|
snprintf(buf, sizeof(buf), fmt __VA_OPT__(,) __VA_ARGS__); \
|
||||||
|
PRIORITY < LOG_WARNING ? \
|
||||||
|
syslog(PRIORITY, "%s(): %s (%s)", __func__, buf, \
|
||||||
|
strerror(errno)) : \
|
||||||
|
syslog(PRIORITY, "%s(): %s", __func__, buf); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
static void signals_handler(int signum)
|
||||||
{
|
{
|
||||||
const gchar *manufacturer;
|
MPLOG(LOG_WARNING, "cancelling the main loop (%d)", signum);
|
||||||
const gchar *model;
|
}
|
||||||
const gchar *imei;
|
|
||||||
const gchar *device_identifier;
|
|
||||||
MMModemPortInfo *ports;
|
|
||||||
guint n_ports;
|
|
||||||
} MPLmodem;
|
|
||||||
|
|
||||||
void mpl_create_dongle_dir()
|
void 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)) {
|
||||||
if (!S_ISDIR(st.st_mode))
|
MPLOG(LOG_WARNING, "%s exists and is not a directory",
|
||||||
{
|
DONGLE_PATH);
|
||||||
syslog(LOG_ERR, "mpl_create_dongle_dir: %s exists and is not a directory", DONGLE_PATH);
|
exit(EXIT_FAILURE);
|
||||||
raise(SIGINT);
|
|
||||||
}
|
}
|
||||||
}
|
} else if (mkdir(DONGLE_PATH,
|
||||||
else if (mkdir(DONGLE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
|
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) {
|
||||||
{
|
MPLOG(LOG_ERR, "unable to create a directory %s", DONGLE_PATH);
|
||||||
syslog(LOG_ERR, "mpl_create_dongle_dir: unable to create a directory %s", DONGLE_PATH);
|
exit(EXIT_FAILURE);
|
||||||
raise(SIGINT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MPLmodem *mpl_get_new_modem()
|
int mpl_init()
|
||||||
{
|
{
|
||||||
MPLmodem *modem = (MPLmodem *)calloc(1, sizeof(MPLmodem));
|
openlog(MPL, LOG_PID, LOG_SYSLOG);
|
||||||
|
|
||||||
if (modem == NULL)
|
int lock_fd = open(LOCKFILE, O_CREAT | O_RDWR, 0644);
|
||||||
{
|
if (lock_fd < 0) {
|
||||||
syslog(LOG_ERR, "mpl_get_new_modem, modem: memory allocation error");
|
MPLOG(LOG_ERR, "Unable to create a lockfile");
|
||||||
raise(SIGINT);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return modem;
|
int rc = flock(lock_fd, LOCK_EX | LOCK_NB);
|
||||||
}
|
if (rc || errno == EWOULDBLOCK) {
|
||||||
|
MPLOG(LOG_ERR, "Only one instance of %s is allowed", MPL);
|
||||||
void mpl_free_modem(MPLmodem *modem)
|
exit(EXIT_FAILURE);
|
||||||
{
|
|
||||||
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_create_dongle_dir();
|
||||||
|
|
||||||
mpl_modem->manufacturer = mm_modem_get_manufacturer(mm_modem);
|
MPLOG(LOG_NOTICE, "Starting the %s daemon", MPL);
|
||||||
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);
|
signal(SIGINT, signals_handler);
|
||||||
|
signal(SIGHUP, signals_handler);
|
||||||
|
signal(SIGTERM, signals_handler);
|
||||||
|
|
||||||
g_object_unref(mm_modem);
|
return lock_fd;
|
||||||
|
|
||||||
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)
|
int mpl_stop(const int lock_fd)
|
||||||
{
|
{
|
||||||
char *dst_path = NULL;
|
flock(lock_fd, LOCK_UN);
|
||||||
|
|
||||||
guint size_id = snprintf(NULL, 0, "-%d", index);
|
MPLOG(LOG_NOTICE, "Stopping the %s daemon", MPL);
|
||||||
char *id = (char *)calloc(size_id + 1, sizeof(char));
|
closelog();
|
||||||
|
|
||||||
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);
|
// typedef struct
|
||||||
strcat(src_path, port_name);
|
// {
|
||||||
|
// const gchar *manufacturer;
|
||||||
|
// const gchar *model;
|
||||||
|
// const gchar *imei;
|
||||||
|
// const gchar *device_identifier;
|
||||||
|
// MMModemPortInfo *ports;
|
||||||
|
// guint n_ports;
|
||||||
|
// } MPLmodem;
|
||||||
|
|
||||||
return src_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mpl_symlink_ports(MPLmodem *modem)
|
// MPLmodem *mpl_get_new_modem()
|
||||||
{
|
// {
|
||||||
for (guint i = 0; i < modem->n_ports; i++)
|
// MPLmodem *modem = (MPLmodem *)calloc(1, sizeof(MPLmodem));
|
||||||
{
|
|
||||||
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)
|
// if (modem == NULL)
|
||||||
{
|
// {
|
||||||
syslog(LOG_ERR, "mpl_symlink_ports, src_path: device file is not available [%s]", src_path);
|
// syslog(LOG_ERR, "mpl_get_new_modem, modem: memory allocation error");
|
||||||
free(src_path);
|
// raise(SIGINT);
|
||||||
free(dst_path);
|
// }
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lstat(dst_path, &st) == 0)
|
// return modem;
|
||||||
{
|
// }
|
||||||
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)
|
// void mpl_free_modem(MPLmodem *modem)
|
||||||
syslog(LOG_NOTICE, "mpl_symlink_ports, dst_path: the symbolic link has been successfully created [%s -> %s]", dst_path, src_path);
|
// {
|
||||||
else
|
// if (modem->n_ports && modem->ports)
|
||||||
syslog(LOG_ERR, "mpl_symlink_ports, dst_path: error creating a symbolic link [%s -> %s]", dst_path, src_path);
|
// mm_modem_port_info_array_free(modem->ports, modem->n_ports);
|
||||||
|
// free(modem);
|
||||||
|
// }
|
||||||
|
|
||||||
free(src_path);
|
// void mpl_print_modem_info(MPLmodem *modem, bool connected)
|
||||||
free(dst_path);
|
// {
|
||||||
}
|
// gchar *status;
|
||||||
}
|
// status = connected ? "Connected" : "Disconnected";
|
||||||
|
|
||||||
void mpl_unlink_ports(MPLmodem *modem)
|
// 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++)
|
|
||||||
{
|
|
||||||
char *dst_path = mpl_get_dst_path(i, modem->imei);
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (lstat(dst_path, &st) == -1)
|
// for (guint i = 0; i < modem->n_ports; i++)
|
||||||
{
|
// {
|
||||||
syslog(LOG_WARNING, "mpl_unlink_ports, dst_path: a symbolic link to the device not exists [%s]", dst_path);
|
// if (i + 1 < modem->n_ports)
|
||||||
free(dst_path);
|
// {
|
||||||
continue;
|
// 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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (unlink(dst_path) == 0)
|
// MPLmodem *mpl_get_new_modem_info(MMObject *obj)
|
||||||
syslog(LOG_NOTICE, "mpl_unlink_ports, dst_path: link was successfully deleted [%s]", dst_path);
|
// {
|
||||||
else
|
// MPLmodem *mpl_modem = NULL;
|
||||||
syslog(LOG_ERR, "mpl_unlink_ports, dst_path: link could not be deleted [%s]", dst_path);
|
// MMModem *mm_modem = mm_object_get_modem(obj);
|
||||||
|
|
||||||
free(dst_path);
|
// if (mm_modem == NULL)
|
||||||
}
|
// {
|
||||||
}
|
// syslog(LOG_ERR, "mpl_get_new_modem_info, mm_modem: modem does not implement the interface");
|
||||||
|
// return NULL;
|
||||||
|
// }
|
||||||
|
|
||||||
void mpl_device_added(MMManager *manager, MMObject *obj)
|
// mpl_modem = mpl_get_new_modem();
|
||||||
{
|
|
||||||
MPLmodem *modem = mpl_get_new_modem_info(obj);
|
|
||||||
|
|
||||||
if (modem == NULL)
|
// mpl_modem->manufacturer = mm_modem_get_manufacturer(mm_modem);
|
||||||
return;
|
// 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);
|
||||||
|
|
||||||
// mpl_print_modem_info(modem, true);
|
// gboolean success = mm_modem_get_ports(mm_modem, &mpl_modem->ports, &mpl_modem->n_ports);
|
||||||
mpl_symlink_ports(modem);
|
|
||||||
|
|
||||||
mpl_free_modem(modem);
|
// g_object_unref(mm_modem);
|
||||||
}
|
|
||||||
|
|
||||||
void mpl_device_removed(MMManager *manager, MMObject *obj)
|
// if (success)
|
||||||
{
|
// return mpl_modem;
|
||||||
MPLmodem *modem = mpl_get_new_modem_info(obj);
|
// else
|
||||||
|
// syslog(LOG_WARNING, "mpl_get_new_modem_info, success: error receiving modem ports");
|
||||||
|
|
||||||
if (modem == NULL)
|
// mpl_free_modem(mpl_modem);
|
||||||
return;
|
|
||||||
|
|
||||||
// mpl_print_modem_info(modem, false);
|
// return NULL;
|
||||||
mpl_unlink_ports(modem);
|
// }
|
||||||
|
|
||||||
mpl_free_modem(modem);
|
// 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);
|
||||||
|
// }
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* mportlink-core.h
|
||||||
|
*
|
||||||
|
* by Alexander Zhirov (alexander@zhirov.kz)
|
||||||
|
* Telegram @alexanderzhirov
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MPL_CORE_H_
|
||||||
|
#define MPL_CORE_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define MPL "mportlink"
|
||||||
|
|
||||||
|
int mpl_init();
|
||||||
|
int mpl_stop(const int lock_fd);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
* mportlink-lib.c
|
||||||
|
*
|
||||||
|
* by Alexander Zhirov (alexander@zhirov.kz)
|
||||||
|
* Telegram @alexanderzhirov
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mportlink-lib.h"
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* mportlink-lib.h
|
||||||
|
*
|
||||||
|
* by Alexander Zhirov (alexander@zhirov.kz)
|
||||||
|
* Telegram @alexanderzhirov
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MPL_LIB_H_
|
||||||
|
#define MPL_LIB_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,90 +1,17 @@
|
||||||
|
/*
|
||||||
|
* mportlink.c
|
||||||
|
*
|
||||||
|
* by Alexander Zhirov (alexander@zhirov.kz)
|
||||||
|
* Telegram @alexanderzhirov
|
||||||
|
*/
|
||||||
|
|
||||||
#include "mportlink.h"
|
#include "mportlink.h"
|
||||||
#include <sys/file.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#define LOCKFILE "/run/lock/mportlink.lock"
|
|
||||||
#define MPL "mportlink"
|
|
||||||
|
|
||||||
static Context *ctx;
|
|
||||||
static GCancellable *cancellable;
|
|
||||||
static GMainLoop *loop;
|
|
||||||
|
|
||||||
static void signals_handler(int signum)
|
|
||||||
{
|
|
||||||
if (cancellable)
|
|
||||||
{
|
|
||||||
if (!g_cancellable_is_cancelled(cancellable))
|
|
||||||
{
|
|
||||||
syslog(LOG_WARNING, "signals_handler: cancelling the operation...");
|
|
||||||
g_cancellable_cancel(cancellable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loop && g_main_loop_is_running(loop))
|
|
||||||
{
|
|
||||||
syslog(LOG_WARNING, "signals_handler: cancelling the main loop...");
|
|
||||||
g_main_loop_quit(loop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_manager_ready(GObject *source, GAsyncResult *result, gpointer none)
|
|
||||||
{
|
|
||||||
ctx->manager = mmcli_get_manager_finish(result);
|
|
||||||
|
|
||||||
g_signal_connect(ctx->manager, "object-added", G_CALLBACK(mpl_device_added), NULL);
|
|
||||||
g_signal_connect(ctx->manager, "object-removed", G_CALLBACK(mpl_device_removed), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
openlog(MPL, LOG_PID, LOG_SYSLOG);
|
int lock_fd = mpl_init();
|
||||||
|
|
||||||
int lock_fd = open(LOCKFILE, O_CREAT | O_RDWR, 0666);
|
mpl_stop(lock_fd);
|
||||||
int rc = flock(lock_fd, LOCK_EX | LOCK_NB);
|
|
||||||
|
|
||||||
if (rc || errno == EWOULDBLOCK)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "main: only one instance of %s is allowed", MPL);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
syslog(LOG_NOTICE, "main: starting the %s daemon", MPL);
|
|
||||||
|
|
||||||
mpl_create_dongle_dir();
|
|
||||||
|
|
||||||
GError *error = NULL;
|
|
||||||
GDBusConnection *connection = NULL;
|
|
||||||
|
|
||||||
signal(SIGINT, signals_handler);
|
|
||||||
signal(SIGHUP, signals_handler);
|
|
||||||
signal(SIGTERM, signals_handler);
|
|
||||||
|
|
||||||
connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
|
|
||||||
if (!connection)
|
|
||||||
{
|
|
||||||
syslog(LOG_ERR, "main, connection: couldn't get bus: %s", error->message);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
cancellable = g_cancellable_new();
|
|
||||||
loop = g_main_loop_new(NULL, FALSE);
|
|
||||||
|
|
||||||
ctx = g_new0(Context, 1);
|
|
||||||
if (cancellable)
|
|
||||||
ctx->cancellable = g_object_ref(cancellable);
|
|
||||||
|
|
||||||
mmcli_get_manager(connection, cancellable, (GAsyncReadyCallback)get_manager_ready, NULL);
|
|
||||||
g_main_loop_run(loop);
|
|
||||||
|
|
||||||
if (cancellable)
|
|
||||||
g_object_unref(cancellable);
|
|
||||||
g_main_loop_unref(loop);
|
|
||||||
g_object_unref(connection);
|
|
||||||
|
|
||||||
flock(lock_fd, LOCK_UN);
|
|
||||||
|
|
||||||
syslog(LOG_NOTICE, "main: stopping the %s daemon", MPL);
|
|
||||||
closelog();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
#include "mm.h"
|
/*
|
||||||
|
* mportlink.h
|
||||||
|
*
|
||||||
|
* by Alexander Zhirov (alexander@zhirov.kz)
|
||||||
|
* Telegram @alexanderzhirov
|
||||||
|
*/
|
||||||
|
|
||||||
void mpl_create_dongle_dir();
|
#ifndef MPL_H_
|
||||||
void mpl_device_added(MMManager *manager, MMObject *obj);
|
#define MPL_H_
|
||||||
void mpl_device_removed(MMManager *manager, MMObject *obj);
|
|
||||||
|
#include "mportlink-lib.h"
|
||||||
|
#include "mportlink-core.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Reference in New Issue