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 -