From 79c7a763fc307e194794df995cff90fccd1c9b10 Mon Sep 17 00:00:00 2001 From: Simo Piiroinen Date: Fri, 6 Jul 2018 16:00:17 +0300 Subject: [PATCH] [usb_moded] Add configfs support. JB#42083 Add custom Makefile for faster smoke-test rebuilds without spending time in configure, autotools, document generation and/or rolling rpm packages. Add multiple include protection to all header files. Move function prototypes away from header files that included in the development package. Mass rename functions to have a prefix giving context for the function. For the most part the prefix is derived from the name of the compilation module containing the function. Mass normalize indentation to four spaces in all source files. Augment author lists on each source file based on git committers. Remove "inline" attributes from not-really-inlineable functions. Remove .gitignore. Remove unused modules-android.c source file. Define _GNU_SOURCE for whole build rather than in individual files. Fix resource leaks here and there. Try to avoid hard-coding android usb paths. Add configfs backend for usb cadget configuration. Probe supported backends (configfs, android usb, or kmod) on usb-moded startup and make them mutually exclusive with each other. Allow configfs and android usb control structures some time to show up if usb-moded is started during device bootup. Refactor udev event listener to utilize a state machine. Simplifies book keeping and makes pc/charger detection heuristics easier to control. Refactor mode selection to utilize three interconnected mini state machines. Allows separating logically wanted mode from mode programmed to usb and mode exposed over D-Bus. Signed-off-by: Simo Piiroinen --- .depend | 448 ++++ .gitignore | 9 - Makefile.custom | 328 +++ config-static.h | 32 + depend_filter.py | 70 + rpm/usb-moded.spec | 5 +- scripts/set_usb_mode.sh | 392 ++++ src/Makefile.am | 8 +- src/usb_moded-android.c | 282 +-- src/usb_moded-android.h | 79 +- src/usb_moded-appsync-dbus-private.h | 53 +- src/usb_moded-appsync-dbus.c | 491 ++--- src/usb_moded-appsync-dbus.h | 57 +- src/usb_moded-appsync.c | 694 +++--- src/usb_moded-appsync.h | 115 +- src/usb_moded-config-private.h | 102 +- src/usb_moded-config.c | 1276 +++++------ src/usb_moded-config.h | 169 +- src/usb_moded-configfs.c | 673 ++++++ src/usb_moded-configfs.h | 42 + src/usb_moded-dbus-private.h | 117 +- src/usb_moded-dbus.c | 1130 +++++----- src/usb_moded-dbus.h | 133 +- src/usb_moded-devicelock.c | 141 +- src/usb_moded-devicelock.h | 79 +- src/usb_moded-dsme.c | 74 +- src/usb_moded-dsme.h | 57 +- src/usb_moded-dyn-config.c | 336 +-- src/usb_moded-dyn-config.h | 189 +- src/usb_moded-hw-ab.h | 39 - src/usb_moded-lock.h | 31 - src/usb_moded-log.c | 262 ++- src/usb_moded-log.h | 148 +- src/usb_moded-mac.c | 175 +- src/usb_moded-mac.h | 48 +- src/usb_moded-modes.h | 79 +- src/usb_moded-modesetting.c | 1046 +++++----- src/usb_moded-modesetting.h | 89 +- src/usb_moded-modules-android.c | 120 -- src/usb_moded-modules.c | 543 +++-- src/usb_moded-modules.h | 106 +- src/usb_moded-network.c | 1970 ++++++++--------- src/usb_moded-network.h | 76 +- src/usb_moded-ssu.c | 59 +- src/usb_moded-ssu.h | 50 +- src/usb_moded-systemd.c | 70 +- src/usb_moded-systemd.h | 56 +- src/usb_moded-trigger.c | 396 ++-- src/usb_moded-trigger.h | 50 +- src/usb_moded-udev.c | 1085 ++++++---- src/usb_moded-udev.h | 44 + src/usb_moded-util.c | 666 +++--- src/usb_moded.c | 2901 +++++++++++++++----------- src/usb_moded.h | 232 +- systemd/buteo-mtpd.service | 9 + utils/udev-search.c | 219 +- 56 files changed, 10793 insertions(+), 7357 deletions(-) create mode 100644 .depend delete mode 100644 .gitignore create mode 100644 Makefile.custom create mode 100644 config-static.h create mode 100755 depend_filter.py create mode 100755 scripts/set_usb_mode.sh create mode 100644 src/usb_moded-configfs.c create mode 100644 src/usb_moded-configfs.h delete mode 100644 src/usb_moded-hw-ab.h delete mode 100644 src/usb_moded-lock.h delete mode 100644 src/usb_moded-modules-android.c create mode 100644 src/usb_moded-udev.h create mode 100644 systemd/buteo-mtpd.service diff --git a/.depend b/.depend new file mode 100644 index 0000000..013c8d4 --- /dev/null +++ b/.depend @@ -0,0 +1,448 @@ +src/usb_moded-android.o:\ + src/usb_moded-android.c\ + config-static.h\ + src/usb_moded-android.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-mac.h\ + src/usb_moded-modesetting.h\ + src/usb_moded.h\ + +src/usb_moded-android.pic.o:\ + src/usb_moded-android.c\ + config-static.h\ + src/usb_moded-android.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-mac.h\ + src/usb_moded-modesetting.h\ + src/usb_moded.h\ + +src/usb_moded-appsync-dbus.o:\ + src/usb_moded-appsync-dbus.c\ + config-static.h\ + src/usb_moded-appsync-dbus-private.h\ + src/usb_moded-appsync-dbus.h\ + src/usb_moded-appsync.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded.h\ + +src/usb_moded-appsync-dbus.pic.o:\ + src/usb_moded-appsync-dbus.c\ + config-static.h\ + src/usb_moded-appsync-dbus-private.h\ + src/usb_moded-appsync-dbus.h\ + src/usb_moded-appsync.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded.h\ + +src/usb_moded-appsync.o:\ + src/usb_moded-appsync.c\ + src/usb_moded-appsync-dbus-private.h\ + src/usb_moded-appsync-dbus.h\ + src/usb_moded-appsync.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-systemd.h\ + +src/usb_moded-appsync.pic.o:\ + src/usb_moded-appsync.c\ + src/usb_moded-appsync-dbus-private.h\ + src/usb_moded-appsync-dbus.h\ + src/usb_moded-appsync.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-systemd.h\ + +src/usb_moded-config.o:\ + src/usb_moded-config.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-ssu.h\ + src/usb_moded.h\ + +src/usb_moded-config.pic.o:\ + src/usb_moded-config.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-ssu.h\ + src/usb_moded.h\ + +src/usb_moded-configfs.o:\ + src/usb_moded-configfs.c\ + config-static.h\ + src/usb_moded-android.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-configfs.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-mac.h\ + src/usb_moded-modesetting.h\ + src/usb_moded.h\ + +src/usb_moded-configfs.pic.o:\ + src/usb_moded-configfs.c\ + config-static.h\ + src/usb_moded-android.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-configfs.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-mac.h\ + src/usb_moded-modesetting.h\ + src/usb_moded.h\ + +src/usb_moded-dbus.o:\ + src/usb_moded-dbus.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-network.h\ + src/usb_moded.h\ + +src/usb_moded-dbus.pic.o:\ + src/usb_moded-dbus.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-network.h\ + src/usb_moded.h\ + +src/usb_moded-devicelock.o:\ + src/usb_moded-devicelock.c\ + config-static.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-devicelock.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded.h\ + +src/usb_moded-devicelock.pic.o:\ + src/usb_moded-devicelock.c\ + config-static.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-devicelock.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded.h\ + +src/usb_moded-dsme.o:\ + src/usb_moded-dsme.c\ + config-static.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dsme.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modesetting.h\ + src/usb_moded.h\ + +src/usb_moded-dsme.pic.o:\ + src/usb_moded-dsme.c\ + config-static.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dsme.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modesetting.h\ + src/usb_moded.h\ + +src/usb_moded-dyn-config.o:\ + src/usb_moded-dyn-config.c\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + +src/usb_moded-dyn-config.pic.o:\ + src/usb_moded-dyn-config.c\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + +src/usb_moded-log.o:\ + src/usb_moded-log.c\ + src/usb_moded-log.h\ + +src/usb_moded-log.pic.o:\ + src/usb_moded-log.c\ + src/usb_moded-log.h\ + +src/usb_moded-mac.o:\ + src/usb_moded-mac.c\ + src/usb_moded-log.h\ + src/usb_moded-mac.h\ + +src/usb_moded-mac.pic.o:\ + src/usb_moded-mac.c\ + src/usb_moded-log.h\ + src/usb_moded-mac.h\ + +src/usb_moded-modesetting.o:\ + src/usb_moded-modesetting.c\ + config-static.h\ + src/usb_moded-android.h\ + src/usb_moded-appsync.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-configfs.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-modules.h\ + src/usb_moded-network.h\ + src/usb_moded.h\ + +src/usb_moded-modesetting.pic.o:\ + src/usb_moded-modesetting.c\ + config-static.h\ + src/usb_moded-android.h\ + src/usb_moded-appsync.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-configfs.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-modules.h\ + src/usb_moded-network.h\ + src/usb_moded.h\ + +src/usb_moded-modules.o:\ + src/usb_moded-modules.c\ + config-static.h\ + src/usb_moded-config.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-modules.h\ + src/usb_moded.h\ + +src/usb_moded-modules.pic.o:\ + src/usb_moded-modules.c\ + config-static.h\ + src/usb_moded-config.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-modules.h\ + src/usb_moded.h\ + +src/usb_moded-network.o:\ + src/usb_moded-network.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-network.h\ + src/usb_moded.h\ + +src/usb_moded-network.pic.o:\ + src/usb_moded-network.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-network.h\ + src/usb_moded.h\ + +src/usb_moded-ssu.o:\ + src/usb_moded-ssu.c\ + src/usb_moded-log.h\ + src/usb_moded-ssu.h\ + +src/usb_moded-ssu.pic.o:\ + src/usb_moded-ssu.c\ + src/usb_moded-log.h\ + src/usb_moded-ssu.h\ + +src/usb_moded-systemd.o:\ + src/usb_moded-systemd.c\ + config-static.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-systemd.h\ + src/usb_moded.h\ + +src/usb_moded-systemd.pic.o:\ + src/usb_moded-systemd.c\ + config-static.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-systemd.h\ + src/usb_moded.h\ + +src/usb_moded-trigger.o:\ + src/usb_moded-trigger.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-devicelock.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-trigger.h\ + src/usb_moded-udev.h\ + src/usb_moded.h\ + +src/usb_moded-trigger.pic.o:\ + src/usb_moded-trigger.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-devicelock.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-trigger.h\ + src/usb_moded-udev.h\ + src/usb_moded.h\ + +src/usb_moded-udev.o:\ + src/usb_moded-udev.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-udev.h\ + src/usb_moded.h\ + +src/usb_moded-udev.pic.o:\ + src/usb_moded-udev.c\ + config-static.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-modes.h\ + src/usb_moded-udev.h\ + src/usb_moded.h\ + +src/usb_moded-util.o:\ + src/usb_moded-util.c\ + src/usb_moded-dbus.h\ + +src/usb_moded-util.pic.o:\ + src/usb_moded-util.c\ + src/usb_moded-dbus.h\ + +src/usb_moded.o:\ + src/usb_moded.c\ + config-static.h\ + src/usb_moded-android.h\ + src/usb_moded-appsync.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-configfs.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-devicelock.h\ + src/usb_moded-dsme.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-mac.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-modules.h\ + src/usb_moded-network.h\ + src/usb_moded-systemd.h\ + src/usb_moded-trigger.h\ + src/usb_moded-udev.h\ + src/usb_moded.h\ + +src/usb_moded.pic.o:\ + src/usb_moded.c\ + config-static.h\ + src/usb_moded-android.h\ + src/usb_moded-appsync.h\ + src/usb_moded-config-private.h\ + src/usb_moded-config.h\ + src/usb_moded-configfs.h\ + src/usb_moded-dbus-private.h\ + src/usb_moded-dbus.h\ + src/usb_moded-devicelock.h\ + src/usb_moded-dsme.h\ + src/usb_moded-dyn-config.h\ + src/usb_moded-log.h\ + src/usb_moded-mac.h\ + src/usb_moded-modes.h\ + src/usb_moded-modesetting.h\ + src/usb_moded-modules.h\ + src/usb_moded-network.h\ + src/usb_moded-systemd.h\ + src/usb_moded-trigger.h\ + src/usb_moded-udev.h\ + src/usb_moded.h\ + +utils/udev-search.o:\ + utils/udev-search.c\ + +utils/udev-search.pic.o:\ + utils/udev-search.c\ + diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1b4eb3e..0000000 --- a/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.o -config.h* -000* -src/.deps/* -RPMS* -installroot* -autom4te.cache -cov-int -docs/html diff --git a/Makefile.custom b/Makefile.custom new file mode 100644 index 0000000..2660fc4 --- /dev/null +++ b/Makefile.custom @@ -0,0 +1,328 @@ +# ----------------------------------------------------------- -*- mode: sh -*- +# Package version +VERSION := 0.86.0 + +# Dummy default install dir - override from packaging scripts +DESTDIR ?= /tmp/usb-moded-test-install + +# ---------------------------------------------------------------------------- +# Standard directories +# ---------------------------------------------------------------------------- + +_PREFIX ?= /usr# # /usr +_INCLUDEDIR ?= $(_PREFIX)/include# # /usr/include +_EXEC_PREFIX ?= $(_PREFIX)# # /usr +_BINDIR ?= $(_EXEC_PREFIX)/bin# # /usr/bin +_SBINDIR ?= $(_EXEC_PREFIX)/sbin# # /usr/sbin +_LIBEXECDIR ?= $(_EXEC_PREFIX)/libexec# # /usr/libexec +_LIBDIR ?= $(_EXEC_PREFIX)/lib# # /usr/lib +_SYSCONFDIR ?= /etc# # /etc +_DATADIR ?= $(_PREFIX)/share# # /usr/share +_MANDIR ?= $(_DATADIR)/man# # /usr/share/man +_INFODIR ?= $(_DATADIR)/info# # /usr/share/info +_DEFAULTDOCDIR ?= $(_DATADIR)/doc# # /usr/share/doc +_LOCALSTATEDIR ?= /var# # /var +_UNITDIR ?= /lib/systemd/system# +_TESTSDIR ?= /opt/tests# # /opt/tests + +# ---------------------------------------------------------------------------- +# Install directories +# ---------------------------------------------------------------------------- + +USB_MODED_SBIN_PATH ?= $(_SBINDIR) + +# ---------------------------------------------------------------------------- +# Files to build / install +# ---------------------------------------------------------------------------- + +TARGETS_SBIN += usb_moded +TARGETS_SBIN += usb_moded_util + +TARGETS_ALL += $(TARGETS_PLUGIN) $(TARGETS_SBIN) $(TARGETS_BIN) + +TARGETS_ALL += udev-search + +# ---------------------------------------------------------------------------- +# Top level targets +# ---------------------------------------------------------------------------- + +.PHONY: build install clean distclean mostlyclean + +build:: $(TARGETS_ALL) + +install:: build + +clean:: mostlyclean + $(RM) $(TARGETS_ALL) + +distclean:: clean + +mostlyclean:: + $(RM) *.o *~ *.bak */*.o */*~ */*.bak + +install :: install_main + +install_main:: + # sbin executables + install -d -m 755 $(DESTDIR)$(USB_MODED_SBIN_PATH) + install -m 755 $(TARGETS_SBIN) $(DESTDIR)$(USB_MODED_SBIN_PATH) + # config directories and files + install -d -m 755 $(DESTDIR)/etc + # /etc/udhcpd.conf + install -d -m 755 $(DESTDIR)/etc/usb-moded/ + install -d -m 755 $(DESTDIR)/etc/usb-moded/dyn-modes + install -d -m 755 $(DESTDIR)/etc/usb-moded/run + install -d -m 755 $(DESTDIR)/etc/modprobe.d + # /etc/modprobe.d/g_ether.conf + # /etc/modprobe.d/usb_moded.conf + install -d -m 755 $(DESTDIR)/etc/tmpfiles.d + # /etc/tmpfiles.d/usb-moded.conf + install -d -m 755 $(DESTDIR)/etc/dbus-1/system.d + install -m 644 debian/usb_moded.conf $(DESTDIR)/etc/dbus-1/system.d/ + +# ---------------------------------------------------------------------------- +# Build rules +# ---------------------------------------------------------------------------- + +%.pic.o : %.c ; $(CC) -o $@ -c $< -fPIC $(CPPFLAGS) $(CFLAGS) +%.so : %.pic.o ; $(CC) -shared -o $@ $^ $(LDFLAGS) $(LDLIBS) +%.o : %.c ; $(CC) -o $@ -c $< $(CPPFLAGS) $(CFLAGS) +% : %.o ; $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) +%.a : ; $(AR) ru $@ $^ + +# ---------------------------------------------------------------------------- +# Preprocessor options +# ---------------------------------------------------------------------------- + +# Preprocessor Defaults +CPPFLAGS += -D_GNU_SOURCE +CPPFLAGS += -D_FILE_OFFSET_BITS=64 +CPPFLAGS += -D_FORTIFY_SOURCE=2 + +# usb-moded specific options +CPPFLAGS += -DSTATIC_CONFIG +CPPFLAGS += -DSYSTEMD +CPPFLAGS += -DCONNMAN +CPPFLAGS += -DAPP_SYNC +CPPFLAGS += -DUSE_MER_SSU +CPPFLAGS += -DMEEGOLOCK +CPPFLAGS += -DDEBUG + +# ---------------------------------------------------------------------------- +# Compiler options +# ---------------------------------------------------------------------------- + +CFLAGS += -std=c99 +CFLAGS += -O2 +CFLAGS += -g +CFLAGS += -Wall +CFLAGS += -Wwrite-strings +CFLAGS += -Wmissing-prototypes +#CFLAGS += -Wextra +#CFLAGS += -Werror + +# ---------------------------------------------------------------------------- +# Linker options +# ---------------------------------------------------------------------------- + +LDFLAGS += -pthread +LDFLAGS += -g +LDFLAGS += -pthread +LDFLAGS += -Wl,--as-needed + +LDLIBS += -ldl + +# ---------------------------------------------------------------------------- +# Flags from pkg-config +# ---------------------------------------------------------------------------- +PKG_NAMES += dbus-1 +PKG_NAMES += dbus-glib-1 +PKG_NAMES += glib-2.0 +PKG_NAMES += libudev +PKG_NAMES += libkmod +PKG_NAMES += libsystemd +PKG_NAMES += ssu-sysinfo +PKG_NAMES += dsme + +maintenance = normalize clean distclean mostlyclean +maintenance += protos-post + +intersection = $(strip $(foreach w,$1, $(filter $w,$2))) +ifneq ($(call intersection,$(maintenance),$(MAKECMDGOALS)),) +PKG_CONFIG ?= true +endif + +ifneq ($(strip $(PKG_NAMES)),) +PKG_CONFIG ?= pkg-config +PKG_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(PKG_NAMES)) +PKG_LDLIBS := $(shell $(PKG_CONFIG) --libs $(PKG_NAMES)) +PKG_CPPFLAGS := $(filter -D%,$(PKG_CFLAGS)) $(filter -I%,$(PKG_CFLAGS)) +PKG_CFLAGS := $(filter-out -I%, $(filter-out -D%, $(PKG_CFLAGS))) +endif + +CPPFLAGS += $(PKG_CPPFLAGS) +CFLAGS += $(PKG_CFLAGS) +LDLIBS += $(PKG_LDLIBS) + +# ---------------------------------------------------------------------------- +# usb_moded +# ---------------------------------------------------------------------------- + +usb_moded-OBJS += src/usb_moded.o +usb_moded-OBJS += src/usb_moded-android.o +usb_moded-OBJS += src/usb_moded-appsync.o +usb_moded-OBJS += src/usb_moded-config.o +usb_moded-OBJS += src/usb_moded-configfs.o +usb_moded-OBJS += src/usb_moded-dbus.o +usb_moded-OBJS += src/usb_moded-devicelock.o +usb_moded-OBJS += src/usb_moded-dsme.o +usb_moded-OBJS += src/usb_moded-dyn-config.o +usb_moded-OBJS += src/usb_moded-log.o +usb_moded-OBJS += src/usb_moded-mac.o +usb_moded-OBJS += src/usb_moded-modesetting.o +usb_moded-OBJS += src/usb_moded-modules.o +usb_moded-OBJS += src/usb_moded-network.o +usb_moded-OBJS += src/usb_moded-ssu.o +usb_moded-OBJS += src/usb_moded-systemd.o +usb_moded-OBJS += src/usb_moded-trigger.o +usb_moded-OBJS += src/usb_moded-udev.o + +usb_moded : $(usb_moded-OBJS) + $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +# ---------------------------------------------------------------------------- +# udev-search +# ---------------------------------------------------------------------------- + +udev-search-OBJS += utils/udev-search.o + +udev-search : $(udev-search-OBJS) + $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +# ---------------------------------------------------------------------------- +# usb_moded_util +# ---------------------------------------------------------------------------- + +usb_moded_util-OBJS += src/usb_moded-util.o + +usb_moded_util : $(usb_moded_util-OBJS) + $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) + +# ---------------------------------------------------------------------------- +# SOURCE FILES +# ---------------------------------------------------------------------------- + +# Files without whitespace issues + +CLEAN_SOURCES += src/usb_moded-android.c +CLEAN_SOURCES += src/usb_moded-appsync-dbus.c +CLEAN_SOURCES += src/usb_moded-appsync.c +CLEAN_SOURCES += src/usb_moded-config.c +CLEAN_SOURCES += src/usb_moded-configfs.c +CLEAN_SOURCES += src/usb_moded-dbus.c +CLEAN_SOURCES += src/usb_moded-devicelock.c +CLEAN_SOURCES += src/usb_moded-dsme.c +CLEAN_SOURCES += src/usb_moded-dyn-config.c +CLEAN_SOURCES += src/usb_moded-log.c +CLEAN_SOURCES += src/usb_moded-mac.c +CLEAN_SOURCES += src/usb_moded-modesetting.c +CLEAN_SOURCES += src/usb_moded-modules.c +CLEAN_SOURCES += src/usb_moded-network.c +CLEAN_SOURCES += src/usb_moded-ssu.c +CLEAN_SOURCES += src/usb_moded-systemd.c +CLEAN_SOURCES += src/usb_moded-trigger.c +CLEAN_SOURCES += src/usb_moded-udev.c +CLEAN_SOURCES += src/usb_moded-util.c +CLEAN_SOURCES += src/usb_moded.c +CLEAN_SOURCES += utils/udev-search.c + +CLEAN_HEADERS += src/usb_moded-android.h +CLEAN_HEADERS += src/usb_moded-appsync-dbus-private.h +CLEAN_HEADERS += src/usb_moded-appsync-dbus.h +CLEAN_HEADERS += src/usb_moded-appsync.h +CLEAN_HEADERS += src/usb_moded-config-private.h +CLEAN_HEADERS += src/usb_moded-config.h +CLEAN_HEADERS += src/usb_moded-configfs.h +CLEAN_HEADERS += src/usb_moded-dbus-private.h +CLEAN_HEADERS += src/usb_moded-dbus.h +CLEAN_HEADERS += src/usb_moded-devicelock.h +CLEAN_HEADERS += src/usb_moded-dsme.h +CLEAN_HEADERS += src/usb_moded-dyn-config.h +CLEAN_HEADERS += src/usb_moded-log.h +CLEAN_HEADERS += src/usb_moded-mac.h +CLEAN_HEADERS += src/usb_moded-modes.h +CLEAN_HEADERS += src/usb_moded-modesetting.h +CLEAN_HEADERS += src/usb_moded-modules.h +CLEAN_HEADERS += src/usb_moded-network.h +CLEAN_HEADERS += src/usb_moded-ssu.h +CLEAN_HEADERS += src/usb_moded-systemd.h +CLEAN_HEADERS += src/usb_moded-trigger.h +CLEAN_HEADERS += src/usb_moded-udev.h +CLEAN_HEADERS += src/usb_moded.h + +# Files with whitespace issues + +# DIRTY_SOURCES += foo.c +# DIRTY_HEADERS += foo.h + +# Files that will not pass preprocessor / compiler ... + +# BROKEN_SOURCES += foo.c foo.h + +ALL_SOURCES += $(CLEAN_SOURCES) $(DIRTY_SOURCES) +ALL_HEADERS += $(CLEAN_HEADERS) $(DIRTY_HEADERS) + +# ---------------------------------------------------------------------------- +# Source code normalization +# ---------------------------------------------------------------------------- + +.PHONY: normalize +normalize:: + normalize_whitespace -M Makefile.custom + normalize_whitespace -a $(CLEAN_SOURCES) $(CLEAN_HEADERS) + normalize_whitespace -e -s $(DIRTY_SOURCES) $(DIRTY_HEADERS) + +# ---------------------------------------------------------------------------- +# AUTOMATIC HEADER DEPENDENCIES +# ---------------------------------------------------------------------------- + +.PHONY: depend +depend:: + @echo "Updating .depend" + $(CC) -MM $(CPPFLAGS) $(CLEAN_SOURCES) $(DIRTY_SOURCES) |\ + ./depend_filter.py > .depend + +ifneq ($(MAKECMDGOALS),depend) # not while: make depend +ifneq (,$(wildcard .depend)) # not if .depend does not exist +include .depend +endif +endif + +# ---------------------------------------------------------------------------- +# AUTOMATIC PROTOTYPE GENERFATION +# ---------------------------------------------------------------------------- + +.SUFFIXES: .q .p .g + +%.q : %.c ; $(CC) -o $@ -E $< $(CPPFLAGS) $(MCE_CFLAGS) +%.p : %.q ; cproto -s < $< | prettyproto.py > $@ +%.g : %.q ; cproto < $< | prettyproto.py > $@ + +clean:: + $(RM) *.[qpg] src/*.[qpg] utils/*.[qpg] + +protos-pre: $(patsubst %.c,%.q,$(ALL_SOURCES)) + touch $@ + +protos-post: $(patsubst %.c,%.p,$(ALL_SOURCES)) $(patsubst %.c,%.g,$(ALL_SOURCES)) + touch $@ + +clean:: + $(RM) protos-pre protos-post + +# ---------------------------------------------------------------------------- +# REMOVE FLUFF LEFT BY MB2 BUILDS +# ---------------------------------------------------------------------------- + +distclean:: + $(RM) -r RPMS installroot diff --git a/config-static.h b/config-static.h new file mode 100644 index 0000000..e18b1a1 --- /dev/null +++ b/config-static.h @@ -0,0 +1,32 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Name of package */ +#define PACKAGE "usb_moded" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "usb_moded" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "usb_moded 0.86.0+mer24" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "usb_moded" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.86.0+mer24" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.86.0+mer24" + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ diff --git a/depend_filter.py b/depend_filter.py new file mode 100755 index 0000000..5cc2936 --- /dev/null +++ b/depend_filter.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# -*- encoding: utf8 -*- + +# ---------------------------------------------------------------------------- +# Copyright (C) 2012-2018 Jolla Ltd. +# Contact: Simo Piiroinen +# License: GPLv2 +# ---------------------------------------------------------------------------- + +import sys,os + +def is_local(path): + return not path.startswith("/") + +def print_rule(dest, srce): + print "%s\\\n" % "\\\n\t".join(["%s:" % dest] + srce) + +def set_extension(path, ext): + return os.path.splitext(path)[0] + ext + +def normalize_path(srce): + return os.path.normpath(srce) + +def fix_directory(dest, srce): + srce = os.path.dirname(srce) + dest = os.path.basename(dest) + return os.path.join(srce, dest) + +if __name__ == "__main__": + + data = sys.stdin.readlines() + data = map(lambda x:x.rstrip(), data) + data.reverse() + + deps = [] + + # Note: dependencies are sorted only to keep + # future diffs cleaner + + while data: + line = data.pop() + while line.endswith('\\'): + line = line[:-1] + data.pop() + if not ':' in line: + continue + + dest,srce = line.split(":",1) + srce = srce.split() + srce,temp = srce[0],srce[1:] + + # take dest path primary srce + dest = fix_directory(dest, srce) + + # remove secondary deps with absolute path + temp = filter(is_local, temp) + + # sort secondary sources + temp.sort() + + srce = [srce] + temp + srce = map(normalize_path, srce) + + deps.append((dest,srce)) + + for dest,srce in sorted(deps): + # emit normal compilation dependencies + print_rule(dest, srce) + # and for -fPIC in case it is needed + dest = set_extension(dest, ".pic.o") + print_rule(dest, srce) diff --git a/rpm/usb-moded.spec b/rpm/usb-moded.spec index 88e5ea9..977180b 100644 --- a/rpm/usb-moded.spec +++ b/rpm/usb-moded.spec @@ -11,7 +11,7 @@ Source1: usb_moded.conf BuildRequires: pkgconfig(dbus-1) BuildRequires: pkgconfig(dbus-glib-1) BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(udev) +BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(libkmod) BuildRequires: doxygen BuildRequires: pkgconfig(libsystemd) @@ -357,6 +357,8 @@ touch %{buildroot}/%{_sysconfdir}/udhcpd.conf install -d $RPM_BUILD_ROOT/lib/systemd/system/basic.target.wants/ install -m 644 -D systemd/%{name}.service %{buildroot}/lib/systemd/system/%{name}.service ln -s ../%{name}.service $RPM_BUILD_ROOT/lib/systemd/system/basic.target.wants/%{name}.service +install -d %{buildroot}/usr/lib/systemd/user +install -m 644 -D systemd/buteo-mtpd.service %{buildroot}/usr/lib/systemd/user/buteo-mtpd.service install -m 644 -D systemd/usb-moded-args.conf %{buildroot}/var/lib/environment/usb-moded/usb-moded-args.conf install -m 755 -D systemd/turn-usb-rescue-mode-off %{buildroot}/%{_bindir}/turn-usb-rescue-mode-off install -m 644 -D systemd/usb-rescue-mode-off.service %{buildroot}/lib/systemd/system/usb-rescue-mode-off.service @@ -387,6 +389,7 @@ systemctl daemon-reload || : %{_mandir}/man1/usb-moded.1.gz /lib/systemd/system/%{name}.service /lib/systemd/system/basic.target.wants/%{name}.service +/usr/lib/systemd/user/buteo-mtpd.service %config %{_sysconfdir}/tmpfiles.d/usb-moded.conf %files devel diff --git a/scripts/set_usb_mode.sh b/scripts/set_usb_mode.sh new file mode 100755 index 0000000..25e35db --- /dev/null +++ b/scripts/set_usb_mode.sh @@ -0,0 +1,392 @@ +#!/bin/sh + +PROGNAME="$(basename $0)" + +# ============================================================================ +# ENV +# ============================================================================ + +CONFIGFS_ROOT="/config" +GADGET_DIR="$CONFIGFS_ROOT/usb_gadget/g1" +CONFIG_DIR="$GADGET_DIR/configs/b.1" +FUNCTION_DIR="$GADGET_DIR/functions" +UDC_CONTROL="$GADGET_DIR/UDC" +UDC_ENABLE="$(ls /sys/class/udc)" +UDC_DISABLE="" + +# "charging_only" +FUNCTION_MASS_STORAGE="mass_storage.usb0" + +# "developer_mode" +FUNCTION_RNDIS="rndis_bam.rndis" + +# "mtp_mode" +FUNCTION_MTP="ffs.mtp" + +# ============================================================================ +# LOG +# ============================================================================ + +LOG_LEVEL=6 + +log_critical() { test $LOG_LEVEL -ge 2 && echo >&2 "$PROGNAME: C: $*" ; } +log_error() { test $LOG_LEVEL -ge 3 && echo >&2 "$PROGNAME: E: $*" ; } +log_warning() { test $LOG_LEVEL -ge 4 && echo >&2 "$PROGNAME: W: $*" ; } +log_notice() { test $LOG_LEVEL -ge 5 && echo >&2 "$PROGNAME: N: $*" ; } +log_info() { test $LOG_LEVEL -ge 6 && echo >&2 "$PROGNAME: I: $*" ; } +log_debug() { test $LOG_LEVEL -ge 7 && echo >&2 "$PROGNAME: D: $*" ; } + +# ============================================================================ +# CONFIGFS +# ============================================================================ + +configfs_validate() { + log_debug "Validate ConfigFS mountpoint" + + mountpoint -q $CONFIGFS_ROOT || exit 1 + test -d "$GADGET_DIR" || exit 1 + test -f "$UDC_CONTROL" || exit 1 + test -d "$CONFIG_DIR" || exit 1 + test -d "$FUNCTION_DIR" || exit 1 +} + +# ============================================================================ +# UDC +# ============================================================================ + +udc_control() { + local prev="$(cat $UDC_CONTROL)" + local next="$1" + if [ "$prev" != "$next" ]; then + echo > "$UDC_CONTROL" "$next" + fi +} + +udc_disable() { + log_debug "Disable UDC" + udc_control "$UDC_DISABLE" +} + +udc_enable() { + log_debug "Enable UDC" + udc_control "$UDC_ENABLE" +} + +# ============================================================================ +# FUNCTION +# ============================================================================ + +function_register() { + log_debug "Register function: $1" + test -d "$FUNCTION_DIR/$1" || mkdir "$FUNCTION_DIR/$1" +} + +function_activate() { + log_debug "Activate function: $1" + test -h "$CONFIG_DIR/$1" || ln -s "$FUNCTION_DIR/$1" "$CONFIG_DIR/$1" +} + +function_deactivate() { + log_debug "Deactivate function: $1" + test -h "$CONFIG_DIR/$1" && rm "$CONFIG_DIR/$1" +} + +function_deactivate_all() { + local err=0 + for f in $CONFIG_DIR/*; do + # symlink == function + test -h $f || continue + if ! function_deactivate $(basename $f); then + err=1 + fi + done + return $err +} + +function_list_active() { + log_debug "List active functions" + for f in $CONFIG_DIR/*; do + # symlink == function + test -h $f || continue + log_debug "Active function: $(basename $f)" + done + return 0 +} + +function_set_attr() { + local f="$1" + local k="$2" + local v="$3" + log_debug "Function $f: set $k = $v" + echo > "$FUNCTION_DIR/$f/$k" "$v" +} + +# ============================================================================ +# RNDIS +# ============================================================================ + +rndis_down() { + log_debug "Disable rndis interface" + ifconfig rndis0 down 2> /dev/null || : +} + +rndis_up() { + log_debug "Enable rndis interface" + ifconfig rndis0 192.168.2.15 255.255.255.0 2> /dev/null || : +} + +udhcpd_configure() { + log_debug "Configure udhcpd" + cat > /etc/udhcpd.conf <<-EOF + start 192.168.2.1 + end 192.168.2.15 + interface rndis0 + option subnet 255.255.255.0 + option lease 3600 + max_leases 15 + EOF +} + +udhcpd_start() { + log_debug "Start udhcpd" + systemctl start udhcpd.service +} + +udhcpd_stop() { + log_debug "Stop udhcpd" + systemctl stop udhcpd.service +} + +# ============================================================================ +# MTP +# ============================================================================ + +MTPD_ENV="LANG=en_GB.utf8 MSYNCD_LOGGING_LEVEL=7" +MTPD_BIN="/usr/lib/mtp/mtp_service" +MTPD_LOG="/tmp/mtpd.log" + +mtp_mount() { + log_debug "Mount mtp endpoint directory" + if ! mountpoint -q /dev/mtp ; then + /bin/mount -o uid=100000,gid=100000 -t functionfs mtp /dev/mtp + fi +} + +mtp_unmount() { + log_debug "Unmount mtp endpoint directory" + if mountpoint -q /dev/mtp ; then + /bin/umount /dev/mtp + fi +} + +mtpd_start() { + log_debug "Start mtpd" + (/bin/su - nemo -c "$MTPD_ENV $MTPD_BIN" 2>$MTPD_LOG) & + + local seen=0 + for i in $(seq 10); do + sleep 0.333 + if killall -0 "$MTPD_BIN" ; then + seen=$((seen+1)) + test "$seen" -ge 3 && return 0 + else + log_debug "Wait for mtpd ..." + fi + done + log_warning "Could not start mtpd" + return 1 +} + +mtpd_stop() { + log_debug "Stop mtpd" + /usr/bin/killall "$MTPD_BIN" || : +} + +# ============================================================================ +# USB_MODE +# ============================================================================ + +# -- undefined -- + +usb_mode_enter_undefined() { + log_debug "ENTER UNKNOWN MODE" + # same as enter undefined... + udc_disable + function_deactivate_all +} + +usb_mode_leave_undefined() { + log_debug "LEAVE UNKNOWN MODE" + udc_disable + function_deactivate_all +} + +# -- charging_only -- + +usb_mode_enter_charging_only() { + log_debug "ENTER CHARGING_ONLY" + function_register $FUNCTION_MASS_STORAGE + function_activate $FUNCTION_MASS_STORAGE + udc_enable +} + +usb_mode_leave_charging_only() { + log_debug "LEAVE CHARGING_ONLY" + udc_disable + function_deactivate_all +} + +# -- developer_mode -- + +usb_mode_enter_developer_mode() { + log_debug "ENTER DEVELOPER_MODE" + function_register $FUNCTION_RNDIS + function_set_attr $FUNCTION_RNDIS wceis 1 + function_activate $FUNCTION_RNDIS + udc_enable + sleep 0.5 + rndis_up + sleep 0.5 + udhcpd_configure + udhcpd_start +} + +usb_mode_leave_developer_mode() { + log_debug "LEAVE DEVELOPER_MODE" + udhcpd_stop + rndis_down + udc_disable + function_deactivate_all +} + +# -- mtp_mode -- + +usb_mode_enter_mtp_mode() { + log_debug "ENTER MTP_MODE" + function_register $FUNCTION_MTP + function_activate $FUNCTION_MTP + mtp_mount + mtpd_start + udc_enable +} + +usb_mode_leave_mtp_mode() { + log_debug "LEAVE MTP_MODE" + udc_disable + mtpd_stop + mtp_unmount + function_deactivate_all +} + +# -- mode switch -- + +usb_mode_enter() { + case $1 in + mtp_mode) + usb_mode_enter_mtp_mode + ;; + developer_mode) + usb_mode_enter_developer_mode + ;; + charging_only) + usb_mode_enter_charging_only + ;; + undefined) + usb_mode_enter_undefined + ;; + *) + log_warning "Unknown mode: $1" + usb_mode_enter_undefined + ;; + esac +} + +usb_mode_leave() { + case $1 in + mtp_mode) + usb_mode_leave_mtp_mode + ;; + developer_mode) + usb_mode_leave_developer_mode + ;; + charging_only) + usb_mode_leave_charging_only + ;; + undefined) + usb_mode_leave_undefined + ;; + *) + log_warning "Unknown mode: $1" + usb_mode_leave_undefined + ;; + esac +} + +usb_mode_switch() { + configfs_validate + local next="$1" + local curr="$(cat /tmp/usb-mode)" + test ! -z "$curr" || curr="undefined" + + if [ "$curr" != "$next" ]; then + log_info "SWITCH FROM: $curr TO: $next" + usb_mode_leave "$curr" + echo > /tmp/usb-mode "$next" + usb_mode_enter "$next" + else + log_info "ALREADY IN: $next" + fi +} + +# ============================================================================ +# MAIN +# ============================================================================ + +# try to guess if we were executed or sourced +if [ "$PROGNAME" = "set_usb_mode.sh" ]; then + TARGET_MODE="$1" + case $TARGET_MODE in + cha*) + TARGET_MODE="charging_only" + ;; + dev*) + TARGET_MODE="developer_mode" + ;; + mtp*) + TARGET_MODE="mtp_mode" + ;; + und*) + TARGET_MODE="undefined" + ;; + -v|--verbose) + LOG_LEVEL=$((LOG_LEVEL+1)) + ;; + -q|--quiet) + LOG_LEVEL=$((LOG_LEVEL-1)) + ;; + -s|--silent) + LOG_LEVEL=0 + ;; + -h|--help|--usage) + cat <<-EOF + Usage: + $PROGNAME + + Valid modes are: + - charging_only + - developer_mode + - mtp_mode + - undefined + EOF + exit 0 + ;; + *) + cat >&2 <<-EOF + unknown option: ${TARGET_MODE:-} + (Use $PROGNAME --usage to show help) + EOF + exit 1 + ;; + esac + usb_mode_switch "$TARGET_MODE" +fi diff --git a/src/Makefile.am b/src/Makefile.am index 440ed09..7023607 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,5 @@ +USB_MODED_CFLAGS += -D_GNU_SOURCE + sbin_PROGRAMS = usb_moded \ usb_moded_util @@ -9,7 +11,7 @@ usb_moded_LDFLAGS = \ usb_moded_LDADD = \ $(USB_MODED_LIBS) - + usb_moded_SOURCES = \ usb_moded.c \ usb_moded.h \ @@ -17,7 +19,7 @@ usb_moded_SOURCES = \ usb_moded-dbus.c \ usb_moded-dbus.h \ usb_moded-dbus-private.h \ - usb_moded-hw-ab.h \ + usb_moded-udev.h \ usb_moded-config-private.h \ usb_moded-modules.h \ usb_moded-log.h \ @@ -35,6 +37,8 @@ usb_moded_SOURCES = \ usb_moded-udev.c \ usb_moded-trigger.c \ usb_moded-modules.c \ + usb_moded-configfs.c \ + usb_moded-configfs.h \ usb_moded-android.h \ usb_moded-android.c diff --git a/src/usb_moded-android.c b/src/usb_moded-android.c index e69b866..e19ab79 100644 --- a/src/usb_moded-android.c +++ b/src/usb_moded-android.c @@ -1,24 +1,25 @@ /** - @file usb_moded-android.c - - Copyright (C) 2013 Jolla. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-android.c + * + * Copyright (C) 2013-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -27,13 +28,62 @@ #include "usb_moded-android.h" #include "usb_moded-log.h" #include "usb_moded-modesetting.h" -#include "usb_moded-config.h" +#include "usb_moded-config-private.h" #include "usb_moded-mac.h" +#include +#include +#include + +/* ========================================================================= * + * Functions + * ========================================================================= */ + +/* -- android -- */ + +bool android_in_use (void); +static bool android_probe (void); +gchar *android_get_serial (void); +bool android_init_values (void); +bool android_set_charging_mode(void); +bool android_set_productid (const char *id); +bool android_set_vendorid (const char *id); + +/* ========================================================================= * + * Data + * ========================================================================= */ + +static int android_probed = -1; + +/* ========================================================================= * + * Functions + * ========================================================================= */ + +bool android_in_use(void) +{ + if( android_probed < 0 ) + log_debug("android_in_use() called before android_probe()"); + + return android_probed > 0; +} + +static bool android_probe(void) +{ + if( android_probed <= 0 ) { + struct stat st; + + android_probed = (lstat(ANDROID0_DIRECTORY, &st) == 0 && + S_ISDIR(st.st_mode)); + log_warning("ANDROID0 %sdetected", android_probed ? "" : "not "); + } + + return android_in_use(); +} /** Read android serial number from kernel command line */ -static gchar *get_android_serial(void) +gchar * +android_get_serial(void) { static const char path[] = "/proc/cmdline"; static const char find[] = "androidboot.serialno="; @@ -81,129 +131,119 @@ static gchar *get_android_serial(void) /** initialize the basic android values */ -void android_init_values(void) +bool android_init_values(void) { - gchar *text; - - /* If the directory is not there, no point emitting warnings - * about every file that is not going to be there either. */ - if( access("/sys/class/android_usb/android0", F_OK) != 0 ) - { - goto EXIT; - } - - /* Disable */ - write_to_file("/sys/class/android_usb/android0/enable", "0"); - - /* Configure */ - if( (text = get_android_serial()) ) - { - write_to_file("/sys/class/android_usb/android0/iSerial", text); - g_free(text); - } - - text = get_android_manufacturer(); - if(text) - { - write_to_file("/sys/class/android_usb/android0/iManufacturer", text); - g_free(text); - } - text = get_android_vendor_id(); - if(text) - { - write_to_file("/sys/class/android_usb/android0/idVendor", text); - g_free(text); - } - text = get_android_product(); - if(text) - { - write_to_file("/sys/class/android_usb/android0/iProduct", text); - g_free(text); - } - text = get_android_product_id(); - if(text) - { - write_to_file("/sys/class/android_usb/android0/idProduct", text); - g_free(text); - } - text = read_mac(); - if(text) - { - write_to_file("/sys/class/android_usb/f_rndis/ethaddr", text); - g_free(text); - } - /* For rndis to be discovered correctly in M$ Windows (vista and later) */ - write_to_file("/sys/class/android_usb/f_rndis/wceis", "1"); - - - /* Some devices can have enumeration issues due to incomplete - * configuration on the 1st connect after bootup. Briefly setting - * up for example mass_storage function can be utilized as a - * workaround in such cases. */ - if(!init_done_p()) { - const char *function = get_android_bootup_function(); - if(function) { - write_to_file("/sys/class/android_usb/android0/functions", function); - write_to_file("/sys/class/android_usb/android0/enable", "1"); - write_to_file("/sys/class/android_usb/android0/enable", "0"); + gchar *text; + + if( !android_probe() ) + goto EXIT; + + /* Disable */ + write_to_file(ANDROID0_ENABLE, "0"); + + /* Configure */ + if( (text = android_get_serial()) ) + { + write_to_file(ANDROID0_SERIAL, text); + g_free(text); } - } - /* Clear functions and enable */ - write_to_file("/sys/class/android_usb/android0/functions", "none"); - write_to_file("/sys/class/android_usb/android0/enable", "1"); + text = config_get_android_manufacturer(); + if(text) + { + write_to_file(ANDROID0_MANUFACTURER, text); + g_free(text); + } + text = config_get_android_vendor_id(); + if(text) + { + write_to_file(ANDROID0_ID_VENDOR, text); + g_free(text); + } + text = config_get_android_product(); + if(text) + { + write_to_file(ANDROID0_PRODUCT, text); + g_free(text); + } + text = config_get_android_product_id(); + if(text) + { + write_to_file(ANDROID0_ID_PRODUCT, text); + g_free(text); + } + text = mac_read_mac(); + if(text) + { + write_to_file("/sys/class/android_usb/f_rndis/ethaddr", text); + g_free(text); + } + /* For rndis to be discovered correctly in M$ Windows (vista and later) */ + write_to_file("/sys/class/android_usb/f_rndis/wceis", "1"); + + /* Some devices can have enumeration issues due to incomplete + * configuration on the 1st connect after bootup. Briefly setting + * up for example mass_storage function can be utilized as a + * workaround in such cases. */ + if(!usbmoded_init_done_p()) { + const char *function = usbmoded_get_android_bootup_function(); + if(function) { + write_to_file(ANDROID0_FUNCTIONS, function); + write_to_file(ANDROID0_ENABLE, "1"); + write_to_file(ANDROID0_ENABLE, "0"); + } + } + + /* Clear functions and enable */ + write_to_file(ANDROID0_FUNCTIONS, "none"); + write_to_file(ANDROID0_ENABLE, "1"); EXIT: - return; + return android_in_use(); } /* Set a charging mode for the android gadget * * @return 0 if successful, 1 on failure */ -int set_android_charging_mode(void) +bool android_set_charging_mode(void) { - int ret = 0; - - /* disable, set functions to "mass_storage", re-enable */ - write_to_file("/sys/class/android_usb/android0/enable", "0"); - write_to_file("/sys/class/android_usb/android0/idProduct", "0AFE"); /* TODO: make configurable */ - write_to_file("/sys/class/android_usb/android0/functions", "mass_storage"); - ret = write_to_file("/sys/class/android_usb/android0/enable", "1"); - if(ret < 0) - return(1); - else - return(ret); + bool ack = false; + if( android_in_use() ) { + /* disable, set functions to "mass_storage", re-enable */ + write_to_file(ANDROID0_ENABLE, "0"); + write_to_file(ANDROID0_ID_PRODUCT, "0AFE"); /* TODO: make configurable */ + write_to_file(ANDROID0_FUNCTIONS, "mass_storage"); + ack = write_to_file(ANDROID0_ENABLE, "1") != -1; + } + log_debug("ANDROID %s() -> %d", __func__, ack); + return ack; } /* Set a product id for the android gadget * * @return 0 if successful, 1 on failure */ -int set_android_productid(char *id) +bool android_set_productid(const char *id) { - int ret = 0; - - /* disable, set functions to "mass_storage", re-enable */ - ret = write_to_file("/sys/class/android_usb/android0/idProduct", id); - if(ret < 0) - return(1); - else - return(ret); + bool ack = false; + if( android_in_use() ) { + ack = write_to_file(ANDROID0_ID_PRODUCT, id) != -1; + } + log_debug("ANDROID %s(%s) -> %d", __func__, id, ack); + return ack; } /* Set a vendor id for the android gadget * * @return 0 if successful, 1 on failure */ -int set_android_vendorid(char *id) +bool android_set_vendorid(const char *id) { - int ret = 0; - - /* disable, set functions to "mass_storage", re-enable */ - ret = write_to_file("/sys/class/android_usb/android0/idVendor", id); - if(ret < 0) - return(1); - else - return(ret); + bool ack = false; + if( android_in_use() ) { + ack = write_to_file(ANDROID0_ID_VENDOR, id) != -1; + } + log_debug("ANDROID %s(%s) -> %d", __func__, id, ack); + return ack; } diff --git a/src/usb_moded-android.h b/src/usb_moded-android.h index 3b2f8ed..9c44c02 100644 --- a/src/usb_moded-android.h +++ b/src/usb_moded-android.h @@ -1,26 +1,55 @@ /** - @file usb_moded-android.h - - Copyright (C) 2013 Jolla. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -void android_init_values(void); -int set_android_charging_mode(void); -int set_android_productid(char *id); -int set_android_vendorid(char *id); + * @file usb_moded-android.h + * + * Copyright (C) 2013-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef USB_MODED_ANDROID_H_ +# define USB_MODED_ANDROID_H_ + +# include + +/* ========================================================================= * + * Constants + * ========================================================================= */ + +# define ANDROID0_DIRECTORY "/sys/class/android_usb/android0" +# define ANDROID0_ENABLE "/sys/class/android_usb/android0/enable" +# define ANDROID0_FUNCTIONS "/sys/class/android_usb/android0/functions" +# define ANDROID0_ID_PRODUCT "/sys/class/android_usb/android0/idProduct" +# define ANDROID0_ID_VENDOR "/sys/class/android_usb/android0/idVendor" +# define ANDROID0_MANUFACTURER "/sys/class/android_usb/android0/iManufacturer" +# define ANDROID0_PRODUCT "/sys/class/android_usb/android0/iProduct" +# define ANDROID0_SERIAL "/sys/class/android_usb/android0/iSerial" + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- android -- */ + +gchar *android_get_serial (void); +bool android_init_values (void); +bool android_in_use (void); +bool android_set_charging_mode(void); +bool android_set_productid (const char *id); +bool android_set_vendorid (const char *id); + +#endif /* USB_MODED_ANDROID_H_ */ diff --git a/src/usb_moded-appsync-dbus-private.h b/src/usb_moded-appsync-dbus-private.h index 86b46b4..5a66ede 100644 --- a/src/usb_moded-appsync-dbus-private.h +++ b/src/usb_moded-appsync-dbus-private.h @@ -1,24 +1,39 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2018 Jolla Ltd. + * + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - Author: Philippe De Swert +#ifndef USB_MODED_APPSYNC_DBUS_PRIVATE_H_ +# define USB_MODED_APPSYNC_DBUS_PRIVATE_H_ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +/* ========================================================================= * + * Prototypes + * ========================================================================= */ - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +/* -- dbusappsync -- */ -gboolean usb_moded_app_sync_init(void); -void usb_moded_appsync_cleanup(void); -int usb_moded_dbus_app_launch(char *launch); -gboolean usb_moded_app_sync_init_connection(void); +gboolean dbusappsync_init_connection(void); +gboolean dbusappsync_init (void); +void dbusappsync_cleanup (void); +int dbusappsync_launch_app (char *launch); + +#endif /* USB_MODED_APPSYNC_DBUS_PRIVATE_H_ */ diff --git a/src/usb_moded-appsync-dbus.c b/src/usb_moded-appsync-dbus.c index f1aff65..fb85222 100644 --- a/src/usb_moded-appsync-dbus.c +++ b/src/usb_moded-appsync-dbus.c @@ -1,24 +1,29 @@ /** - @file usb_moded-dbus.c - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-dbus.c + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -37,260 +42,279 @@ #include "usb_moded-appsync-dbus.h" #include "usb_moded-appsync-dbus-private.h" +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- dbusappsync -- */ + +static void dbusappsync_release_name (void); +static gboolean dbusappsync_obtain_name (void); +static DBusHandlerResult dbusappsync_msg_handler (DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data); +static DBusHandlerResult dbusappsync_handle_disconnect (DBusConnection *conn, DBusMessage *msg, void *user_data); +static void dbusappsync_cleanup_connection(void); +gboolean dbusappsync_init_connection (void); +gboolean dbusappsync_init (void); +void dbusappsync_cleanup (void); +int dbusappsync_launch_app (char *launch); + +/* ========================================================================= * + * Data + * ========================================================================= */ + static DBusConnection *dbus_connection_ses = NULL; // connection static gboolean dbus_connection_name = FALSE; // have name static gboolean dbus_connection_disc = FALSE; // got disconnected -static void usb_moded_app_sync_cleanup_connection(void); +/* ========================================================================= * + * Functions + * ========================================================================= */ -static DBusHandlerResult handle_disconnect(DBusConnection *conn, DBusMessage *msg, void *user_data); -static DBusHandlerResult msg_handler(DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data); - -static void usb_moded_app_sync_release_name(void) +static void dbusappsync_release_name(void) { - /* Drop the service name - if we have it */ - if( dbus_connection_ses && dbus_connection_name ) - { - DBusError error = DBUS_ERROR_INIT; - int ret = dbus_bus_release_name(dbus_connection_ses, USB_MODE_SERVICE, &error); - - switch( ret ) - { - case DBUS_RELEASE_NAME_REPLY_RELEASED: - // as expected - log_debug("released name: %s", USB_MODE_SERVICE); - break; - case DBUS_RELEASE_NAME_REPLY_NON_EXISTENT: - // weird, but since nobody owns the name ... - log_debug("nonexisting name: %s", USB_MODE_SERVICE); - break; - case DBUS_RELEASE_NAME_REPLY_NOT_OWNER: - log_warning("somebody else owns: %s", USB_MODE_SERVICE); - } - - if( dbus_error_is_set(&error) ) + /* Drop the service name - if we have it */ + if( dbus_connection_ses && dbus_connection_name ) { - log_debug("DBUS ERROR: %s, %s \n", error.name, error.message); - dbus_error_free(&error); + DBusError error = DBUS_ERROR_INIT; + int ret = dbus_bus_release_name(dbus_connection_ses, USB_MODE_SERVICE, &error); + + switch( ret ) + { + case DBUS_RELEASE_NAME_REPLY_RELEASED: + // as expected + log_debug("released name: %s", USB_MODE_SERVICE); + break; + case DBUS_RELEASE_NAME_REPLY_NON_EXISTENT: + // weird, but since nobody owns the name ... + log_debug("nonexisting name: %s", USB_MODE_SERVICE); + break; + case DBUS_RELEASE_NAME_REPLY_NOT_OWNER: + log_warning("somebody else owns: %s", USB_MODE_SERVICE); + } + + if( dbus_error_is_set(&error) ) + { + log_debug("DBUS ERROR: %s, %s \n", error.name, error.message); + dbus_error_free(&error); + } } - } - dbus_connection_name = FALSE; + dbus_connection_name = FALSE; } -static gboolean usb_moded_app_sync_obtain_name(void) +static gboolean dbusappsync_obtain_name(void) { - DBusError error = DBUS_ERROR_INIT; - - int ret; - - if( dbus_connection_name ) - { - goto EXIT; - } + DBusError error = DBUS_ERROR_INIT; - if( dbus_connection_ses == 0 ) - { - goto EXIT; - } + int ret; - /* Acquire D-Bus service name */ - ret = dbus_bus_request_name(dbus_connection_ses, USB_MODE_SERVICE, DBUS_NAME_FLAG_DO_NOT_QUEUE , &error); + if( dbus_connection_name ) + { + goto EXIT; + } - switch( ret ) - { - case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: - // expected result - log_debug("primary owner of: %s", USB_MODE_SERVICE); - break; + if( dbus_connection_ses == 0 ) + { + goto EXIT; + } - case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: - // functionally ok, but we do have a logic error somewhere - log_warning("already owner of: %s", USB_MODE_SERVICE); - break; + /* Acquire D-Bus service name */ + ret = dbus_bus_request_name(dbus_connection_ses, USB_MODE_SERVICE, DBUS_NAME_FLAG_DO_NOT_QUEUE , &error); - default: - // something odd - log_err("failed to claim: %s", USB_MODE_SERVICE); - goto EXIT; - } + switch( ret ) + { + case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: + // expected result + log_debug("primary owner of: %s", USB_MODE_SERVICE); + break; + + case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: + // functionally ok, but we do have a logic error somewhere + log_warning("already owner of: %s", USB_MODE_SERVICE); + break; + + default: + // something odd + log_err("failed to claim: %s", USB_MODE_SERVICE); + goto EXIT; + } - dbus_connection_name = TRUE; + dbus_connection_name = TRUE; EXIT: - if( dbus_error_is_set(&error) ) - { - log_debug("DBUS ERROR: %s, %s \n", error.name, error.message); - dbus_error_free(&error); - } + if( dbus_error_is_set(&error) ) + { + log_debug("DBUS ERROR: %s, %s \n", error.name, error.message); + dbus_error_free(&error); + } - return dbus_connection_name; + return dbus_connection_name; } /** * Handle USB_MODE_INTERFACE method calls */ -static DBusHandlerResult msg_handler(DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data) +static DBusHandlerResult dbusappsync_msg_handler(DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data) { - DBusHandlerResult status = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - int type = dbus_message_get_type(msg); - const char *interface = dbus_message_get_interface(msg); - const char *member = dbus_message_get_member(msg); - const char *object = dbus_message_get_path(msg); + DBusHandlerResult status = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + int type = dbus_message_get_type(msg); + const char *interface = dbus_message_get_interface(msg); + const char *member = dbus_message_get_member(msg); + const char *object = dbus_message_get_path(msg); - if(!interface || !member || !object) goto IGNORE; + if(!interface || !member || !object) goto IGNORE; - if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && - !strcmp(interface, USB_MODE_INTERFACE) && - !strcmp(object, USB_MODE_OBJECT) ) - - { - DBusMessage *reply = 0; - - status = DBUS_HANDLER_RESULT_HANDLED; - - if(!strcmp(member, USB_MODE_APP_STATE)) - { - char *use = 0; - DBusError err = DBUS_ERROR_INIT; - - if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID)) - { - // could not parse method call args - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - } - else if( mark_active(use) < 0 ) - { - // name could not be marked active - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - } - else if((reply = dbus_message_new_method_return(msg))) - { - // generate normal reply - dbus_message_append_args (reply, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID); - } - dbus_error_free(&err); - } - else - { - /*unknown methods are handled here */ - reply = dbus_message_new_error(msg, DBUS_ERROR_UNKNOWN_METHOD, member); - } + if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && + !strcmp(interface, USB_MODE_INTERFACE) && + !strcmp(object, USB_MODE_OBJECT) ) - if( !dbus_message_get_no_reply(msg) ) { - if( !reply ) - { - // we failed to generate reply above -> generate one - reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, member); - } - if( !reply || !dbus_connection_send(connection, reply, 0) ) - { - log_debug("Failed sending reply. Out Of Memory!\n"); - } + DBusMessage *reply = 0; + + status = DBUS_HANDLER_RESULT_HANDLED; + + if(!strcmp(member, USB_MODE_APP_STATE)) + { + char *use = 0; + DBusError err = DBUS_ERROR_INIT; + + if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID)) + { + // could not parse method call args + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + } + else if( appsync_mark_active(use) < 0 ) + { + // name could not be marked active + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + } + else if((reply = dbus_message_new_method_return(msg))) + { + // generate normal reply + dbus_message_append_args (reply, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID); + } + dbus_error_free(&err); + } + else + { + /*unknown methods are handled here */ + reply = dbus_message_new_error(msg, DBUS_ERROR_UNKNOWN_METHOD, member); + } + + if( !dbus_message_get_no_reply(msg) ) + { + if( !reply ) + { + // we failed to generate reply above -> generate one + reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, member); + } + if( !reply || !dbus_connection_send(connection, reply, 0) ) + { + log_debug("Failed sending reply. Out Of Memory!\n"); + } + } + + if( reply ) dbus_message_unref(reply); } - if( reply ) dbus_message_unref(reply); - } - IGNORE: - return status; + return status; } /** * Handle disconnect signals */ -static DBusHandlerResult handle_disconnect(DBusConnection *conn, DBusMessage *msg, void *user_data) +static DBusHandlerResult dbusappsync_handle_disconnect(DBusConnection *conn, DBusMessage *msg, void *user_data) { - if( dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected") ) - { - log_warning("disconnected from session bus - expecting restart/stop soon\n"); - dbus_connection_disc = TRUE; - usb_moded_app_sync_cleanup_connection(); - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if( dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected") ) + { + log_warning("disconnected from session bus - expecting restart/stop soon\n"); + dbus_connection_disc = TRUE; + dbusappsync_cleanup_connection(); + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } /** * Detach from session bus */ -static void usb_moded_app_sync_cleanup_connection(void) +static void dbusappsync_cleanup_connection(void) { - if( dbus_connection_ses != 0 ) - { - /* Remove message filters */ - dbus_connection_remove_filter(dbus_connection_ses, msg_handler, 0); - dbus_connection_remove_filter(dbus_connection_ses, handle_disconnect, 0); - - /* Release name, but only if we can still talk to dbus daemon */ - if( !dbus_connection_disc ) + if( dbus_connection_ses != 0 ) { - usb_moded_app_sync_release_name(); + /* Remove message filters */ + dbus_connection_remove_filter(dbus_connection_ses, dbusappsync_msg_handler, 0); + dbus_connection_remove_filter(dbus_connection_ses, dbusappsync_handle_disconnect, 0); + + /* Release name, but only if we can still talk to dbus daemon */ + if( !dbus_connection_disc ) + { + dbusappsync_release_name(); + } + + dbus_connection_unref(dbus_connection_ses); + dbus_connection_ses = NULL; + //dbus_connection_disc = FALSE; } - - dbus_connection_unref(dbus_connection_ses); - dbus_connection_ses = NULL; - //dbus_connection_disc = FALSE; - } - log_debug("succesfully cleaned up appsync dbus\n"); + log_debug("succesfully cleaned up appsync dbus\n"); } /** * Attach to session bus */ -gboolean usb_moded_app_sync_init_connection(void) +gboolean dbusappsync_init_connection(void) { - gboolean result = FALSE; - DBusError error = DBUS_ERROR_INIT; + gboolean result = FALSE; + DBusError error = DBUS_ERROR_INIT; - if( dbus_connection_ses != 0 ) - { - result = TRUE; - goto EXIT; - } + if( dbus_connection_ses != 0 ) + { + result = TRUE; + goto EXIT; + } - if( dbus_connection_disc ) - { - // we've already observed death of session - goto EXIT; - } + if( dbus_connection_disc ) + { + // we've already observed death of session + goto EXIT; + } - /* Connect to session bus */ - if ((dbus_connection_ses = dbus_bus_get(DBUS_BUS_SESSION, &error)) == NULL) - { - log_err("Failed to open connection to session message bus; %s\n", error.message); - goto EXIT; - } + /* Connect to session bus */ + if ((dbus_connection_ses = dbus_bus_get(DBUS_BUS_SESSION, &error)) == NULL) + { + log_err("Failed to open connection to session message bus; %s\n", error.message); + goto EXIT; + } - /* Add disconnect handler */ - dbus_connection_add_filter(dbus_connection_ses, handle_disconnect, 0, 0); + /* Add disconnect handler */ + dbus_connection_add_filter(dbus_connection_ses, dbusappsync_handle_disconnect, 0, 0); - /* Add method call handler */ - dbus_connection_add_filter(dbus_connection_ses, msg_handler, 0, 0); + /* Add method call handler */ + dbus_connection_add_filter(dbus_connection_ses, dbusappsync_msg_handler, 0, 0); - /* Make sure we do not get forced to exit if dbus session dies or stops */ - dbus_connection_set_exit_on_disconnect(dbus_connection_ses, FALSE); + /* Make sure we do not get forced to exit if dbus session dies or stops */ + dbus_connection_set_exit_on_disconnect(dbus_connection_ses, FALSE); - /* Connect D-Bus to the mainloop (Seems it is only needed once and is done at the main + /* Connect D-Bus to the mainloop (Seems it is only needed once and is done at the main D-Bus init - dbus_connection_setup_with_g_main(dbus_connection_ses, NULL); - */ + dbus_connection_setup_with_g_main(dbus_connection_ses, NULL); + */ - /* Request service name */ - if( !usb_moded_app_sync_obtain_name() ) - { - goto EXIT; - } + /* Request service name */ + if( !dbusappsync_obtain_name() ) + { + goto EXIT; + } - /* everything went fine */ - result = TRUE; + /* everything went fine */ + result = TRUE; EXIT: - dbus_error_free(&error); - return result; + dbus_error_free(&error); + return result; } /** @@ -298,56 +322,55 @@ gboolean usb_moded_app_sync_init_connection(void) * * @return TRUE when everything went ok */ -gboolean usb_moded_app_sync_init(void) +gboolean dbusappsync_init(void) { - gboolean status = FALSE; + gboolean status = FALSE; - if( !usb_moded_app_sync_init_connection() ) - { - goto EXIT; - } + if( !dbusappsync_init_connection() ) + { + goto EXIT; + } - /* everything went fine */ - status = TRUE; + /* everything went fine */ + status = TRUE; EXIT: - return status; + return status; } /** * Clean up the dbus connections for the application * synchronisation after sync is done */ -void usb_moded_appsync_cleanup(void) +void dbusappsync_cleanup(void) { - usb_moded_app_sync_cleanup_connection(); - // NOP + dbusappsync_cleanup_connection(); + // NOP } /** * Launch applications over dbus that need to be synchronized */ -int usb_moded_dbus_app_launch(char *launch) +int dbusappsync_launch_app(char *launch) { - int ret = -1; // assume failure - - if( dbus_connection_ses == 0 ) - { - log_err("could not start '%s': no session bus connection", launch); - } - else - { - DBusError error = DBUS_ERROR_INIT; - if( !dbus_bus_start_service_by_name(dbus_connection_ses, launch, 0, NULL, &error) ) + int ret = -1; // assume failure + + if( dbus_connection_ses == 0 ) { - log_err("could not start '%s': %s: %s", launch, error.name, error.message); - dbus_error_free(&error); + log_err("could not start '%s': no session bus connection", launch); } else { - ret = 0; // success + DBusError error = DBUS_ERROR_INIT; + if( !dbus_bus_start_service_by_name(dbus_connection_ses, launch, 0, NULL, &error) ) + { + log_err("could not start '%s': %s: %s", launch, error.name, error.message); + dbus_error_free(&error); + } + else + { + ret = 0; // success + } } - } - return ret; + return ret; } - diff --git a/src/usb_moded-appsync-dbus.h b/src/usb_moded-appsync-dbus.h index d067e92..d16f19f 100644 --- a/src/usb_moded-appsync-dbus.h +++ b/src/usb_moded-appsync-dbus.h @@ -1,28 +1,43 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2018 Jolla Ltd. + * + * Author: Philippe De Swert + * Author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - Author: Philippe De Swert +#ifndef USB_MODED_APPSYNC_DBUS_H_ +# define USB_MODED_APPSYNC_DBUS_H_ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +/* ========================================================================= * + * Constants + * ========================================================================= */ - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +# define USB_MODE_SERVICE "com.meego.usb_moded" +# define USB_MODE_INTERFACE "com.meego.usb_moded" +# define USB_MODE_OBJECT "/com/meego/usb_moded" -#include +/* supported methods */ +# define USB_MODE_APP_STATE "ready" -#define USB_MODE_SERVICE "com.meego.usb_moded" -#define USB_MODE_INTERFACE "com.meego.usb_moded" -#define USB_MODE_OBJECT "/com/meego/usb_moded" +/* ========================================================================= * + * Prototypes + * ========================================================================= */ -/* supported methods */ -#define USB_MODE_APP_STATE "ready" +// (in usb_moded-appsync-dbus-private.h) + +#endif /* USB_MODED_APPSYNC_DBUS_H_ */ diff --git a/src/usb_moded-appsync.c b/src/usb_moded-appsync.c index 4c82b2b..d522ab0 100644 --- a/src/usb_moded-appsync.c +++ b/src/usb_moded-appsync.c @@ -1,29 +1,30 @@ /** - @file usb_moded-appsync.c - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2013-2016 Jolla Ltd. - - @author: Philippe De Swert - @author: Philippe De Swert - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#define _GNU_SOURCE + * @file usb_moded-appsync.c + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Thomas Perl + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -43,11 +44,31 @@ #include "usb_moded-log.h" #include "usb_moded-systemd.h" -static struct list_elem *read_file(const gchar *filename, int diag); -static void enumerate_usb(void); -static gboolean enumerate_usb_cb(gpointer data); -static void start_enumerate_usb_timer(void); -static void cancel_enumerate_usb_timer(void); +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- appsync -- */ + +static void appsync_free_elem (struct list_elem *elem); +static void appsync_free_elem_cb (gpointer elem, gpointer user_data); +void appsync_free_appsync_list (void); +static gint appsync_list_sort_func (gconstpointer a, gconstpointer b); +void appsync_read_list (int diag); +static struct list_elem *appsync_read_file (const gchar *filename, int diag); +int appsync_activate_sync (const char *mode); +int appsync_activate_sync_post (const char *mode); +int appsync_mark_active (const gchar *name, int post); +static gboolean appsync_enumerate_usb_cb (gpointer data); +static void appsync_start_enumerate_usb_timer (void); +static void appsync_cancel_enumerate_usb_timer(void); +static void appsync_enumerate_usb (void); +static void appsync_stop_apps (int post); +int appsync_stop (gboolean force); + +/* ========================================================================= * + * Data + * ========================================================================= */ static GList *sync_list = NULL; @@ -59,421 +80,424 @@ static int no_dbus = 0; static int no_dbus = 0; #endif /* APP_SYNC_DBUS */ +/* ========================================================================= * + * Functions + * ========================================================================= */ -static void free_elem(struct list_elem *elem) +static void appsync_free_elem(struct list_elem *elem) { - g_free(elem->name); - g_free(elem->launch); - g_free(elem->mode); - free(elem); + g_free(elem->name); + g_free(elem->launch); + g_free(elem->mode); + free(elem); } -static void free_elem_cb(gpointer elem, gpointer user_data) +static void appsync_free_elem_cb(gpointer elem, gpointer user_data) { - (void)user_data; - free_elem(elem); + (void)user_data; + appsync_free_elem(elem); } -void free_appsync_list(void) +void appsync_free_appsync_list(void) { - if( sync_list != 0 ) - { - /*g_list_free_full(sync_list, free_elem); */ - g_list_foreach (sync_list, free_elem_cb, NULL); - g_list_free (sync_list); - sync_list = 0; - log_debug("Appsync list freed\n"); - } + if( sync_list != 0 ) + { + /*g_list_free_full(sync_list, appsync_free_elem); */ + g_list_foreach (sync_list, appsync_free_elem_cb, NULL); + g_list_free (sync_list); + sync_list = 0; + log_debug("Appsync list freed\n"); + } } -static gint list_sort_func(gconstpointer a, gconstpointer b) -{ - return strcasecmp( (char*)a, (char*)b ); +static gint appsync_list_sort_func(gconstpointer a, gconstpointer b) +{ + return strcasecmp( (char*)a, (char*)b ); } -void readlist(int diag) +void appsync_read_list(int diag) { - GDir *confdir = 0; - - const gchar *dirname; - struct list_elem *list_item; - - free_appsync_list(); - - if(diag) - { - if( !(confdir = g_dir_open(CONF_DIR_DIAG_PATH, 0, NULL)) ) - goto cleanup; - } - else - { - if( !(confdir = g_dir_open(CONF_DIR_PATH, 0, NULL)) ) - goto cleanup; - } - - while( (dirname = g_dir_read_name(confdir)) ) - { - log_debug("Read file %s\n", dirname); - if( (list_item = read_file(dirname, diag)) ) - sync_list = g_list_append(sync_list, list_item); - } + GDir *confdir = 0; + + const gchar *dirname; + struct list_elem *list_item; + + appsync_free_appsync_list(); + + if(diag) + { + if( !(confdir = g_dir_open(CONF_DIR_DIAG_PATH, 0, NULL)) ) + goto cleanup; + } + else + { + if( !(confdir = g_dir_open(CONF_DIR_PATH, 0, NULL)) ) + goto cleanup; + } + + while( (dirname = g_dir_read_name(confdir)) ) + { + log_debug("Read file %s\n", dirname); + if( (list_item = appsync_read_file(dirname, diag)) ) + sync_list = g_list_append(sync_list, list_item); + } cleanup: - if( confdir ) g_dir_close(confdir); + if( confdir ) g_dir_close(confdir); - /* sort list alphabetically so services for a mode + /* sort list alphabetically so services for a mode can be run in a certain order */ - sync_list=g_list_sort(sync_list, list_sort_func); + sync_list=g_list_sort(sync_list, appsync_list_sort_func); - /* set up session bus connection if app sync in use - * so we do not need to make the time consuming connect - * operation at enumeration time ... */ + /* set up session bus connection if app sync in use + * so we do not need to make the time consuming connect + * operation at enumeration time ... */ - if( sync_list ) - { - log_debug("Sync list valid\n"); + if( sync_list ) + { + log_debug("Sync list valid\n"); #ifdef APP_SYN_DBUS - usb_moded_app_sync_init_connection(); + dbusappsync_init_connection(); #endif - } + } } -static struct list_elem *read_file(const gchar *filename, int diag) +static struct list_elem *appsync_read_file(const gchar *filename, int diag) { - gchar *full_filename = NULL; - GKeyFile *settingsfile = NULL; - struct list_elem *list_item = NULL; - - if(diag) - { - if( !(full_filename = g_strconcat(CONF_DIR_DIAG_PATH, "/", filename, NULL)) ) - goto cleanup; - } - else - { - if( !(full_filename = g_strconcat(CONF_DIR_PATH, "/", filename, NULL)) ) - goto cleanup; - } - - if( !(settingsfile = g_key_file_new()) ) - goto cleanup; - - if( !g_key_file_load_from_file(settingsfile, full_filename, G_KEY_FILE_NONE, NULL) ) - goto cleanup; - - if( !(list_item = calloc(1, sizeof *list_item)) ) - goto cleanup; - - list_item->name = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_NAME_KEY, NULL); - log_debug("Appname = %s\n", list_item->name); - list_item->launch = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_LAUNCH_KEY, NULL); - log_debug("Launch = %s\n", list_item->launch); - list_item->mode = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_MODE_KEY, NULL); - log_debug("Launch mode = %s\n", list_item->mode); - list_item->systemd = g_key_file_get_integer(settingsfile, APP_INFO_ENTRY, APP_INFO_SYSTEMD_KEY, NULL); - log_debug("Systemd control = %d\n", list_item->systemd); - list_item->post = g_key_file_get_integer(settingsfile, APP_INFO_ENTRY, APP_INFO_POST, NULL); - list_item->state = APP_STATE_DONTCARE; + gchar *full_filename = NULL; + GKeyFile *settingsfile = NULL; + struct list_elem *list_item = NULL; + + if(diag) + { + if( !(full_filename = g_strconcat(CONF_DIR_DIAG_PATH, "/", filename, NULL)) ) + goto cleanup; + } + else + { + if( !(full_filename = g_strconcat(CONF_DIR_PATH, "/", filename, NULL)) ) + goto cleanup; + } + + if( !(settingsfile = g_key_file_new()) ) + goto cleanup; + + if( !g_key_file_load_from_file(settingsfile, full_filename, G_KEY_FILE_NONE, NULL) ) + goto cleanup; + + if( !(list_item = calloc(1, sizeof *list_item)) ) + goto cleanup; + + list_item->name = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_NAME_KEY, NULL); + log_debug("Appname = %s\n", list_item->name); + list_item->launch = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_LAUNCH_KEY, NULL); + log_debug("Launch = %s\n", list_item->launch); + list_item->mode = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_MODE_KEY, NULL); + log_debug("Launch mode = %s\n", list_item->mode); + list_item->systemd = g_key_file_get_integer(settingsfile, APP_INFO_ENTRY, APP_INFO_SYSTEMD_KEY, NULL); + log_debug("Systemd control = %d\n", list_item->systemd); + list_item->post = g_key_file_get_integer(settingsfile, APP_INFO_ENTRY, APP_INFO_POST, NULL); + list_item->state = APP_STATE_DONTCARE; cleanup: - if(settingsfile) - g_key_file_free(settingsfile); - g_free(full_filename); + if(settingsfile) + g_key_file_free(settingsfile); + g_free(full_filename); - /* if a minimum set of required elements is not filled in we discard the list_item */ - if( list_item && !(list_item->name && list_item->mode) ) - { - log_debug("Element invalid, discarding\n"); - free_elem(list_item); - list_item = 0; - } + /* if a minimum set of required elements is not filled in we discard the list_item */ + if( list_item && !(list_item->name && list_item->mode) ) + { + log_debug("Element invalid, discarding\n"); + appsync_free_elem(list_item); + list_item = 0; + } - return list_item; + return list_item; } /* @return 0 on succes, 1 if there is a failure */ -int activate_sync(const char *mode) +int appsync_activate_sync(const char *mode) { - GList *iter; - int count = 0; - - log_debug("activate sync"); - - /* Get start of activation timestamp */ - gettimeofday(&sync_tv, 0); + GList *iter; + int count = 0; - if( sync_list == 0 ) - { - log_debug("No sync list! Enumerating\n"); - enumerate_usb(); - return 0; - } + log_debug("activate sync"); - /* Count apps that need to be activated for this mode and - * mark them as currently inactive */ - for( iter = sync_list; iter; iter = g_list_next(iter) ) - { - struct list_elem *data = iter->data; + /* Get start of activation timestamp */ + gettimeofday(&sync_tv, 0); - if(!strcmp(data->mode, mode)) + if( sync_list == 0 ) { - ++count; - data->state = APP_STATE_INACTIVE; + log_debug("No sync list! Enumerating\n"); + appsync_enumerate_usb(); + return 0; } - else + + /* Count apps that need to be activated for this mode and + * mark them as currently inactive */ + for( iter = sync_list; iter; iter = g_list_next(iter) ) { - data->state = APP_STATE_DONTCARE; + struct list_elem *data = iter->data; + + if(!strcmp(data->mode, mode)) + { + ++count; + data->state = APP_STATE_INACTIVE; + } + else + { + data->state = APP_STATE_DONTCARE; + } } - } - /* If there is nothing to activate, enumerate immediately */ - if(count <= 0) - { - log_debug("Nothing to launch.\n"); - enumerate_usb(); - return(0); - } + /* If there is nothing to activate, enumerate immediately */ + if(count <= 0) + { + log_debug("Nothing to launch.\n"); + appsync_enumerate_usb(); + return(0); + } #ifdef APP_SYNC_DBUS - /* check dbus initialisation, skip dbus activated services if this fails */ - if(!usb_moded_app_sync_init()) - { - log_debug("dbus setup failed => skipping dbus launched apps \n"); - no_dbus = 1; - } + /* check dbus initialisation, skip dbus activated services if this fails */ + if(!dbusappsync_init()) + { + log_debug("dbus setup failed => skipping dbus launched apps \n"); + no_dbus = 1; + } #endif /* APP_SYNC_DBUS */ - /* start timer */ - start_enumerate_usb_timer(); + /* start timer */ + appsync_start_enumerate_usb_timer(); - /* go through list and launch apps */ - for( iter = sync_list; iter; iter = g_list_next(iter) ) - { - struct list_elem *data = iter->data; - if(!strcmp(mode, data->mode)) + /* go through list and launch apps */ + for( iter = sync_list; iter; iter = g_list_next(iter) ) { - /* do not launch items marked as post, will be launched after usb is up */ - if(data->post) - { - continue; - } - log_debug("launching pre-enum-app %s\n", data->name); - if(data->systemd) - { - if(!systemd_control_service(data->name, SYSTEMD_START)) - goto error; - mark_active(data->name, 0); - } - else if(data->launch) - { - /* skipping if dbus session bus is not available, - or not compiled in */ - if(no_dbus) - mark_active(data->name, 0); + struct list_elem *data = iter->data; + if(!strcmp(mode, data->mode)) + { + /* do not launch items marked as post, will be launched after usb is up */ + if(data->post) + { + continue; + } + log_debug("launching pre-enum-app %s\n", data->name); + if(data->systemd) + { + if(!systemd_control_service(data->name, SYSTEMD_START)) + goto error; + appsync_mark_active(data->name, 0); + } + else if(data->launch) + { + /* skipping if dbus session bus is not available, + or not compiled in */ + if(no_dbus) + appsync_mark_active(data->name, 0); #ifdef APP_SYNC_DBUS - else - if(!usb_moded_dbus_app_launch(data->launch)) - mark_active(data->name, 0); - else - goto error; + else + if(!dbusappsync_launch_app(data->launch)) + appsync_mark_active(data->name, 0); + else + goto error; #endif /* APP_SYNC_DBUS */ - } + } + } } - } - return(0); + return(0); error: - log_warning("Error launching a service!\n"); - return(1); + log_warning("Error launching a service!\n"); + return(1); } -int activate_sync_post(const char *mode) +int appsync_activate_sync_post(const char *mode) { - GList *iter; + GList *iter; - log_debug("activate post sync"); + log_debug("activate post sync"); - if( sync_list == 0 ) - { - log_debug("No sync list! skipping post sync\n"); - return 0; - } + if( sync_list == 0 ) + { + log_debug("No sync list! skipping post sync\n"); + return 0; + } #ifdef APP_SYNC_DBUS - /* check dbus initialisation, skip dbus activated services if this fails */ - if(!usb_moded_app_sync_init()) - { - log_debug("dbus setup failed => skipping dbus launched apps \n"); - no_dbus = 1; - } + /* check dbus initialisation, skip dbus activated services if this fails */ + if(!dbusappsync_init()) + { + log_debug("dbus setup failed => skipping dbus launched apps \n"); + no_dbus = 1; + } #endif /* APP_SYNC_DBUS */ - /* go through list and launch apps */ - for( iter = sync_list; iter; iter = g_list_next(iter) ) - { - struct list_elem *data = iter->data; - if(!strcmp(mode, data->mode)) + /* go through list and launch apps */ + for( iter = sync_list; iter; iter = g_list_next(iter) ) { - /* launch only items marked as post, others are already running */ - if(!data->post) - continue; - log_debug("launching post-enum-app %s\n", data->name); - if(data->systemd) - { - if(!systemd_control_service(data->name, SYSTEMD_START)) - goto error; - mark_active(data->name, 1); - } - else if(data->launch) - { - /* skipping if dbus session bus is not available, - or not compiled in */ - if(no_dbus) - continue; + struct list_elem *data = iter->data; + if(!strcmp(mode, data->mode)) + { + /* launch only items marked as post, others are already running */ + if(!data->post) + continue; + log_debug("launching post-enum-app %s\n", data->name); + if(data->systemd) + { + if(!systemd_control_service(data->name, SYSTEMD_START)) + goto error; + appsync_mark_active(data->name, 1); + } + else if(data->launch) + { + /* skipping if dbus session bus is not available, + or not compiled in */ + if(no_dbus) + continue; #ifdef APP_SYNC_DBUS - else - if(usb_moded_dbus_app_launch(data->launch) != 0) - goto error; + else + if(dbusappsync_launch_app(data->launch) != 0) + goto error; #endif /* APP_SYNC_DBUS */ - } + } + } } - } - return(0); + return(0); error: - log_warning("Error launching a service!\n"); - return(1); + log_warning("Error launching a service!\n"); + return(1); } -int mark_active(const gchar *name, int post) +int appsync_mark_active(const gchar *name, int post) { - int ret = -1; // assume name not found - int missing = 0; - - GList *iter; + int ret = -1; // assume name not found + int missing = 0; - log_debug("%s-enum-app %s is started\n", post ? "post" : "pre", name); + GList *iter; - for( iter = sync_list; iter; iter = g_list_next(iter) ) - { - struct list_elem *data = iter->data; + log_debug("%s-enum-app %s is started\n", post ? "post" : "pre", name); - if(!strcmp(data->name, name)) + for( iter = sync_list; iter; iter = g_list_next(iter) ) { - /* TODO: do we need to worry about duplicate names in the list? */ - ret = (data->state != APP_STATE_ACTIVE); - data->state = APP_STATE_ACTIVE; - - /* updated + missing -> not going to enumerate */ - if( missing ) break; + struct list_elem *data = iter->data; + + if(!strcmp(data->name, name)) + { + /* TODO: do we need to worry about duplicate names in the list? */ + ret = (data->state != APP_STATE_ACTIVE); + data->state = APP_STATE_ACTIVE; + + /* updated + missing -> not going to enumerate */ + if( missing ) break; + } + else if( data->state == APP_STATE_INACTIVE && data->post == post ) + { + missing = 1; + + /* updated + missing -> not going to enumerate */ + if( ret != -1 ) break; + } } - else if( data->state == APP_STATE_INACTIVE && data->post == post ) + if( !post && !missing ) { - missing = 1; - - /* updated + missing -> not going to enumerate */ - if( ret != -1 ) break; + log_debug("All pre-enum-apps active. Let's enumerate\n"); + appsync_enumerate_usb(); } - } - if( !post && !missing ) - { - log_debug("All pre-enum-apps active. Let's enumerate\n"); - enumerate_usb(); - } - - /* -1=not found, 0=already active, 1=activated now */ - return ret; + + /* -1=not found, 0=already active, 1=activated now */ + return ret; } -static gboolean enumerate_usb_cb(gpointer data) +static gboolean appsync_enumerate_usb_cb(gpointer data) { - (void)data; - enumerate_usb_id = 0; - log_debug("handling enumeration timeout"); - enumerate_usb(); - /* return false to stop the timer from repeating */ - return FALSE; + (void)data; + enumerate_usb_id = 0; + log_debug("handling enumeration timeout"); + appsync_enumerate_usb(); + /* return false to stop the timer from repeating */ + return FALSE; } -static void start_enumerate_usb_timer(void) +static void appsync_start_enumerate_usb_timer(void) { - log_debug("scheduling enumeration timeout"); - if( enumerate_usb_id ) - g_source_remove(enumerate_usb_id), enumerate_usb_id = 0; - enumerate_usb_id = g_timeout_add_seconds(2, enumerate_usb_cb, NULL); + log_debug("scheduling enumeration timeout"); + if( enumerate_usb_id ) + g_source_remove(enumerate_usb_id), enumerate_usb_id = 0; + enumerate_usb_id = g_timeout_add_seconds(2, appsync_enumerate_usb_cb, NULL); } -static void cancel_enumerate_usb_timer(void) +static void appsync_cancel_enumerate_usb_timer(void) { - if( enumerate_usb_id ) - { - log_debug("canceling enumeration timeout"); - g_source_remove(enumerate_usb_id), enumerate_usb_id = 0; - } + if( enumerate_usb_id ) + { + log_debug("canceling enumeration timeout"); + g_source_remove(enumerate_usb_id), enumerate_usb_id = 0; + } } -static void enumerate_usb(void) +static void appsync_enumerate_usb(void) { - struct timeval tv; + struct timeval tv; - /* Stop the timer in case of explicit enumeration call */ - cancel_enumerate_usb_timer(); + /* Stop the timer in case of explicit enumeration call */ + appsync_cancel_enumerate_usb_timer(); - /* Debug: how long it took from sync start to get here */ - gettimeofday(&tv, 0); - timersub(&tv, &sync_tv, &tv); - log_debug("sync to enum: %.3f seconds", tv.tv_sec + tv.tv_usec * 1e-6); + /* Debug: how long it took from sync start to get here */ + gettimeofday(&tv, 0); + timersub(&tv, &sync_tv, &tv); + log_debug("sync to enum: %.3f seconds", tv.tv_sec + tv.tv_usec * 1e-6); #ifdef APP_SYNC_DBUS - /* remove dbus service */ - usb_moded_appsync_cleanup(); + /* remove dbus service */ + dbusappsync_cleanup(); #endif /* APP_SYNC_DBUS */ } static void appsync_stop_apps(int post) { - GList *iter = 0; - - for( iter = sync_list; iter; iter = g_list_next(iter) ) - { - struct list_elem *data = iter->data; + GList *iter = 0; - if(data->systemd && data->state == APP_STATE_ACTIVE && data->post == post) + for( iter = sync_list; iter; iter = g_list_next(iter) ) { - log_debug("stopping %s-enum-app %s", post ? "post" : "pre", data->name); - if(!systemd_control_service(data->name, SYSTEMD_STOP)) - log_debug("Failed to stop %s\n", data->name); - data->state = APP_STATE_DONTCARE; + struct list_elem *data = iter->data; + + if(data->systemd && data->state == APP_STATE_ACTIVE && data->post == post) + { + log_debug("stopping %s-enum-app %s", post ? "post" : "pre", data->name); + if(!systemd_control_service(data->name, SYSTEMD_STOP)) + log_debug("Failed to stop %s\n", data->name); + data->state = APP_STATE_DONTCARE; + } } - } } int appsync_stop(gboolean force) { - /* If force arg is used, stop all applications that - * could have been started by usb-moded */ - if(force) - { - GList *iter; - log_debug("assuming all applications are active"); - - for( iter = sync_list; iter; iter = g_list_next(iter) ) + /* If force arg is used, stop all applications that + * could have been started by usb-moded */ + if(force) { - struct list_elem *data = iter->data; - data->state = APP_STATE_ACTIVE; + GList *iter; + log_debug("assuming all applications are active"); + + for( iter = sync_list; iter; iter = g_list_next(iter) ) + { + struct list_elem *data = iter->data; + data->state = APP_STATE_ACTIVE; + } } - } - /* Stop post-apps 1st */ - appsync_stop_apps(1); + /* Stop post-apps 1st */ + appsync_stop_apps(1); - /* Then pre-apps */ - appsync_stop_apps(0); + /* Then pre-apps */ + appsync_stop_apps(0); - /* Do not leave active timers behind */ - cancel_enumerate_usb_timer(); - return(0); + /* Do not leave active timers behind */ + appsync_cancel_enumerate_usb_timer(); + return(0); } diff --git a/src/usb_moded-appsync.h b/src/usb_moded-appsync.h index 0234957..5ade098 100644 --- a/src/usb_moded-appsync.h +++ b/src/usb_moded-appsync.h @@ -1,65 +1,84 @@ /* - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2013-2016 Jolla Ltd. + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * author: Philippe De Swert + * author: Philippe De Swert + * author: Philippe De Swert + * author: Philippe De Swert + * author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - author: Philippe De Swert - author: Philippe De Swert - author: Simo Piiroinen +#ifndef USB_MODED_APPSYNC_H_ +# define USB_MODED_APPSYNC_H_ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +/* ========================================================================= * + * Constants + * ========================================================================= */ - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +# define CONF_DIR_PATH "/etc/usb-moded/run" +# define CONF_DIR_DIAG_PATH "/etc/usb-moded/run-diag" -#define CONF_DIR_PATH "/etc/usb-moded/run" -#define CONF_DIR_DIAG_PATH "/etc/usb-moded/run-diag" +# define APP_INFO_ENTRY "info" +# define APP_INFO_MODE_KEY "mode" +# define APP_INFO_NAME_KEY "name" +# define APP_INFO_LAUNCH_KEY "launch" +# define APP_INFO_SYSTEMD_KEY "systemd" +# define APP_INFO_POST "post" -#define APP_INFO_ENTRY "info" -#define APP_INFO_MODE_KEY "mode" -#define APP_INFO_NAME_KEY "name" -#define APP_INFO_LAUNCH_KEY "launch" -#define APP_INFO_SYSTEMD_KEY "systemd" -#define APP_INFO_POST "post" +/* ========================================================================= * + * Types + * ========================================================================= */ /** Application activation state */ typedef enum { - /** Application is not relevant for the current mode */ - APP_STATE_DONTCARE = 0, - /** Application should be started */ - APP_STATE_INACTIVE = 1, - /** Application should be stopped when exiting the mode */ - APP_STATE_ACTIVE = 2, + /** Application is not relevant for the current mode */ + APP_STATE_DONTCARE = 0, + /** Application should be started */ + APP_STATE_INACTIVE = 1, + /** Application should be stopped when exiting the mode */ + APP_STATE_ACTIVE = 2, } app_state_t; -/** - * keep all the needed info together for launching an app +/** + * keep all the needed info together for launching an app */ typedef struct list_elem { - char *name; /**< name of the app to launch */ - char *mode; /**< mode in which to launch the app */ - char *launch; /**< dbus launch command/address */ - app_state_t state; /**< marker to check if the app has started sucessfully */ - int systemd; /**< marker to know if we start it with systemd or not */ - int post; /**< marker to indicate when to start the app */ + char *name; /**< name of the app to launch */ + char *mode; /**< mode in which to launch the app */ + char *launch; /**< dbus launch command/address */ + app_state_t state; /**< marker to check if the app has started sucessfully */ + int systemd; /**< marker to know if we start it with systemd or not */ + int post; /**< marker to indicate when to start the app */ } list_elem; -void readlist(int diag); -int activate_sync(const char *mode); -int activate_sync_post(const char *mode); -int mark_active(const gchar *name, int post); -int appsync_stop(gboolean force); -void free_appsync_list(void); -void usb_moded_appsync_cleanup(void); +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- appsync -- */ + +void appsync_free_appsync_list (void); +void appsync_read_list (int diag); +int appsync_activate_sync (const char *mode); +int appsync_activate_sync_post(const char *mode); +int appsync_mark_active (const gchar *name, int post); +int appsync_stop (gboolean force); + +#endif /* USB_MODED_APPSYNC_H_ */ diff --git a/src/usb_moded-config-private.h b/src/usb_moded-config-private.h index 362104d..6c682f5 100644 --- a/src/usb_moded-config-private.h +++ b/src/usb_moded-config-private.h @@ -1,36 +1,80 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2012-2015 Jolla. All rights reserved. - - Author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2012-2018 Jolla. All rights reserved. + * + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Slava Monich + * Author: Martin Jones + * Author: Andrew den Exter + * Author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + /* * Gets/sets information for the usb modes from dbus -*/ + */ /*============================================================================= */ -char * get_mode_setting(void); -set_config_result_t set_mode_setting(const char *mode); -set_config_result_t set_hide_mode_setting(const char *mode); -set_config_result_t set_unhide_mode_setting(const char *mode); -char * get_hidden_modes(void); -set_config_result_t set_network_setting(const char *config, const char *setting); -char * get_mode_whitelist(void); -set_config_result_t set_mode_whitelist(const char *whitelist); -set_config_result_t set_mode_in_whitelist(const char *mode, int allowed); +#ifndef USB_MODED_CONFIG_PRIVATE_H_ +# define USB_MODED_CONFIG_PRIVATE_H_ + +# include "usb_moded-config.h" + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- config -- */ + +char *config_find_mounts (void); +int config_find_sync (void); +char *config_find_alt_mount (void); +char *config_find_udev_path (void); +char *config_find_udev_subsystem (void); +char *config_check_trigger (void); +char *config_get_trigger_subsystem (void); +char *config_get_trigger_mode (void); +char *config_get_trigger_property (void); +char *config_get_trigger_value (void); +char *config_get_mode_setting (void); +int config_value_changed (GKeyFile *settingsfile, const char *entry, const char *key, const char *new_value); +set_config_result_t config_set_config_setting (const char *entry, const char *key, const char *value); +set_config_result_t config_set_mode_setting (const char *mode); +set_config_result_t config_set_hide_mode_setting (const char *mode); +set_config_result_t config_set_unhide_mode_setting (const char *mode); +set_config_result_t config_set_mode_whitelist (const char *whitelist); +set_config_result_t config_set_mode_in_whitelist (const char *mode, int allowed); +set_config_result_t config_set_network_setting (const char *config, const char *setting); +char *config_get_network_setting (const char *config); +int config_merge_conf_file (void); +char *config_get_android_manufacturer(void); +char *config_get_android_vendor_id (void); +char *config_get_android_product (void); +char *config_get_android_product_id (void); +char *config_get_hidden_modes (void); +char *config_get_mode_whitelist (void); +int config_is_roaming_not_allowed (void); + +/* ========================================================================= * + * Macros + * ========================================================================= */ + +# define SET_CONFIG_OK(ret) ((ret) >= SET_CONFIG_UPDATED) +#endif /* USB_MODED_CONFIG_PRIVATE_H_ */ diff --git a/src/usb_moded-config.c b/src/usb_moded-config.c index 26a74e5..5272174 100644 --- a/src/usb_moded-config.c +++ b/src/usb_moded-config.c @@ -1,25 +1,35 @@ /** - @file usb_moded-config.c - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2012-2015 Jolla. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-config.c + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2012-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Reto Zingg + * @author: Thomas Perl + * @author: Slava Monich + * @author: Martin Jones + * @author: Jarko Poutiainen + * @author: Simo Piiroinen + * @author: Andrew den Exter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -32,10 +42,7 @@ #include #include -/* -#include -#include -*/ + #include "usb_moded.h" #include "usb_moded-config.h" #include "usb_moded-config-private.h" @@ -49,308 +56,359 @@ # include "usb_moded-ssu.h" #endif -static int get_conf_int(const gchar *entry, const gchar *key); -static char * get_conf_string(const gchar *entry, const gchar *key); -static char * get_kcmdline_string(const char *entry); - -static int validate_ip(const char *ipadd) -{ - unsigned int b1, b2, b3, b4; - unsigned char c; - - if (sscanf(ipadd, "%3u.%3u.%3u.%3u%c", &b1, &b2, &b3, &b4, &c) != 4) +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- config -- */ + +static int config_validate_ip (const char *ipadd); +char *config_find_mounts (void); +int config_find_sync (void); +char *config_find_alt_mount (void); +char *config_find_udev_path (void); +char *config_find_udev_subsystem (void); +char *config_check_trigger (void); +char *config_get_trigger_subsystem (void); +char *config_get_trigger_mode (void); +char *config_get_trigger_property (void); +char *config_get_trigger_value (void); +static char *config_get_network_ip (void); +static char *config_get_network_interface (void); +static char *config_get_network_gateway (void); +static char *config_get_network_netmask (void); +static char *config_get_network_nat_interface(void); +static void config_create_conf_file (void); +static int config_get_conf_int (const gchar *entry, const gchar *key); +static char *config_get_conf_string (const gchar *entry, const gchar *key); +static char *config_get_kcmdline_string (const char *entry); +char *config_get_mode_setting (void); +int config_value_changed (GKeyFile *settingsfile, const char *entry, const char *key, const char *new_value); +set_config_result_t config_set_config_setting (const char *entry, const char *key, const char *value); +set_config_result_t config_set_mode_setting (const char *mode); +static char *config_make_modes_string (const char *key, const char *mode_name, int include); +set_config_result_t config_set_hide_mode_setting (const char *mode); +set_config_result_t config_set_unhide_mode_setting (const char *mode); +set_config_result_t config_set_mode_whitelist (const char *whitelist); +set_config_result_t config_set_mode_in_whitelist (const char *mode, int allowed); +set_config_result_t config_set_network_setting (const char *config, const char *setting); +char *config_get_network_setting (const char *config); +static void config_merge_key (GKeyFile *dest, GKeyFile *srce, const char *grp, const char *key); +static void config_merge_group (GKeyFile *dest, GKeyFile *srce, const char *grp); +static void config_merge_file (GKeyFile *dest, GKeyFile *srce); +static int config_glob_error_cb (const char *path, int err); +static GKeyFile *config_read_ini_files (void); +int config_merge_conf_file (void); +char *config_get_android_manufacturer (void); +char *config_get_android_vendor_id (void); +char *config_get_android_product (void); +char *config_get_android_product_id (void); +char *config_get_hidden_modes (void); +char *config_get_mode_whitelist (void); +int config_is_roaming_not_allowed (void); + +/* ========================================================================= * + * Functions + * ========================================================================= */ + +static int config_validate_ip(const char *ipadd) +{ + unsigned int b1, b2, b3, b4; + unsigned char c; + + if (sscanf(ipadd, "%3u.%3u.%3u.%3u%c", &b1, &b2, &b3, &b4, &c) != 4) return(-1); - if ((b1 | b2 | b3 | b4) > 255) + if ((b1 | b2 | b3 | b4) > 255) return(-1); - if (strspn(ipadd, "0123456789.") < strlen(ipadd)) + if (strspn(ipadd, "0123456789.") < strlen(ipadd)) return(-1); - /* all ok */ - return 0; + /* all ok */ + return 0; } -char *find_mounts(void) +char *config_find_mounts(void) { - - char *ret = NULL; - ret = get_conf_string(FS_MOUNT_ENTRY, FS_MOUNT_KEY); - if(ret == NULL) - { - ret = g_strdup(FS_MOUNT_DEFAULT); - log_debug("Default mount = %s\n", ret); - } - return(ret); + char *ret = NULL; + + ret = config_get_conf_string(FS_MOUNT_ENTRY, FS_MOUNT_KEY); + if(ret == NULL) + { + ret = g_strdup(FS_MOUNT_DEFAULT); + log_debug("Default mount = %s\n", ret); + } + return(ret); } -int find_sync(void) +int config_find_sync(void) { - return(get_conf_int(FS_SYNC_ENTRY, FS_SYNC_KEY)); + return(config_get_conf_int(FS_SYNC_ENTRY, FS_SYNC_KEY)); } -char * find_alt_mount(void) +char * config_find_alt_mount(void) { - return(get_conf_string(ALT_MOUNT_ENTRY, ALT_MOUNT_KEY)); + return(config_get_conf_string(ALT_MOUNT_ENTRY, ALT_MOUNT_KEY)); } -char * find_udev_path(void) +char * config_find_udev_path(void) { - return(get_conf_string(UDEV_PATH_ENTRY, UDEV_PATH_KEY)); + return(config_get_conf_string(UDEV_PATH_ENTRY, UDEV_PATH_KEY)); } -char * find_udev_subsystem(void) +char * config_find_udev_subsystem(void) { - return(get_conf_string(UDEV_PATH_ENTRY, UDEV_SUBSYSTEM_KEY)); + return(config_get_conf_string(UDEV_PATH_ENTRY, UDEV_SUBSYSTEM_KEY)); } -char * check_trigger(void) +char * config_check_trigger(void) { - return(get_conf_string(TRIGGER_ENTRY, TRIGGER_PATH_KEY)); + return(config_get_conf_string(TRIGGER_ENTRY, TRIGGER_PATH_KEY)); } -char * get_trigger_subsystem(void) +char * config_get_trigger_subsystem(void) { - return(get_conf_string(TRIGGER_ENTRY, TRIGGER_UDEV_SUBSYSTEM)); + return(config_get_conf_string(TRIGGER_ENTRY, TRIGGER_UDEV_SUBSYSTEM)); } -char * get_trigger_mode(void) +char * config_get_trigger_mode(void) { - return(get_conf_string(TRIGGER_ENTRY, TRIGGER_MODE_KEY)); + return(config_get_conf_string(TRIGGER_ENTRY, TRIGGER_MODE_KEY)); } -char * get_trigger_property(void) +char * config_get_trigger_property(void) { - return(get_conf_string(TRIGGER_ENTRY, TRIGGER_PROPERTY_KEY)); + return(config_get_conf_string(TRIGGER_ENTRY, TRIGGER_PROPERTY_KEY)); } -char * get_trigger_value(void) +char * config_get_trigger_value(void) { - return(get_conf_string(TRIGGER_ENTRY, TRIGGER_PROPERTY_VALUE_KEY)); + return(config_get_conf_string(TRIGGER_ENTRY, TRIGGER_PROPERTY_VALUE_KEY)); } -static char * get_network_ip(void) +static char * config_get_network_ip(void) { - char * ip = get_kcmdline_string(NETWORK_IP_KEY); - if (ip != NULL) - if(!validate_ip(ip)) - return(ip); + char * ip = config_get_kcmdline_string(NETWORK_IP_KEY); + if (ip != NULL) + if(!config_validate_ip(ip)) + return(ip); - return(get_conf_string(NETWORK_ENTRY, NETWORK_IP_KEY)); + return(config_get_conf_string(NETWORK_ENTRY, NETWORK_IP_KEY)); } -static char * get_network_interface(void) +static char * config_get_network_interface(void) { - return(get_conf_string(NETWORK_ENTRY, NETWORK_INTERFACE_KEY)); + return(config_get_conf_string(NETWORK_ENTRY, NETWORK_INTERFACE_KEY)); } -static char * get_network_gateway(void) +static char * config_get_network_gateway(void) { - char * gw = get_kcmdline_string(NETWORK_GATEWAY_KEY); - if (gw != NULL) - return(gw); + char * gw = config_get_kcmdline_string(NETWORK_GATEWAY_KEY); + if (gw != NULL) + return(gw); - return(get_conf_string(NETWORK_ENTRY, NETWORK_GATEWAY_KEY)); + return(config_get_conf_string(NETWORK_ENTRY, NETWORK_GATEWAY_KEY)); } -static char * get_network_netmask(void) +static char * config_get_network_netmask(void) { - char * netmask = get_kcmdline_string(NETWORK_NETMASK_KEY); - if (netmask != NULL) - return(netmask); + char * netmask = config_get_kcmdline_string(NETWORK_NETMASK_KEY); + if (netmask != NULL) + return(netmask); - return(get_conf_string(NETWORK_ENTRY, NETWORK_NETMASK_KEY)); + return(config_get_conf_string(NETWORK_ENTRY, NETWORK_NETMASK_KEY)); } -static char * get_network_nat_interface(void) +static char * config_get_network_nat_interface(void) { - return(get_conf_string(NETWORK_ENTRY, NETWORK_NAT_INTERFACE_KEY)); + return(config_get_conf_string(NETWORK_ENTRY, NETWORK_NAT_INTERFACE_KEY)); } /* create basic conffile with sensible defaults */ -static void create_conf_file(void) +static void config_create_conf_file(void) { - GKeyFile *settingsfile; - gchar *keyfile; - int dir = 1; - struct stat dir_stat; + GKeyFile *settingsfile; + gchar *keyfile; + int dir = 1; + struct stat dir_stat; - /* since this function can also be called when the dir exists we only create + /* since this function can also be called when the dir exists we only create it if it is missing */ - if(stat(CONFIG_FILE_DIR, &dir_stat)) - { - dir = mkdir(CONFIG_FILE_DIR, 0755); - if(dir < 0) - { - log_warning("Could not create confdir, continuing without configuration!\n"); - /* no point in trying to generate the config file if the dir cannot be created */ - return; - } - } - - settingsfile = g_key_file_new(); - - g_key_file_set_string(settingsfile, MODE_SETTING_ENTRY, MODE_SETTING_KEY, MODE_DEVELOPER ); - keyfile = g_key_file_to_data (settingsfile, NULL, NULL); - if(g_file_set_contents(FS_MOUNT_CONFIG_FILE, keyfile, -1, NULL) == 0) - log_debug("Conffile creation failed. Continuing without configuration!\n"); - free(keyfile); - g_key_file_free(settingsfile); -} - -static int get_conf_int(const gchar *entry, const gchar *key) -{ - GKeyFile *settingsfile; - gboolean test = FALSE; - gchar **keys, **origkeys; - int ret = 0; - - settingsfile = g_key_file_new(); - test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); - if(!test) - { - log_debug("no conffile, Creating\n"); - create_conf_file(); - } - keys = g_key_file_get_keys (settingsfile, entry, NULL, NULL); - if(keys == NULL) + if(stat(CONFIG_FILE_DIR, &dir_stat)) + { + dir = mkdir(CONFIG_FILE_DIR, 0755); + if(dir < 0) + { + log_warning("Could not create confdir, continuing without configuration!\n"); + /* no point in trying to generate the config file if the dir cannot be created */ + return; + } + } + + settingsfile = g_key_file_new(); + + g_key_file_set_string(settingsfile, MODE_SETTING_ENTRY, MODE_SETTING_KEY, MODE_DEVELOPER ); + keyfile = g_key_file_to_data (settingsfile, NULL, NULL); + if(g_file_set_contents(FS_MOUNT_CONFIG_FILE, keyfile, -1, NULL) == 0) + log_debug("Conffile creation failed. Continuing without configuration!\n"); + free(keyfile); + g_key_file_free(settingsfile); +} + +static int config_get_conf_int(const gchar *entry, const gchar *key) +{ + GKeyFile *settingsfile; + gboolean test = FALSE; + gchar **keys, **origkeys; + int ret = 0; + + settingsfile = g_key_file_new(); + test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); + if(!test) + { + log_debug("no conffile, Creating\n"); + config_create_conf_file(); + } + keys = g_key_file_get_keys (settingsfile, entry, NULL, NULL); + if(keys == NULL) return ret; - origkeys = keys; - while (*keys != NULL) - { + origkeys = keys; + while (*keys != NULL) + { if(!strcmp(*keys, key)) { - ret = g_key_file_get_integer(settingsfile, entry, *keys, NULL); - log_debug("%s key value = %d\n", key, ret); + ret = g_key_file_get_integer(settingsfile, entry, *keys, NULL); + log_debug("%s key value = %d\n", key, ret); } keys++; - } - g_strfreev(origkeys); - g_key_file_free(settingsfile); - return(ret); - -} - -static char * get_conf_string(const gchar *entry, const gchar *key) -{ - GKeyFile *settingsfile; - gboolean test = FALSE; - gchar **keys, **origkeys, *tmp_char = NULL; - settingsfile = g_key_file_new(); - test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); - if(!test) - { - log_debug("No conffile. Creating\n"); - create_conf_file(); - /* should succeed now */ - g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); - } - keys = g_key_file_get_keys (settingsfile, entry, NULL, NULL); - if(keys == NULL) + } + g_strfreev(origkeys); + g_key_file_free(settingsfile); + return(ret); + +} + +static char * config_get_conf_string(const gchar *entry, const gchar *key) +{ + GKeyFile *settingsfile; + gboolean test = FALSE; + gchar **keys, **origkeys, *tmp_char = NULL; + settingsfile = g_key_file_new(); + test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); + if(!test) + { + log_debug("No conffile. Creating\n"); + config_create_conf_file(); + /* should succeed now */ + g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); + } + keys = g_key_file_get_keys (settingsfile, entry, NULL, NULL); + if(keys == NULL) goto end; - origkeys = keys; - while (*keys != NULL) - { + origkeys = keys; + while (*keys != NULL) + { if(!strcmp(*keys, key)) { - tmp_char = g_key_file_get_string(settingsfile, entry, *keys, NULL); - if(tmp_char) - { - log_debug("key %s value = %s\n", key, tmp_char); - } + tmp_char = g_key_file_get_string(settingsfile, entry, *keys, NULL); + if(tmp_char) + { + log_debug("key %s value = %s\n", key, tmp_char); + } } keys++; - } - g_strfreev(origkeys); + } + g_strfreev(origkeys); end: - g_key_file_free(settingsfile); - return(tmp_char); + g_key_file_free(settingsfile); + return(tmp_char); } -static char * get_kcmdline_string(const char *entry) +static char * config_get_kcmdline_string(const char *entry) { - int fd; - char cmdLine[1024]; - char *ret = NULL; - int len; - gint argc = 0; - gchar **argv = NULL; - gchar **arg_tokens = NULL, **network_tokens = NULL; - GError *optErr = NULL; - int i; + int fd; + char cmdLine[1024]; + char *ret = NULL; + int len; + gint argc = 0; + gchar **argv = NULL; + gchar **arg_tokens = NULL, **network_tokens = NULL; + GError *optErr = NULL; + int i; - if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) - { - log_debug("could not read /proc/cmdline"); - return(ret); - } + if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) + { + log_debug("could not read /proc/cmdline"); + return(ret); + } - len = read(fd, cmdLine, sizeof(cmdLine) - 1); - close(fd); + len = read(fd, cmdLine, sizeof(cmdLine) - 1); + close(fd); - if (len <= 0) - { - log_debug("kernel command line was empty"); - return(ret); - } + if (len <= 0) + { + log_debug("kernel command line was empty"); + return(ret); + } - cmdLine[len] = '\0'; + cmdLine[len] = '\0'; - /* we're looking for a piece of the kernel command line matching this: - ip=192.168.3.100::192.168.3.1:255.255.255.0::usb0:on */ - if (!g_shell_parse_argv(cmdLine, &argc, &argv, &optErr)) - { - g_error_free(optErr); - return(ret); - } + /* we're looking for a piece of the kernel command line matching this: + ip=192.168.3.100::192.168.3.1:255.255.255.0::usb0:on */ + if (!g_shell_parse_argv(cmdLine, &argc, &argv, &optErr)) + { + g_error_free(optErr); + return(ret); + } - /* find the ip token */ - for (i=0; i < argc; i++) - { - arg_tokens = g_strsplit(argv[i], "=", 2); - if (!g_ascii_strcasecmp(arg_tokens[0], "usb_moded_ip")) + /* find the ip token */ + for (i=0; i < argc; i++) { - network_tokens = g_strsplit(arg_tokens[1], ":", 7); - /* check if it is for the usb or rndis interface */ - if(g_strrstr(network_tokens[5], "usb")|| (g_strrstr(network_tokens[5], "rndis"))) - { - if(!strcmp(entry, NETWORK_IP_KEY)) - { - g_free(ret), ret = g_strdup(network_tokens[0]); - log_debug("Command line ip = %s\n", ret); - } - if(!strcmp(entry, NETWORK_GATEWAY_KEY)) - { - /* gateway might be empty, so we do not want to return an empty string */ - if(strlen(network_tokens[2]) > 2) - { - g_free(ret), ret = g_strdup(network_tokens[2]); - log_debug("Command line gateway = %s\n", ret); - } - } - if(!strcmp(entry, NETWORK_NETMASK_KEY)) - { - g_free(ret), ret = g_strdup(network_tokens[3]); - log_debug("Command line netmask = %s\n", ret); - } - } - } - g_strfreev(arg_tokens); - } - g_strfreev(argv); - g_strfreev(network_tokens); - - return(ret); -} - -char * get_mode_setting(void) -{ - char * mode = get_kcmdline_string(MODE_SETTING_KEY); - if (mode != NULL) - return(mode); - - return(get_conf_string(MODE_SETTING_ENTRY, MODE_SETTING_KEY)); + arg_tokens = g_strsplit(argv[i], "=", 2); + if (!g_ascii_strcasecmp(arg_tokens[0], "usb_moded_ip")) + { + network_tokens = g_strsplit(arg_tokens[1], ":", 7); + /* check if it is for the usb or rndis interface */ + if(g_strrstr(network_tokens[5], "usb")|| (g_strrstr(network_tokens[5], "rndis"))) + { + if(!strcmp(entry, NETWORK_IP_KEY)) + { + g_free(ret), ret = g_strdup(network_tokens[0]); + log_debug("Command line ip = %s\n", ret); + } + if(!strcmp(entry, NETWORK_GATEWAY_KEY)) + { + /* gateway might be empty, so we do not want to return an empty string */ + if(strlen(network_tokens[2]) > 2) + { + g_free(ret), ret = g_strdup(network_tokens[2]); + log_debug("Command line gateway = %s\n", ret); + } + } + if(!strcmp(entry, NETWORK_NETMASK_KEY)) + { + g_free(ret), ret = g_strdup(network_tokens[3]); + log_debug("Command line netmask = %s\n", ret); + } + } + } + g_strfreev(arg_tokens); + } + g_strfreev(argv); + g_strfreev(network_tokens); + + return(ret); +} + +char * config_get_mode_setting(void) +{ + char * mode = config_get_kcmdline_string(MODE_SETTING_KEY); + if (mode != NULL) + return(mode); + + return(config_get_conf_string(MODE_SETTING_ENTRY, MODE_SETTING_KEY)); } /* * @param settingsfile: already opened settingsfile we want to read an entry from @@ -362,304 +420,304 @@ char * get_mode_setting(void) */ int config_value_changed(GKeyFile *settingsfile, const char *entry, const char *key, const char *new_value) { - char *old_value = g_key_file_get_string(settingsfile, entry, key, NULL); - int changed = (g_strcmp0(old_value, new_value) != 0); - g_free(old_value); - return changed; -} - -set_config_result_t set_config_setting(const char *entry, const char *key, const char *value) -{ - GKeyFile *settingsfile; - gboolean test = FALSE; - set_config_result_t ret = SET_CONFIG_ERROR; - gchar *keyfile; - - settingsfile = g_key_file_new(); - test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); - if(test) - { - if(!config_value_changed(settingsfile, entry, key, value)) - { - g_key_file_free(settingsfile); - return SET_CONFIG_UNCHANGED; - } - } - else - { - log_debug("No conffile. Creating.\n"); - create_conf_file(); - } - - g_key_file_set_string(settingsfile, entry, key, value); - keyfile = g_key_file_to_data (settingsfile, NULL, NULL); - /* free the settingsfile before writing things out to be sure + char *old_value = g_key_file_get_string(settingsfile, entry, key, NULL); + int changed = (g_strcmp0(old_value, new_value) != 0); + g_free(old_value); + return changed; +} + +set_config_result_t config_set_config_setting(const char *entry, const char *key, const char *value) +{ + GKeyFile *settingsfile; + gboolean test = FALSE; + set_config_result_t ret = SET_CONFIG_ERROR; + gchar *keyfile; + + settingsfile = g_key_file_new(); + test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); + if(test) + { + if(!config_value_changed(settingsfile, entry, key, value)) + { + g_key_file_free(settingsfile); + return SET_CONFIG_UNCHANGED; + } + } + else + { + log_debug("No conffile. Creating.\n"); + config_create_conf_file(); + } + + g_key_file_set_string(settingsfile, entry, key, value); + keyfile = g_key_file_to_data (settingsfile, NULL, NULL); + /* free the settingsfile before writing things out to be sure the contents will be correctly written to file afterwards. Just a precaution. */ - g_key_file_free(settingsfile); - if (g_file_set_contents(FS_MOUNT_CONFIG_FILE, keyfile, -1, NULL)) - ret = SET_CONFIG_UPDATED; - g_free(keyfile); - - return (ret); + g_key_file_free(settingsfile); + if (g_file_set_contents(FS_MOUNT_CONFIG_FILE, keyfile, -1, NULL)) + ret = SET_CONFIG_UPDATED; + g_free(keyfile); + + return (ret); } -set_config_result_t set_mode_setting(const char *mode) +set_config_result_t config_set_mode_setting(const char *mode) { - if (strcmp(mode, MODE_ASK) && valid_mode(mode)) - return SET_CONFIG_ERROR; - return (set_config_setting(MODE_SETTING_ENTRY, MODE_SETTING_KEY, mode)); + if (strcmp(mode, MODE_ASK) && usbmoded_valid_mode(mode)) + return SET_CONFIG_ERROR; + return (config_set_config_setting(MODE_SETTING_ENTRY, MODE_SETTING_KEY, mode)); } /* Builds the string used for hidden modes, when hide set to one builds the - new string of hidden modes when adding one, otherwise it will remove one */ -static char * make_modes_string(const char *key, const char *mode_name, int include) -{ - char *modes_new = 0; - char *modes_old = 0; - gchar **modes_arr = 0; - GString *modes_tmp = 0; - int i; - - /* Get current comma separated list of hidden modes */ - modes_old = get_conf_string(MODE_SETTING_ENTRY, key); - if(!modes_old) - { - modes_old = g_strdup(""); - } + new string of hidden modes when adding one, otherwise it will remove one */ +static char * config_make_modes_string(const char *key, const char *mode_name, int include) +{ + char *modes_new = 0; + char *modes_old = 0; + gchar **modes_arr = 0; + GString *modes_tmp = 0; + int i; + + /* Get current comma separated list of hidden modes */ + modes_old = config_get_conf_string(MODE_SETTING_ENTRY, key); + if(!modes_old) + { + modes_old = g_strdup(""); + } - modes_arr = g_strsplit(modes_old, ",", 0); + modes_arr = g_strsplit(modes_old, ",", 0); - modes_tmp = g_string_new(NULL); + modes_tmp = g_string_new(NULL); - for(i = 0; modes_arr[i] != NULL; i++) - { - if(strlen(modes_arr[i]) == 0) + for(i = 0; modes_arr[i] != NULL; i++) { - /* Skip any empty strings */ - continue; - } + if(strlen(modes_arr[i]) == 0) + { + /* Skip any empty strings */ + continue; + } - if(!strcmp(modes_arr[i], mode_name)) - { - /* When unhiding, just skip all matching entries */ - if(!include) - continue; + if(!strcmp(modes_arr[i], mode_name)) + { + /* When unhiding, just skip all matching entries */ + if(!include) + continue; - /* When hiding, keep the 1st match and ignore the rest */ - include = 0; - } + /* When hiding, keep the 1st match and ignore the rest */ + include = 0; + } - if(modes_tmp->len > 0) - modes_tmp = g_string_append(modes_tmp, ","); - modes_tmp = g_string_append(modes_tmp, modes_arr[i]); - } + if(modes_tmp->len > 0) + modes_tmp = g_string_append(modes_tmp, ","); + modes_tmp = g_string_append(modes_tmp, modes_arr[i]); + } - if(include) - { - /* Adding a hidden mode and no matching entry was found */ - if(modes_tmp->len > 0) - modes_tmp = g_string_append(modes_tmp, ","); - modes_tmp = g_string_append(modes_tmp, mode_name); - } + if(include) + { + /* Adding a hidden mode and no matching entry was found */ + if(modes_tmp->len > 0) + modes_tmp = g_string_append(modes_tmp, ","); + modes_tmp = g_string_append(modes_tmp, mode_name); + } - modes_new = g_string_free(modes_tmp, FALSE), modes_tmp = 0; + modes_new = g_string_free(modes_tmp, FALSE), modes_tmp = 0; - g_strfreev(modes_arr), modes_arr = 0; + g_strfreev(modes_arr), modes_arr = 0; - g_free(modes_old), modes_old = 0; + g_free(modes_old), modes_old = 0; - return modes_new; + return modes_new; } -set_config_result_t set_hide_mode_setting(const char *mode) +set_config_result_t config_set_hide_mode_setting(const char *mode) { - set_config_result_t ret = SET_CONFIG_UNCHANGED; + set_config_result_t ret = SET_CONFIG_UNCHANGED; - char *hidden_modes = make_modes_string(MODE_HIDE_KEY, mode, 1); + char *hidden_modes = config_make_modes_string(MODE_HIDE_KEY, mode, 1); - if( hidden_modes ) { - ret = set_config_setting(MODE_SETTING_ENTRY, MODE_HIDE_KEY, hidden_modes); - } + if( hidden_modes ) { + ret = config_set_config_setting(MODE_SETTING_ENTRY, MODE_HIDE_KEY, hidden_modes); + } - if(ret == SET_CONFIG_UPDATED) { - send_hidden_modes_signal(); - send_supported_modes_signal(); - send_available_modes_signal(); - } + if(ret == SET_CONFIG_UPDATED) { + usbmoded_send_hidden_modes_signal(); + usbmoded_send_supported_modes_signal(); + usbmoded_send_available_modes_signal(); + } - g_free(hidden_modes); + g_free(hidden_modes); - return(ret); + return(ret); } -set_config_result_t set_unhide_mode_setting(const char *mode) +set_config_result_t config_set_unhide_mode_setting(const char *mode) { - set_config_result_t ret = SET_CONFIG_UNCHANGED; + set_config_result_t ret = SET_CONFIG_UNCHANGED; - char *hidden_modes = make_modes_string(MODE_HIDE_KEY, mode, 0); + char *hidden_modes = config_make_modes_string(MODE_HIDE_KEY, mode, 0); - if( hidden_modes ) { - ret = set_config_setting(MODE_SETTING_ENTRY, MODE_HIDE_KEY, hidden_modes); - } + if( hidden_modes ) { + ret = config_set_config_setting(MODE_SETTING_ENTRY, MODE_HIDE_KEY, hidden_modes); + } - if(ret == SET_CONFIG_UPDATED) { - send_hidden_modes_signal(); - send_supported_modes_signal(); - send_available_modes_signal(); - } + if(ret == SET_CONFIG_UPDATED) { + usbmoded_send_hidden_modes_signal(); + usbmoded_send_supported_modes_signal(); + usbmoded_send_available_modes_signal(); + } - g_free(hidden_modes); + g_free(hidden_modes); - return(ret); + return(ret); } -set_config_result_t set_mode_whitelist(const char *whitelist) +set_config_result_t config_set_mode_whitelist(const char *whitelist) { - set_config_result_t ret = set_config_setting(MODE_SETTING_ENTRY, MODE_WHITELIST_KEY, whitelist); + set_config_result_t ret = config_set_config_setting(MODE_SETTING_ENTRY, MODE_WHITELIST_KEY, whitelist); - if(ret == SET_CONFIG_UPDATED) { - char *mode_setting; - const char *current_mode; + if(ret == SET_CONFIG_UPDATED) { + char *mode_setting; + const char *current_mode; - mode_setting = get_mode_setting(); - if (strcmp(mode_setting, MODE_ASK) && valid_mode(mode_setting)) - set_mode_setting(MODE_ASK); - g_free(mode_setting); + mode_setting = config_get_mode_setting(); + if (strcmp(mode_setting, MODE_ASK) && usbmoded_valid_mode(mode_setting)) + config_set_mode_setting(MODE_ASK); + g_free(mode_setting); - current_mode = get_usb_mode(); - if (!strcmp(current_mode, MODE_UNDEFINED)) { - /* Disconnected -> do nothing */ - } - else if (strcmp(current_mode, MODE_CHARGING_FALLBACK) && strcmp(current_mode, MODE_ASK) && valid_mode(current_mode)) { - /* Invalid mode that is not MODE_ASK or MODE_CHARGING_FALLBACK - * -> switch to MODE_CHARGING_FALLBACK */ - usb_moded_mode_cleanup(get_usb_module()); - set_usb_mode(MODE_CHARGING_FALLBACK); - } + current_mode = usbmoded_get_usb_mode(); + if (!strcmp(current_mode, MODE_UNDEFINED)) { + /* Disconnected -> do nothing */ + } + else if (strcmp(current_mode, MODE_CHARGING_FALLBACK) && strcmp(current_mode, MODE_ASK) && usbmoded_valid_mode(current_mode)) { + /* Invalid mode that is not MODE_ASK or MODE_CHARGING_FALLBACK + * -> switch to MODE_CHARGING_FALLBACK */ + modesetting_cleanup(usbmoded_get_usb_module()); + usbmoded_set_usb_mode(MODE_CHARGING_FALLBACK); + } - usb_moded_send_whitelisted_modes_signal(whitelist); - send_available_modes_signal(); - } + umdbus_send_whitelisted_modes_signal(whitelist); + usbmoded_send_available_modes_signal(); + } - return ret; + return ret; } -set_config_result_t set_mode_in_whitelist(const char *mode, int allowed) +set_config_result_t config_set_mode_in_whitelist(const char *mode, int allowed) { - set_config_result_t ret = SET_CONFIG_UNCHANGED; + set_config_result_t ret = SET_CONFIG_UNCHANGED; - char *whitelist = make_modes_string(MODE_WHITELIST_KEY, mode, allowed); + char *whitelist = config_make_modes_string(MODE_WHITELIST_KEY, mode, allowed); - if (whitelist) { - ret = set_mode_whitelist(whitelist); - } + if (whitelist) { + ret = config_set_mode_whitelist(whitelist); + } - g_free(whitelist); + g_free(whitelist); - return(ret); + return(ret); } /* * @param config : the key to be set * @param setting : The value to be set */ -set_config_result_t set_network_setting(const char *config, const char *setting) -{ - GKeyFile *settingsfile; - gboolean test = FALSE; - gchar *keyfile; - - if(!strcmp(config, NETWORK_IP_KEY) || !strcmp(config, NETWORK_GATEWAY_KEY)) - if(validate_ip(setting) != 0) - return SET_CONFIG_ERROR; - - settingsfile = g_key_file_new(); - test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); - - if(!strcmp(config, NETWORK_IP_KEY) || !strcmp(config, NETWORK_INTERFACE_KEY) || !strcmp(config, NETWORK_GATEWAY_KEY)) - { - set_config_result_t ret = SET_CONFIG_ERROR; - if (test) - { - if(!config_value_changed(settingsfile, NETWORK_ENTRY, config, setting)) - { - g_key_file_free(settingsfile); - return SET_CONFIG_UNCHANGED; - } - } - else - { - log_debug("No conffile. Creating.\n"); - create_conf_file(); - } - - g_key_file_set_string(settingsfile, NETWORK_ENTRY, config, setting); - keyfile = g_key_file_to_data (settingsfile, NULL, NULL); - /* free the settingsfile before writing things out to be sure - the contents will be correctly written to file afterwards. - Just a precaution. */ - g_key_file_free(settingsfile); - if (g_file_set_contents(FS_MOUNT_CONFIG_FILE, keyfile, -1, NULL)) - ret = SET_CONFIG_UPDATED; - free(keyfile); - return ret; - } - else - { - g_key_file_free(settingsfile); - return SET_CONFIG_ERROR; - } -} - -char * get_network_setting(const char *config) -{ - char * ret = 0; - struct mode_list_elem *data; - - if(!strcmp(config, NETWORK_IP_KEY)) - { - ret = get_network_ip(); - if(!ret) - ret = strdup("192.168.2.15"); - } - else if(!strcmp(config, NETWORK_INTERFACE_KEY)) - { - - /* check main configuration before using - the information from the specific mode */ - ret = get_network_interface(); - - if(ret) - goto end; - /* no interface override specified, let's use the one - from the mode config */ - data = get_usb_mode_data(); - if(data) - { - if(data->network_interface) - { - ret = strdup(data->network_interface); - goto end; - } - } - ret = strdup("usb0"); - } - else if(!strcmp(config, NETWORK_GATEWAY_KEY)) - return(get_network_gateway()); - else if(!strcmp(config, NETWORK_NETMASK_KEY)) - { - ret = get_network_netmask(); - if(!ret) - ret = strdup("255.255.255.0"); - } - else if(!strcmp(config, NETWORK_NAT_INTERFACE_KEY)) - return(get_network_nat_interface()); - else - /* no matching keys, return error */ - return(NULL); +set_config_result_t config_set_network_setting(const char *config, const char *setting) +{ + GKeyFile *settingsfile; + gboolean test = FALSE; + gchar *keyfile; + + if(!strcmp(config, NETWORK_IP_KEY) || !strcmp(config, NETWORK_GATEWAY_KEY)) + if(config_validate_ip(setting) != 0) + return SET_CONFIG_ERROR; + + settingsfile = g_key_file_new(); + test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); + + if(!strcmp(config, NETWORK_IP_KEY) || !strcmp(config, NETWORK_INTERFACE_KEY) || !strcmp(config, NETWORK_GATEWAY_KEY)) + { + set_config_result_t ret = SET_CONFIG_ERROR; + if (test) + { + if(!config_value_changed(settingsfile, NETWORK_ENTRY, config, setting)) + { + g_key_file_free(settingsfile); + return SET_CONFIG_UNCHANGED; + } + } + else + { + log_debug("No conffile. Creating.\n"); + config_create_conf_file(); + } + + g_key_file_set_string(settingsfile, NETWORK_ENTRY, config, setting); + keyfile = g_key_file_to_data (settingsfile, NULL, NULL); + /* free the settingsfile before writing things out to be sure + the contents will be correctly written to file afterwards. + Just a precaution. */ + g_key_file_free(settingsfile); + if (g_file_set_contents(FS_MOUNT_CONFIG_FILE, keyfile, -1, NULL)) + ret = SET_CONFIG_UPDATED; + free(keyfile); + return ret; + } + else + { + g_key_file_free(settingsfile); + return SET_CONFIG_ERROR; + } +} + +char * config_get_network_setting(const char *config) +{ + char * ret = 0; + struct mode_list_elem *data; + + if(!strcmp(config, NETWORK_IP_KEY)) + { + ret = config_get_network_ip(); + if(!ret) + ret = strdup("192.168.2.15"); + } + else if(!strcmp(config, NETWORK_INTERFACE_KEY)) + { + + /* check main configuration before using + the information from the specific mode */ + ret = config_get_network_interface(); + + if(ret) + goto end; + /* no interface override specified, let's use the one + from the mode config */ + data = usbmoded_get_usb_mode_data(); + if(data) + { + if(data->network_interface) + { + ret = strdup(data->network_interface); + goto end; + } + } + ret = strdup("usb0"); + } + else if(!strcmp(config, NETWORK_GATEWAY_KEY)) + return(config_get_network_gateway()); + else if(!strcmp(config, NETWORK_NETMASK_KEY)) + { + ret = config_get_network_netmask(); + if(!ret) + ret = strdup("255.255.255.0"); + } + else if(!strcmp(config, NETWORK_NAT_INTERFACE_KEY)) + return(config_get_network_nat_interface()); + else + /* no matching keys, return error */ + return(NULL); end: - return(ret); + return(ret); } /** @@ -672,15 +730,15 @@ char * get_network_setting(const char *config) * @param grp value group to merge * @param key value key to merge */ -static void merge_key(GKeyFile *dest, GKeyFile *srce, - const char *grp, const char *key) -{ - gchar *val = g_key_file_get_value(srce, grp, key, 0); - if( val ) { - log_debug("[%s] %s = %s", grp, key, val); - g_key_file_set_value(dest, grp, key, val); - g_free(val); - } +static void config_merge_key(GKeyFile *dest, GKeyFile *srce, + const char *grp, const char *key) +{ + gchar *val = g_key_file_get_value(srce, grp, key, 0); + if( val ) { + log_debug("[%s] %s = %s", grp, key, val); + g_key_file_set_value(dest, grp, key, val); + g_free(val); + } } /** @@ -690,15 +748,15 @@ static void merge_key(GKeyFile *dest, GKeyFile *srce, * @param srce keyfile to merge from * @param grp value group to merge */ -static void merge_group(GKeyFile *dest, GKeyFile *srce, - const char *grp) -{ - gchar **key = g_key_file_get_keys(srce, grp, 0, 0); - if( key ) { - for( size_t i = 0; key[i]; ++i ) - merge_key(dest, srce, grp, key[i]); - g_strfreev(key); - } +static void config_merge_group(GKeyFile *dest, GKeyFile *srce, + const char *grp) +{ + gchar **key = g_key_file_get_keys(srce, grp, 0, 0); + if( key ) { + for( size_t i = 0; key[i]; ++i ) + config_merge_key(dest, srce, grp, key[i]); + g_strfreev(key); + } } /** @@ -707,15 +765,15 @@ static void merge_group(GKeyFile *dest, GKeyFile *srce, * @param dest keyfile to modify * @param srce keyfile to merge from */ -static void merge_file(GKeyFile *dest, GKeyFile *srce) +static void config_merge_file(GKeyFile *dest, GKeyFile *srce) { - gchar **grp = g_key_file_get_groups(srce, 0); + gchar **grp = g_key_file_get_groups(srce, 0); - if( grp ) { - for( size_t i = 0; grp[i]; ++i ) - merge_group(dest, srce, grp[i]); - g_strfreev(grp); - } + if( grp ) { + for( size_t i = 0; grp[i]; ++i ) + config_merge_group(dest, srce, grp[i]); + g_strfreev(grp); + } } /** @@ -726,10 +784,10 @@ static void merge_file(GKeyFile *dest, GKeyFile *srce) * * @return 0 (= do not stop glob) */ -static int glob_error_cb(const char *path, int err) +static int config_glob_error_cb(const char *path, int err) { - log_debug("%s: glob: %s", path, g_strerror(err)); - return 0; + log_debug("%s: glob: %s", path, g_strerror(err)); + return 0; } /** @@ -737,39 +795,39 @@ static int glob_error_cb(const char *path, int err) * * @return the in memory value-pair file. */ -static GKeyFile *read_ini_files(void) -{ - static const char pattern[] = CONFIG_FILE_DIR"/*.ini"; - - GKeyFile *ini = g_key_file_new(); - glob_t gb; - - memset(&gb, 0, sizeof gb); - - if( glob(pattern, 0, glob_error_cb, &gb) != 0 ) { - log_debug("no configuration ini-files found"); - g_key_file_free(ini); - ini = NULL; - goto exit; - } - - for( size_t i = 0; i < gb.gl_pathc; ++i ) { - const char *path = gb.gl_pathv[i]; - GError *err = 0; - GKeyFile *tmp = g_key_file_new(); - - if( !g_key_file_load_from_file(tmp, path, 0, &err) ) { - log_debug("%s: can't load: %s", path, err->message); - } else { - log_debug("processing %s ...", path); - merge_file(ini, tmp); - } - g_clear_error(&err); - g_key_file_free(tmp); - } +static GKeyFile *config_read_ini_files(void) +{ + static const char pattern[] = CONFIG_FILE_DIR"/*.ini"; + + GKeyFile *ini = g_key_file_new(); + glob_t gb; + + memset(&gb, 0, sizeof gb); + + if( glob(pattern, 0, config_glob_error_cb, &gb) != 0 ) { + log_debug("no configuration ini-files found"); + g_key_file_free(ini); + ini = NULL; + goto exit; + } + + for( size_t i = 0; i < gb.gl_pathc; ++i ) { + const char *path = gb.gl_pathv[i]; + GError *err = 0; + GKeyFile *tmp = g_key_file_new(); + + if( !g_key_file_load_from_file(tmp, path, 0, &err) ) { + log_debug("%s: can't load: %s", path, err->message); + } else { + log_debug("processing %s ...", path); + config_merge_file(ini, tmp); + } + g_clear_error(&err); + g_key_file_free(tmp); + } exit: - globfree(&gb); - return ini; + globfree(&gb); + return ini; } /** @@ -778,95 +836,95 @@ static GKeyFile *read_ini_files(void) * * @return 0 on failure */ -int conf_file_merge(void) -{ - GString *keyfile_string = NULL; - GKeyFile *settingsfile,*tempfile; - int ret = 0; - - settingsfile = read_ini_files(); - if (!settingsfile) - { - log_debug("No configuration. Creating defaults."); - create_conf_file(); - /* There was no configuration so no info to be merged */ - return ret; - } - - tempfile = g_key_file_new(); - if (g_key_file_load_from_file(tempfile, FS_MOUNT_CONFIG_FILE, - G_KEY_FILE_NONE,NULL)) { - if (!g_strcmp0(g_key_file_to_data(settingsfile, NULL, NULL), - g_key_file_to_data(tempfile, NULL, NULL))) - goto out; - } - - log_debug("Merging configuration"); - keyfile_string = g_string_new(NULL); - keyfile_string = g_string_append(keyfile_string, - g_key_file_to_data(settingsfile, - NULL, NULL)); - if (keyfile_string) { - ret = !g_file_set_contents(FS_MOUNT_CONFIG_FILE, - keyfile_string->str,-1, NULL); - g_string_free(keyfile_string, TRUE); - } +int config_merge_conf_file(void) +{ + GString *keyfile_string = NULL; + GKeyFile *settingsfile,*tempfile; + int ret = 0; + + settingsfile = config_read_ini_files(); + if (!settingsfile) + { + log_debug("No configuration. Creating defaults."); + config_create_conf_file(); + /* There was no configuration so no info to be merged */ + return ret; + } + + tempfile = g_key_file_new(); + if (g_key_file_load_from_file(tempfile, FS_MOUNT_CONFIG_FILE, + G_KEY_FILE_NONE,NULL)) { + if (!g_strcmp0(g_key_file_to_data(settingsfile, NULL, NULL), + g_key_file_to_data(tempfile, NULL, NULL))) + goto out; + } + + log_debug("Merging configuration"); + keyfile_string = g_string_new(NULL); + keyfile_string = g_string_append(keyfile_string, + g_key_file_to_data(settingsfile, + NULL, NULL)); + if (keyfile_string) { + ret = !g_file_set_contents(FS_MOUNT_CONFIG_FILE, + keyfile_string->str,-1, NULL); + g_string_free(keyfile_string, TRUE); + } out: - g_key_file_free(tempfile); - g_key_file_free(settingsfile); - return ret; + g_key_file_free(tempfile); + g_key_file_free(settingsfile); + return ret; } -char * get_android_manufacturer(void) +char * config_get_android_manufacturer(void) { #ifdef USE_MER_SSU - /* If SSU can provide manufacturer name, use it. Otherwise fall - * back to using the name specified in configuration files. */ - char *ssu_name = ssu_get_manufacturer_name(); - if( ssu_name ) - { - return ssu_name; - } + /* If SSU can provide manufacturer name, use it. Otherwise fall + * back to using the name specified in configuration files. */ + char *ssu_name = ssu_get_manufacturer_name(); + if( ssu_name ) + { + return ssu_name; + } #endif - return get_conf_string(ANDROID_ENTRY, ANDROID_MANUFACTURER_KEY); + return config_get_conf_string(ANDROID_ENTRY, ANDROID_MANUFACTURER_KEY); } -char * get_android_vendor_id(void) +char * config_get_android_vendor_id(void) { - return(get_conf_string(ANDROID_ENTRY, ANDROID_VENDOR_ID_KEY)); + return(config_get_conf_string(ANDROID_ENTRY, ANDROID_VENDOR_ID_KEY)); } -char * get_android_product(void) +char * config_get_android_product(void) { #ifdef USE_MER_SSU - /* If SSU can provide device model name, use it. Otherwise fall - * back to using the name specified in configuration files. */ - char *ssu_name = ssu_get_product_name(); - if( ssu_name ) - { - return ssu_name; - } + /* If SSU can provide device model name, use it. Otherwise fall + * back to using the name specified in configuration files. */ + char *ssu_name = ssu_get_product_name(); + if( ssu_name ) + { + return ssu_name; + } #endif - return get_conf_string(ANDROID_ENTRY, ANDROID_PRODUCT_KEY); + return config_get_conf_string(ANDROID_ENTRY, ANDROID_PRODUCT_KEY); } -char * get_android_product_id(void) +char * config_get_android_product_id(void) { - return(get_conf_string(ANDROID_ENTRY, ANDROID_PRODUCT_ID_KEY)); + return(config_get_conf_string(ANDROID_ENTRY, ANDROID_PRODUCT_ID_KEY)); } -char * get_hidden_modes(void) +char * config_get_hidden_modes(void) { - return(get_conf_string(MODE_SETTING_ENTRY, MODE_HIDE_KEY)); + return(config_get_conf_string(MODE_SETTING_ENTRY, MODE_HIDE_KEY)); } -char * get_mode_whitelist(void) +char * config_get_mode_whitelist(void) { - return(get_conf_string(MODE_SETTING_ENTRY, MODE_WHITELIST_KEY)); + return(config_get_conf_string(MODE_SETTING_ENTRY, MODE_WHITELIST_KEY)); } -int is_roaming_not_allowed(void) +int config_is_roaming_not_allowed(void) { - return(get_conf_int(NETWORK_ENTRY, NO_ROAMING_KEY)); + return(config_get_conf_int(NETWORK_ENTRY, NO_ROAMING_KEY)); } diff --git a/src/usb_moded-config.h b/src/usb_moded-config.h index c6ed11d..73e95cf 100644 --- a/src/usb_moded-config.h +++ b/src/usb_moded-config.h @@ -1,89 +1,81 @@ /* - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2012-2015 Jolla. All rights reserved. - - author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - - -#define CONFIG_FILE_DIR "/etc/usb-moded" -#define FS_MOUNT_CONFIG_FILE CONFIG_FILE_DIR"/usb-moded.ini" - -#define MODE_SETTING_ENTRY "usbmode" -#define MODE_SETTING_KEY "mode" -#define FS_MOUNT_DEFAULT "/dev/mmcblk0p1" -#define FS_MOUNT_ENTRY "mountpoints" -#define FS_MOUNT_KEY "mount" -#define FS_SYNC_ENTRY "sync" -#define FS_SYNC_KEY "nofua" -#define ALT_MOUNT_ENTRY "altmount" -#define ALT_MOUNT_KEY "mount" -#define UDEV_PATH_ENTRY "udev" -#define UDEV_PATH_KEY "path" -#define UDEV_SUBSYSTEM_KEY "subsystem" -#define CDROM_ENTRY "cdrom" -#define CDROM_PATH_KEY "path" -#define CDROM_TIMEOUT_KEY "timeout" -#define TRIGGER_ENTRY "trigger" -#define TRIGGER_PATH_KEY "path" -#define TRIGGER_UDEV_SUBSYSTEM "udev_subsystem" -#define TRIGGER_MODE_KEY "mode" -#define TRIGGER_PROPERTY_KEY "property" -#define TRIGGER_PROPERTY_VALUE_KEY "value" -#define NETWORK_ENTRY "network" -#define NETWORK_IP_KEY "ip" -#define NETWORK_INTERFACE_KEY "interface" -#define NETWORK_GATEWAY_KEY "gateway" -#define NETWORK_NAT_INTERFACE_KEY "nat_interface" -#define NETWORK_NETMASK_KEY "netmask" -#define NO_ROAMING_KEY "noroaming" -#define ANDROID_ENTRY "android" -#define ANDROID_MANUFACTURER_KEY "iManufacturer" -#define ANDROID_VENDOR_ID_KEY "idVendor" -#define ANDROID_PRODUCT_KEY "iProduct" -#define ANDROID_PRODUCT_ID_KEY "idProduct" -#define MODE_HIDE_KEY "hide" -#define MODE_WHITELIST_KEY "whitelist" - -char * find_mounts(void); -int find_sync(void); -char * find_alt_mount(void); - -char * find_udev_path(void); -char * find_udev_subsystem(void); - -char * check_trigger(void); -char * get_trigger_subsystem(void); -char * get_trigger_mode(void); -char * get_trigger_property(void); -char * get_trigger_value(void); - -char * get_network_setting(const char *config); - -char * get_android_manufacturer(void); -char * get_android_vendor_id(void); -char * get_android_product(void); -char * get_android_product_id(void); - -char * get_hidden_modes(void); -char * get_mode_whitelist(void); + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2012-2018 Jolla. All rights reserved. + * + * author: Philippe De Swert + * author: Philippe De Swert + * author: Philippe De Swert + * author: Philippe De Swert + * author: Thomas Perl + * author: Slava Monich + * author: Simo Piiroinen + * author: Andrew den Exter + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ -int is_roaming_not_allowed(void); +#ifndef USB_MODED_CONFIG_H_ +# define USB_MODED_CONFIG_H_ + +/* ========================================================================= * + * Constants + * ========================================================================= */ + +# define CONFIG_FILE_DIR "/etc/usb-moded" +# define FS_MOUNT_CONFIG_FILE CONFIG_FILE_DIR"/usb-moded.ini" + +# define MODE_SETTING_ENTRY "usbmode" +# define MODE_SETTING_KEY "mode" +# define FS_MOUNT_DEFAULT "/dev/mmcblk0p1" +# define FS_MOUNT_ENTRY "mountpoints" +# define FS_MOUNT_KEY "mount" +# define FS_SYNC_ENTRY "sync" +# define FS_SYNC_KEY "nofua" +# define ALT_MOUNT_ENTRY "altmount" +# define ALT_MOUNT_KEY "mount" +# define UDEV_PATH_ENTRY "udev" +# define UDEV_PATH_KEY "path" +# define UDEV_SUBSYSTEM_KEY "subsystem" +# define CDROM_ENTRY "cdrom" +# define CDROM_PATH_KEY "path" +# define CDROM_TIMEOUT_KEY "timeout" +# define TRIGGER_ENTRY "trigger" +# define TRIGGER_PATH_KEY "path" +# define TRIGGER_UDEV_SUBSYSTEM "udev_subsystem" +# define TRIGGER_MODE_KEY "mode" +# define TRIGGER_PROPERTY_KEY "property" +# define TRIGGER_PROPERTY_VALUE_KEY "value" +# define NETWORK_ENTRY "network" +# define NETWORK_IP_KEY "ip" +# define NETWORK_INTERFACE_KEY "interface" +# define NETWORK_GATEWAY_KEY "gateway" +# define NETWORK_NAT_INTERFACE_KEY "nat_interface" +# define NETWORK_NETMASK_KEY "netmask" +# define NO_ROAMING_KEY "noroaming" +# define ANDROID_ENTRY "android" +# define ANDROID_MANUFACTURER_KEY "iManufacturer" +# define ANDROID_VENDOR_ID_KEY "idVendor" +# define ANDROID_PRODUCT_KEY "iProduct" +# define ANDROID_PRODUCT_ID_KEY "idProduct" +# define MODE_HIDE_KEY "hide" +# define MODE_WHITELIST_KEY "whitelist" + +/* ========================================================================= * + * Types + * ========================================================================= */ /** Configuration change result */ @@ -93,9 +85,10 @@ typedef enum set_config_result_t { SET_CONFIG_UNCHANGED, /**< Value did not change */ } set_config_result_t; -int conf_file_merge(void); +/* ========================================================================= * + * Prototypes + * ========================================================================= */ -int config_value_changed(GKeyFile *settingsfile, const char *entry, const char *key, const char *new_value); -set_config_result_t set_config_setting(const char *entry, const char *key, const char *value); +// (in usb_moded-config-private.h) -#define SET_CONFIG_OK(ret) ((ret) >= SET_CONFIG_UPDATED) +#endif /* USB_MODED_CONFIG_H_ */ diff --git a/src/usb_moded-configfs.c b/src/usb_moded-configfs.c new file mode 100644 index 0000000..6de953a --- /dev/null +++ b/src/usb_moded-configfs.c @@ -0,0 +1,673 @@ +/** + * @file usb_moded-configfs.c + * + * Copyright (C) 2018 Jolla. All rights reserved. + * + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "usb_moded-configfs.h" + +#include + +#include +#include +#include + +#include + +#include "usb_moded.h" +#include "usb_moded-android.h" +#include "usb_moded-log.h" +#include "usb_moded-modesetting.h" +#include "usb_moded-config-private.h" +#include "usb_moded-mac.h" + +/* ========================================================================= * + * Constants + * ========================================================================= */ + +#define FUNCTION_MASS_STORAGE "mass_storage.usb0" +#define FUNCTION_RNDIS "rndis_bam.rndis" +#define FUNCTION_MTP "ffs.mtp" + +#define CONFIGFS_GADGET "/config/usb_gadget/g1" +#define CONFIGFS_CONFIG CONFIGFS_GADGET"/configs/b.1" +#define CONFIGFS_FUNCTIONS CONFIGFS_GADGET"/functions" +#define CONFIGFS_UDC CONFIGFS_GADGET"/UDC" +#define CONFIGFS_ID_VENDOR CONFIGFS_GADGET"/idVendor" +#define CONFIGFS_ID_PRODUCT CONFIGFS_GADGET"/idProduct" +#define CONFIGFS_MANUFACTURER CONFIGFS_GADGET"/strings/0x409/manufacturer" +#define CONFIGFS_PRODUCT CONFIGFS_GADGET"/strings/0x409/product" +#define CONFIGFS_SERIAL CONFIGFS_GADGET"/strings/0x409/serialnumber" + +#define CONFIGFS_RNDIS_WCEIS CONFIGFS_FUNCTIONS"/rndis_bam.rndis/wceis" +#define CONFIGFS_RNDIS_ETHADDR CONFIGFS_FUNCTIONS"/rndis_bam.rndis/ethaddr" + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- configfs -- */ + +static int configfs_file_type (const char *path); +static const char *configfs_function_path (char *buff, size_t size, const char *func); +static const char *configfs_config_path (char *buff, size_t size, const char *func); +static const char *configfs_register_function (const char *function); +#ifdef DEAD_CODE +static bool configfs_unregister_function (const char *function); +#endif +static bool configfs_enable_function (const char *function); +static bool configfs_disable_function (const char *function); +static bool configfs_disable_all_functions(void); +static char *configfs_strip (char *str); +bool configfs_in_use (void); +static bool configfs_probe (void); +static const char *configfs_udc_enable_value (void); +static bool configfs_write_file (const char *path, const char *text); +static bool configfs_read_file (const char *path, char *buff, size_t size); +#ifdef DEAD_CODE +static bool configfs_read_udc (char *buff, size_t size); +#endif +static bool configfs_write_udc (const char *text); +bool configfs_set_udc (bool enable); +bool configfs_init_values (void); +bool configfs_set_charging_mode (void); +bool configfs_set_productid (const char *id); +bool configfs_set_vendorid (const char *id); + +/* ========================================================================= * + * Data + * ========================================================================= */ + +static int configfs_probed = -1; + +/* ========================================================================= * + * Functions + * ========================================================================= */ + +static int configfs_file_type(const char *path) +{ + int type = -1; + + if( !path ) + goto EXIT; + + struct stat st; + if( lstat(path, &st) == -1 ) + goto EXIT; + + type = st.st_mode & S_IFMT; + +EXIT: + return type; +} + +static const char * +configfs_function_path(char *buff, size_t size, const char *func) +{ + snprintf(buff, size, "%s/%s", CONFIGFS_FUNCTIONS, func); + return buff; +} + +static const char * +configfs_config_path(char *buff, size_t size, const char *func) +{ + snprintf(buff, size, "%s/%s", CONFIGFS_CONFIG, func); + return buff; +} + +static const char * +configfs_register_function(const char *function) +{ + const char *res = 0; + + static char fpath[256]; + configfs_function_path(fpath, sizeof fpath, function); + + if( mkdir(fpath, 0775) == -1 && errno != EEXIST ) { + log_err("%s: mkdir failed: %m", fpath); + goto EXIT; + } + + if( configfs_file_type(fpath) != S_IFDIR ) { + log_err("%s: is not a directory", fpath); + goto EXIT; + } + + log_debug("function %s is registered", function); + + res = fpath; + +EXIT: + return res; +} + +#ifdef DEAD_CODE +static bool +configfs_unregister_function(const char *function) +{ + bool ack = false; + + char fpath[256]; + configfs_function_path(fpath, sizeof fpath, function); + + if( rmdir(fpath) == -1 && errno != ENOENT ) { + log_err("%s: rmdir failed: %m", fpath); + goto EXIT; + } + + log_debug("function %s is unregistered", function); + ack = true; + +EXIT: + return ack; +} +#endif + +static bool +configfs_enable_function(const char *function) +{ + bool ack = false; + + const char *fpath = configfs_register_function(function); + if( !fpath ) { + log_err("function %s is not registered", function); + goto EXIT; + } + + char cpath[256]; + configfs_config_path(cpath, sizeof cpath, function); + + switch( configfs_file_type(cpath) ) { + case S_IFLNK: + if( unlink(cpath) == -1 ) { + log_err("%s: unlink failed: %m", cpath); + goto EXIT; + } + /* fall through */ + case -1: + if( symlink(fpath, cpath) == -1 ) { + log_err("%s: failed to symlink to %s: %m", cpath, fpath); + goto EXIT; + } + break; + default: + log_err("%s: is not a symlink", cpath); + goto EXIT; + } + + log_debug("function %s is enabled", function); + ack = true; + +EXIT: + return ack; +} + +static bool +configfs_disable_function(const char *function) +{ + bool ack = false; + + char cpath[256]; + configfs_config_path(cpath, sizeof cpath, function); + + if( configfs_file_type(cpath) != S_IFLNK ) { + log_err("%s: is not a symlink", cpath); + goto EXIT; + } + + if( unlink(cpath) == -1 ) { + log_err("%s: unlink failed: %m", cpath); + goto EXIT; + } + + log_debug("function %s is disabled", function); + ack = true; + +EXIT: + return ack; +} + +static bool +configfs_disable_all_functions(void) +{ + bool ack = false; + DIR *dir = 0; + + if( !(dir = opendir(CONFIGFS_CONFIG)) ) { + log_err("%s: opendir failed: %m", CONFIGFS_CONFIG); + goto EXIT; + } + + ack = true; + + struct dirent *de; + while( (de = readdir(dir)) ) { + if( de->d_type != DT_LNK ) + continue; + + if( !configfs_disable_function(de->d_name) ) + ack = false; + } + + if( ack ) + log_debug("all functions are disabled"); + +EXIT: + if( dir ) + closedir(dir); + + return ack; +} + +static char *configfs_strip(char *str) +{ + unsigned char *src = (unsigned char *)str; + unsigned char *dst = (unsigned char *)str; + + while( *src > 0 && *src <= 32 ) ++src; + + for( ;; ) + { + while( *src > 32 ) *dst++ = *src++; + while( *src > 0 && *src <= 32 ) ++src; + if( *src == 0 ) break; + *dst++ = ' '; + } + *dst = 0; + return str; +} + +bool +configfs_in_use(void) +{ + if( configfs_probed < 0 ) + log_debug("configfs_in_use() called before configfs_probe()"); + return configfs_probed > 0; +} + +static bool +configfs_probe(void) +{ + if( configfs_probed <= 0 ) { + configfs_probed = access(CONFIGFS_GADGET, F_OK) == 0; + log_warning("CONFIGFS %sdetected", configfs_probed ? "" : "not "); + } + return configfs_in_use(); +} + +static const char * +configfs_udc_enable_value(void) +{ + static bool probed = false; + static char *value = 0; + + if( !probed ) { + probed = true; + + /* Find first symlink in /sys/class/udc directory */ + struct dirent *de; + DIR *dir = opendir("/sys/class/udc"); + if( dir ) { + while( (de = readdir(dir)) ) { + if( de->d_type != DT_LNK ) + continue; + if( de->d_name[0] == '.' ) + continue; + value = strdup(de->d_name); + break; + } + closedir(dir); + } + } + + return value ?: ""; +} + +static bool +configfs_write_file(const char *path, const char *text) +{ + bool ack = false; + int fd = -1; + + if( !path || !text ) + goto EXIT; + + log_debug("WRITE %s '%s'", path, text); + + char buff[64]; + snprintf(buff, sizeof buff, "%s\n", text); + size_t size = strlen(buff); + + if( (fd = open(path, O_WRONLY)) == -1 ) { + log_err("%s: can't open for writing: %m", path); + goto EXIT; + } + + int rc = write(fd, text, size); + if( rc == -1 ) { + log_err("%s: write failure: %m", path); + goto EXIT; + } + + if( (size_t)rc != size ) { + log_err("%s: write failure: partial success", path); + goto EXIT; + } + + ack = true; + +EXIT: + if( fd != -1 ) + close(fd); + + return ack; +} + +static bool +configfs_read_file(const char *path, char *buff, size_t size) +{ + bool ack = false; + int fd = -1; + + if( !path || !buff ) + goto EXIT; + + if( size < 2 ) + goto EXIT; + + if( (fd = open(path, O_RDONLY)) == -1 ) { + log_err("%s: can't open for reading: %m", path); + goto EXIT; + } + + int rc = read(fd, buff, size - 1); + if( rc == -1 ) { + log_err("%s: read failure: %m", path); + goto EXIT; + } + + buff[rc] = 0; + configfs_strip(buff); + + ack = true; + + log_debug("READ %s '%s'", path, buff); + +EXIT: + if( fd != -1 ) + close(fd); + + return ack; +} + +#ifdef DEAD_CODE +static bool +configfs_read_udc(char *buff, size_t size) +{ + return configfs_read_file(CONFIGFS_UDC, buff, size); +} +#endif + +static bool +configfs_write_udc(const char *text) +{ + bool ack = false; + + char prev[64]; + + if( !configfs_read_file(CONFIGFS_UDC, prev, sizeof prev) ) + goto EXIT; + + if( strcmp(prev, text) ) { + if( !configfs_write_file(CONFIGFS_UDC, text) ) + goto EXIT; + } + + ack = true; + +EXIT: + return ack; + +} + +bool +configfs_set_udc(bool enable) +{ + log_debug("UDC - %s", enable ? "ENABLE" : "DISABLE"); + + const char *value = ""; + + if( enable ) + value = configfs_udc_enable_value(); + + return configfs_write_udc(value); +} + +/** initialize the basic configfs values + */ +bool +configfs_init_values(void) +{ + if( !configfs_probe() ) + goto EXIT; + + /* Disable */ + configfs_set_udc(false); + + /* Configure */ + gchar *text; + if( (text = config_get_android_vendor_id()) ) { + configfs_write_file(CONFIGFS_ID_VENDOR, text); + g_free(text); + } + + if( (text = config_get_android_product_id()) ) { + configfs_write_file(CONFIGFS_ID_PRODUCT, text); + g_free(text); + } + + if( (text = config_get_android_manufacturer()) ) { + configfs_write_file(CONFIGFS_MANUFACTURER, text); + g_free(text); + } + + if( (text = config_get_android_product()) ) { + configfs_write_file(CONFIGFS_PRODUCT, text); + g_free(text); + } + + if( (text = android_get_serial()) ) { + configfs_write_file(CONFIGFS_SERIAL, text); + g_free(text); + } + + /* Prep: charging_only */ + configfs_register_function(FUNCTION_MASS_STORAGE); + + /* Prep: mtp_mode */ + configfs_register_function(FUNCTION_MTP); + if( access("/dev/mtp/ep0", F_OK) == -1 ) { + usbmoded_system("/bin/mount -o uid=100000,gid=100000 -t functionfs mtp /dev/mtp"); + } + + /* Prep: developer_mode */ + configfs_register_function(FUNCTION_RNDIS); + if( (text = mac_read_mac()) ) { + configfs_write_file(CONFIGFS_RNDIS_ETHADDR, text); + g_free(text); + } + /* For rndis to be discovered correctly in M$ Windows (vista and later) */ + configfs_write_file(CONFIGFS_RNDIS_WCEIS, "1"); + + /* Leave disabled, will enable on cable connect detected */ +EXIT: + return configfs_in_use(); +} + +/* Set a charging mode for the configfs gadget + * + * @return true if successful, false on failure + */ +bool +configfs_set_charging_mode(void) +{ + bool ack = false; + + if( !configfs_set_function("mass_storage") ) + goto EXIT; + + /* TODO: make this configurable */ + configfs_set_productid("0AFE"); + + if( !configfs_set_udc(true) ) + goto EXIT; + + ack = true; + +EXIT: + log_debug("CONFIGFS %s() -> %d", __func__, ack); + return ack; +} + +/* Set a product id for the configfs gadget + * + * @return true if successful, false on failure + */ +bool +configfs_set_productid(const char *id) +{ + bool ack = false; + + if( id && configfs_in_use() ) { + /* Config files have things like "0A02". + * Kernel wants to see "0x0a02" ... */ + char *end = 0; + unsigned num = strtol(id, &end, 16); + char str[16]; + if( end > id && *end == 0 ) { + snprintf(str, sizeof str, "0x%04x", num); + id = str; + } + ack = configfs_write_file(CONFIGFS_ID_PRODUCT, id); + } + + log_debug("CONFIGFS %s(%s) -> %d", __func__, id, ack); + return ack; +} + +/* Set a vendor id for the configfs gadget + * + * @return true if successful, false on failure + */ +bool +configfs_set_vendorid(const char *id) +{ + bool ack = false; + + if( id && configfs_in_use() ) { + log_debug("%s(%s) was called", __func__, id); + + /* Config files have things like "0A02". + * Kernel wants to see "0x0a02" ... */ + char *end = 0; + unsigned num = strtol(id, &end, 16); + char str[16]; + + if( end > id && *end == 0 ) { + snprintf(str, sizeof str, "0x%04x", num); + id = str; + } + + ack = configfs_write_file(CONFIGFS_ID_VENDOR, id); + } + + log_debug("CONFIGFS %s(%s) -> %d", __func__, id, ack); + return ack; +} + +static const char * +configfs_map_function(const char *func) +{ + if( !strcmp(func, "mass_storage") ) + func = FUNCTION_MASS_STORAGE; + else if( !strcmp(func, "rndis") ) + func = FUNCTION_RNDIS; + else if( !strcmp(func, "mtp") ) + func = FUNCTION_MTP; + else if( !strcmp(func, "ffs") ) // existing config files ... + func = FUNCTION_MTP; + return func; +} + +/* Set a function + * + * @return true if successful, false on failure + */ +bool +configfs_set_function(const char *func) +{ + bool ack = false; + + if( !func ) + goto EXIT; + + if( !configfs_in_use() ) + goto EXIT; + + /* Normalize names used by usb-moded itself and already + * existing configuration files etc. + */ + func = configfs_map_function(func); + + /* HACK: Stop mtp daemon when enabling any other function + * after bootup is finished (assumption being it + * can't be started before init done and we do not + * want to spam bootup journal with warnings. + */ + if( strcmp(func, FUNCTION_MTP) && usbmoded_init_done_p() ) + usbmoded_system("systemctl-user stop buteo-mtp.service"); + + if( !configfs_set_udc(false) ) + goto EXIT; + + if( !configfs_disable_all_functions() ) + goto EXIT; + + if( !configfs_enable_function(func) ) + goto EXIT; + + /* HACK: Start mtp daemon when enabling mtp function. + * Then wait "a bit" since udc can't be enabled + * before mtpd has written suitable configuration + * to control endpoint. + */ + if( !strcmp(func, FUNCTION_MTP) ) { + usbmoded_system("systemctl-user start buteo-mtp.service"); + usbmoded_msleep(1500); + } + + /* Leave disabled, so that caller can adjust attributes + * etc before enabling */ + + ack = true; + +EXIT: + log_debug("CONFIGFS %s(%s) -> %d", __func__, func, ack); + return ack; +} diff --git a/src/usb_moded-configfs.h b/src/usb_moded-configfs.h new file mode 100644 index 0000000..2613c54 --- /dev/null +++ b/src/usb_moded-configfs.h @@ -0,0 +1,42 @@ +/** + * @file usb_moded-configfs.h + * + * Copyright (C) 2018 Jolla. All rights reserved. + * + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef USB_MODED_CONFIGFS_H_ +# define USB_MODED_CONFIGFS_H_ + +# include + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- configfs -- */ + +bool configfs_init_values (void); +bool configfs_in_use (void); +bool configfs_set_charging_mode(void); +bool configfs_set_productid (const char *id); +bool configfs_set_vendorid (const char *id); +bool configfs_set_function (const char *func); +bool configfs_set_udc (bool enable); + +#endif /* USB_MODED_CONFIGFS_H_ */ diff --git a/src/usb_moded-dbus-private.h b/src/usb_moded-dbus-private.h index 6c23677..a752d6e 100644 --- a/src/usb_moded-dbus-private.h +++ b/src/usb_moded-dbus-private.h @@ -1,68 +1,67 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2013-2016 Jolla Ltd. - - Author: Philippe De Swert - Author: Philippe De Swert - Author: Vesa Halttunen - Author: Martin Jones - Author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Vesa Halttunen + * Author: Martin Jones + * Author: Simo Piiroinen + * Author: Andrew den Exter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef USB_MODED_DBUS_PRIVATE_H_ +# define USB_MODED_DBUS_PRIVATE_H_ + +# include + +/* ========================================================================= * + * Constants + * ========================================================================= */ /** Logical name for org.freedesktop.DBus.GetNameOwner method */ -#define DBUS_GET_NAME_OWNER_REQ "GetNameOwner" +# define DBUS_GET_NAME_OWNER_REQ "GetNameOwner" /** Logical name for org.freedesktop.DBus.NameOwnerChanged signal */ -#define DBUS_NAME_OWNER_CHANGED_SIG "NameOwnerChanged" - -/* Connect to D-Bus System Bus */ -gboolean usb_moded_dbus_init_connection(void); - -/* Claim D-Bus Service Name */ -gboolean usb_moded_dbus_init_service(void); - -/* Get current SystemBus connection */ -DBusConnection *usb_moded_dbus_get_connection(void); - -/* cleanup usb on exit */ -void usb_moded_dbus_cleanup(void); - -/* send signal on system bus */ -int usb_moded_send_signal(const char *state_ind); - -/* send error signal system bus */ -int usb_moded_send_error_signal(const char *error); - -/* send supported modes signal system bus */ -int usb_moded_send_supported_modes_signal(const char *supported_modes); - -/* send available modes signal system bus */ -int usb_moded_send_available_modes_signal(const char *available_modes); - -/* send hidden modes signal system bus */ -int usb_moded_send_hidden_modes_signal(const char *hidden_modes); +# define DBUS_NAME_OWNER_CHANGED_SIG "NameOwnerChanged" -/* send whitelisted modes signal system bus */ -int usb_moded_send_whitelisted_modes_signal(const char *hidden_modes); +/* ========================================================================= * + * Types + * ========================================================================= */ -/* Callback function type used with usb_moded_get_name_owner_async() */ +/* Callback function type used with umdbus_get_name_owner_async() */ typedef void (*usb_moded_get_name_owner_fn)(const char *owner); -/* Asynchronous GetNameOwner query */ -gboolean usb_moded_get_name_owner_async(const char *name, - usb_moded_get_name_owner_fn cb, - DBusPendingCall **ppc); +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- umdbus -- */ + +DBusConnection *umdbus_get_connection (void); +gboolean umdbus_init_connection (void); +gboolean umdbus_init_service (void); +void umdbus_cleanup (void); +int umdbus_send_state_signal (const char *state_ind); +int umdbus_send_error_signal (const char *error); +int umdbus_send_supported_modes_signal (const char *supported_modes); +int umdbus_send_available_modes_signal (const char *available_modes); +int umdbus_send_hidden_modes_signal (const char *hidden_modes); +int umdbus_send_whitelisted_modes_signal(const char *whitelist); +gboolean umdbus_get_name_owner_async (const char *name, usb_moded_get_name_owner_fn cb, DBusPendingCall **ppc); + +#endif /* USB_MODED_DBUS_PRIVATE_H_ */ diff --git a/src/usb_moded-dbus.c b/src/usb_moded-dbus.c index 96c703c..d6d8136 100644 --- a/src/usb_moded-dbus.c +++ b/src/usb_moded-dbus.c @@ -1,27 +1,34 @@ /** - @file usb_moded-dbus.c - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2012-2016 Jolla. All rights reserved. - - @author: Philippe De Swert - @author: Philippe De Swert - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-dbus.c + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2012-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Vesa Halttunen + * @author: Slava Monich + * @author: Martin Jones + * @author: Simo Piiroinen + * @author: Andrew den Exter + * @author: Andrew den Exter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -40,39 +47,44 @@ #include "usb_moded-network.h" #include "usb_moded-log.h" +/* ========================================================================= * + * Constants + * ========================================================================= */ + #define INIT_DONE_INTERFACE "com.nokia.startup.signal" #define INIT_DONE_SIGNAL "init_done" #define INIT_DONE_MATCH "type='signal',interface='"INIT_DONE_INTERFACE"',member='"INIT_DONE_SIGNAL"'" +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- umdbus -- */ + +static void umdbus_send_config_signal (const char *section, const char *key, const char *value); +static DBusHandlerResult umdbus_msg_handler (DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data); +DBusConnection *umdbus_get_connection (void); +gboolean umdbus_init_connection (void); +gboolean umdbus_init_service (void); +static void umdbus_cleanup_service (void); +void umdbus_cleanup (void); +static int umdbus_send_signal_ex (const char *signal_type, const char *content); +int umdbus_send_state_signal (const char *state_ind); +int umdbus_send_error_signal (const char *error); +int umdbus_send_supported_modes_signal (const char *supported_modes); +int umdbus_send_available_modes_signal (const char *available_modes); +int umdbus_send_hidden_modes_signal (const char *hidden_modes); +int umdbus_send_whitelisted_modes_signal(const char *whitelist); +static void umdbus_get_name_owner_cb (DBusPendingCall *pc, void *aptr); +gboolean umdbus_get_name_owner_async (const char *name, usb_moded_get_name_owner_fn cb, DBusPendingCall **ppc); + +/* ========================================================================= * + * Data + * ========================================================================= */ + static DBusConnection *dbus_connection_sys = NULL; static gboolean have_service_name = FALSE; -/** - * Issues "sig_usb_config_ind" signal. -*/ -static void usb_moded_send_config_signal(const char *section, const char *key, const char *value) -{ - log_debug("broadcast signal %s(%s, %s, %s)\n", USB_MODE_CONFIG_SIGNAL_NAME, section, key, value); - - if( !have_service_name ) - { - log_err("config notification without service: [%s] %s=%s", - section, key, value); - } - else if (dbus_connection_sys) - { - DBusMessage* msg = dbus_message_new_signal(USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_CONFIG_SIGNAL_NAME); - if (msg) { - dbus_message_append_args(msg, DBUS_TYPE_STRING, §ion, - DBUS_TYPE_STRING, &key, - DBUS_TYPE_STRING, &value, - DBUS_TYPE_INVALID); - dbus_connection_send(dbus_connection_sys, msg, NULL); - dbus_message_unref(msg); - } - } -} - /** Introspect xml format string for parents of USB_MODE_OBJECT */ static const char intospect_template[] = "\n" @@ -141,7 +153,7 @@ static const char introspect_usb_moded[] = " \n" " \n" " \n" -" \n" +" \n" " " " " " " @@ -173,407 +185,437 @@ static const char introspect_usb_moded[] = " \n" "\n"; -static DBusHandlerResult msg_handler(DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data) +/* ========================================================================= * + * Functions + * ========================================================================= */ + +/** + * Issues "sig_usb_config_ind" signal. +*/ +static void umdbus_send_config_signal(const char *section, const char *key, const char *value) { - DBusHandlerResult status = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - DBusMessage *reply = 0; - const char *interface = dbus_message_get_interface(msg); - const char *member = dbus_message_get_member(msg); - const char *object = dbus_message_get_path(msg); - int type = dbus_message_get_type(msg); - - (void)user_data; - - if(!interface || !member || !object) goto EXIT; - - log_debug("DBUS %s %s.%s from %s", - dbus_message_type_to_string(type), - interface, member, - dbus_message_get_sender(msg) ?: "N/A"); - - if( type == DBUS_MESSAGE_TYPE_SIGNAL ) - { - if( !strcmp(interface, INIT_DONE_INTERFACE) && !strcmp(member, INIT_DONE_SIGNAL) ) { - /* Update the cached state value */ - set_init_done(true); - - /* Auto-disable rescue mode when bootup is finished */ - if( rescue_mode ) { - rescue_mode = FALSE; - log_debug("init done reached - rescue mode disabled"); - } - } - goto EXIT; - } - - if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && !strcmp(interface, USB_MODE_INTERFACE) && !strcmp(object, USB_MODE_OBJECT)) - { - status = DBUS_HANDLER_RESULT_HANDLED; - - if(!strcmp(member, USB_MODE_STATE_REQUEST)) - { - const char *mode = get_usb_mode(); - - /* To the outside we want to keep CHARGING and CHARGING_FALLBACK the same */ - if(!strcmp(MODE_CHARGING_FALLBACK, mode)) - mode = MODE_CHARGING; - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); - } - else if(!strcmp(member, USB_MODE_STATE_SET)) - { - char *use = 0; - DBusError err = DBUS_ERROR_INIT; - - if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID)) - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - else - { - /* check if usb is connected, since it makes no sense to change mode if it isn't */ - if(!get_usb_connection_state()) - { - log_warning("USB not connected, not changing mode!\n"); - goto error_reply; - } - /* check if the mode exists */ - if(valid_mode(use)) - goto error_reply; - /* do not change mode if the mode requested is the one already set */ - if(strcmp(use, get_usb_mode()) != 0) - { - usb_moded_mode_cleanup(get_usb_module()); - set_usb_mode(use); - } - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID); - else -error_reply: - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - } - dbus_error_free(&err); + log_debug("broadcast signal %s(%s, %s, %s)\n", USB_MODE_CONFIG_SIGNAL_NAME, section, key, value); + + if( !have_service_name ) + { + log_err("config notification without service: [%s] %s=%s", + section, key, value); + } + else if (dbus_connection_sys) + { + DBusMessage* msg = dbus_message_new_signal(USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_CONFIG_SIGNAL_NAME); + if (msg) { + dbus_message_append_args(msg, DBUS_TYPE_STRING, §ion, + DBUS_TYPE_STRING, &key, + DBUS_TYPE_STRING, &value, + DBUS_TYPE_INVALID); + dbus_connection_send(dbus_connection_sys, msg, NULL); + dbus_message_unref(msg); } - else if(!strcmp(member, USB_MODE_CONFIG_SET)) - { - char *config = 0; - DBusError err = DBUS_ERROR_INIT; - - if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID)) - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - else - { - /* error checking is done when setting configuration */ - int ret = set_mode_setting(config); - if (ret == SET_CONFIG_UPDATED) - usb_moded_send_config_signal(MODE_SETTING_ENTRY, MODE_SETTING_KEY, config); - if (SET_CONFIG_OK(ret)) - { - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); - } - else - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); - } - dbus_error_free(&err); - } - else if(!strcmp(member, USB_MODE_HIDE)) - { - char *config = 0; - DBusError err = DBUS_ERROR_INIT; - - if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID)) - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - else - { - /* error checking is done when setting configuration */ - int ret = set_hide_mode_setting(config); - if (ret == SET_CONFIG_UPDATED) - usb_moded_send_config_signal(MODE_SETTING_ENTRY, MODE_HIDE_KEY, config); - if (SET_CONFIG_OK(ret)) - { - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); - } - else - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); - } - dbus_error_free(&err); - } - else if(!strcmp(member, USB_MODE_UNHIDE)) - { - char *config = 0; - DBusError err = DBUS_ERROR_INIT; - - if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID)) - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - else - { - /* error checking is done when setting configuration */ - int ret = set_unhide_mode_setting(config); - if (ret == SET_CONFIG_UPDATED) - usb_moded_send_config_signal(MODE_SETTING_ENTRY, MODE_HIDE_KEY, config); - if (SET_CONFIG_OK(ret)) - { - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); - } - else - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); - } - dbus_error_free(&err); - } - else if(!strcmp(member, USB_MODE_HIDDEN_GET)) + } +} + +static DBusHandlerResult umdbus_msg_handler(DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data) +{ + DBusHandlerResult status = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + DBusMessage *reply = 0; + const char *interface = dbus_message_get_interface(msg); + const char *member = dbus_message_get_member(msg); + const char *object = dbus_message_get_path(msg); + int type = dbus_message_get_type(msg); + + (void)user_data; + + if(!interface || !member || !object) goto EXIT; + + log_debug("DBUS %s %s.%s from %s", + dbus_message_type_to_string(type), + interface, member, + dbus_message_get_sender(msg) ?: "N/A"); + + if( type == DBUS_MESSAGE_TYPE_SIGNAL ) + { + if( !strcmp(interface, INIT_DONE_INTERFACE) && !strcmp(member, INIT_DONE_SIGNAL) ) { + /* Update the cached state value */ + usbmoded_set_init_done(true); + + /* Auto-disable rescue mode when bootup is finished */ + if( usbmoded_rescue_mode ) { + usbmoded_rescue_mode = FALSE; + log_debug("init done reached - rescue mode disabled"); + } + } + goto EXIT; + } + + if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && !strcmp(interface, USB_MODE_INTERFACE) && !strcmp(object, USB_MODE_OBJECT)) + { + status = DBUS_HANDLER_RESULT_HANDLED; + + if(!strcmp(member, USB_MODE_STATE_REQUEST)) + { + const char *mode = usbmoded_get_external_mode(); + + /* To the outside we want to keep CHARGING and CHARGING_FALLBACK the same */ + if(!strcmp(MODE_CHARGING_FALLBACK, mode)) + mode = MODE_CHARGING; + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); + } + else if(!strcmp(member, USB_MODE_STATE_SET)) { - char *config = get_hidden_modes(); - if(!config) - config = g_strdup(""); + char *use = 0; + DBusError err = DBUS_ERROR_INIT; + + if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID)) + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + else + { + /* check if usb is connected, since it makes no sense to change mode if it isn't */ + if(!usbmoded_get_connection_state()) + { + log_warning("USB not connected, not changing mode!\n"); + goto error_reply; + } + /* check if the mode exists */ + if(usbmoded_valid_mode(use)) + goto error_reply; + /* do not change mode if the mode requested is the one already set */ + if(strcmp(use, usbmoded_get_usb_mode()) != 0) + { + modesetting_cleanup(usbmoded_get_usb_module()); + usbmoded_set_usb_mode(use); + } if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID); + else + error_reply: + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + } + dbus_error_free(&err); + } + else if(!strcmp(member, USB_MODE_CONFIG_SET)) + { + char *config = 0; + DBusError err = DBUS_ERROR_INIT; + + if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID)) + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + else + { + /* error checking is done when setting configuration */ + int ret = config_set_mode_setting(config); + if (ret == SET_CONFIG_UPDATED) + umdbus_send_config_signal(MODE_SETTING_ENTRY, MODE_SETTING_KEY, config); + if (SET_CONFIG_OK(ret)) + { + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); + } + else + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); + } + dbus_error_free(&err); + } + else if(!strcmp(member, USB_MODE_HIDE)) + { + char *config = 0; + DBusError err = DBUS_ERROR_INIT; + + if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID)) + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + else + { + /* error checking is done when setting configuration */ + int ret = config_set_hide_mode_setting(config); + if (ret == SET_CONFIG_UPDATED) + umdbus_send_config_signal(MODE_SETTING_ENTRY, MODE_HIDE_KEY, config); + if (SET_CONFIG_OK(ret)) + { + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); + } + else + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); + } + dbus_error_free(&err); + } + else if(!strcmp(member, USB_MODE_UNHIDE)) + { + char *config = 0; + DBusError err = DBUS_ERROR_INIT; + + if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID)) + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + else + { + /* error checking is done when setting configuration */ + int ret = config_set_unhide_mode_setting(config); + if (ret == SET_CONFIG_UPDATED) + umdbus_send_config_signal(MODE_SETTING_ENTRY, MODE_HIDE_KEY, config); + if (SET_CONFIG_OK(ret)) + { + if((reply = dbus_message_new_method_return(msg))) dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); - g_free(config); + } + else + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); + } + dbus_error_free(&err); } - else if(!strcmp(member, USB_MODE_NETWORK_SET)) - { - char *config = 0, *setting = 0; - DBusError err = DBUS_ERROR_INIT; - - if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID)) - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - else - { - /* error checking is done when setting configuration */ - int ret = set_network_setting(config, setting); - if (ret == SET_CONFIG_UPDATED) - usb_moded_send_config_signal(NETWORK_ENTRY, config, setting); - if (SET_CONFIG_OK(ret)) - { - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID); - usb_network_update(); - } - else - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); - } - dbus_error_free(&err); - } - else if(!strcmp(member, USB_MODE_NETWORK_GET)) - { - char *config = 0; - char *setting = 0; - DBusError err = DBUS_ERROR_INIT; - - if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID)) - { - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - } - else - { - setting = get_network_setting(config); - if(setting) - { - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID); - free(setting); - } - else - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); - } - } - else if(!strcmp(member, USB_MODE_CONFIG_GET)) - { - char *config = get_mode_setting(); - - if(!config) - { - /* Config is corrupted or we do not have a mode - * configured, fallback to undefined. */ - config = g_strdup(MODE_UNDEFINED); - } - - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); - g_free(config); - } - else if(!strcmp(member, USB_MODE_LIST)) - { - gchar *mode_list = get_mode_list(SUPPORTED_MODES_LIST); + else if(!strcmp(member, USB_MODE_HIDDEN_GET)) + { + char *config = config_get_hidden_modes(); + if(!config) + config = g_strdup(""); + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); + g_free(config); + } + else if(!strcmp(member, USB_MODE_NETWORK_SET)) + { + char *config = 0, *setting = 0; + DBusError err = DBUS_ERROR_INIT; + + if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID)) + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + else + { + /* error checking is done when setting configuration */ + int ret = config_set_network_setting(config, setting); + if (ret == SET_CONFIG_UPDATED) + umdbus_send_config_signal(NETWORK_ENTRY, config, setting); + if (SET_CONFIG_OK(ret)) + { + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID); + network_update(); + } + else + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); + } + dbus_error_free(&err); + } + else if(!strcmp(member, USB_MODE_NETWORK_GET)) + { + char *config = 0; + char *setting = 0; + DBusError err = DBUS_ERROR_INIT; + + if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID)) + { + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + } + else + { + setting = config_get_network_setting(config); + if(setting) + { + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID); + free(setting); + } + else + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config); + } + } + else if(!strcmp(member, USB_MODE_CONFIG_GET)) + { + char *config = config_get_mode_setting(); + + if(!config) + { + /* Config is corrupted or we do not have a mode + * configured, fallback to undefined. */ + config = g_strdup(MODE_UNDEFINED); + } + + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID); + g_free(config); + } + else if(!strcmp(member, USB_MODE_LIST)) + { + gchar *mode_list = usbmoded_get_mode_list(SUPPORTED_MODES_LIST); - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, (const char *) &mode_list, DBUS_TYPE_INVALID); - g_free(mode_list); - } - else if(!strcmp(member, USB_MODE_AVAILABLE_MODES_GET)) - { - gchar *mode_list = get_mode_list(AVAILABLE_MODES_LIST); - - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, DBUS_TYPE_STRING, (const char *) &mode_list, DBUS_TYPE_INVALID); - g_free(mode_list); - } - else if(!strcmp(member, USB_MODE_RESCUE_OFF)) - { - rescue_mode = FALSE; - log_debug("Rescue mode off\n "); - reply = dbus_message_new_method_return(msg); - } - else if(!strcmp(member, USB_MODE_WHITELISTED_MODES_GET)) - { - gchar *mode_list = get_mode_whitelist(); - - if(!mode_list) - mode_list = g_strdup(""); - - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args(reply, DBUS_TYPE_STRING, &mode_list, DBUS_TYPE_INVALID); - g_free(mode_list); - } - else if(!strcmp(member, USB_MODE_WHITELISTED_MODES_SET)) - { - const char *whitelist = 0; - DBusError err = DBUS_ERROR_INIT; - - if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &whitelist, DBUS_TYPE_INVALID)) - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - else - { - int ret = set_mode_whitelist(whitelist); - if (ret == SET_CONFIG_UPDATED) - usb_moded_send_config_signal(MODE_SETTING_ENTRY, MODE_WHITELIST_KEY, whitelist); - if (SET_CONFIG_OK(ret)) - { - if ((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args(reply, DBUS_TYPE_STRING, &whitelist, DBUS_TYPE_INVALID); - } - else - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, whitelist); - } - dbus_error_free(&err); - } - else if (!strcmp(member, USB_MODE_WHITELISTED_SET)) - { - const char *mode = 0; - dbus_bool_t enabled = FALSE; - DBusError err = DBUS_ERROR_INIT; - - if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &mode, DBUS_TYPE_BOOLEAN, &enabled, DBUS_TYPE_INVALID)) - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); - else - { - int ret = set_mode_in_whitelist(mode, enabled); - if (ret == SET_CONFIG_UPDATED) - { - char *whitelist = get_mode_whitelist(); - if (!whitelist) - whitelist = g_strdup(MODE_UNDEFINED); - usb_moded_send_config_signal(MODE_SETTING_ENTRY, MODE_WHITELIST_KEY, whitelist); - g_free(whitelist); - } - if (SET_CONFIG_OK(ret)) - reply = dbus_message_new_method_return(msg); - else - reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, mode); - } - dbus_error_free(&err); - } - else - { - /*unknown methods are handled here */ - reply = dbus_message_new_error(msg, DBUS_ERROR_UNKNOWN_METHOD, member); - } - - if( !reply ) - { - reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, member); - } - } - else if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && - !strcmp(interface, "org.freedesktop.DBus.Introspectable") && - !strcmp(member, "Introspect")) - { - const gchar *xml = 0; - gchar *tmp = 0; - gchar *err = 0; - size_t len = strlen(object); - const char *pos = USB_MODE_OBJECT; - - if( !strncmp(object, pos, len) ) - { - if( pos[len] == 0 ) - { - /* Full length USB_MODE_OBJECT requested */ - xml = introspect_usb_moded; - } - else if( pos[len] == '/' ) - { - /* Leading part of USB_MODE_OBJECT requested */ - gchar *parent = 0; - gchar *child = 0; - parent = g_strndup(pos, len); - pos += len + 1; - len = strcspn(pos, "/"); - child = g_strndup(pos, len); - xml = tmp = g_strdup_printf(intospect_template, - parent, child); - g_free(child); - g_free(parent); - } - else if( !strcmp(object, "/") ) - { - /* Root object needs to be handled separately */ - const char *parent = "/"; - gchar *child = 0; - pos += 1; - len = strcspn(pos, "/"); - child = g_strndup(pos, len); - xml = tmp = g_strdup_printf(intospect_template, - parent, child); - g_free(child); - } - } - - if( xml ) - { - if((reply = dbus_message_new_method_return(msg))) - dbus_message_append_args (reply, - DBUS_TYPE_STRING, &xml, - DBUS_TYPE_INVALID); - } - else - { - err = g_strdup_printf("Object '%s' does not exist", object); - reply = dbus_message_new_error(msg, DBUS_ERROR_UNKNOWN_OBJECT, - err); - } - - g_free(err); - g_free(tmp); - - if( reply ) - { - status = DBUS_HANDLER_RESULT_HANDLED; - } - } + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, (const char *) &mode_list, DBUS_TYPE_INVALID); + g_free(mode_list); + } + else if(!strcmp(member, USB_MODE_AVAILABLE_MODES_GET)) + { + gchar *mode_list = usbmoded_get_mode_list(AVAILABLE_MODES_LIST); + + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, (const char *) &mode_list, DBUS_TYPE_INVALID); + g_free(mode_list); + } + else if(!strcmp(member, USB_MODE_RESCUE_OFF)) + { + usbmoded_rescue_mode = FALSE; + log_debug("Rescue mode off\n "); + reply = dbus_message_new_method_return(msg); + } + else if(!strcmp(member, USB_MODE_WHITELISTED_MODES_GET)) + { + gchar *mode_list = config_get_mode_whitelist(); + + if(!mode_list) + mode_list = g_strdup(""); + + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args(reply, DBUS_TYPE_STRING, &mode_list, DBUS_TYPE_INVALID); + g_free(mode_list); + } + else if(!strcmp(member, USB_MODE_WHITELISTED_MODES_SET)) + { + const char *whitelist = 0; + DBusError err = DBUS_ERROR_INIT; + + if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &whitelist, DBUS_TYPE_INVALID)) + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + else + { + int ret = config_set_mode_whitelist(whitelist); + if (ret == SET_CONFIG_UPDATED) + umdbus_send_config_signal(MODE_SETTING_ENTRY, MODE_WHITELIST_KEY, whitelist); + if (SET_CONFIG_OK(ret)) + { + if ((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args(reply, DBUS_TYPE_STRING, &whitelist, DBUS_TYPE_INVALID); + } + else + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, whitelist); + } + dbus_error_free(&err); + } + else if (!strcmp(member, USB_MODE_WHITELISTED_SET)) + { + const char *mode = 0; + dbus_bool_t enabled = FALSE; + DBusError err = DBUS_ERROR_INIT; + + if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &mode, DBUS_TYPE_BOOLEAN, &enabled, DBUS_TYPE_INVALID)) + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member); + else + { + int ret = config_set_mode_in_whitelist(mode, enabled); + if (ret == SET_CONFIG_UPDATED) + { + char *whitelist = config_get_mode_whitelist(); + if (!whitelist) + whitelist = g_strdup(MODE_UNDEFINED); + umdbus_send_config_signal(MODE_SETTING_ENTRY, MODE_WHITELIST_KEY, whitelist); + g_free(whitelist); + } + if (SET_CONFIG_OK(ret)) + reply = dbus_message_new_method_return(msg); + else + reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, mode); + } + dbus_error_free(&err); + } + else + { + /*unknown methods are handled here */ + reply = dbus_message_new_error(msg, DBUS_ERROR_UNKNOWN_METHOD, member); + } + + if( !reply ) + { + reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, member); + } + } + else if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && + !strcmp(interface, "org.freedesktop.DBus.Introspectable") && + !strcmp(member, "Introspect")) + { + const gchar *xml = 0; + gchar *tmp = 0; + gchar *err = 0; + size_t len = strlen(object); + const char *pos = USB_MODE_OBJECT; + + if( !strncmp(object, pos, len) ) + { + if( pos[len] == 0 ) + { + /* Full length USB_MODE_OBJECT requested */ + xml = introspect_usb_moded; + } + else if( pos[len] == '/' ) + { + /* Leading part of USB_MODE_OBJECT requested */ + gchar *parent = 0; + gchar *child = 0; + parent = g_strndup(pos, len); + pos += len + 1; + len = strcspn(pos, "/"); + child = g_strndup(pos, len); + xml = tmp = g_strdup_printf(intospect_template, + parent, child); + g_free(child); + g_free(parent); + } + else if( !strcmp(object, "/") ) + { + /* Root object needs to be handled separately */ + const char *parent = "/"; + gchar *child = 0; + pos += 1; + len = strcspn(pos, "/"); + child = g_strndup(pos, len); + xml = tmp = g_strdup_printf(intospect_template, + parent, child); + g_free(child); + } + } + + if( xml ) + { + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, + DBUS_TYPE_STRING, &xml, + DBUS_TYPE_INVALID); + } + else + { + err = g_strdup_printf("Object '%s' does not exist", object); + reply = dbus_message_new_error(msg, DBUS_ERROR_UNKNOWN_OBJECT, + err); + } + + g_free(err); + g_free(tmp); + + if( reply ) + { + status = DBUS_HANDLER_RESULT_HANDLED; + } + } EXIT: - if(reply) - { - if( !dbus_message_get_no_reply(msg) ) - { - if( !dbus_connection_send(connection, reply, 0) ) - log_debug("Failed sending reply. Out Of Memory!\n"); - } - dbus_message_unref(reply); - } - - return status; + if(reply) + { + if( !dbus_message_get_no_reply(msg) ) + { + if( !dbus_connection_send(connection, reply, 0) ) + log_debug("Failed sending reply. Out Of Memory!\n"); + } + dbus_message_unref(reply); + } + + return status; } -DBusConnection *usb_moded_dbus_get_connection(void) +DBusConnection *umdbus_get_connection(void) { DBusConnection *connection = 0; if( dbus_connection_sys ) - connection = dbus_connection_ref(dbus_connection_sys); + connection = dbus_connection_ref(dbus_connection_sys); else - log_err("something asked for connection ref while unconnected"); + log_err("something asked for connection ref while unconnected"); return connection; } @@ -582,37 +624,37 @@ DBusConnection *usb_moded_dbus_get_connection(void) * * @return TRUE when everything went ok */ -gboolean usb_moded_dbus_init_connection(void) +gboolean umdbus_init_connection(void) { - gboolean status = FALSE; - DBusError error = DBUS_ERROR_INIT; + gboolean status = FALSE; + DBusError error = DBUS_ERROR_INIT; - /* connect to system bus */ - if ((dbus_connection_sys = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == NULL) - { - log_debug("Failed to open connection to system message bus; %s\n", error.message); + /* connect to system bus */ + if ((dbus_connection_sys = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == NULL) + { + log_debug("Failed to open connection to system message bus; %s\n", error.message); goto EXIT; - } + } - /* Initialise message handlers */ - if (!dbus_connection_add_filter(dbus_connection_sys, msg_handler, NULL, NULL)) - goto EXIT; + /* Initialise message handlers */ + if (!dbus_connection_add_filter(dbus_connection_sys, umdbus_msg_handler, NULL, NULL)) + goto EXIT; - /* Listen to init-done signals */ - dbus_bus_add_match(dbus_connection_sys, INIT_DONE_MATCH, 0); + /* Listen to init-done signals */ + dbus_bus_add_match(dbus_connection_sys, INIT_DONE_MATCH, 0); - /* Re-check flag file after adding signal listener */ - probe_init_done(); + /* Re-check flag file after adding signal listener */ + usbmoded_probe_init_done(); - /* Connect D-Bus to the mainloop */ - dbus_connection_setup_with_g_main(dbus_connection_sys, NULL); + /* Connect D-Bus to the mainloop */ + dbus_connection_setup_with_g_main(dbus_connection_sys, NULL); - /* everything went fine */ - status = TRUE; + /* everything went fine */ + status = TRUE; EXIT: - dbus_error_free(&error); - return status; + dbus_error_free(&error); + return status; } /** @@ -620,38 +662,38 @@ gboolean usb_moded_dbus_init_connection(void) * * @return TRUE when everything went ok */ -gboolean usb_moded_dbus_init_service(void) +gboolean umdbus_init_service(void) { - gboolean status = FALSE; - DBusError error = DBUS_ERROR_INIT; - int ret; - - if( !dbus_connection_sys ) { - goto EXIT; - } - - /* Acquire D-Bus service */ - ret = dbus_bus_request_name(dbus_connection_sys, USB_MODE_SERVICE, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error); - if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) - { - log_debug("failed claiming dbus name\n"); - if( dbus_error_is_set(&error) ) - log_debug("DBUS ERROR: %s, %s \n", error.name, error.message); + gboolean status = FALSE; + DBusError error = DBUS_ERROR_INIT; + int ret; + + if( !dbus_connection_sys ) { goto EXIT; - } - log_debug("claimed name %s", USB_MODE_SERVICE); - have_service_name = TRUE; - /* everything went fine */ - status = TRUE; + } + + /* Acquire D-Bus service */ + ret = dbus_bus_request_name(dbus_connection_sys, USB_MODE_SERVICE, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error); + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) + { + log_debug("failed claiming dbus name\n"); + if( dbus_error_is_set(&error) ) + log_debug("DBUS ERROR: %s, %s \n", error.name, error.message); + goto EXIT; + } + log_debug("claimed name %s", USB_MODE_SERVICE); + have_service_name = TRUE; + /* everything went fine */ + status = TRUE; EXIT: - dbus_error_free(&error); - return status; + dbus_error_free(&error); + return status; } /** Release "com.meego.usb_moded" D-Bus Service Name */ -static void usb_moded_dbus_cleanup_service(void) +static void umdbus_cleanup_service(void) { if( !have_service_name ) goto EXIT; @@ -673,17 +715,17 @@ static void usb_moded_dbus_cleanup_service(void) * Clean up the dbus connections on exit * */ -void usb_moded_dbus_cleanup(void) +void umdbus_cleanup(void) { /* clean up system bus connection */ if (dbus_connection_sys != NULL) { - usb_moded_dbus_cleanup_service(); + umdbus_cleanup_service(); - dbus_connection_remove_filter(dbus_connection_sys, msg_handler, NULL); + dbus_connection_remove_filter(dbus_connection_sys, umdbus_msg_handler, NULL); - dbus_connection_unref(dbus_connection_sys), - dbus_connection_sys = NULL; + dbus_connection_unref(dbus_connection_sys), + dbus_connection_sys = NULL; } } @@ -694,53 +736,53 @@ void usb_moded_dbus_cleanup(void) * @param signal_type the type of signal (normal, error, ...) * @@param content string which can be mode name, error, list of modes, ... */ -static int usb_moded_dbus_signal(const char *signal_type, const char *content) +static int umdbus_send_signal_ex(const char *signal_type, const char *content) { - int result = 1; - DBusMessage* msg = 0; - - log_debug("broadcast signal %s(%s)\n", signal_type, content); - - if( !have_service_name ) - { - log_err("sending signal without service: %s(%s)", - signal_type, content); - goto EXIT; - } - if(!dbus_connection_sys) - { - log_err("Dbus system connection broken!\n"); - goto EXIT; - } - // create a signal and check for errors - msg = dbus_message_new_signal(USB_MODE_OBJECT, USB_MODE_INTERFACE, signal_type ); - if (NULL == msg) - { - log_debug("Message Null\n"); - goto EXIT; - } - - // append arguments onto signal - if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &content, DBUS_TYPE_INVALID)) - { - log_debug("Appending arguments failed. Out Of Memory!\n"); - goto EXIT; - } - - // send the message on the correct bus and flush the connection - if (!dbus_connection_send(dbus_connection_sys, msg, 0)) - { - log_debug("Failed sending message. Out Of Memory!\n"); - goto EXIT; - } - result = 0; + int result = 1; + DBusMessage* msg = 0; + + log_debug("broadcast signal %s(%s)\n", signal_type, content); + + if( !have_service_name ) + { + log_err("sending signal without service: %s(%s)", + signal_type, content); + goto EXIT; + } + if(!dbus_connection_sys) + { + log_err("Dbus system connection broken!\n"); + goto EXIT; + } + // create a signal and check for errors + msg = dbus_message_new_signal(USB_MODE_OBJECT, USB_MODE_INTERFACE, signal_type ); + if (NULL == msg) + { + log_debug("Message Null\n"); + goto EXIT; + } + + // append arguments onto signal + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &content, DBUS_TYPE_INVALID)) + { + log_debug("Appending arguments failed. Out Of Memory!\n"); + goto EXIT; + } + + // send the message on the correct bus and flush the connection + if (!dbus_connection_send(dbus_connection_sys, msg, 0)) + { + log_debug("Failed sending message. Out Of Memory!\n"); + goto EXIT; + } + result = 0; EXIT: - // free the message - if(msg != 0) - dbus_message_unref(msg); + // free the message + if(msg != 0) + dbus_message_unref(msg); - return result; + return result; } /** @@ -750,9 +792,9 @@ static int usb_moded_dbus_signal(const char *signal_type, const char *content) * @param state_ind the signal name * */ -int usb_moded_send_signal(const char *state_ind) +int umdbus_send_state_signal(const char *state_ind) { - return(usb_moded_dbus_signal(USB_MODE_SIGNAL_NAME, state_ind)); + return(umdbus_send_signal_ex(USB_MODE_SIGNAL_NAME, state_ind)); } /** @@ -762,9 +804,9 @@ int usb_moded_send_signal(const char *state_ind) * @param error the error to be signalled * */ -int usb_moded_send_error_signal(const char *error) +int umdbus_send_error_signal(const char *error) { - return(usb_moded_dbus_signal(USB_MODE_ERROR_SIGNAL_NAME, error)); + return(umdbus_send_signal_ex(USB_MODE_ERROR_SIGNAL_NAME, error)); } /** @@ -774,9 +816,9 @@ int usb_moded_send_error_signal(const char *error) * @param supported_modes list of supported modes * */ -int usb_moded_send_supported_modes_signal(const char *supported_modes) +int umdbus_send_supported_modes_signal(const char *supported_modes) { - return(usb_moded_dbus_signal(USB_MODE_SUPPORTED_MODES_SIGNAL_NAME, supported_modes)); + return(umdbus_send_signal_ex(USB_MODE_SUPPORTED_MODES_SIGNAL_NAME, supported_modes)); } /** @@ -786,9 +828,9 @@ int usb_moded_send_supported_modes_signal(const char *supported_modes) * @param available_modes list of available modes * */ -int usb_moded_send_available_modes_signal(const char *available_modes) +int umdbus_send_available_modes_signal(const char *available_modes) { - return(usb_moded_dbus_signal(USB_MODE_AVAILABLE_MODES_SIGNAL_NAME, available_modes)); + return(umdbus_send_signal_ex(USB_MODE_AVAILABLE_MODES_SIGNAL_NAME, available_modes)); } /** @@ -798,9 +840,9 @@ int usb_moded_send_available_modes_signal(const char *available_modes) * @param hidden_modes list of supported modes * */ -int usb_moded_send_hidden_modes_signal(const char *hidden_modes) +int umdbus_send_hidden_modes_signal(const char *hidden_modes) { - return(usb_moded_dbus_signal(USB_MODE_HIDDEN_MODES_SIGNAL_NAME, hidden_modes)); + return(umdbus_send_signal_ex(USB_MODE_HIDDEN_MODES_SIGNAL_NAME, hidden_modes)); } /** @@ -809,17 +851,17 @@ int usb_moded_send_hidden_modes_signal(const char *hidden_modes) * @return 0 on success, 1 on failure * @param whitelist list of allowed modes */ -int usb_moded_send_whitelisted_modes_signal(const char *whitelist) +int umdbus_send_whitelisted_modes_signal(const char *whitelist) { - return(usb_moded_dbus_signal(USB_MODE_WHITELISTED_MODES_SIGNAL_NAME, whitelist)); + return(umdbus_send_signal_ex(USB_MODE_WHITELISTED_MODES_SIGNAL_NAME, whitelist)); } -/** Async reply handler for usb_moded_get_name_owner_async() +/** Async reply handler for umdbus_get_name_owner_async() * * @param pc Pending call object pointer * @param aptr Notify function to call (as a void pointer) */ -static void usb_moded_get_name_owner_cb(DBusPendingCall *pc, void *aptr) +static void umdbus_get_name_owner_cb(DBusPendingCall *pc, void *aptr) { usb_moded_get_name_owner_fn cb = aptr; @@ -866,7 +908,7 @@ static void usb_moded_get_name_owner_cb(DBusPendingCall *pc, void *aptr) * * @return TRUE if method call was sent, FALSE otherwise */ -gboolean usb_moded_get_name_owner_async(const char *name, +gboolean umdbus_get_name_owner_async(const char *name, usb_moded_get_name_owner_fn cb, DBusPendingCall **ppc) { @@ -899,7 +941,7 @@ gboolean usb_moded_get_name_owner_async(const char *name, if( !pc ) goto EXIT; - if( !dbus_pending_call_set_notify(pc, usb_moded_get_name_owner_cb, cb, 0) ) + if( !dbus_pending_call_set_notify(pc, umdbus_get_name_owner_cb, cb, 0) ) goto EXIT; ack = TRUE; diff --git a/src/usb_moded-dbus.h b/src/usb_moded-dbus.h index 6d7c427..4a26f68 100644 --- a/src/usb_moded-dbus.h +++ b/src/usb_moded-dbus.h @@ -1,31 +1,44 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2012-2015 Jolla. All rights reserved. - - Author: Philippe De Swert + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2012-2018 Jolla. All rights reserved. + * + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Vesa Halttunen + * Author: Slava Monich + * Author: Martin Jones + * Author: Andrew den Exter + * Author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +#ifndef USB_MODED_DBUS_H_ +# define USB_MODED_DBUS_H_ - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +/* ========================================================================= * + * Constants + * ========================================================================= */ -#include /** - * @credential usb-moded::usb-moded-dbus-bind Credential needed to connect to the bus -**/ -#define USB_MODE_SERVICE "com.meego.usb_moded" -#define USB_MODE_INTERFACE "com.meego.usb_moded" -#define USB_MODE_OBJECT "/com/meego/usb_moded" + * @credential usb-moded::usb-moded-dbus-bind Credential needed to connect to the bus + **/ +# define USB_MODE_SERVICE "com.meego.usb_moded" +# define USB_MODE_INTERFACE "com.meego.usb_moded" +# define USB_MODE_OBJECT "/com/meego/usb_moded" /** * sig_usb_state_ind: Notify interested parties of state and mode changes @@ -33,46 +46,54 @@ * This signals both the transient states listed below as well as the "real" * states listed in usb_moded-modes.h. **/ -#define USB_MODE_SIGNAL_NAME "sig_usb_state_ind" -#define USB_MODE_CONFIG_SIGNAL_NAME "sig_usb_config_ind" -#define USB_MODE_ERROR_SIGNAL_NAME "sig_usb_state_error_ind" -#define USB_MODE_SUPPORTED_MODES_SIGNAL_NAME "sig_usb_supported_modes_ind" -#define USB_MODE_HIDDEN_MODES_SIGNAL_NAME "sig_usb_hidden_modes_ind" -#define USB_MODE_WHITELISTED_MODES_SIGNAL_NAME "sig_usb_whitelisted_modes_ind" -#define USB_MODE_AVAILABLE_MODES_SIGNAL_NAME "sig_usb_available_modes_ind" +# define USB_MODE_SIGNAL_NAME "sig_usb_state_ind" +# define USB_MODE_CONFIG_SIGNAL_NAME "sig_usb_config_ind" +# define USB_MODE_ERROR_SIGNAL_NAME "sig_usb_state_error_ind" +# define USB_MODE_SUPPORTED_MODES_SIGNAL_NAME "sig_usb_supported_modes_ind" +# define USB_MODE_HIDDEN_MODES_SIGNAL_NAME "sig_usb_hidden_modes_ind" +# define USB_MODE_WHITELISTED_MODES_SIGNAL_NAME "sig_usb_whitelisted_modes_ind" +# define USB_MODE_AVAILABLE_MODES_SIGNAL_NAME "sig_usb_available_modes_ind" /* supported methods */ -#define USB_MODE_STATE_REQUEST "mode_request" /* returns the current mode */ -#define USB_MODE_RESCUE_OFF "rescue_off" /* turns rescue mode off so normal mode selection is restored */ -#define USB_MODE_CONFIG_GET "get_config" /* returns the mode set in the config */ -#define USB_MODE_LIST "get_modes" /* returns a comma-separated list of supported modes for ui's */ -#define USB_MODE_HIDE "hide_mode" /* hide a mode */ -#define USB_MODE_UNHIDE "unhide_mode" /* unhide a mode */ -#define USB_MODE_HIDDEN_GET "get_hidden" /* return the hidden modes */ -#define USB_MODE_STATE_SET "set_mode" /* set a mode (only works when connected) */ -#define USB_MODE_CONFIG_SET "set_config" /* set the mode that needs to be activated in the config file */ -#define USB_MODE_NETWORK_SET "net_config" /* set the network config in the config file */ -#define USB_MODE_NETWORK_GET "get_net_config" /* get the network config from the config file */ -#define USB_MODE_WHITELISTED_MODES_GET "get_whitelisted_modes" /* get the list of whitelisted modes */ -#define USB_MODE_WHITELISTED_MODES_SET "set_whitelisted_modes" /* set the list of whitelisted modes */ -#define USB_MODE_WHITELISTED_SET "set_whitelisted" /* sets whether an specific mode is in the whitelist */ -#define USB_MODE_AVAILABLE_MODES_GET "get_available_modes" /* returns a comma separated list of modes which are currently available for selection */ +# define USB_MODE_STATE_REQUEST "mode_request" /* returns the current mode */ +# define USB_MODE_RESCUE_OFF "rescue_off" /* turns rescue mode off so normal mode selection is restored */ +# define USB_MODE_CONFIG_GET "get_config" /* returns the mode set in the config */ +# define USB_MODE_LIST "get_modes" /* returns a comma-separated list of supported modes for ui's */ +# define USB_MODE_HIDE "hide_mode" /* hide a mode */ +# define USB_MODE_UNHIDE "unhide_mode" /* unhide a mode */ +# define USB_MODE_HIDDEN_GET "get_hidden" /* return the hidden modes */ +# define USB_MODE_STATE_SET "set_mode" /* set a mode (only works when connected) */ +# define USB_MODE_CONFIG_SET "set_config" /* set the mode that needs to be activated in the config file */ +# define USB_MODE_NETWORK_SET "net_config" /* set the network config in the config file */ +# define USB_MODE_NETWORK_GET "get_net_config" /* get the network config from the config file */ +# define USB_MODE_WHITELISTED_MODES_GET "get_whitelisted_modes" /* get the list of whitelisted modes */ +# define USB_MODE_WHITELISTED_MODES_SET "set_whitelisted_modes" /* set the list of whitelisted modes */ +# define USB_MODE_WHITELISTED_SET "set_whitelisted" /* sets whether an specific mode is in the whitelist */ +# define USB_MODE_AVAILABLE_MODES_GET "get_available_modes" /* returns a comma separated list of modes which are currently available for selection */ /** * (Transient) states reported by "sig_usb_state_ind" that are not modes. * These are only reported by the signal, and never returned by e.g. "mode_request". **/ -#define USB_CONNECTED "USB connected" -#define USB_DISCONNECTED "USB disconnected" -#define USB_REALLY_DISCONNECT "USB mode change in progress" -#define DATA_IN_USE "data_in_use" -#define USB_CONNECTED_DIALOG_SHOW "mode_requested_show_dialog" -#define USB_PRE_UNMOUNT "pre-unmount" -#define RE_MOUNT_FAILED "mount_failed" -#define CHARGER_CONNECTED "charger_connected" -#define CHARGER_DISCONNECTED "charger_disconnected" -#define MODE_SETTING_FAILED "mode_setting_failed" +# define USB_CONNECTED "USB connected" +# define USB_DISCONNECTED "USB disconnected" +# define USB_REALLY_DISCONNECT "USB mode change in progress" +# define DATA_IN_USE "data_in_use" +# define USB_CONNECTED_DIALOG_SHOW "mode_requested_show_dialog" +# define USB_PRE_UNMOUNT "pre-unmount" +# define RE_MOUNT_FAILED "mount_failed" +# define CHARGER_CONNECTED "charger_connected" +# define CHARGER_DISCONNECTED "charger_disconnected" +# define MODE_SETTING_FAILED "mode_setting_failed" /* errors */ -#define UMOUNT_ERROR "Unmounting filesystem failed. Exporting impossible" +# define UMOUNT_ERROR "Unmounting filesystem failed. Exporting impossible" /* qtn_usb_filessystem_inuse is the NOKIA/Meego error string */ + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +// (in usb_moded-dbus-private.h) + +#endif /* USB_MODED_DBUS_H_ */ diff --git a/src/usb_moded-devicelock.c b/src/usb_moded-devicelock.c index 23e1986..bc90a9f 100644 --- a/src/usb_moded-devicelock.c +++ b/src/usb_moded-devicelock.c @@ -1,51 +1,50 @@ /** - - @file: usb_moded-devicelock.c - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2013-2016 Jolla Ltd. - - @author: Philippe De Swert - @author: Philippe De Swert - @author: Jonni Rainisto - @author: Vesa Halttunen - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file: usb_moded-devicelock.c + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Jonni Rainisto + * @author: Philippe De Swert + * @author: Vesa Halttunen + * @author: Jonni Rainisto + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ /* * Interacts with the devicelock to know if we can expose the system contents or not */ -/*============================================================================= */ - #include #include #include #include #include "usb_moded-devicelock.h" -#include "usb_moded-lock.h" #include "usb_moded-log.h" #include "usb_moded.h" #include "usb_moded-modes.h" #include "usb_moded-dbus-private.h" /* ========================================================================= * - * devicelock state type + * Types * ========================================================================= */ /** Devicelock states */ @@ -61,6 +60,45 @@ typedef enum DEVICE_LOCK_UNDEFINED = 2, } devicelock_state_t; +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- devicelock -- */ + +static const char *devicelock_state_repr (devicelock_state_t state); +bool devicelock_have_export_permission(void); +static void devicelock_state_changed (devicelock_state_t state); +static void devicelock_state_cancel (void); +static void devicelock_state_query_cb (DBusPendingCall *pending, void *aptr); +static void devicelock_state_query (void); +static void devicelock_state_signal (DBusMessage *msg); +static void devicelock_available_changed (const char *owner); +static void devicelock_available_cb (const char *owner); +static void devicelock_available_cancel (void); +static void devicelock_available_query (void); +static void devicelock_name_owner_signal (DBusMessage *msg); +static DBusHandlerResult devicelock_dbus_filter_cb (DBusConnection *con, DBusMessage *msg, void *aptr); +bool devicelock_start_listener (void); +void devicelock_stop_listener (void); + +/* ========================================================================= * + * module state data + * ========================================================================= */ + +/* SystemBus connection ref used for devicelock ipc */ +static DBusConnection *devicelock_con = NULL; + +/* Cached devicelock state */ +static devicelock_state_t device_lock_state = DEVICE_LOCK_UNDEFINED; + +/* Flag for: devicelock is available on system bus */ +static gboolean devicelock_is_available = FALSE; + +/* ========================================================================= * + * devicelock state type + * ========================================================================= */ + /** Return human readable representation of devicelock state enum */ static const char * @@ -79,19 +117,6 @@ devicelock_state_repr(devicelock_state_t state) return repr; } -/* ========================================================================= * - * module state data - * ========================================================================= */ - -/* SystemBus connection ref used for devicelock ipc */ -static DBusConnection *devicelock_con = NULL; - -/* Cached devicelock state */ -static devicelock_state_t device_lock_state = DEVICE_LOCK_UNDEFINED; - -/* Flag for: devicelock is available on system bus */ -static gboolean devicelock_is_available = FALSE; - /* ========================================================================= * * functionality provided to the other modules * ========================================================================= */ @@ -101,9 +126,9 @@ static gboolean devicelock_is_available = FALSE; * @return TRUE for unlocked, FALSE for locked * */ -gboolean usb_moded_get_export_permission(void) +bool devicelock_have_export_permission(void) { - gboolean unlocked = (device_lock_state == DEVICE_LOCK_UNLOCKED); + bool unlocked = (device_lock_state == DEVICE_LOCK_UNLOCKED); return unlocked; } @@ -122,7 +147,7 @@ static void devicelock_state_changed(devicelock_state_t state) devicelock_state_repr(state)); device_lock_state = state; - rethink_usb_charging_fallback(); + usbmoded_rethink_usb_charging_fallback(); EXIT: return; @@ -281,7 +306,7 @@ static void devicelock_available_cancel(void) { if( devicelock_available_pc ) { - dbus_pending_call_cancel(devicelock_available_pc); + dbus_pending_call_cancel(devicelock_available_pc); dbus_pending_call_unref(devicelock_available_pc), devicelock_available_pc = 0; } @@ -293,12 +318,12 @@ static void devicelock_available_query(void) log_debug("querying %s name owner", DEVICELOCK_SERVICE); - usb_moded_get_name_owner_async(DEVICELOCK_SERVICE, - devicelock_available_cb, - &devicelock_available_pc); + umdbus_get_name_owner_async(DEVICELOCK_SERVICE, + devicelock_available_cb, + &devicelock_available_pc); } -static void name_owner_signal(DBusMessage *msg) +static void devicelock_name_owner_signal(DBusMessage *msg) { DBusError err = DBUS_ERROR_INIT; const char *name = 0; @@ -341,7 +366,7 @@ devicelock_dbus_filter_cb(DBusConnection *con, DBusMessage *msg, void *aptr) DBUS_INTERFACE_DBUS, DBUS_NAME_OWNER_CHANGED_SIG) ) { - name_owner_signal(msg); + devicelock_name_owner_signal(msg); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -351,15 +376,15 @@ devicelock_dbus_filter_cb(DBusConnection *con, DBusMessage *msg, void *aptr) * start/stop devicelock state tracking * ========================================================================= */ -gboolean -start_devicelock_listener(void) +bool +devicelock_start_listener(void) { - gboolean ack = FALSE; + bool ack = false; log_debug("starting devicelock listener"); /* Get connection ref */ - if( (devicelock_con = usb_moded_dbus_get_connection()) == 0 ) + if( (devicelock_con = umdbus_get_connection()) == 0 ) { log_err("Could not connect to dbus for devicelock\n"); goto cleanup; @@ -380,7 +405,7 @@ start_devicelock_listener(void) /* Initiate async devicelock name owner query */ devicelock_available_query(); - ack = TRUE; + ack = true; cleanup: @@ -388,7 +413,7 @@ start_devicelock_listener(void) } void -stop_devicelock_listener(void) +devicelock_stop_listener(void) { log_debug("stopping devicelock listener"); diff --git a/src/usb_moded-devicelock.h b/src/usb_moded-devicelock.h index c1802a4..a5daa70 100644 --- a/src/usb_moded-devicelock.h +++ b/src/usb_moded-devicelock.h @@ -1,45 +1,66 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2013-2016 Jolla Ltd. - - Author: Philippe De Swert - Author: Vesa Halttunen - Author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * Author: Philippe De Swert + * Author: Vesa Halttunen + * Author: Simo Piiroinen + * Author: Andrew den Exter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + /* * Interacts with the devicelock to know if we can expose the system contents or not */ -/*============================================================================= */ +#ifndef USB_MODED_DEVICELOCK_H_ +# define USB_MODED_DEVICELOCK_H_ + +# include + +/* ========================================================================= * + * Constants + * ========================================================================= */ -#define DEVICELOCK_SERVICE "org.nemomobile.devicelock" -#define DEVICELOCK_OBJECT "/devicelock" -#define DEVICELOCK_INTERFACE "org.nemomobile.lipstick.devicelock" -#define DEVICELOCK_GET_STATE_REQ "state" -#define DEVICELOCK_STATE_CHANGED_SIG "stateChanged" +# define DEVICELOCK_SERVICE "org.nemomobile.devicelock" +# define DEVICELOCK_OBJECT "/devicelock" +# define DEVICELOCK_INTERFACE "org.nemomobile.lipstick.devicelock" +# define DEVICELOCK_GET_STATE_REQ "state" +# define DEVICELOCK_STATE_CHANGED_SIG "stateChanged" -#define DEVICELOCK_STATE_CHANGED_MATCH\ +# define DEVICELOCK_STATE_CHANGED_MATCH\ "type='signal'"\ ",interface='"DEVICELOCK_INTERFACE"'"\ ",path='"DEVICELOCK_OBJECT"'"\ ",member='"DEVICELOCK_STATE_CHANGED_SIG"'" -#define DEVICELOCK_NAME_OWNER_CHANGED_MATCH\ +# define DEVICELOCK_NAME_OWNER_CHANGED_MATCH\ "type='signal'"\ ",interface='"DBUS_INTERFACE_DBUS"'"\ ",member='"DBUS_NAME_OWNER_CHANGED_SIG"'"\ ",arg0='"DEVICELOCK_SERVICE"'" + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- devicelock -- */ + +bool devicelock_have_export_permission(void); +bool devicelock_start_listener (void); +void devicelock_stop_listener (void); + +#endif /* USB_MODED_DEVICELOCK_H_ */ diff --git a/src/usb_moded-dsme.c b/src/usb_moded-dsme.c index c1c0938..2cef64a 100644 --- a/src/usb_moded-dsme.c +++ b/src/usb_moded-dsme.c @@ -1,28 +1,26 @@ /** - @file usb_moded-dsme.c - - Copyright (C) 2013-2016 Jolla. All rights reserved. - - @author: Philippe De Swert - @author: Jonni Rainisto - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#define _GNU_SOURCE + * @file usb_moded-dsme.c + * + * Copyright (C) 2013-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Jonni Rainisto + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include @@ -121,7 +119,7 @@ static void dsme_dbus_quit (void); gboolean dsme_listener_start (void); void dsme_listener_stop (void); -gboolean is_in_user_state (void); +gboolean dsme_in_user_state (void); /* ========================================================================= * * DSME_STATE_TRACKING @@ -202,7 +200,7 @@ dsme_state_update(dsme_state_t state) dsme_user_state = user_state; log_debug("in user state: %s", dsme_user_state ? "true" : "false"); - rethink_usb_charging_fallback(); + usbmoded_rethink_usb_charging_fallback(); } /* Handle entry to / exit from SHUTDOWN / REBOOT state */ @@ -213,9 +211,9 @@ dsme_state_update(dsme_state_t state) dsme_shutdown_state = shutdown_state; log_debug("in shutdown: %s", dsme_shutdown_state ? "true" : "false"); - /* Re-evaluate dsmesock connection */ - if( !dsme_shutdown_state ) - dsme_socket_connect(); + /* Re-evaluate dsmesock connection */ + if( !dsme_shutdown_state ) + dsme_socket_connect(); } } @@ -226,7 +224,7 @@ dsme_state_update(dsme_state_t state) static bool dsme_state_is_shutdown(void) { - return dsme_shutdown_state; + return dsme_shutdown_state; } /** Checks if the device is is USER-state. @@ -367,7 +365,7 @@ dsme_socket_recv_cb(GIOChannel *source, dsme_socket_processwd_pong(); /* Do heartbeat actions here */ - usb_moded_mode_verify_values(); + modesetting_verify_values(); } else if( (msg2 = DSMEMSG_CAST(DSM_MSGTYPE_STATE_CHANGE_IND, msg)) ) { dsme_state_update(msg2->state); @@ -383,7 +381,7 @@ dsme_socket_recv_cb(GIOChannel *source, if( !keep_going ) { if( !dsme_state_is_shutdown() ) { log_warning("DSME i/o notifier disabled;" - " assuming dsme was stopped"); + " assuming dsme was stopped"); } /* mark notifier as removed */ @@ -421,7 +419,7 @@ dsme_socket_connect(void) /* No new connections uness dsme dbus service is available */ if( !dsme_dbus_name_owner_available() ) - goto EXIT; + goto EXIT; /* Already connected ? */ if( dsme_socket_iowatch ) @@ -669,9 +667,9 @@ dsme_dbus_name_owner_query(void) { dsme_dbus_name_owner_cancel(); - usb_moded_get_name_owner_async(DSME_DBUS_SERVICE, - dsme_dbus_name_owner_query_cb, - &dsme_dbus_name_owner_query_pc); + umdbus_get_name_owner_async(DSME_DBUS_SERVICE, + dsme_dbus_name_owner_query_cb, + &dsme_dbus_name_owner_query_pc); } static void @@ -741,7 +739,7 @@ dsme_dbus_init(void) bool ack = false; /* Get connection ref */ - if( (dsme_dbus_con = usb_moded_dbus_get_connection()) == 0 ) + if( (dsme_dbus_con = umdbus_get_connection()) == 0 ) { log_err("Could not connect to dbus for dsme\n"); goto cleanup; @@ -821,7 +819,7 @@ dsme_listener_stop(void) * @return 1 if it is in USER-state, 0 for not */ gboolean -is_in_user_state(void) +dsme_in_user_state(void) { return dsme_state_is_user(); } diff --git a/src/usb_moded-dsme.h b/src/usb_moded-dsme.h index d521eeb..9f21c8b 100644 --- a/src/usb_moded-dsme.h +++ b/src/usb_moded-dsme.h @@ -1,30 +1,41 @@ /** - @file usb_moded-dsme.h - - Copyright (C) 2013-2016 Jolla. All rights reserved. - - @author: Philippe De Swert - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-dsme.h + * + * Copyright (C) 2013-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #ifndef MEEGOLOCK # warning usb_moded-dsme.h included without enabling MEEGOLOCK #endif -gboolean is_in_user_state(void); +#ifndef USB_MODED_DSME_H_ +# define USB_MODED_DSME_H_ + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- dsme -- */ + gboolean dsme_listener_start(void); -void dsme_listener_stop(void); +void dsme_listener_stop (void); +gboolean dsme_in_user_state (void); + +#endif /* USB_MODED_DSME_H_ */ diff --git a/src/usb_moded-dyn-config.c b/src/usb_moded-dyn-config.c index dfff972..2da0df9 100644 --- a/src/usb_moded-dyn-config.c +++ b/src/usb_moded-dyn-config.c @@ -1,26 +1,30 @@ /** - @file usb_moded-dyn-mode.c - - Copyright (C) 2011 Nokia Corporation. All rights reserved. - Copyright (C) 2013 Jolla. All rights reserved. - - @author: Philippe De Swert - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-dyn-mode.c + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Thomas Perl + * @author: Slava Monich + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -33,162 +37,174 @@ #include "usb_moded-dyn-config.h" #include "usb_moded-log.h" -static struct mode_list_elem *read_mode_file(const gchar *filename); +/* ========================================================================= * + * Prototypes + * ========================================================================= */ -void list_item_free(mode_list_elem *list_item) +/* -- dynconfig -- */ + +void dynconfig_free_list_item(mode_list_elem *list_item); +void dynconfig_free_mode_list(GList *modelist); +static gint dynconfig_compare_modes (gconstpointer a, gconstpointer b); +GList *dynconfig_read_mode_list(int diag); +static struct mode_list_elem *dynconfig_read_mode_file(const gchar *filename); + +/* ========================================================================= * + * Functions + * ========================================================================= */ + +void dynconfig_free_list_item(mode_list_elem *list_item) { - free(list_item->mode_name); - free(list_item->mode_module); - free(list_item->network_interface); - free(list_item->sysfs_path); - free(list_item->sysfs_value); - free(list_item->sysfs_reset_value); - free(list_item->softconnect); - free(list_item->softconnect_disconnect); - free(list_item->softconnect_path); - free(list_item->android_extra_sysfs_path); - free(list_item->android_extra_sysfs_value); - free(list_item->android_extra_sysfs_path2); - free(list_item->android_extra_sysfs_value2); - free(list_item->android_extra_sysfs_path3); - free(list_item->android_extra_sysfs_value3); - free(list_item->android_extra_sysfs_path4); - free(list_item->android_extra_sysfs_value4); - free(list_item->idProduct); - free(list_item->idVendorOverride); + free(list_item->mode_name); + free(list_item->mode_module); + free(list_item->network_interface); + free(list_item->sysfs_path); + free(list_item->sysfs_value); + free(list_item->sysfs_reset_value); + free(list_item->softconnect); + free(list_item->softconnect_disconnect); + free(list_item->softconnect_path); + free(list_item->android_extra_sysfs_path); + free(list_item->android_extra_sysfs_value); + free(list_item->android_extra_sysfs_path2); + free(list_item->android_extra_sysfs_value2); + free(list_item->android_extra_sysfs_path3); + free(list_item->android_extra_sysfs_value3); + free(list_item->android_extra_sysfs_path4); + free(list_item->android_extra_sysfs_value4); + free(list_item->idProduct); + free(list_item->idVendorOverride); #ifdef CONNMAN - free(list_item->connman_tethering); + free(list_item->connman_tethering); #endif - free(list_item); + free(list_item); } -void free_mode_list(GList *modelist) +void dynconfig_free_mode_list(GList *modelist) { - if(modelist) - { - g_list_foreach(modelist, (GFunc) list_item_free, NULL); - g_list_free(modelist); - modelist = 0; - } + if(modelist) + { + g_list_foreach(modelist, (GFunc) dynconfig_free_list_item, NULL); + g_list_free(modelist); + modelist = 0; + } } -static gint compare_modes(gconstpointer a, gconstpointer b) +static gint dynconfig_compare_modes(gconstpointer a, gconstpointer b) { - struct mode_list_elem *aa = (struct mode_list_elem *)a; - struct mode_list_elem *bb = (struct mode_list_elem *)b; + struct mode_list_elem *aa = (struct mode_list_elem *)a; + struct mode_list_elem *bb = (struct mode_list_elem *)b; - return g_strcmp0(aa->mode_name, bb->mode_name); + return g_strcmp0(aa->mode_name, bb->mode_name); } -GList *read_mode_list(int diag) +GList *dynconfig_read_mode_list(int diag) { - GDir *confdir; - GList *modelist = NULL; - const gchar *dirname; - struct mode_list_elem *list_item; - gchar *full_filename = NULL; - - if(diag) - confdir = g_dir_open(DIAG_DIR_PATH, 0, NULL); - else - confdir = g_dir_open(MODE_DIR_PATH, 0, NULL); - if(confdir) - { - while((dirname = g_dir_read_name(confdir)) != NULL) - { - log_debug("Read file %s\n", dirname); - if(diag) - full_filename = g_strconcat(DIAG_DIR_PATH, "/", dirname, NULL); - else - full_filename = g_strconcat(MODE_DIR_PATH, "/", dirname, NULL); - list_item = read_mode_file(full_filename); - /* free full_filename immediately as we do not use it anymore */ - free(full_filename); - if(list_item) - modelist = g_list_append(modelist, list_item); - } - g_dir_close(confdir); - } - else - log_debug("Mode confdir open failed or file is incomplete/invalid.\n"); - - modelist = g_list_sort (modelist, compare_modes); - return(modelist); + GDir *confdir; + GList *modelist = NULL; + const gchar *dirname; + struct mode_list_elem *list_item; + gchar *full_filename = NULL; + + if(diag) + confdir = g_dir_open(DIAG_DIR_PATH, 0, NULL); + else + confdir = g_dir_open(MODE_DIR_PATH, 0, NULL); + if(confdir) + { + while((dirname = g_dir_read_name(confdir)) != NULL) + { + log_debug("Read file %s\n", dirname); + if(diag) + full_filename = g_strconcat(DIAG_DIR_PATH, "/", dirname, NULL); + else + full_filename = g_strconcat(MODE_DIR_PATH, "/", dirname, NULL); + list_item = dynconfig_read_mode_file(full_filename); + /* free full_filename immediately as we do not use it anymore */ + free(full_filename); + if(list_item) + modelist = g_list_append(modelist, list_item); + } + g_dir_close(confdir); + } + else + log_debug("Mode confdir open failed or file is incomplete/invalid.\n"); + + modelist = g_list_sort (modelist, dynconfig_compare_modes); + return(modelist); } -static struct mode_list_elem *read_mode_file(const gchar *filename) +static struct mode_list_elem *dynconfig_read_mode_file(const gchar *filename) { - GKeyFile *settingsfile; - gboolean test = FALSE; - struct mode_list_elem *list_item = NULL; - - settingsfile = g_key_file_new(); - test = g_key_file_load_from_file(settingsfile, filename, G_KEY_FILE_NONE, NULL); - if(!test) - { - return(NULL); - } - list_item = malloc(sizeof(struct mode_list_elem)); - list_item->mode_name = g_key_file_get_string(settingsfile, MODE_ENTRY, MODE_NAME_KEY, NULL); - log_debug("Dynamic mode name = %s\n", list_item->mode_name); - list_item->mode_module = g_key_file_get_string(settingsfile, MODE_ENTRY, MODE_MODULE_KEY, NULL); - log_debug("Dynamic mode module = %s\n", list_item->mode_module); - list_item->appsync = g_key_file_get_integer(settingsfile, MODE_ENTRY, MODE_NEEDS_APPSYNC_KEY, NULL); - list_item->mass_storage = g_key_file_get_integer(settingsfile, MODE_ENTRY, MODE_MASS_STORAGE, NULL); - list_item->network = g_key_file_get_integer(settingsfile, MODE_ENTRY, MODE_NETWORK_KEY, NULL); - list_item->network_interface = g_key_file_get_string(settingsfile, MODE_ENTRY, MODE_NETWORK_INTERFACE_KEY, NULL); - list_item->sysfs_path = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SYSFS_PATH, NULL); - //log_debug("Dynamic mode sysfs path = %s\n", list_item->sysfs_path); - list_item->sysfs_value = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SYSFS_VALUE, NULL); - //log_debug("Dynamic mode sysfs value = %s\n", list_item->sysfs_value); - list_item->sysfs_reset_value = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SYSFS_RESET_VALUE, NULL); - list_item->softconnect = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SOFTCONNECT, NULL); - list_item->softconnect_disconnect = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SOFTCONNECT_DISCONNECT, NULL); - list_item->softconnect_path = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SOFTCONNECT_PATH, NULL); - list_item->android_extra_sysfs_path = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_PATH, NULL); - list_item->android_extra_sysfs_path2 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_PATH2, NULL); - list_item->android_extra_sysfs_path3 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_PATH3, NULL); - list_item->android_extra_sysfs_path4 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_PATH4, NULL); - //log_debug("Android extra mode sysfs path2 = %s\n", list_item->android_extra_sysfs_path2); - list_item->android_extra_sysfs_value = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_VALUE, NULL); - list_item->android_extra_sysfs_value2 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_VALUE2, NULL); - list_item->android_extra_sysfs_value3 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_VALUE3, NULL); - list_item->android_extra_sysfs_value4 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_VALUE4, NULL); - //log_debug("Android extra value2 = %s\n", list_item->android_extra_sysfs_value2); - list_item->idProduct = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_IDPRODUCT, NULL); - list_item->idVendorOverride = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_IDVENDOROVERRIDE, NULL); - list_item->nat = g_key_file_get_integer(settingsfile, MODE_OPTIONS_ENTRY, MODE_HAS_NAT, NULL); - list_item->dhcp_server = g_key_file_get_integer(settingsfile, MODE_OPTIONS_ENTRY, MODE_HAS_DHCP_SERVER, NULL); + GKeyFile *settingsfile; + gboolean test = FALSE; + struct mode_list_elem *list_item = NULL; + + settingsfile = g_key_file_new(); + test = g_key_file_load_from_file(settingsfile, filename, G_KEY_FILE_NONE, NULL); + if(!test) + { + return(NULL); + } + list_item = malloc(sizeof(struct mode_list_elem)); + list_item->mode_name = g_key_file_get_string(settingsfile, MODE_ENTRY, MODE_NAME_KEY, NULL); + log_debug("Dynamic mode name = %s\n", list_item->mode_name); + list_item->mode_module = g_key_file_get_string(settingsfile, MODE_ENTRY, MODE_MODULE_KEY, NULL); + log_debug("Dynamic mode module = %s\n", list_item->mode_module); + list_item->appsync = g_key_file_get_integer(settingsfile, MODE_ENTRY, MODE_NEEDS_APPSYNC_KEY, NULL); + list_item->mass_storage = g_key_file_get_integer(settingsfile, MODE_ENTRY, MODE_MASS_STORAGE, NULL); + list_item->network = g_key_file_get_integer(settingsfile, MODE_ENTRY, MODE_NETWORK_KEY, NULL); + list_item->network_interface = g_key_file_get_string(settingsfile, MODE_ENTRY, MODE_NETWORK_INTERFACE_KEY, NULL); + list_item->sysfs_path = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SYSFS_PATH, NULL); + //log_debug("Dynamic mode sysfs path = %s\n", list_item->sysfs_path); + list_item->sysfs_value = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SYSFS_VALUE, NULL); + //log_debug("Dynamic mode sysfs value = %s\n", list_item->sysfs_value); + list_item->sysfs_reset_value = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SYSFS_RESET_VALUE, NULL); + list_item->softconnect = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SOFTCONNECT, NULL); + list_item->softconnect_disconnect = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SOFTCONNECT_DISCONNECT, NULL); + list_item->softconnect_path = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_SOFTCONNECT_PATH, NULL); + list_item->android_extra_sysfs_path = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_PATH, NULL); + list_item->android_extra_sysfs_path2 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_PATH2, NULL); + list_item->android_extra_sysfs_path3 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_PATH3, NULL); + list_item->android_extra_sysfs_path4 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_PATH4, NULL); + //log_debug("Android extra mode sysfs path2 = %s\n", list_item->android_extra_sysfs_path2); + list_item->android_extra_sysfs_value = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_VALUE, NULL); + list_item->android_extra_sysfs_value2 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_VALUE2, NULL); + list_item->android_extra_sysfs_value3 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_VALUE3, NULL); + list_item->android_extra_sysfs_value4 = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_ANDROID_EXTRA_SYSFS_VALUE4, NULL); + //log_debug("Android extra value2 = %s\n", list_item->android_extra_sysfs_value2); + list_item->idProduct = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_IDPRODUCT, NULL); + list_item->idVendorOverride = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_IDVENDOROVERRIDE, NULL); + list_item->nat = g_key_file_get_integer(settingsfile, MODE_OPTIONS_ENTRY, MODE_HAS_NAT, NULL); + list_item->dhcp_server = g_key_file_get_integer(settingsfile, MODE_OPTIONS_ENTRY, MODE_HAS_DHCP_SERVER, NULL); #ifdef CONNMAN - list_item->connman_tethering = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_CONNMAN_TETHERING, NULL); + list_item->connman_tethering = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_CONNMAN_TETHERING, NULL); #endif - g_key_file_free(settingsfile); - if(list_item->mode_name == NULL || list_item->mode_module == NULL) - { - /* free list_item as it will not be used */ - list_item_free(list_item); - return NULL; - } - if(list_item->network && list_item->network_interface == NULL) - { - /* free list_item as it will not be used */ - list_item_free(list_item); - return NULL; - } - if(list_item->sysfs_path && list_item->sysfs_value == NULL) - { - /* free list_item as it will not be used */ - list_item_free(list_item); - return NULL; - } - if(list_item->softconnect && list_item->softconnect_path == NULL) - { - /* free list_item as it will not be used */ - list_item_free(list_item); - return NULL; - } - else - return(list_item); + g_key_file_free(settingsfile); + if(list_item->mode_name == NULL || list_item->mode_module == NULL) + { + /* free list_item as it will not be used */ + dynconfig_free_list_item(list_item); + return NULL; + } + if(list_item->network && list_item->network_interface == NULL) + { + /* free list_item as it will not be used */ + dynconfig_free_list_item(list_item); + return NULL; + } + if(list_item->sysfs_path && list_item->sysfs_value == NULL) + { + /* free list_item as it will not be used */ + dynconfig_free_list_item(list_item); + return NULL; + } + if(list_item->softconnect && list_item->softconnect_path == NULL) + { + /* free list_item as it will not be used */ + dynconfig_free_list_item(list_item); + return NULL; + } + return(list_item); } - diff --git a/src/usb_moded-dyn-config.h b/src/usb_moded-dyn-config.h index aa9ab96..3a1d9b6 100644 --- a/src/usb_moded-dyn-config.h +++ b/src/usb_moded-dyn-config.h @@ -1,103 +1,122 @@ /* - - Copyright (C) 2011 Nokia Corporation. All rights reserved. - - author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * author: Philippe De Swert + * author: Philippe De Swert + * author: Philippe De Swert + * author: Philippe De Swert + * author: Thomas Perl + * author: Slava Monich + * author: Simo Piiroinen + * author: Andrew den Exter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ -#ifndef USB_MODED_DYN_CONFIG_H_ -#define USB_MODED_DYN_CONFIG_H_ +#ifndef USB_MODED_DYN_CONFIG_H_ +# define USB_MODED_DYN_CONFIG_H_ +/* ========================================================================= * + * Constants + * ========================================================================= */ -#define MODE_DIR_PATH "/etc/usb-moded/dyn-modes" -#define DIAG_DIR_PATH "/etc/usb-moded/diag" +# define MODE_DIR_PATH "/etc/usb-moded/dyn-modes" +# define DIAG_DIR_PATH "/etc/usb-moded/diag" -#define MODE_ENTRY "mode" -#define MODE_NAME_KEY "name" -#define MODE_MODULE_KEY "module" -#define MODE_NEEDS_APPSYNC_KEY "appsync" -#define MODE_NETWORK_KEY "network" -#define MODE_MASS_STORAGE "mass_storage" -#define MODE_NETWORK_INTERFACE_KEY "network_interface" -#define MODE_OPTIONS_ENTRY "options" -#define MODE_SYSFS_PATH "sysfs_path" -#define MODE_SYSFS_VALUE "sysfs_value" -#define MODE_SYSFS_RESET_VALUE "sysfs_reset_value" -#define MODE_SOFTCONNECT "softconnect" -#define MODE_SOFTCONNECT_DISCONNECT "softconnect_disconnect" -#define MODE_SOFTCONNECT_PATH "softconnect_path" -/* Instead of hard-coding values that never change or have only one option, -android engineers prefered to have sysfs entries... go figure... */ -#define MODE_ANDROID_EXTRA_SYSFS_PATH "android_extra_sysfs_path" -#define MODE_ANDROID_EXTRA_SYSFS_VALUE "android_extra_sysfs_value" +# define MODE_ENTRY "mode" +# define MODE_NAME_KEY "name" +# define MODE_MODULE_KEY "module" +# define MODE_NEEDS_APPSYNC_KEY "appsync" +# define MODE_NETWORK_KEY "network" +# define MODE_MASS_STORAGE "mass_storage" +# define MODE_NETWORK_INTERFACE_KEY "network_interface" +# define MODE_OPTIONS_ENTRY "options" +# define MODE_SYSFS_PATH "sysfs_path" +# define MODE_SYSFS_VALUE "sysfs_value" +# define MODE_SYSFS_RESET_VALUE "sysfs_reset_value" +# define MODE_SOFTCONNECT "softconnect" +# define MODE_SOFTCONNECT_DISCONNECT "softconnect_disconnect" +# define MODE_SOFTCONNECT_PATH "softconnect_path" +/* Instead of hard-coding values that never change or have only one option, + android engineers prefered to have sysfs entries... go figure... */ +# define MODE_ANDROID_EXTRA_SYSFS_PATH "android_extra_sysfs_path" +# define MODE_ANDROID_EXTRA_SYSFS_VALUE "android_extra_sysfs_value" /* in combined android gadgets we sometime need more than one extra sysfs path or value */ -#define MODE_ANDROID_EXTRA_SYSFS_PATH2 "android_extra_sysfs_path2" -#define MODE_ANDROID_EXTRA_SYSFS_VALUE2 "android_extra_sysfs_value2" -#define MODE_ANDROID_EXTRA_SYSFS_PATH3 "android_extra_sysfs_path3" -#define MODE_ANDROID_EXTRA_SYSFS_VALUE3 "android_extra_sysfs_value3" -#define MODE_ANDROID_EXTRA_SYSFS_PATH4 "android_extra_sysfs_path4" -#define MODE_ANDROID_EXTRA_SYSFS_VALUE4 "android_extra_sysfs_value4" +# define MODE_ANDROID_EXTRA_SYSFS_PATH2 "android_extra_sysfs_path2" +# define MODE_ANDROID_EXTRA_SYSFS_VALUE2 "android_extra_sysfs_value2" +# define MODE_ANDROID_EXTRA_SYSFS_PATH3 "android_extra_sysfs_path3" +# define MODE_ANDROID_EXTRA_SYSFS_VALUE3 "android_extra_sysfs_value3" +# define MODE_ANDROID_EXTRA_SYSFS_PATH4 "android_extra_sysfs_path4" +# define MODE_ANDROID_EXTRA_SYSFS_VALUE4 "android_extra_sysfs_value4" /* For windows different modes/usb profiles need their own idProduct */ -#define MODE_IDPRODUCT "idProduct" -#define MODE_IDVENDOROVERRIDE "idVendorOverride" -#define MODE_HAS_NAT "nat" -#define MODE_HAS_DHCP_SERVER "dhcp_server" -#ifdef CONNMAN -#define MODE_CONNMAN_TETHERING "connman_tethering" -#endif +# define MODE_IDPRODUCT "idProduct" +# define MODE_IDVENDOROVERRIDE "idVendorOverride" +# define MODE_HAS_NAT "nat" +# define MODE_HAS_DHCP_SERVER "dhcp_server" +# ifdef CONNMAN +# define MODE_CONNMAN_TETHERING "connman_tethering" +# endif + +/* ========================================================================= * + * Types + * ========================================================================= */ /** * Struct keeping all the data needed for the definition of a dynamic mode */ typedef struct mode_list_elem { - char *mode_name; /**< Mode name */ - char *mode_module; /**< Needed module for given mode */ - int appsync; /**< Requires appsync or not */ - int network; /**< Bring up network or not */ - int mass_storage; /**< Use mass-storage functions */ - char *network_interface; /**< Which network interface to bring up if network needs to be enabled */ - char *sysfs_path; /**< Path to set sysfs options */ - char *sysfs_value; /**< Option name/value to write to sysfs */ - char *sysfs_reset_value; /**< Value to reset the the sysfs to default */ - char *softconnect; /**< Value to be written to softconnect interface */ - char *softconnect_disconnect; /**< Value to set on the softconnect interface to disable after disconnect */ - char *softconnect_path; /**< Path for the softconnect */ - char *android_extra_sysfs_path; /**< Path for static value that never changes that needs to be set by sysfs :( */ - char *android_extra_sysfs_value; /**< Static value that never changes that needs to be set by sysfs :( */ - char *android_extra_sysfs_path2; /**< Path for static value that never changes that needs to be set by sysfs :( */ - char *android_extra_sysfs_value2; /**< Static value that never changes that needs to be set by sysfs :( */ - char *android_extra_sysfs_path3; /**< Path for static value that never changes that needs to be set by sysfs :( */ - char *android_extra_sysfs_value3; /**< Static value that never changes that needs to be set by sysfs :( */ - char *android_extra_sysfs_path4; /**< Path for static value that never changes that needs to be set by sysfs :( */ - char *android_extra_sysfs_value4; /**< Static value that never changes that needs to be set by sysfs :( */ - char *idProduct; /**< Product id to assign to a specific profile */ - char *idVendorOverride; /**< Temporary vendor override for special modes used by odms in testing/manufacturing */ - int nat; /**< If NAT should be set up in this mode or not */ - int dhcp_server; /**< if a DHCP server needs to be configured and started or not */ -#ifdef CONNMAN - char* connman_tethering; /**< Connman's tethering technology path */ -#endif + char *mode_name; /**< Mode name */ + char *mode_module; /**< Needed module for given mode */ + int appsync; /**< Requires appsync or not */ + int network; /**< Bring up network or not */ + int mass_storage; /**< Use mass-storage functions */ + char *network_interface; /**< Which network interface to bring up if network needs to be enabled */ + char *sysfs_path; /**< Path to set sysfs options */ + char *sysfs_value; /**< Option name/value to write to sysfs */ + char *sysfs_reset_value; /**< Value to reset the the sysfs to default */ + char *softconnect; /**< Value to be written to softconnect interface */ + char *softconnect_disconnect; /**< Value to set on the softconnect interface to disable after disconnect */ + char *softconnect_path; /**< Path for the softconnect */ + char *android_extra_sysfs_path; /**< Path for static value that never changes that needs to be set by sysfs :( */ + char *android_extra_sysfs_value; /**< Static value that never changes that needs to be set by sysfs :( */ + char *android_extra_sysfs_path2; /**< Path for static value that never changes that needs to be set by sysfs :( */ + char *android_extra_sysfs_value2; /**< Static value that never changes that needs to be set by sysfs :( */ + char *android_extra_sysfs_path3; /**< Path for static value that never changes that needs to be set by sysfs :( */ + char *android_extra_sysfs_value3; /**< Static value that never changes that needs to be set by sysfs :( */ + char *android_extra_sysfs_path4; /**< Path for static value that never changes that needs to be set by sysfs :( */ + char *android_extra_sysfs_value4; /**< Static value that never changes that needs to be set by sysfs :( */ + char *idProduct; /**< Product id to assign to a specific profile */ + char *idVendorOverride; /**< Temporary vendor override for special modes used by odms in testing/manufacturing */ + int nat; /**< If NAT should be set up in this mode or not */ + int dhcp_server; /**< if a DHCP server needs to be configured and started or not */ +# ifdef CONNMAN + char* connman_tethering; /**< Connman's tethering technology path */ +# endif } mode_list_elem; -/* diag is used to select a secondary configuration location for diagnostic purposes */ -GList *read_mode_list(int diag); -void list_item_free(mode_list_elem *list_item); -void free_mode_list(GList *modelist); +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- dynconfig -- */ +void dynconfig_free_list_item(mode_list_elem *list_item); +void dynconfig_free_mode_list(GList *modelist); +GList *dynconfig_read_mode_list(int diag); #endif /* USB_MODED_DYN_CONFIG_H_ */ diff --git a/src/usb_moded-hw-ab.h b/src/usb_moded-hw-ab.h deleted file mode 100644 index 7ac245b..0000000 --- a/src/usb_moded-hw-ab.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (C) 2010 Nokia Corporation. All rights reserved. - - Author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ -/* - hardware abstraction glue layer. - Each HW abstraction system needs to implement the functions declared here - - Communication is done through the signal functions defined in usb_moded.h -*/ - -/*============================================================================= */ - -#include - -/* set up the hw abstraction layer - * - * @return Returns true when succesful - * - * */ -gboolean hwal_init(void); - -/* cleans up the hw abstraction layer on exit */ -void hwal_cleanup(void); diff --git a/src/usb_moded-lock.h b/src/usb_moded-lock.h deleted file mode 100644 index 8e5803d..0000000 --- a/src/usb_moded-lock.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (C) 2012 Nokia Corporation. All rights reserved. - Copyright (C) 2013-2016 Jolla Ltd. - - Author: Philippe De Swert - Author: Philippe De Swert - Author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ -/* - * Function definitions to interact with a security lock to know if - we can expose the system contents or not - */ - -/*============================================================================= */ -gboolean usb_moded_get_export_permission(void); -gboolean start_devicelock_listener(void); -void stop_devicelock_listener(void); diff --git a/src/usb_moded-log.c b/src/usb_moded-log.c index 5a19c8c..dd72bee 100644 --- a/src/usb_moded-log.c +++ b/src/usb_moded-log.c @@ -1,28 +1,29 @@ /** - @file usb_moded-log.c - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2016 Jolla Ltd. - - @author: Philippe De Swert - @author: Simo Piiroinen - @author: Simo Piiroinen - - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-log.c + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2016-2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Simo Piiroinen + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -34,35 +35,64 @@ #include "usb_moded-log.h" +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- log -- */ + +static char *log_strip (char *str); +static void log_gettime (struct timeval *tv); +void log_emit_va (const char *file, const char *func, int line, int lev, const char *fmt, va_list va); +void log_emit_real (const char *file, const char *func, int line, int lev, const char *fmt, ...); +void log_debugf (const char *fmt, ...); +int log_get_level (void); +void log_set_level (int lev); +bool log_p (int lev); +int log_get_type (void); +void log_set_type (int type); +const char *log_get_name (void); +void log_set_name (const char *name); +void log_set_lineinfo(bool lineinfo); +bool log_get_lineinfo(void); +void log_init (void); + +/* ========================================================================= * + * Data + * ========================================================================= */ + static const char *log_name = ""; static int log_level = LOG_WARNING; static int log_type = LOG_TO_STDERR; static bool log_lineinfo = false; +static struct timeval log_begtime = { 0, 0 }; -static char *strip(char *str) -{ - unsigned char *src = (unsigned char *)str; - unsigned char *dst = (unsigned char *)str; +/* ========================================================================= * + * Functions + * ========================================================================= */ - while( *src > 0 && *src <= 32 ) ++src; +static char *log_strip(char *str) +{ + unsigned char *src = (unsigned char *)str; + unsigned char *dst = (unsigned char *)str; - for( ;; ) - { - while( *src > 32 ) *dst++ = *src++; while( *src > 0 && *src <= 32 ) ++src; - if( *src == 0 ) break; - *dst++ = ' '; - } - *dst = 0; - return str; -} -static struct timeval log_begtime = { 0, 0 }; + for( ;; ) + { + while( *src > 32 ) *dst++ = *src++; + while( *src > 0 && *src <= 32 ) ++src; + if( *src == 0 ) break; + *dst++ = ' '; + } + *dst = 0; + return str; +} static void log_gettime(struct timeval *tv) { - gettimeofday(tv, 0); - timersub(tv, &log_begtime, tv); + gettimeofday(tv, 0); + timersub(tv, &log_begtime, tv); } /** Print the logged messages to the selected output @@ -76,68 +106,68 @@ static void log_gettime(struct timeval *tv) */ void log_emit_va(const char *file, const char *func, int line, int lev, const char *fmt, va_list va) { - int saved = errno; - if( log_p(lev) ) + int saved = errno; + if( log_p(lev) ) + { + switch( log_type ) { - switch( log_type ) - { - case LOG_TO_SYSLOG: + case LOG_TO_SYSLOG: - vsyslog(lev, fmt, va); - break; + vsyslog(lev, fmt, va); + break; - case LOG_TO_STDERR: + case LOG_TO_STDERR: - if( log_get_lineinfo() ) { - /* Use gcc error like prefix for logging so - * that logs can be analyzed with jump to - * line parsing available in editors. */ - fprintf(stderr, "%s:%d: %s(): ", file, line, func); - } - else { - fprintf(stderr, "%s: ", log_get_name()); - } + if( log_get_lineinfo() ) { + /* Use gcc error like prefix for logging so + * that logs can be analyzed with jump to + * line parsing available in editors. */ + fprintf(stderr, "%s:%d: %s(): ", file, line, func); + } + else { + fprintf(stderr, "%s: ", log_get_name()); + } #if LOG_ENABLE_TIMESTAMPS - { - struct timeval tv; - log_gettime(&tv); - fprintf(stderr, "%3ld.%03ld ", - (long)tv.tv_sec, - (long)tv.tv_usec/1000); - } + { + struct timeval tv; + log_gettime(&tv); + fprintf(stderr, "%3ld.%03ld ", + (long)tv.tv_sec, + (long)tv.tv_usec/1000); + } #endif #if LOG_ENABLE_LEVELTAGS - { - static const char *tag = "U:"; - switch( lev ) - { - case LOG_CRIT: tag = "C:"; break; - case LOG_ERR: tag = "E:"; break; - case LOG_WARNING: tag = "W:"; break; - case LOG_NOTICE: tag = "N:"; break; - case LOG_INFO: tag = "I:"; break; - case LOG_DEBUG: tag = "D:"; break; - } - fprintf(stderr, "%s ", tag); - } -#endif - { - // squeeze whitespace like syslog does - char buf[1024]; - errno = saved; - vsnprintf(buf, sizeof buf - 1, fmt, va); - fprintf(stderr, "%s\n", strip(buf)); - } - break; - - default: - // no logging - break; + { + static const char *tag = "U:"; + switch( lev ) + { + case LOG_CRIT: tag = "C:"; break; + case LOG_ERR: tag = "E:"; break; + case LOG_WARNING: tag = "W:"; break; + case LOG_NOTICE: tag = "N:"; break; + case LOG_INFO: tag = "I:"; break; + case LOG_DEBUG: tag = "D:"; break; } + fprintf(stderr, "%s ", tag); + } +#endif + { + // squeeze whitespace like syslog does + char buf[1024]; + errno = saved; + vsnprintf(buf, sizeof buf - 1, fmt, va); + fprintf(stderr, "%s\n", log_strip(buf)); + } + break; + + default: + // no logging + break; } - errno = saved; + } + errno = saved; } /** Print the logged messages to the selected output @@ -151,22 +181,22 @@ void log_emit_va(const char *file, const char *func, int line, int lev, const ch */ void log_emit_real(const char *file, const char *func, int line, int lev, const char *fmt, ...) { - va_list va; - va_start(va, fmt); - log_emit_va(file, func, line, lev, fmt, va); - va_end(va); + va_list va; + va_start(va, fmt); + log_emit_va(file, func, line, lev, fmt, va); + va_end(va); } void log_debugf(const char *fmt, ...) { - /* This goes always to stderr */ - if( log_type == LOG_TO_STDERR && log_p(LOG_DEBUG) ) - { - va_list va; - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - } + /* This goes always to stderr */ + if( log_type == LOG_TO_STDERR && log_p(LOG_DEBUG) ) + { + va_list va; + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); + } } /** Get the currently set logging level @@ -175,7 +205,7 @@ void log_debugf(const char *fmt, ...) */ int log_get_level(void) { - return log_level; + return log_level; } /** Set the logging level @@ -184,7 +214,7 @@ int log_get_level(void) */ void log_set_level(int lev) { - log_level = lev; + log_level = lev; } /** Test if logging should be done at given level @@ -195,7 +225,7 @@ void log_set_level(int lev) */ bool log_p(int lev) { - return lev <= log_level; + return lev <= log_level; } /** Get the currently set logging type @@ -204,7 +234,7 @@ bool log_p(int lev) */ int log_get_type(void) { - return log_type; + return log_type; } /* Set the logging type @@ -213,7 +243,7 @@ int log_get_type(void) */ void log_set_type(int type) { - log_type = type; + log_type = type; } /** Get the currently set logging name @@ -222,7 +252,7 @@ void log_set_type(int type) */ const char *log_get_name(void) { - return log_name; + return log_name; } /** Set the logging name @@ -231,7 +261,7 @@ const char *log_get_name(void) */ void log_set_name(const char *name) { - log_name = name; + log_name = name; } /** Enable/disable the logging line info @@ -240,7 +270,7 @@ void log_set_name(const char *name) */ void log_set_lineinfo(bool lineinfo) { - log_lineinfo = lineinfo; + log_lineinfo = lineinfo; } /** Test if line info should be included in logging @@ -249,13 +279,13 @@ void log_set_lineinfo(bool lineinfo) */ bool log_get_lineinfo(void) { - return log_lineinfo; + return log_lineinfo; } /** Initialize logging */ void log_init(void) { - /* Get reference time used for verbose logging */ - if( !timerisset(&log_begtime) ) - gettimeofday(&log_begtime, 0); + /* Get reference time used for verbose logging */ + if( !timerisset(&log_begtime) ) + gettimeofday(&log_begtime, 0); } diff --git a/src/usb_moded-log.h b/src/usb_moded-log.h index 51f80fd..85d0d42 100644 --- a/src/usb_moded-log.h +++ b/src/usb_moded-log.h @@ -1,80 +1,96 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2016 Jolla Ltd. + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2016-2018 Jolla Ltd. + * + * Author: Philippe De Swert + * Author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - Author: Philippe De Swert - Author: Simo Piiroinen +#ifndef USB_MODED_LOG_H_ +# define USB_MODED_LOG_H_ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +# include +# include +# include +# include +# include +# include +# include - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +/* Logging functionality */ -#include -#include -#include -#include -#include -#include -#include +/* ========================================================================= * + * Constants + * ========================================================================= */ -/* Logging functionality */ +# define LOG_ENABLE_DEBUG 01 +# define LOG_ENABLE_TIMESTAMPS 01 +# define LOG_ENABLE_LEVELTAGS 01 + +enum +{ + LOG_TO_STDERR, // log to stderr + LOG_TO_SYSLOG, // log to syslog +}; + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- log -- */ -#define LOG_ENABLE_DEBUG 01 -#define LOG_ENABLE_TIMESTAMPS 01 -#define LOG_ENABLE_LEVELTAGS 01 - -enum -{ - LOG_TO_STDERR, // log to stderr - LOG_TO_SYSLOG, // log to syslog -}; - - -void log_set_level(int lev); -int log_get_level(void); -int log_get_type(void); -void log_set_type(int type); -const char *log_get_name(void); -void log_set_name(const char *name); -void log_set_lineinfo(bool lineinfo); -bool log_get_lineinfo(void); +void log_emit_va (const char *file, const char *func, int line, int lev, const char *fmt, va_list va); +void log_emit_real (const char *file, const char *func, int line, int lev, const char *fmt, ...); +void log_debugf (const char *fmt, ...); +int log_get_level (void); +void log_set_level (int lev); +bool log_p (int lev); +int log_get_type (void); +void log_set_type (int type); +const char *log_get_name (void); +void log_set_name (const char *name); +void log_set_lineinfo(bool lineinfo); +bool log_get_lineinfo(void); +void log_init (void); -void log_init(void); -void log_emit_va(const char *file, const char *func, int line, int lev, const char *fmt, va_list va); -void log_emit_real(const char *file, const char *func, int line, int lev, const char *fmt, ...) __attribute__((format(printf,5,6))); -void log_debugf(const char *fmt, ...) __attribute__((format(printf,1,2))); -bool log_p(int lev); +/* ========================================================================= * + * Macros + * ========================================================================= */ -#define log_emit(LEV, FMT, ARGS...) do {\ - if( log_p(LEV) ) {\ - log_emit_real(__FILE__,__FUNCTION__,__LINE__, LEV, FMT, ##ARGS);\ - }\ +# define log_emit(LEV, FMT, ARGS...) do {\ + if( log_p(LEV) ) {\ + log_emit_real(__FILE__,__FUNCTION__,__LINE__, LEV, FMT, ##ARGS);\ + }\ } while(0) -#define log_crit( FMT, ARGS...) log_emit(LOG_CRIT, FMT, ##ARGS) -#define log_err( FMT, ARGS...) log_emit(LOG_ERR, FMT, ##ARGS) -#define log_warning( FMT, ARGS...) log_emit(LOG_WARNING, FMT, ##ARGS) +# define log_crit( FMT, ARGS...) log_emit(LOG_CRIT, FMT, ##ARGS) +# define log_err( FMT, ARGS...) log_emit(LOG_ERR, FMT, ##ARGS) +# define log_warning( FMT, ARGS...) log_emit(LOG_WARNING, FMT, ##ARGS) -#if LOG_ENABLE_DEBUG -# define log_notice( FMT, ARGS...) log_emit(LOG_NOTICE, FMT, ##ARGS) -# define log_info( FMT, ARGS...) log_emit(LOG_INFO, FMT, ##ARGS) -# define log_debug( FMT, ARGS...) log_emit(LOG_DEBUG, FMT, ##ARGS) -#else -# define log_notice( FMT, ARGS...) do{}while(0) -# define log_info( FMT, ARGS...) do{}while(0) -# define log_debug( FMT, ARGS...) do{}while(0) +# if LOG_ENABLE_DEBUG +# define log_notice( FMT, ARGS...) log_emit(LOG_NOTICE, FMT, ##ARGS) +# define log_info( FMT, ARGS...) log_emit(LOG_INFO, FMT, ##ARGS) +# define log_debug( FMT, ARGS...) log_emit(LOG_DEBUG, FMT, ##ARGS) +# else +# define log_notice( FMT, ARGS...) do{}while(0) +# define log_info( FMT, ARGS...) do{}while(0) +# define log_debug( FMT, ARGS...) do{}while(0) -# define log_debugf( FMT, ARGS...) do{}while(0) -#endif +# define log_debugf( FMT, ARGS...) do{}while(0) +# endif +#endif /* USB_MODED_LOG_H_ */ diff --git a/src/usb_moded-mac.c b/src/usb_moded-mac.c index 1fae642..e7f788d 100644 --- a/src/usb_moded-mac.c +++ b/src/usb_moded-mac.c @@ -1,100 +1,115 @@ /** - @file usb_moded-mac.c + * @file usb_moded-mac.c + * + * Copyright (C) 2013-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - Copyright (C) 2013 Jolla. All rights reserved. +#include +#include "usb_moded-mac.h" +#include "usb_moded-log.h" - @author: Philippe De Swert +/* ========================================================================= * + * Prototypes + * ========================================================================= */ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +/* -- mac -- */ - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +static void mac_random_ether_addr (unsigned char *addr); +void mac_generate_random_mac(void); +char *mac_read_mac (void); -#include -#include "usb_moded-mac.h" -#include "usb_moded-log.h" +/* ========================================================================= * + * Functions + * ========================================================================= */ -static void random_ether_addr(unsigned char *addr) +static void mac_random_ether_addr(unsigned char *addr) { - FILE *random; - size_t count = 0; + FILE *random; + size_t count = 0; - random = fopen("/dev/urandom", "r"); - count = fread(addr, 1, 6, random); - fclose(random); + random = fopen("/dev/urandom", "r"); + count = fread(addr, 1, 6, random); + fclose(random); - if(count > 0 ) - { - addr [0] &= 0xfe; /* clear multicast bit */ - addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ - } - else - log_warning("MAC generation failed!\n"); + if(count > 0 ) + { + addr [0] &= 0xfe; /* clear multicast bit */ + addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ + } + else + log_warning("MAC generation failed!\n"); } -void generate_random_mac (void) +void mac_generate_random_mac (void) { - unsigned char addr[6]; - int i; - FILE *g_ether; + unsigned char addr[6]; + int i; + FILE *g_ether; + + log_debug("Getting random usb ethernet mac\n"); + mac_random_ether_addr(addr); + + g_ether = fopen("/etc/modprobe.d/g_ether.conf", "w"); + if(!g_ether) + { + log_warning("Failed to write mac address to /etc/modprobe.d/g_ether.conf\n"); + return; + } + fprintf(g_ether, "options g_ether host_addr="); - log_debug("Getting random usb ethernet mac\n"); - random_ether_addr(addr); - - g_ether = fopen("/etc/modprobe.d/g_ether.conf", "w"); - if(!g_ether) - { - log_warning("Failed to write mac address to /etc/modprobe.d/g_ether.conf\n"); - return; - } - fprintf(g_ether, "options g_ether host_addr="); - - for(i=0; i<5; i++) - { - fprintf(g_ether, "%02x:",addr[i]); - } - fprintf(g_ether, "%02x\n",addr[i]); - fclose(g_ether); + for(i=0; i<5; i++) + { + fprintf(g_ether, "%02x:",addr[i]); + } + fprintf(g_ether, "%02x\n",addr[i]); + fclose(g_ether); } -char * read_mac(void) +char * mac_read_mac(void) { - FILE *g_ether; - char *mac = NULL, *ret = NULL; - size_t read = 0; - int test = 0; + FILE *g_ether; + char *mac = NULL, *ret = NULL; + size_t read = 0; + int test = 0; - g_ether = fopen("/etc/modprobe.d/g_ether.conf", "r"); - if(!g_ether) - { - log_warning("Failed to read mac address from /etc/modprobe.d/g_ether.conf\n"); - return(NULL); - } - test = fseek(g_ether, 26, SEEK_SET); - if(test == -1) - { - fclose(g_ether); - return 0; - } - mac = malloc(sizeof(char) *17); - if(mac) - read = fread(mac, 1, 17, g_ether); - if(read == 17) - ret = strndup(mac,17); - else - ret = 0; + g_ether = fopen("/etc/modprobe.d/g_ether.conf", "r"); + if(!g_ether) + { + log_warning("Failed to read mac address from /etc/modprobe.d/g_ether.conf\n"); + return(NULL); + } + test = fseek(g_ether, 26, SEEK_SET); + if(test == -1) + { + fclose(g_ether); + return 0; + } + mac = malloc(sizeof(char) *17); + if(mac) + read = fread(mac, 1, 17, g_ether); + if(read == 17) + ret = strndup(mac,17); + else + ret = 0; - free(mac); - fclose(g_ether); - return(ret); + free(mac); + fclose(g_ether); + return(ret); } diff --git a/src/usb_moded-mac.h b/src/usb_moded-mac.h index 71f4a58..6cb9d78 100644 --- a/src/usb_moded-mac.h +++ b/src/usb_moded-mac.h @@ -1,24 +1,36 @@ /** - @file usb_moded-mac.h + * @file usb_moded-mac.h + * + * Copyright (C) 2013-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - Copyright (C) 2013 Jolla. All rights reserved. +#ifndef USB_MODED_MAC_H_ +# define USB_MODED_MAC_H_ - @author: Philippe De Swert +/* ========================================================================= * + * Prototypes + * ========================================================================= */ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +/* -- mac -- */ - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +void mac_generate_random_mac(void); +char *mac_read_mac (void); -void generate_random_mac (void); -char * read_mac(void); +#endif /* USB_MODED_MAC_H_ */ diff --git a/src/usb_moded-modes.h b/src/usb_moded-modes.h index 77a4330..2ef2fce 100644 --- a/src/usb_moded-modes.h +++ b/src/usb_moded-modes.h @@ -1,38 +1,52 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. - - Author: Philippe De Swert + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Thomas Perl + * Author: Martin Jones + * Author: Andrew den Exter + * Author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +#ifndef USB_MODED_MODES_H_ +# define USB_MODED_MODES_H_ - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +/* ========================================================================= * + * Constants + * ========================================================================= */ /* possible values for the mode - the first two are internal only. + * the first two are internal only. */ -#define MODE_UNDEFINED "undefined" -#define MODE_ASK "ask" -#define MODE_MASS_STORAGE "mass_storage" -#define MODE_DEVELOPER "developer_mode" -#define MODE_MTP "mtp_mode" -#define MODE_HOST "host_mode" -#define MODE_CONNECTION_SHARING "connection_sharing" -#define MODE_DIAG "diag_mode" -#define MODE_ADB "adb_mode" -#define MODE_PC_SUITE "pc_suite" -#define MODE_CHARGING "charging_only" +# define MODE_UNDEFINED "undefined" +# define MODE_ASK "ask" +# define MODE_MASS_STORAGE "mass_storage" +# define MODE_DEVELOPER "developer_mode" +# define MODE_MTP "mtp_mode" +# define MODE_HOST "host_mode" +# define MODE_CONNECTION_SHARING "connection_sharing" +# define MODE_DIAG "diag_mode" +# define MODE_ADB "adb_mode" +# define MODE_PC_SUITE "pc_suite" +# define MODE_CHARGING "charging_only" /** * @@ -42,10 +56,7 @@ * * the two last ones cannot be set and are not full modes **/ -#define MODE_CHARGING_FALLBACK "charging_only_fallback" -#define MODE_CHARGER "dedicated_charger" +# define MODE_CHARGING_FALLBACK "charging_only_fallback" +# define MODE_CHARGER "dedicated_charger" -void send_supported_modes_signal(void); -void send_available_modes_signal(void); -void send_hidden_modes_signal(void); -void send_whitelisted_modes_signal(void); +#endif /* USB_MODED_MODES_H_ */ diff --git a/src/usb_moded-modesetting.c b/src/usb_moded-modesetting.c index ee53a63..d7a969e 100644 --- a/src/usb_moded-modesetting.c +++ b/src/usb_moded-modesetting.c @@ -1,31 +1,33 @@ /** - @file usb_moded-modesetting.c - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2013-2016 Jolla Ltd. - - @author: Philippe De Swert - @author: Philippe De Swert - @author: Bernd Wachter - @author: Slava Monich - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#define _GNU_SOURCE + * @file usb_moded-modesetting.c + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Bernd Wachter + * @author: Slava Monich + * @author: Thomas Perl + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + #include #include #include @@ -43,17 +45,45 @@ #include "usb_moded-dbus.h" #include "usb_moded-dbus-private.h" #include "usb_moded-appsync.h" -#include "usb_moded-config.h" +#include "usb_moded-config-private.h" #include "usb_moded-modesetting.h" #include "usb_moded-network.h" #include "usb_moded-android.h" - - -static char *read_from_file(const char *path, size_t maxsize); +#include "usb_moded-configfs.h" + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- modesetting -- */ + +static void modesetting_track_value (const char *path, const char *text); +void modesetting_verify_values (void); +static char *modesetting_strip (char *str); +static char *modesetting_read_from_file (const char *path, size_t maxsize); +int modesetting_write_to_file_real (const char *file, int line, const char *func, const char *path, const char *text); +static gboolean modesetting_network_retry (gpointer data); +static int modesetting_set_mass_storage_mode (struct mode_list_elem *data); +static int modesetting_unset_mass_storage_mode (struct mode_list_elem *data); +static void modesetting_report_mass_storage_blocker(const char *mountpoint, int try); +int modesetting_set_dynamic_mode (void); +static void modesetting_unset_dynamic_mode (void); +int modesetting_cleanup (const char *module); +void modesetting_init (void); +void modesetting_quit (void); + +/* ========================================================================= * + * Data + * ========================================================================= */ static GHashTable *tracked_values = 0; +static guint delayed_network = 0; -static void usb_moded_mode_track_value(const char *path, const char *text) +/* ========================================================================= * + * Functions + * ========================================================================= */ + +static void modesetting_track_value(const char *path, const char *text) { if( !tracked_values || !path ) goto EXIT; @@ -67,7 +97,7 @@ static void usb_moded_mode_track_value(const char *path, const char *text) return; } -void usb_moded_mode_verify_values(void) +void modesetting_verify_values(void) { GHashTableIter iter; gpointer key, value; @@ -81,7 +111,7 @@ void usb_moded_mode_verify_values(void) const char *path = key; const char *text = value; - char *curr = read_from_file(path, 0x1000); + char *curr = modesetting_read_from_file(path, 0x1000); if( g_strcmp0(text, curr) ) { /* There might be case mismatch between hexadecimal @@ -97,7 +127,7 @@ void usb_moded_mode_verify_values(void) text ?: "???", curr ?: "???"); } - usb_moded_mode_track_value(path, curr); + modesetting_track_value(path, curr); } free(curr); @@ -107,576 +137,586 @@ void usb_moded_mode_verify_values(void) return; } -static void report_mass_storage_blocker(const char *mountpoint, int try); -static guint delayed_network = 0; - -static char *strip(char *str) +static char *modesetting_strip(char *str) { - unsigned char *src = (unsigned char *)str; - unsigned char *dst = (unsigned char *)str; - - while( *src > 0 && *src <= 32 ) ++src; + unsigned char *src = (unsigned char *)str; + unsigned char *dst = (unsigned char *)str; - for( ;; ) - { - while( *src > 32 ) *dst++ = *src++; while( *src > 0 && *src <= 32 ) ++src; - if( *src == 0 ) break; - *dst++ = ' '; - } - *dst = 0; - return str; + + for( ;; ) + { + while( *src > 32 ) *dst++ = *src++; + while( *src > 0 && *src <= 32 ) ++src; + if( *src == 0 ) break; + *dst++ = ' '; + } + *dst = 0; + return str; } -static char *read_from_file(const char *path, size_t maxsize) +static char *modesetting_read_from_file(const char *path, size_t maxsize) { - int fd = -1; - ssize_t done = 0; - char *data = 0; - char *text = 0; - - if((fd = open(path, O_RDONLY)) == -1) - { - /* Silently ignore things that could result - * from missing / read-only files */ - if( errno != ENOENT && errno != EACCES ) - log_warning("%s: open: %m", path); - goto cleanup; - } - - if( !(data = malloc(maxsize + 1)) ) - goto cleanup; - - if((done = read(fd, data, maxsize)) == -1) - { - log_warning("%s: read: %m", path); - goto cleanup; - } - - text = realloc(data, done + 1), data = 0; - text[done] = 0; - strip(text); + int fd = -1; + ssize_t done = 0; + char *data = 0; + char *text = 0; + + if((fd = open(path, O_RDONLY)) == -1) + { + /* Silently ignore things that could result + * from missing / read-only files */ + if( errno != ENOENT && errno != EACCES ) + log_warning("%s: open: %m", path); + goto cleanup; + } + + if( !(data = malloc(maxsize + 1)) ) + goto cleanup; + + if((done = read(fd, data, maxsize)) == -1) + { + log_warning("%s: read: %m", path); + goto cleanup; + } + + text = realloc(data, done + 1), data = 0; + text[done] = 0; + modesetting_strip(text); cleanup: - free(data); - if(fd != -1) close(fd); - return text; + free(data); + if(fd != -1) close(fd); + return text; } -int write_to_file_real(const char *file, int line, const char *func, - const char *path, const char *text) +int modesetting_write_to_file_real(const char *file, int line, const char *func, + const char *path, const char *text) { - int err = -1; - int fd = -1; - size_t todo = 0; - char *prev = 0; - bool clear = false; + int err = -1; + int fd = -1; + size_t todo = 0; + char *prev = 0; + bool clear = false; - /* if either path or the text to be written are not there + /* if either path or the text to be written are not there we return an error */ - if(!text || !path) - return err; - - /* When attempting to clear ffs function list, writing an - * empty string is ignored and accomplishes nothing - while - * writing non-existing function clears the list but returns - * write error. - * - * Treat "none" (which is used as place-holder value in both - * configuration files and usb-moded sources) and "" similarly: - * - Write invalid function name to sysfs - * - Ignore resulting write error under default logging level - * - Assume reading from sysfs will result in empty string - */ - if( !strcmp(path, "/sys/class/android_usb/android0/functions") ) { - if( !strcmp(text, "") || !strcmp(text, "none") ) { - text = "none"; - clear = true; + if(!text || !path) + return err; + + /* When attempting to clear ffs function list, writing an + * empty string is ignored and accomplishes nothing - while + * writing non-existing function clears the list but returns + * write error. + * + * Treat "none" (which is used as place-holder value in both + * configuration files and usb-moded sources) and "" similarly: + * - Write invalid function name to sysfs + * - Ignore resulting write error under default logging level + * - Assume reading from sysfs will result in empty string + */ + if( !strcmp(path, ANDROID0_FUNCTIONS) ) { + if( !strcmp(text, "") || !strcmp(text, "none") ) { + text = "none"; + clear = true; + } } - } - - /* If the file can be read, it also means we can later check that - * the file retains the value we are about to write here. */ - if( (prev = read_from_file(path, 0x1000)) ) - usb_moded_mode_track_value(path, clear ? "" : text); - - log_debug("%s:%d: %s(): WRITE '%s' : '%s' --> '%s'", - file, line, func, - path, prev ?: "???", text); - - todo = strlen(text); - - /* no O_CREAT -> writes only to already existing files */ - if( (fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY))) == -1 ) - { - log_warning("open(%s): %m", path); - goto cleanup; - } - - while( todo > 0 ) - { - ssize_t n = TEMP_FAILURE_RETRY(write(fd, text, todo)); - if( n < 0 ) + + /* If the file can be read, it also means we can later check that + * the file retains the value we are about to write here. */ + if( (prev = modesetting_read_from_file(path, 0x1000)) ) + modesetting_track_value(path, clear ? "" : text); + + log_debug("%s:%d: %s(): WRITE '%s' : '%s' --> '%s'", + file, line, func, + path, prev ?: "???", text); + + todo = strlen(text); + + /* no O_CREAT -> writes only to already existing files */ + if( (fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY))) == -1 ) { - if( clear && errno == EINVAL ) - log_debug("write(%s): %m (expected failure)", path); - else - log_warning("write(%s): %m", path); - goto cleanup; + log_warning("open(%s): %m", path); + goto cleanup; } - todo -= n; - text += n; - } - err = 0; + while( todo > 0 ) + { + ssize_t n = TEMP_FAILURE_RETRY(write(fd, text, todo)); + if( n < 0 ) + { + if( clear && errno == EINVAL ) + log_debug("write(%s): %m (expected failure)", path); + else + log_warning("write(%s): %m", path); + goto cleanup; + } + todo -= n; + text += n; + } + + err = 0; cleanup: - if( fd != -1 ) TEMP_FAILURE_RETRY(close(fd)); + if( fd != -1 ) TEMP_FAILURE_RETRY(close(fd)); - free(prev); + free(prev); - return err; + return err; } -static gboolean network_retry(gpointer data) +static gboolean modesetting_network_retry(gpointer data) { - delayed_network = 0; - usb_network_up(data); - return(FALSE); + delayed_network = 0; + network_up(data); + return(FALSE); } -static int set_mass_storage_mode(struct mode_list_elem *data) +static int modesetting_set_mass_storage_mode(struct mode_list_elem *data) { - gchar *command; - char command2[256], *real_path = NULL, *mountpath; - char *mount; - gchar **mounts; - int ret = 0, i = 0, mountpoints = 0, fua = 0, try = 0; - - /* send unmount signal so applications can release their grasp on the fs, do this here so they have time to act */ - usb_moded_send_signal(USB_PRE_UNMOUNT); - fua = find_sync(); - mount = find_mounts(); - if(mount) + gchar *command; + char command2[256], *real_path = NULL, *mountpath; + char *mount; + gchar **mounts; + int ret = 0, i = 0, mountpoints = 0, fua = 0, try = 0; + + /* send unmount signal so applications can release their grasp on the fs, do this here so they have time to act */ + umdbus_send_state_signal(USB_PRE_UNMOUNT); + fua = config_find_sync(); + mount = config_find_mounts(); + if(mount) + { + mounts = g_strsplit(mount, ",", 0); + /* check amount of mountpoints */ + for(i=0 ; mounts[i] != NULL; i++) { - mounts = g_strsplit(mount, ",", 0); - /* check amount of mountpoints */ - for(i=0 ; mounts[i] != NULL; i++) - { - mountpoints++; - } + mountpoints++; + } - if(strcmp(data->mode_module, MODULE_NONE)) - { - /* check if the file storage module has been loaded with sufficient luns in the parameter, - if not, unload and reload or load it. Since mountpoints start at 0 the amount of them is one more than their id */ - sprintf(command2, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", (mountpoints - 1) ); - if(access(command2, R_OK) == -1) - { - log_debug("%s does not exist, unloading and reloading mass_storage\n", command2); - usb_moded_unload_module(MODULE_MASS_STORAGE); - sprintf(command2, "modprobe %s luns=%d \n", MODULE_MASS_STORAGE, mountpoints); - log_debug("usb-load command = %s \n", command2); - ret = usb_moded_system(command2); - if(ret) - return(ret); - } - } - /* umount filesystems */ - for(i=0 ; mounts[i] != NULL; i++) - { - /* check if filesystem is mounted or not, if ret = 1 it is already unmounted */ - real_path = realpath(mounts[i], NULL); - if(real_path) - mountpath = real_path; - else - mountpath = mounts[i]; + if(strcmp(data->mode_module, MODULE_NONE)) + { + /* check if the file storage module has been loaded with sufficient luns in the parameter, + if not, unload and reload or load it. Since mountpoints start at 0 the amount of them is one more than their id */ + sprintf(command2, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", (mountpoints - 1) ); + if(access(command2, R_OK) == -1) + { + log_debug("%s does not exist, unloading and reloading mass_storage\n", command2); + modules_unload_module(MODULE_MASS_STORAGE); + sprintf(command2, "modprobe %s luns=%d \n", MODULE_MASS_STORAGE, mountpoints); + log_debug("usb-load command = %s \n", command2); + ret = usbmoded_system(command2); + if(ret) + return(ret); + } + } + /* umount filesystems */ + for(i=0 ; mounts[i] != NULL; i++) + { + /* check if filesystem is mounted or not, if ret = 1 it is already unmounted */ + real_path = realpath(mounts[i], NULL); + if(real_path) + mountpath = real_path; + else + mountpath = mounts[i]; umount: command = g_strconcat("mount | grep ", mountpath, NULL); - ret = usb_moded_system(command); - g_free(command); - if(!ret) - { - /* no check for / needed as that will fail to umount anyway */ - command = g_strconcat("umount ", mountpath, NULL); - log_debug("unmount command = %s\n", command); - ret = usb_moded_system(command); - g_free(command); - if(ret != 0) - { - if(try != 3) - { - try++; - usb_moded_sleep(1); - log_err("Umount failed. Retrying\n"); - report_mass_storage_blocker(mount, 1); - goto umount; - } - else - { - log_err("Unmounting %s failed\n", mount); - report_mass_storage_blocker(mount, 2); - usb_moded_send_error_signal(UMOUNT_ERROR); - return(ret); - } - } - } - else - /* already unmounted. Set return value to 0 since there is no error */ - ret = 0; - } - - /* activate mounts after sleeping 1s to be sure enumeration happened and autoplay will work in windows*/ - usb_moded_sleep(1); - for(i=0 ; mounts[i] != NULL; i++) - { - - if(strcmp(data->mode_module, MODULE_NONE)) - { - sprintf(command2, "echo %i > /sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/nofua", fua, i); - log_debug("usb lun = %s active\n", command2); - usb_moded_system(command2); - sprintf(command2, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", i); - log_debug("usb lun = %s active\n", command2); - write_to_file(command2, mounts[i]); - } - else - { - write_to_file("/sys/class/android_usb/android0/enable", "0"); - write_to_file("/sys/class/android_usb/android0/functions", "mass_storage"); - //write_to_file("/sys/class/android_usb/f_mass_storage/lun/nofua", fua); - write_to_file("/sys/class/android_usb/f_mass_storage/lun/file", mount); - write_to_file("/sys/class/android_usb/android0/enable", "1"); - - } + ret = usbmoded_system(command); + g_free(command); + if(!ret) + { + /* no check for / needed as that will fail to umount anyway */ + command = g_strconcat("umount ", mountpath, NULL); + log_debug("unmount command = %s\n", command); + ret = usbmoded_system(command); + g_free(command); + if(ret != 0) + { + if(try != 3) + { + try++; + usbmoded_sleep(1); + log_err("Umount failed. Retrying\n"); + modesetting_report_mass_storage_blocker(mount, 1); + goto umount; + } + else + { + log_err("Unmounting %s failed\n", mount); + modesetting_report_mass_storage_blocker(mount, 2); + umdbus_send_error_signal(UMOUNT_ERROR); + return(ret); + } } - g_strfreev(mounts); - g_free(mount); - if(real_path) - free(real_path); - } - - /* only send data in use signal in case we actually succeed */ - if(!ret) - usb_moded_send_signal(DATA_IN_USE); - - return(ret); + } + else + /* already unmounted. Set return value to 0 since there is no error */ + ret = 0; + } + + /* activate mounts after sleeping 1s to be sure enumeration happened and autoplay will work in windows*/ + usbmoded_sleep(1); + for(i=0 ; mounts[i] != NULL; i++) + { + + if(strcmp(data->mode_module, MODULE_NONE)) + { + sprintf(command2, "echo %i > /sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/nofua", fua, i); + log_debug("usb lun = %s active\n", command2); + usbmoded_system(command2); + sprintf(command2, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", i); + log_debug("usb lun = %s active\n", command2); + write_to_file(command2, mounts[i]); + } + else + { + write_to_file(ANDROID0_ENABLE, "0"); + write_to_file(ANDROID0_FUNCTIONS, "mass_storage"); + //write_to_file("/sys/class/android_usb/f_mass_storage/lun/nofua", fua); + write_to_file("/sys/class/android_usb/f_mass_storage/lun/file", mount); + write_to_file(ANDROID0_ENABLE, "1"); + + } + } + g_strfreev(mounts); + g_free(mount); + if(real_path) + free(real_path); + } + + /* only send data in use signal in case we actually succeed */ + if(!ret) + umdbus_send_state_signal(DATA_IN_USE); + + return(ret); } -static int unset_mass_storage_mode(struct mode_list_elem *data) +static int modesetting_unset_mass_storage_mode(struct mode_list_elem *data) { - gchar *command; - char command2[256], *real_path = NULL, *mountpath; - char *mount; - gchar **mounts; - int ret = 1, i = 0; - - mount = find_mounts(); - if(mount) + gchar *command; + char command2[256], *real_path = NULL, *mountpath; + char *mount; + gchar **mounts; + int ret = 1, i = 0; + + mount = config_find_mounts(); + if(mount) + { + mounts = g_strsplit(mount, ",", 0); + for(i=0 ; mounts[i] != NULL; i++) { - mounts = g_strsplit(mount, ",", 0); - for(i=0 ; mounts[i] != NULL; i++) + /* check if it is still or already mounted, if so (ret==0) skip mounting */ + real_path = realpath(mounts[i], NULL); + if(real_path) + mountpath = real_path; + else + mountpath = mounts[i]; + command = g_strconcat("mount | grep ", mountpath, NULL); + ret = usbmoded_system(command); + g_free(command); + if(ret) + { + command = g_strconcat("mount ", mountpath, NULL); + log_debug("mount command = %s\n",command); + ret = usbmoded_system(command); + g_free(command); + /* mount returns 0 if success */ + if(ret != 0 ) { - /* check if it is still or already mounted, if so (ret==0) skip mounting */ - real_path = realpath(mounts[i], NULL); - if(real_path) - mountpath = real_path; - else - mountpath = mounts[i]; - command = g_strconcat("mount | grep ", mountpath, NULL); - ret = usb_moded_system(command); - g_free(command); - if(ret) + log_err("Mounting %s failed\n", mount); + if(ret) + { + g_free(mount); + mount = config_find_alt_mount(); + if(mount) { - command = g_strconcat("mount ", mountpath, NULL); - log_debug("mount command = %s\n",command); - ret = usb_moded_system(command); - g_free(command); - /* mount returns 0 if success */ - if(ret != 0 ) - { - log_err("Mounting %s failed\n", mount); - if(ret) - { - g_free(mount); - mount = find_alt_mount(); - if(mount) - { - command = g_strconcat("mount -t tmpfs tmpfs -o ro --size=512K ", mount, NULL); - log_debug("Total failure, mount ro tmpfs as fallback\n"); - ret = usb_moded_system(command); - g_free(command); - } - usb_moded_send_error_signal(RE_MOUNT_FAILED); - } - - } + command = g_strconcat("mount -t tmpfs tmpfs -o ro --size=512K ", mount, NULL); + log_debug("Total failure, mount ro tmpfs as fallback\n"); + ret = usbmoded_system(command); + g_free(command); } - if(data != NULL) - { - if(!strcmp(data->mode_module, MODULE_NONE)) - { - log_debug("Disable android mass storage\n"); - write_to_file("/sys/class/android_usb/f_mass_storage/lun/file", "0"); - write_to_file("/sys/class/android_usb/android0/enable", "0"); - } - } - else - { - sprintf(command2, "echo \"\" > /sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", i); - log_debug("usb lun = %s inactive\n", command2); - usb_moded_system(command2); - } - } - g_strfreev(mounts); - g_free(mount); - if(real_path) - free(real_path); + umdbus_send_error_signal(RE_MOUNT_FAILED); + } + + } + } + if(data != NULL) + { + if(!strcmp(data->mode_module, MODULE_NONE)) + { + log_debug("Disable android mass storage\n"); + write_to_file("/sys/class/android_usb/f_mass_storage/lun/file", "0"); + write_to_file(ANDROID0_ENABLE, "0"); + } + } + else + { + sprintf(command2, "echo \"\" > /sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", i); + log_debug("usb lun = %s inactive\n", command2); + usbmoded_system(command2); + } } + g_strfreev(mounts); + g_free(mount); + if(real_path) + free(real_path); + } - return(ret); + return(ret); } -static void report_mass_storage_blocker(const char *mountpoint, int try) +static void modesetting_report_mass_storage_blocker(const char *mountpoint, int try) { - FILE *stream = 0; - gchar *lsof_command = 0; - int count = 0; + FILE *stream = 0; + gchar *lsof_command = 0; + int count = 0; - lsof_command = g_strconcat("lsof ", mountpoint, NULL); + lsof_command = g_strconcat("lsof ", mountpoint, NULL); - if( (stream = usb_moded_popen(lsof_command, "r")) ) - { - char *text = 0; - size_t size = 0; - - while( getline(&text, &size, stream) >= 0 ) + if( (stream = usbmoded_popen(lsof_command, "r")) ) { - /* skip the first line as it does not contain process info */ - if(count != 0) + char *text = 0; + size_t size = 0; + + while( getline(&text, &size, stream) >= 0 ) { - gchar **split = 0; - split = g_strsplit((const gchar*)text, " ", 2); - log_err("Mass storage blocked by process %s\n", split[0]); - usb_moded_send_error_signal(split[0]); - g_strfreev(split); + /* skip the first line as it does not contain process info */ + if(count != 0) + { + gchar **split = 0; + split = g_strsplit((const gchar*)text, " ", 2); + log_err("Mass storage blocked by process %s\n", split[0]); + umdbus_send_error_signal(split[0]); + g_strfreev(split); + } + count++; } - count++; + pclose(stream); } - pclose(stream); - } - g_free(lsof_command); - if(try == 2) - log_err("Setting Mass storage blocked. Giving up.\n"); + g_free(lsof_command); + if(try == 2) + log_err("Setting Mass storage blocked. Giving up.\n"); } -int set_dynamic_mode(void) +int modesetting_set_dynamic_mode(void) { + struct mode_list_elem *data; + int ret = 1; + int network = 1; - struct mode_list_elem *data; - int ret = 1; - int network = 1; - - data = get_usb_mode_data(); + data = usbmoded_get_usb_mode_data(); - if(!data) - return(ret); + if(!data) + return(ret); - if(data->mass_storage) - { - return set_mass_storage_mode(data); - } + if(data->mass_storage) + { + return modesetting_set_mass_storage_mode(data); + } #ifdef APP_SYNC - if(data->appsync) - if(activate_sync(data->mode_name)) /* returns 1 on error */ - { - log_debug("Appsync failure"); - return(ret); - } + if(data->appsync) + if(appsync_activate_sync(data->mode_name)) /* returns 1 on error */ + { + log_debug("Appsync failure"); + return(ret); + } #endif - /* make sure things are disabled before changing functionality */ - if(data->softconnect_disconnect) - { - write_to_file(data->softconnect_path, data->softconnect_disconnect); - } - /* set functionality first, then enable */ - if(data->android_extra_sysfs_value && data->android_extra_sysfs_path) - { - ret = write_to_file(data->android_extra_sysfs_path, data->android_extra_sysfs_value); - } - if(data->android_extra_sysfs_value2 && data->android_extra_sysfs_path2) - { - write_to_file(data->android_extra_sysfs_path2, data->android_extra_sysfs_value2); - } - if(data->sysfs_path) - { - write_to_file(data->sysfs_path, data->sysfs_value); - } - if(data->idProduct) - { - /* only works for android since the idProduct is a module parameter */ - set_android_productid(data->idProduct); - } - if(data->idVendorOverride) - { - /* only works for android since the idProduct is a module parameter */ - set_android_vendorid(data->idVendorOverride); - } - - /* enable the device */ - if(data->softconnect) - { - ret = write_to_file(data->softconnect_path, data->softconnect); - } - - /* functionality should be enabled, so we can enable the network now */ - if(data->network) - { + if( configfs_in_use() ) { + /* Configfs based gadget configuration */ + char *id = config_get_android_vendor_id(); + configfs_set_udc(false); + configfs_set_productid(data->idProduct); + configfs_set_vendorid(data->idVendorOverride ?: id); + configfs_set_function(data->sysfs_value); + ret = configfs_set_udc(true) ? 0 : -1; + free(id); + } + else if( android_in_use() ) { + /* Android USB based gadget configuration */ + + /* make sure things are disabled before changing functionality */ + write_to_file(data->softconnect_path, data->softconnect_disconnect); + + /* set functionality first, then enable */ + if(data->android_extra_sysfs_value) + ret = write_to_file(data->android_extra_sysfs_path, data->android_extra_sysfs_value); + + /* ??? */ + write_to_file(data->android_extra_sysfs_path2, data->android_extra_sysfs_value2); + + /* only works for android since the idProduct is a module parameter */ + android_set_productid(data->idProduct); + + /* only works for android since the idProduct is a module parameter */ + android_set_vendorid(data->idVendorOverride); + + write_to_file(data->sysfs_path, data->sysfs_value); + + /* enable the device */ + if( ret == 0 ) + ret = write_to_file(data->softconnect_path, data->softconnect); + } + else if( modules_in_use() ) { + /* Assume relevant module has already been successfully loaded + * from somewhere else. + */ + ret = 0; + } + else { + log_crit("no backend is selected, can't set dynamic mode"); + ret = 1; + } + + /* functionality should be enabled, so we can enable the network now */ + if(data->network) + { #ifdef DEBIAN - char command[256]; + char command[256]; - g_snprintf(command, 256, "ifdown %s ; ifup %s", data->network_interface, data->network_interface); - usb_moded_system(command); + g_snprintf(command, 256, "ifdown %s ; ifup %s", data->network_interface, data->network_interface); + usbmoded_system(command); #else - usb_network_down(data); - network = usb_network_up(data); + network_down(data); + network = network_up(data); #endif /* DEBIAN */ - } + } - /* try a second time to bring up the network if it failed the first time, + /* try a second time to bring up the network if it failed the first time, this can happen with functionfs based gadgets (which is why we sleep for a bit */ - if(network != 0 && data->network) - { - log_debug("Retry setting up the network later\n"); - if(delayed_network) - g_source_remove(delayed_network); - delayed_network = g_timeout_add_seconds(3, network_retry, data); - } - - /* Needs to be called before application post synching so + if(network != 0 && data->network) + { + log_debug("Retry setting up the network later\n"); + if(delayed_network) + g_source_remove(delayed_network); + delayed_network = g_timeout_add_seconds(3, modesetting_network_retry, data); + } + + /* Needs to be called before application post synching so that the dhcp server has the right config */ - if(data->nat || data->dhcp_server) - usb_network_set_up_dhcpd(data); + if(data->nat || data->dhcp_server) + network_set_up_dhcpd(data); - /* no need to execute the post sync if there was an error setting the mode */ - if(data->appsync && !ret) - { - /* let's sleep for a bit (350ms) to allow interfaces to settle before running postsync */ - usb_moded_msleep(350); - activate_sync_post(data->mode_name); - } + /* no need to execute the post sync if there was an error setting the mode */ + if(data->appsync && !ret) + { + /* let's sleep for a bit (350ms) to allow interfaces to settle before running postsync */ + usbmoded_msleep(350); + appsync_activate_sync_post(data->mode_name); + } #ifdef CONNMAN - if(data->connman_tethering) - connman_set_tethering(data->connman_tethering, TRUE); + if(data->connman_tethering) + connman_set_tethering(data->connman_tethering, TRUE); #endif - if(ret) - usb_moded_send_error_signal(MODE_SETTING_FAILED); - return(ret); + if(ret) + umdbus_send_error_signal(MODE_SETTING_FAILED); + return(ret); } -void unset_dynamic_mode(void) -{ - - struct mode_list_elem *data; +static void modesetting_unset_dynamic_mode(void) +{ + struct mode_list_elem *data; - data = get_usb_mode_data(); + data = usbmoded_get_usb_mode_data(); - if(delayed_network) - { - g_source_remove(delayed_network); - delayed_network = 0; - } + if(delayed_network) + { + g_source_remove(delayed_network); + delayed_network = 0; + } - /* the modelist could be empty */ - if(!data) - return; + /* the modelist could be empty */ + if(!data) + return; - if(!strcmp(data->mode_name, MODE_MASS_STORAGE)) - { - unset_mass_storage_mode(data); - return; - } + if(!strcmp(data->mode_name, MODE_MASS_STORAGE)) + { + modesetting_unset_mass_storage_mode(data); + return; + } #ifdef CONNMAN - if(data->connman_tethering) - connman_set_tethering(data->connman_tethering, FALSE); + if(data->connman_tethering) + connman_set_tethering(data->connman_tethering, FALSE); #endif - if(data->network) - { - usb_network_down(data); - } - - /* disconnect before changing functionality */ - if(data->softconnect_disconnect) - { - write_to_file(data->softconnect_path, data->softconnect_disconnect); - } - if(data->sysfs_path) - { - write_to_file(data->sysfs_path, data->sysfs_reset_value); - } - /* restore vendorid if the mode had an override */ - if(data->idVendorOverride) - { - char *id; - id = get_android_vendor_id(); - set_android_vendorid(id); - g_free(id); - } - - /* enable after the changes have been made */ - if(data->softconnect) - { - write_to_file(data->softconnect_path, data->softconnect); - } + if(data->network) + { + network_down(data); + } + + if( configfs_in_use() ) { + /* Leave as is. We will reprogram wnen mode is + * set, not when it is unset. + */ + } + else if( android_in_use() ) { + /* disconnect before changing functionality */ + write_to_file(data->softconnect_path, data->softconnect_disconnect); + write_to_file(data->sysfs_path, data->sysfs_reset_value); + + /* restore vendorid if the mode had an override */ + if(data->idVendorOverride) + { + char *id = config_get_android_vendor_id(); + android_set_vendorid(id); + g_free(id); + } + + /* enable after the changes have been made */ + write_to_file(data->softconnect_path, data->softconnect); + } + else if( modules_in_use() ) { + /* Assume unloading happens somewhere else */ + } + else { + log_crit("no backend is selected, can't unset dynamic mode"); + } } -/** clean up mode changes or extra actions to perform after a mode change +/** clean up mode changes or extra actions to perform after a mode change * @param module Name of module currently in use * @return 0 on success, non-zero on failure * */ -int usb_moded_mode_cleanup(const char *module) +int modesetting_cleanup(const char *module) { - log_debug("Cleaning up mode\n"); + log_debug("Cleaning up mode\n"); - if(!module) - { - log_warning("No module found to unload. Skipping cleanup\n"); - return 0; - } + if(!module) + { + log_warning("No module found to unload. Skipping cleanup\n"); + return 0; + } #ifdef APP_SYNC - /* Stop applications started due to entering this mode */ - appsync_stop(FALSE); + /* Stop applications started due to entering this mode */ + appsync_stop(FALSE); #endif /* APP_SYNC */ - if(!strcmp(module, MODULE_MASS_STORAGE)|| !strcmp(module, MODULE_FILE_STORAGE)) - { - /* no clean-up needs to be done when we come from charging mode. We need - to check since we use fake mass-storage for charging */ - if(!strcmp(MODE_CHARGING, get_usb_mode()) || !strcmp(MODE_CHARGING_FALLBACK, get_usb_mode())) - return 0; - unset_mass_storage_mode(NULL); - } + if(!strcmp(module, MODULE_MASS_STORAGE)|| !strcmp(module, MODULE_FILE_STORAGE)) + { + /* no clean-up needs to be done when we come from charging mode. We need + to check since we use fake mass-storage for charging */ + if(!strcmp(MODE_CHARGING, usbmoded_get_usb_mode()) || !strcmp(MODE_CHARGING_FALLBACK, usbmoded_get_usb_mode())) + return 0; + modesetting_unset_mass_storage_mode(NULL); + } - else if(get_usb_mode_data()) - unset_dynamic_mode(); + else if(usbmoded_get_usb_mode_data()) + modesetting_unset_dynamic_mode(); - return(0); + return(0); } /** Allocate modesetting related dynamic resouces */ -void usb_moded_mode_init(void) +void modesetting_init(void) { if( !tracked_values ) { tracked_values = g_hash_table_new_full(g_str_hash, g_str_equal, @@ -686,7 +726,7 @@ void usb_moded_mode_init(void) /** Release modesetting related dynamic resouces */ -void usb_moded_mode_quit(void) +void modesetting_quit(void) { if( tracked_values ) { g_hash_table_unref(tracked_values), tracked_values = 0; diff --git a/src/usb_moded-modesetting.h b/src/usb_moded-modesetting.h index 3868ac9..c4ed440 100644 --- a/src/usb_moded-modesetting.h +++ b/src/usb_moded-modesetting.h @@ -1,37 +1,54 @@ /** - @file usb_moded-modesetting.h - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#include "usb_moded-dyn-config.h" - -int write_to_file_real(const char *file, int line, const char *func, const char *path, const char *text); - -#define write_to_file(path,text)\ - write_to_file_real(__FILE__,__LINE__,__FUNCTION__,(path),(text)) - -int set_mtp_mode(void); -int set_dynamic_mode(void); -void unset_dynamic_mode(void); -/* clean up for the mode changes on disconnect */ -int usb_moded_mode_cleanup(const char *module); -void usb_moded_mode_verify_values(void); -void usb_moded_mode_init(void); -void usb_moded_mode_quit(void); + * @file usb_moded-modesetting.h + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Thomas Perl + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef USB_MODED_MODESETTING_H_ +# define USB_MODED_MODESETTING_H_ + +# include "usb_moded-dyn-config.h" + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- modesetting -- */ + +void modesetting_verify_values (void); +int modesetting_write_to_file_real(const char *file, int line, const char *func, const char *path, const char *text); +int modesetting_set_dynamic_mode (void); +int modesetting_cleanup (const char *module); +void modesetting_init (void); +void modesetting_quit (void); + +/* ========================================================================= * + * Macros + * ========================================================================= */ + +# define write_to_file(path,text)\ + modesetting_write_to_file_real(__FILE__,__LINE__,__FUNCTION__,(path),(text)) + +#endif /* USB_MODED_MODESETTING_H_ */ diff --git a/src/usb_moded-modules-android.c b/src/usb_moded-modules-android.c deleted file mode 100644 index dc29bd2..0000000 --- a/src/usb_moded-modules-android.c +++ /dev/null @@ -1,120 +0,0 @@ -/** - @file usb_moded-modules-android.c - - Copyright (C) 2012 Jolla. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#include -#include -#include -#include - -#include - -#include - -#include "usb_moded.h" -#include "usb_moded-modules.h" -#include "usb_moded-log.h" -#include "usb_moded-config.h" -#include "usb_moded-dbus.h" -#include "usb_moded-dbus-private.h" -#include "usb_moded-config.h" -#include "usb_moded-modesetting.h" - -/** load module - * - * @param module Name of the module to load - * @return 0 on success, non-zero on failure - * - */ -int usb_moded_load_module(const char *module) -{ - int ret = 0; - - write_to_file("/sys/class/android_usb/android0/functions", module); - write_to_file("/sys/class/android_usb/android0/enable", "1"); - if( ret == 0) - log_info("Module setting to %s successfully\n", module); - return(ret); -} - -/** unload module - * - * @param module Name of the module to unload - * @return 0 on success, non-zero on failure - * - */ -int usb_moded_unload_module(const char *module) -{ - write_to_file("/sys/class/android_usb/android0/enable", "0"); - return(0); -} - -/** Check which state a module is in - * - * @return 1 if loaded, 0 when not loaded - */ -inline static int module_state_check(const char *module) -{ - return(0); -} - -/** find which module is loaded - * - * @return The name of the loaded module, or NULL if no modules are loaded. - */ -inline const char * usb_moded_find_module(void) -{ - return(0); -} - -/** clean up for modules when usb gets disconnected - * - * @param module The name of the module to unload - * @return 0 on success, non-zero on failure - * - */ -inline int usb_moded_module_cleanup(const char *module) -{ - return(0); -} - -/** try to unload modules to support switching - * - * - * @param force force unloading with a nasty clean-up on TRUE, or just try unloading when FALSE - * @return 0 on success, 1 on failure, 2 if hard clean-up failed - */ -inline int usb_moded_module_switch_prepare (int force) -{ - return 0; -} - -/** check for loaded modules and clean-up if they are not for the chosen mode - * - * @param module_name module name to check for - * - */ -inline void check_module_state(const char *module_name) -{ - return; -} - - diff --git a/src/usb_moded-modules.c b/src/usb_moded-modules.c index e028a47..8459e8c 100644 --- a/src/usb_moded-modules.c +++ b/src/usb_moded-modules.c @@ -1,28 +1,31 @@ /** - @file usb_moded-modules.c - - Copyright (C) 2010 Nokia Corporation. All rights reserved. - Copyright (C) 2012-2016 Jolla. All rights reserved. - - @author: Philippe De Swert - @author: Philippe De Swert - @author: Slava Monich - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-modules.c + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2012-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Thomas Perl + * @author: Slava Monich + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -43,149 +46,270 @@ #include "usb_moded-modesetting.h" #include "usb_moded-modes.h" -/* kmod context - initialized at start in usb_moded_init by ctx_init() - and cleaned up by ctx_cleanup() functions */ +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- modules -- */ + +bool modules_init (void); +bool modules_in_use (void); +void modules_quit (void); +int modules_load_module (const char *module); +int modules_unload_module (const char *module); +static int modules_module_is_loaded (const char *module); +const char *modules_get_loaded_module (void); +int modules_cleanup_module (const char *module); +static int modules_prepare_for_module_switch(int force); +void modules_check_module_state (const char *module_name); + +/* ========================================================================= * + * Data + * ========================================================================= */ + +/* kmod context - initialized at start in usbmoded_init by ctx_init() + * and cleaned up by ctx_cleanup() functions */ static struct kmod_ctx *ctx = 0; +/* ========================================================================= * + * Functions + * ========================================================================= */ + +static bool modules_have_module(const char *module) +{ + // TODO: not fully untested due to lack of suitable hw + + bool ack = false; + struct kmod_list *list = 0; + + if( kmod_module_new_from_lookup(ctx, module, &list) < 0 ) + goto EXIT; + + if( list == 0 ) + goto EXIT; + + ack = true; + +EXIT: + if( list ) + kmod_module_unref_list(list); + + log_debug("module %s does%s exist", ack ? "" : "not "); + return ack; + +} + +static int modules_probed = -1; + +bool modules_in_use(void) +{ + if( modules_probed < 0 ) + log_debug("modules_in_use() called before modules_probe()"); + + return modules_probed > 0; +} + +static bool modules_probe(void) +{ + static const char * const lut[] = { + MODULE_MASS_STORAGE, + MODULE_FILE_STORAGE, + MODULE_DEVELOPER, + MODULE_MTP, + 0 + }; + + if( modules_probed == -1 ) { + modules_probed = false; + /* Check if we have at least one of the kernel modules we + * expect to use for something. + */ + for( size_t i = 0; lut[i] ; ++i ) { + if( modules_have_module(lut[i]) ) { + modules_probed = true; + break; + } + } + log_warning("MODULES %sdetected", modules_probed ? "" : "not "); + } + + return modules_in_use(); +} + /* kmod module init */ -void usb_moded_module_ctx_init(void) +bool modules_init(void) { - ctx = kmod_new(NULL, NULL); - kmod_load_resources(ctx); + bool ack = false; + + if( !ctx ) { + if( !(ctx = kmod_new(NULL, NULL)) ) + goto EXIT; + } + + if( kmod_load_resources(ctx) < 0 ) + goto EXIT; + + if( !modules_probe() ) + goto EXIT; + + ack = true; +EXIT: + return ack; } /* kmod module cleanup */ -void usb_moded_module_ctx_cleanup(void) +void modules_quit(void) { if( ctx ) - kmod_unref(ctx), ctx = 0; + kmod_unref(ctx), ctx = 0; } -/** load module +/** load module * * @param module Name of the module to load * @return 0 on success, non-zero on failure * */ -int usb_moded_load_module(const char *module) +int modules_load_module(const char *module) { - int ret = 0; - - const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; - struct kmod_module *mod; - char *charging_args = NULL; - char *load = NULL; - - if(!strcmp(module, MODULE_NONE)) - return 0; - - /* copy module to load as it might be modified if we're trying charging mode */ - load = strdup(module); - if(!strcmp(module, MODULE_CHARGING) || !strcmp(module, MODULE_CHARGE_FALLBACK)) - { - /* split the string in module name and argument, they are the same for MODULE_CHARGE_FALLBACK - so no need to handle them separately */ - gchar **strings; - - /* since the mass_storage module is the newer one and we check against it to avoid - loading failures we use it here, as we fall back to g_file_storage if g_mass_storage - fails to load */ - strings = g_strsplit(MODULE_CHARGE_FALLBACK, " ", 2); - //log_debug("module args = %s, module = %s\n", strings[1], strings[0]); - charging_args = strdup(strings[1]); - /* load was already assigned. Free it to re-assign */ - free(load); - load = strdup(strings[0]); - g_strfreev(strings); - - } - ret = kmod_module_new_from_name(ctx, load, &mod); - /* since kmod_module_new_from_name does not check if the module - exists we test it's path in case we deal with the mass-storage one */ - if(!strcmp(module, MODULE_MASS_STORAGE) && - (kmod_module_get_path(mod) == NULL)) - { - log_debug("Fallback on older g_file_storage\n"); - ret = kmod_module_new_from_name(ctx, MODULE_FILE_STORAGE, &mod); - } - - if(!charging_args) - ret = kmod_module_probe_insert_module(mod, probe_flags, NULL, NULL, NULL, NULL); - else - { - ret = kmod_module_probe_insert_module(mod, probe_flags, charging_args, NULL, NULL, NULL); - free(charging_args); - } - kmod_module_unref(mod); - free(load); - - if( ret == 0) - log_info("Module %s loaded successfully\n", module); - else - log_info("Module %s failed to load\n", module); - return(ret); + int ret = 0; + + const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; + struct kmod_module *mod; + char *charging_args = NULL; + char *load = NULL; + + if(!strcmp(module, MODULE_NONE)) + return 0; + + if( !modules_in_use() ) { + log_warning("load module %s - without module support", module); + return -1; + } + + /* copy module to load as it might be modified if we're trying charging mode */ + load = strdup(module); + if(!strcmp(module, MODULE_CHARGING) || !strcmp(module, MODULE_CHARGE_FALLBACK)) + { + /* split the string in module name and argument, they are the same for MODULE_CHARGE_FALLBACK + so no need to handle them separately */ + gchar **strings; + + /* since the mass_storage module is the newer one and we check against it to avoid + loading failures we use it here, as we fall back to g_file_storage if g_mass_storage + fails to load */ + strings = g_strsplit(MODULE_CHARGE_FALLBACK, " ", 2); + //log_debug("module args = %s, module = %s\n", strings[1], strings[0]); + charging_args = strdup(strings[1]); + /* load was already assigned. Free it to re-assign */ + free(load); + load = strdup(strings[0]); + g_strfreev(strings); + + } + ret = kmod_module_new_from_name(ctx, load, &mod); + /* since kmod_module_new_from_name does not check if the module + exists we test it's path in case we deal with the mass-storage one */ + if(!strcmp(module, MODULE_MASS_STORAGE) && + (kmod_module_get_path(mod) == NULL)) + { + log_debug("Fallback on older g_file_storage\n"); + ret = kmod_module_new_from_name(ctx, MODULE_FILE_STORAGE, &mod); + } + + if(!charging_args) + ret = kmod_module_probe_insert_module(mod, probe_flags, NULL, NULL, NULL, NULL); + else + { + ret = kmod_module_probe_insert_module(mod, probe_flags, charging_args, NULL, NULL, NULL); + free(charging_args); + } + kmod_module_unref(mod); + free(load); + + if( ret == 0) + log_info("Module %s loaded successfully\n", module); + else + log_info("Module %s failed to load\n", module); + return(ret); } /** unload module - * + * * @param module Name of the module to unload * @return 0 on success, non-zero on failure * */ -int usb_moded_unload_module(const char *module) +int modules_unload_module(const char *module) { - int ret = 0; + int ret = 0; - struct kmod_module *mod; + struct kmod_module *mod; - if(!strcmp(module, MODULE_NONE)) - return 0; + if(!strcmp(module, MODULE_NONE)) + return 0; - kmod_module_new_from_name(ctx, module, &mod); - ret = kmod_module_remove_module(mod, KMOD_REMOVE_NOWAIT); - kmod_module_unref(mod); + if( !modules_in_use() ) { + log_warning("unload module %s - without module support", module); + return -1; + } - return(ret); + kmod_module_new_from_name(ctx, module, &mod); + ret = kmod_module_remove_module(mod, KMOD_REMOVE_NOWAIT); + kmod_module_unref(mod); + + return(ret); } /** Check which state a module is in * * @return 1 if loaded, 0 when not loaded */ -static int module_state_check(const char *module) +static int modules_module_is_loaded(const char *module) { - int ret = 0; - struct kmod_module *mod; - - kmod_module_new_from_name(ctx, module, &mod); - ret = kmod_module_get_initstate(mod); - kmod_module_unref(mod); - if( ret == KMOD_MODULE_LIVE) - return(1); - else - return(0); + int ret = 0; + struct kmod_module *mod; + + kmod_module_new_from_name(ctx, module, &mod); + ret = kmod_module_get_initstate(mod); + kmod_module_unref(mod); + if( ret == KMOD_MODULE_LIVE) + return 1; + + return 0; } -/** find which module is loaded +/** find which module is loaded * * @return The name of the loaded module, or NULL if no modules are loaded. */ -const char * usb_moded_find_module(void) +const char * modules_get_loaded_module(void) { - if(module_state_check("g_ether")) - return(MODULE_DEVELOPER); - else if(module_state_check("g_ncm")) - return("g_ncm"); - else if(module_state_check("g_ffs")) - return(MODULE_MTP); - else if(module_state_check("g_mass_storage")) - return(MODULE_MASS_STORAGE); - else if(module_state_check("g_file_storage")) - return(MODULE_FILE_STORAGE); - else if(module_state_check(get_usb_module())) - return(get_usb_module()); - /* no module loaded */ - return(0); + if( !modules_in_use() ) { + log_warning("get loaded module - without module support"); + return 0; + } + + if(modules_module_is_loaded("g_ether")) + return(MODULE_DEVELOPER); + + if(modules_module_is_loaded("g_ncm")) + return("g_ncm"); + + if(modules_module_is_loaded("g_ffs")) + return(MODULE_MTP); + + if(modules_module_is_loaded("g_mass_storage")) + return(MODULE_MASS_STORAGE); + + if(modules_module_is_loaded("g_file_storage")) + return(MODULE_FILE_STORAGE); + + if(modules_module_is_loaded(usbmoded_get_usb_module())) + return(usbmoded_get_usb_module()); + + /* no module loaded */ + return(0); } /** clean up for modules when usb gets disconnected @@ -194,58 +318,64 @@ const char * usb_moded_find_module(void) * @return 0 on success, non-zero on failure * */ -int usb_moded_module_cleanup(const char *module) +int modules_cleanup_module(const char *module) { - int retry = 0, failure; - - if(!strcmp(module, MODULE_NONE)) - goto END; - /* wait a bit for all components listening on dbus to clean up their act - usb_moded_sleep(2); */ - /* check if things were not reconnected in that timespan - if(get_usb_connection_state()) - return(0); - */ - - failure = usb_moded_unload_module(module); - - /* if we have MODULE_MASS_STORAGE it might be MODULE_FILE_STORAGE might - be loaded. So check and unload that one if unloading fails first time */ - if(failure && !strcmp(MODULE_MASS_STORAGE, module)) - failure = usb_moded_unload_module(MODULE_FILE_STORAGE); - - /* if it still failed it might be the mode has not been cleaned-up correctly, - so we clean up the mode to be sure */ - if(failure) - { - usb_moded_mode_cleanup(usb_moded_find_module()); - } - - while(failure) - { - /* module did not get unloaded. We will wait a bit and try again */ - usb_moded_sleep(1); - /* send the REALLY disconnect message */ - usb_moded_send_signal(USB_REALLY_DISCONNECT); - failure = usb_moded_unload_module(module); - log_debug("unloading failure = %d\n", failure); - if(!failure) - break; - if(!usb_moded_find_module()) - goto END; - retry++; - if(retry == 2) - break; - } - if(!failure) - log_info("Module %s unloaded successfully\n", module); - else - { - log_err("Module %s did not unload! Failing and going to undefined.\n", module); - return(1); - } + int retry = 0, failure; + + if(!strcmp(module, MODULE_NONE)) + goto END; + + if( !modules_in_use() ) { + log_warning("cleanup module %s - without module support", module); + goto END; + } + + /* wait a bit for all components listening on dbus to clean up their act + usbmoded_sleep(2); */ + /* check if things were not reconnected in that timespan + if(usbmoded_get_connection_state()) + return(0); + */ + + failure = modules_unload_module(module); + + /* if we have MODULE_MASS_STORAGE it might be MODULE_FILE_STORAGE might + be loaded. So check and unload that one if unloading fails first time */ + if(failure && !strcmp(MODULE_MASS_STORAGE, module)) + failure = modules_unload_module(MODULE_FILE_STORAGE); + + /* if it still failed it might be the mode has not been cleaned-up correctly, + so we clean up the mode to be sure */ + if(failure) + { + modesetting_cleanup(modules_get_loaded_module()); + } + + while(failure) + { + /* module did not get unloaded. We will wait a bit and try again */ + usbmoded_sleep(1); + /* send the REALLY disconnect message */ + umdbus_send_state_signal(USB_REALLY_DISCONNECT); + failure = modules_unload_module(module); + log_debug("unloading failure = %d\n", failure); + if(!failure) + break; + if(!modules_get_loaded_module()) + goto END; + retry++; + if(retry == 2) + break; + } + if(!failure) + log_info("Module %s unloaded successfully\n", module); + else + { + log_err("Module %s did not unload! Failing and going to undefined.\n", module); + return(1); + } END: - return(0); + return(0); } /** try to unload modules to support switching @@ -255,44 +385,51 @@ int usb_moded_module_cleanup(const char *module) * @return 0 on success, 1 on failure, 2 if hard clean-up failed */ -int usb_moded_module_switch_prepare (int force) +static int modules_prepare_for_module_switch (int force) { - const char *unload; - int ret = 1; - - unload = usb_moded_find_module(); - if(unload) - { - if(force) - ret = usb_moded_module_cleanup(unload); - else - ret = usb_moded_unload_module(unload); - } - if(ret && force) - return(2); - else - return(ret); + if( !modules_in_use() ) { + log_warning("prep for module switch force=%d - without module support", force); + return 0; + } + + const char *unload; + int ret = 1; + + unload = modules_get_loaded_module(); + if(unload) + { + if(force) + ret = modules_cleanup_module(unload); + else + ret = modules_unload_module(unload); + } + if(ret && force) + return(2); + return ret; } -/** check for loaded modules and clean-up if they are not for the chosen mode +/** check for loaded modules and clean-up if they are not for the chosen mode * * @param module_name module name to check for * */ -void check_module_state(const char *module_name) +void modules_check_module_state(const char *module_name) { - const char *module; + if( !modules_in_use() ) { + log_warning("check module %s state - without module support", module_name); + return; + } + + const char *module; - module = usb_moded_find_module(); - if(module != NULL) - { + module = modules_get_loaded_module(); + if(module != NULL) + { /* do nothing if the right module is already loaded */ - if(strcmp(usb_moded_find_module(), module_name) != 0) + if(strcmp(module, module_name) != 0) { - log_debug("%s not loaded, cleaning up\n", module_name); - usb_moded_module_switch_prepare(TRUE); + log_debug("%s not loaded, cleaning up\n", module_name); + modules_prepare_for_module_switch(TRUE); } - } + } } - - diff --git a/src/usb_moded-modules.h b/src/usb_moded-modules.h index f4df058..20f9cb5 100644 --- a/src/usb_moded-modules.h +++ b/src/usb_moded-modules.h @@ -1,52 +1,60 @@ /* - Copyright (C) 2010 Nokia Corporation. All rights reserved. - - Author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Thomas Perl + * Author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef USB_MODED_MODULES_H_ +# define USB_MODED_MODULES_H_ + +# include + +/* ========================================================================= * + * Constants + * ========================================================================= */ /* module name definitions */ -#define MODULE_MASS_STORAGE "g_mass_storage" -#define MODULE_FILE_STORAGE "g_file_storage" -#define MODULE_CHARGING "g_mass_storage luns=1 stall=0 removable=1" -#define MODULE_CHARGE_FALLBACK "g_file_storage luns=1 stall=0 removable=1" -#define MODULE_NONE "none" -#define MODULE_DEVELOPER "g_ether" -#define MODULE_MTP "g_ffs" - -/* module loading init */ -void usb_moded_module_ctx_init(void); - -/* module loading context cleanup */ -void usb_moded_module_ctx_cleanup(void); - -/* load module */ -int usb_moded_load_module(const char *module); - -/* unload module */ -int usb_moded_unload_module(const char *module); - -/* find which module is loaded */ -const char * usb_moded_find_module(void); - -/* clean up modules when usb gets disconnected */ -int usb_moded_module_cleanup(const char *module); - -/* clean up to allow for switching */ -int usb_moded_module_switch_prepare(int force); - -/* check if the correct module is loaded or not and switch if not */ -void check_module_state(const char *module_name); +# define MODULE_MASS_STORAGE "g_mass_storage" +# define MODULE_FILE_STORAGE "g_file_storage" +# define MODULE_CHARGING "g_mass_storage luns=1 stall=0 removable=1" +# define MODULE_CHARGE_FALLBACK "g_file_storage luns=1 stall=0 removable=1" +# define MODULE_NONE "none" +# define MODULE_DEVELOPER "g_ether" +# define MODULE_MTP "g_ffs" + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- modules -- */ + +bool modules_in_use (void); +bool modules_init (void); +void modules_quit (void); +int modules_load_module (const char *module); +int modules_unload_module (const char *module); +const char *modules_get_loaded_module (void); +int modules_cleanup_module (const char *module); +void modules_check_module_state(const char *module_name); + +#endif /* USB_MODED_MODULES_H_ */ diff --git a/src/usb_moded-network.c b/src/usb_moded-network.c index 72e2d82..539efb2 100644 --- a/src/usb_moded-network.c +++ b/src/usb_moded-network.c @@ -1,31 +1,33 @@ /* - @file usb-moded_network.c : (De)activates network depending on the network setting system. - - Copyright (C) 2011 Nokia Corporation. All rights reserved. - Copyright (C) 2012 Jolla. All rights reserved. - - @author: Philippe De Swert - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb-moded_network.c : (De)activates network depending on the network setting system. + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Copyright (C) 2012-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Marko Saukko + * @author: Slava Monich + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ /*============================================================================= */ -#define _GNU_SOURCE - #include #include #include @@ -38,222 +40,265 @@ #include "usb_moded.h" #include "usb_moded-network.h" -#include "usb_moded-config.h" +#include "usb_moded-config-private.h" #include "usb_moded-log.h" #include "usb_moded-modesetting.h" #if CONNMAN || OFONO -#include -#include -#include +# include +# include +# include #endif -#define UDHCP_CONFIG_PATH "/run/usb-moded/udhcpd.conf" -#define UDHCP_CONFIG_DIR "/run/usb-moded" -#define UDHCP_CONFIG_LINK "/etc/udhcpd.conf" +/* ========================================================================= * + * Constants + * ========================================================================= */ -static const char default_interface[] = "usb0"; +#define UDHCP_CONFIG_PATH "/run/usb-moded/udhcpd.conf" +#define UDHCP_CONFIG_DIR "/run/usb-moded" +#define UDHCP_CONFIG_LINK "/etc/udhcpd.conf" + +/* ========================================================================= * + * Types + * ========================================================================= */ /** IP forwarding configuration block */ typedef struct ipforward_data { - /** Address of primary DNS */ - char *dns1; - /** Address of secondary DNS */ - char *dns2; - /** Interface from which packets should be forwarded */ - char *nat_interface; + /** Address of primary DNS */ + char *dns1; + /** Address of secondary DNS */ + char *dns2; + /** Interface from which packets should be forwarded */ + char *nat_interface; }ipforward_data; +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- network -- */ + +static void network_free_ipforward_data (struct ipforward_data *ipforward); +static int network_check_interface (char *interface); +static char *network_get_interface (struct mode_list_elem *data); +static int network_set_usb_ip_forward (struct mode_list_elem *data, struct ipforward_data *ipforward); +static void network_clean_usb_ip_forward(void); +static int network_checklink (void); +static int network_write_udhcpd_conf (struct ipforward_data *ipforward, struct mode_list_elem *data); +int network_set_up_dhcpd (struct mode_list_elem *data); +int network_up (struct mode_list_elem *data); +int network_down (struct mode_list_elem *data); +int network_update (void); + +/* -- connman -- */ + #ifdef CONNMAN -static int connman_reset_state(void); +static gboolean connman_try_set_tethering (DBusConnection *connection, const char *path, gboolean on); +gboolean connman_set_tethering (const char *path, gboolean on); +static char *connman_parse_manager_reply (DBusMessage *reply, const char *req_service); +static int connman_fill_connection_data(DBusMessage *reply, struct ipforward_data *ipforward); +static int connman_set_cellular_online (DBusConnection *dbus_conn_connman, const char *service, int retry); +static int connman_wifi_power_control (DBusConnection *dbus_conn_connman, int on); +static int connman_get_connection_data (struct ipforward_data *ipforward); +static int connman_reset_state (void); #endif -static void free_ipforward_data (struct ipforward_data *ipforward) +/* ========================================================================= * + * Data + * ========================================================================= */ + +static const char default_interface[] = "usb0"; + +/* ========================================================================= * + * Functions + * ========================================================================= */ + +static void network_free_ipforward_data (struct ipforward_data *ipforward) { - if(ipforward) - { - if(ipforward->dns1) - free(ipforward->dns1); - if(ipforward->dns2) - free(ipforward->dns2); - if(ipforward->nat_interface) - free(ipforward->nat_interface); - free(ipforward); - } + if(ipforward) + { + if(ipforward->dns1) + free(ipforward->dns1); + if(ipforward->dns2) + free(ipforward->dns2); + if(ipforward->nat_interface) + free(ipforward->nat_interface); + free(ipforward); + } } /* This function checks if the configured interface exists */ -static int check_interface(char *interface) +static int network_check_interface(char *interface) { - int ret = -1; + int ret = -1; - if(interface) - { - char path[256]; - snprintf(path, sizeof path, "/sys/class/net/%s", interface); - ret = access(path, F_OK); - } + if(interface) + { + char path[256]; + snprintf(path, sizeof path, "/sys/class/net/%s", interface); + ret = access(path, F_OK); + } - return ret; + return ret; } -static char* get_interface(struct mode_list_elem *data) +static char* network_get_interface(struct mode_list_elem *data) { - (void)data; // FIXME: why is this passed in the 1st place? - - char *interface = 0; - char *setting = get_network_setting(NETWORK_INTERFACE_KEY); - - if(check_interface(setting) == 0) - { - /* Use the configured value */ - interface = setting, setting = 0; - } - else - { - /* Fall back to default value */ - interface = strdup(default_interface); - if(check_interface(interface) != 0) + (void)data; // FIXME: why is this passed in the 1st place? + + char *interface = 0; + char *setting = config_get_network_setting(NETWORK_INTERFACE_KEY); + + if(network_check_interface(setting) == 0) { - log_warning("Neither configured %s nor fallback %s interface exists." - " Check your config!", - setting ?: "NULL", - interface ?: "NULL"); - free(interface), interface = 0; + /* Use the configured value */ + interface = setting, setting = 0; + } + else + { + /* Fall back to default value */ + interface = strdup(default_interface); + if(network_check_interface(interface) != 0) + { + log_warning("Neither configured %s nor fallback %s interface exists." + " Check your config!", + setting ?: "NULL", + interface ?: "NULL"); + free(interface), interface = 0; + } } - } - log_debug("interface = %s\n", interface ?: "NULL"); - free(setting); - return interface; + log_debug("interface = %s\n", interface ?: "NULL"); + free(setting); + return interface; } /** * Turn on ip forwarding on the usb interface * @return: 0 on success, 1 on failure */ -static int set_usb_ip_forward(struct mode_list_elem *data, struct ipforward_data *ipforward) +static int network_set_usb_ip_forward(struct mode_list_elem *data, struct ipforward_data *ipforward) { - char *interface, *nat_interface; - char command[128]; - - interface = get_interface(data); - if(interface == NULL) - return(1); - nat_interface = get_network_setting(NETWORK_NAT_INTERFACE_KEY); - if((nat_interface == NULL) && (ipforward->nat_interface != NULL)) - nat_interface = strdup(ipforward->nat_interface); - else - { - log_debug("No nat interface available!\n"); + char *interface, *nat_interface; + char command[128]; + + interface = network_get_interface(data); + if(interface == NULL) + return(1); + nat_interface = config_get_network_setting(NETWORK_NAT_INTERFACE_KEY); + if((nat_interface == NULL) && (ipforward->nat_interface != NULL)) + nat_interface = strdup(ipforward->nat_interface); + else + { + log_debug("No nat interface available!\n"); #ifdef CONNMAN - /* in case the cellular did not come up we want to make sure wifi gets restored */ - connman_reset_state(); + /* in case the cellular did not come up we want to make sure wifi gets restored */ + connman_reset_state(); #endif - free(interface); - free(nat_interface); - return(1); - } - write_to_file("/proc/sys/net/ipv4/ip_forward", "1"); - snprintf(command, 128, "/sbin/iptables -t nat -A POSTROUTING -o %s -j MASQUERADE", nat_interface); - usb_moded_system(command); - - snprintf(command, 128, "/sbin/iptables -A FORWARD -i %s -o %s -m state --state RELATED,ESTABLISHED -j ACCEPT", nat_interface, interface); - usb_moded_system(command); - - snprintf(command, 128, "/sbin/iptables -A FORWARD -i %s -o %s -j ACCEPT", interface, nat_interface); - usb_moded_system(command); - - free(interface); - free(nat_interface); - log_debug("ipforwarding success!\n"); - return(0); + free(interface); + free(nat_interface); + return(1); + } + write_to_file("/proc/sys/net/ipv4/ip_forward", "1"); + snprintf(command, 128, "/sbin/iptables -t nat -A POSTROUTING -o %s -j MASQUERADE", nat_interface); + usbmoded_system(command); + + snprintf(command, 128, "/sbin/iptables -A FORWARD -i %s -o %s -m state --state RELATED,ESTABLISHED -j ACCEPT", nat_interface, interface); + usbmoded_system(command); + + snprintf(command, 128, "/sbin/iptables -A FORWARD -i %s -o %s -j ACCEPT", interface, nat_interface); + usbmoded_system(command); + + free(interface); + free(nat_interface); + log_debug("ipforwarding success!\n"); + return(0); } -/** +/** * Remove ip forward */ -static void clean_usb_ip_forward(void) +static void network_clean_usb_ip_forward(void) { #ifdef CONNMAN - connman_reset_state(); + connman_reset_state(); #endif - write_to_file("/proc/sys/net/ipv4/ip_forward", "0"); - usb_moded_system("/sbin/iptables -F FORWARD"); + write_to_file("/proc/sys/net/ipv4/ip_forward", "0"); + usbmoded_system("/sbin/iptables -F FORWARD"); } #ifdef OFONO /** * Get roaming data from ofono - * + * * @return : 1 if roaming, 0 when not (or when ofono is unavailable) */ static int get_roaming(void) { - int ret = 0, type; - DBusError error; - DBusMessage *msg = NULL, *reply; - DBusConnection *dbus_conn_ofono = NULL; - char *modem = NULL; - DBusMessageIter iter, subiter; - - dbus_error_init(&error); - - if( (dbus_conn_ofono = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) - { - log_err("Could not connect to dbus for ofono\n"); - } - - /* find the modem object path so can find out if it is roaming or not (one modem only is assumed) */ - if ((msg = dbus_message_new_method_call("org.ofono", "/", "org.ofono.Manager", "GetModems")) != NULL) - { + int ret = 0, type; + DBusError error; + DBusMessage *msg = NULL, *reply; + DBusConnection *dbus_conn_ofono = NULL; + char *modem = NULL; + DBusMessageIter iter, subiter; + + dbus_error_init(&error); + + if( (dbus_conn_ofono = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) + { + log_err("Could not connect to dbus for ofono\n"); + } + + /* find the modem object path so can find out if it is roaming or not (one modem only is assumed) */ + if ((msg = dbus_message_new_method_call("org.ofono", "/", "org.ofono.Manager", "GetModems")) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_ofono, msg, -1, NULL)) != NULL) { - dbus_message_iter_init(reply, &iter); - dbus_message_iter_recurse(&iter, &subiter); - iter = subiter; - dbus_message_iter_recurse(&iter, &subiter); - type = dbus_message_iter_get_arg_type(&subiter); - if(type == DBUS_TYPE_OBJECT_PATH) - { - dbus_message_iter_get_basic(&subiter, &modem); - log_debug("modem = %s\n", modem); - } - dbus_message_unref(reply); + dbus_message_iter_init(reply, &iter); + dbus_message_iter_recurse(&iter, &subiter); + iter = subiter; + dbus_message_iter_recurse(&iter, &subiter); + type = dbus_message_iter_get_arg_type(&subiter); + if(type == DBUS_TYPE_OBJECT_PATH) + { + dbus_message_iter_get_basic(&subiter, &modem); + log_debug("modem = %s\n", modem); + } + dbus_message_unref(reply); } dbus_message_unref(msg); - } - /* if modem found then we check roaming state */ - if(modem != NULL) - { - if ((msg = dbus_message_new_method_call("org.ofono", modem, "org.ofono.NetworkRegistration", "GetProperties")) != NULL) - { - if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_ofono, msg, -1, NULL)) != NULL) - { - dbus_message_iter_init(reply, &iter); - dbus_message_iter_recurse(&iter, &subiter); - iter = subiter; - dbus_message_iter_recurse(&iter, &subiter); - type = dbus_message_iter_get_arg_type(&subiter); - if(type == DBUS_TYPE_STRING) - { - dbus_message_iter_next (&subiter); - iter = subiter; - dbus_message_iter_recurse(&iter, &subiter); - dbus_message_iter_get_basic(&subiter, &modem); - log_debug("modem status = %s\n", modem); - } - } - dbus_message_unref(reply); - } + } + /* if modem found then we check roaming state */ + if(modem != NULL) + { + if ((msg = dbus_message_new_method_call("org.ofono", modem, "org.ofono.NetworkRegistration", "GetProperties")) != NULL) + { + if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_ofono, msg, -1, NULL)) != NULL) + { + dbus_message_iter_init(reply, &iter); + dbus_message_iter_recurse(&iter, &subiter); + iter = subiter; + dbus_message_iter_recurse(&iter, &subiter); + type = dbus_message_iter_get_arg_type(&subiter); + if(type == DBUS_TYPE_STRING) + { + dbus_message_iter_next (&subiter); + iter = subiter; + dbus_message_iter_recurse(&iter, &subiter); + dbus_message_iter_get_basic(&subiter, &modem); + log_debug("modem status = %s\n", modem); + } + } + dbus_message_unref(reply); + } dbus_message_unref(msg); - - if(!strcmp("roaming", modem)) - ret = 1; - } - return(ret); + if(!strcmp("roaming", modem)) + ret = 1; + } + + return(ret); } #endif @@ -263,253 +308,252 @@ static int get_roaming(void) */ static int resolv_conf_dns(struct ipforward_data *ipforward) { - FILE *resolv; - int i = 0, count = 0; - char *line = NULL, **tokens; - size_t len = 0; - ssize_t read; - - - resolv = fopen("/etc/resolv.conf", "r"); - if (resolv == NULL) - return(1); - - /* we don't expect more than 10 lines in /etc/resolv.conf */ - for (i=0; i < 10; i++) - { - read = getline(&line, &len, resolv); - if(read) - { - if(strstr(line, "nameserver") != NULL) - { - tokens = g_strsplit(line, " ", 2); - if(count == 0) - ipforward->dns1 = strdup(tokens[1]); - else - ipforward->dns2 = strdup(tokens[1]); - count++; - g_strfreev(tokens); - } - } - if(count == 2) - goto end; - } + FILE *resolv; + int i = 0, count = 0; + char *line = NULL, **tokens; + size_t len = 0; + ssize_t read; + + resolv = fopen("/etc/resolv.conf", "r"); + if (resolv == NULL) + return(1); + + /* we don't expect more than 10 lines in /etc/resolv.conf */ + for (i=0; i < 10; i++) + { + read = getline(&line, &len, resolv); + if(read) + { + if(strstr(line, "nameserver") != NULL) + { + tokens = g_strsplit(line, " ", 2); + if(count == 0) + ipforward->dns1 = strdup(tokens[1]); + else + ipforward->dns2 = strdup(tokens[1]); + count++; + g_strfreev(tokens); + } + } + if(count == 2) + goto end; + } end: - free(line); - fclose(resolv); - return(0); + free(line); + fclose(resolv); + return(0); } #endif -static int checklink(void) +static int network_checklink(void) { - int ret = -1; - char dest[sizeof(UDHCP_CONFIG_PATH)+1]; - size_t len = readlink(UDHCP_CONFIG_LINK, dest, sizeof(dest)-1); - - if (len > 0) - { - dest[len] = 0; - ret = strcmp(dest, UDHCP_CONFIG_PATH); - } - return(ret); + int ret = -1; + char dest[sizeof(UDHCP_CONFIG_PATH)+1]; + size_t len = readlink(UDHCP_CONFIG_LINK, dest, sizeof(dest)-1); + + if (len > 0) + { + dest[len] = 0; + ret = strcmp(dest, UDHCP_CONFIG_PATH); + } + return(ret); } -/** - * Write udhcpd.conf - * @ipforward : NULL if we want a simple config, otherwise include dns info etc... - */ -static int write_udhcpd_conf(struct ipforward_data *ipforward, struct mode_list_elem *data) +/** + * Write udhcpd.conf + * @ipforward : NULL if we want a simple config, otherwise include dns info etc... + */ +static int network_write_udhcpd_conf(struct ipforward_data *ipforward, struct mode_list_elem *data) { - FILE *conffile; - char *ip, *interface, *netmask; - char *ipstart, *ipend; - int dot = 0, i = 0, test; - struct stat st; - - /* /tmp and /run is often tmpfs, so we avoid writing to flash */ - mkdir(UDHCP_CONFIG_DIR, 0664); - conffile = fopen(UDHCP_CONFIG_PATH, "w"); - if(conffile == NULL) - { - log_debug("Error creating "UDHCP_CONFIG_PATH"!\n"); - return(1); - } - - interface = get_interface(data); - if(interface == NULL) - { - fclose(conffile); - return(1); - } - /* generate start and end ip based on the setting */ - ip = get_network_setting(NETWORK_IP_KEY); - ipstart = malloc(sizeof(char)*15); - ipend = malloc(sizeof(char)*15); - while(i < 15) - { + FILE *conffile; + char *ip, *interface, *netmask; + char *ipstart, *ipend; + int dot = 0, i = 0, test; + struct stat st; + + /* /tmp and /run is often tmpfs, so we avoid writing to flash */ + mkdir(UDHCP_CONFIG_DIR, 0664); + conffile = fopen(UDHCP_CONFIG_PATH, "w"); + if(conffile == NULL) + { + log_debug("Error creating "UDHCP_CONFIG_PATH"!\n"); + return(1); + } + + interface = network_get_interface(data); + if(interface == NULL) + { + fclose(conffile); + return(1); + } + /* generate start and end ip based on the setting */ + ip = config_get_network_setting(NETWORK_IP_KEY); + ipstart = malloc(sizeof(char)*15); + ipend = malloc(sizeof(char)*15); + while(i < 15) + { if(dot < 3) { - if(ip[i] == '.') - dot ++; - ipstart[i] = ip[i]; - ipend[i] = ip[i]; + if(ip[i] == '.') + dot ++; + ipstart[i] = ip[i]; + ipend[i] = ip[i]; } else { - ipstart[i] = '\0'; - ipend[i] = '\0'; - break; + ipstart[i] = '\0'; + ipend[i] = '\0'; + break; } i++; - } - strcat(ipstart,"1"); - strcat(ipend, "15"); - - netmask = get_network_setting(NETWORK_NETMASK_KEY); - - /* print all data in the file */ - fprintf(conffile, "start\t%s\n", ipstart); - fprintf(conffile, "end\t%s\n", ipend); - fprintf(conffile, "interface\t%s\n", interface); - fprintf(conffile, "option\tsubnet\t%s\n", netmask); - fprintf(conffile, "option\tlease\t3600\n"); - fprintf(conffile, "max_leases\t15\n"); - - if(ipforward != NULL) - { - if(!ipforward->dns1 || !ipforward->dns2) - { - log_debug("No dns info!"); - } - else - fprintf(conffile, "opt\tdns\t%s %s\n", ipforward->dns1, ipforward->dns2); - fprintf(conffile, "opt\trouter\t%s\n", ip); - } - - free(ipstart); - free(ipend); - free(ip); - free(interface); - free(netmask); - fclose(conffile); - - /* check if it is a symlink, if not remove and link, create the link if missing */ - test = lstat(UDHCP_CONFIG_LINK, &st); - /* if stat fails there is no file or link */ - if(test == -1) - goto link; - /* if it is not a link, or points to the wrong place we remove it */ - if(((st.st_mode & S_IFMT) != S_IFLNK) || checklink()) - { - unlink(UDHCP_CONFIG_LINK); - } - else - goto end; + } + strcat(ipstart,"1"); + strcat(ipend, "15"); + + netmask = config_get_network_setting(NETWORK_NETMASK_KEY); + + /* print all data in the file */ + fprintf(conffile, "start\t%s\n", ipstart); + fprintf(conffile, "end\t%s\n", ipend); + fprintf(conffile, "interface\t%s\n", interface); + fprintf(conffile, "option\tsubnet\t%s\n", netmask); + fprintf(conffile, "option\tlease\t3600\n"); + fprintf(conffile, "max_leases\t15\n"); + + if(ipforward != NULL) + { + if(!ipforward->dns1 || !ipforward->dns2) + { + log_debug("No dns info!"); + } + else + fprintf(conffile, "opt\tdns\t%s %s\n", ipforward->dns1, ipforward->dns2); + fprintf(conffile, "opt\trouter\t%s\n", ip); + } + + free(ipstart); + free(ipend); + free(ip); + free(interface); + free(netmask); + fclose(conffile); + + /* check if it is a symlink, if not remove and link, create the link if missing */ + test = lstat(UDHCP_CONFIG_LINK, &st); + /* if stat fails there is no file or link */ + if(test == -1) + goto link; + /* if it is not a link, or points to the wrong place we remove it */ + if(((st.st_mode & S_IFMT) != S_IFLNK) || network_checklink()) + { + unlink(UDHCP_CONFIG_LINK); + } + else + goto end; link: - if (symlink(UDHCP_CONFIG_PATH, UDHCP_CONFIG_LINK) == -1) - { - log_debug("Error creating link "UDHCP_CONFIG_LINK" -> "UDHCP_CONFIG_PATH": %m\n"); - unlink(UDHCP_CONFIG_PATH); - return(1); - } + if (symlink(UDHCP_CONFIG_PATH, UDHCP_CONFIG_LINK) == -1) + { + log_debug("Error creating link "UDHCP_CONFIG_LINK" -> "UDHCP_CONFIG_PATH": %m\n"); + unlink(UDHCP_CONFIG_PATH); + return(1); + } end: - log_debug(UDHCP_CONFIG_LINK" created\n"); - return(0); + log_debug(UDHCP_CONFIG_LINK" created\n"); + return(0); } #ifdef CONNMAN -#define CONNMAN_SERVICE "net.connman" -#define CONNMAN_TECH_INTERFACE "net.connman.Technology" -#define CONNMAN_ERROR_INTERFACE CONNMAN_SERVICE ".Error" -#define CONNMAN_ERROR_ALREADY_ENABLED CONNMAN_ERROR_INTERFACE ".AlreadyEnabled" -#define CONNMAN_ERROR_ALREADY_DISABLED CONNMAN_ERROR_INTERFACE ".AlreadyDisabled" +# define CONNMAN_SERVICE "net.connman" +# define CONNMAN_TECH_INTERFACE "net.connman.Technology" +# define CONNMAN_ERROR_INTERFACE CONNMAN_SERVICE ".Error" +# define CONNMAN_ERROR_ALREADY_ENABLED CONNMAN_ERROR_INTERFACE ".AlreadyEnabled" +# define CONNMAN_ERROR_ALREADY_DISABLED CONNMAN_ERROR_INTERFACE ".AlreadyDisabled" /* * Configures tethering for the specified connman technology. */ static gboolean connman_try_set_tethering(DBusConnection *connection, const char *path, gboolean on) { - gboolean ok = FALSE; - DBusMessage *message = dbus_message_new_method_call(CONNMAN_SERVICE, path, CONNMAN_TECH_INTERFACE, "SetProperty"); - if (message) - { - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter iter2; - DBusError error; - - const char* key = "Tethering"; - dbus_bool_t value = (on != FALSE); - - dbus_message_iter_init_append(message, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key); - dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING, &iter2); - dbus_message_iter_append_basic(&iter2, DBUS_TYPE_BOOLEAN, &value); - dbus_message_iter_close_container(&iter, &iter2); - - dbus_error_init(&error); - reply = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error); - dbus_message_unref(message); - if (reply) - { - log_debug("%s tethering %s", path, on ? "on" : "off"); - dbus_message_unref(reply); - ok = TRUE; - } - else - { - if ((on && !g_strcmp0(error.name, CONNMAN_ERROR_ALREADY_ENABLED)) || - (!on && (!g_strcmp0(error.name, CONNMAN_ERROR_ALREADY_DISABLED) || - !g_strcmp0(error.name, DBUS_ERROR_UNKNOWN_OBJECT)))) - { - ok = TRUE; - } - else - { - log_err("%s\n", error.message); - } - dbus_error_free(&error); - } - } - return ok; + gboolean ok = FALSE; + DBusMessage *message = dbus_message_new_method_call(CONNMAN_SERVICE, path, CONNMAN_TECH_INTERFACE, "SetProperty"); + if (message) + { + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter iter2; + DBusError error; + + const char* key = "Tethering"; + dbus_bool_t value = (on != FALSE); + + dbus_message_iter_init_append(message, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key); + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING, &iter2); + dbus_message_iter_append_basic(&iter2, DBUS_TYPE_BOOLEAN, &value); + dbus_message_iter_close_container(&iter, &iter2); + + dbus_error_init(&error); + reply = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error); + dbus_message_unref(message); + if (reply) + { + log_debug("%s tethering %s", path, on ? "on" : "off"); + dbus_message_unref(reply); + ok = TRUE; + } + else + { + if ((on && !g_strcmp0(error.name, CONNMAN_ERROR_ALREADY_ENABLED)) || + (!on && (!g_strcmp0(error.name, CONNMAN_ERROR_ALREADY_DISABLED) || + !g_strcmp0(error.name, DBUS_ERROR_UNKNOWN_OBJECT)))) + { + ok = TRUE; + } + else + { + log_err("%s\n", error.message); + } + dbus_error_free(&error); + } + } + return ok; } gboolean connman_set_tethering(const char *path, gboolean on) { - gboolean ok = FALSE; - DBusError error; - DBusConnection *connection; - - dbus_error_init(&error); - connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); - if (connection) - { - int i; - for (i=0; i<10; i++) - { - if (i>0) - { - usb_moded_msleep(200); - } - if (connman_try_set_tethering(connection, path, on)) - { - ok = TRUE; - break; - } - } - dbus_connection_unref(connection); - } - else - { - log_err("%s\n", error.message); - dbus_error_free (&error); - } - - return ok; + gboolean ok = FALSE; + DBusError error; + DBusConnection *connection; + + dbus_error_init(&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (connection) + { + int i; + for (i=0; i<10; i++) + { + if (i>0) + { + usbmoded_msleep(200); + } + if (connman_try_set_tethering(connection, path, on)) + { + ok = TRUE; + break; + } + } + dbus_connection_unref(connection); + } + else + { + log_err("%s\n", error.message); + dbus_error_free (&error); + } + + return ok; } /** @@ -517,438 +561,438 @@ gboolean connman_set_tethering(const char *path, gboolean on) */ static char * connman_parse_manager_reply(DBusMessage *reply, const char *req_service) { - DBusMessageIter iter, subiter, origiter; - int type; - char *service; - - dbus_message_iter_init(reply, &iter); - type = dbus_message_iter_get_arg_type(&iter); - dbus_message_iter_recurse(&iter, &subiter); - type = dbus_message_iter_get_arg_type(&subiter); - origiter = subiter; - iter = subiter; - while(type != DBUS_TYPE_INVALID) - { - - if(type == DBUS_TYPE_STRUCT) - { - origiter = iter; - dbus_message_iter_recurse(&iter, &subiter); - type = dbus_message_iter_get_arg_type(&subiter); - if(type == DBUS_TYPE_OBJECT_PATH) - { - dbus_message_iter_get_basic(&subiter, &service); - log_debug("service = %s\n", service); - if(strstr(service, req_service)) - { - log_debug("%s service found!\n", req_service); - return(strdup(service)); - } - } - } - dbus_message_iter_next(&origiter); - type = dbus_message_iter_get_arg_type(&origiter); - iter = origiter; - } - log_debug("end of list\n"); - return(0); + DBusMessageIter iter, subiter, origiter; + int type; + char *service; + + dbus_message_iter_init(reply, &iter); + type = dbus_message_iter_get_arg_type(&iter); + dbus_message_iter_recurse(&iter, &subiter); + type = dbus_message_iter_get_arg_type(&subiter); + origiter = subiter; + iter = subiter; + while(type != DBUS_TYPE_INVALID) + { + + if(type == DBUS_TYPE_STRUCT) + { + origiter = iter; + dbus_message_iter_recurse(&iter, &subiter); + type = dbus_message_iter_get_arg_type(&subiter); + if(type == DBUS_TYPE_OBJECT_PATH) + { + dbus_message_iter_get_basic(&subiter, &service); + log_debug("service = %s\n", service); + if(strstr(service, req_service)) + { + log_debug("%s service found!\n", req_service); + return(strdup(service)); + } + } + } + dbus_message_iter_next(&origiter); + type = dbus_message_iter_get_arg_type(&origiter); + iter = origiter; + } + log_debug("end of list\n"); + return(0); } static int connman_fill_connection_data(DBusMessage *reply, struct ipforward_data *ipforward) { - DBusMessageIter array_iter, dict_iter, inside_dict_iter, variant_iter; - DBusMessageIter sub_array_iter, string_iter; - int type, next; - char *string; - - log_debug("Filling in dns data\n"); - dbus_message_iter_init(reply, &array_iter); - type = dbus_message_iter_get_arg_type(&array_iter); - - dbus_message_iter_recurse(&array_iter, &dict_iter); - type = dbus_message_iter_get_arg_type(&dict_iter); - - while(type != DBUS_TYPE_INVALID) - { - dbus_message_iter_recurse(&dict_iter, &inside_dict_iter); - type = dbus_message_iter_get_arg_type(&inside_dict_iter); - if(type == DBUS_TYPE_STRING) - { - dbus_message_iter_get_basic(&inside_dict_iter, &string); - //log_debug("string = %s\n", string); - if(!strcmp(string, "Nameservers")) - { - //log_debug("Trying to get Nameservers"); - dbus_message_iter_next (&inside_dict_iter); - type = dbus_message_iter_get_arg_type(&inside_dict_iter); - dbus_message_iter_recurse(&inside_dict_iter, &variant_iter); - type = dbus_message_iter_get_arg_type(&variant_iter); - if(type == DBUS_TYPE_ARRAY) - { - dbus_message_iter_recurse(&variant_iter, &string_iter); - type = dbus_message_iter_get_arg_type(&string_iter); - if(type != DBUS_TYPE_STRING) - { - /* not online */ - return(1); - } - dbus_message_iter_get_basic(&string_iter, &string); - log_debug("dns = %s\n", string); - ipforward->dns1 = strdup(string); - next = dbus_message_iter_next (&string_iter); - if(!next) - { - log_debug("No secundary dns\n"); - /* FIXME: set the same dns for dns2 to avoid breakage */ - ipforward->dns2 = strdup(string); - return(0); - } - dbus_message_iter_get_basic(&string_iter, &string); - log_debug("dns2 = %s\n", string); - ipforward->dns2 = strdup(string); - return(0); - } - } - else if(!strcmp(string, "State")) - { - //log_debug("Trying to get online state"); - dbus_message_iter_next (&inside_dict_iter); - type = dbus_message_iter_get_arg_type(&inside_dict_iter); - dbus_message_iter_recurse(&inside_dict_iter, &variant_iter); - type = dbus_message_iter_get_arg_type(&variant_iter); - if(type == DBUS_TYPE_STRING) - { - dbus_message_iter_get_basic(&variant_iter, &string); - log_debug("Connection state = %s\n", string); - /* if cellular not online, connect it */ - if(strcmp(string, "online")) - { - /* if in ready state connection might be up anyway */ - if(strcmp(string, "ready")) - log_debug("Not online. Turning on cellular data connection.\n"); - return(1); - } - - } - - } - else if(!strcmp(string, "Ethernet")) - { - dbus_message_iter_next (&inside_dict_iter); - type = dbus_message_iter_get_arg_type(&inside_dict_iter); - dbus_message_iter_recurse(&inside_dict_iter, &variant_iter); - type = dbus_message_iter_get_arg_type(&variant_iter); - if(type == DBUS_TYPE_ARRAY) - { - dbus_message_iter_recurse(&variant_iter, &sub_array_iter); - /* we want the second dict */ - dbus_message_iter_next(&sub_array_iter); - /* we go into the dict and get the string */ - dbus_message_iter_recurse(&sub_array_iter, &variant_iter); - type = dbus_message_iter_get_arg_type(&variant_iter); - if(type == DBUS_TYPE_STRING) - { - dbus_message_iter_get_basic(&variant_iter, &string); - if(!strcmp(string, "Interface")) - { - /* get variant and iter down in it */ - dbus_message_iter_next(&variant_iter); - dbus_message_iter_recurse(&variant_iter, &string_iter); - dbus_message_iter_get_basic(&string_iter, &string); - log_debug("cellular interface = %s\n", string); - ipforward->nat_interface = strdup(string); - } - } - } - - } - } - dbus_message_iter_next (&dict_iter); - type = dbus_message_iter_get_arg_type(&dict_iter); - } - return(0); + DBusMessageIter array_iter, dict_iter, inside_dict_iter, variant_iter; + DBusMessageIter sub_array_iter, string_iter; + int type, next; + char *string; + + log_debug("Filling in dns data\n"); + dbus_message_iter_init(reply, &array_iter); + type = dbus_message_iter_get_arg_type(&array_iter); + + dbus_message_iter_recurse(&array_iter, &dict_iter); + type = dbus_message_iter_get_arg_type(&dict_iter); + + while(type != DBUS_TYPE_INVALID) + { + dbus_message_iter_recurse(&dict_iter, &inside_dict_iter); + type = dbus_message_iter_get_arg_type(&inside_dict_iter); + if(type == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&inside_dict_iter, &string); + //log_debug("string = %s\n", string); + if(!strcmp(string, "Nameservers")) + { + //log_debug("Trying to get Nameservers"); + dbus_message_iter_next (&inside_dict_iter); + type = dbus_message_iter_get_arg_type(&inside_dict_iter); + dbus_message_iter_recurse(&inside_dict_iter, &variant_iter); + type = dbus_message_iter_get_arg_type(&variant_iter); + if(type == DBUS_TYPE_ARRAY) + { + dbus_message_iter_recurse(&variant_iter, &string_iter); + type = dbus_message_iter_get_arg_type(&string_iter); + if(type != DBUS_TYPE_STRING) + { + /* not online */ + return(1); + } + dbus_message_iter_get_basic(&string_iter, &string); + log_debug("dns = %s\n", string); + ipforward->dns1 = strdup(string); + next = dbus_message_iter_next (&string_iter); + if(!next) + { + log_debug("No secundary dns\n"); + /* FIXME: set the same dns for dns2 to avoid breakage */ + ipforward->dns2 = strdup(string); + return(0); + } + dbus_message_iter_get_basic(&string_iter, &string); + log_debug("dns2 = %s\n", string); + ipforward->dns2 = strdup(string); + return(0); + } + } + else if(!strcmp(string, "State")) + { + //log_debug("Trying to get online state"); + dbus_message_iter_next (&inside_dict_iter); + type = dbus_message_iter_get_arg_type(&inside_dict_iter); + dbus_message_iter_recurse(&inside_dict_iter, &variant_iter); + type = dbus_message_iter_get_arg_type(&variant_iter); + if(type == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&variant_iter, &string); + log_debug("Connection state = %s\n", string); + /* if cellular not online, connect it */ + if(strcmp(string, "online")) + { + /* if in ready state connection might be up anyway */ + if(strcmp(string, "ready")) + log_debug("Not online. Turning on cellular data connection.\n"); + return(1); + } + + } + + } + else if(!strcmp(string, "Ethernet")) + { + dbus_message_iter_next (&inside_dict_iter); + type = dbus_message_iter_get_arg_type(&inside_dict_iter); + dbus_message_iter_recurse(&inside_dict_iter, &variant_iter); + type = dbus_message_iter_get_arg_type(&variant_iter); + if(type == DBUS_TYPE_ARRAY) + { + dbus_message_iter_recurse(&variant_iter, &sub_array_iter); + /* we want the second dict */ + dbus_message_iter_next(&sub_array_iter); + /* we go into the dict and get the string */ + dbus_message_iter_recurse(&sub_array_iter, &variant_iter); + type = dbus_message_iter_get_arg_type(&variant_iter); + if(type == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&variant_iter, &string); + if(!strcmp(string, "Interface")) + { + /* get variant and iter down in it */ + dbus_message_iter_next(&variant_iter); + dbus_message_iter_recurse(&variant_iter, &string_iter); + dbus_message_iter_get_basic(&string_iter, &string); + log_debug("cellular interface = %s\n", string); + ipforward->nat_interface = strdup(string); + } + } + } + + } + } + dbus_message_iter_next (&dict_iter); + type = dbus_message_iter_get_arg_type(&dict_iter); + } + return(0); } /** - * Turn on cellular connection if it is not on + * Turn on cellular connection if it is not on */ static int connman_set_cellular_online(DBusConnection *dbus_conn_connman, const char *service, int retry) { - DBusMessage *msg = NULL, *reply; - DBusError error; - int ret = 0; - char *wifi = NULL; - - dbus_error_init(&error); - - if(!retry) - { - if ((msg = dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "GetServices")) != NULL) - { - if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) - { - wifi = connman_parse_manager_reply(reply, "wifi"); - dbus_message_unref(reply); - } - dbus_message_unref(msg); - } - - if(wifi != NULL) - { - /* we must make sure that wifi is disconnected as sometimes cellular will not come up otherwise */ - if ((msg = dbus_message_new_method_call("net.connman", wifi, "net.connman.Service", "Disconnect")) != NULL) - { - /* we don't care for the reply, which is empty anyway if all goes well */ - ret = !dbus_connection_send(dbus_conn_connman, msg, NULL); - dbus_connection_flush(dbus_conn_connman); - dbus_message_unref(msg); - } - } - } - if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "Connect")) != NULL) - { - /* we don't care for the reply, which is empty anyway if all goes well */ + DBusMessage *msg = NULL, *reply; + DBusError error; + int ret = 0; + char *wifi = NULL; + + dbus_error_init(&error); + + if(!retry) + { + if ((msg = dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "GetServices")) != NULL) + { + if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) + { + wifi = connman_parse_manager_reply(reply, "wifi"); + dbus_message_unref(reply); + } + dbus_message_unref(msg); + } + + if(wifi != NULL) + { + /* we must make sure that wifi is disconnected as sometimes cellular will not come up otherwise */ + if ((msg = dbus_message_new_method_call("net.connman", wifi, "net.connman.Service", "Disconnect")) != NULL) + { + /* we don't care for the reply, which is empty anyway if all goes well */ + ret = !dbus_connection_send(dbus_conn_connman, msg, NULL); + dbus_connection_flush(dbus_conn_connman); + dbus_message_unref(msg); + } + } + } + if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "Connect")) != NULL) + { + /* we don't care for the reply, which is empty anyway if all goes well */ ret = !dbus_connection_send(dbus_conn_connman, msg, NULL); - /* sleep for the connection to come up */ - usb_moded_sleep(5); - /* make sure the message is sent before cleaning up and closing the connection */ - dbus_connection_flush(dbus_conn_connman); + /* sleep for the connection to come up */ + usbmoded_sleep(5); + /* make sure the message is sent before cleaning up and closing the connection */ + dbus_connection_flush(dbus_conn_connman); dbus_message_unref(msg); - } + } - if(wifi) - free(wifi); + if(wifi) + free(wifi); - return(ret); + return(ret); } /* * Turn on or off the wifi service * wifistatus static variable tracks the state so we do not turn on the wifi if it was off * -*/ + */ static int connman_wifi_power_control(DBusConnection *dbus_conn_connman, int on) { - static int wifistatus = 0; - int type = 0; - char *string; - DBusMessage *msg = NULL, *reply; - //DBusError error; - DBusMessageIter array_iter, dict_iter, inside_dict_iter, variant_iter; - - if(!on) - { - /* check wifi status only before turning off */ - if ((msg = dbus_message_new_method_call("net.connman", "/net/connman/technology/wifi", "net.connman.Technology", "GetProperties")) != NULL) - { - if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) - { - dbus_message_iter_init(reply, &array_iter); - - dbus_message_iter_recurse(&array_iter, &dict_iter); - type = dbus_message_iter_get_arg_type(&dict_iter); - - while(type != DBUS_TYPE_INVALID) - { - dbus_message_iter_recurse(&dict_iter, &inside_dict_iter); - type = dbus_message_iter_get_arg_type(&inside_dict_iter); - if(type == DBUS_TYPE_STRING) - { - dbus_message_iter_get_basic(&inside_dict_iter, &string); + static int wifistatus = 0; + int type = 0; + char *string; + DBusMessage *msg = NULL, *reply; + //DBusError error; + DBusMessageIter array_iter, dict_iter, inside_dict_iter, variant_iter; + + if(!on) + { + /* check wifi status only before turning off */ + if ((msg = dbus_message_new_method_call("net.connman", "/net/connman/technology/wifi", "net.connman.Technology", "GetProperties")) != NULL) + { + if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) + { + dbus_message_iter_init(reply, &array_iter); + + dbus_message_iter_recurse(&array_iter, &dict_iter); + type = dbus_message_iter_get_arg_type(&dict_iter); + + while(type != DBUS_TYPE_INVALID) + { + dbus_message_iter_recurse(&dict_iter, &inside_dict_iter); + type = dbus_message_iter_get_arg_type(&inside_dict_iter); + if(type == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic(&inside_dict_iter, &string); log_debug("string = %s\n", string); if(!strcmp(string, "Powered")) { - dbus_message_iter_next (&inside_dict_iter); - type = dbus_message_iter_get_arg_type(&inside_dict_iter); - dbus_message_iter_recurse(&inside_dict_iter, &variant_iter); - type = dbus_message_iter_get_arg_type(&variant_iter); - if(type == DBUS_TYPE_BOOLEAN) - { - dbus_message_iter_get_basic(&variant_iter, &wifistatus); - log_debug("Powered state = %d\n", wifistatus); - } - break; - } - } - dbus_message_iter_next (&dict_iter); - type = dbus_message_iter_get_arg_type(&dict_iter); - } - dbus_message_unref(reply); - } - dbus_message_unref(msg); - } - } - - /* /net/connman/technology/wifi net.connman.Technology.SetProperty string:Powered variant:boolean:false */ - if(wifistatus && !on) - usb_moded_system("/bin/dbus-send --print-reply --type=method_call --system --dest=net.connman /net/connman/technology/wifi net.connman.Technology.SetProperty string:Powered variant:boolean:false"); - if(wifistatus && on) - /* turn on wifi after tethering is over and wifi was on before */ - usb_moded_system("/bin/dbus-send --print-reply --type=method_call --system --dest=net.connman /net/connman/technology/wifi net.connman.Technology.SetProperty string:Powered variant:boolean:true"); - - return(0); + dbus_message_iter_next (&inside_dict_iter); + type = dbus_message_iter_get_arg_type(&inside_dict_iter); + dbus_message_iter_recurse(&inside_dict_iter, &variant_iter); + type = dbus_message_iter_get_arg_type(&variant_iter); + if(type == DBUS_TYPE_BOOLEAN) + { + dbus_message_iter_get_basic(&variant_iter, &wifistatus); + log_debug("Powered state = %d\n", wifistatus); + } + break; + } + } + dbus_message_iter_next (&dict_iter); + type = dbus_message_iter_get_arg_type(&dict_iter); + } + dbus_message_unref(reply); + } + dbus_message_unref(msg); + } + } + + /* /net/connman/technology/wifi net.connman.Technology.SetProperty string:Powered variant:boolean:false */ + if(wifistatus && !on) + usbmoded_system("/bin/dbus-send --print-reply --type=method_call --system --dest=net.connman /net/connman/technology/wifi net.connman.Technology.SetProperty string:Powered variant:boolean:false"); + if(wifistatus && on) + /* turn on wifi after tethering is over and wifi was on before */ + usbmoded_system("/bin/dbus-send --print-reply --type=method_call --system --dest=net.connman /net/connman/technology/wifi net.connman.Technology.SetProperty string:Powered variant:boolean:true"); + + return(0); } static int connman_get_connection_data(struct ipforward_data *ipforward) { - DBusConnection *dbus_conn_connman = NULL; - DBusMessage *msg = NULL, *reply = NULL; - DBusError error; - char *service = NULL; - int online = 0, ret = 0; + DBusConnection *dbus_conn_connman = NULL; + DBusMessage *msg = NULL, *reply = NULL; + DBusError error; + char *service = NULL; + int online = 0, ret = 0; - dbus_error_init(&error); + dbus_error_init(&error); - if( (dbus_conn_connman = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) - { - log_err("Could not connect to dbus for connman\n"); - } + if( (dbus_conn_connman = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) + { + log_err("Could not connect to dbus for connman\n"); + } - /* turn off wifi in preparation for cellular connection if needed */ - connman_wifi_power_control(dbus_conn_connman, 0); + /* turn off wifi in preparation for cellular connection if needed */ + connman_wifi_power_control(dbus_conn_connman, 0); - /* get list of services so we can find out which one is the cellular */ - if ((msg = dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "GetServices")) != NULL) - { + /* get list of services so we can find out which one is the cellular */ + if ((msg = dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "GetServices")) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) { - service = connman_parse_manager_reply(reply, "cellular"); + service = connman_parse_manager_reply(reply, "cellular"); dbus_message_unref(reply); } dbus_message_unref(msg); - } - - log_debug("service = %s\n", service); - if(service) - { + } + + log_debug("service = %s\n", service); + if(service) + { try_again: - if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "GetProperties")) != NULL) - { - if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) - { - if(connman_fill_connection_data(reply, ipforward)) - { - if(!connman_set_cellular_online(dbus_conn_connman, service, online) && !online) - { - online = 1; - goto try_again; - } - else - { - log_debug("Cannot connect to cellular data\n"); - ret = 1; - } - } - dbus_message_unref(reply); - } - dbus_message_unref(msg); - } - } - dbus_connection_unref(dbus_conn_connman); - dbus_error_free(&error); - free(service); - return(ret); + if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "GetProperties")) != NULL) + { + if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) + { + if(connman_fill_connection_data(reply, ipforward)) + { + if(!connman_set_cellular_online(dbus_conn_connman, service, online) && !online) + { + online = 1; + goto try_again; + } + else + { + log_debug("Cannot connect to cellular data\n"); + ret = 1; + } + } + dbus_message_unref(reply); + } + dbus_message_unref(msg); + } + } + dbus_connection_unref(dbus_conn_connman); + dbus_error_free(&error); + free(service); + return(ret); } static int connman_reset_state(void) { - DBusConnection *dbus_conn_connman = NULL; - DBusError error; + DBusConnection *dbus_conn_connman = NULL; + DBusError error; - dbus_error_init(&error); + dbus_error_init(&error); - if( (dbus_conn_connman = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) - { - log_err("Could not connect to dbus for connman\n"); - } + if( (dbus_conn_connman = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) + { + log_err("Could not connect to dbus for connman\n"); + } - /* make sure connman turns wifi back on when we disconnect */ - log_debug("Turning wifi back on\n"); - connman_wifi_power_control(dbus_conn_connman, 1); - dbus_connection_unref(dbus_conn_connman); - dbus_error_free(&error); + /* make sure connman turns wifi back on when we disconnect */ + log_debug("Turning wifi back on\n"); + connman_wifi_power_control(dbus_conn_connman, 1); + dbus_connection_unref(dbus_conn_connman); + dbus_error_free(&error); - return(0); + return(0); } #endif /* CONNMAN */ -/** +/** * Write out /etc/udhcpd.conf conf so the config is available when it gets started */ -int usb_network_set_up_dhcpd(struct mode_list_elem *data) +int network_set_up_dhcpd(struct mode_list_elem *data) { - struct ipforward_data *ipforward = NULL; - int ret = 1; + struct ipforward_data *ipforward = NULL; + int ret = 1; - /* Set up nat info only if it is required */ - if(data->nat) - { + /* Set up nat info only if it is required */ + if(data->nat) + { #ifdef OFONO - /* check if we are roaming or not */ - if(get_roaming()) - { - /* get permission to use roaming */ - if(is_roaming_not_allowed()) - goto end; - } + /* check if we are roaming or not */ + if(get_roaming()) + { + /* get permission to use roaming */ + if(config_is_roaming_not_allowed()) + goto end; + } #endif /* OFONO */ - ipforward = malloc(sizeof(struct ipforward_data)); - memset(ipforward, 0, sizeof(struct ipforward_data)); + ipforward = malloc(sizeof(struct ipforward_data)); + memset(ipforward, 0, sizeof(struct ipforward_data)); #ifdef CONNMAN - if(connman_get_connection_data(ipforward)) - { - log_debug("data connection not available!\n"); - /* TODO: send a message to the UI */ - goto end; - } + if(connman_get_connection_data(ipforward)) + { + log_debug("data connection not available!\n"); + /* TODO: send a message to the UI */ + goto end; + } #else - if(resolv_conf_dns(ipforward)) - goto end; + if(resolv_conf_dns(ipforward)) + goto end; #endif /*CONNMAN */ - } - /* ipforward can be NULL here, which is expected and handled in this function */ - ret = write_udhcpd_conf(ipforward, data); + } + /* ipforward can be NULL here, which is expected and handled in this function */ + ret = network_write_udhcpd_conf(ipforward, data); - if(data->nat) - ret = set_usb_ip_forward(data, ipforward); + if(data->nat) + ret = network_set_usb_ip_forward(data, ipforward); end: - /* the function checks if ipforward is NULL or not */ - free_ipforward_data(ipforward); - return(ret); + /* the function checks if ipforward is NULL or not */ + network_free_ipforward_data(ipforward); + return(ret); } #if CONNMAN_WORKS_BETTER static int append_variant(DBusMessageIter *iter, const char *property, - int type, const char *value) + int type, const char *value) { - DBusMessageIter variant; - const char *type_str; + DBusMessageIter variant; + const char *type_str; + + switch(type) { + case DBUS_TYPE_BOOLEAN: + type_str = DBUS_TYPE_BOOLEAN_AS_STRING; + break; + case DBUS_TYPE_BYTE: + type_str = DBUS_TYPE_BYTE_AS_STRING; + break; + case DBUS_TYPE_STRING: + type_str = DBUS_TYPE_STRING_AS_STRING; + break; + case DBUS_TYPE_INT32: + type_str = DBUS_TYPE_INT32_AS_STRING; + break; + default: + return -EOPNOTSUPP; + } - switch(type) { - case DBUS_TYPE_BOOLEAN: - type_str = DBUS_TYPE_BOOLEAN_AS_STRING; - break; - case DBUS_TYPE_BYTE: - type_str = DBUS_TYPE_BYTE_AS_STRING; - break; - case DBUS_TYPE_STRING: - type_str = DBUS_TYPE_STRING_AS_STRING; - break; - case DBUS_TYPE_INT32: - type_str = DBUS_TYPE_INT32_AS_STRING; - break; - default: - return -EOPNOTSUPP; - } - - dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property); - dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type_str, - &variant); - dbus_message_iter_append_basic(&variant, type, value); - dbus_message_iter_close_container(iter, &variant); - - return 0; + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property); + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type_str, + &variant); + dbus_message_iter_append_basic(&variant, type, value); + dbus_message_iter_close_container(iter, &variant); + + return 0; } #endif /* CONNMAN */ @@ -956,165 +1000,165 @@ static int append_variant(DBusMessageIter *iter, const char *property, * Activate the network interface * */ -int usb_network_up(struct mode_list_elem *data) +int network_up(struct mode_list_elem *data) { - char *ip = NULL, *gateway = NULL; - int ret = -1; + char *ip = NULL, *gateway = NULL; + int ret = -1; #if CONNMAN_WORKS_BETTER - DBusConnection *dbus_conn_connman = NULL; - DBusMessage *msg = NULL, *reply = NULL; - DBusMessageIter iter, variant, dict; - DBusMessageIter msg_iter; - DBusMessageIter dict_entry; - DBusError error; - const char *service = NULL; - - /* make sure connman will recognize the gadget interface NEEDED? */ - //usb_moded_system("/bin/dbus-send --print-reply --type=method_call --system --dest=net.connman /net/connman/technology/gadget net.connman.Technology.SetProperty string:Powered variant:boolean:true"); - //usb_moded_system("/sbin/ifconfig rndis0 up"); - - log_debug("waiting for connman to pick up interface\n"); - usb_moded_sleep(1); - dbus_error_init(&error); - - if( (dbus_conn_connman = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) - { - log_err("Could not connect to dbus for connman\n"); - } - - /* get list of services so we can find out which one is the usb gadget */ - if ((msg = dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "GetServices")) != NULL) - { + DBusConnection *dbus_conn_connman = NULL; + DBusMessage *msg = NULL, *reply = NULL; + DBusMessageIter iter, variant, dict; + DBusMessageIter msg_iter; + DBusMessageIter dict_entry; + DBusError error; + const char *service = NULL; + + /* make sure connman will recognize the gadget interface NEEDED? */ + //usbmoded_system("/bin/dbus-send --print-reply --type=method_call --system --dest=net.connman /net/connman/technology/gadget net.connman.Technology.SetProperty string:Powered variant:boolean:true"); + //usbmoded_system("/sbin/ifconfig rndis0 up"); + + log_debug("waiting for connman to pick up interface\n"); + usbmoded_sleep(1); + dbus_error_init(&error); + + if( (dbus_conn_connman = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) + { + log_err("Could not connect to dbus for connman\n"); + } + + /* get list of services so we can find out which one is the usb gadget */ + if ((msg = dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "GetServices")) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) { service = connman_parse_manager_reply(reply, "gadget"); dbus_message_unref(reply); } dbus_message_unref(msg); - } - - if(service == NULL) - return(1); - log_debug("gadget = %s\n", service); - - /* now we need to configure the connection */ - if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "SetProperty")) != NULL) - { - log_debug("iter init\n"); - dbus_message_iter_init_append(msg, &msg_iter); - log_debug("iter append\n"); - // TODO: crashes here, need to rework this whole bit, connman dbus is hell - dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, "IPv4.Configuration"); - log_debug("iter open container\n"); - dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, - DBUS_TYPE_ARRAY_AS_STRING - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &variant); - - log_debug("iter open container 2\n"); - dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &dict); - - log_debug("Set Method\n"); - dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry); - append_variant(&dict_entry, "Method", DBUS_TYPE_STRING, "manual"); - dbus_message_iter_close_container(&dict, &dict_entry); - - log_debug("Set ip\n"); - ip = get_network_settings(NETWORK_IP_KEY); - dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry); - append_variant(&dict_entry, "Address", DBUS_TYPE_STRING, ip); - dbus_message_iter_close_container(&dict, &dict_entry); - - log_debug("Set netmask\n"); - dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry); - append_variant(&dict_entry, "Netmask", DBUS_TYPE_STRING, "255.255.255.0"); - dbus_message_iter_close_container(&dict, &dict_entry); - - log_debug("set gateway\n"); - gateway = get_network_setting(NETWORK_GATEWAY_KEY); - if(gateway) - { - dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry); - append_variant(&dict_entry, "Gateway", DBUS_TYPE_STRING, gateway); - dbus_message_iter_close_container(&dict, &dict_entry); - } - dbus_message_iter_close_container(&variant, &dict); - dbus_message_iter_close_container(&msg_iter, &variant); - } - - log_debug("Connect gadget\n"); - /* Finally we can bring it up */ - if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "Connect")) != NULL) - { + } + + if(service == NULL) + return(1); + log_debug("gadget = %s\n", service); + + /* now we need to configure the connection */ + if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "SetProperty")) != NULL) + { + log_debug("iter init\n"); + dbus_message_iter_init_append(msg, &msg_iter); + log_debug("iter append\n"); + // TODO: crashes here, need to rework this whole bit, connman dbus is hell + dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, "IPv4.Configuration"); + log_debug("iter open container\n"); + dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &variant); + + log_debug("iter open container 2\n"); + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &dict); + + log_debug("Set Method\n"); + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry); + append_variant(&dict_entry, "Method", DBUS_TYPE_STRING, "manual"); + dbus_message_iter_close_container(&dict, &dict_entry); + + log_debug("Set ip\n"); + ip = get_network_settings(NETWORK_IP_KEY); + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry); + append_variant(&dict_entry, "Address", DBUS_TYPE_STRING, ip); + dbus_message_iter_close_container(&dict, &dict_entry); + + log_debug("Set netmask\n"); + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry); + append_variant(&dict_entry, "Netmask", DBUS_TYPE_STRING, "255.255.255.0"); + dbus_message_iter_close_container(&dict, &dict_entry); + + log_debug("set gateway\n"); + gateway = config_get_network_setting(NETWORK_GATEWAY_KEY); + if(gateway) + { + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry); + append_variant(&dict_entry, "Gateway", DBUS_TYPE_STRING, gateway); + dbus_message_iter_close_container(&dict, &dict_entry); + } + dbus_message_iter_close_container(&variant, &dict); + dbus_message_iter_close_container(&msg_iter, &variant); + } + + log_debug("Connect gadget\n"); + /* Finally we can bring it up */ + if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "Connect")) != NULL) + { /* we don't care for the reply, which is empty anyway if all goes well */ ret = !dbus_connection_send(dbus_conn_connman, msg, NULL); /* make sure the message is sent before cleaning up and closing the connection */ dbus_connection_flush(dbus_conn_connman); dbus_message_unref(msg); - } - dbus_connection_unref(dbus_conn_connman); - dbus_error_free(&error); - free(service); - if(ip) - free(ip); - if(gateway) - free(gateway); - return(ret); + } + dbus_connection_unref(dbus_conn_connman); + dbus_error_free(&error); + free(service); + if(ip) + free(ip); + if(gateway) + free(gateway); + return(ret); #else - char command[128]; - char *interface; - char *netmask; - - interface = get_interface(data); - - if(interface == NULL) - return(1); - - /* interface found, so we can get all the rest */ - ip = get_network_setting(NETWORK_IP_KEY); - gateway = get_network_setting(NETWORK_GATEWAY_KEY); - netmask = get_network_setting(NETWORK_NETMASK_KEY); - - if(!strcmp(ip, "dhcp")) - { - sprintf(command, "dhclient -d %s\n", interface); - ret = usb_moded_system(command); - if(ret != 0) - { - sprintf(command, "udhcpc -i %s\n", interface); - usb_moded_system(command); - } - - } - else - { - sprintf(command, "ifconfig %s %s %s\n", interface, ip, netmask); - usb_moded_system(command); - } - - /* TODO: Check first if there is a gateway set */ - if(gateway) - { - sprintf(command, "route add default gw %s\n", gateway); - usb_moded_system(command); - } - - free(interface); - free(gateway); - free(ip); - free(netmask); - - return(0); + char command[128]; + char *interface; + char *netmask; + + interface = network_get_interface(data); + + if(interface == NULL) + return(1); + + /* interface found, so we can get all the rest */ + ip = config_get_network_setting(NETWORK_IP_KEY); + gateway = config_get_network_setting(NETWORK_GATEWAY_KEY); + netmask = config_get_network_setting(NETWORK_NETMASK_KEY); + + if(!strcmp(ip, "dhcp")) + { + sprintf(command, "dhclient -d %s\n", interface); + ret = usbmoded_system(command); + if(ret != 0) + { + sprintf(command, "udhcpc -i %s\n", interface); + usbmoded_system(command); + } + + } + else + { + sprintf(command, "ifconfig %s %s %s\n", interface, ip, netmask); + usbmoded_system(command); + } + + /* TODO: Check first if there is a gateway set */ + if(gateway) + { + sprintf(command, "route add default gw %s\n", gateway); + usbmoded_system(command); + } + + free(interface); + free(gateway); + free(ip); + free(netmask); + + return(0); #endif /* CONNMAN */ } @@ -1122,95 +1166,95 @@ int usb_network_up(struct mode_list_elem *data) * Deactivate the network interface * */ -int usb_network_down(struct mode_list_elem *data) +int network_down(struct mode_list_elem *data) { #if CONNMAN_WORKS_BETTER - DBusConnection *dbus_conn_connman = NULL; - DBusMessage *msg = NULL, *reply = NULL; - DBusError error; - char *service = NULL; - int ret = -1; - - dbus_error_init(&error); - - if( (dbus_conn_connman = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) - { - log_err("Could not connect to dbus for connman\n"); - } - - /* get list of services so we can find out which one is the usb gadget */ - if ((msg = dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "GetServices")) != NULL) - { + DBusConnection *dbus_conn_connman = NULL; + DBusMessage *msg = NULL, *reply = NULL; + DBusError error; + char *service = NULL; + int ret = -1; + + dbus_error_init(&error); + + if( (dbus_conn_connman = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) + { + log_err("Could not connect to dbus for connman\n"); + } + + /* get list of services so we can find out which one is the usb gadget */ + if ((msg = dbus_message_new_method_call("net.connman", "/", "net.connman.Manager", "GetServices")) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_connman, msg, -1, NULL)) != NULL) { service = connman_parse_manager_reply(reply, "gadget"); dbus_message_unref(reply); } dbus_message_unref(msg); - } + } - if(service == NULL) - return(1); + if(service == NULL) + return(1); - /* Finally we can shut it down */ - if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "Disconnect")) != NULL) - { + /* Finally we can shut it down */ + if ((msg = dbus_message_new_method_call("net.connman", service, "net.connman.Service", "Disconnect")) != NULL) + { /* we don't care for the reply, which is empty anyway if all goes well */ ret = !dbus_connection_send(dbus_conn_connman, msg, NULL); /* make sure the message is sent before cleaning up and closing the connection */ dbus_connection_flush(dbus_conn_connman); dbus_message_unref(msg); - } - free(service); + } + free(service); - /* dhcp server shutdown happens on disconnect automatically */ - if(data->nat) - clean_usb_ip_forward(); - dbus_error_free(&error); + /* dhcp server shutdown happens on disconnect automatically */ + if(data->nat) + network_clean_usb_ip_forward(); + dbus_error_free(&error); - return(ret); + return(ret); #else - char *interface; - char command[128]; + char *interface; + char command[128]; + + interface = network_get_interface(data); + if(interface == NULL) + return(0); - interface = get_interface(data); - if(interface == NULL) - return(0); + sprintf(command, "ifconfig %s down\n", interface); + usbmoded_system(command); - sprintf(command, "ifconfig %s down\n", interface); - usb_moded_system(command); + /* dhcp client shutdown happens on disconnect automatically */ + if(data->nat) + network_clean_usb_ip_forward(); - /* dhcp client shutdown happens on disconnect automatically */ - if(data->nat) - clean_usb_ip_forward(); + free(interface); - free(interface); - - return(0); + return(0); #endif /* CONNMAN_IS_EVER_FIXED_FOR_USB */ } /** * Update the network interface with the new setting if connected. - * -*/ -int usb_network_update(void) + * + */ +int network_update(void) { - struct mode_list_elem * data; - - if(!get_usb_connection_state()) - return(0); - - data = get_usb_mode_data(); - if(data == NULL) - return(0); - if(data->network) - { - usb_network_down(data); - usb_network_up(data); - return(0); - } - else - return(0); + struct mode_list_elem * data; + + if(!usbmoded_get_connection_state()) + return(0); + + data = usbmoded_get_usb_mode_data(); + if(data == NULL) + return(0); + if(data->network) + { + network_down(data); + network_up(data); + return(0); + } + else + return(0); } diff --git a/src/usb_moded-network.h b/src/usb_moded-network.h index 3be8f4c..efe3b42 100644 --- a/src/usb_moded-network.h +++ b/src/usb_moded-network.h @@ -1,37 +1,49 @@ /* - Copyright (C) 2011 Nokia Corporation. All rights reserved. - - Author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA - - usb-moded_network : (De)activates network depending on the network setting system. -*/ - -#ifndef USB_MODED_NETWORK_H_ -#define USB_MODED_NETWORK_H_ - -#include "usb_moded-dyn-config.h" + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * Author: Philippe De Swert + * Author: Philippe De Swert + * Author: Slava Monich + * Author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * usb-moded_network : (De)activates network depending on the network setting system. + */ + +#ifndef USB_MODED_NETWORK_H_ +# define USB_MODED_NETWORK_H_ + +# include "usb_moded-dyn-config.h" + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- connman -- */ + +# ifdef CONNMAN +gboolean connman_set_tethering(const char *path, gboolean on); +# endif -int usb_network_up(struct mode_list_elem *data); -int usb_network_down(struct mode_list_elem *data); -int usb_network_update(void); -int usb_network_set_up_dhcpd(struct mode_list_elem *data); +/* -- network -- */ -#ifdef CONNMAN -gboolean connman_set_tethering(const char *path, gboolean on); -#endif +int network_set_up_dhcpd(struct mode_list_elem *data); +int network_up (struct mode_list_elem *data); +int network_down (struct mode_list_elem *data); +int network_update (void); #endif /* USB_MODED_NETWORK_H_ */ diff --git a/src/usb_moded-ssu.c b/src/usb_moded-ssu.c index 837a020..7f62b2a 100644 --- a/src/usb_moded-ssu.c +++ b/src/usb_moded-ssu.c @@ -1,36 +1,55 @@ /** - @file usb_moded-ssu.c - - Copyright (C) 2016 Jolla. All rights reserved. - - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-ssu.c + * + * Copyright (C) 2016-2018 Jolla. All rights reserved. + * + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include #include "usb_moded-ssu.h" #include "usb_moded-log.h" +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- ssu -- */ + +static void ssu_free_handle (void); +static ssusysinfo_t *ssu_get_handle (void); +gchar *ssu_get_manufacturer_name(void); +gchar *ssu_get_product_name (void); + +/* ========================================================================= * + * Data + * ========================================================================= */ + /** Cached ssu-sysinfo handle */ static ssusysinfo_t *ssu_instance = 0; /** Flag for ssu-sysinfo instance has been initialized */ static gboolean ssu_intialized = FALSE; +/* ========================================================================= * + * Functions + * ========================================================================= */ + /** Atexit callback for releasing cached ssu-sysinfo handle */ static void ssu_free_handle(void) { diff --git a/src/usb_moded-ssu.h b/src/usb_moded-ssu.h index 0eef2c2..77080e8 100644 --- a/src/usb_moded-ssu.h +++ b/src/usb_moded-ssu.h @@ -1,29 +1,35 @@ /** - @file usb_moded-ssu.h - - Copyright (C) 2016 Jolla. All rights reserved. - - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-ssu.h + * + * Copyright (C) 2016-2018 Jolla. All rights reserved. + * + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #ifndef USB_MODED_SSU_H_ # define USB_MODED_SSU_H_ -gchar * ssu_get_manufacturer_name(void); -gchar * ssu_get_product_name(void); +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- ssu -- */ + +gchar *ssu_get_manufacturer_name(void); +gchar *ssu_get_product_name (void); #endif // USB_MODED_SSU_H_ diff --git a/src/usb_moded-systemd.c b/src/usb_moded-systemd.c index 5b62ea1..236e823 100644 --- a/src/usb_moded-systemd.c +++ b/src/usb_moded-systemd.c @@ -1,27 +1,27 @@ /** - @file usb_moded-systemd.c + * @file usb_moded-systemd.c + * + * Copyright (C) 2013-2018 Jolla oy. All rights reserved. + * + * @author: Philippe De Swert + * @author: Slava Monich + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - Copyright (C) 2013-2016 Jolla oy. All rights reserved. - - @author: Philippe De Swert - @author: Simo Piiroinen - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - -#define _GNU_SOURCE #include #include @@ -35,18 +35,38 @@ #include "usb_moded-log.h" #include "usb_moded-systemd.h" +/* ========================================================================= * + * Constants + * ========================================================================= */ + #define SYSTEMD_DBUS_SERVICE "org.freedesktop.systemd1" #define SYSTEMD_DBUS_PATH "/org/freedesktop/systemd1" #define SYSTEMD_DBUS_INTERFACE "org.freedesktop.systemd1.Manager" +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- systemd -- */ + +gboolean systemd_control_service(const char *name, const char *method); +gboolean systemd_control_start (void); +void systemd_control_stop (void); + +/* ========================================================================= * + * Data + * ========================================================================= */ /* SystemBus connection ref used for systemd control ipc */ static DBusConnection *systemd_con = NULL; +/* ========================================================================= * + * Functions + * ========================================================================= */ + // QDBusObjectPath org.freedesktop.systemd1.Manager.StartUnit(QString name, QString mode) // QDBusObjectPath org.freedesktop.systemd1.Manager.StopUnit(QString name, QString mode) - // mode = replace // method = StartUnit or StopUnit gboolean systemd_control_service(const char *name, const char *method) @@ -57,7 +77,6 @@ gboolean systemd_control_service(const char *name, const char *method) const char *arg = "replace"; const char *res = 0; - log_debug("%s(%s) ...", method, name); if( !systemd_con ) { @@ -85,7 +104,6 @@ gboolean systemd_control_service(const char *name, const char *method) goto EXIT; } - rsp = dbus_connection_send_with_reply_and_block(systemd_con, req, -1, &err); if( !rsp ) { log_err("no reply to %s.%s request: %s: %s", @@ -137,7 +155,7 @@ systemd_control_start(void) log_debug("starting systemd control"); /* Get connection ref */ - if( (systemd_con = usb_moded_dbus_get_connection()) == 0 ) + if( (systemd_con = umdbus_get_connection()) == 0 ) { log_err("Could not connect to dbus for systemd control\n"); goto cleanup; diff --git a/src/usb_moded-systemd.h b/src/usb_moded-systemd.h index 05f9452..a69f441 100644 --- a/src/usb_moded-systemd.h +++ b/src/usb_moded-systemd.h @@ -1,28 +1,42 @@ /* - - Copyright (C) 2013-2016 Jolla Oy. All rights reserved. + * Copyright (C) 2013-2018 Jolla Oy. All rights reserved. + * + * author: Philippe De Swert + * author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - author: Philippe De Swert - author: Simo Piiroinen +#ifndef USB_MODED_SYSTEMD_H_ +# define USB_MODED_SYSTEMD_H_ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. +/* ========================================================================= * + * Constants + * ========================================================================= */ - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +# define SYSTEMD_STOP "StopUnit" +# define SYSTEMD_START "StartUnit" -#define SYSTEMD_STOP "StopUnit" -#define SYSTEMD_START "StartUnit" +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- systemd -- */ gboolean systemd_control_service(const char *name, const char *method); -gboolean systemd_control_start(void); -void systemd_control_stop(void); +gboolean systemd_control_start (void); +void systemd_control_stop (void); + +#endif /* USB_MODED_SYSTEMD_H_ */ diff --git a/src/usb_moded-trigger.c b/src/usb_moded-trigger.c index 8ad73fe..589131d 100644 --- a/src/usb_moded-trigger.c +++ b/src/usb_moded-trigger.c @@ -1,25 +1,29 @@ /** - @file usb_moded-trigger.c - - Copyright (C) 2011 Nokia Corporation. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - + * @file usb_moded-trigger.c + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Copyright (C) 2014-2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -34,14 +38,30 @@ #include "usb_moded.h" #include "usb_moded-log.h" -#include "usb_moded-config.h" -#include "usb_moded-hw-ab.h" +#include "usb_moded-config-private.h" +#include "usb_moded-udev.h" #include "usb_moded-modesetting.h" #include "usb_moded-trigger.h" #if defined MEEGOLOCK -#include "usb_moded-lock.h" +# include "usb_moded-devicelock.h" #endif /* MEEGOLOCK */ +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- trigger -- */ + +static void trigger_notify_issue (gpointer data); +gboolean trigger_init (void); +static gboolean trigger_udev_event_cb (GIOChannel *iochannel, GIOCondition cond, gpointer data); +void trigger_stop (void); +static void trigger_parse_udev_properties(struct udev_device *dev); + +/* ========================================================================= * + * Data + * ========================================================================= */ + /* global variables */ static struct udev *udev = 0; static struct udev_monitor *mon = 0; @@ -49,197 +69,195 @@ static GIOChannel *iochannel = 0; static guint watch_id = 0; static const char *dev_name = 0; -/* static function definitions */ -static gboolean monitor_udev(GIOChannel *iochannel G_GNUC_UNUSED, GIOCondition cond, - gpointer data G_GNUC_UNUSED); -static void udev_parse(struct udev_device *dev); +/* ========================================================================= * + * Functions + * ========================================================================= */ -static void notify_issue (gpointer data) +static void trigger_notify_issue (gpointer data) { - (void)data; + (void)data; - log_debug("trigger watch destroyed\n!"); - /* clean up & restart trigger */ - trigger_stop(); - trigger_init(); + log_debug("trigger watch destroyed\n!"); + /* clean up & restart trigger */ + trigger_stop(); + trigger_init(); } - gboolean trigger_init(void) { - const gchar *udev_path = NULL; - struct udev_device *dev; - int ret = 0; - - /* Create the udev object */ - udev = udev_new(); - if (!udev) - { - log_err("Can't create udev\n"); - return 1; - } - - udev_path = check_trigger(); - if(udev_path) - dev = udev_device_new_from_syspath(udev, udev_path); - else - { - log_err("No trigger path. Not starting trigger.\n"); - return 1; - } - if (!dev) - { - log_err("Unable to find the trigger device."); - return 1; - } - else - { - dev_name = udev_device_get_sysname(dev); - log_debug("device name = %s\n", dev_name); - } - mon = udev_monitor_new_from_netlink (udev, "udev"); - if (!mon) - { - log_err("Unable to monitor the netlink\n"); - /* communicate failure, mainloop will exit and call appropriate clean-up */ - return 1; - } - ret = udev_monitor_filter_add_match_subsystem_devtype(mon, get_trigger_subsystem(), NULL); - if(ret != 0) - { - log_err("Udev match failed.\n"); - return 1; - } - ret = udev_monitor_enable_receiving (mon); - if(ret != 0) - { - log_err("Failed to enable monitor recieving.\n"); - return 1; - } - - /* check if we are already connected */ - udev_parse(dev); - - iochannel = g_io_channel_unix_new(udev_monitor_get_fd(mon)); - watch_id = g_io_add_watch_full(iochannel, 0, G_IO_IN, monitor_udev, NULL, notify_issue); - - /* everything went well */ - log_debug("Trigger enabled!\n"); - return 0; -} + const gchar *udev_path = NULL; + struct udev_device *dev; + int ret = 0; -static gboolean monitor_udev(GIOChannel *iochannel G_GNUC_UNUSED, GIOCondition cond, - gpointer data G_GNUC_UNUSED) -{ - struct udev_device *dev; + /* Create the udev object */ + udev = udev_new(); + if (!udev) + { + log_err("Can't create udev\n"); + return 1; + } - if(cond & G_IO_IN) - { - /* This normally blocks but G_IO_IN indicates that we can read */ - dev = udev_monitor_receive_device (mon); - if (dev) + udev_path = config_check_trigger(); + if(udev_path) + dev = udev_device_new_from_syspath(udev, udev_path); + else { - /* check if it is the actual device we want to check */ - if(strcmp(dev_name, udev_device_get_sysname(dev))) { - log_crit("name does not match, disabling udev trigger io-watch"); - watch_id = 0; - return FALSE; - } - - if(!strcmp(udev_device_get_action(dev), "change")) - { - log_debug("Trigger event recieved.\n"); - udev_parse(dev); - } - udev_device_unref(dev); + log_err("No trigger path. Not starting trigger.\n"); + return 1; + } + if (!dev) + { + log_err("Unable to find the trigger device."); + return 1; } - /* if we get something else something bad happened stop watching to avoid busylooping */ else { - log_debug("Bad trigger data. Stopping\n"); - watch_id = 0; - trigger_stop(); - return FALSE; + dev_name = udev_device_get_sysname(dev); + log_debug("device name = %s\n", dev_name); + } + mon = udev_monitor_new_from_netlink (udev, "udev"); + if (!mon) + { + log_err("Unable to monitor the netlink\n"); + /* communicate failure, mainloop will exit and call appropriate clean-up */ + return 1; + } + ret = udev_monitor_filter_add_match_subsystem_devtype(mon, config_get_trigger_subsystem(), NULL); + if(ret != 0) + { + log_err("Udev match failed.\n"); + return 1; + } + ret = udev_monitor_enable_receiving (mon); + if(ret != 0) + { + log_err("Failed to enable monitor recieving.\n"); + return 1; } - } - - /* keep watching */ - return TRUE; + + /* check if we are already connected */ + trigger_parse_udev_properties(dev); + + iochannel = g_io_channel_unix_new(udev_monitor_get_fd(mon)); + watch_id = g_io_add_watch_full(iochannel, 0, G_IO_IN, trigger_udev_event_cb, NULL, trigger_notify_issue); + + /* everything went well */ + log_debug("Trigger enabled!\n"); + return 0; +} + +static gboolean trigger_udev_event_cb(GIOChannel *iochannel G_GNUC_UNUSED, GIOCondition cond, + gpointer data G_GNUC_UNUSED) +{ + struct udev_device *dev; + + if(cond & G_IO_IN) + { + /* This normally blocks but G_IO_IN indicates that we can read */ + dev = udev_monitor_receive_device (mon); + if (dev) + { + /* check if it is the actual device we want to check */ + if(strcmp(dev_name, udev_device_get_sysname(dev))) { + log_crit("name does not match, disabling udev trigger io-watch"); + watch_id = 0; + return FALSE; + } + + if(!strcmp(udev_device_get_action(dev), "change")) + { + log_debug("Trigger event recieved.\n"); + trigger_parse_udev_properties(dev); + } + udev_device_unref(dev); + } + /* if we get something else something bad happened stop watching to avoid busylooping */ + else + { + log_debug("Bad trigger data. Stopping\n"); + watch_id = 0; + trigger_stop(); + return FALSE; + } + } + + /* keep watching */ + return TRUE; } void trigger_stop(void) { - if(watch_id) - { - g_source_remove(watch_id); - watch_id = 0; - } - if(iochannel) { - g_io_channel_unref(iochannel); - iochannel = NULL; - } - if(mon) - { - udev_monitor_unref(mon); - mon = 0; - } - if(udev) - { - udev_unref(udev); - udev = 0; - } - dev_name = 0; + if(watch_id) + { + g_source_remove(watch_id); + watch_id = 0; + } + if(iochannel) { + g_io_channel_unref(iochannel); + iochannel = NULL; + } + if(mon) + { + udev_monitor_unref(mon); + mon = 0; + } + if(udev) + { + udev_unref(udev); + udev = 0; + } + dev_name = 0; } -static void udev_parse(struct udev_device *dev) +static void trigger_parse_udev_properties(struct udev_device *dev) { - const char *tmp = 0; - char *trigger = 0; - - trigger = get_trigger_property(); - tmp = udev_device_get_property_value(dev, trigger); - if(!tmp) - { - /* do nothing and return */ - free(trigger); - return; - } - else - { - free(trigger); - trigger = get_trigger_value(); - if(trigger) + const char *tmp = 0; + char *trigger = 0; + + trigger = config_get_trigger_property(); + tmp = udev_device_get_property_value(dev, trigger); + if(!tmp) { - if(!strcmp(tmp, trigger)) - { -#if defined MEEGOLOCK - if(usb_moded_get_export_permission()) -#endif /* MEEGOLOCK */ - if(strcmp(get_trigger_mode(), get_usb_mode()) != 0) - { - usb_moded_mode_cleanup(get_usb_module()); - set_usb_mode(get_trigger_mode()); - } - free(trigger); - } - else - { - free(trigger); - return; - } + /* do nothing and return */ + free(trigger); + return; } else - /* for triggers without trigger value */ { + free(trigger); + trigger = config_get_trigger_value(); + if(trigger) + { + if(!strcmp(tmp, trigger)) + { +#if defined MEEGOLOCK + if(devicelock_have_export_permission()) +#endif /* MEEGOLOCK */ + if(strcmp(config_get_trigger_mode(), usbmoded_get_usb_mode()) != 0) + { + modesetting_cleanup(usbmoded_get_usb_module()); + usbmoded_set_usb_mode(config_get_trigger_mode()); + } + free(trigger); + } + else + { + free(trigger); + return; + } + } + else + /* for triggers without trigger value */ + { #if defined MEEGOLOCK - if(usb_moded_get_export_permission()) + if(devicelock_have_export_permission()) #endif /* MEEGOLOCK */ - if(strcmp(get_trigger_mode(), get_usb_mode()) != 0) - { - usb_moded_mode_cleanup(get_usb_module()); - set_usb_mode(get_trigger_mode()); - } + if(strcmp(config_get_trigger_mode(), usbmoded_get_usb_mode()) != 0) + { + modesetting_cleanup(usbmoded_get_usb_module()); + usbmoded_set_usb_mode(config_get_trigger_mode()); + } + } + return; } - return; - } } diff --git a/src/usb_moded-trigger.h b/src/usb_moded-trigger.h index 5bdae60..2503ba4 100644 --- a/src/usb_moded-trigger.h +++ b/src/usb_moded-trigger.h @@ -1,25 +1,37 @@ /** - @file usb_moded-trigger.h - - Copyright (C) 2011 Nokia Corporation. All rights reserved. + * @file usb_moded-trigger.h + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Copyright (C) 2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ - @author: Philippe De Swert +#ifndef USB_MODED_TRIGGER_H_ +# define USB_MODED_TRIGGER_H_ - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ +/* ========================================================================= * + * Prototypes + * ========================================================================= */ +/* -- trigger -- */ gboolean trigger_init(void); -void trigger_stop(void); +void trigger_stop(void); + +#endif /* USB_MODED_TRIGGER_H_ */ diff --git a/src/usb_moded-udev.c b/src/usb_moded-udev.c index 1e39b7f..8dad79a 100644 --- a/src/usb_moded-udev.c +++ b/src/usb_moded-udev.c @@ -1,25 +1,31 @@ /** - @file usb_moded-udev.c - - Copyright (C) 2011 Nokia Corporation. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ - + * @file usb_moded-udev.c + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Copyright (C) 2013-2018 Jolla Ltd. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Tapio Rantala + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Jarko Poutiainen + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -34,456 +40,695 @@ #include #include "usb_moded-log.h" -#include "usb_moded-config.h" -#include "usb_moded-hw-ab.h" +#include "usb_moded-config-private.h" +#include "usb_moded-udev.h" #include "usb_moded.h" #include "usb_moded-modes.h" +/* ========================================================================= * + * Types + * ========================================================================= */ + +typedef enum { + CABLE_STATE_UNKNOWN, + CABLE_STATE_DISCONNECTED, + CABLE_STATE_CHARGER_CONNECTED, + CABLE_STATE_PC_CONNECTED, + CABLE_STATE_NUMOF +} cable_state_t; + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- cable -- */ + +static gboolean cable_state_timer_cb (gpointer aptr); +static void cable_state_stop_timer (void); +static void cable_state_start_timer(void); +static bool cable_state_connected (void); +static cable_state_t cable_state_get (void); +static void cable_state_set (cable_state_t state); +static void cable_state_changed (void); +static void cable_state_from_udev (cable_state_t state); + +/* -- umudev -- */ + +static void umudev_io_error_cb (gpointer data); +static gboolean umudev_io_input_cb (GIOChannel *iochannel, GIOCondition cond, gpointer data); +static void umudev_parse_properties (struct udev_device *dev, bool initial); +static int umudev_score_as_power_supply(const char *syspath); +gboolean umudev_init (void); +void umudev_quit (void); + +/* ========================================================================= * + * Data + * ========================================================================= */ + +static const char * const cable_state_name[CABLE_STATE_NUMOF] = { + [CABLE_STATE_UNKNOWN] = "unknown", + [CABLE_STATE_DISCONNECTED] = "disconnected", + [CABLE_STATE_CHARGER_CONNECTED] = "charger_connected", + [CABLE_STATE_PC_CONNECTED] = "pc_connected", +}; + /* global variables */ -static struct udev *udev = 0; -static struct udev_monitor *mon = 0; -static GIOChannel *iochannel = 0; -static guint watch_id = 0; -static char *dev_name = 0; -static int cleanup = 0; -/* track cable and charger connects disconnects */ -static int cable = 0, charger = 0; -static guint cable_connection_timeout_id = 0; - -/** Bookkeeping data for power supply locating heuristics */ -typedef struct power_device { - /** Device path used by udev */ - const char *syspath; - /** Likelyhood of being power supply */ - int score; -} power_device; - -/* static function definitions */ -static gboolean monitor_udev(GIOChannel *iochannel G_GNUC_UNUSED, GIOCondition cond, - gpointer data G_GNUC_UNUSED); -static void udev_parse(struct udev_device *dev, bool initial); -static void setup_cable_connection(void); -static void setup_charger_connection(void); -static void cancel_cable_connection_timeout(void); -static void schedule_cable_connection_timeout(void); -static gboolean cable_connection_timeout_cb(gpointer data); - -static void notify_issue (gpointer data) -{ - (void)data; +static struct udev *umudev_object = 0; +static struct udev_monitor *umudev_monitor = 0; +static gchar *umudev_sysname = 0; +static guint umudev_watch_id = 0; +static bool umudev_in_cleanup = false; - /* we do not want to restart when we try to clean up */ - if(cleanup) - return; - log_debug("USB connection watch destroyed, restarting it\n!"); - /* restart trigger */ - hwal_cleanup(); - hwal_init(); -} +/** Cable state as evaluated from udev events */ +static cable_state_t cable_state_current = CABLE_STATE_UNKNOWN; -static int check_device_is_usb_power_supply(const char *syspath) -{ - struct udev *udev; - struct udev_device *dev = 0; - const char *udev_name; - int score = 0; - - udev = udev_new(); - dev = udev_device_new_from_syspath(udev, syspath); - if(!dev) - return 0; - udev_name = udev_device_get_sysname(dev); - - /* try to assign a weighed score */ - - /* check it is no battery */ - if(strstr(udev_name, "battery") || strstr(udev_name, "BAT")) - return 0; - /* if it contains usb in the name it very likely is good */ - if(strstr(udev_name, "usb")) - score = score + 10; - /* often charger is also mentioned in the name */ - if(strstr(udev_name, "charger")) - score = score + 5; - /* present property is used to detect activity, however online is better */ - if(udev_device_get_property_value(dev, "POWER_SUPPLY_PRESENT")) - score = score + 5; - if(udev_device_get_property_value(dev, "POWER_SUPPLY_ONLINE")) - score = score + 10; - /* type is used to detect if it is a cable or dedicated charger. - Bonus points if it is there. */ - if(udev_device_get_property_value(dev, "POWER_SUPPLY_TYPE")) - score = score + 10; +/** Cable state considered active by usb-moded */ +static cable_state_t cable_state_active = CABLE_STATE_UNKNOWN; - /* clean up */ - udev_device_unref(dev); - udev_unref(udev); +/** Previously active cable state */ +static cable_state_t cable_state_previous = CABLE_STATE_UNKNOWN; - return(score); -} +/** Timer id for delaying: reported by udev -> active in usb-moded */ +static guint cable_state_timer_id = 0; +/* ========================================================================= * + * cable state + * ========================================================================= */ -gboolean hwal_init(void) +static gboolean cable_state_timer_cb(gpointer aptr) { - char *udev_path = NULL, *udev_subsystem = NULL; - struct udev_device *dev; - struct udev_enumerate *list; - struct udev_list_entry *list_entry, *first_entry; - struct power_device power_dev; - int ret = 0; - - cleanup = 0; - - /* Create the udev object */ - udev = udev_new(); - if (!udev) - { - log_err("Can't create udev\n"); + (void)aptr; + cable_state_timer_id = 0; + + log_debug("trigger delayed transfer to: %s", + cable_state_name[cable_state_current]); + cable_state_set(cable_state_current); return FALSE; - } - - udev_path = find_udev_path(); - if(udev_path) - { - dev = udev_device_new_from_syspath(udev, udev_path); - g_free(udev_path); - } - else - dev = udev_device_new_from_syspath(udev, "/sys/class/power_supply/usb"); - if (!dev) - { - log_debug("Trying to guess $power_supply device.\n"); - - power_dev.score = 0; - power_dev.syspath = 0; - - list = udev_enumerate_new(udev); - udev_enumerate_add_match_subsystem(list, "power_supply"); - udev_enumerate_scan_devices(list); - first_entry = udev_enumerate_get_list_entry(list); - udev_list_entry_foreach(list_entry, first_entry) - { - udev_path = (char *)udev_list_entry_get_name(list_entry); - ret = check_device_is_usb_power_supply(udev_path); - if(ret) - { - if(ret > power_dev.score) - { - power_dev.score = ret; - power_dev.syspath = udev_path; - } - } +} + +static void cable_state_stop_timer(void) +{ + if( cable_state_timer_id ) { + log_debug("cancel delayed transfer to: %s", + cable_state_name[cable_state_current]); + g_source_remove(cable_state_timer_id), + cable_state_timer_id = 0; } - /* check if we found anything with some kind of score */ - if(power_dev.score > 0) - { - dev = udev_device_new_from_syspath(udev, power_dev.syspath); +} + +static void cable_state_start_timer(void) +{ + if( !cable_state_timer_id ) { + log_debug("schedule delayed transfer to: %s", + cable_state_name[cable_state_current]); + cable_state_timer_id = g_timeout_add(1500, cable_state_timer_cb, 0); } - if(!dev) - { - log_err("Unable to find $power_supply device."); - /* communicate failure, mainloop will exit and call appropriate clean-up */ - return FALSE; +} + +static bool +cable_state_connected(void) +{ + bool connected = false; + switch( cable_state_get() ) { + default: + break; + case CABLE_STATE_CHARGER_CONNECTED: + case CABLE_STATE_PC_CONNECTED: + connected = true; + break; } - } - - dev_name = strdup(udev_device_get_sysname(dev)); - log_debug("device name = %s\n", dev_name); - mon = udev_monitor_new_from_netlink (udev, "udev"); - if (!mon) - { - log_err("Unable to monitor the netlink\n"); - /* communicate failure, mainloop will exit and call appropriate clean-up */ - return FALSE; - } - udev_subsystem = find_udev_subsystem(); - if(udev_subsystem) - { - ret = udev_monitor_filter_add_match_subsystem_devtype(mon, udev_subsystem, NULL); - g_free(udev_subsystem); - } - else - ret = udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL); - if(ret != 0) - { - log_err("Udev match failed.\n"); - return FALSE; - } - ret = udev_monitor_enable_receiving (mon); - if(ret != 0) - { - log_err("Failed to enable monitor recieving.\n"); - return FALSE; - } - - /* check if we are already connected */ - udev_parse(dev, true); - - iochannel = g_io_channel_unix_new(udev_monitor_get_fd(mon)); - watch_id = g_io_add_watch_full(iochannel, 0, G_IO_IN, monitor_udev, NULL,notify_issue); - - /* everything went well */ - udev_device_unref(dev); - return TRUE; + return connected; } -static gboolean monitor_udev(GIOChannel *iochannel G_GNUC_UNUSED, GIOCondition cond, - gpointer data G_GNUC_UNUSED) +static cable_state_t cable_state_get(void) { - struct udev_device *dev; + return cable_state_active; +} - gboolean continue_watching = TRUE; +static void cable_state_set(cable_state_t state) +{ + cable_state_stop_timer(); - /* No code paths are allowed to bypass the release_wakelock() call below */ - acquire_wakelock(USB_MODED_WAKELOCK_PROCESS_INPUT); + if( cable_state_active == state ) + goto EXIT; - if(cond & G_IO_IN) - { - /* This normally blocks but G_IO_IN indicates that we can read */ - dev = udev_monitor_receive_device (mon); - if (!dev) - { - /* if we get something else something bad happened stop watching to avoid busylooping */ - continue_watching = FALSE; + cable_state_previous = cable_state_active; + cable_state_active = state; + + log_debug("cable_state: %s -> %s", + cable_state_name[cable_state_previous], + cable_state_name[cable_state_active]); + + cable_state_changed(); + +EXIT: + return; +} + +static void cable_state_changed(void) +{ + /* The rest of usb-moded separates charger + * and pc connection states... make single + * state tracking compatible with that. */ + + /* First handle pc/charger disconnect based + * on previous state. + */ + switch( cable_state_previous ) { + default: + case CABLE_STATE_DISCONNECTED: + /* dontcare */ + break; + case CABLE_STATE_CHARGER_CONNECTED: + log_debug("*** HANDLE CHARGER DISCONNECT"); + usbmoded_set_charger_connected(false); + break; + case CABLE_STATE_PC_CONNECTED: + log_debug("*** HANDLE PC DISCONNECT"); + usbmoded_set_usb_connected(false); + break; } - else - { - /* check if it is the actual device we want to check */ - if(!strcmp(dev_name, udev_device_get_sysname(dev))) - { - if(!strcmp(udev_device_get_action(dev), "change")) - { - udev_parse(dev, false); - } - } - - udev_device_unref(dev); + + /* Then handle pc/charger sconnect based + * on current state. + */ + + switch( cable_state_active ) { + default: + case CABLE_STATE_DISCONNECTED: + /* dontcare */ + break; + case CABLE_STATE_CHARGER_CONNECTED: + log_debug("*** HANDLE CHARGER CONNECT"); + usbmoded_set_charger_connected(true); + break; + case CABLE_STATE_PC_CONNECTED: + log_debug("*** HANDLE PC CONNECT"); + usbmoded_set_usb_connected(true); + break; } - } +} - if(cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) - { - /* Unhandled errors turn io watch to virtual busyloop too */ - continue_watching = FALSE; - } +static void cable_state_from_udev(cable_state_t curr) +{ + cable_state_t prev = cable_state_current; + cable_state_current = curr; + + if( prev == curr ) + goto EXIT; - release_wakelock(USB_MODED_WAKELOCK_PROCESS_INPUT); + log_debug("reported cable state: %s -> %s", + cable_state_name[prev], + cable_state_name[curr]); - if (!continue_watching && watch_id ) - { - watch_id = 0; - log_crit("udev io watch disabled"); - } + if( curr == CABLE_STATE_PC_CONNECTED && prev != CABLE_STATE_UNKNOWN ) + cable_state_start_timer(); + else + cable_state_set(curr); - return continue_watching; +EXIT: + return; } -void hwal_cleanup(void) +/* ========================================================================= * + * legacy code + * ========================================================================= */ + +static void umudev_io_error_cb(gpointer data) { - cleanup = 1; - - log_debug("HWhal cleanup\n"); - - if(watch_id != 0) - { - g_source_remove(watch_id); - watch_id = 0; - } - if(iochannel != NULL) - { - g_io_channel_unref(iochannel); - iochannel = NULL; - } - cancel_cable_connection_timeout(); - free(dev_name); - udev_monitor_unref(mon); - udev_unref(udev); + (void)data; + + /* we do not want to restart when we try to clean up */ + if( !umudev_in_cleanup ) { + log_debug("USB connection watch destroyed, restarting it\n!"); + /* restart trigger */ + umudev_quit(); + umudev_init(); + } } -static void setup_cable_connection(void) +static gboolean umudev_io_input_cb(GIOChannel *iochannel, GIOCondition cond, gpointer data) { - cancel_cable_connection_timeout(); + (void)iochannel; + (void)data; + + gboolean continue_watching = TRUE; + + /* No code paths are allowed to bypass the usbmoded_release_wakelock() call below */ + usbmoded_acquire_wakelock(USB_MODED_WAKELOCK_PROCESS_INPUT); + + if( cond & G_IO_IN ) + { + /* This normally blocks but G_IO_IN indicates that we can read */ + struct udev_device *dev = udev_monitor_receive_device(umudev_monitor); + if( !dev ) + { + /* if we get something else something bad happened stop watching to avoid busylooping */ + continue_watching = FALSE; + } + else + { + /* check if it is the actual device we want to check */ + if( !strcmp(umudev_sysname, udev_device_get_sysname(dev)) ) + { + if( !strcmp(udev_device_get_action(dev), "change") ) + { + umudev_parse_properties(dev, false); + } + } + + udev_device_unref(dev); + } + } + + if( cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL) ) + { + /* Unhandled errors turn io watch to virtual busyloop too */ + continue_watching = FALSE; + } - log_debug("UDEV:USB pc cable connected\n"); + if( !continue_watching && umudev_watch_id ) + { + umudev_watch_id = 0; + log_crit("udev io watch disabled"); + } - cable = 1; - charger = 0; - set_usb_connected(TRUE); + usbmoded_release_wakelock(USB_MODED_WAKELOCK_PROCESS_INPUT); + + return continue_watching; } -static void setup_charger_connection(void) +static void umudev_parse_properties(struct udev_device *dev, bool initial) { - cancel_cable_connection_timeout(); - - log_debug("UDEV:USB dedicated charger connected\n"); - - if (cable) { - /* The connection was initially reported incorrectly - * as pc cable, then later on declared as charger. - * - * Clear "connected" boolean flag so that the - * set_charger_connected() call below acts as if charger - * were detected already on connect: mode gets declared - * as dedicated charger (and the mode selection dialog - * shown by ui gets closed). - */ - set_usb_connection_state(FALSE); - } - - charger = 1; - cable = 0; - set_charger_connected(TRUE); + (void)initial; + + /* udev properties we are interested in */ + const char *power_supply_present = 0; + const char *power_supply_online = 0; + const char *power_supply_type = 0; + + /* Assume there is no usb connection until proven otherwise */ + bool connected = false; + + /* Unless debug logging has been request via command line, + * suppress warnings about potential property issues and/or + * fallback strategies applied (to avoid spamming due to the + * code below seeing the same property values over and over + * again also in stable states). + */ + bool warnings = log_p(LOG_DEBUG); + + /* + * Check for present first as some drivers use online for when charging + * is enabled + */ + power_supply_present = udev_device_get_property_value(dev, "POWER_SUPPLY_PRESENT"); + if( !power_supply_present ) { + power_supply_present = + power_supply_online = udev_device_get_property_value(dev, "POWER_SUPPLY_ONLINE"); + } + + if( power_supply_present && !strcmp(power_supply_present, "1") ) + connected = true; + + /* Transition period = Connection status derived from udev + * events disagrees with usb-moded side bookkeeping. */ + if( connected != usbmoded_get_connection_state() ) { + /* Enable udev property diagnostic logging */ + warnings = true; + /* Block suspend briefly */ + usbmoded_delay_suspend(); + } + + if( !connected ) { + /* Handle: Disconnected */ + + if( warnings && !power_supply_present ) + log_err("No usable power supply indicator\n"); + cable_state_from_udev(CABLE_STATE_DISCONNECTED); + +// QUARANTINE log_debug("DISCONNECTED"); +// QUARANTINE +// QUARANTINE cancel_cable_connection_timeout(); +// QUARANTINE +// QUARANTINE if (charger) { +// QUARANTINE log_debug("UDEV:USB dedicated charger disconnected\n"); +// QUARANTINE usbmoded_set_charger_connected(FALSE); +// QUARANTINE } +// QUARANTINE +// QUARANTINE if (cable) { +// QUARANTINE log_debug("UDEV:USB cable disconnected\n"); +// QUARANTINE usbmoded_set_usb_connected(FALSE); +// QUARANTINE } +// QUARANTINE +// QUARANTINE cable = 0; +// QUARANTINE charger = 0; + } + else { + if( warnings && power_supply_online ) + log_warning("Using online property\n"); + + /* At least h4113 i.e. "Xperia XA2 - Dual SIM" seem to have + * POWER_SUPPLY_REAL_TYPE udev property with information + * that usb-moded expects to be in POWER_SUPPLY_TYPE prop. + */ + power_supply_type = udev_device_get_property_value(dev, "POWER_SUPPLY_REAL_TYPE"); + if( !power_supply_type ) + power_supply_type = udev_device_get_property_value(dev, "POWER_SUPPLY_TYPE"); + /* + * Power supply type might not exist also :( + * Send connected event but this will not be able + * to discriminate between charger/cable. + */ + if( !power_supply_type ) { + if( warnings ) + log_warning("Fallback since cable detection might not be accurate. " + "Will connect on any voltage on charger.\n"); + cable_state_from_udev(CABLE_STATE_PC_CONNECTED); +// QUARANTINE schedule_cable_connection_timeout(); + goto cleanup; + } + + log_debug("CONNECTED - POWER_SUPPLY_TYPE = %s", power_supply_type); + + if( !strcmp(power_supply_type, "USB") || + !strcmp(power_supply_type, "USB_CDP") ) { + cable_state_from_udev(CABLE_STATE_PC_CONNECTED); +// QUARANTINE if( initial ) +// QUARANTINE setup_cable_connection(); +// QUARANTINE else +// QUARANTINE schedule_cable_connection_timeout(); + } + else if( !strcmp(power_supply_type, "USB_DCP") || + !strcmp(power_supply_type, "USB_HVDCP") || + !strcmp(power_supply_type, "USB_HVDCP_3") ) { + cable_state_from_udev(CABLE_STATE_CHARGER_CONNECTED); +// QUARANTINE setup_charger_connection(); + } + else if( !strcmp(power_supply_type, "USB_FLOAT")) { + if( !cable_state_connected() ) + log_warning("connection type detection failed, assuming charger"); + cable_state_from_udev(CABLE_STATE_CHARGER_CONNECTED); + } + else if( !strcmp(power_supply_type, "Unknown")) { + // nop + log_warning("unknown connection type reported, assuming disconnected"); + cable_state_from_udev(CABLE_STATE_DISCONNECTED); + } + else { + if( warnings ) + log_warning("unhandled power supply type: %s", power_supply_type); + cable_state_from_udev(CABLE_STATE_DISCONNECTED); + } + } + +cleanup: + return; } -static gboolean cable_connection_timeout_cb(gpointer data) +static int umudev_score_as_power_supply(const char *syspath) { - (void)data; + int score = 0; + struct udev_device *dev = 0; + const char *sysname = 0; + + if( !umudev_object ) + goto EXIT; + + if( !(dev = udev_device_new_from_syspath(umudev_object, syspath)) ) + goto EXIT; + + if( !(sysname = udev_device_get_sysname(dev)) ) + goto EXIT; - log_debug("connect delay: timeout"); - cable_connection_timeout_id = 0; + /* try to assign a weighed score */ - setup_cable_connection(); + /* check that it is not a battery */ + if(strstr(sysname, "battery") || strstr(sysname, "BAT")) + goto EXIT; + + /* if it contains usb in the name it very likely is good */ + if(strstr(sysname, "usb")) + score = score + 10; + + /* often charger is also mentioned in the name */ + if(strstr(sysname, "charger")) + score = score + 5; - return FALSE; + /* present property is used to detect activity, however online is better */ + if(udev_device_get_property_value(dev, "POWER_SUPPLY_PRESENT")) + score = score + 5; + + if(udev_device_get_property_value(dev, "POWER_SUPPLY_ONLINE")) + score = score + 10; + + /* type is used to detect if it is a cable or dedicated charger. + Bonus points if it is there. */ + if(udev_device_get_property_value(dev, "POWER_SUPPLY_TYPE")) + score = score + 10; + +EXIT: + /* clean up */ + if( dev ) + udev_device_unref(dev); + + return score; } -static void cancel_cable_connection_timeout(void) +gboolean umudev_init(void) { - if (cable_connection_timeout_id) { - log_debug("connect delay: cancel"); - g_source_remove(cable_connection_timeout_id); - cable_connection_timeout_id = 0; - } -} + gboolean success = FALSE; + char *configured_device = NULL; + char *configured_subsystem = NULL; + struct udev_device *dev = 0; + static GIOChannel *iochannel = 0; -static void schedule_cable_connection_timeout(void) -{ - /* Ignore If already connected */ - if (get_usb_connection_state()) - return; - - if (!cable_connection_timeout_id && cable_connection_delay > 0) { - /* Dedicated charger might be initially misdetected as - * pc cable. Delay a bit befor accepting the state. */ - - log_debug("connect delay: started (%d ms)", - cable_connection_delay); - cable_connection_timeout_id = - g_timeout_add(cable_connection_delay, - cable_connection_timeout_cb, - NULL); - } - else { - /* If more udev events indicating cable connection - * are received while waiting, accept immediately. */ - setup_cable_connection(); - } + int ret = 0; + + /* Clear in-cleanup in case of restart */ + umudev_in_cleanup = false; + + /* Create the udev object */ + if( !(umudev_object = udev_new()) ) { + log_err("Can't create umudev_object\n"); + goto EXIT; + } + + if( !(configured_device = config_find_udev_path()) ) + configured_device = g_strdup("/sys/class/power_supply/usb"); + + if( !(configured_subsystem = config_find_udev_subsystem()) ) + configured_subsystem = g_strdup("power_supply"); + + /* Try with configured / default device */ + dev = udev_device_new_from_syspath(umudev_object, configured_device); + + /* If needed, try heuristics */ + if( !dev ) { + log_debug("Trying to guess $power_supply device.\n"); + + int current_score = 0; + gchar *current_name = 0; + + struct udev_enumerate *list; + struct udev_list_entry *list_entry; + struct udev_list_entry *first_entry; + + list = udev_enumerate_new(umudev_object); + udev_enumerate_add_match_subsystem(list, "power_supply"); + udev_enumerate_scan_devices(list); + first_entry = udev_enumerate_get_list_entry(list); + udev_list_entry_foreach(list_entry, first_entry) { + const char *name = udev_list_entry_get_name(list_entry); + int score = umudev_score_as_power_supply(name); + if( current_score < score ) { + g_free(current_name); + current_name = g_strdup(name); + current_score = score; + } + } + /* check if we found anything with some kind of score */ + if(current_score > 0) { + dev = udev_device_new_from_syspath(umudev_object, current_name); + } + g_free(current_name); + } + + /* Give up if no power supply device was found */ + if( !dev ) { + log_err("Unable to find $power_supply device."); + /* communicate failure, mainloop will exit and call appropriate clean-up */ + goto EXIT; + } + + /* Cache device name */ + umudev_sysname = g_strdup(udev_device_get_sysname(dev)); + log_debug("device name = %s\n", umudev_sysname); + + /* Start monitoring for changes */ + umudev_monitor = udev_monitor_new_from_netlink(umudev_object, "udev"); + if( !umudev_monitor ) + { + log_err("Unable to monitor the netlink\n"); + /* communicate failure, mainloop will exit and call appropriate clean-up */ + goto EXIT; + } + + ret = udev_monitor_filter_add_match_subsystem_devtype(umudev_monitor, + configured_subsystem, + NULL); + if(ret != 0) + { + log_err("Udev match failed.\n"); + goto EXIT; + } + + ret = udev_monitor_enable_receiving(umudev_monitor); + if(ret != 0) + { + log_err("Failed to enable monitor recieving.\n"); + goto EXIT; + } + + iochannel = g_io_channel_unix_new(udev_monitor_get_fd(umudev_monitor)); + if( !iochannel ) + goto EXIT; + + umudev_watch_id = g_io_add_watch_full(iochannel, 0, G_IO_IN, umudev_io_input_cb, NULL, umudev_io_error_cb); + if( !umudev_watch_id ) + goto EXIT; + + /* everything went well */ + success = TRUE; + + /* check initial status */ + umudev_parse_properties(dev, true); + +EXIT: + /* Cleanup local resources */ + if( iochannel ) + g_io_channel_unref(iochannel); + + if( dev ) + udev_device_unref(dev); + + g_free(configured_subsystem); + g_free(configured_device); + + /* All or nothing */ + if( !success ) + umudev_quit(); + + return success; } -static void udev_parse(struct udev_device *dev, bool initial) +void umudev_quit(void) { - /* udev properties we are interested in */ - const char *power_supply_present = 0; - const char *power_supply_online = 0; - const char *power_supply_type = 0; - - /* Assume there is no usb connection until proven otherwise */ - bool connected = false; - - /* Unless debug logging has been request via command line, - * suppress warnings about potential property issues and/or - * fallback strategies applied (to avoid spamming due to the - * code below seeing the same property values over and over - * again also in stable states). - */ - bool warnings = log_p(LOG_DEBUG); - - /* - * Check for present first as some drivers use online for when charging - * is enabled - */ - power_supply_present = udev_device_get_property_value(dev, "POWER_SUPPLY_PRESENT"); - if (!power_supply_present) { - power_supply_present = - power_supply_online = udev_device_get_property_value(dev, "POWER_SUPPLY_ONLINE"); - } - - if (power_supply_present && !strcmp(power_supply_present, "1")) - connected = true; - - /* Transition period = Connection status derived from udev - * events disagrees with usb-moded side bookkeeping. */ - if (connected != get_usb_connection_state()) { - /* Enable udev property diagnostic logging */ - warnings = true; - /* Block suspend briefly */ - delay_suspend(); - } - - /* disconnect */ - if (!connected) { - if (warnings && !power_supply_present) - log_err("No usable power supply indicator\n"); - - log_debug("DISCONNECTED"); - - cancel_cable_connection_timeout(); - - if (charger) { - log_debug("UDEV:USB dedicated charger disconnected\n"); - set_charger_connected(FALSE); - } - - if (cable) { - log_debug("UDEV:USB cable disconnected\n"); - set_usb_connected(FALSE); - } - - cable = 0; - charger = 0; - } - else { - if (warnings && power_supply_online) - log_warning("Using online property\n"); - - power_supply_type = udev_device_get_property_value(dev, "POWER_SUPPLY_TYPE"); - /* - * Power supply type might not exist also :( - * Send connected event but this will not be able - * to discriminate between charger/cable. - */ - if (!power_supply_type) { - if( warnings ) - log_warning("Fallback since cable detection might not be accurate. " - "Will connect on any voltage on charger.\n"); - schedule_cable_connection_timeout(); - goto cleanup; - } - - log_debug("CONNECTED - POWER_SUPPLY_TYPE = %s", power_supply_type); - - if (!strcmp(power_supply_type, "USB") || - !strcmp(power_supply_type, "USB_CDP")) { - if( initial ) - setup_cable_connection(); - else - schedule_cable_connection_timeout(); - } - else if (!strcmp(power_supply_type, "USB_DCP") || - !strcmp(power_supply_type, "USB_HVDCP") || - !strcmp(power_supply_type, "USB_HVDCP_3")) { - setup_charger_connection(); - } - else if( !strcmp(power_supply_type, "Unknown")) { - // nop - } - else { - if (warnings) - log_warning("unhandled power supply type: %s", power_supply_type); - } - } + umudev_in_cleanup = true; -cleanup: - return; + log_debug("HWhal cleanup\n"); + +// QUARANTINE cancel_cable_connection_timeout(); + + if( umudev_watch_id ) + { + g_source_remove(umudev_watch_id), + umudev_watch_id = 0; + } + + if( umudev_monitor ) { + udev_monitor_unref(umudev_monitor), + umudev_monitor = 0; + } + + if( umudev_object ) { + udev_unref(umudev_object), + umudev_object =0 ; + } + + g_free(umudev_sysname), + umudev_sysname = 0; + + cable_state_stop_timer(); } + +// QUARANTINE static void setup_cable_connection(void) +// QUARANTINE { +// QUARANTINE cancel_cable_connection_timeout(); +// QUARANTINE +// QUARANTINE log_debug("UDEV:USB pc cable connected\n"); +// QUARANTINE +// QUARANTINE cable = 1; +// QUARANTINE charger = 0; +// QUARANTINE usbmoded_set_usb_connected(TRUE); +// QUARANTINE } + +// QUARANTINE static void setup_charger_connection(void) +// QUARANTINE { +// QUARANTINE cancel_cable_connection_timeout(); +// QUARANTINE +// QUARANTINE log_debug("UDEV:USB dedicated charger connected\n"); +// QUARANTINE +// QUARANTINE if (cable) { +// QUARANTINE /* The connection was initially reported incorrectly +// QUARANTINE * as pc cable, then later on declared as charger. +// QUARANTINE * +// QUARANTINE * Clear "connected" boolean flag so that the +// QUARANTINE * usbmoded_set_charger_connected() call below acts as if charger +// QUARANTINE * were detected already on connect: mode gets declared +// QUARANTINE * as dedicated charger (and the mode selection dialog +// QUARANTINE * shown by ui gets closed). +// QUARANTINE */ +// QUARANTINE usbmoded_set_connection_state(FALSE); +// QUARANTINE } +// QUARANTINE +// QUARANTINE charger = 1; +// QUARANTINE cable = 0; +// QUARANTINE usbmoded_set_charger_connected(TRUE); +// QUARANTINE } + +// QUARANTINE static gboolean cable_connection_timeout_cb(gpointer data) +// QUARANTINE { +// QUARANTINE (void)data; +// QUARANTINE +// QUARANTINE log_debug("connect delay: timeout"); +// QUARANTINE cable_connection_timeout_id = 0; +// QUARANTINE +// QUARANTINE setup_cable_connection(); +// QUARANTINE +// QUARANTINE return FALSE; +// QUARANTINE } + +// QUARANTINE static void cancel_cable_connection_timeout(void) +// QUARANTINE { +// QUARANTINE if (cable_connection_timeout_id) { +// QUARANTINE log_debug("connect delay: cancel"); +// QUARANTINE g_source_remove(cable_connection_timeout_id); +// QUARANTINE cable_connection_timeout_id = 0; +// QUARANTINE } +// QUARANTINE } + +// QUARANTINE static void schedule_cable_connection_timeout(void) +// QUARANTINE { +// QUARANTINE /* Ignore If already connected */ +// QUARANTINE if (usbmoded_get_connection_state()) +// QUARANTINE return; +// QUARANTINE +// QUARANTINE if (!cable_connection_timeout_id && usbmoded_cable_connection_delay > 0) { +// QUARANTINE /* Dedicated charger might be initially misdetected as +// QUARANTINE * pc cable. Delay a bit befor accepting the state. */ +// QUARANTINE +// QUARANTINE log_debug("connect delay: started (%d ms)", +// QUARANTINE usbmoded_cable_connection_delay); +// QUARANTINE cable_connection_timeout_id = +// QUARANTINE g_timeout_add(usbmoded_cable_connection_delay, +// QUARANTINE cable_connection_timeout_cb, +// QUARANTINE NULL); +// QUARANTINE } +// QUARANTINE else { +// QUARANTINE /* If more udev events indicating cable connection +// QUARANTINE * are received while waiting, accept immediately. */ +// QUARANTINE setup_cable_connection(); +// QUARANTINE } +// QUARANTINE } diff --git a/src/usb_moded-udev.h b/src/usb_moded-udev.h new file mode 100644 index 0000000..8039fd1 --- /dev/null +++ b/src/usb_moded-udev.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Copyright (C) 2018 Jolla Ltd. + * + * Author: Philippe De Swert + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef USB_MODED_UDEV_H_ +# define USB_MODED_UDEV_H_ + +/* + * hardware abstraction glue layer. + * Each HW abstraction system needs to implement the functions declared here + * + * Communication is done through the signal functions defined in usb_moded.h + */ + +# include + +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- umudev -- */ + +gboolean umudev_init(void); +void umudev_quit(void); + +#endif /* USB_MODED_UDEV_H_ */ diff --git a/src/usb_moded-util.c b/src/usb_moded-util.c index 2007f78..3d383b3 100644 --- a/src/usb_moded-util.c +++ b/src/usb_moded-util.c @@ -1,24 +1,27 @@ /** - @file usb_moded-util.c - - Copyright (C) 2013 Jolla. All rights reserved. - - @author: Philippe De Swert - - This program is free software; you can redistribute it and/or - modify it under the terms of the Lesser GNU General Public License - version 2 as published by the Free Software Foundation. - - This program 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 - General Public License for more details. - - You should have received a copy of the Lesser GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA -*/ + * @file usb_moded-util.c + * + * Copyright (C) 2013-2018 Jolla. All rights reserved. + * + * @author: Philippe De Swert + * @author: Philippe De Swert + * @author: Martin Jones + * @author: Simo Piiroinen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Lesser GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the Lesser GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ #include #include @@ -29,422 +32,445 @@ #include "usb_moded-dbus.h" +/* ========================================================================= * + * Prototypes + * ========================================================================= */ + +/* -- util -- */ + +static int util_query_mode (void); +static int util_get_modelist (void); +static int util_get_mode_configured (void); +static int util_unset_rescue (void); +static int util_set_mode (char *mode); +static int util_set_mode_config (char *mode); +static int util_set_hide_mode_config (char *mode); +static int util_set_unhide_mode_config(char *mode); +static int util_get_hiddenlist (void); +static int util_handle_network (char *network); + +/* ========================================================================= * + * Data + * ========================================================================= */ + static DBusConnection *conn = 0; -static int query_mode (void) +/* ========================================================================= * + * Functions + * ========================================================================= */ + +static int util_query_mode (void) { - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_STATE_REQUEST)) != NULL) - { + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_STATE_REQUEST)) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); dbus_message_unref(reply); } dbus_message_unref(req); - } + } - if(ret) - { - printf("mode = %s\n", ret); - return 0; - } - - /* not everything went as planned, return error */ - return 1; + if(ret) + { + printf("mode = %s\n", ret); + return 0; + } + + /* not everything went as planned, return error */ + return 1; } -static int get_modelist (void) +static int util_get_modelist (void) { - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_LIST)) != NULL) - { + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_LIST)) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); dbus_message_unref(reply); } dbus_message_unref(req); - } + } - if(ret) - { - printf("modes supported are = %s\n", ret); - return 0; - } - - /* not everything went as planned, return error */ - return 1; + if(ret) + { + printf("modes supported are = %s\n", ret); + return 0; + } + + /* not everything went as planned, return error */ + return 1; } -static int get_mode_configured (void) +static int util_get_mode_configured (void) { - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_CONFIG_GET)) != NULL) - { + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_CONFIG_GET)) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); dbus_message_unref(reply); } dbus_message_unref(req); - } + } - if(ret) - { - printf("On USB connection usb_moded will set the following mode based on the configuration = %s\n", ret); - return 0; - } - - /* not everything went as planned, return error */ - return 1; + if(ret) + { + printf("On USB connection usb_moded will set the following mode based on the configuration = %s\n", ret); + return 0; + } + + /* not everything went as planned, return error */ + return 1; } -static int unset_rescue (void) +static int util_unset_rescue (void) { - DBusMessage *req = NULL, *reply = NULL; - int ret = 0; + DBusMessage *req = NULL, *reply = NULL; + int ret = 0; - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_RESCUE_OFF)) != NULL) - { + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_RESCUE_OFF)) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { - if(reply) - ret = 1; + if(reply) + ret = 1; dbus_message_unref(reply); } dbus_message_unref(req); - } - - if(ret) - { - printf("Rescue mode is off\n"); - return 0; - } - else - return 1; + } + + if(ret) + { + printf("Rescue mode is off\n"); + return 0; + } + else + return 1; } -static int set_mode (char *mode) +static int util_set_mode (char *mode) { - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; - printf("Trying to set the following mode %s\n", mode); - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_STATE_SET)) != NULL) - { - dbus_message_append_args (req, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); + printf("Trying to set the following mode %s\n", mode); + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_STATE_SET)) != NULL) + { + dbus_message_append_args (req, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); dbus_message_unref(reply); } dbus_message_unref(req); - } + } - if(ret) - { - printf("mode set = %s\n", ret); - return 0; - } - - /* not everything went as planned, return error */ - return 1; + if(ret) + { + printf("mode set = %s\n", ret); + return 0; + } + + /* not everything went as planned, return error */ + return 1; } -static int set_mode_config (char *mode) +static int util_set_mode_config (char *mode) { - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; - printf("Trying to set the following mode %s in the config file\n", mode); - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_CONFIG_SET)) != NULL) - { - dbus_message_append_args (req, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); + printf("Trying to set the following mode %s in the config file\n", mode); + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_CONFIG_SET)) != NULL) + { + dbus_message_append_args (req, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); dbus_message_unref(reply); } dbus_message_unref(req); - } + } - if(ret) - { - printf("mode set in the configuration file = %s\n", ret); - return 0; - } + if(ret) + { + printf("mode set in the configuration file = %s\n", ret); + return 0; + } - /* not everything went as planned, return error */ - return 1; + /* not everything went as planned, return error */ + return 1; } -static int set_hide_mode_config (char *mode) +static int util_set_hide_mode_config (char *mode) { - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; - printf("Trying to hide the following mode %s in the config file\n", mode); - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_HIDE)) != NULL) - { - dbus_message_append_args (req, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); + printf("Trying to hide the following mode %s in the config file\n", mode); + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_HIDE)) != NULL) + { + dbus_message_append_args (req, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); dbus_message_unref(reply); } dbus_message_unref(req); - } + } - if(ret) - { - printf("mode hidden = %s\n", ret); - return 0; - } + if(ret) + { + printf("mode hidden = %s\n", ret); + return 0; + } - /* not everything went as planned, return error */ - return 1; + /* not everything went as planned, return error */ + return 1; } -static int set_unhide_mode_config (char *mode) +static int util_set_unhide_mode_config (char *mode) { - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; - printf("Trying to unhide the following mode %s in the config file\n", mode); - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_UNHIDE)) != NULL) - { - dbus_message_append_args (req, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); + printf("Trying to unhide the following mode %s in the config file\n", mode); + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_UNHIDE)) != NULL) + { + dbus_message_append_args (req, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); dbus_message_unref(reply); } dbus_message_unref(req); - } + } - if(ret) - { - printf("mode unhidden = %s\n", ret); - return 0; - } + if(ret) + { + printf("mode unhidden = %s\n", ret); + return 0; + } - /* not everything went as planned, return error */ - return 1; + /* not everything went as planned, return error */ + return 1; } -static int get_hiddenlist (void) +static int util_get_hiddenlist (void) { - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_HIDDEN_GET)) != NULL) - { + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_HIDDEN_GET)) != NULL) + { if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) { dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); dbus_message_unref(reply); } dbus_message_unref(req); - } + } - if(ret) - { - printf("hidden modes are = %s\n", ret); - return 0; - } + if(ret) + { + printf("hidden modes are = %s\n", ret); + return 0; + } - /* not everything went as planned, return error */ - return 1; + /* not everything went as planned, return error */ + return 1; } -static int handle_network(char *network) +static int util_handle_network(char *network) { - char *operation = 0, *setting = 0, *value = 0; - DBusMessage *req = NULL, *reply = NULL; - char *ret = 0; - - operation = strtok(network, ":"); - printf("Operation = %s\n", operation); - setting = strtok(NULL, ","); - printf("Setting = %s\n", setting); - value = strtok(NULL, ","); - printf("Value = %s\n", value); - if(operation == NULL || setting == NULL ) - { - printf("Argument list is wrong. Please use get:$setting or set:$setting,$value\n"); - return 1; - } - if(!strcmp(operation, "set")) - { - if(value == NULL) - { - printf("Argument list is wrong. Please use set:$setting,$value\n"); - return 1; - } - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_NETWORK_SET)) != NULL) - { - dbus_message_append_args (req, DBUS_TYPE_STRING, &setting, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID); - if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) - { - dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &setting, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); - dbus_message_unref(reply); - } - dbus_message_unref(req); - } - - if(ret) - { - printf("The following USB network setting %s = %s has been set\n", setting, ret); - return 0; - } - else - return 1; - } - else if(!strcmp(operation, "get")) - { - - if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_NETWORK_GET)) != NULL) - { - dbus_message_append_args (req, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID); - if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) - { - dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &setting, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); - dbus_message_unref(reply); - } - dbus_message_unref(req); - } - - if(ret) - { - printf("USB network setting %s = %s\n", setting, ret); - return 0; - } - else - return 1; - } - else - /* unknown operation */ - return 1; -} + char *operation = 0, *setting = 0, *value = 0; + DBusMessage *req = NULL, *reply = NULL; + char *ret = 0; + + operation = strtok(network, ":"); + printf("Operation = %s\n", operation); + setting = strtok(NULL, ","); + printf("Setting = %s\n", setting); + value = strtok(NULL, ","); + printf("Value = %s\n", value); + if(operation == NULL || setting == NULL ) + { + printf("Argument list is wrong. Please use get:$setting or set:$setting,$value\n"); + return 1; + } + if(!strcmp(operation, "set")) + { + if(value == NULL) + { + printf("Argument list is wrong. Please use set:$setting,$value\n"); + return 1; + } + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_NETWORK_SET)) != NULL) + { + dbus_message_append_args (req, DBUS_TYPE_STRING, &setting, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID); + if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) + { + dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &setting, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); + dbus_message_unref(reply); + } + dbus_message_unref(req); + } + if(ret) + { + printf("The following USB network setting %s = %s has been set\n", setting, ret); + return 0; + } + else + return 1; + } + else if(!strcmp(operation, "get")) + { + + if ((req = dbus_message_new_method_call(USB_MODE_SERVICE, USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_NETWORK_GET)) != NULL) + { + dbus_message_append_args (req, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID); + if ((reply = dbus_connection_send_with_reply_and_block(conn, req, -1, NULL)) != NULL) + { + dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &setting, DBUS_TYPE_STRING, &ret, DBUS_TYPE_INVALID); + dbus_message_unref(reply); + } + dbus_message_unref(req); + } + + if(ret) + { + printf("USB network setting %s = %s\n", setting, ret); + return 0; + } + else + return 1; + } + else + /* unknown operation */ + return 1; +} int main (int argc, char *argv[]) { - int query = 0, network = 0, setmode = 0, config = 0; - int modelist = 0, mode_configured = 0, hide = 0, unhide = 0, hiddenlist = 0; - int res = 1, opt, rescue = 0; - char *option = 0; - - if(argc == 1) - { - fprintf(stderr, "No options given, try -h for more information\n"); - exit(1); - } - - while ((opt = getopt(argc, argv, "c:dhi:mn:qrs:u:v")) != -1) - { - switch (opt) { - case 'c': - config = 1; - option = optarg; - break; - case 'd': - mode_configured = 1; - break; - case 'i': - hide = 1; - option = optarg; - break; - case 'm': - modelist = 1; - break; - case 'n': - network = 1; - option = optarg; - break; - case 'q': - query = 1; - break; - case 'r': - rescue = 1; - break; - case 's': - setmode = 1; - option = optarg; - break; - case 'u': - unhide = 1; - option = optarg; - break; - case 'v': - hiddenlist = 1; - break; - case 'h': - default: - fprintf(stderr, "\nUsage: %s -