diff --git a/.vscode/settings.json b/.vscode/settings.json index 40c4294..9e0f33e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -37,7 +37,11 @@ "stdio.h": "c", "getopt.h": "c", "mpl-common.h": "c", - "cerrno": "c" + "cerrno": "c", + "string": "c", + "string_view": "c", + "regex.h": "c", + "dirent.h": "c" }, "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/src/mpl-core.c b/src/mpl-core.c index 8f93523..66685ca 100644 --- a/src/mpl-core.c +++ b/src/mpl-core.c @@ -12,7 +12,7 @@ #include #include -int device_path(const char *dirname, int num) +int device_path(const MPL_MODEM *modem) { DIR *dir; struct dirent *ent; @@ -26,10 +26,10 @@ int device_path(const char *dirname, int num) return 1; } - dir = opendir(dirname); + dir = opendir(modem->path); if (dir == NULL) { - printf("Failed to open directory\n"); + printf("Failed to open directory: %s\n", modem->path); regfree(®ex); return 1; } @@ -64,7 +64,7 @@ int device_path(const char *dirname, int num) if (tty != NULL) { - printf("Найдено устройство tty: %s\n", tty); + printf("%s устройство tty: %s\n", modem->action ? "Добавлено" : "Удалено", tty); // if (!num) // print_imei(tty); diff --git a/src/mpl-core.h b/src/mpl-core.h index 76bc1b1..662dca7 100644 --- a/src/mpl-core.h +++ b/src/mpl-core.h @@ -8,6 +8,13 @@ #ifndef MPL_CORE_H_ #define MPL_CORE_H_ -int device_path(const char *dirname, int num); +typedef struct +{ + int port; + char *path; + int action; +} MPL_MODEM; + +int device_path(const MPL_MODEM *modem); #endif diff --git a/src/mpl-lib.c b/src/mpl-lib.c index a7f4fbf..b5ffa5c 100644 --- a/src/mpl-lib.c +++ b/src/mpl-lib.c @@ -6,3 +6,20 @@ */ #include "mpl-lib.h" + +char *mpl_get_copy_string(const char *str) +{ + int size = strlen(str); + char *copy = (char *)calloc(size + 1, sizeof(char)); + + if (!copy) + { + MPLOG(LOG_ERR, "error getting the string"); + return NULL; + } + + strcpy(copy, str); + copy[size] = '\0'; + + return copy; +} diff --git a/src/mpl-lib.h b/src/mpl-lib.h index ca818f0..c769e44 100644 --- a/src/mpl-lib.h +++ b/src/mpl-lib.h @@ -34,4 +34,6 @@ typedef struct int exit; } MPL_CANCELLABLE; +char *mpl_get_copy_string(const char *str); + #endif diff --git a/src/mpl-udev.c b/src/mpl-udev.c index acfee46..983789e 100644 --- a/src/mpl-udev.c +++ b/src/mpl-udev.c @@ -11,6 +11,43 @@ #include #include +void test(struct udev_device *dev) +{ + const char *action = udev_device_get_action(dev); + // printf("action: %s\n", action); + // const char *devpath = udev_device_get_devpath(dev); + // printf("devpath: %s\n", devpath); + + // const char *subsystem = udev_device_get_subsystem(dev); + // printf("subsystem: %s\n", subsystem); + + const char *devtype = udev_device_get_devtype(dev); + // printf("devtype: %s\n", devtype); + + const char *driver = udev_device_get_driver(dev); + // printf("driver: %s\n", driver); + + // const char *sysattr_value = udev_device_get_sysattr_value(dev, "bInterfaceNumber"); + // printf("Номер порта: %s\n", sysattr_value); + + const char *syspath = udev_device_get_syspath(dev); + // printf("syspath: %s\n", syspath); + + // const char *sysname = udev_device_get_sysname(dev); + // printf("sysname: %s\n", sysname); + + // const char *sysnum = udev_device_get_sysnum(dev); + // printf("sysnum: %s\n", sysnum); + + const char *devnode = udev_device_get_devnode(dev); + // printf("devnode: %s\n", devnode); + + // int is_initialized = udev_device_get_is_initialized(dev); + // printf("is_initialized: %d\n", is_initialized); + + printf("action: %s\tdevtype: %s\tdriver: %s\tsyspath: %s\tdevnode: %s\n", action, devtype, driver, syspath, devnode); +} + int mpl_udev_init(MPL_UDEV *udev) { udev->context = udev_new(); @@ -42,12 +79,71 @@ int mpl_udev_init(MPL_UDEV *udev) return 0; } +// action: bind devtype: usb_interface driver: option syspath: /sys/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.3/3-3.3:1.1 +// action: unbind devtype: usb_interface driver: (null) syspath: /sys/devices/pci0000:00/0000:00:14.0/usb3/3-3/3-3.3/3-3.3:1.1 + +static int mpl_device_is_interface(struct udev_device *dev) +{ + return strcmp(udev_device_get_devtype(dev), "usb_interface") == 0; +} + +static int mpl_device_is_modem(struct udev_device *dev) +{ + const char *driver = udev_device_get_driver(dev); + const char *sysattr = udev_device_get_sysattr_value(dev, "bInterfaceNumber"); + + if (!driver || !sysattr) + return 0; + + return mpl_device_is_interface(dev) && strcmp(driver, "option") == 0 && sysattr; +} + +static int mpl_connect_modem(struct udev_device *dev) +{ + const char *action = udev_device_get_property_value(dev, "ACTION"); + + return strcmp(action, "bind") == 0 && mpl_device_is_modem(dev); +} + +static int mpl_disconnect_modem(struct udev_device *dev) +{ + const char *action = udev_device_get_property_value(dev, "ACTION"); + + return strcmp(action, "unbind") == 0 && mpl_device_is_interface(dev); +} + +static MPL_MODEM *mpl_get_modem_info(struct udev_device *dev) +{ + MPL_MODEM *modem = (MPL_MODEM *)calloc(1, sizeof(MPL_MODEM)); + + if (modem == NULL) + { + MPLOG(LOG_ERR, "error creating modem"); + return NULL; + } + + modem->port = atoi(udev_device_get_sysattr_value(dev, "bInterfaceNumber")); + modem->path = mpl_get_copy_string(udev_device_get_syspath(dev)); + modem->action = strcmp(udev_device_get_property_value(dev, "ACTION"), "bind") == 0; + + return modem; +} + +static void mpl_free_modem(MPL_MODEM *modem) +{ + if (modem->path) + free(modem->path); + free(modem); +} + int mpl_udev_check_devices(MPL_UDEV *udev) { struct udev_device *dev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; + MPL_MODEM *modem = NULL; + enumerate = udev_enumerate_new(udev->context); if (enumerate == NULL) @@ -72,24 +168,14 @@ int mpl_udev_check_devices(MPL_UDEV *udev) const char *syspath = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev->context, syspath); - const char *devtype = udev_device_get_devtype(dev); - if (!(strcmp(devtype, "usb_interface") == 0)) + if (!mpl_device_is_modem(dev)) continue; - const char *driver = udev_device_get_driver(dev); - if (!(strcmp(driver, "option") == 0)) - continue; + modem = mpl_get_modem_info(dev); - const char *sysattr_value = udev_device_get_sysattr_value(dev, "bInterfaceNumber"); - printf("Number of port: %s\n", sysattr_value); - - // int num = atoi(sysattr_value); - - const char *devsyspath = udev_device_get_syspath(dev); - printf("syspath: %s\n", devsyspath); - - // device_path(syspaths, num); + device_path(modem); + mpl_free_modem(modem); udev_device_unref(dev); } @@ -114,12 +200,13 @@ void mpl_udev_free(MPL_UDEV *udev) void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable) { - const char *path_to_device = NULL; - int port_number = -1; + MPL_MODEM *modem = NULL; int status = -1; pid_t pid = -1; - while (1) + int stop = 0; + + while (!stop) { fd_set fds; FD_ZERO(&fds); @@ -137,46 +224,25 @@ void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable) 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)) + // test(dev); + + if (mpl_connect_modem(dev)) { - udev_device_unref(dev); - continue; - } + modem = mpl_get_modem_info(dev); - const char *devtype = udev_device_get_devtype(dev); - if (!(strcmp(devtype, "usb_interface") == 0)) + pid = fork(); + if (pid == 0) + { + stop = 1; + } + else + wait(&status); + } + else if (mpl_disconnect_modem(dev)) { - udev_device_unref(dev); - continue; + // unmount ports } - - 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); } } @@ -186,5 +252,8 @@ void mpl_udev_loop(MPL_UDEV *udev, MPL_CANCELLABLE *cancellable) if (cancellable->exit) return; - device_path(path_to_device, port_number); + // printf("path: %s\t port: %d\t action: %d\n", modem->path, modem->port, modem->action); + + device_path(modem); + mpl_free_modem(modem); }