diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..e57d917 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = src + +EXTRA_DIST = \ + autogen.sh \ + debian/* + +doc: + cd $(top_srcdir)/docs && $(MAKE) && cd .. + +.PHONY: doc + +deb: dist + -mkdir $(top_builddir)/debian-build + cd $(top_builddir)/debian-build && tar zxf ../$(top_builddir)/$(PACKAGE)-$(VERSION).tar.gz + cd $(top_builddir)/debian-build/$(PACKAGE)-$(VERSION) && dpkg-buildpackage -rfakeroot + -rm -rf $(top_builddir)/debian-build/$(PACKAGE)-$(VERSION) + +DISTCLEANFILES = *~ diff --git a/TODO b/TODO new file mode 100644 index 0000000..e69de29 diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..8793b76 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -x +libtoolize --automake --copy +aclocal +autoconf +autoheader +automake --add-missing --foreign --copy diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..b5d988f --- /dev/null +++ b/configure.ac @@ -0,0 +1,90 @@ +AC_INIT([usb_moded], [0.33]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) + +AM_CONFIG_HEADER([config.h]) + +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LIBTOOL + +AC_C_CONST +AC_HEADER_STDC + +test_gcc_flag() { + AC_LANG_CONFTEST([int main() {}]) + $CC -c conftest.c $CFLAGS $@ > /dev/null 2> /dev/null + ret=$? + rm -f conftest.o + return $ret +} + +# If using GCC specify some additional parameters +if test "x$GCC" = "xyes" ; then + # We use gnu99 instead of c99 because many have interpreted the standard + # in a way that int64_t isn't defined on non-64 bit platforms. + DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wmissing-noreturn -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter" + + for flag in $DESIRED_FLAGS ; do + AC_MSG_CHECKING([whether $CC accepts $flag]) + if test_gcc_flag $flag ; then + CFLAGS="$CFLAGS $flag" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + done +fi + +AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug],[Enable debug @<:@default=false@:>@]), + [case "${enableval}" in + yes) debug=true ; CFLAGS="-ggdb -O0 -DDEBUG -DOSSOLOG_STDERR $CFLAGS" ;; + no) debug=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; + esac],[debug=false]) +AM_CONDITIONAL([DEBUG], [test x$debug = xtrue]) + +AC_ARG_ENABLE([nokia], AS_HELP_STRING([--enable-nokia], [Enable Nokia extra's @<:@default=false@:>@]), + [case "${enableval}" in + yes) nokia=true ; CFLAGS="-DNOKIA $CFLAGS" ;; + no) nokia=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-nokia]) ;; + esac],[nokia=false]) +AM_CONDITIONAL([NOKIA], [test x$nokia = xtrue]) + +AC_ARG_ENABLE([app_sync], AS_HELP_STRING([--enable-app-sync], [Enable application syncing @<:@default=false@:>@]), + [case "${enableval}" in + yes) app_sync=true ; CFLAGS="-DAPP_SYNC $CFLAGS" ;; + no) app_sync=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-app_sync]) ;; + esac],[app_sync=false]) +AM_CONDITIONAL([APP_SYNC], [test x$app_sync = xtrue]) + +PKG_CHECK_MODULES([USB_MODED], [ + glib-2.0 >= 2.2.0 + dbus-1 >= 1.2.1 + dbus-glib-1 >= 0.78 + gobject-2.0 >= 2.16.6 + gconf-2.0 >= 2.16.0 + gio-2.0 +]) + +AC_SUBST(USB_MODED_LIBS) +AC_SUBST(USB_MODED_CFLAGS) + +AC_CONFIG_FILES([ + Makefile + src/Makefile + usb_moded.pc + docs/usb_moded-doxygen.conf + docs/Makefile +]) + +echo " + == $PACKAGE_NAME $VERSION == + + Compiler: ${CC} + CFLAGS: ${CFLAGS} + + Debug enabled: ${debug} +" +AC_OUTPUT diff --git a/dbus-send-test.txt b/dbus-send-test.txt new file mode 100644 index 0000000..e57a312 --- /dev/null +++ b/dbus-send-test.txt @@ -0,0 +1,8 @@ +dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.mode_request +dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.set_mode string:'ovi_suite' +dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.set_config string:'ovi_suite' +dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.set_mode string:'mass_storage' + +security extra: +aegis-exec -a usb-moded::USBControl + diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..b899ff2 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,6 @@ +usb-moded +--------- + +Replaces ke-recv + + -- Philippe De Swert Tue, 09 Mar 2010 11:28:10 +0200 diff --git a/debian/api b/debian/api new file mode 100644 index 0000000..1a5f48e --- /dev/null +++ b/debian/api @@ -0,0 +1,6 @@ +interface: usb_moded +type: dbus +scope: Internal +state: unstable +dev-pkg: usb-moded-dev + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..6b03f89 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,253 @@ +usb-moded (0.33) unstable; urgency=low + + * More security guesswork. Hopefully the doxygen tags are + correct now. Fixes: NB#231818 + + -- Philippe De Swert Thu, 17 Mar 2011 12:48:49 +0200 + +usb-moded (0.32) unstable; urgency=low + + * Coverity fixes. Fixes: NB#235405 + * Make charging fallback timeout shorter. Fixes: NB#234094 + + -- Philippe De Swert Thu, 10 Mar 2011 16:08:58 +0200 + +usb-moded (0.31) unstable; urgency=low + + * Fix appearance of drive even if umounting fails. Fixes: NB#229105 + * Mode setting and clean-up seperated from module loading. + * Fix dev package dependencies. Fixes: NB#232170 + * Add credential tags to header file. Fixes: NB#231818 + + -- Philippe De Swert Mon, 28 Feb 2011 14:21:58 +0200 + +usb-moded (0.30) unstable; urgency=low + + * signal re-mounting error, and mount fallback. Fixes: NB#207408 + + -- Philippe De Swert Fri, 11 Feb 2011 16:14:24 +0200 + +usb-moded (0.29) unstable; urgency=low + + * Don't build docs when NODOCS is specified in the Debian build options. Fixes: NB#226245 + Patch supplied by Yakubenko Sergey + * Listen to DSME shutdown signal to disconnect the current mode for ACT_DEAD. Fixes: NB#209842 + * Updated doxygen config to remove errors. + + -- Philippe De Swert Thu, 10 Feb 2011 12:11:04 +0200 + +usb-moded (0.28) unstable; urgency=low + + * Make sure filesystem is remounted before sending disconnect signal + * Send pre-unmount signal. Fixes: NB#187735 + + -- Philippe De Swert Tue, 25 Jan 2011 14:51:33 +0200 + +usb-moded (0.27) unstable; urgency=low + + * Do not error out in case the filesystem is still unmounted. Fixes: NB#218025 + + -- Philippe De Swert Wed, 12 Jan 2011 13:57:44 +0200 + +usb-moded (0.26) unstable; urgency=low + + * Improve robustness of appsync file parsing. Fixes: NB#209600 + * Make sure we do not exit when session dbus dies. Fixes: NB#210575 + + -- Philippe De Swert Fri, 10 Dec 2010 16:05:16 +0200 + +usb-moded (0.25) unstable; urgency=low + + * Silence output of system() calls when not in debug mode + * Improve program killer to avoid unnecessary work + * Increase debouncing timeout. Fixes: NB#193301 + + -- Philippe De Swert Mon, 29 Nov 2010 16:34:23 +0200 + +usb-moded (0.24) unstable; urgency=low + + * Send error signals when something goes wrong. Fixes: NB#197206 + * Delay module unloading. To avoid unload/reload on fast disconnect/reconnect. Fixes: NB#193301 + + -- Philippe De Swert Tue, 16 Nov 2010 12:31:20 +0200 + +usb-moded (0.23) unstable; urgency=low + + * Correct nsu mode detection by not using /proc/bootreason. Fixes: NB#193559 + + -- Philippe De Swert Thu, 11 Nov 2010 17:16:07 +0200 + +usb-moded (0.22) unstable; urgency=low + + * Check for nsu mode and then do nothing until cable gets unplugged/replugged + * Update connect mode for g_nokia + * Sync after mtp mode disconnection as suggested by Bityutskiy Artem. + + -- Philippe De Swert Mon, 18 Oct 2010 15:42:15 +0300 + +usb-moded (0.21) unstable; urgency=low + + * Do not unload mass_storage when going into charging mode. Avoids USB cert issues + when the devicelock is not functioning or replying. Fixes: NB#196588 + + -- Philippe De Swert Fri, 08 Oct 2010 12:55:27 +0300 + +usb-moded (0.20) unstable; urgency=low + + * Do not try to mount fs if it is not unmounted + * Clean up dirty devicelock fix + + -- Philippe De Swert Wed, 29 Sep 2010 12:14:55 +0300 + +usb-moded (0.19) unstable; urgency=low + + * Implement CR for app sync. + * Log everything with logging functions and remove fprintf + * Fix logic error in mount/umount. Fixes: NB#178489 + + -- Philippe De Swert Mon, 20 Sep 2010 16:32:07 +0300 + +usb-moded (0.18) unstable; urgency=low + + * Add fua handling. Fixes: NB#187000 + * Remove static options for g_file_storage that belong in /etc/modprobe.d + * Add a check in connection routine to only select a mode if the connection status is false + * Remove non necessary and non standard desktop ready signals and fix the mode broadcasting signals + + -- Philippe De Swert Tue, 07 Sep 2010 13:30:41 +0300 + +usb-moded (0.17) unstable; urgency=low + + * Improve charger detection to avoid showing connection dialog when + using wall charger. Fixes: NB#169825 + * Get rid of HAL completely to increase MeeGo support while at it + * Include autotools in build-dependencies. Fixes: NB#187685 + + -- Tuomo Tanskanen Mon, 30 Aug 2010 10:26:44 +0300 + +usb-moded (0.16) unstable; urgency=low + + * Add aegis manifest. Fixes: NB#182124 + * Add g_ether/windows_network mode for mad development + * Fix most superfluous linking + + -- Philippe De Swert Tue, 10 Aug 2010 11:01:11 +0300 + +usb-moded (0.15) unstable; urgency=low + + * If mode change is requested, do not change mode if requested mode is already active. Fixes: NB#181153 + * Check if devicelock is unlocked and initiate connection if the cable has been inserted previously + + -- Philippe De Swert Thu, 22 Jul 2010 17:29:57 +0300 + +usb-moded (0.14) unstable; urgency=low + + * Route -n does not always return default... Fixes: NB#175249 + + -- Philippe De Swert Mon, 21 Jun 2010 14:21:14 +0300 + +usb-moded (0.13) unstable; urgency=low + + * Only activate usb network if no other network is up. + * use GConf schema instead of gconftool-2 in postinst. Fixes: NB#174536 + + -- Philippe De Swert Mon, 14 Jun 2010 16:13:17 +0300 + +usb-moded (0.12) unstable; urgency=low + + * Improved killer. Does not ignore mtp and gc interfaces and tries to be + less agressive with sigterm before sigkill. + + -- Philippe De Swert Mon, 07 Jun 2010 11:28:33 +0300 + +usb-moded (0.11) unstable; urgency=low + + * Add removable=1 flag to the mass-storage profile. Fixes: NB#159847 + + -- Philippe De Swert Tue, 01 Jun 2010 14:40:21 +0300 + +usb-moded (0.10) unstable; urgency=low + + * Make devicelock and act_dead stuff Nokia specific. + * Add lsof dependency + + -- Philippe De Swert Fri, 28 May 2010 16:36:17 +0300 + +usb-moded (0.9) unstable; urgency=low + + * Add devicelock support. Implemented: SWP#MaSSW-1743 + * Send data in use signal when mass storage is chosen. + * Do not export anything in act_dead mode. + + -- Philippe De Swert Tue, 25 May 2010 15:37:32 +0300 + +usb-moded (0.8-1) unstable; urgency=low + + * Added use_mtp=1 parameter to loading of g_nokia as TEMPORARY workaround + (Fixes: NB#170537) + + -- Pekka Lundstrom Wed, 26 May 2010 13:26:45 +0300 + +usb-moded (0.8) unstable; urgency=low + + * Tweak dbus security policy to let users invoke the query and set_mode methods + Fixes: NB#169901 + * clean-up some lintian warnings. + * add preparations for devicelock support + + -- Philippe De Swert Mon, 24 May 2010 11:52:51 +0300 + +usb-moded (0.7) unstable; urgency=low + + * Introduce killer for unstable programs that block module unloading. + + -- Philippe De Swert Tue, 11 May 2010 12:50:19 +0300 + +usb-moded (0.6) unstable; urgency=low + + * Make usb mass storage work + * Bring up usb network interface + * Charging mode loads g_file_storage without exporting fs + * Switching modes works if nobody claims the interfaces so modules can be unloaded + + -- Philippe De Swert Sat, 08 May 2010 14:24:47 +0300 + +usb-moded (0.5) unstable; urgency=low + + * Make sure that the charging fallback does not override the chosen mode. + * Fix some lintian warnings. + * Improve g_file_storage loading and add mount point config file. + + -- Philippe De Swert Fri, 30 Apr 2010 15:58:50 +0300 + +usb-moded (0.4) unstable; urgency=low + + * Split the logging functions to their own files + * Add documentation with doxygen + + -- Philippe De Swert Wed, 28 Apr 2010 20:56:34 +0300 + +usb-moded (0.3) unstable; urgency=low + + * Usb-moded start before HAL d-bus interface is ready. Thanks to Simo Piiroinen. Fixes: NB#165616 + * Add postinstall script so gconf is set up correctly + + -- Philippe De Swert Tue, 27 Apr 2010 13:14:44 +0300 + +usb-moded (0.2) unstable; urgency=low + + * Add introspective dbus support for QDBusInterface (thanks to David Kedves) + * Make dbus conf a bit more permissive + * pre-eliminary module loading/unloading + * add ability to set gconf key (new method call). + * fix wrong path in .pc file. Fixes: NB#165780 + + -- Philippe De Swert Mon, 26 Apr 2010 19:12:58 +0300 + +usb-moded (0.1-1) unstable; urgency=low + + * Initial release + Fixes: NB#156765, NB#159816 + + -- Philippe De Swert Tue, 09 Mar 2010 11:28:10 +0200 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..9f3e929 --- /dev/null +++ b/debian/control @@ -0,0 +1,49 @@ +Source: usb-moded +Section: misc +Priority: optional +Maintainer: Philippe De Swert +Build-Depends: debhelper (>= 5), autoconf, automake, libdbus-1-dev, libdbus-glib-1-dev, libglib2.0-dev, libgconf2-dev, doxygen, aegis-builder +Standards-Version: 3.8.0 + +Package: usb-moded +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, lsof +Description: usb_moded - USB mode controller + Usb_moded is a daemon to control the USB states. For this + it loads unloads the relevant usb gadget modules, keeps track + of the filesystem(s) and notifies about changes on the DBUS + system bus. + +Package: usb-moded-doc +Section: doc +Architecture: any +Depends: usb-moded (= ${binary:Version}), ${misc:Depends} +Description: usb_moded - USB mode controller - documentation + Usb_moded is a daemon to control the USB states. For this + it loads unloads the relevant usb gadget modules, keeps track + of the filesystem(s) and notifies about changes on the DBUS + system bus. + === This package contains the documentation === + +Package: usb-moded-dbg +Section: debug +Architecture: any +Depends: usb-moded (= ${binary:Version}), ${misc:Depends} +Priority: extra +Description: usb_moded - USB mode controller - Debug symbols + Usb_moded is a daemon to control the USB states. For this + it loads unloads the relevant usb gadget modules, keeps track + of the filesystem(s) and notifies about changes on the DBUS + system bus. + === This package contains the debug symbols === + +Package: usb-moded-dev +Architecture: any +Depends: ${misc:Depends}, libdbus-1-dev +Description: usb_moded - USB mode controller - development files + Usb_moded is a daemon to control the USB states. For this + it loads unloads the relevant usb gadget modules, keeps track + of the filesystem(s) and notifies about changes on the DBUS + system bus. + === This package contains the files needed to program for usb_moded === + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..26d2510 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,15 @@ +This package was debianized by Philippe De Swert on +Tue, 09 Mar 2010 11:28:10 +0200. + +Author: Philippe De Swert + +Copyright: + + + +License: + + LGPL v2 + +The Debian packaging is Copyright © 2010, Philippe De Swert and +is licensed under the LGPL, see `/usr/share/common-licenses/LGPL'. diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..236670a --- /dev/null +++ b/debian/dirs @@ -0,0 +1 @@ +usr/sbin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..1333ed7 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +TODO diff --git a/debian/manpage.1 b/debian/manpage.1 new file mode 100644 index 0000000..e3c5881 --- /dev/null +++ b/debian/manpage.1 @@ -0,0 +1,62 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH USB-MODED SECTION "March 9, 2010" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +usb_moded \- USB mode controlling daemon +.SH SYNOPSIS +.B usb_moded +.RI [ options ] " files" ... +.br +.B bar +.RI [ options ] " files" ... +.SH DESCRIPTION +This manual page documents briefly the +.B usb-moded +commands. +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +\fBusb-moded\fP is a program that controls the loading and unloading of usb gadget modules and +keeps track of the USB state the device is in. +.SH OPTIONS +These programs follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +For a complete description, see the Info files. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-d, \-\-daemonflag +run as a daemon +.B \-s, \-\-force-syslog +log to syslog +.B \-T, \-\-force-stderr +log to stderr even when daemonized +.B \-D, \-\-debug +turn on debug printing +.B \-h, \-\-help +display this help and exit +.B \-v, \-\-version +Show version of program. +.br +.SH AUTHOR +usb-moded was written by . +(c) Copyrigh Nokia, 2010 +.PP +This manual page was written by Philippe De Swert diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..0a01cad --- /dev/null +++ b/debian/rules @@ -0,0 +1,120 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +MAKE_DOCS=1 + +ifneq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS))) + MAKE_DOCS=0 +endif + + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + if [ ! -x configure ]; then ./autogen.sh; fi + ./configure --prefix=/usr --enable-nokia --enable-app-sync + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + $(MAKE) +ifneq (0,$(MAKE_DOCS)) + $(MAKE) doc +endif + #docbook-to-man debian/usb-moded.sgml > usb-moded.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + [ ! -f Makefile ] || $(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/usb-moded. + $(MAKE) DESTDIR=$(CURDIR)/debian/usb-moded install + #mkdir -p $(CURDIR)/debian/usb-moded/etc/dbus-1/system.d/ + #install -m 644 $(CURDIR)/debian/usb_moded.conf $(CURDIR)/debian/usb-moded/etc/dbus-1/system.d/usb_moded.conf + mkdir -p $(CURDIR)/debian/usb-moded-dev/usr/include/usb-moded/ + install -m 644 $(CURDIR)/src/usb_moded-dbus.h $(CURDIR)/debian/usb-moded-dev/usr/include/usb-moded/usb_moded-dbus.h + install -m 644 $(CURDIR)/src/usb_moded-modes.h $(CURDIR)/debian/usb-moded-dev/usr/include/usb-moded/usb_moded-modes.h + install -m 644 $(CURDIR)/src/usb_moded-appsync-dbus.h $(CURDIR)/debian/usb-moded-dev/usr/include/usb-moded/usb_moded-appsync-dbus.h + mkdir -p $(CURDIR)/debian/usb-moded-dev/usr/lib/pkgconfig + install -m 644 $(CURDIR)/usb_moded.pc $(CURDIR)/debian/usb-moded-dev/usr/lib/pkgconfig/usb_moded.pc +ifneq (0,$(MAKE_DOCS)) + mkdir -p $(CURDIR)/debian/usb-moded-doc/usr/share/doc/usb-moded/html/ + cp $(CURDIR)/docs/html/* $(CURDIR)/debian/usb-moded-doc/usr/share/doc/usb-moded/html/ +endif + mkdir -p $(CURDIR)/debian/usb-moded/etc/usb-moded + install -m 644 $(CURDIR)/usb-moded.ini $(CURDIR)/debian/usb-moded/etc/usb-moded/usb-moded.ini + mkdir -p $(CURDIR)/debian/usb-moded/etc/gconf/schemas + install -m 644 $(CURDIR)/debian/usb-moded.schemas $(CURDIR)/debian/usb-moded/etc/gconf/schemas/usb-moded.schemas + + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs +# dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_gconf + dh_installman + dh_link + dh_strip --dbg-package=usb-moded-dbg + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + aegis-deb-add -control debian/usb-moded/DEBIAN/control .. debian/usb-moded.aegis=_aegis + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/debian/usb-moded-doc.doc-base b/debian/usb-moded-doc.doc-base new file mode 100644 index 0000000..04f3da9 --- /dev/null +++ b/debian/usb-moded-doc.doc-base @@ -0,0 +1,10 @@ +Document: usb-moded +Title: Debian usb-moded Manual +Author: Philippe De Swert +Abstract: Contains the documentation for the developers in html format +Section: System/Administration + +Format: HTML +Index: /usr/share/doc/usb-moded/html/index.html +Files: /usr/share/doc/usb-moded/html/*.html + diff --git a/debian/usb-moded.aegis b/debian/usb-moded.aegis new file mode 100644 index 0000000..bbc329b --- /dev/null +++ b/debian/usb-moded.aegis @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/debian/usb-moded.schemas b/debian/usb-moded.schemas new file mode 100644 index 0000000..7d45606 --- /dev/null +++ b/debian/usb-moded.schemas @@ -0,0 +1,17 @@ + + + + + /schemas/Meego/System/UsbMode + /Meego/System/UsbMode + usb_moded + string + ask + + Default mode to set for usb_moded + This key contains the default mode usb_moded will set if usb is connected. + + + + + diff --git a/debian/usb_moded.conf b/debian/usb_moded.conf new file mode 100644 index 0000000..e200c35 --- /dev/null +++ b/debian/usb_moded.conf @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..5e3eb5f --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,10 @@ +# tells make to run html-local when the user asks for 'all'. +all: doc + +doc: + rm -rf html/ + doxygen usb_moded-doxygen.conf + +clean-local: + -rm -rf html/ + diff --git a/docs/usb_moded-doxygen.conf.in b/docs/usb_moded-doxygen.conf.in new file mode 100644 index 0000000..cf8e36f --- /dev/null +++ b/docs/usb_moded-doxygen.conf.in @@ -0,0 +1,1631 @@ +# Doxyfile 1.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PACKAGE@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = NO + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c \ + *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NONE + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..6d4fbc7 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,46 @@ +sbin_PROGRAMS = usb_moded + +usb_moded_CPPFLAGS = \ + $(USB_MODED_CFLAGS) + +usb_moded_LDFLAGS = \ + -Wl,--as-needed + +usb_moded_LDADD = \ + $(USB_MODED_LIBS) + +usb_moded_SOURCES = \ + usb_moded.c \ + usb_moded.h \ + usb_moded-modes.h \ + usb_moded-chargerdetection.c \ + usb_moded-dbus.c \ + usb_moded-dbus.h \ + usb_moded-dbus-private.h \ + usb_moded-gconf.c \ + usb_moded-gconf.h \ + usb_moded-gconf-private.h \ + usb_moded-hw-ab.h \ + usb_moded-modules.c \ + usb_moded-modules.h \ + usb_moded-log.h \ + usb_moded-log.c \ + usb_moded-config.c \ + usb_moded-config.h \ + usb_moded-modesetting.c \ + usb_moded-modesetting.h +if NOKIA +usb_moded_SOURCES += \ + usb_moded-devicelock.h \ + usb_moded-devicelock.c +endif + +if APP_SYNC +usb_moded_SOURCES += \ + usb_moded-appsync.c \ + usb_moded-appsync.h \ + usb_moded-appsync-dbus.c \ + usb_moded-appsync-dbus.h \ + usb_moded-appsync-dbus-private.h +endif + diff --git a/src/usb_moded-appsync-dbus-private.h b/src/usb_moded-appsync-dbus-private.h new file mode 100644 index 0000000..26642fd --- /dev/null +++ b/src/usb_moded-appsync-dbus-private.h @@ -0,0 +1,23 @@ +/* + 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 +*/ + +gboolean usb_moded_app_sync_init(GList *list); +void usb_moded_appsync_cleanup(GList *list); +int usb_moded_dbus_app_launch(const char *launch); diff --git a/src/usb_moded-appsync-dbus.c b/src/usb_moded-appsync-dbus.c new file mode 100644 index 0000000..878525b --- /dev/null +++ b/src/usb_moded-appsync-dbus.c @@ -0,0 +1,204 @@ +/** + @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 +*/ + +#include +#include + +#include +#include +#include + +#include "usb_moded-dbus.h" +#include "usb_moded-dbus-private.h" +#include "usb_moded.h" +#include "usb_moded-log.h" +#include "usb_moded-modes.h" +#include "usb_moded-gconf-private.h" +#include "usb_moded-appsync.h" +#include "usb_moded-appsync-dbus.h" +#include "usb_moded-appsync-dbus-private.h" + +static DBusConnection *dbus_connection_ses = NULL; + +static DBusHandlerResult 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); + + + if(!interface || !member || !object) 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_APP_STATE)) + { + 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 + { + + if(mark_active((GList *)user_data, use)) + goto error_reply; + else + { + 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 + { + /*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); + } + + +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; +} + +/** + * Init dbus for usb_moded application synchronisation + * + * @return TRUE when everything went ok + */ +gboolean usb_moded_app_sync_init(GList *list) +{ + gboolean status = FALSE; + DBusError error; + int ret; + + dbus_error_init(&error); + + /* connect to session bus */ + if ((dbus_connection_ses = dbus_bus_get_private(DBUS_BUS_SESSION, &error)) == NULL) + { + log_err("Failed to open connection to session message bus; %s\n", error.message); + goto EXIT; + } + + /* 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); + + /* Initialise message handlers */ + if (!dbus_connection_add_filter(dbus_connection_ses, msg_handler, list, NULL)) + { + log_err("failed to add filter\n"); + goto EXIT; + } + /* Acquire D-Bus service */ + ret = dbus_bus_request_name(dbus_connection_ses, USB_MODE_SERVICE, DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_ALLOW_REPLACEMENT , &error); + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) + { + log_err("failed claiming dbus name\n"); + if( dbus_error_is_set(&error) ) + log_debug("DBUS ERROR: %s, %s \n", error.name, error.message); + goto EXIT; + } + + /* Connect D-Bus to the mainloop */ + dbus_connection_setup_with_g_main(dbus_connection_ses, NULL); + + /* everything went fine */ + status = TRUE; + +EXIT: + dbus_error_free(&error); + return status; +} + +/** + * Clean up the dbus connections for the application + * synchronisation after sync is done + */ +void usb_moded_appsync_cleanup(GList *list) +{ + DBusError error; + + dbus_error_init(&error); + /* clean up system bus connection */ + if (dbus_connection_ses != NULL) + { + dbus_bus_release_name(dbus_connection_ses, USB_MODE_SERVICE, &error); + dbus_connection_remove_filter(dbus_connection_ses, msg_handler, list); + dbus_connection_close(dbus_connection_ses); + dbus_connection_unref(dbus_connection_ses); + dbus_connection_ses = NULL; + log_debug("succesfully cleaned up appsync dbus\n"); + } + dbus_error_free(&error); +} + +/** + * Launch applications over dbus that need to be synchronized + */ +int usb_moded_dbus_app_launch(const char *launch) +{ + DBusConnection *dbus_conn = NULL; + DBusError error; + int ret = 0; + + dbus_error_init(&error); + + if( (dbus_conn = dbus_bus_get(DBUS_BUS_SESSION, &error)) == 0 ) + { + log_err("Could not connect to dbus session\n"); + } + + dbus_bus_start_service_by_name(dbus_conn, launch, 0, NULL, &error); + + dbus_connection_unref(dbus_conn); + + return(ret); +} diff --git a/src/usb_moded-appsync-dbus.h b/src/usb_moded-appsync-dbus.h new file mode 100644 index 0000000..d067e92 --- /dev/null +++ b/src/usb_moded-appsync-dbus.h @@ -0,0 +1,28 @@ +/* + 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 + +#define USB_MODE_SERVICE "com.meego.usb_moded" +#define USB_MODE_INTERFACE "com.meego.usb_moded" +#define USB_MODE_OBJECT "/com/meego/usb_moded" + +/* supported methods */ +#define USB_MODE_APP_STATE "ready" diff --git a/src/usb_moded-appsync.c b/src/usb_moded-appsync.c new file mode 100644 index 0000000..6492ce0 --- /dev/null +++ b/src/usb_moded-appsync.c @@ -0,0 +1,204 @@ +/** + @file usb_moded-config.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 +*/ + +#include +#include +#include +#include + +#include +#include + +#include "usb_moded-appsync.h" +#include "usb_moded-appsync-dbus.h" +#include "usb_moded-appsync-dbus-private.h" +#include "usb_moded-log.h" + +static struct list_elem *read_file(const gchar *filename); + +GList *readlist(void) +{ + GDir *confdir; + GList *applist = NULL; + const gchar *dirname; + struct list_elem *list_item; + + confdir = g_dir_open(CONF_DIR_PATH, 0, NULL); + if(confdir) + { + while((dirname = g_dir_read_name(confdir)) != NULL) + { + log_debug("Read file %s\n", dirname); + list_item = read_file(dirname); + if(list_item) + applist = g_list_append(applist, list_item); + } + + } + else + log_debug("confdir open failed.\n"); + return(applist); +} + +static struct list_elem *read_file(const gchar *filename) +{ + GKeyFile *settingsfile; + gboolean test = FALSE; + gchar **keys; + const char *name_char, *launch_char; + struct list_elem *list_item = NULL; + gchar *full_filename = NULL; + + full_filename = g_strconcat(CONF_DIR_PATH, "/", filename, NULL); + + settingsfile = g_key_file_new(); + test = g_key_file_load_from_file(settingsfile, full_filename, G_KEY_FILE_NONE, NULL); + /* free full_filename immediately as we do not use it anymore */ + free(full_filename); + if(!test) + { + return(NULL); + } + list_item = malloc(sizeof(struct list_elem)); + keys = g_key_file_get_keys (settingsfile, APP_INFO_ENTRY , NULL, NULL); + while (*keys != NULL) + { + if(!strcmp(*keys, APP_INFO_NAME_KEY)) + { + name_char = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, *keys, NULL); + if(name_char) + { + list_item->name = g_strdup(name_char); + log_debug("Appname = %s\n", name_char); + } + } + if(!strcmp(*keys, APP_INFO_LAUNCH_KEY)) + { + launch_char = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, *keys, NULL); + if(launch_char) + { + list_item->launch = g_strdup(launch_char); + log_debug("launch path = %s\n", launch_char); + } + } + keys++; + } + g_key_file_free(settingsfile); + if(launch_char == NULL || name_char == NULL) + { + /* free list_item as it will not be used */ + free(list_item); + return NULL; + } + else + return(list_item); +} + +int activate_sync(GList *list) +{ + /* set list to inactive */ + do + { + struct list_elem *data = list->data; + data->active = 0; + } + while(g_list_next(list) != NULL); + + /* add dbus filter. Use session bus for ready method call? */ + if(!usb_moded_app_sync_init(list)) + { + log_debug("dbus setup failed => activate immediately \n"); + enumerate_usb(NULL); + return(1); + } + + /* go through list and launch apps */ + do + { + struct list_elem *data = list->data; + log_debug("launching app %s\n", data->launch); + usb_moded_dbus_app_launch(data->launch); + } + while(g_list_next(list) != NULL); + + /* start timer */ + log_debug("Starting timer\n"); + g_timeout_add_seconds(2, enumerate_usb, list); + + return(0); +} + +int mark_active(GList *list, const gchar *name) +{ + int ret = 0; + static int list_length=0; + int counter=0; + + log_debug("app %s notified it is ready\n", name); + if(list_length == 0) + list_length = g_list_length(list); + + do + { + struct list_elem *data = list->data; + if(!strcmp(data->name, name)) + { + if(!data->active) + { + data->active = 1; + counter++; + + if(list_length == counter) + { + counter = 0; + log_debug("All apps active. Let's enumerate\n"); + enumerate_usb(list); + } + ret = 0; + break; + } + else + { + ret = 1; + } + } + } + while(g_list_next(list) != NULL); + + return(ret); +} + +gboolean enumerate_usb(gpointer data) +{ + + /* activate usb connection/enumeration */ + system("echo 1 > /sys/devices/platform/musb_hdrc/gadget/softconnect"); + + /* no need to remove timer */ + + /* remove dbus filter */ + if(data != NULL) + usb_moded_appsync_cleanup((GList *)data); + + /* return false to stop the timer from repeating */ + return(FALSE); +} diff --git a/src/usb_moded-appsync.h b/src/usb_moded-appsync.h new file mode 100644 index 0000000..230d164 --- /dev/null +++ b/src/usb_moded-appsync.h @@ -0,0 +1,38 @@ +/* + + 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 +*/ + +#define CONF_DIR_PATH "/etc/usb-moded/run" + +#define APP_INFO_ENTRY "info" +#define APP_INFO_NAME_KEY "name" +#define APP_INFO_LAUNCH_KEY "launch" + +typedef struct list_elem +{ + char *name; + char *launch; + int active; +}list_elem; + +GList *readlist(void); +int activate_sync(GList *list); +int mark_active(GList *list, const gchar *name); +gboolean enumerate_usb(gpointer data); diff --git a/src/usb_moded-chargerdetection.c b/src/usb_moded-chargerdetection.c new file mode 100644 index 0000000..38bd47b --- /dev/null +++ b/src/usb_moded-chargerdetection.c @@ -0,0 +1,294 @@ +/** + @file usb_moded-chargerdetection.c + + Copyright (C) 2010 Nokia Corporation. All rights reserved. + + @author: Philippe De Swert + Simo Piiroinen + Tuomo Tanskanen + + 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 +#include + +#include "usb_moded.h" +#include "usb_moded-hw-ab.h" +#include "usb_moded-log.h" + +/* ========================================================================= * + * Quick guide to the state logic ... + * + * startup: + * @ hwal_init() + * - connect to system bus + * + * hwaö_dbus_message_cb + * @ hwal_set_usb_connected() + * - broadcast connection status over dbus + * + * shutdown: + * @ hwal_cleanup() + * - forget dbus connection + * + * dbus disconnect: + * - exit + * ========================================================================= */ + +/* ========================================================================= * + * CONSTANTS + * ========================================================================= */ + +#define BME_INTERFACE_DBUS "com.nokia.bme.signal" +#define BME_PATH_DBUS "/com/nokia/bme/signal" +#define BME_MEMBER_CHARGER_CONNECTED "charger_connected" +#define BME_MEMBER_CHARGER_DISCONNECTED "charger_disconnected" + +// D-Bus signal match for tracking bme signal on charger connections +#define MATCH_BME_CHARGER_CONNECTED\ + "type='signal'"\ + ",interface='"BME_INTERFACE_DBUS"'"\ + ",path='"BME_PATH_DBUS"'"\ + ",member='"BME_MEMBER_CHARGER_CONNECTED"'" + +// D-Bus signal match for tracking bme signal on charger disconnections +#define MATCH_BME_CHARGER_DISCONNECTED\ + "type='signal'"\ + ",interface='"BME_INTERFACE_DBUS"'"\ + ",path='"BME_PATH_DBUS"'"\ + ",member='"BME_MEMBER_CHARGER_DISCONNECTED"'" + +// D-Bus signal match to catch DESKTOP_VISIBLE in case of act_dead->user transition +#define STARTUP_INTERFACE_DBUS "com.nokia.startup.signal" +#define STARTUP_PATH_DBUS "/com/nokia/startup/signal" +#define STARTUP_MEMBER_DESKTOP_VISIBLE "desktop_visible" + +// D-Bus signal match for desktop visible signal +#define MATCH_STARTUP_DESKTOP_VISIBLE\ + "type='signal'"\ + ",interface='"STARTUP_INTERFACE_DBUS"'"\ + ",path='"STARTUP_PATH_DBUS"'"\ + ",member='"STARTUP_MEMBER_DESKTOP_VISIBLE"'" + +// id's meaning usb host connection in /sys/class/power_supply/usb/uevent" +#define USB_UEVENT_FILE "/sys/class/power_supply/usb/uevent" +#define USB_TYPE1 "POWER_SUPPLY_TYPE=USB_CDP" +#define USB_TYPE2 "POWER_SUPPLY_TYPE=USB\n" +#define USB_PRESENT "POWER_SUPPLY_PRESENT=1" + + +/* ========================================================================= * + * STATE VARIABLES + * ========================================================================= */ + +static DBusConnection *hwal_dbus_con = 0; // system bus connection + + +/* ========================================================================= * + * STATE LOGIC FUNCTIONS + * ========================================================================= */ + +/* ------------------------------------------------------------------------- * + * hwal_is_usb_host_connected -- get charger type from sysfs, triggered by + * bme dbus signal about charger connection + * ------------------------------------------------------------------------- */ + +static gboolean hwal_is_usb_host_connected(void) +{ + gboolean is_usb = TRUE; + gchar *file_content = NULL; + gsize file_length = 0; + + // read uevent file contents, check for keywords and see if its host usb + if (g_file_get_contents(USB_UEVENT_FILE, &file_content, &file_length, NULL) == TRUE) + { + gboolean usb_type1_found = FALSE, usb_type2_found = FALSE; + gboolean usb_cable_present = FALSE; + + usb_type1_found = (g_strrstr(file_content, USB_TYPE1) != NULL); + usb_type2_found = (g_strrstr(file_content, USB_TYPE2) != NULL); + usb_cable_present = (g_strrstr(file_content, USB_PRESENT) != NULL); + + log_debug("%s: type1=%d, type2=%d, present=%d\n", + __FUNCTION__, usb_type1_found, usb_type2_found, usb_cable_present); + g_free(file_content); + + is_usb = usb_cable_present & (usb_type1_found | usb_type2_found); + } + + /* fallback value is TRUE, so in case of errors we rather show dialog + * than keep silent, thus disabling usb practically */ + return is_usb; +} + +/* ------------------------------------------------------------------------- * + * hwal_set_usb_connected -- forward usb connection status + * ------------------------------------------------------------------------- */ + +static void hwal_set_usb_connected(gboolean connected) +{ + log_notice("%s(%s)\n", __FUNCTION__, connected ? "CONNECTED" : "DISCONNECTED"); + set_usb_connected(connected); +} + + +/* ========================================================================= * + * CALLBACK FUNCTIONS + * ========================================================================= */ + +/* ------------------------------------------------------------------------- * + * hwal_dbus_message_cb -- handle dbus message + * ------------------------------------------------------------------------- */ + +static +DBusHandlerResult +hwal_dbus_message_cb(DBusConnection *conn, + DBusMessage *msg, + void *user_data) +{ + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + 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); + const char *typestr = dbus_message_type_to_string(type); + DBusError err = DBUS_ERROR_INIT; + + if( !interface || !member || !object ) + { + goto cleanup; + } + + log_debug("DBUS: %s - %s.%s(%s)\n", typestr, interface, member, object); + + if( type == DBUS_MESSAGE_TYPE_SIGNAL ) + { + if( !strcmp(interface, BME_INTERFACE_DBUS) && !strcmp(object, BME_PATH_DBUS) ) + { + if( (!strcmp(member, BME_MEMBER_CHARGER_CONNECTED) ) ) + { + log_debug("bme signals charger connected\n"); + if(hwal_is_usb_host_connected()) + hwal_set_usb_connected(TRUE); + } + else if( !strcmp(member, BME_MEMBER_CHARGER_DISCONNECTED) ) + { + log_debug("bme signals charger disconnected\n"); + hwal_set_usb_connected(FALSE); + } + } + } + +cleanup: + + dbus_error_free(&err); + return result; +} + +/* ------------------------------------------------------------------------- * + * hwal_init -- set up the hw abstraction layer + * ------------------------------------------------------------------------- */ + +gboolean hwal_init(void) +{ + gboolean res = FALSE; + DBusError err = DBUS_ERROR_INIT; + + // initialize system bus connection + + if( (hwal_dbus_con = dbus_bus_get(DBUS_BUS_SYSTEM, &err)) == 0 ) + { + log_crit("%s: %s: %s\n", "bus get", err.name, err.message); + goto cleanup; + } + + if( !dbus_connection_add_filter(hwal_dbus_con, hwal_dbus_message_cb, 0, 0) ) + { + goto cleanup; + } + + dbus_bus_add_match(hwal_dbus_con, MATCH_BME_CHARGER_CONNECTED, &err); + if( dbus_error_is_set(&err) ) + { + log_crit("%s: %s: %s\n", "add match", err.name, err.message); + goto cleanup; + } + dbus_bus_add_match(hwal_dbus_con, MATCH_BME_CHARGER_DISCONNECTED, &err); + if( dbus_error_is_set(&err) ) + { + log_crit("%s: %s: %s\n", "add match", err.name, err.message); + goto cleanup; + } + + dbus_connection_set_exit_on_disconnect(hwal_dbus_con, TRUE); + + dbus_connection_setup_with_g_main(hwal_dbus_con, NULL); + + if(hwal_is_usb_host_connected()) + hwal_set_usb_connected(TRUE); + + res = TRUE; + +cleanup: + + dbus_error_free(&err); + return res; +} + +/* ------------------------------------------------------------------------- * + * hwal_cleanup -- cleans up the hw abstraction layer on exit + * ------------------------------------------------------------------------- */ + +void hwal_cleanup(void) +{ + // drop system bus connection + if( hwal_dbus_con != 0 ) + { + DBusError err = DBUS_ERROR_INIT; + + dbus_bus_remove_match(hwal_dbus_con, MATCH_BME_CHARGER_CONNECTED, &err); + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", "remove match", err.name, err.message); + dbus_error_free(&err); + } + dbus_bus_remove_match(hwal_dbus_con, MATCH_BME_CHARGER_DISCONNECTED, &err); + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", "remove match", err.name, err.message); + dbus_error_free(&err); + } + + // remove message handlers + dbus_connection_remove_filter(hwal_dbus_con, hwal_dbus_message_cb, 0); + + // forget the connection + dbus_connection_unref(hwal_dbus_con); + hwal_dbus_con = 0; + + // TODO: detach from the mainloop, how? + } +} diff --git a/src/usb_moded-config.c b/src/usb_moded-config.c new file mode 100644 index 0000000..50ac26a --- /dev/null +++ b/src/usb_moded-config.c @@ -0,0 +1,129 @@ +/** + @file usb_moded-config.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 +*/ + +#include +#include +#include +#include + +#include +#include + +#include "usb_moded-config.h" +#include "usb_moded-log.h" + +const char *find_mounts(void) +{ + GKeyFile *settingsfile; + gboolean test = FALSE; + gchar **keys; + const char *ret = NULL, *tmp_char; + + settingsfile = g_key_file_new(); + test = g_key_file_load_from_file(settingsfile, FS_MOUNT_CONFIG_FILE, G_KEY_FILE_NONE, NULL); + if(!test) + { + ret = g_strdup(FS_MOUNT_DEFAULT); + log_debug("Module parameter string = %s\n", ret); + g_key_file_free(settingsfile); + return(ret); + } + keys = g_key_file_get_keys (settingsfile, FS_MOUNT_ENTRY, NULL, NULL); + while (*keys != NULL) + { + if(!strcmp(*keys, FS_MOUNT_KEY)) + { + tmp_char = g_key_file_get_string(settingsfile, FS_MOUNT_ENTRY, *keys, NULL); + if(tmp_char) + { + ret = g_strdup(tmp_char); + log_debug("Module parameter string = %s\n", ret); + } + } + keys++; + } + g_key_file_free(settingsfile); + return(ret); +} + +int find_sync(void) +{ + GKeyFile *settingsfile; + gboolean test = FALSE; + gchar **keys; + 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("Sync is default = %d\n", ret); + g_key_file_free(settingsfile); + return(ret); + } + keys = g_key_file_get_keys (settingsfile, FS_SYNC_ENTRY, NULL, NULL); + while (*keys != NULL) + { + if(!strcmp(*keys, FS_SYNC_KEY)) + { + ret = g_key_file_get_integer(settingsfile, FS_SYNC_ENTRY, *keys, NULL); + log_debug("key value = %d\n", ret); + } + keys++; + } + g_key_file_free(settingsfile); + return(ret); +} + +const char * find_alt_mount(void) +{ + GKeyFile *settingsfile; + gboolean test = FALSE; + gchar **keys; + const char *ret = NULL, *tmp_char; + + 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("Keyfile unavailable no fallback mount."); + g_key_file_free(settingsfile); + return(ret); + } + keys = g_key_file_get_keys (settingsfile, ALT_MOUNT_ENTRY, NULL, NULL); + while (*keys != NULL) + { + if(!strcmp(*keys, ALT_MOUNT_KEY)) + { + tmp_char = g_key_file_get_string(settingsfile, ALT_MOUNT_ENTRY, *keys, NULL); + if(tmp_char) + { + ret = g_strdup(tmp_char); + log_debug("Alternate mount = %s\n", ret); + } + } + keys++; + } + g_key_file_free(settingsfile); + return(ret); + +} diff --git a/src/usb_moded-config.h b/src/usb_moded-config.h new file mode 100644 index 0000000..c1b366f --- /dev/null +++ b/src/usb_moded-config.h @@ -0,0 +1,35 @@ +/* + + 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 +*/ + + +#define FS_MOUNT_CONFIG_FILE "/etc/usb-moded/usb-moded.ini" + +#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" + +const char * find_mounts(void); +int find_sync(void); +const char * find_alt_mount(void); diff --git a/src/usb_moded-dbus-private.h b/src/usb_moded-dbus-private.h new file mode 100644 index 0000000..d527e8b --- /dev/null +++ b/src/usb_moded-dbus-private.h @@ -0,0 +1,38 @@ +/* + 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 +*/ + +/* initialize dbus communication channels */ +gboolean usb_moded_dbus_init(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); + +#ifdef NOKIA +/* track dsme shutdown indication signal */ +int usb_moded_dsme_listener(void); + + +#endif diff --git a/src/usb_moded-dbus.c b/src/usb_moded-dbus.c new file mode 100644 index 0000000..0993e8d --- /dev/null +++ b/src/usb_moded-dbus.c @@ -0,0 +1,366 @@ +/** + @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 +*/ + +#include +#include + +#include +#include +#include + +#include "usb_moded-dbus.h" +#include "usb_moded-dbus-private.h" +#include "usb_moded.h" +#include "usb_moded-modes.h" +#include "usb_moded-gconf-private.h" +#include "usb_moded-log.h" + +#ifdef NOKIA +static DBusHandlerResult usb_moded_dsme_cb(DBusConnection *conn, DBusMessage *msg, void *user_data); +#endif + +static DBusConnection *dbus_connection_sys = NULL; + +static DBusHandlerResult 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); + const char *xml = "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n"; + + + (void)user_data; + + if(!interface || !member || !object) 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(); + + 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 for valid USB MODES in the request */ + if(!strcmp(MODE_MASS_STORAGE, use) || !strcmp(MODE_OVI_SUITE, use) || !strcmp(MODE_CHARGING, use) || !strcmp(MODE_WINDOWS_NET, use)) + { + /* check if usb is connected, since it makes no sense to change mode if it isn't */ + if(!get_usb_connection_state()) + goto error_reply; + /* do not change mode if the mode requested is the one already set */ + if(strcmp(use, get_usb_mode()) != 0) + 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 the GConf key */ + if(!set_mode_setting(config)) + { + 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 + { + /*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(object, USB_MODE_OBJECT) && !strcmp(member, "Introspect")) + { + status = DBUS_HANDLER_RESULT_HANDLED; + + if((reply = dbus_message_new_method_return(msg))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID); + } + + +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; +} + +/** + * Init dbus for usb_moded + * + * @return TRUE when everything went ok + */ +gboolean usb_moded_dbus_init(void) +{ + gboolean status = FALSE; + DBusError error; + int ret; + + dbus_error_init(&error); + + /* 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; + + /* 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; + } + + /* only match on signals/methods we support (if needed) + dbus_bus_add_match(dbus_connection_sys, USB_MODE_INTERFACE, &error); + */ + + /* Connect D-Bus to the mainloop */ + dbus_connection_setup_with_g_main(dbus_connection_sys, NULL); + + /* everything went fine */ + status = TRUE; + +EXIT: + dbus_error_free(&error); + return status; +} + +/** + * Clean up the dbus connections on exit + * + */ +void usb_moded_dbus_cleanup(void) +{ + /* clean up system bus connection */ + if (dbus_connection_sys != NULL) + { + dbus_connection_remove_filter(dbus_connection_sys, msg_handler, NULL); + dbus_connection_unref(dbus_connection_sys); + dbus_connection_sys = NULL; + } +} + +/** + * Send regular usb_moded state signal + * + * @return 1 on success, 0 on failure + * @args the signal name + * +*/ +int usb_moded_send_signal(const char *state_ind) +{ + int result = 1; + DBusMessage* msg = 0; + + // create a signal and check for errors + msg = dbus_message_new_signal(USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_SIGNAL_NAME ); + if (NULL == msg) + { + log_debug("Message Null\n"); + goto EXIT; + } + + // append arguments onto signal + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &state_ind, 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); + + return result; +} + +int usb_moded_send_error_signal(const char *error) +{ + int result = 1; + DBusMessage* msg = 0; + + // create a signal and check for errors + msg = dbus_message_new_signal(USB_MODE_OBJECT, USB_MODE_INTERFACE, USB_MODE_ERROR_SIGNAL_NAME ); + if (NULL == msg) + { + log_debug("Message Null\n"); + goto EXIT; + } + + // append arguments onto signal + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &error, 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); + + return result; +} + +#ifdef NOKIA +int usb_moded_dsme_listener(void) +{ + DBusError err = DBUS_ERROR_INIT; + DBusConnection *dbus_conn_dsme = NULL; + + if( (dbus_conn_dsme = dbus_bus_get(DBUS_BUS_SYSTEM, &err)) == 0 ) + { + log_err("Could not connect to dbus for dsme\n"); + goto cleanup; + } + + dbus_bus_add_match(dbus_conn_dsme, "type='signal',interface='com.nokia.dsme.signal',path='/com/nokia/dsme/signal'", &err); + if( dbus_error_is_set(&err) ) + { + goto cleanup; + } + if( !dbus_connection_add_filter(dbus_conn_dsme, usb_moded_dsme_cb , 0, 0) ) + { + log_err("adding system dbus filter for dsme failed"); + goto cleanup; + } + dbus_connection_setup_with_g_main(dbus_conn_dsme, NULL); + +cleanup: + dbus_error_free(&err); + return(1); +} + +static DBusHandlerResult usb_moded_dsme_cb(DBusConnection *conn, DBusMessage *msg, void *user_data) +{ + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + 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; + + // sanity checks + if( !interface || !member || !object ) goto cleanup; + if( type != DBUS_MESSAGE_TYPE_SIGNAL ) goto cleanup; + if( strcmp(interface, "com.nokia.dsme.signal") ) goto cleanup; + if( strcmp(object, "/com/nokia/dsme/signal") ) goto cleanup; + + // handle known signals + else if( !strcmp(member, "shutdown_ind") ) + { + log_debug("Shutdown indication. Cleaning up.\n"); + set_usb_mode(MODE_CHARGING); + } + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +cleanup: + return result; +} + +#endif /* NOKIA */ diff --git a/src/usb_moded-dbus.h b/src/usb_moded-dbus.h new file mode 100644 index 0000000..b9bc5b7 --- /dev/null +++ b/src/usb_moded-dbus.h @@ -0,0 +1,49 @@ +/* + 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 +/** + * @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" +#define USB_MODE_SIGNAL_NAME "sig_usb_state_ind" +#define USB_MODE_ERROR_SIGNAL_NAME "sig_usb_state_error_ind" + +/* supported methods */ +#define USB_MODE_STATE_REQUEST "mode_request" +/** + * @credential usb-moded::USBControl Credential needed to be able to call the set_mode or set_config methods +**/ +#define USB_MODE_STATE_SET "set_mode" +#define USB_MODE_CONFIG_SET "set_config" + +/* state definitions for signals and method parameters */ +#define USB_CONNECTED "USB connected" +#define USB_DISCONNECTED "USB disconnected" +#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" + +/* errors */ +#define UMOUNT_ERROR "Unmounting filesystem failed. Exporting impossible" +/* qtn_usb_filessystem_inuse is the NOKIA/Meego error string */ diff --git a/src/usb_moded-devicelock.c b/src/usb_moded-devicelock.c new file mode 100644 index 0000000..aad7081 --- /dev/null +++ b/src/usb_moded-devicelock.c @@ -0,0 +1,139 @@ +/** + + @file: usb_moded-devicelock.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 +*/ +/* + * 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-log.h" +#include "usb_moded.h" +#include "usb_moded-modes.h" + +static DBusHandlerResult devicelock_unlocked_cb(DBusConnection *conn, DBusMessage *msg, void *user_data); + +/** Checks if the device is locked. + * + * @return 0 for unlocked, 1 for locked + * + */ +int usb_moded_get_export_permission(void) +{ + DBusConnection *dbus_conn_devicelock = NULL; + DBusMessage *msg = NULL, *reply = NULL; + DBusError error; + int ret = 2; + dbus_int32_t arg = 1; + + dbus_error_init(&error); + + if( (dbus_conn_devicelock = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) == 0 ) + { + log_err("Could not connect to dbus for devicelock\n"); + } + + if ((msg = dbus_message_new_method_call(DEVICELOCK_SERVICE, DEVICELOCK_REQUEST_PATH, DEVICELOCK_REQUEST_IF, DEVICELOCK_STATE_REQ)) != NULL) + { + dbus_message_append_args (msg, DBUS_TYPE_INT32, &arg, DBUS_TYPE_INVALID); + if ((reply = dbus_connection_send_with_reply_and_block(dbus_conn_devicelock, msg, -1, NULL)) != NULL) + { + dbus_message_get_args(reply, NULL, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + dbus_message_unref(reply); + log_debug("Got reply from devicelock\n"); + } + dbus_message_unref(msg); + } + dbus_connection_unref(dbus_conn_devicelock); + + log_debug("devicelock state = %d\n", ret); + return(ret); +} + +int start_devicelock_listener(void) +{ + DBusError err = DBUS_ERROR_INIT; + DBusConnection *dbus_conn_devicelock = NULL; + + if( (dbus_conn_devicelock = dbus_bus_get(DBUS_BUS_SYSTEM, &err)) == 0 ) + { + log_err("Could not connect to dbus for devicelock\n"); + goto cleanup; + } + + dbus_bus_add_match(dbus_conn_devicelock, MATCH_DEVICELOCK_SIGNALS, &err); + if( dbus_error_is_set(&err) ) + { + goto cleanup; + } + if( !dbus_connection_add_filter(dbus_conn_devicelock, devicelock_unlocked_cb , 0, 0) ) + { + log_err("adding system dbus filter for devicelock failed"); + goto cleanup; + } + dbus_connection_setup_with_g_main(dbus_conn_devicelock, NULL); + +cleanup: + dbus_error_free(&err); + return(1); +} + +static DBusHandlerResult devicelock_unlocked_cb(DBusConnection *conn, DBusMessage *msg, void *user_data) +{ + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + 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); + int ret=0, ret1 = 0; + + (void) user_data; + + // sanity checks + if( !interface || !member || !object ) goto cleanup; + if( type != DBUS_MESSAGE_TYPE_SIGNAL ) goto cleanup; + if( strcmp(interface, DEVICELOCK_REQUEST_IF) ) goto cleanup; + if( strcmp(object, DEVICELOCK_REQUEST_PATH) ) goto cleanup; + + // handle known signals + else if( !strcmp(member, "stateChanged") ) + { + dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &ret1, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + log_debug("Devicelock state changed. New state = %d\n", ret); + if(ret == 0 && get_usb_connection_state() == 1 ) + { + if(!strcmp(get_usb_mode(), MODE_UNDEFINED) || !strcmp(get_usb_mode(), MODE_CHARGING)) + set_usb_connected_state(); + } + } + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +cleanup: + return result; +} + diff --git a/src/usb_moded-devicelock.h b/src/usb_moded-devicelock.h new file mode 100644 index 0000000..fdc6692 --- /dev/null +++ b/src/usb_moded-devicelock.h @@ -0,0 +1,39 @@ +/* + 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 +*/ +/* + * Interacts with the devicelock to know if we can expose the system contents or not + */ + +/*============================================================================= */ +int usb_moded_get_export_permission(void); +int start_devicelock_listener(void); + +#define DEVICELOCK_SERVICE "com.nokia.devicelock" +#define DEVICELOCK_REQUEST_PATH "/request" +#define DEVICELOCK_REQUEST_IF "com.nokia.devicelock" +#define DEVICELOCK_STATE_REQ "getState" + +#define DEVICELOCK_LOCKED "Locked" + +#define MATCH_DEVICELOCK_SIGNALS\ + "type='signal'"\ + ",interface='"DEVICELOCK_REQUEST_IF"'"\ + ",path='"DEVICELOCK_REQUEST_PATH"'" + diff --git a/src/usb_moded-gconf-private.h b/src/usb_moded-gconf-private.h new file mode 100644 index 0000000..56eefa1 --- /dev/null +++ b/src/usb_moded-gconf-private.h @@ -0,0 +1,27 @@ +/* + 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 +*/ +/* + * Gets information from Gconf for the usb modes +*/ + +/*============================================================================= */ + +const char * get_mode_setting(void); +int set_mode_setting(const char *mode); diff --git a/src/usb_moded-gconf.c b/src/usb_moded-gconf.c new file mode 100644 index 0000000..bb5e5c1 --- /dev/null +++ b/src/usb_moded-gconf.c @@ -0,0 +1,92 @@ +/** + @file usb_moded-gconf.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 +*/ +/* + * Gets information from Gconf for the usb modes +*/ + +/*============================================================================= */ + +#include +#include + +#include +#include + +#include + +#include "usb_moded-gconf.h" +#include "usb_moded-gconf-private.h" +#include "usb_moded-modes.h" +#include "usb_moded-log.h" + +/** Get the config option set in gconf for the default action + * + * @return The mode to set by default, or NULL on failure + * + */ +const char * get_mode_setting(void) +{ + GConfClient *gclient = NULL; + gchar *mode_value; + + gclient = gconf_client_get_default(); + + if (gclient == NULL) + { + log_err("Unable to get GConfClient"); + return(0); + } + mode_value = gconf_client_get_string(gclient, USB_MODE_GCONF, NULL); + + g_object_unref(gclient); + return(mode_value); +} + +/** Set the config option for the default action + * + * @param mode The default action to store in gconf + * @return 0 on on success, 1 on failure + * + */ +int set_mode_setting(const char *mode) +{ + GConfClient *gclient = NULL; + + if(!strcmp(mode, MODE_MASS_STORAGE) || !strcmp(mode, MODE_OVI_SUITE) || !strcmp(mode, MODE_CHARGING) || !strcmp(mode, MODE_ASK)|| !strcmp(mode, MODE_WINDOWS_NET)) + { + gclient = gconf_client_get_default(); + if (gclient == NULL) + { + log_err("Unable to get GConfClient"); + return(1); + } + if (!gconf_client_set_string(gclient, USB_MODE_GCONF, mode, NULL)) + { + log_err("Unable to set GConf key"); + return(1); + } + } + else + return(1); + + return(0); +} diff --git a/src/usb_moded-gconf.h b/src/usb_moded-gconf.h new file mode 100644 index 0000000..d279449 --- /dev/null +++ b/src/usb_moded-gconf.h @@ -0,0 +1,27 @@ +/* + 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 +*/ +/* + * Gets information from Gconf for the usb modes +*/ + +/*============================================================================= */ + +#define USB_MODE_GCONF "/Meego/System/UsbMode" + diff --git a/src/usb_moded-hal.c b/src/usb_moded-hal.c new file mode 100644 index 0000000..ae97c3c --- /dev/null +++ b/src/usb_moded-hal.c @@ -0,0 +1,726 @@ +/** + @file usb_moded-hal.c + + Copyright (C) 2010 Nokia Corporation. All rights reserved. + + @author: Philippe De Swert + 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 +#include +#include +#include + +#include +#include + +#include "usb_moded.h" +#include "usb_moded-hw-ab.h" +#include "usb_moded-log.h" + +/* ========================================================================= * + * Quick guide to the state logic ... + * + * startup: + * @ hwal_init() + * - connect to system bus + * - partially initialize libhal context + * - listen to hald service ownership changes + * - check if hald is already running + * + * hald running / started: + * @ hwal_set_hald_running(true) + * - finalize libhal context + * - listen to hal device added/removed notifications + * - check availability of musb device + * + * musb device added / available: + * @ hwal_set_musb_tracking(true) + * - listen to hal property changes for musb device + * - broadcast initial state of usb connection + * + * musb connection status change: + * @ hwal_set_usb_connected() + * - broadcast connection status over dbus + * + * musb device removed: + * @ hwal_set_musb_tracking(false) + * - stop listening to hal property changes for musb device + * + * hald stopped: + * @ hwal_set_hald_running(false) + * - stop listening to hal property changes for musb device + * - shutdown libhal context + * + * shutdown: + * @ hwal_cleanup() + * - shutdown and free libhal context + * - forget dbus connection + * + * dbus disconnect: + * - exit + * ========================================================================= */ + +/* ========================================================================= * + * CONSTANTS + * ========================================================================= */ + +// FIXME: is there "official" macro for "org.freedesktop.Hal"? +#define HALD_DBUS_SERVICE "org.freedesktop.Hal" + +// D-Bus signal match for tracking hal service ownership on system bus +#define MATCH_HALD_OWNERCHANGED\ + "type='signal'"\ + ",sender='"DBUS_SERVICE_DBUS"'"\ + ",interface='"DBUS_INTERFACE_DBUS"'"\ + ",path='"DBUS_PATH_DBUS"'"\ + ",member='NameOwnerChanged'"\ + ",arg0='"HALD_DBUS_SERVICE"'" + +// Hal device UDI and property name we are tracking +static const char musb_udi[] = "/org/freedesktop/Hal/devices/platform_musb_hdrc"; +static const char musb_prp[] = "button.state.value"; + +/* ========================================================================= * + * STATE VARIABLES + * ========================================================================= */ + +static DBusConnection *hwal_con = 0; // system bus connection +static LibHalContext *hwal_ctx = 0; // libhal context + +static gboolean hald_running = FALSE; /* Is hald detected on system bus. + * Set via hwal_set_hald_running() */ + +static gboolean ctx_attached = FALSE; /* Is libhal context ready for use. + * Set via hwal_set_ctx_state() */ + +static gboolean tracking_musb = FALSE; /* is musb hal device being tracked. + * Set via hwal_set_musb_tracking() */ + +/* ========================================================================= * + * DEBUG UTILITIES + * ========================================================================= */ + + +/* ------------------------------------------------------------------------- * + * debug_show_property -- query & show current state of hal property + * ------------------------------------------------------------------------- */ + +#if LOG_ENABLE_DEBUG +static void debug_show_property(const char *udi, const char *key) +{ + DBusError err = DBUS_ERROR_INIT; + + LibHalPropertyType tid; + + tid = libhal_device_get_property_type(hwal_ctx, udi, key, &err); + + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", __FUNCTION__, err.name, err.message); + dbus_error_free(&err); + } + + log_debugf("\t%s = ", key); + switch( tid ) + { + case LIBHAL_PROPERTY_TYPE_INVALID: + log_debugf("invalid"); + break; + + case LIBHAL_PROPERTY_TYPE_INT32: + log_debugf("int32:%ld", (long)libhal_device_get_property_int(hwal_ctx, udi, key, &err)); + break; + + case LIBHAL_PROPERTY_TYPE_UINT64: + log_debugf("uint64:%llu", (unsigned long long)libhal_device_get_property_uint64(hwal_ctx, udi, key, &err)); + break; + + case LIBHAL_PROPERTY_TYPE_DOUBLE: + log_debugf("double:%g", libhal_device_get_property_double(hwal_ctx, udi, key, &err)); + break; + + case LIBHAL_PROPERTY_TYPE_BOOLEAN: + log_debugf("bool:%s", libhal_device_get_property_bool(hwal_ctx, udi, key, &err) ? "true" : "false"); + break; + + case LIBHAL_PROPERTY_TYPE_STRING: + log_debugf("string:\"%s\"", libhal_device_get_property_string(hwal_ctx, udi, key, &err)); + break; + + case LIBHAL_PROPERTY_TYPE_STRLIST: + log_debugf("strlist:{"); + { + char **v = libhal_device_get_property_strlist(hwal_ctx, udi, key, &err); + + if( v != 0 ) + { + for( int i = 0; v[i]; ++i ) log_debugf(" \"%s\"", v[i]); + libhal_free_string_array(v); + } + } + log_debugf(" }"); + break; + } + log_debugf("\n"); + + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", __FUNCTION__, err.name, err.message); + dbus_error_free(&err); + } +} +#endif // LOG_ENABLE_DEBUG + +/* ------------------------------------------------------------------------- * + * debug_show_property_set -- show all values in property set + * ------------------------------------------------------------------------- */ + +#if LOG_ENABLE_DEBUG +static void debug_show_property_set(LibHalPropertySet *ps) +{ + LibHalPropertySetIterator psi; + + libhal_psi_init(&psi, ps); + + for( ; libhal_psi_has_more(&psi); libhal_psi_next(&psi) ) + { + log_debugf("\t%s = ", libhal_psi_get_key(&psi)); + + switch( libhal_psi_get_type(&psi) ) + { + case LIBHAL_PROPERTY_TYPE_INVALID: + log_debugf("invalid"); + break; + + case LIBHAL_PROPERTY_TYPE_INT32: + log_debugf("int32:%ld", (long)libhal_psi_get_int(&psi)); + break; + + case LIBHAL_PROPERTY_TYPE_UINT64: + log_debugf("uint64:%llu", (unsigned long long)libhal_psi_get_uint64(&psi)); + break; + + case LIBHAL_PROPERTY_TYPE_DOUBLE: + log_debugf("double:%g", libhal_psi_get_double(&psi)); + break; + + case LIBHAL_PROPERTY_TYPE_BOOLEAN: + log_debugf("bool:%s", libhal_psi_get_bool(&psi) ? "true" : "false"); + break; + + case LIBHAL_PROPERTY_TYPE_STRING: + log_debugf("string:\"%s\"", libhal_psi_get_string(&psi)); + break; + + case LIBHAL_PROPERTY_TYPE_STRLIST: + log_debugf("strlist:{"); + { + char **v = libhal_psi_get_strlist(&psi); + if( v ) for( int i = 0; v[i]; ++i ) log_debugf(" \"%s\"", v[i]); + } + log_debugf(" }"); + break; + } + log_debugf("\n"); + } +} +#endif // LOG_ENABLE_DEBUG + +/* ========================================================================= * + * LIBHAL UTILITIES + * ========================================================================= */ + +/* ------------------------------------------------------------------------- * + * halipc_get_all_properties + * ------------------------------------------------------------------------- */ + +static LibHalPropertySet *halipc_get_all_properties(const char *udi) +{ + DBusError err = DBUS_ERROR_INIT; + LibHalPropertySet *res = 0; + + res = libhal_device_get_all_properties(hwal_ctx, udi, &err); + + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", __FUNCTION__, err.name, err.message); + dbus_error_free(&err); + } + + return res; +} + +/* ------------------------------------------------------------------------- * + * halipc_device_exists + * ------------------------------------------------------------------------- */ + +static int halipc_device_exists(const char *udi) +{ + DBusError err = DBUS_ERROR_INIT; + int res = libhal_device_exists(hwal_ctx, udi, &err); + + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", __FUNCTION__, err.name, err.message); + dbus_error_free(&err); + } + + return res; +} + +/* ------------------------------------------------------------------------- * + * halipc_device_add_watch + * ------------------------------------------------------------------------- */ + +static int halipc_device_add_watch(const char *udi) +{ + DBusError err = DBUS_ERROR_INIT; + int res = libhal_device_add_property_watch(hwal_ctx, udi, &err); + + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", __FUNCTION__, err.name, err.message); + dbus_error_free(&err); + } + + return res; +} + +/* ------------------------------------------------------------------------- * + * halipc_device_remove_watch + * ------------------------------------------------------------------------- */ + +static int halipc_device_remove_watch(const char *udi) +{ + DBusError err = DBUS_ERROR_INIT; + int res = libhal_device_remove_property_watch(hwal_ctx, udi, &err); + + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", __FUNCTION__, err.name, err.message); + dbus_error_free(&err); + } + + return res; +} + +/* ------------------------------------------------------------------------- * + * halipc_type_to_string + * ------------------------------------------------------------------------- */ + +static const char *halipc_type_to_string(LibHalPropertyType tid) +{ + switch( tid ) + { + case LIBHAL_PROPERTY_TYPE_INVALID: return "invalid"; + case LIBHAL_PROPERTY_TYPE_INT32: return "int32"; + case LIBHAL_PROPERTY_TYPE_UINT64: return "uint64"; + case LIBHAL_PROPERTY_TYPE_DOUBLE: return "double"; + case LIBHAL_PROPERTY_TYPE_BOOLEAN: return "boolean"; + case LIBHAL_PROPERTY_TYPE_STRING: return "string"; + case LIBHAL_PROPERTY_TYPE_STRLIST: return "strlist"; + } + return "unknown"; +} + +/* ========================================================================= * + * STATE LOGIC FUNCTIONS + * ========================================================================= */ + +/* ------------------------------------------------------------------------- * + * hwal_set_usb_connected -- forward usb connection status + * ------------------------------------------------------------------------- */ + +static void hwal_set_usb_connected(gboolean connected) +{ + log_notice("%s(%s)\n", __FUNCTION__, connected ? "CONNECTED" : "DISCONNECTED"); + set_usb_connected(connected); +} + +/* ------------------------------------------------------------------------- * + * hwal_set_musb_tracking -- start/stop usb device property tracking + * ------------------------------------------------------------------------- */ + +static void hwal_set_musb_tracking(int enable) +{ + if( enable ) + { + if( ctx_attached && !tracking_musb ) + { + if( (tracking_musb = halipc_device_add_watch(musb_udi)) ) + { + LibHalPropertySet *ps = 0; + LibHalPropertyType tid; + + if( (ps = halipc_get_all_properties(musb_udi)) ) + { +#if LOG_ENABLE_DEBUG + if( log_get_level() >= LOG_DEBUG ) debug_show_property_set(ps); +#endif + tid = libhal_ps_get_type(ps, musb_prp); + + if( tid != LIBHAL_PROPERTY_TYPE_BOOLEAN ) + { + log_err("%s: %s: expected '%s', got '%s'\n", + musb_udi, musb_prp, + halipc_type_to_string(LIBHAL_PROPERTY_TYPE_BOOLEAN), + halipc_type_to_string(tid)); + } + else + { + hwal_set_usb_connected(libhal_ps_get_bool(ps, musb_prp)); + } + + libhal_free_property_set(ps); + } + } + } + } + else + { + if( tracking_musb ) + { + halipc_device_remove_watch(musb_udi); + tracking_musb = 0; + } + } + log_notice("%s(%s) -> %s\n", __FUNCTION__, + enable ? "ENABLE" : "DISABLE", + tracking_musb ? "ENABLED" : "DISABLED"); +} + +/* ------------------------------------------------------------------------- * + * hwal_set_ctx_state + * ------------------------------------------------------------------------- */ + +static gboolean hwal_set_ctx_state(gboolean attach) +{ + if( attach ) + { + if( hwal_ctx != 0 && !ctx_attached ) + { + DBusError err = DBUS_ERROR_INIT; + + if( !libhal_ctx_init(hwal_ctx, &err) ) + { + log_err("%s: %s: %s\n", "ctx init", err.name, err.message); + dbus_error_free(&err); + } + else + { + ctx_attached = TRUE; + } + } + } + else + { + if( hwal_ctx != 0 && ctx_attached ) + { + DBusError err = DBUS_ERROR_INIT; + + if( !libhal_ctx_shutdown(hwal_ctx, &err) ) + { + log_err("%s: %s: %s\n", "ctx shutdown", err.name, err.message); + dbus_error_free(&err); + } + + ctx_attached = FALSE; + } + } + + log_notice("%s(%s) -> %s\n", __FUNCTION__, + attach ? "ATTACH" : "DETACH", + ctx_attached ? "ATTACHED" : "DETACHED"); + + return ctx_attached; +} + +/* ------------------------------------------------------------------------- * + * hwal_set_hald_running -- react to hal run state changes + * ------------------------------------------------------------------------- */ + +static void hwal_set_hald_running(gboolean running) +{ + hald_running = running; + + log_notice("HALD -> %s\n", hald_running ? "RUNNING" : "STOPPED"); + + if( hald_running ) + { + hwal_set_ctx_state(TRUE); + hwal_set_musb_tracking(halipc_device_exists(musb_udi)); + } + else + { + hwal_set_musb_tracking(FALSE); + hwal_set_ctx_state(FALSE); + } +} + +/* ========================================================================= * + * CALLBACK FUNCTIONS + * ========================================================================= */ + +/* ------------------------------------------------------------------------- * + * hwal_property_modified_cb -- handle hal property modified notification + * ------------------------------------------------------------------------- */ + +static void +hwal_property_modified_cb(LibHalContext *ctx, const char *udi, const char *key, + dbus_bool_t is_removed, dbus_bool_t is_added) +{ + log_info("%s(%s, %s, %d, %d)\n", __FUNCTION__, udi, key, is_removed, is_added); + + if( udi && !strcmp(udi, musb_udi) ) + { +#if LOG_ENABLE_DEBUG + // usb device prop changed -> debug output + if( !is_removed ) + { + if( log_get_level() >= LOG_DEBUG ) debug_show_property(udi, key); + } +#endif + + if( key && !strcmp(key, musb_prp) ) + { + // state property changed -> propagate change + DBusError err = DBUS_ERROR_INIT; + dbus_bool_t val = libhal_device_get_property_bool(ctx, udi, key, &err); + + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", "get property bool", err.name, err.message); + dbus_error_free(&err); + } + else + { + hwal_set_usb_connected(val); + } + } + } +} + +/* ------------------------------------------------------------------------- * + * hwal_device_added_cb -- handle hal device added notification + * ------------------------------------------------------------------------- */ + +static void +hwal_device_added_cb(LibHalContext *ctx, const char *udi) +{ + log_info("%s(%s)\n", __FUNCTION__, udi); + + if( udi && !strcmp(udi, musb_udi) ) + { + // usb device was added -> track properties if hald is running + hwal_set_musb_tracking(hald_running); + } +} + +/* ------------------------------------------------------------------------- * + * hwal_device_removed_cb -- handle hal device removed notification + * ------------------------------------------------------------------------- */ + +static void +hwal_device_removed_cb(LibHalContext *ctx, const char *udi) +{ + log_info("%s(%s)\n", __FUNCTION__, udi); + + if( udi && !strcmp(udi, musb_udi) ) + { + // usb device was removed -> stop tracking properties + hwal_set_musb_tracking(FALSE); + } +} + +/* ------------------------------------------------------------------------- * + * hwal_dbus_message_cb -- handle dbus message + * ------------------------------------------------------------------------- */ + +static +DBusHandlerResult +hwal_dbus_message_cb(DBusConnection *conn, + DBusMessage *msg, + void *user_data) +{ + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + 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); + const char *typestr = dbus_message_type_to_string(type); + DBusError err = DBUS_ERROR_INIT; + + if( !interface || !member || !object ) + { + goto cleanup; + } + + log_debug("DBUS: %s - %s.%s(%s)\n", typestr, interface, member, object); + + if( type == DBUS_MESSAGE_TYPE_SIGNAL ) + { + if( !strcmp(interface, DBUS_INTERFACE_DBUS) && !strcmp(object,DBUS_PATH_DBUS) ) + { + if( !strcmp(member, "NameOwnerChanged") ) + { + const char *prev = 0; + const char *curr = 0; + const char *serv = 0; + + if (! dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &serv, + DBUS_TYPE_STRING, &prev, + DBUS_TYPE_STRING, &curr, + DBUS_TYPE_INVALID) ) + { + goto cleanup; + } + else + { + log_debug("service: \"%s\", old: \"%s\", new: \"%s\"\n", serv, prev, curr); + } + if( serv != 0 && !strcmp(serv, HALD_DBUS_SERVICE) ) + { + hwal_set_hald_running(curr && *curr); + } + + } + } + } + +cleanup: + + dbus_error_free(&err); + return result; +} + +/* ------------------------------------------------------------------------- * + * hwal_init -- set up the hw abstraction layer + * ------------------------------------------------------------------------- */ + +gboolean hwal_init(void) +{ + gboolean res = FALSE; + DBusError err = DBUS_ERROR_INIT; + + // initialize system bus connection + + if( (hwal_con = dbus_bus_get(DBUS_BUS_SYSTEM, &err)) == 0 ) + { + log_crit("%s: %s: %s\n", "bus get", err.name, err.message); + goto cleanup; + } + + if( !dbus_connection_add_filter(hwal_con, hwal_dbus_message_cb, 0, 0) ) + { + goto cleanup; + } + + dbus_bus_add_match(hwal_con, MATCH_HALD_OWNERCHANGED, &err); + if( dbus_error_is_set(&err) ) + { + log_crit("%s: %s: %s\n", "add match", err.name, err.message); + goto cleanup; + } + + dbus_connection_set_exit_on_disconnect(hwal_con, TRUE); + + dbus_connection_setup_with_g_main(hwal_con, NULL); + + // partially initialize libhal context + + if( (hwal_ctx = libhal_ctx_new()) == 0 ) + { + goto cleanup; + } + + libhal_ctx_set_dbus_connection(hwal_ctx, hwal_con); + + libhal_ctx_set_device_added(hwal_ctx, hwal_device_added_cb); + libhal_ctx_set_device_removed(hwal_ctx, hwal_device_removed_cb); + libhal_ctx_set_device_property_modified(hwal_ctx, hwal_property_modified_cb); + + // check if hald is already present on system bus + + if( !dbus_bus_name_has_owner(hwal_con, HALD_DBUS_SERVICE, &err) ) + { + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", "has owner", err.name, err.message); + dbus_error_free(&err); + } + hwal_set_hald_running(FALSE); + } + else + { + hwal_set_hald_running(TRUE); + } + + // success + + res = TRUE; + +cleanup: + + dbus_error_free(&err); + return res; +} + +/* ------------------------------------------------------------------------- * + * hwal_cleanup -- cleans up the hw abstraction layer on exit + * ------------------------------------------------------------------------- */ + +void hwal_cleanup(void) +{ + // drop libhal context + if( hwal_ctx != 0 ) + { + hwal_set_ctx_state(FALSE); + libhal_ctx_free(hwal_ctx); + hwal_ctx = 0; + } + + // drop system bus connection + if( hwal_con != 0 ) + { + DBusError err = DBUS_ERROR_INIT; + + // stop listening to signals + dbus_bus_remove_match(hwal_con, MATCH_HALD_OWNERCHANGED, &err); + if( dbus_error_is_set(&err) ) + { + log_err("%s: %s: %s\n", "remove match", err.name, err.message); + dbus_error_free(&err); + } + + // remove message handlers + dbus_connection_remove_filter(hwal_con, hwal_dbus_message_cb, 0); + + // forget the connection + dbus_connection_unref(hwal_con); + hwal_con = 0; + + // TODO: detach from the mainloop, how? + } +} diff --git a/src/usb_moded-hw-ab.h b/src/usb_moded-hw-ab.h new file mode 100644 index 0000000..dde770a --- /dev/null +++ b/src/usb_moded-hw-ab.h @@ -0,0 +1,37 @@ +/* + 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 +*/ + +/*============================================================================= */ + +/* 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-log.c b/src/usb_moded-log.c new file mode 100644 index 0000000..bf40e54 --- /dev/null +++ b/src/usb_moded-log.c @@ -0,0 +1,129 @@ +/** + @file usb_moded-log.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 +*/ + +#include +#include +#include +#include +#include + +#include "usb_moded-log.h" + +const char *log_name = ""; +int log_level = LOG_WARNING; +int log_type = LOG_TO_STDERR; + +/** + * Print the logged messages to the selected output + * + * @param lev The wanted log level + * @param fmt The message to be logged + * @param va The stdarg variable list + */ +void log_emit_va(int lev, const char *fmt, va_list va) +{ + if( log_level >= lev ) + { + switch( log_type ) + { + case LOG_TO_SYSLOG: + + vsyslog(lev, fmt, va); + break; + + case LOG_TO_STDERR: + + fprintf(stderr, "%s: ", log_name); + +#if LOG_ENABLE_TIMESTAMPS + { + struct timeval tv; + gettimeofday(&tv, 0); + fprintf(stderr, "%ld.%06ld ", + (long)tv.tv_sec, + (long)tv.tv_usec); + } +#endif + +#if LOG_ENABLE_LEVELTAGS + { + static const char *tag = "U:"; + switch( lev ) + { + case 2: tag = "C:"; break; + case 3: tag = "E:"; break; + case 4: tag = "W:"; break; + case 5: tag = "N:"; break; + case 6: tag = "I:"; break; + case 7: tag = "D:"; break; + } + fprintf(stderr, "%s ", tag); + } +#endif + vfprintf(stderr, fmt, va); + break; + + default: + // no logging + break; + } + } +} + +void log_emit(int lev, const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + log_emit_va(lev, fmt, va); + va_end(va); +} + +void log_debugf(const char *fmt, ...) +{ + /* This goes always to stderr */ + if( log_type == LOG_TO_STDERR && log_level >= LOG_DEBUG ) + { + va_list va; + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); + } +} +/** + * returns the currently set log level + * + * @return The current log level + */ +int log_get_level(void) +{ + return log_level; +} + +/* Set the log level + * + * @param The wanted log level + */ +void log_set_level(int lev) +{ + log_level = lev; +} + diff --git a/src/usb_moded-log.h b/src/usb_moded-log.h new file mode 100644 index 0000000..eabb4d7 --- /dev/null +++ b/src/usb_moded-log.h @@ -0,0 +1,66 @@ +/* + 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 +#include +#include +#include +#include +#include + +/* Logging functionality */ +extern const char *log_name; +extern int log_level; +extern int log_type; + +#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); + +void log_emit_va(int lev, const char *fmt, va_list va); +void log_emit(int lev, const char *fmt, ...) __attribute__((format(printf,2,3))); +void log_debugf(const char *fmt, ...) __attribute__((format(printf,1,2))); + +#define log_crit(...) log_emit(2, __VA_ARGS__) +#define log_err(...) log_emit(3, __VA_ARGS__) +#define log_warning(...) log_emit(4, __VA_ARGS__) + +#if LOG_ENABLE_DEBUG +# define log_notice(...) log_emit(5, __VA_ARGS__) +# define log_info(...) log_emit(6, __VA_ARGS__) +# define log_debug(...) log_emit(7, __VA_ARGS__) +#else +# define log_notice(...) do{}while(0) +# define log_info(...) do{}while(0) +# define log_debug(...) do{}while(0) + +# define log_debugf(...) do{}while(0) +#endif + diff --git a/src/usb_moded-modes.h b/src/usb_moded-modes.h new file mode 100644 index 0000000..a79e68b --- /dev/null +++ b/src/usb_moded-modes.h @@ -0,0 +1,30 @@ +/* + 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 +*/ + +/* possible values for the mode, however only the first three can be set through the method call + the others being internal only. + */ +#define MODE_MASS_STORAGE "mass_storage" +#define MODE_OVI_SUITE "ovi_suite" +#define MODE_CHARGING "charging_only" +#define MODE_UNDEFINED "undefined" +#define MODE_ASK "ask" +#define MODE_WINDOWS_NET "windows_network" + diff --git a/src/usb_moded-modesetting.c b/src/usb_moded-modesetting.c new file mode 100644 index 0000000..9df3e35 --- /dev/null +++ b/src/usb_moded-modesetting.c @@ -0,0 +1,253 @@ +/** + @file usb_moded-modesetting.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 +*/ + +#include +#include +#include +#include + +#include + +#include "usb_moded.h" +#include "usb_moded-modules.h" +#include "usb_moded-log.h" +#include "usb_moded-dbus.h" +#include "usb_moded-dbus-private.h" +#include "usb_moded-appsync.h" +#include "usb_moded-config.h" +#include "usb_moded-modesetting.h" + +#ifdef MAYBE_NEEDED +int find_number_of_mounts(void) +{ + const char *mount; + gchar **mounts; + int mountpoints = 0, i = 0; + + mount = find_mounts(); + if(mount) + { + mounts = g_strsplit(mount, ",", 0); + /* check amount of mountpoints */ + for(i=0 ; mounts[i] != NULL; i++) + { + mountpoints++; + } + } + return(mountpoints); +} +#endif /* MAYBE_NEEDED */ + +int set_mass_storage_mode(void) +{ + gchar *command; + char command2[256]; + const 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) + { + mounts = g_strsplit(mount, ",", 0); + /* check amount of mountpoints */ + for(i=0 ; mounts[i] != NULL; i++) + { + mountpoints++; + } + + /* 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 = 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 */ +umount: command = g_strconcat("mount | grep ", mounts[i], NULL); + ret = system(command); + g_free(command); + if(!ret) + { + command = g_strconcat("umount ", mounts[i], NULL); + log_debug("unmount command = %s\n", command); + ret = system(command); + g_free(command); + if(ret != 0) + { + if(try != 1) + { + try++; + sleep(1); + log_err("Umount failed. Retrying\n"); + goto umount; + } + else + { + log_err("Unmounting %s failed\n", mount); +#ifdef NOKIA + usb_moded_send_error_signal("qtn_usb_filessystem_inuse"); +#else + usb_moded_send_error_signal(UMOUNT_ERROR); +#endif + return(ret); + } + } + } + else + /* already unmounted. Set return value to 0 since there is no error */ + ret = 0; + } + + /* activate mounts */ + for(i=0 ; mounts[i] != NULL; i++) + { + sprintf(command2, "echo %s > /sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", mounts[i], i); + log_debug("usb lun = %s active\n", command2); + system(command2); + sprintf(command2, "echo %i > /sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/nofua", fua, i); + log_debug("usb lun = %s active\n", command2); + system(command2); + } + g_strfreev(mounts); + } + + /* only send data in use signal in case we actually succeed */ + if(!ret) + usb_moded_send_signal(DATA_IN_USE); + + return(ret); + +} + +int set_ovi_suite_mode(GList *applist) +{ + int net = 0; + +#ifdef NOKIA + /* do not go through the appsync routine if there is no applist */ + if(applist) + activate_sync(applist); + else + enumerate_usb(NULL); +#endif /* NOKIA */ + /* bring network interface up in case no other network is up */ + net = system("route | grep default"); + if(net) + net = system("ifdown usb0 ; ifup usb0"); + + return(0); +} + + + +/** 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) +{ + gchar *command; + char command2[256]; + const char *mount; + gchar **mounts; + int ret = 0, i = 0; + + + if(!strcmp(module, MODULE_MASS_STORAGE)) + { + mount = find_mounts(); + if(mount) + { + 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 */ + command = g_strconcat("mount | grep ", mounts[i], NULL); + ret = system(command); + g_free(command); + if(ret) + { + command = g_strconcat("mount ", mounts[i], NULL); + ret = system(command); + g_free(command); + if(ret != 0) + { + log_err("Mounting %s failed\n", mount); + usb_moded_send_error_signal(RE_MOUNT_FAILED); + mount = find_alt_mount(); + if(mount) + { + command = g_strconcat("mount | grep ", mount, NULL); + ret = system(command); + g_free(command); + if(ret) + { + command = g_strconcat("mount -t tmpfs tmpfs -o ro -size=512K ", mount, NULL); + ret = system(command); + g_free(command); + } + + } + + } + } + + sprintf(command2, "echo 0 > /sys/devices/platform/musb_hdrc/gadget/gadget-lun%d/file", i); + log_debug("usb lun = %s inactive\n", command2); + system(command2); + } + g_strfreev(mounts); + } + + } +#ifdef NOKIA + if(!strcmp(module, MODULE_NETWORK)) + { + /* preventive sync in case of bad quality mtp clients */ + sync(); + /* bring network down immediately */ + system("ifdown usb0"); + /* do soft disconnect */ + system("echo 0 > /sys/devices/platform/musb_hdrc/gadget/softconnect"); + /* DIRTY WORKAROUND: acm/phonet does not work as it should, remove when it does */ + system("killall -SIGTERM acm"); + } +#endif /* NOKIA */ + + + return(ret); +} + diff --git a/src/usb_moded-modesetting.h b/src/usb_moded-modesetting.h new file mode 100644 index 0000000..e964b8b --- /dev/null +++ b/src/usb_moded-modesetting.h @@ -0,0 +1,29 @@ +/** + @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 +*/ + +#ifdef MAYBE_NEEDED +int find_number_of_mounts(void); +#endif +int set_mass_storage_mode(void); +int set_ovi_suite_mode(GList *applist); +int usb_moded_mode_cleanup(const char *module); + diff --git a/src/usb_moded-modules.c b/src/usb_moded-modules.c new file mode 100644 index 0000000..9c9a55a --- /dev/null +++ b/src/usb_moded-modules.c @@ -0,0 +1,230 @@ +/** + @file usb_moded-modules.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 +*/ + +#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" + +/** 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) +{ + gchar *command; + int ret = 0; + + command = g_strconcat("modprobe ", module, NULL); + ret = system(command); + g_free(command); + if( ret == 0) + log_info("Module %s loaded 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) +{ + gchar *command; + int ret = 0; + + command = g_strconcat("rmmod ", module, NULL); + ret = system(command); + g_free(command); + + return(ret); +} + +/** 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) +{ + + if(system("lsmod | grep g_nokia") == 0) + return(MODULE_NETWORK); + + if(system("lsmod | grep g_file_storage") == 0) + return(MODULE_MASS_STORAGE); + + if(system("lsmod | grep g_ether") == 0) + return(MODULE_WINDOWS_NET); + + return(NULL); +} + +/** 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 + * + */ +int usb_moded_module_cleanup(const char *module) +{ + int retry = 0, success; + + if(!strcmp(module, MODULE_NONE)) + goto END; + /* wait a bit for all components listening on dbus to clean up their act + sleep(2); */ + /* check if things were not reconnected in that timespan + if(get_usb_connection_state()) + return(0); + */ + + success = usb_moded_unload_module(module); + while(success) + { + /* module did not get unloaded. We will wait a bit and try again */ + sleep(1); + success = usb_moded_unload_module(module); + log_debug("unloading success = %d\n", success); + if(!success) + break; + if(!usb_moded_find_module()) + goto END; + retry++; + if(retry == 2) + break; + } + if(!strcmp(module, MODULE_NETWORK)) + { + if(retry >= 2) + { + /* we exited the loop due to max retry's. Module is not unloaded yet + lets go for more extreme measures + lsof, then various options of kill + */ + log_info("DIE DIE DIE! Free USB-illy!\n"); +kill: + /* DIRTY DESPERATE WORKAROUND */ + /*system("for i in `lsof -t /dev/ttyGS*`; do cat /proc/$i/cmdline | sed 's/|//g' | sed "s/\x00/ /g" | awk '{ print $1 }' | xargs kill; done"); + system("for i in `ps ax | grep phonet-at | grep -v grep | awk '{ print $1 }'`; do kill -9 $i ; done");*/ + /* kill anything that still claims the usb tty's */ + system("for i in `lsof -t /dev/ttyGS*`; do kill -s SIGTERM $i ; done"); + system("for i in `lsof -t /dev/gc*`; do kill -s SIGTERM $i ; done"); + system("for i in `lsof -t /dev/mtp*`; do kill -s SIGTERM $i ; done"); + /* try to unload again and give up if it did not work yet */ + success = usb_moded_unload_module(module); + if(success && retry < 10) + { + retry++; + goto kill; + } + if(success && retry == 10) + { + system("for i in `lsof -t /dev/ttyGS*`; do kill -9 $i ; done"); + system("for i in `lsof -t /dev/gc*`; do kill -9 $i ; done"); + system("for i in `lsof -t /dev/mtp*`; do kill -9 $i ; done"); + /* try again since there seem to be hard to kill processes there */ + system("killall -9 obexd"); + success = usb_moded_unload_module(module); + } + + } + } + if(!success) + 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); +} + +/** 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 + */ + +int usb_moded_module_switch_prepare (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); +} + +/** 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) +{ + const char *module; + + module = usb_moded_find_module(); + if(module != NULL) + { + /* do nothing if the right module is already loaded */ + if(strcmp(usb_moded_find_module(), module_name) != 0) + { + log_debug("%s not loaded, cleaning up\n", module_name); + usb_moded_module_switch_prepare(TRUE); + } + } +} + + +#ifdef NOKIA +gboolean usb_module_timeout_cleanup(gpointer data) +{ + usb_moded_module_cleanup(get_usb_module()); + return FALSE; +} +#endif /* NOKIA */ + diff --git a/src/usb_moded-modules.h b/src/usb_moded-modules.h new file mode 100644 index 0000000..43dc15d --- /dev/null +++ b/src/usb_moded-modules.h @@ -0,0 +1,57 @@ +/* + 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 +*/ + +/* module name definitions */ +#define MODULE_NETWORK "g_nokia" +#ifdef NOKIA +#define MODULE_NETWORK_MTP "g_nokia use_mtp=1 connect=0" +#else +#define MODULE_NETWORK_MTP "g_nokia use_mtp=1" +#endif /* NOKIA */ +#define MODULE_MASS_STORAGE "g_file_storage" +#define MODULE_CHARGING "g_file_storage luns=1 stall=0 removable=1" +#define MODULE_NONE "none" +#define MODULE_WINDOWS_NET "g_ether" + +/* 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 for the mode changes on disconnect */ +int usb_moded_mode_cleanup(const char *module); + +/* 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); + +#ifdef NOKIA +/* handler for a cleanup after a timeout */ +gboolean usb_module_timeout_cleanup(gpointer data); +#endif /* NOKIA */ diff --git a/src/usb_moded-udev.c b/src/usb_moded-udev.c new file mode 100644 index 0000000..94a032a --- /dev/null +++ b/src/usb_moded-udev.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +#include + +#include + +#include "usb_moded-loh.h" + +/* global variables */ +struct udev *udev; +struct udev_monitor *mon; +struct udev_device *dev; + +int hwal_init(void) +{ + struct udev_list_entry *devices, *dev_list_entry; + struct pollfd *fds; + int poll_ret = 0; + + /* Create the udev object */ + udev = udev_new(); + if (!udev) + { + log_err("Can't create udev\n"); + return 1; + } + + /* Set up a monitor to monitor devices */ + mon = udev_monitor_new_from_netlink(udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", NULL); + udev_monitor_enable_receiving(mon); + /* Get the file descriptor (fd) for the monitor. + This fd will get passed to select() */ + fd = udev_monitor_get_fd(mon); + + /* loop waiting for events */ + while(1) + { + /* set a poll on the fd so we do not block trying to read data */ + fds = malloc(sizeof(struct pollfd)); + fds->fd = fd; + fds->events = POLLPRI; + poll_ret = poll(fds, 1, -1); + if(poll_ret) + { + dev = udev_monitor_receive_device(mon); + if(dev) + { + log_debug("Got Device\n"); + log_debug(" Node: %s\n", udev_device_get_devnode(dev)); + log_debug(" Subsystem: %s\n", udev_device_get_subsystem(dev)); + log_debug(" Devtype: %s\n", udev_device_get_devtype(dev)); + log_debug(" Action: %s\n", udev_device_get_action(dev)); + udev_device_unref(dev); + } + + } + +} + +int hwal_cleanup(void) +{ + udev_enumerate_unref(enumerate); + udev_unref(udev); + return 0; +} + + diff --git a/src/usb_moded.c b/src/usb_moded.c new file mode 100644 index 0000000..d41e554 --- /dev/null +++ b/src/usb_moded.c @@ -0,0 +1,583 @@ +/** + @file usb_moded.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 +*/ + +#define _GNU_SOURCE +#include + +#include +#include +#ifdef NOKIA +#include +#endif + +#include "usb_moded.h" +#include "usb_moded-modes.h" +#include "usb_moded-dbus.h" +#include "usb_moded-dbus-private.h" +#include "usb_moded-hw-ab.h" +#include "usb_moded-gconf.h" +#include "usb_moded-gconf-private.h" +#include "usb_moded-modules.h" +#include "usb_moded-log.h" +#include "usb_moded-devicelock.h" +#include "usb_moded-modesetting.h" +#include "usb_moded-modules.h" +#include "usb_moded-appsync.h" + +/* global definitions */ + +extern const char *log_name; +extern int log_level; +extern int log_type; + +gboolean run_as_daemon = FALSE; +gboolean runlevel_ignore = FALSE; +struct usb_mode current_mode; +#ifdef NOKIA +gboolean special_mode = FALSE; +guint timeout_source = 0; +#endif /* NOKIA */ + +#ifdef APP_SYNC +GList *applist = NULL; +#endif /* APP_SYNC */ + +/* static helper functions */ +static void usb_moded_init(void); +static gboolean charging_fallback(gpointer data); +static void usage(void); +static gboolean daemonize(void); + + +/* ============= Implementation starts here =========================================== */ + +/** set the usb connection status + * + * @param connected The connection status, true for connected + * + */ +void set_usb_connected(gboolean connected) +{ +#ifdef NOKIA + if(special_mode) + { + /* Do nothing for the time being to leave currently loaded modules active. + Set special_mode to false so next usb connect makes things work as they should. + */ + special_mode = FALSE; + log_debug("nsu active. Not doing anything before cable disconnect/reconnect\n"); + return; + } +#endif /* NOKIA */ + + if(connected) + { + /* do not go through the routine if already connected to avoid + spurious load/unloads due to faulty signalling + NOKIA: careful with devicelock + */ + if(current_mode.connected) + return; +#ifdef NOKIA + if(timeout_source) + { + g_source_remove(timeout_source); + timeout_source = 0; + } +#endif /* NOKIA */ + current_mode.connected = TRUE; + set_usb_connected_state(); + } + else + { + current_mode.connected = FALSE; + /* signal usb disconnected */ + log_debug("usb disconnected\n"); + /* clean-up state */ + usb_moded_mode_cleanup(get_usb_module()); + usb_moded_send_signal(USB_DISCONNECTED); +#ifdef NOKIA + timeout_source = g_timeout_add_seconds(5, usb_module_timeout_cleanup, NULL); +#else + /* unload modules and general cleanup */ + usb_moded_module_cleanup(get_usb_module()); +#endif /* NOKIA */ + + set_usb_mode(MODE_UNDEFINED); + } +} + +/** set the chosen usb state + * + */ +void set_usb_connected_state(void) +{ + + const char *mode_to_set; +#ifdef NOKIA + int export = 0, act_dead = 0; +#endif /* NOKIA */ + + /* signal usb connected */ + log_debug("usb connected\n"); + usb_moded_send_signal(USB_CONNECTED); + mode_to_set = get_mode_setting(); +#ifdef NOKIA + /* check if we are allowed to export system contents 0 is unlocked */ + export = usb_moded_get_export_permission(); + /* check if we are in acting dead or not, /tmp/USER will not exist in acting dead */ + act_dead = access("/tmp/USER", R_OK); + if(mode_to_set && !export && !act_dead) +#else + if(mode_to_set) +#endif /* NOKIA */ + { + if(!strcmp(MODE_ASK, mode_to_set)) + { + /* send signal, mode will be set when the dialog service calls + the set_mode method call. + */ + usb_moded_send_signal(USB_CONNECTED_DIALOG_SHOW); + /* fallback to charging mode after 3 seconds */ + g_timeout_add_seconds(3, charging_fallback, NULL); + /* in case there was nobody listening for the UI, they will know + that the UI is needed by requesting the current mode */ + set_usb_mode(MODE_ASK); + } + else + set_usb_mode(mode_to_set); + } + else + { + /* gconf is corrupted or does not return a value, fallback to charging + We also fall back here in case the device is locked and we do not + export the system contents. Or if we are in acting dead mode. + */ + set_usb_mode(MODE_CHARGING); + } + +} + +/** set the usb mode + * + * @param mode The requested USB mode + * + */ +void set_usb_mode(const char *mode) +{ + int ret=0, net=0; + + if(!strcmp(mode, MODE_MASS_STORAGE)) + { + + check_module_state(MODULE_MASS_STORAGE); + /* now proceed to set the mode correctly */ + set_usb_module(MODULE_MASS_STORAGE); + ret = usb_moded_load_module(MODULE_MASS_STORAGE); + if(!ret) + ret = set_mass_storage_mode(); + goto end; + } + if(!strcmp(mode, MODE_CHARGING)) + { + check_module_state(MODULE_MASS_STORAGE); + /* for charging we use a fake file_storage (blame USB certification for this insanity */ + set_usb_module(MODULE_MASS_STORAGE); + /* MODULE_CHARGING has all the parameters defined, so it will not match the g_file_storage rule in usb_moded_load_module */ + ret = usb_moded_load_module(MODULE_CHARGING); + goto end; + } + +#ifdef NOKIA + if(!strcmp(mode, MODE_OVI_SUITE)) + { + check_module_state(MODULE_NETWORK); + set_usb_module(MODULE_NETWORK); + ret = usb_moded_load_module(MODULE_NETWORK_MTP); + if(!ret) + ret = set_ovi_suite_mode(applist); + } +#endif /* NOKIA */ + + if(!strcmp(mode, MODE_WINDOWS_NET)) + { + check_module_state(MODULE_WINDOWS_NET); + set_usb_module(MODULE_WINDOWS_NET); + ret = usb_moded_load_module(MODULE_WINDOWS_NET); + net = system("ifdown usb0 ; ifup usb0"); + } + +end: + /* if ret != 0 then usb_module loading failed */ + if(ret) + { + set_usb_module(MODULE_NONE); + mode = MODE_UNDEFINED; + } + free(current_mode.mode); + current_mode.mode = strdup(mode); + usb_moded_send_signal(get_usb_mode()); +} + +/** get the usb mode + * + * @return the currently set mode + * + */ +const char * get_usb_mode(void) +{ + return(current_mode.mode); +} + +/** set the loaded module + * + * @param module The module name for the requested mode + * + */ +void set_usb_module(const char *module) +{ + free(current_mode.module); + current_mode.module = strdup(module); +} + +/** get the supposedly loaded module + * + * @return The name of the loaded module + * + */ +const char * get_usb_module(void) +{ + return(current_mode.module); +} + +/** get if the cable is connected or not + * + * @ return A boolean value for connected (TRUE) or not (FALSE) + * + */ +gboolean get_usb_connection_state(void) +{ + return current_mode.connected; +} + + +/*================ Static functions ===================================== */ + +/* set default values for usb_moded */ +static void usb_moded_init(void) +{ +#ifdef NOKIA + char readbuf[MAX_READ_BUF]; + FILE *proc_fd; +#endif /* NOKIA */ + + current_mode.connected = FALSE; + current_mode.mounted = FALSE; + current_mode.mode = strdup(MODE_UNDEFINED); + current_mode.module = g_strdup(MODULE_NONE); + +#ifdef NOKIA + proc_fd = fopen("/proc/cmdline", "r"); + if(proc_fd) + { + fgets(readbuf, MAX_READ_BUF, proc_fd); + readbuf[strlen(readbuf)-1]=0; + + if(strstr(readbuf, "nsu")) + special_mode = TRUE; + fclose(proc_fd); + } + +#endif /* NOKIA */ +#ifdef APP_SYNC + applist = readlist(); +#endif /* APP_SYNC */ + /* TODO: add more start-up clean-up and init here if needed */ + +} + +/* charging fallback handler */ +static gboolean charging_fallback(gpointer data) +{ + /* if a mode has been set we don't want it changed to charging + * after 5 seconds. We set it to ask, so anything different + * means a mode has been set */ + if(strcmp(get_usb_mode(), MODE_ASK) != 0) + return FALSE; + set_usb_mode(MODE_CHARGING); + /* since this is the fallback, we keep an indication + for the UI, as we are not really in charging mode. + */ + free(current_mode.mode); + current_mode.mode = strdup(MODE_ASK); + log_info("Falling back on charging mode.\n"); + + return(FALSE); +} + +/* Display usage information */ +static void usage(void) +{ + fprintf(stdout, + "Usage: usb_moded [OPTION]...\n" + "USB mode daemon\n" + "\n" + " -d, --daemon run as a daemon\n" + " -s, --force-syslog log to syslog even when not " + "daemonized\n" + " -T, --force-stderr log to stderr even when daemonized\n" + " -D, --debug turn on debug printing\n" + " -h, --help display this help and exit\n" + " -v, --version output version information and exit\n" + " -w, --watch-off do not act on runlevel change\n" + "\n"); +} + +/* Turn the process in a daemon */ +static gboolean daemonize(void) +{ + gint retries = 0; + gint i = 0; + gchar str[10]; + + if (getppid() == 1) + exit(0); /* Already daemonized */ + + /* Detach from process group */ + switch (fork()) + { + case -1: + /* Failure */ + exit(1); + + case 0: + /* Child */ + break; + + default: + /* Parent -- exit */ + exit(0); + } + + /* Detach TTY */ + setsid(); + + /* Close all file descriptors and redirect stdio to /dev/null */ + if ((i = getdtablesize()) == -1) + i = 256; + + while (--i >= 0) + { + if (close(i) == -1) + { + if (retries > 10) + { + log_crit("close() was interrupted more than 10 times. Exiting.\n"); + exit(1); + } + + if (errno == EINTR) + { + log_err("close() was interrupted; retrying.\n"); + errno = 0; + i++; + retries++; + } + else if (errno == EBADF) + { + /* fprintf(stdout, "Failed to close() fd %d; %s. Ignoring.\n", + i + 1, g_strerror(errno));*/ + errno = 0; + } + else + { + log_crit("Failed to close() fd %d; %s. Exiting.", i + 1, g_strerror(errno)); + exit(1); + } + } + else + retries = 0; + } + + if ((i = open("/dev/null", O_RDWR)) == -1) + { + log_crit("Cannot open `/dev/null'; %s. Exiting.", g_strerror(errno)); + exit(1); + } + + if ((dup(i) == -1)) + { + log_crit("Failed to dup() `/dev/null'; %s. Exiting.", g_strerror(errno)); + exit(1); + } + if ((dup(i) == -1)) + { + log_crit("Failed to dup() `/dev/null'; %s. Exiting.", g_strerror(errno)); + exit(1); + } + + /* Set umask */ + umask(022); + + /* Set working directory */ + if ((chdir("/tmp") == -1)) + { + log_crit("Failed to chdir() to `/tmp'; %s. Exiting.", g_strerror(errno)); + exit(1); + } + + /* Single instance */ + if ((i = open(USB_MODED_LOCKFILE, O_RDWR | O_CREAT, 0640)) == -1) + { + log_crit("Cannot open lockfile; %s. Exiting.", g_strerror(errno)); + exit(1); + } + + if (lockf(i, F_TLOCK, 0) == -1) + { + log_crit("Already running. Exiting."); + exit(1); + } + + sprintf(str, "%d\n", getpid()); + write(i, str, strlen(str)); + close(i); + + /* Ignore TTY signals */ + signal(SIGTSTP, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + + /* Ignore child terminate signal */ + signal(SIGCHLD, SIG_IGN); + + log_info("Daemon running."); + return 0; +} + + + +int main(int argc, char* argv[]) +{ + int result = EXIT_FAILURE; + int opt = 0, opt_idx = 0; + GMainLoop *mainloop = NULL; + + struct option const options[] = { + { "daemon", no_argument, 0, 'd' }, + { "force-syslog", no_argument, 0, 's' }, + { "force-stderr", no_argument, 0, 'T' }, + { "debug", no_argument, 0, 'D' }, + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { 0, 0, 0, 0 } + }; + + log_name = basename(*argv); + + /* Parse the command-line options */ + while ((opt = getopt_long(argc, argv, "dsTDhvw", options, &opt_idx)) != -1) + { + switch (opt) + { + case 'd': + run_as_daemon = TRUE; + break; + + case 's': + log_type = LOG_TO_SYSLOG; + break; + + case 'T': + log_type = LOG_TO_STDERR; + break; + + case 'D': + log_level = LOG_DEBUG; + break; + + case 'h': + usage(); + exit(0); + + case 'v': + printf("USB mode daemon version: %s\n", VERSION); + exit(0); + + case 'w': + runlevel_ignore = TRUE; + printf("Ignore runlevel changes.\n"); + break; + default: + usage(); + exit(0); + } + } + + if(run_as_daemon == TRUE) + { + log_notice("going to daemon mode\n"); + daemonize(); + } + + /* silence system() calls */ + if(log_type != LOG_TO_STDERR || log_level != LOG_DEBUG ) + { + freopen("/dev/null", "a", stdout); + freopen("/dev/null", "a", stderr); + } + g_type_init(); + mainloop = g_main_loop_new(NULL, FALSE); + log_debug("usb_moded starting\n"); + + /* init daemon into a clean state first, then dbus and hw_abstraction last */ + usb_moded_init(); + if( !usb_moded_dbus_init() ) + { + log_crit("dbus ipc init failed\n"); + goto EXIT; + } + if( !hwal_init() ) + { + log_crit("hwal init failed\n"); + goto EXIT; + } +#ifdef NOKIA + start_devicelock_listener(); + if(!runlevel_ignore) + usb_moded_dsme_listener(); +#endif /* NOKIA */ + + /* init succesful, run main loop */ + result = EXIT_SUCCESS; + g_main_loop_run(mainloop); +EXIT: + /* exiting and clean-up when mainloop ended */ + hwal_cleanup(); + usb_moded_dbus_cleanup(); + + /* If the mainloop is initialised, unreference it */ + if (mainloop != NULL) + g_main_loop_unref(mainloop); + + return result; +} diff --git a/src/usb_moded.h b/src/usb_moded.h new file mode 100644 index 0000000..c8ab0e8 --- /dev/null +++ b/src/usb_moded.h @@ -0,0 +1,58 @@ +/* + 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 +*/ + +#ifndef USB_MODED_H_ +#define USB_MODED_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define USB_MODED_LOCKFILE "/var/run/usb_moded.pid" +#define MAX_READ_BUF 512 + +typedef struct usb_mode +{ + gboolean connected; + gboolean mounted; + char *mode; + char *module; + +}usb_mode; + +void set_usb_connected(gboolean connected); +void set_usb_connected_state(void); +void set_usb_mode(const char *mode); +const char * get_usb_mode(void); +void set_usb_module(const char *module); +const char * get_usb_module(void); +gboolean get_usb_connection_state(void); + +#endif /* USB_MODED_H */ diff --git a/usb-moded.ini b/usb-moded.ini new file mode 100644 index 0000000..b3d31e4 --- /dev/null +++ b/usb-moded.ini @@ -0,0 +1,10 @@ +[mountpoints] +mount = /dev/mmcblk0p1 + +#you can add more filesystems to the mount option, by making it a comma-seperated list. + +[sync] +nofua = 1 + +[altmount] +mount = /home/user/MyDocs diff --git a/usb_moded.pc.in b/usb_moded.pc.in new file mode 100644 index 0000000..5ee8bbd --- /dev/null +++ b/usb_moded.pc.in @@ -0,0 +1,10 @@ +prefix=/usr +includedir=${prefix}/include/usb-moded +libdir=${prefix}/lib + +Name: usb_moded +Description: usb_moded defines for dbus and mode names +Version: @VERSION@ +Requires: +Libs: +Cflags: -I${includedir}