connman: add Tizen patches 90/31190/2
authorKévin THIERRY <kevin.thierry@open.eurogiciel.org>
Tue, 2 Dec 2014 10:20:40 +0000 (11:20 +0100)
committerronan(Eurogiciel) Le Martret <ronan.lemartret@open.eurogiciel.org>
Fri, 5 Dec 2014 13:41:13 +0000 (05:41 -0800)
Change-Id: I5b9f65476b2d08fb602b7365fdb8556665f7ec30
Signed-off-by: Kévin THIERRY <kevin.thierry@open.eurogiciel.org>
33 files changed:
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0001-Add-bootstrap-files.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0002-Add-package-build-spec-file.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0003-Add-systemd-service-to-manager-ConnMan-NTP.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0004-Set-manifest-request-domain-to-floor.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0005-Set-ConnMan-default-settings-in-config-files.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0006-Enable-ConnMan-NTP-configurable-in-spec-file.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0007-Enable-ConnMan-VPND-OpenVPN-OpenConnect-configurable.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0008-Add-connmanctl-to-the-built-rpm.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0009-Tizen-Export-more-wifi-info-in-ConnMan-network-API.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0010-Tizen-Append-extra-wifi-service-property.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0011-Tizen-Export-network-proxy-API-for-telephony-plugin.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0012-Tizen-Integrate-telephony-plugin.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0013-Tizen-Fix-wifi-enterprise-to-support-SIM-and-AKA.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0014-Tizen-Check-some-telephony-flags-before-active-conte.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0015-Tizen-Unify-bluetooth-tethering-enable-logic.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0016-Tethering-Add-handling-for-wpa_supplicant-authorized.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0017-Tethering-Add-station-information-management-feature.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0018-Tethering-Add-interface-that-save-lease-in-DHCP-info.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0019-Tethering-Notify-listeners-when-station-connection-c.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0020-Tethering-Add-open-access-point-support-in-technolog.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0021-Tethering-Add-hidden-access-point-support-in-technol.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0022-Tethering-Add-test-script-of-open-and-hidden-AP.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0023-Tethering-Add-tethering-interfaces-description-to-te.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0024-Tethering-Watch-the-connection-and-disconnection-sig.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0025-Tethering-Get-the-client-mac-info-of-Gadget-tether.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0026-multi-user-Add-function-to-get-dbus-user-id-synchron.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0027-multi-user-Add-multi-user-support-in-service.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0028-multi-user-Add-multi-user-support-in-technology.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0029-multi-user-Add-multi-user-support-in-manager.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0030-multi-user-Add-multi-user-support-for-auto-connect-s.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0031-multi-user-Expose-function-to-check-service-user-fav.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0032-multi-user-Fix-service-load-save-issues.patch [new file with mode: 0644]
meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman_%.bbappend [new file with mode: 0644]

diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0001-Add-bootstrap-files.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0001-Add-bootstrap-files.patch
new file mode 100644 (file)
index 0000000..c0cec7f
--- /dev/null
@@ -0,0 +1,55 @@
+From 79fe33b1a73f42592ac98c44b87dc15b52c7d791 Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 11 Jul 2014 09:34:05 +0800
+Subject: [PATCH 01/32] Add bootstrap files
+
+Change-Id: Ia3923cb1ff35e7bfbd4e45f13dd18af15ed89f56
+---
+ bootstrap           |  7 +++++++
+ bootstrap-configure | 20 ++++++++++++++++++++
+ 2 files changed, 27 insertions(+)
+ create mode 100755 bootstrap
+ create mode 100755 bootstrap-configure
+
+diff --git a/bootstrap b/bootstrap
+new file mode 100755
+index 0000000..0dd71d9
+--- /dev/null
++++ b/bootstrap
+@@ -0,0 +1,7 @@
++#!/bin/sh
++
++aclocal && \
++    autoheader && \
++        libtoolize --automake --copy --force && \
++          automake --add-missing --copy && \
++              autoconf
+diff --git a/bootstrap-configure b/bootstrap-configure
+new file mode 100755
+index 0000000..070c676
+--- /dev/null
++++ b/bootstrap-configure
+@@ -0,0 +1,20 @@
++#!/bin/sh
++
++if [ -f config.status ]; then
++      make maintainer-clean
++fi
++
++./bootstrap && \
++    ./configure --enable-maintainer-mode \
++              --enable-debug \
++              --prefix=/usr \
++              --mandir=/usr/share/man \
++              --localstatedir=/var \
++              --sysconfdir=/etc \
++              --disable-datafiles \
++              --enable-openconnect=builtin \
++              --enable-openvpn=builtin \
++              --enable-vpnc=builtin \
++              --enable-session-policy-local=builtin \
++              --enable-nmcompat \
++              --enable-polkit $*
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0002-Add-package-build-spec-file.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0002-Add-package-build-spec-file.patch
new file mode 100644 (file)
index 0000000..7c29ad5
--- /dev/null
@@ -0,0 +1,117 @@
+From 88ec373b61d46ef46dcab48fe14d02ab7254763c Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 4 Jul 2014 13:45:07 +0800
+Subject: [PATCH 02/32] Add package build spec file
+
+Change-Id: Ia8c78e122998da70565700d895dbf54688e7c8b9
+---
+ packaging/connman.spec | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 97 insertions(+)
+ create mode 100644 packaging/connman.spec
+
+diff --git a/packaging/connman.spec b/packaging/connman.spec
+new file mode 100644
+index 0000000..7da9ddd
+--- /dev/null
++++ b/packaging/connman.spec
+@@ -0,0 +1,97 @@
++Name:           connman
++Version:        1.26
++Release:        1
++License:        GPL-2.0
++Summary:        Connection Manager
++Url:            http://connman.net
++Group:          Network & Connectivity/Connection Management
++Source0:        %{name}-%{version}.tar.gz
++BuildRequires:        systemd
++BuildRequires:  pkgconfig(dbus-1)
++BuildRequires:  pkgconfig(glib-2.0)
++BuildRequires:  pkgconfig(libiptc)
++BuildRequires:  pkgconfig(xtables)
++BuildRequires:  pkgconfig(gnutls)
++BuildRequires:  readline-devel
++%systemd_requires
++Requires:       iptables
++
++%description
++Connection Manager provides a daemon for managing Internet connections
++within embedded devices running the Linux operating system.
++
++%package test
++Summary:        Test Scripts for Connection Manager
++Requires:       %{name} = %{version}
++Requires:       dbus-python
++Requires:       pygobject
++Requires:       python-xml
++
++%description test
++Scripts for testing Connman and its functionality
++
++%package devel
++Summary:        Development Files for connman
++Requires:       %{name} = %{version}
++
++%description devel
++Header files and development files for connman.
++
++%prep
++%setup -q
++
++%build
++CFLAGS+=" -DTIZEN_EXT"
++
++chmod +x bootstrap
++./bootstrap
++%configure \
++            --enable-threads \
++            --enable-client \
++            --enable-pacrunner \
++            --enable-wifi=builtin \
++            --enable-test \
++            --enable-loopback \
++            --enable-ethernet \
++            --with-systemdunitdir=%{_unitdir}
++
++make %{?_smp_mflags}
++
++%install
++%make_install
++
++mkdir -p %{buildroot}%{_sysconfdir}/connman
++cp src/main.conf %{buildroot}%{_sysconfdir}/connman/main.conf
++
++%install_service network.target.wants connman.service
++%install_service multi-user.target.wants connman.service
++
++%post
++systemctl daemon-reload
++systemctl restart connman.service
++
++%preun
++systemctl stop connman.service
++
++%postun
++systemctl daemon-reload
++
++%docs_package
++
++%files
++%license COPYING
++%{_sbindir}/*
++%config %{_sysconfdir}/connman/main.conf
++%config %{_sysconfdir}/dbus-1/system.d/*
++%{_unitdir}/connman.service
++%{_unitdir}/network.target.wants/connman.service
++%{_unitdir}/multi-user.target.wants/connman.service
++
++%files test
++%{_libdir}/%{name}/test/*
++
++%files devel
++%{_includedir}/connman/*.h
++%{_libdir}/pkgconfig/*.pc
++
++%changelog
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0003-Add-systemd-service-to-manager-ConnMan-NTP.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0003-Add-systemd-service-to-manager-ConnMan-NTP.patch
new file mode 100644 (file)
index 0000000..f12ba95
--- /dev/null
@@ -0,0 +1,41 @@
+From cdc8865c44bb77e9b7fa664a3669f84f7305718d Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 4 Jul 2014 14:12:08 +0800
+Subject: [PATCH 03/32] Add systemd service to manager ConnMan NTP
+
+---
+ packaging/40-connman-ntp.list |  1 +
+ packaging/connman-ntp.service | 13 +++++++++++++
+ 2 files changed, 14 insertions(+)
+ create mode 100644 packaging/40-connman-ntp.list
+ create mode 100644 packaging/connman-ntp.service
+
+diff --git a/packaging/40-connman-ntp.list b/packaging/40-connman-ntp.list
+new file mode 100644
+index 0000000..9b84282
+--- /dev/null
++++ b/packaging/40-connman-ntp.list
+@@ -0,0 +1 @@
++connman-ntp.service
+diff --git a/packaging/connman-ntp.service b/packaging/connman-ntp.service
+new file mode 100644
+index 0000000..6ca46e2
+--- /dev/null
++++ b/packaging/connman-ntp.service
+@@ -0,0 +1,13 @@
++[Unit]
++Description=Connman NTP service
++Requires=connman.service
++After=connman.service
++
++[Service]
++Type=oneshot
++ExecStart=/bin/bash -c "dbus-send --system --type=method_call --print-reply --dest=net.connman / net.connman.Clock.SetProperty string:'TimeUpdates' variant:string:'auto'"
++ExecStop=/bin/bash -c "dbus-send --system --type=method_call --print-reply --dest=net.connman / net.connman.Clock.SetProperty string:'TimeUpdates' variant:string:'manual'"
++RemainAfterExit=yes
++
++[Install]
++WantedBy=multi-user.target
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0004-Set-manifest-request-domain-to-floor.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0004-Set-manifest-request-domain-to-floor.patch
new file mode 100644 (file)
index 0000000..ffb90f7
--- /dev/null
@@ -0,0 +1,65 @@
+From 7923d6ca6ccb144a5b036b03a015a182c3622a92 Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 4 Jul 2014 13:50:49 +0800
+Subject: [PATCH 04/32] Set manifest request domain to floor
+
+---
+ packaging/connman.manifest | 5 +++++
+ packaging/connman.spec     | 5 +++++
+ 2 files changed, 10 insertions(+)
+ create mode 100644 packaging/connman.manifest
+
+diff --git a/packaging/connman.manifest b/packaging/connman.manifest
+new file mode 100644
+index 0000000..017d22d
+--- /dev/null
++++ b/packaging/connman.manifest
+@@ -0,0 +1,5 @@
++<manifest>
++ <request>
++    <domain name="_"/>
++ </request>
++</manifest>
+diff --git a/packaging/connman.spec b/packaging/connman.spec
+index 7da9ddd..c43deaa 100644
+--- a/packaging/connman.spec
++++ b/packaging/connman.spec
+@@ -6,6 +6,7 @@ Summary:        Connection Manager
+ Url:            http://connman.net
+ Group:          Network & Connectivity/Connection Management
+ Source0:        %{name}-%{version}.tar.gz
++Source1001:     connman.manifest
+ BuildRequires:        systemd
+ BuildRequires:  pkgconfig(dbus-1)
+ BuildRequires:  pkgconfig(glib-2.0)
+@@ -39,6 +40,7 @@ Header files and development files for connman.
+ %prep
+ %setup -q
++cp %{SOURCE1001} .
+ %build
+ CFLAGS+=" -DTIZEN_EXT"
+@@ -79,6 +81,7 @@ systemctl daemon-reload
+ %docs_package
+ %files
++%manifest %{name}.manifest
+ %license COPYING
+ %{_sbindir}/*
+ %config %{_sysconfdir}/connman/main.conf
+@@ -88,9 +91,11 @@ systemctl daemon-reload
+ %{_unitdir}/multi-user.target.wants/connman.service
+ %files test
++%manifest %{name}.manifest
+ %{_libdir}/%{name}/test/*
+ %files devel
++%manifest %{name}.manifest
+ %{_includedir}/connman/*.h
+ %{_libdir}/pkgconfig/*.pc
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0005-Set-ConnMan-default-settings-in-config-files.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0005-Set-ConnMan-default-settings-in-config-files.patch
new file mode 100644 (file)
index 0000000..8c37f11
--- /dev/null
@@ -0,0 +1,66 @@
+From 85053773dfe482c81ca1ac87dc6baf2ff6b29df0 Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 4 Jul 2014 14:49:18 +0800
+Subject: [PATCH 05/32] Set ConnMan default settings in config files
+
+---
+ src/connman.service.in | 3 ++-
+ src/main.conf          | 4 ++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/connman.service.in b/src/connman.service.in
+index 7b6195e..67d051d 100644
+--- a/src/connman.service.in
++++ b/src/connman.service.in
+@@ -5,10 +5,11 @@ After=dbus.socket
+ Before=remote-fs.target
+ [Service]
++EnvironmentFile=-/etc/sysconfig/connman
+ Type=dbus
+ BusName=net.connman
+ Restart=on-failure
+-ExecStart=@prefix@/sbin/connmand -n
++ExecStart=@prefix@/sbin/connmand -n $OPTIONS
+ StandardOutput=null
+ [Install]
+diff --git a/src/main.conf b/src/main.conf
+index 93c7a50..c979553 100644
+--- a/src/main.conf
++++ b/src/main.conf
+@@ -19,6 +19,7 @@
+ # the scan list is empty. In that case, a simple backoff
+ # mechanism starting from 10s up to 5 minutes will run.
+ # BackgroundScanning = true
++BackgroundScanning = false
+ # List of Fallback timeservers separated by ",".
+ # These timeservers are used for NTP sync when there are
+@@ -26,6 +27,7 @@
+ # These can contain mixed combination of fully qualified
+ # domain names, IPv4 and IPv6 addresses.
+ # FallbackTimeservers =
++FallbackTimeservers = pool.ntp.org
+ # List of fallback nameservers separated by "," used if no
+ # nameservers are otherwise provided by the service. The
+@@ -52,6 +54,7 @@
+ # the default route when compared to either a non-preferred
+ # type or a preferred type further down in the list.
+ # PreferredTechnologies =
++PreferredTechnologies = ethernet,wifi
+ # List of blacklisted network interfaces separated by ",".
+ # Found interfaces will be compared to the list and will
+@@ -59,6 +62,7 @@
+ # match any of the list entries. Default value is
+ # vmnet,vboxnet,virbr,ifb.
+ # NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb
++NetworkInterfaceBlacklist = vmnet,vboxnet,virbr
+ # Allow connman to change the system hostname. This can
+ # happen for example if we receive DHCP hostname option.
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0006-Enable-ConnMan-NTP-configurable-in-spec-file.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0006-Enable-ConnMan-NTP-configurable-in-spec-file.patch
new file mode 100644 (file)
index 0000000..46074fb
--- /dev/null
@@ -0,0 +1,60 @@
+From 346988b0c78109cce94fec48f8eeb16719426fa3 Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 4 Jul 2014 14:33:55 +0800
+Subject: [PATCH 06/32] Enable ConnMan NTP configurable in spec file
+
+---
+ packaging/connman.spec | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/packaging/connman.spec b/packaging/connman.spec
+index c43deaa..5438f4c 100644
+--- a/packaging/connman.spec
++++ b/packaging/connman.spec
+@@ -1,3 +1,5 @@
++%bcond_with     connman_ntp
++
+ Name:           connman
+ Version:        1.26
+ Release:        1
+@@ -6,6 +8,8 @@ Summary:        Connection Manager
+ Url:            http://connman.net
+ Group:          Network & Connectivity/Connection Management
+ Source0:        %{name}-%{version}.tar.gz
++Source10:       40-connman-ntp.list
++Source11:       connman-ntp.service
+ Source1001:     connman.manifest
+ BuildRequires:        systemd
+ BuildRequires:  pkgconfig(dbus-1)
+@@ -62,6 +66,14 @@ make %{?_smp_mflags}
+ %install
+ %make_install
++%if %{with connman_ntp}
++mkdir -p %{buildroot}/usr/lib/systemd/ntp-units.d
++install -m644 %{SOURCE10} %{buildroot}/usr/lib/systemd/ntp-units.d
++install -m644 %{SOURCE11} %{buildroot}%{_unitdir}
++%install_service network.target.wants connman-ntp.service
++%install_service multi-user.target.wants connman-ntp.service
++%endif
++
+ mkdir -p %{buildroot}%{_sysconfdir}/connman
+ cp src/main.conf %{buildroot}%{_sysconfdir}/connman/main.conf
+@@ -89,6 +101,13 @@ systemctl daemon-reload
+ %{_unitdir}/connman.service
+ %{_unitdir}/network.target.wants/connman.service
+ %{_unitdir}/multi-user.target.wants/connman.service
++%if %{with connman_ntp}
++%dir /usr/lib/systemd/ntp-units.d
++%{_unitdir}/connman-ntp.service
++%{_unitdir}/multi-user.target.wants/connman-ntp.service
++%{_unitdir}/network.target.wants/connman-ntp.service
++/usr/lib/systemd/ntp-units.d/40-connman-ntp.list
++%endif
+ %files test
+ %manifest %{name}.manifest
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0007-Enable-ConnMan-VPND-OpenVPN-OpenConnect-configurable.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0007-Enable-ConnMan-VPND-OpenVPN-OpenConnect-configurable.patch
new file mode 100644 (file)
index 0000000..2ab8b28
--- /dev/null
@@ -0,0 +1,148 @@
+From 509d88ad3a5d229a5df0e7f349ac70e02148396e Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 4 Jul 2014 14:37:58 +0800
+Subject: [PATCH 07/32] Enable ConnMan VPND/OpenVPN/OpenConnect configurable in
+ spec file
+
+---
+ packaging/connman.spec | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 88 insertions(+)
+
+diff --git a/packaging/connman.spec b/packaging/connman.spec
+index 5438f4c..edc1d53 100644
+--- a/packaging/connman.spec
++++ b/packaging/connman.spec
+@@ -1,3 +1,6 @@
++%bcond_with     connman_openconnect
++%bcond_with     connman_openvpn
++%bcond_with     connman_vpnd
+ %bcond_with     connman_ntp
+ Name:           connman
+@@ -17,6 +20,12 @@ BuildRequires:  pkgconfig(glib-2.0)
+ BuildRequires:  pkgconfig(libiptc)
+ BuildRequires:  pkgconfig(xtables)
+ BuildRequires:  pkgconfig(gnutls)
++%if %{with connman_openconnect}
++BuildRequires:  openconnect
++%endif
++%if %{with connman_openvpn}
++BuildRequires:  openvpn
++%endif
+ BuildRequires:  readline-devel
+ %systemd_requires
+ Requires:       iptables
+@@ -25,6 +34,36 @@ Requires:       iptables
+ Connection Manager provides a daemon for managing Internet connections
+ within embedded devices running the Linux operating system.
++%if %{with connman_openconnect}
++%package plugin-openconnect
++Summary:        Openconnect Support for Connman
++Requires:       %{name} = %{version}
++Requires:       openconnect
++
++%description plugin-openconnect
++Openconnect Support for Connman.
++%endif
++
++%if %{with connman_openvpn}
++%package plugin-openvpn
++Summary:        Openvpn Support for Connman
++Requires:       %{name} = %{version}
++Requires:       openvpn
++
++%description plugin-openvpn
++OpenVPN support for Connman.
++%endif
++
++%if %{with connman_vpnd}
++%package connman-vpnd
++Summary:        VPN Support for Connman
++BuildRequires:  %{name} = %{version}
++Requires:       %{name} = %{version}
++
++%description connman-vpnd
++Provides VPN support for Connman
++%endif
++
+ %package test
+ Summary:        Test Scripts for Connection Manager
+ Requires:       %{name} = %{version}
+@@ -56,6 +95,12 @@ chmod +x bootstrap
+             --enable-client \
+             --enable-pacrunner \
+             --enable-wifi=builtin \
++%if %{with connman_openconnect}
++            --enable-openconnect \
++%endif
++%if %{with connman_openvpn}
++            --enable-openvpn \
++%endif
+             --enable-test \
+             --enable-loopback \
+             --enable-ethernet \
+@@ -80,12 +125,23 @@ cp src/main.conf %{buildroot}%{_sysconfdir}/connman/main.conf
+ %install_service network.target.wants connman.service
+ %install_service multi-user.target.wants connman.service
++%if %{with connman_vpnd}
++%install_service network.target.wants connman-vpn.service
++%install_service multi-user.target.wants connman-vpn.service
++%endif
++
+ %post
+ systemctl daemon-reload
+ systemctl restart connman.service
++%if %{with connman_vpnd}
++systemctl restart connman-vpn.service
++%endif
+ %preun
+ systemctl stop connman.service
++%if %{with connman_vpnd}
++systemctl stop connman-vpn.service
++%endif
+ %postun
+ systemctl daemon-reload
+@@ -118,4 +174,36 @@ systemctl daemon-reload
+ %{_includedir}/connman/*.h
+ %{_libdir}/pkgconfig/*.pc
++%if %{with connman_openconnect}
++%files plugin-openconnect
++%manifest %{name}.manifest
++%{_unitdir}/connman-vpn.service
++%{_libdir}/connman/plugins-vpn/openconnect.so
++%{_libdir}/connman/scripts/openconnect-script
++%{_datadir}/dbus-1/system-services/net.connman.vpn.service
++%endif
++
++%if %{with connman_openvpn}
++%files plugin-openvpn
++%manifest %{name}.manifest
++%{_unitdir}/connman-vpn.service
++%{_libdir}/%{name}/plugins-vpn/openvpn.so
++%{_libdir}/%{name}/scripts/openvpn-script
++%{_datadir}/dbus-1/system-services/net.connman.vpn.service
++%endif
++
++%if %{with connman_vpnd}
++%files connman-vpnd
++%manifest %{name}.manifest
++%{_sbindir}/connman-vpnd
++%{_unitdir}/connman-vpn.service
++%{_unitdir}/network.target.wants/connman-vpn.service
++%{_unitdir}/multi-user.target.wants/connman-vpn.service
++%dir %{_libdir}/%{name}
++%dir %{_libdir}/%{name}/scripts
++%dir %{_libdir}/%{name}/plugins-vpn
++%config %{_sysconfdir}/dbus-1/system.d/connman-vpn-dbus.conf
++%{_datadir}/dbus-1/system-services/net.connman.vpn.service
++%endif
++
+ %changelog
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0008-Add-connmanctl-to-the-built-rpm.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0008-Add-connmanctl-to-the-built-rpm.patch
new file mode 100644 (file)
index 0000000..dd89415
--- /dev/null
@@ -0,0 +1,26 @@
+From 8b828d775adb413be2e02a5377d83af9ecb979ed Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Tue, 19 Aug 2014 09:41:09 +0800
+Subject: [PATCH 08/32] Add connmanctl to the built rpm
+
+Change-Id: I84fb13ea9224985ad9e15b5c3c5f616bcf7431a4
+---
+ Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index a574170..76863cf 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -237,7 +237,7 @@ script_LTLIBRARIES =
+ include Makefile.plugins
+ if CLIENT
+-noinst_PROGRAMS += client/connmanctl
++sbin_PROGRAMS += client/connmanctl
+ noinst_MANUAL_PAGES = doc/connmanctl.1
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0009-Tizen-Export-more-wifi-info-in-ConnMan-network-API.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0009-Tizen-Export-more-wifi-info-in-ConnMan-network-API.patch
new file mode 100644 (file)
index 0000000..cd3eafd
--- /dev/null
@@ -0,0 +1,283 @@
+From 98894f533f23fe532a4449ddaafaa69d39441980 Mon Sep 17 00:00:00 2001
+From: Arron Wang <arron.wang@intel.com>
+Date: Mon, 24 Sep 2012 14:18:07 +0800
+Subject: [PATCH 09/32] Tizen: Export more wifi info in ConnMan network API
+
+Network client requires additional wifi specific info
+
+Export the BSSID property
+Export the MaxRate property
+Export the detailed info for encryption mode(mixed,aes,tkip,wep,none)
+
+Export the connman_network get/set method for bssid, maxrate,
+encryption_mode property
+
+Change-Id: Ic5744978282e49cb2f70165aaadc7822dc718dfb
+---
+ gsupplicant/gsupplicant.h | 10 +++++++
+ gsupplicant/supplicant.c  | 49 +++++++++++++++++++++++++++++++
+ include/network.h         | 17 +++++++++++
+ plugins/wifi.c            | 25 +++++++++++++++-
+ src/network.c             | 73 +++++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 173 insertions(+), 1 deletion(-)
+
+diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
+index e49aaa6..27826dc 100644
+--- a/gsupplicant/gsupplicant.h
++++ b/gsupplicant/gsupplicant.h
+@@ -336,6 +336,16 @@ GSupplicantInterface *g_supplicant_peer_get_group_interface(GSupplicantPeer *pee
+ bool g_supplicant_peer_is_client(GSupplicantPeer *peer);
+ bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer);
++#if defined TIZEN_EXT
++/*
++* Description: Network client requires additional wifi specific info
++*/
++const unsigned char *g_supplicant_network_get_bssid(
++                                              GSupplicantNetwork *network);
++unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network);
++const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network);
++#endif
++
+ struct _GSupplicantCallbacks {
+       void (*system_ready) (void);
+       void (*system_killed) (void);
+diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
+index 909a617..d2e4a64 100644
+--- a/gsupplicant/supplicant.c
++++ b/gsupplicant/supplicant.c
+@@ -1169,6 +1169,55 @@ bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer)
+       return peer->connection_requested;
+ }
++#if defined TIZEN_EXT
++/*
++ * Description: Network client requires additional wifi specific info
++ */
++const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
++{
++      if (network == NULL || network->best_bss == NULL)
++              return NULL;
++
++      return (const unsigned char *)network->best_bss->bssid;
++}
++
++unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
++{
++      if (network == NULL || network->best_bss == NULL)
++              return 0;
++
++      return network->best_bss->maxrate;
++}
++
++const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
++{
++      if (network == NULL || network->best_bss == NULL)
++              return NULL;
++
++      if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
++          network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
++              unsigned int pairwise;
++
++              pairwise = network->best_bss->rsn_pairwise |
++                              network->best_bss->wpa_pairwise;
++
++              if ((pairwise & G_SUPPLICANT_PAIRWISE_CCMP) &&
++                  (pairwise & G_SUPPLICANT_PAIRWISE_TKIP))
++                      return "mixed";
++              else if (pairwise & G_SUPPLICANT_PAIRWISE_CCMP)
++                      return "aes";
++              else if (pairwise & G_SUPPLICANT_PAIRWISE_TKIP)
++                      return "tkip";
++
++      } else if (network->best_bss->security == G_SUPPLICANT_SECURITY_WEP)
++              return "wep";
++      else if (network->best_bss->security == G_SUPPLICANT_SECURITY_NONE)
++              return "none";
++
++      return NULL;
++}
++#endif
++
+ static void merge_network(GSupplicantNetwork *network)
+ {
+       GString *str;
+diff --git a/include/network.h b/include/network.h
+index d772699..180f2a2 100644
+--- a/include/network.h
++++ b/include/network.h
+@@ -116,6 +116,23 @@ int connman_network_set_nameservers(struct connman_network *network,
+                               const char *nameservers);
+ int connman_network_set_domain(struct connman_network *network,
+                                    const char *domain);
++#if defined TIZEN_EXT
++/*
++ * Description: Network client requires additional wifi specific info
++ */
++int connman_network_set_bssid(struct connman_network *network,
++                              const unsigned char *bssid);
++unsigned char *connman_network_get_bssid(struct connman_network *network);
++
++int connman_network_set_maxrate(struct connman_network *network,
++                              unsigned int maxrate);
++unsigned int connman_network_get_maxrate(struct connman_network *network);
++
++int connman_network_set_enc_mode(struct connman_network *network,
++                              const char *encryption_mode);
++const char *connman_network_get_enc_mode(struct connman_network *network);
++#endif
++
+ int connman_network_set_name(struct connman_network *network,
+                                                       const char *name);
+ int connman_network_set_strength(struct connman_network *network,
+diff --git a/plugins/wifi.c b/plugins/wifi.c
+index 5f2ebf1..69a0e23 100644
+--- a/plugins/wifi.c
++++ b/plugins/wifi.c
+@@ -2602,7 +2602,14 @@ static void network_added(GSupplicantNetwork *supplicant_network)
+       connman_network_set_frequency(network,
+                       g_supplicant_network_get_frequency(supplicant_network));
+-
++#if defined TIZEN_EXT
++      connman_network_set_bssid(network,
++                      g_supplicant_network_get_bssid(supplicant_network));
++      connman_network_set_maxrate(network,
++                      g_supplicant_network_get_maxrate(supplicant_network));
++      connman_network_set_enc_mode(network,
++                      g_supplicant_network_get_enc_mode(supplicant_network));
++#endif
+       connman_network_set_available(network, true);
+       connman_network_set_string(network, "WiFi.Mode", mode);
+@@ -2658,6 +2665,12 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
+       const char *name, *identifier;
+       struct connman_network *connman_network;
++#if defined TIZEN_EXT
++      const unsigned char *bssid;
++      unsigned int maxrate;
++      uint16_t frequency;
++#endif
++
+       interface = g_supplicant_network_get_interface(network);
+       wifi = g_supplicant_interface_get_data(interface);
+       identifier = g_supplicant_network_get_identifier(network);
+@@ -2677,6 +2690,16 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
+                                       calculate_strength(network));
+              connman_network_update(connman_network);
+       }
++
++#if defined TIZEN_EXT
++      bssid = g_supplicant_network_get_bssid(network);
++      maxrate = g_supplicant_network_get_maxrate(network);
++      frequency = g_supplicant_network_get_frequency(network);
++
++      connman_network_set_bssid(connman_network, bssid);
++      connman_network_set_maxrate(connman_network, maxrate);
++      connman_network_set_frequency(connman_network, frequency);
++#endif
+ }
+ static void apply_peer_services(GSupplicantPeer *peer,
+diff --git a/src/network.c b/src/network.c
+index b388995..c40a079 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -41,6 +41,11 @@
+  */
+ #define RS_REFRESH_TIMEOUT    3
++#if defined TIZEN_EXT
++#define WIFI_ENCYPTION_MODE_LEN_MAX 6
++#define WIFI_BSSID_LEN_MAX 6
++#endif
++
+ static GSList *network_list = NULL;
+ static GSList *driver_list = NULL;
+@@ -87,6 +92,11 @@ struct connman_network {
+               bool wps;
+               bool use_wps;
+               char *pin_wps;
++#if defined TIZEN_EXT
++              char encryption_mode[WIFI_ENCYPTION_MODE_LEN_MAX];
++              unsigned char bssid[WIFI_BSSID_LEN_MAX];
++              unsigned int maxrate;
++#endif
+       } wifi;
+ };
+@@ -1737,6 +1747,69 @@ int connman_network_set_ipaddress(struct connman_network *network,
+       return 0;
+ }
++#if defined TIZEN_EXT
++/*
++ * Description: Network client requires additional wifi specific info
++ */
++int connman_network_set_bssid(struct connman_network *network,
++                              const unsigned char *bssid)
++{
++      int i = 0;
++
++      if (bssid == NULL)
++              return -EINVAL;
++
++      DBG("network %p bssid %02x:%02x:%02x:%02x:%02x:%02x", network,
++                      bssid[0], bssid[1], bssid[2],
++                      bssid[3], bssid[4], bssid[5]);
++
++      for (;i < WIFI_BSSID_LEN_MAX;i++)
++              network->wifi.bssid[i] = bssid[i];
++
++      return 0;
++}
++
++unsigned char *connman_network_get_bssid(struct connman_network *network)
++{
++      return (unsigned char *)network->wifi.bssid;
++}
++
++int connman_network_set_maxrate(struct connman_network *network,
++                              unsigned int maxrate)
++{
++      DBG("network %p maxrate %d", network, maxrate);
++
++      network->wifi.maxrate = maxrate;
++
++      return 0;
++}
++
++unsigned int connman_network_get_maxrate(struct connman_network *network)
++{
++      return network->wifi.maxrate;
++}
++
++int connman_network_set_enc_mode(struct connman_network *network,
++                              const char *encryption_mode)
++{
++      if (encryption_mode == NULL)
++              return -EINVAL;
++
++      DBG("network %p encryption mode %s", network, encryption_mode);
++
++      g_strlcpy(network->wifi.encryption_mode, encryption_mode,
++                                      WIFI_ENCYPTION_MODE_LEN_MAX);
++
++      return 0;
++}
++
++const char *connman_network_get_enc_mode(struct connman_network *network)
++{
++      return (const char *)network->wifi.encryption_mode;
++}
++
++#endif
++
+ int connman_network_set_nameservers(struct connman_network *network,
+                               const char *nameservers)
+ {
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0010-Tizen-Append-extra-wifi-service-property.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0010-Tizen-Append-extra-wifi-service-property.patch
new file mode 100644 (file)
index 0000000..cb17315
--- /dev/null
@@ -0,0 +1,122 @@
+From d9c8d2e9c9b3d0b7c8c884e74b124895a627d148 Mon Sep 17 00:00:00 2001
+From: Arron Wang <arron.wang@intel.com>
+Date: Mon, 24 Sep 2012 14:42:02 +0800
+Subject: [PATCH 10/32] Tizen: Append extra wifi service property
+
+Append wifi property bssid, maxrate, frequency, encryptionmode to wifi
+service
+
+Change-Id: I1d5987334ab288fc04ff931fda5108f4afe864f0
+---
+ doc/service-api.txt | 26 ++++++++++++++++++++++++++
+ src/service.c       | 43 +++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 69 insertions(+)
+
+diff --git a/doc/service-api.txt b/doc/service-api.txt
+index c9dd7e2..74c8345 100644
+--- a/doc/service-api.txt
++++ b/doc/service-api.txt
+@@ -191,6 +191,32 @@ Properties        string State [readonly]
+                       This property might be only present for WiFi
+                       services.
++              string BSSID [readonly]
++
++                      If the service type is WiFi, then this property
++                      indicates the BSSID of the service.
++
++              uint32 MaxRate [readonly]
++
++                      If the service type is WiFi, then this property
++                      indicates the Maximum speed(bps) of the service.
++
++              uint16 Frequency [readonly]
++
++                      If the service type is WiFi, then this property
++                      indicates the frequency band(MHz) of the service.
++
++              string EncryptionMode [readonly]
++
++                      If the service type is WiFi, then this property
++                      indicates the key encryption mode.
++
++                      Possible values are "none", "wep", "tkip", "aes"
++                      and "mixed".
++
++                      This property might be only present for WiFi
++                      services.
++
+               uint8 Strength [readonly]
+                       Indicates the signal strength of the service. This
+diff --git a/src/service.c b/src/service.c
+index 87a2f2c..d3b219f 100644
+--- a/src/service.c
++++ b/src/service.c
+@@ -39,6 +39,10 @@
+ #define CONNECT_TIMEOUT               120
++#if defined TIZEN_EXT
++#define WIFI_BSSID_STR_LEN    18
++#endif
++
+ static DBusConnection *connection = NULL;
+ static GList *service_list = NULL;
+@@ -2252,6 +2256,37 @@ int __connman_service_iterate_services(service_iterate_cb cb, void *user_data)
+       return 0;
+ }
++#if defined TIZEN_EXT
++static void append_wifi_ext_info(DBusMessageIter *dict,
++                                      struct connman_network *network)
++{
++      char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
++      char *bssid_str = bssid_buff;
++      unsigned char *bssid;
++      unsigned int maxrate;
++      uint16_t frequency;
++      const char *enc_mode;
++
++      bssid = connman_network_get_bssid(network);
++      maxrate = connman_network_get_maxrate(network);
++      frequency = connman_network_get_frequency(network);
++      enc_mode = connman_network_get_enc_mode(network);
++
++      snprintf(bssid_str, WIFI_BSSID_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
++                              bssid[0], bssid[1], bssid[2],
++                              bssid[3], bssid[4], bssid[5]);
++
++      connman_dbus_dict_append_basic(dict, "BSSID",
++                                      DBUS_TYPE_STRING, &bssid_str);
++      connman_dbus_dict_append_basic(dict, "MaxRate",
++                                      DBUS_TYPE_UINT32, &maxrate);
++      connman_dbus_dict_append_basic(dict, "Frequency",
++                                      DBUS_TYPE_UINT16, &frequency);
++      connman_dbus_dict_append_basic(dict, "EncryptionMode",
++                                      DBUS_TYPE_STRING, &enc_mode);
++}
++#endif
++
+ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
+                                       struct connman_service *service)
+ {
+@@ -2317,6 +2352,14 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
+                                               append_ethernet, service);
+               break;
+       case CONNMAN_SERVICE_TYPE_WIFI:
++#if defined TIZEN_EXT
++              if (service->network != NULL)
++                      append_wifi_ext_info(dict, service->network);
++
++              connman_dbus_dict_append_dict(dict, "Ethernet",
++                                              append_ethernet, service);
++              break;
++#endif
+       case CONNMAN_SERVICE_TYPE_ETHERNET:
+       case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+       case CONNMAN_SERVICE_TYPE_GADGET:
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0011-Tizen-Export-network-proxy-API-for-telephony-plugin.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0011-Tizen-Export-network-proxy-API-for-telephony-plugin.patch
new file mode 100644 (file)
index 0000000..78bf825
--- /dev/null
@@ -0,0 +1,104 @@
+From 2bbc2b500806c808f54b459615ea4daddef1cf4e Mon Sep 17 00:00:00 2001
+From: Arron Wang <arron.wang@intel.com>
+Date: Tue, 9 Oct 2012 16:20:45 +0800
+Subject: [PATCH 11/32] Tizen: Export network proxy API for telephony plugin
+
+Telephony plug-in requires manual PROXY setting function
+Telephony stack provides proxy address (3G profile).
+
+Change-Id: Iaa02f59465a687961c303667ee09051b419507d2
+---
+ include/network.h |  3 +++
+ src/connman.h     |  4 ++++
+ src/network.c     | 18 ++++++++++++++++++
+ src/service.c     | 16 ++++++++++++++++
+ 4 files changed, 41 insertions(+)
+
+diff --git a/include/network.h b/include/network.h
+index 180f2a2..e433c22 100644
+--- a/include/network.h
++++ b/include/network.h
+@@ -131,6 +131,9 @@ unsigned int connman_network_get_maxrate(struct connman_network *network);
+ int connman_network_set_enc_mode(struct connman_network *network,
+                               const char *encryption_mode);
+ const char *connman_network_get_enc_mode(struct connman_network *network);
++
++int connman_network_set_proxy(struct connman_network *network,
++                               const char *proxies);
+ #endif
+ int connman_network_set_name(struct connman_network *network,
+diff --git a/src/connman.h b/src/connman.h
+index da01215..4d78eab 100644
+--- a/src/connman.h
++++ b/src/connman.h
+@@ -756,6 +756,10 @@ void __connman_service_timeserver_changed(struct connman_service *service,
+               GSList *ts_list);
+ void __connman_service_set_pac(struct connman_service *service,
+                                       const char *pac);
++#if defined TIZEN_EXT
++void __connman_service_set_proxy(struct connman_service *service,
++                                       const char *proxies);
++#endif
+ bool __connman_service_is_hidden(struct connman_service *service);
+ bool __connman_service_is_split_routing(struct connman_service *service);
+ bool __connman_service_index_is_split_routing(int index);
+diff --git a/src/network.c b/src/network.c
+index c40a079..8c9fdcb 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -1808,6 +1808,24 @@ const char *connman_network_get_enc_mode(struct connman_network *network)
+       return (const char *)network->wifi.encryption_mode;
+ }
++int connman_network_set_proxy(struct connman_network *network,
++                              const char *proxies)
++{
++      struct connman_service *service;
++
++      DBG("network %p proxies %s", network, proxies);
++
++      service = connman_service_lookup_from_network(network);
++      if (service == NULL)
++              return -EINVAL;
++
++      __connman_service_set_proxy(service, proxies);
++
++      connman_service_set_proxy_method(service,
++                              CONNMAN_SERVICE_PROXY_METHOD_MANUAL);
++
++      return 0;
++}
+ #endif
+ int connman_network_set_nameservers(struct connman_network *network,
+diff --git a/src/service.c b/src/service.c
+index d3b219f..8d3c619 100644
+--- a/src/service.c
++++ b/src/service.c
+@@ -2806,6 +2806,22 @@ void __connman_service_set_pac(struct connman_service *service,
+       proxy_changed(service);
+ }
++#if defined TIZEN_EXT
++void __connman_service_set_proxy(struct connman_service *service,
++                                       const char *proxies)
++{
++       char **proxies_array = NULL;
++
++       g_strfreev(service->proxies);
++       service->proxies = NULL;
++
++       if (proxies != NULL)
++               proxies_array = g_strsplit(proxies, " ", 0);
++
++       service->proxies = proxies_array;
++}
++#endif
++
+ void __connman_service_set_identity(struct connman_service *service,
+                                       const char *identity)
+ {
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0012-Tizen-Integrate-telephony-plugin.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0012-Tizen-Integrate-telephony-plugin.patch
new file mode 100644 (file)
index 0000000..88613f2
--- /dev/null
@@ -0,0 +1,1833 @@
+From f5af9712213cb0da9e5066e0a2fcf8fbedccc075 Mon Sep 17 00:00:00 2001
+From: Arron Wang <arron.wang@intel.com>
+Date: Wed, 10 Oct 2012 09:56:13 +0800
+Subject: [PATCH 12/32] Tizen: Integrate telephony plugin
+
+Change-Id: Ia178f5de981501296573bf3f48e329d5a1355af6
+---
+ Makefile.plugins       |   12 +
+ configure.ac           |    6 +
+ packaging/connman.spec |    2 +
+ plugins/telephony.c    | 1757 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 1777 insertions(+)
+ create mode 100644 plugins/telephony.c
+
+diff --git a/Makefile.plugins b/Makefile.plugins
+index e90ad19..83ad8fb 100644
+--- a/Makefile.plugins
++++ b/Makefile.plugins
+@@ -55,6 +55,18 @@ builtin_modules += dundee
+ builtin_sources += plugins/dundee.c
+ endif
++if TELEPHONY
++if TELEPHONY_BUILTIN
++builtin_modules += telephony
++builtin_sources += plugins/telephony.c
++else
++plugin_LTLIBRARIES += plugins/telephony.la
++plugin_objects += $(plugins_telephony_la_OBJECTS)
++plugins_telephony_la_CFLAGS = $(plugin_cflags)
++plugins_telephony_la_LDFLAGS = $(plugin_ldflags)
++endif
++endif
++
+ if VPN
+ builtin_modules += vpn
+ builtin_sources += plugins/vpn.c
+diff --git a/configure.ac b/configure.ac
+index 6f35c78..dee2dcb 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -61,6 +61,12 @@ AC_ARG_ENABLE(hh2serial-gps,
+ AM_CONDITIONAL(HH2SERIAL_GPS, test "${enable_hh2serial_gps}" != "no")
+ AM_CONDITIONAL(HH2SERIAL_GPS_BUILTIN, test "${enable_hh2serial_gps}" = "builtin")
++AC_ARG_ENABLE(telephony,
++      AC_HELP_STRING([--enable-telephony], [enable Telephony support]),
++                      [enable_telephony=${enableval}], [enable_telephony="yes"])
++AM_CONDITIONAL(TELEPHONY, test "${enable_telephony}" != "no")
++AM_CONDITIONAL(TELEPHONY_BUILTIN, test "${enable_telephony}" = "builtin")
++
+ AC_ARG_WITH(openconnect, AC_HELP_STRING([--with-openconnect=PROGRAM],
+         [specify location of openconnect binary]), [path_openconnect=${withval}])
+diff --git a/packaging/connman.spec b/packaging/connman.spec
+index edc1d53..f4faf92 100644
+--- a/packaging/connman.spec
++++ b/packaging/connman.spec
+@@ -152,6 +152,8 @@ systemctl daemon-reload
+ %manifest %{name}.manifest
+ %license COPYING
+ %{_sbindir}/*
++%{_libdir}/connman/plugins/*.so
++%{_datadir}/man/*
+ %config %{_sysconfdir}/connman/main.conf
+ %config %{_sysconfdir}/dbus-1/system.d/*
+ %{_unitdir}/connman.service
+diff --git a/plugins/telephony.c b/plugins/telephony.c
+new file mode 100644
+index 0000000..63e7f6e
+--- /dev/null
++++ b/plugins/telephony.c
+@@ -0,0 +1,1757 @@
++/*
++ *
++ *  Connection Manager
++ *
++ *  Copyright (C) 2011-2013  Samsung Electronics Co., Ltd. All rights reserved.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the 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 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 HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <errno.h>
++#include <stdlib.h>
++
++#include <gdbus.h>
++#include <string.h>
++
++#define CONNMAN_API_SUBJECT_TO_CHANGE
++#include <connman/plugin.h>
++#include <connman/device.h>
++#include <connman/network.h>
++#include <connman/ipconfig.h>
++#include <connman/dbus.h>
++#include <connman/inet.h>
++#include <connman/technology.h>
++#include <connman/log.h>
++
++#define PS_DBUS_SERVICE                               "com.tcore.ps"
++
++#define PS_MASTER_INTERFACE           PS_DBUS_SERVICE ".master"
++#define PS_MODEM_INTERFACE            PS_DBUS_SERVICE ".modem"
++#define PS_SERVICE_INTERFACE          PS_DBUS_SERVICE ".service"
++#define PS_CONTEXT_INTERFACE          PS_DBUS_SERVICE ".context"
++
++/* methods */
++#define GET_MODEMS                    "GetModems"
++#define GET_SERVICES                  "GetServices"
++#define GET_CONTEXTS                  "GetContexts"
++#define ACTIVATE_CONTEXT              "Activate"
++#define DEACTIVATE_CONTEXT            "Deactivate"
++#define GET_PROPERTIES                        "GetProperties"
++#define SET_PROPERTY                  "SetProperties"
++
++/* signals */
++#define MODEM_ADDED                   "ModemAdded"
++#define MODEM_REMOVED                 "ModemRemoved"
++#define SERVICE_ADDED                 "ServiceAdded"
++#define SERVICE_REMOVED                       "ServiceRemoved"
++#define CONTEXT_ADDED                 "ContextAdded"
++#define CONTEXT_REMOVED                       "ContextRemoved"
++#define PROPERTY_CHANGED              "PropertyChanged"
++
++#define TIMEOUT 40000
++
++#define STRING2BOOL(a)        ((g_str_equal(a, "TRUE")) ?  (TRUE):(FALSE))
++
++static DBusConnection *connection;
++static GHashTable     *modem_hash;
++static GHashTable     *service_hash;
++static GHashTable     *network_hash;
++
++struct telephony_service {
++      char *path;
++
++      gpointer p_modem;
++      char *act;
++      gboolean roaming; /* global roaming state */
++      gboolean ps_attached; /* packet service is available */
++};
++
++struct telephony_modem {
++      char *path;
++
++      char *operator;
++      gboolean powered;
++      gboolean sim_init;
++      gboolean flight_mode;
++      gboolean data_allowed;
++      gboolean roaming_allowed;
++
++      struct connman_device *device;
++      struct telephony_service *s_service;
++};
++
++struct telephony_network {
++      char *path;
++      struct connman_network *network;
++
++      enum connman_ipconfig_method ipv4_method;
++      struct connman_ipaddress *ipv4_address;
++
++      enum connman_ipconfig_method ipv6_method;
++      struct connman_ipaddress *ipv6_address;
++};
++
++/* function prototype */
++static void telephony_connect(DBusConnection *connection, void *user_data);
++static void telephony_disconnect(DBusConnection *connection, void *user_data);
++static void __remove_modem(gpointer data);
++static void __remove_service(gpointer data);
++static void __remove_network(gpointer data);
++
++static int __modem_probe(struct connman_device *device);
++static void __modem_remove(struct connman_device *device);
++static int __modem_enable(struct connman_device *device);
++static int __modem_disable(struct connman_device *device);
++
++static int __network_probe(struct connman_network *network);
++static void __network_remove(struct connman_network *network);
++static int __network_connect(struct connman_network *network);
++static int __network_disconnect(struct connman_network *network);
++
++
++/* dbus request and reply */
++static int __dbus_request(const char *path, const char *interface,
++                      const char *method,
++                      DBusPendingCallNotifyFunction notify, void *user_data,
++                      DBusFreeFunction free_function, int type, ...);
++
++static int __request_get_modems(void);
++static void __response_get_modems(DBusPendingCall *call, void *user_data);
++static int __request_get_services(const char *path);
++static void __response_get_services(DBusPendingCall *call, void *user_data);
++static int __request_get_contexts(struct telephony_modem *modem);
++static void __response_get_contexts(DBusPendingCall *call, void *user_data);
++static int __request_network_activate(struct connman_network *network);
++static void __response_network_activate(DBusPendingCall *call, void *user_data);
++static int __request_network_deactivate(struct connman_network *network);
++
++/* telephony internal function */
++static void __add_modem(const char *path, DBusMessageIter *prop);
++static void __add_service(struct telephony_modem *modem,
++                      const char *service_path, DBusMessageIter *prop);
++static void __add_connman_device(const char *modem_path, const char *operator);
++static void __remove_connman_device(struct telephony_modem *modem);
++static void __remove_connman_networks(struct connman_device *device);
++static void __set_device_powered(struct telephony_modem *modem,
++                                      gboolean powered);
++static int __check_device_powered(const char *path, gboolean online);
++static gboolean __check_network_available(struct connman_network *network);
++static void __create_service(struct connman_network *network);
++static int __add_context(struct connman_device *device, const char *path,
++                                                      DBusMessageIter *prop);
++static gboolean __set_network_ipconfig(struct telephony_network *network,
++                                                      DBusMessageIter *dict);
++static void __set_network_connected(struct telephony_network *network,
++                                                      gboolean connected);
++static char *__get_ident(const char *path);
++
++/* signal handler */
++static gboolean __changed_modem(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++static gboolean __added_modem(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++static gboolean __removed_modem(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++static gboolean __changed_service(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++static gboolean __added_service(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++static gboolean __removed_service(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++static gboolean __changed_context(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++static gboolean __added_context(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++static gboolean __removed_context(DBusConnection *connection,
++                              DBusMessage *message, void *user_data);
++
++/* device driver */
++static struct connman_device_driver modem_driver = {
++      .name           = "device",
++      .type           = CONNMAN_DEVICE_TYPE_CELLULAR,
++      .probe          = __modem_probe,
++      .remove         = __modem_remove,
++      .enable         = __modem_enable,
++      .disable        = __modem_disable,
++};
++
++/* network driver */
++static struct connman_network_driver network_driver = {
++      .name           = "network",
++      .type           = CONNMAN_NETWORK_TYPE_CELLULAR,
++      .probe          = __network_probe,
++      .remove         = __network_remove,
++      .connect        = __network_connect,
++      .disconnect     = __network_disconnect,
++};
++
++static int tech_probe(struct connman_technology *technology)
++{
++      return 0;
++}
++
++static void tech_remove(struct connman_technology *technology)
++{
++}
++
++static struct connman_technology_driver tech_driver = {
++      .name           = "cellular",
++      .type           = CONNMAN_SERVICE_TYPE_CELLULAR,
++      .probe          = tech_probe,
++      .remove         = tech_remove,
++};
++
++/* local function */
++static void telephony_connect(DBusConnection *connection, void *user_data)
++{
++      DBG("connection %p", connection);
++      modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
++                                              g_free, __remove_modem);
++      service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
++                                              g_free, __remove_service);
++      network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
++                                              g_free, __remove_network);
++      __request_get_modems();
++      return;
++}
++
++static void telephony_disconnect(DBusConnection *connection, void *user_data)
++{
++      DBG("connection %p", connection);
++
++      if (modem_hash != NULL) {
++              g_hash_table_destroy(modem_hash);
++              modem_hash = NULL;
++      }
++
++      if (network_hash != NULL) {
++              g_hash_table_destroy(network_hash);
++              network_hash = NULL;
++      }
++
++      return;
++}
++
++static void __remove_modem(gpointer data)
++{
++      struct telephony_modem *modem = data;
++
++      __remove_connman_device(modem);
++
++      g_free(modem->path);
++      g_free(modem->operator);
++      g_free(modem);
++}
++
++static void __remove_service(gpointer data)
++{
++      struct telephony_service *service = data;
++
++      g_free(service->path);
++      g_free(service->act);
++      g_free(service);
++}
++
++static void __remove_network(gpointer data)
++{
++      struct telephony_network *info = data;
++      struct connman_device *device;
++
++      device = connman_network_get_device(info->network);
++      if (device != NULL)
++              connman_device_remove_network(device, info->network);
++
++      connman_network_unref(info->network);
++
++      g_free(info->path);
++      connman_ipaddress_free(info->ipv4_address);
++      connman_ipaddress_free(info->ipv6_address);
++      g_free(info);
++}
++
++static int __modem_probe(struct connman_device *device)
++{
++      DBG("device %p", device);
++      return 0;
++}
++
++static void __modem_remove(struct connman_device *device)
++{
++      DBG("device %p", device);
++}
++
++static int __modem_enable(struct connman_device *device)
++{
++      const char *path = connman_device_get_string(device, "Path");
++      DBG("device %p, path, %s", device, path);
++
++      return __check_device_powered(path, TRUE);
++}
++
++static int __modem_disable(struct connman_device *device)
++{
++      const char *path = connman_device_get_string(device, "Path");
++      DBG("device %p, path, %s", device, path);
++
++      return __check_device_powered(path, FALSE);
++}
++
++static int __network_probe(struct connman_network *network)
++{
++      DBG("network_prove network(%p)", network);
++      return 0;
++}
++
++static int __network_connect(struct connman_network *network)
++{
++      struct connman_device *device;
++      struct telephony_modem *modem;
++
++      DBG("network %p", network);
++
++      device = connman_network_get_device(network);
++      if (device == NULL)
++              return -ENODEV;
++
++      modem = connman_device_get_data(device);
++      if (modem == NULL)
++              return -ENODEV;
++
++      if (modem->powered == FALSE)
++              return -ENOLINK;
++
++      return __request_network_activate(network);
++}
++
++static int __network_disconnect(struct connman_network *network)
++{
++      DBG("network %p", network);
++
++      if (connman_network_get_index(network) < 0)
++              return -ENOTCONN;
++
++      connman_network_set_associating(network, FALSE);
++
++      return __request_network_deactivate(network);
++}
++
++static void __network_remove(struct connman_network *network)
++{
++      char const *path = connman_network_get_string(network, "Path");
++      DBG("network %p path %s", network, path);
++
++      g_hash_table_remove(network_hash, path);
++      return;
++}
++
++static int __dbus_request(const char *path, const char *interface,
++                      const char *method,
++                      DBusPendingCallNotifyFunction notify, void *user_data,
++                      DBusFreeFunction free_function, int type, ...)
++{
++      DBusMessage *message;
++      DBusPendingCall *call;
++      dbus_bool_t ok;
++      va_list va;
++
++      DBG("Telephony request path %s %s.%s", path, interface, method);
++
++      if (path == NULL)
++              return -EINVAL;
++
++      message = dbus_message_new_method_call(PS_DBUS_SERVICE, path,
++                                              interface, method);
++      if (message == NULL)
++              return -ENOMEM;
++
++      dbus_message_set_auto_start(message, FALSE);
++
++      va_start(va, type);
++      ok = dbus_message_append_args_valist(message, type, va);
++      va_end(va);
++
++      if (!ok)
++              return -ENOMEM;
++
++      if (dbus_connection_send_with_reply(connection, message,
++                                              &call, TIMEOUT) == FALSE) {
++              connman_error("Failed to call %s.%s", interface, method);
++              dbus_message_unref(message);
++              return -EINVAL;
++      }
++
++      if (call == NULL) {
++              connman_error("D-Bus connection not available");
++              dbus_message_unref(message);
++              return -EINVAL;
++      }
++
++      dbus_pending_call_set_notify(call, notify, user_data, free_function);
++
++      dbus_message_unref(message);
++
++      return -EINPROGRESS;
++}
++
++static int __request_get_modems(void)
++{
++      DBG("request get modem");
++      /* call connect master */
++      return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS,
++                      __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
++}
++
++static void __response_get_modems(DBusPendingCall *call, void *user_data)
++{
++      DBusMessage *reply;
++      DBusError error;
++      DBusMessageIter args, dict;
++
++      DBG("");
++
++      reply = dbus_pending_call_steal_reply(call);
++
++      dbus_error_init(&error);
++
++      if (dbus_set_error_from_message(&error, reply)) {
++              connman_error("GetModems() %s %s", error.name, error.message);
++              dbus_error_free(&error);
++              goto done;
++      }
++
++      DBG("message signature (%s)", dbus_message_get_signature(reply));
++
++      if (dbus_message_iter_init(reply, &args) == FALSE)
++              goto done;
++
++      dbus_message_iter_recurse(&args, &dict);
++
++      while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry, property;
++              const char *modem_path;
++
++              dbus_message_iter_recurse(&dict, &entry);
++              dbus_message_iter_get_basic(&entry, &modem_path);
++              DBG("modem path (%s)", modem_path);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_recurse(&entry, &property);
++
++              __add_modem(modem_path, &property);
++
++              dbus_message_iter_next(&dict);
++      }
++
++done:
++      dbus_message_unref(reply);
++      dbus_pending_call_unref(call);
++      return;
++}
++
++static int __request_get_services(const char *path)
++{
++      DBG("request get service");
++      return __dbus_request(path, PS_MODEM_INTERFACE, GET_SERVICES,
++                              __response_get_services, g_strdup(path),
++                              g_free, DBUS_TYPE_INVALID);
++}
++
++static void __response_get_services(DBusPendingCall *call, void *user_data)
++{
++      DBusMessage *reply;
++      DBusError error;
++      DBusMessageIter args, dict;
++
++      const char *path = user_data;
++      struct telephony_modem *modem;
++
++      modem = g_hash_table_lookup(modem_hash, path);
++      if (modem == NULL)
++              return;
++      if (modem->device == NULL)
++              return;
++
++      DBG("");
++
++      reply = dbus_pending_call_steal_reply(call);
++
++      dbus_error_init(&error);
++
++      if (dbus_set_error_from_message(&error, reply)) {
++              connman_error("GetServices() %s %s", error.name, error.message);
++              dbus_error_free(&error);
++              goto done;
++      }
++
++      DBG("message signature (%s)", dbus_message_get_signature(reply));
++
++      if (dbus_message_iter_init(reply, &args) == FALSE)
++              goto done;
++
++      dbus_message_iter_recurse(&args, &dict);
++
++      while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry, property;
++              const char *service_path;
++
++              dbus_message_iter_recurse(&dict, &entry);
++              dbus_message_iter_get_basic(&entry, &service_path);
++              DBG("service path (%s)", service_path);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_recurse(&entry, &property);
++
++              __add_service(modem, service_path, &property);
++
++              dbus_message_iter_next(&dict);
++      }
++
++done:
++      dbus_message_unref(reply);
++      dbus_pending_call_unref(call);
++      return;
++}
++
++static int __request_get_contexts(struct telephony_modem *modem)
++{
++      DBG("request get contexts");
++      return __dbus_request(modem->s_service->path,
++                              PS_SERVICE_INTERFACE, GET_CONTEXTS,
++                              __response_get_contexts, g_strdup(modem->path),
++                              g_free, DBUS_TYPE_INVALID);
++}
++
++static void __response_get_contexts(DBusPendingCall *call, void *user_data)
++{
++      DBusError error;
++      DBusMessage *reply;
++      DBusMessageIter args, dict;
++
++      const char *path = user_data;
++      struct telephony_modem *modem;
++
++      DBG("");
++
++      modem = g_hash_table_lookup(modem_hash, path);
++      if (modem == NULL)
++              return;
++      if (modem->s_service == NULL)
++                      return;
++      if (modem->device == NULL)
++              return;
++
++      reply = dbus_pending_call_steal_reply(call);
++
++      dbus_error_init(&error);
++
++      if (dbus_set_error_from_message(&error, reply)) {
++              connman_error("GetContexts() %s %s", error.name, error.message);
++              dbus_error_free(&error);
++              goto done;
++      }
++
++      DBG("message signature (%s)", dbus_message_get_signature(reply));
++
++      if (dbus_message_iter_init(reply, &args) == FALSE)
++              goto done;
++
++      dbus_message_iter_recurse(&args, &dict);
++
++      while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry, property;
++              const char *context_path;
++
++              dbus_message_iter_recurse(&dict, &entry);
++              dbus_message_iter_get_basic(&entry, &context_path);
++              DBG("context path (%s)", context_path);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_recurse(&entry, &property);
++
++              __add_context(modem->device, context_path, &property);
++
++              dbus_message_iter_next(&dict);
++      }
++
++done:
++      dbus_message_unref(reply);
++      dbus_pending_call_unref(call);
++      return;
++}
++
++static int __request_network_activate(struct connman_network *network)
++{
++      DBG("request network activate");
++
++      const char *path = connman_network_get_string(network, "Path");
++      DBG("network %p, path %s", network, path);
++
++      return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
++                      __response_network_activate,
++                      g_strdup(path), NULL, DBUS_TYPE_INVALID);
++}
++
++static void __response_network_activate(DBusPendingCall *call, void *user_data)
++{
++      DBG("network activation response");
++
++      DBusError error;
++      DBusMessage *reply;
++
++      struct telephony_network *info;
++      const char *path = user_data;
++
++      info = g_hash_table_lookup(network_hash, path);
++      reply = dbus_pending_call_steal_reply(call);
++
++      if (info == NULL)
++              goto done;
++
++      if (!__check_network_available(info->network)) {
++              g_hash_table_remove(network_hash, path);
++              goto done;
++      }
++
++      dbus_error_init(&error);
++      if (dbus_set_error_from_message(&error, reply)) {
++              connman_error("connection activate() %s %s",
++                                      error.name, error.message);
++
++              if (connman_network_get_index(info->network) < 0)
++                      connman_network_set_error(info->network,
++                                      CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
++
++              dbus_error_free(&error);
++              goto done;
++      }
++
++done:
++      dbus_message_unref(reply);
++      dbus_pending_call_unref(call);
++      return;
++}
++
++static int __request_network_deactivate(struct connman_network *network)
++{
++      DBG("request network deactivate");
++
++      const char *path = connman_network_get_string(network, "Path");
++      DBG("network %p, path %s", network, path);
++
++      return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
++              NULL, NULL, NULL, DBUS_TYPE_INVALID);
++}
++
++static void __add_modem(const char *path, DBusMessageIter *prop)
++{
++      struct telephony_modem *modem;
++
++      modem = g_hash_table_lookup(modem_hash, path);
++      if (modem != NULL)
++              return;
++
++      modem = (struct telephony_modem *)malloc(
++                                      sizeof(struct telephony_modem));
++      memset(modem, 0, sizeof(struct telephony_modem));
++
++      modem->path = g_strdup(path);
++      modem->device = NULL;
++      modem->s_service = NULL;
++
++      g_hash_table_insert(modem_hash, g_strdup(path), modem);
++
++      while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry;
++              const char *key, *tmp;
++
++              dbus_message_iter_recurse(prop, &entry);
++              dbus_message_iter_get_basic(&entry, &key);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_get_basic(&entry, &tmp);
++
++              DBG("key (%s) value(%s)", key, tmp);
++
++              if (g_str_equal(key, "powered") == TRUE) {
++                      modem->powered = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "operator") == TRUE) {
++                      modem->operator = g_strdup(tmp);
++              } else if (g_str_equal(key, "sim_init") == TRUE) {
++                      modem->sim_init = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "flight_mode") == TRUE) {
++                      modem->flight_mode = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
++                      modem->roaming_allowed = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "data_allowed") == TRUE) {
++                      modem->data_allowed = STRING2BOOL(tmp);
++              }
++              dbus_message_iter_next(prop);
++      }
++
++      __add_connman_device(path, modem->operator);
++      __set_device_powered(modem, modem->powered);
++
++      if (modem->powered != TRUE) {
++              DBG("modem is not powered");
++              return;
++      }
++
++      __request_get_services(modem->path);
++
++      return;
++}
++
++static void __add_service(struct telephony_modem *modem,
++                              const char *service_path, DBusMessageIter *prop)
++{
++      struct telephony_service *service;
++
++      if (modem->s_service != NULL)
++              return;
++
++      service = (struct telephony_service *)g_try_malloc(
++                                      sizeof(struct telephony_service));
++      if (service == NULL)
++              return;
++
++      memset(service, 0, sizeof(struct telephony_service));
++
++      service->path = g_strdup(service_path);
++      service->p_modem = modem;
++      g_hash_table_insert(service_hash, g_strdup(service_path), service);
++
++      while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry;
++              const char *key, *tmp;
++
++              dbus_message_iter_recurse(prop, &entry);
++              dbus_message_iter_get_basic(&entry, &key);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_get_basic(&entry, &tmp);
++
++              DBG("key (%s) value(%s)", key, tmp);
++
++              if (g_str_equal(key, "roaming") == TRUE) {
++                      service->roaming = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "act") == TRUE) {
++                      service->act = g_strdup(tmp);
++              } else if (g_str_equal(key, "ps_attached") == TRUE) {
++                      service->ps_attached = STRING2BOOL(tmp);
++              }
++
++              dbus_message_iter_next(prop);
++      }
++
++      modem->s_service = service;
++      __request_get_contexts(modem);
++
++      return;
++}
++
++static void __add_connman_device(const char *modem_path, const char *operator)
++{
++      struct telephony_modem *modem;
++      struct connman_device *device;
++
++      DBG("path %s operator %s", modem_path, operator);
++
++      if (modem_path == NULL)
++              return;
++
++      if (operator == NULL)
++              return;
++
++      modem = g_hash_table_lookup(modem_hash, modem_path);
++      if (modem == NULL)
++              return;
++
++      if (modem->device) {
++              if (!g_strcmp0(operator,
++                              connman_device_get_ident(modem->device)))
++                      return;
++
++              __remove_connman_device(modem);
++      }
++
++      if (strlen(operator) == 0)
++              return;
++
++      device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR);
++      if (device == NULL)
++              return;
++
++      connman_device_set_ident(device, operator);
++      connman_device_set_string(device, "Path", modem_path);
++      connman_device_set_data(device, modem);
++
++      if (connman_device_register(device) < 0) {
++              connman_error("Failed to register cellular device");
++              connman_device_unref(device);
++              return;
++      }
++
++      modem->device = device;
++
++      return;
++}
++
++static void __remove_connman_device(struct telephony_modem *modem)
++{
++      DBG("modem %p path %s device %p", modem, modem->path, modem->device);
++
++      if (modem->device == NULL)
++              return;
++
++      __remove_connman_networks(modem->device);
++
++      connman_device_unregister(modem->device);
++      connman_device_unref(modem->device);
++
++      modem->device = NULL;
++
++      return;
++}
++
++static void __remove_connman_networks(struct connman_device *device)
++{
++      GHashTableIter iter;
++      gpointer key, value;
++      GSList *info_list = NULL;
++      GSList *list;
++
++      if (network_hash == NULL)
++              return;
++
++      g_hash_table_iter_init(&iter, network_hash);
++
++      while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
++              struct telephony_network *info = value;
++
++              if (connman_network_get_device(info->network) != device)
++                      continue;
++
++              info_list = g_slist_append(info_list, info);
++      }
++
++      for (list = info_list; list != NULL; list = list->next) {
++              struct telephony_network *info = list->data;
++              connman_device_remove_network(device, info->network);
++      }
++
++      g_slist_free(info_list);
++}
++
++static void __set_device_powered(struct telephony_modem *modem,
++                                      gboolean powered)
++{
++      DBG("set modem(%s) powered(%d)", modem->path, powered);
++
++      if (modem->device)
++              connman_device_set_powered(modem->device, powered);
++
++      return;
++}
++
++static int __check_device_powered(const char *path, gboolean powered)
++{
++      struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
++
++      if (modem == NULL)
++              return -ENODEV;
++
++      DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
++
++      if (modem->powered == powered)
++              return -EALREADY;
++
++      return 0;
++}
++
++static gboolean __check_network_available(struct connman_network *network)
++{
++      if (network == NULL || connman_network_get_device(network) == NULL) {
++              DBG("Modem or network was removed");
++              return FALSE;
++      }
++
++      return TRUE;
++}
++
++static int __add_context(struct connman_device *device, const char *path,
++                              DBusMessageIter *prop)
++{
++      char *ident;
++      gboolean active = FALSE;
++
++      struct telephony_modem *modem = connman_device_get_data(device);
++      struct connman_network *network;
++      struct telephony_network *info;
++
++      DBG("modem %p device %p path %s", modem, device, path);
++
++      ident = __get_ident(path);
++
++      network = connman_device_get_network(device, ident);
++      if (network != NULL)
++              return -EALREADY;
++
++      info = g_hash_table_lookup(network_hash, path);
++      if (info != NULL) {
++              DBG("path %p already exists with device %p", path,
++                      connman_network_get_device(info->network));
++
++              if (connman_network_get_device(info->network))
++                      return -EALREADY;
++
++              g_hash_table_remove(network_hash, path);
++      }
++
++      network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
++      if (network == NULL)
++              return -ENOMEM;
++
++      info = (struct telephony_network *)g_try_malloc(
++                                      sizeof(struct telephony_network));
++      if (info == NULL) {
++              connman_network_unref(network);
++              return -ENOMEM;
++      }
++
++      memset(info, 0, sizeof(struct telephony_network));
++
++      info->path = g_strdup(path);
++
++      connman_ipaddress_clear(info->ipv4_address);
++      connman_ipaddress_clear(info->ipv6_address);
++      info->network = network;
++
++      connman_network_set_string(network, "Path", path);
++      connman_network_set_name(network, path);
++
++      __create_service(network);
++
++      g_hash_table_insert(network_hash, g_strdup(path), info);
++
++      connman_network_set_available(network, TRUE);
++      connman_network_set_index(network, -1);
++      connman_network_set_bool(network, "Roaming", modem->s_service->roaming);
++
++      if (connman_device_add_network(device, network) != 0) {
++              g_hash_table_remove(network_hash, path);
++              return -EIO;
++      }
++
++      active = __set_network_ipconfig(info, prop);
++
++      if (active && (connman_network_get_connecting(network) ||
++                              connman_network_get_associating(network)))
++              __set_network_connected(info, active);
++
++      return 0;
++}
++
++static void __create_service(struct connman_network *network)
++{
++      const char *path;
++      char *group;
++
++      DBG("");
++
++      path = connman_network_get_string(network, "Path");
++
++      group = __get_ident(path);
++
++      connman_network_set_group(network, group);
++}
++
++static gboolean __set_network_ipconfig(struct telephony_network *network,
++                                      DBusMessageIter *dict)
++{
++      DBG("set network info");
++
++      gboolean active = FALSE;
++      char *dev_name = NULL, *proxy_addr = NULL;
++      char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
++                                      *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
++      char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
++                                      *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
++      int index;
++      int dns_flag = 0;
++
++      while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry;
++              const char *key, *tmp;
++
++              dbus_message_iter_recurse(dict, &entry);
++              dbus_message_iter_get_basic(&entry, &key);
++
++              dbus_message_iter_next(&entry);
++
++              DBG("key (%s)", key);
++
++              if (g_str_equal(key, "dev_name") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &dev_name);
++                      DBG("dev_name (%s)", dev_name);
++              } else if (g_str_equal(key, "proxy") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &proxy_addr);
++              } else if (g_str_equal(key, "ipv4_address") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv4_addr);
++                      DBG("ipv4 address (%s)", ipv4_addr);
++              } else if (g_str_equal(key, "ipv4_gateway") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv4_gw);
++              } else if (g_str_equal(key, "ipv4_netmask") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv4_netmask);
++              } else if (g_str_equal(key, "ipv4_dns1") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv4_dns1);
++              } else if (g_str_equal(key, "ipv4_dns2") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv4_dns2);
++              } else if (g_str_equal(key, "ipv6_address") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv6_addr);
++                      DBG("ipv6 address (%s)", ipv6_addr);
++              } else if (g_str_equal(key, "ipv6_gateway") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv6_gw);
++              } else if (g_str_equal(key, "ipv6_netmask") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv6_netmask);
++              } else if (g_str_equal(key, "ipv6_dns1") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv6_dns1);
++              } else if (g_str_equal(key, "ipv6_dns2") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &ipv6_dns2);
++              } else if (g_str_equal(key, "active") == TRUE) {
++                      dbus_message_iter_get_basic(&entry, &tmp);
++                      DBG("active (%s)", tmp);
++                      active = STRING2BOOL(tmp);
++              }
++
++              dbus_message_iter_next(dict);
++      }
++
++      /* interface index set */
++      if (dev_name == NULL)
++              dev_name = "";
++
++      if (!g_str_equal(dev_name, "")) {
++              index = connman_inet_ifindex(dev_name);
++              DBG("interface %s, index %d", dev_name, index);
++              connman_network_set_index(network->network, index);
++      }
++
++      /* proxy set */
++      if (proxy_addr == NULL)
++              proxy_addr = "";
++
++      DBG("proxy (%s) is set", proxy_addr);
++      connman_network_set_proxy(network->network, proxy_addr);
++
++      /* ipv4 set */
++      if (ipv4_addr == NULL)
++              ipv4_addr = "0.0.0.0";
++
++      if (g_str_equal(ipv4_addr, "0.0.0.0")) {
++              network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
++      } else {
++              network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
++              network->ipv4_address =
++                      connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
++              if (network->ipv4_address == NULL)
++                      return FALSE;
++
++              connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
++                                              ipv4_netmask, ipv4_gw);
++
++              if (ipv4_dns1 == NULL)
++                      ipv4_dns1 = "0.0.0.0";
++              if (ipv4_dns2 == NULL)
++                      ipv4_dns2 = "0.0.0.0";
++
++              if (g_str_equal(ipv4_dns1, "0.0.0.0"))
++                      dns_flag += 1;
++
++              if (g_str_equal(ipv4_dns2, "0.0.0.0"))
++                      dns_flag += 2;
++
++              gchar *nameservers = NULL;
++
++              switch (dns_flag) {
++              case 0:
++                      nameservers = g_strdup_printf("%s %s", ipv4_dns1,
++                                                              ipv4_dns2);
++                      break;
++              case 1:
++                      nameservers = g_strdup_printf("%s", ipv4_dns2);
++                      break;
++              case 2:
++                      nameservers = g_strdup_printf("%s", ipv4_dns1);
++              }
++
++              connman_network_set_nameservers(network->network, nameservers);
++              g_free(nameservers);
++      }
++
++      /* ipv6 set */
++      if (ipv6_addr == NULL)
++              ipv6_addr = "::";
++
++      if (g_str_equal(ipv6_addr, "::")) {
++              network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
++      } else {
++              network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
++              unsigned char prefix_length = 64;
++              network->ipv6_address =
++                      connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
++              if (network->ipv6_address == NULL)
++                      return FALSE;
++
++              connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
++                                              prefix_length, ipv6_gw);
++
++              dns_flag = 0;
++
++              if (ipv6_dns1 == NULL)
++                      ipv6_dns1 = "::";
++              if (ipv6_dns2 == NULL)
++                      ipv6_dns2 = "::";
++
++              if (g_str_equal(ipv6_dns1, "::"))
++                      dns_flag += 1;
++
++              if (g_str_equal(ipv6_dns2, "::"))
++                      dns_flag += 2;
++
++              gchar *nameservers = NULL;
++
++              switch (dns_flag) {
++              case 0:
++                      nameservers = g_strdup_printf("%s %s", ipv6_dns1,
++                                                              ipv6_dns2);
++                      break;
++              case 1:
++                      nameservers = g_strdup_printf("%s", ipv6_dns2);
++                      break;
++              case 2:
++                      nameservers = g_strdup_printf("%s", ipv6_dns1);
++              }
++
++              connman_network_set_nameservers(network->network, nameservers);
++              g_free(nameservers);
++      }
++
++      if (active)
++              connman_network_set_associating(network->network, TRUE);
++
++      return active;
++}
++
++static void __set_network_connected(struct telephony_network *network,
++                                      gboolean connected)
++{
++      gboolean setip = FALSE;
++
++      DBG("network %p connected %d", network, connected);
++
++      switch (network->ipv4_method) {
++      case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
++      case CONNMAN_IPCONFIG_METHOD_OFF:
++      case CONNMAN_IPCONFIG_METHOD_MANUAL:
++      case CONNMAN_IPCONFIG_METHOD_AUTO:
++              setip = TRUE;
++              break;
++
++      case CONNMAN_IPCONFIG_METHOD_FIXED:
++              connman_network_set_ipv4_method(network->network,
++                                                      network->ipv4_method);
++              connman_network_set_ipaddress(network->network,
++                                                      network->ipv4_address);
++              setip = TRUE;
++              break;
++
++      case CONNMAN_IPCONFIG_METHOD_DHCP:
++              connman_network_set_ipv4_method(network->network,
++                                                      network->ipv4_method);
++              setip = TRUE;
++              break;
++      }
++
++      switch (network->ipv6_method) {
++      case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
++      case CONNMAN_IPCONFIG_METHOD_OFF:
++      case CONNMAN_IPCONFIG_METHOD_MANUAL:
++      case CONNMAN_IPCONFIG_METHOD_DHCP:
++      case CONNMAN_IPCONFIG_METHOD_AUTO:
++              DBG("ipv6 not supported");
++              break;
++
++      case CONNMAN_IPCONFIG_METHOD_FIXED:
++              connman_network_set_ipv6_method(network->network,
++                                                      network->ipv6_method);
++              connman_network_set_ipaddress(network->network,
++                                                      network->ipv6_address);
++              setip = TRUE;
++              break;
++      }
++
++      if (setip == TRUE)
++              connman_network_set_connected(network->network, connected);
++
++      return;
++}
++
++static char *__get_ident(const char *path)
++{
++      char *pos;
++
++      if (*path != '/')
++              return NULL;
++
++      pos = strrchr(path, '/');
++      if (pos == NULL)
++              return NULL;
++
++      return pos + 1;
++}
++
++static gboolean __changed_modem(DBusConnection *connection,
++                              DBusMessage *message, void *user_data)
++{
++      DBG("modem changed signal");
++
++      DBusMessageIter args, dict;
++      const char *path = dbus_message_get_path(message);
++      struct telephony_modem *modem;
++
++      DBG("modem path %s", path);
++
++      modem = g_hash_table_lookup(modem_hash, path);
++      if (modem == NULL) {
++              DBG("modem object does not exists");
++              return TRUE;
++      }
++
++      DBG("message signature (%s)", dbus_message_get_signature(message));
++
++      if (dbus_message_iter_init(message, &args) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_recurse(&args, &dict);
++
++      while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry;
++              const char *key, *tmp;
++
++              dbus_message_iter_recurse(&dict, &entry);
++              dbus_message_iter_get_basic(&entry, &key);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_get_basic(&entry, &tmp);
++
++              DBG("key(%s), value(%s)", key, tmp);
++
++              if (g_str_equal(key, "powered") == TRUE) {
++                      modem->powered = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "operator") == TRUE) {
++                      modem->operator = g_strdup(tmp);
++              } else if (g_str_equal(key, "sim_init") == TRUE) {
++                      modem->sim_init = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "flight_mode") == TRUE) {
++                      modem->flight_mode = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
++                      modem->roaming_allowed = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "data_allowed") == TRUE) {
++                      modem->data_allowed = STRING2BOOL(tmp);
++              }
++
++              dbus_message_iter_next(&dict);
++      }
++
++      if (modem->device == NULL)
++              __add_connman_device(path, modem->operator);
++
++      __set_device_powered(modem, modem->powered);
++
++      if (modem->powered != TRUE) {
++              DBG("modem is not powered");
++              return TRUE;
++      }
++
++      if (!modem->s_service) {
++              __request_get_services(modem->path);
++              return TRUE;
++      }
++
++      if (modem->flight_mode || !modem->data_allowed) {
++              DBG("modem(%s) flight mode(%d) data allowed(%d)",
++                      modem->path, modem->flight_mode, modem->data_allowed);
++              return TRUE;
++      }
++
++      return TRUE;
++}
++
++static gboolean __added_modem(DBusConnection *connection,
++                              DBusMessage *message, void *user_data)
++{
++      DBG("modem added signal");
++
++      const char *modem_path = NULL;
++      DBusMessageIter args, dict, tmp;
++
++      DBG("message signature (%s)", dbus_message_get_signature(message));
++      if (dbus_message_iter_init(message, &args) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_recurse(&args, &dict);
++      memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
++
++      while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry;
++              const char *key, *value;
++
++              dbus_message_iter_recurse(&tmp, &entry);
++              dbus_message_iter_get_basic(&entry, &key);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_get_basic(&entry, &value);
++
++              DBG("key (%s) value(%s)", key, value);
++
++              if (g_str_equal(key, "path") == TRUE)
++                      modem_path = g_strdup(value);
++
++              dbus_message_iter_next(&tmp);
++      }
++
++      if (modem_path != NULL)
++              __add_modem(modem_path, &dict);
++
++      return TRUE;
++}
++
++static gboolean __removed_modem(DBusConnection *connection,
++                                      DBusMessage *message, void *user_data)
++{
++      DBG("modem removed signal");
++
++      DBusMessageIter iter;
++      const char *modem_path;
++
++      if (dbus_message_iter_init(message, &iter) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_get_basic(&iter, &modem_path);
++      g_hash_table_remove(modem_hash, modem_path);
++
++      return TRUE;
++}
++
++static gboolean __changed_service(DBusConnection *connection,
++                                      DBusMessage *message, void *user_data)
++{
++      DBG("service changed signal");
++
++      DBusMessageIter args, dict;
++      const char *service_path = dbus_message_get_path(message);
++      struct telephony_modem *modem;
++      struct telephony_service *s_service;
++      gboolean roaming_option = TRUE;
++
++      DBG("service path %s", service_path);
++
++      s_service = g_hash_table_lookup(service_hash, service_path);
++      if (s_service == NULL) {
++              DBG("service object does not exists");
++              return TRUE;
++      }
++
++      modem = s_service->p_modem;
++      if (modem == NULL) {
++              DBG("modem object does not exists");
++              return TRUE;
++      }
++
++      DBG("message signature (%s)", dbus_message_get_signature(message));
++
++      if (dbus_message_iter_init(message, &args) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_recurse(&args, &dict);
++
++      while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry;
++              const char *key, *tmp;
++
++              dbus_message_iter_recurse(&dict, &entry);
++              dbus_message_iter_get_basic(&entry, &key);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_get_basic(&entry, &tmp);
++
++              DBG("key(%s), value(%s)", key, tmp);
++
++              if (g_str_equal(key, "roaming") == TRUE) {
++                      s_service->roaming = STRING2BOOL(tmp);
++              } else if (g_str_equal(key, "act") == TRUE) {
++                      s_service->act = g_strdup(tmp);
++              } else if (g_str_equal(key, "ps_attached") == TRUE) {
++                      s_service->ps_attached = STRING2BOOL(tmp);
++              }
++
++              dbus_message_iter_next(&dict);
++      }
++
++      roaming_option &= (!s_service->roaming && !modem->roaming_allowed)
++                              || modem->roaming_allowed;
++
++      return TRUE;
++}
++
++
++static gboolean __added_service(DBusConnection *connection,
++                              DBusMessage *message, void *user_data)
++{
++      DBG("service added signal");
++
++      const char *path = dbus_message_get_path(message);
++      const char *service_path = NULL;
++      DBusMessageIter args, dict, tmp;
++      struct telephony_modem *modem;
++
++      modem = g_hash_table_lookup(modem_hash, path);
++      if (modem == NULL || modem->device == NULL)
++              return TRUE;
++
++      DBG("message signature (%s)", dbus_message_get_signature(message));
++      if (dbus_message_iter_init(message, &args) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_recurse(&args, &dict);
++      memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
++
++      while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry;
++              const char *key, *value;
++
++              dbus_message_iter_recurse(&tmp, &entry);
++              dbus_message_iter_get_basic(&entry, &key);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_get_basic(&entry, &value);
++
++              DBG("key (%s) value(%s)", key, value);
++
++              if (g_str_equal(key, "path") == TRUE) {
++                      service_path = g_strdup(value);
++              }
++
++              dbus_message_iter_next(&tmp);
++      }
++
++      if (service_path != NULL)
++              __add_service(modem, service_path, &dict);
++
++      return TRUE;
++}
++
++static gboolean __removed_service(DBusConnection *connection,
++                                      DBusMessage *message, void *user_data)
++{
++      DBG("service removed signal");
++
++      DBusMessageIter iter;
++      const char *service_path;
++
++      if (dbus_message_iter_init(message, &iter) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_get_basic(&iter, &service_path);
++      g_hash_table_remove(service_hash, service_path);
++
++      return TRUE;
++}
++
++static gboolean __changed_context(DBusConnection *connection,
++                                      DBusMessage *message, void *user_data)
++{
++      DBG("network changed signal");
++
++      gboolean active = FALSE;
++      const char *path = dbus_message_get_path(message);
++      struct telephony_network *info;
++      DBusMessageIter args, dict;
++
++      DBG("path %s", path);
++      info = g_hash_table_lookup(network_hash, path);
++      if (info == NULL)
++              return TRUE;
++
++      if (!__check_network_available(info->network)) {
++              g_hash_table_remove(network_hash, path);
++              return TRUE;
++      }
++
++      if (dbus_message_iter_init(message, &args) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_recurse(&args, &dict);
++
++      active = __set_network_ipconfig(info, &dict);
++
++      if (active == FALSE)
++              __set_network_connected(info, active);
++      else if ((connman_network_get_connecting(info->network) ||
++                      connman_network_get_associating(info->network)))
++              __set_network_connected(info, active);
++
++      return TRUE;
++}
++
++static gboolean __added_context(DBusConnection *connection,
++                                      DBusMessage *message, void *user_data)
++{
++      DBG("network added signal");
++
++      DBusMessageIter args, dict, tmp;
++      const char *path = dbus_message_get_path(message);
++      const char *network_path = NULL;
++      struct telephony_service *service = NULL;
++      struct telephony_modem *modem = NULL;
++
++      service = g_hash_table_lookup(service_hash, path);
++      if (service == NULL || service->p_modem == NULL)
++              return TRUE;
++
++      modem = service->p_modem;
++      if (modem == NULL || modem->device == NULL)
++              return TRUE;
++
++      DBG("message signature (%s)", dbus_message_get_signature(message));
++      if (dbus_message_iter_init(message, &args) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_recurse(&args, &dict);
++      memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
++
++      while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
++              DBusMessageIter entry;
++              const char *key, *value;
++
++              dbus_message_iter_recurse(&tmp, &entry);
++              dbus_message_iter_get_basic(&entry, &key);
++
++              dbus_message_iter_next(&entry);
++              dbus_message_iter_get_basic(&entry, &value);
++
++              DBG("key (%s) value(%s)", key, value);
++
++              if (g_str_equal(key, "path") == TRUE)
++                      network_path = g_strdup(value);
++
++              dbus_message_iter_next(&tmp);
++      }
++
++      if (network_path != NULL)
++              __add_context(modem->device, network_path, &dict);
++
++      return TRUE;
++}
++
++static gboolean __removed_context(DBusConnection *connection,
++                                      DBusMessage *message, void *user_data)
++{
++      DBG("network removed signal");
++
++      DBusMessageIter iter;
++      const char *path = dbus_message_get_path(message);
++      const char *network_path = NULL;
++      struct telephony_service *service = NULL;
++
++      service = g_hash_table_lookup(service_hash, path);
++      if (service == NULL || service->p_modem == NULL)
++              return TRUE;
++
++      if (dbus_message_iter_init(message, &iter) == FALSE) {
++              DBG("error to read message");
++              return TRUE;
++      }
++
++      dbus_message_iter_get_basic(&iter, &network_path);
++      g_hash_table_remove(network_hash, network_path);
++
++      return TRUE;
++}
++
++/* telephony initialization */
++static guint watch;
++static guint modem_watch;
++static guint modem_added_watch;
++static guint modem_removed_watch;
++static guint service_watch;
++static guint service_added_watch;
++static guint service_removed_watch;
++static guint context_watch;
++static guint context_added_watch;
++static guint context_removed_watch;
++
++static int telephony_init(void)
++{
++      DBG("telephony plugin");
++      int err;
++
++      connection = connman_dbus_get_connection();
++      if (connection == NULL)
++              return -EIO;
++
++      /* telephony watch */
++      watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE,
++                                      telephony_connect, telephony_disconnect,
++                                      NULL, NULL);
++
++      modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_MODEM_INTERFACE,
++                                              PROPERTY_CHANGED,
++                                              __changed_modem, NULL, NULL);
++
++      modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_MASTER_INTERFACE,
++                                              MODEM_ADDED, __added_modem,
++                                              NULL, NULL);
++
++      modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_MASTER_INTERFACE,
++                                              MODEM_REMOVED, __removed_modem,
++                                              NULL, NULL);
++
++      service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_SERVICE_INTERFACE,
++                                              PROPERTY_CHANGED,
++                                              __changed_service,
++                                              NULL, NULL);
++
++      service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_MODEM_INTERFACE,
++                                              SERVICE_ADDED, __added_service,
++                                              NULL, NULL);
++
++      service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_MODEM_INTERFACE,
++                                              SERVICE_REMOVED,
++                                              __removed_service,
++                                              NULL, NULL);
++
++      context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_CONTEXT_INTERFACE,
++                                              PROPERTY_CHANGED,
++                                              __changed_context,
++                                              NULL, NULL);
++
++      context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_SERVICE_INTERFACE,
++                                              CONTEXT_ADDED, __added_context,
++                                              NULL, NULL);
++
++      context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
++                                              PS_SERVICE_INTERFACE,
++                                              CONTEXT_REMOVED,
++                                              __removed_context,
++                                              NULL, NULL);
++
++      if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
++                      || modem_removed_watch == 0 || service_watch == 0
++                      || service_added_watch == 0 || context_watch == 0
++                      || service_removed_watch == 0
++                      || context_added_watch == 0
++                      || context_removed_watch == 0) {
++              err = -EIO;
++              goto remove;
++      }
++
++      err = connman_network_driver_register(&network_driver);
++      if (err < 0)
++              goto remove;
++
++      err = connman_device_driver_register(&modem_driver);
++      if (err < 0) {
++              connman_network_driver_unregister(&network_driver);
++              goto remove;
++      }
++
++      err = connman_technology_driver_register(&tech_driver);
++      if (err < 0) {
++              connman_device_driver_unregister(&modem_driver);
++              connman_network_driver_unregister(&network_driver);
++              goto remove;
++      }
++
++      return 0;
++
++remove:
++      g_dbus_remove_watch(connection, watch);
++      g_dbus_remove_watch(connection, modem_watch);
++      g_dbus_remove_watch(connection, modem_added_watch);
++      g_dbus_remove_watch(connection, modem_removed_watch);
++      g_dbus_remove_watch(connection, service_watch);
++      g_dbus_remove_watch(connection, service_added_watch);
++      g_dbus_remove_watch(connection, service_removed_watch);
++      g_dbus_remove_watch(connection, context_watch);
++      g_dbus_remove_watch(connection, context_added_watch);
++      g_dbus_remove_watch(connection, context_removed_watch);
++
++      dbus_connection_unref(connection);
++      return err;
++}
++
++static void telephony_exit(void)
++{
++      g_dbus_remove_watch(connection, watch);
++      g_dbus_remove_watch(connection, modem_watch);
++      g_dbus_remove_watch(connection, modem_added_watch);
++      g_dbus_remove_watch(connection, modem_removed_watch);
++      g_dbus_remove_watch(connection, service_watch);
++      g_dbus_remove_watch(connection, service_added_watch);
++      g_dbus_remove_watch(connection, service_removed_watch);
++      g_dbus_remove_watch(connection, context_watch);
++      g_dbus_remove_watch(connection, context_added_watch);
++      g_dbus_remove_watch(connection, context_removed_watch);
++
++      telephony_disconnect(connection, NULL);
++
++      connman_device_driver_unregister(&modem_driver);
++      connman_network_driver_unregister(&network_driver);
++
++      dbus_connection_unref(connection);
++}
++
++CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION,
++              CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit)
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0013-Tizen-Fix-wifi-enterprise-to-support-SIM-and-AKA.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0013-Tizen-Fix-wifi-enterprise-to-support-SIM-and-AKA.patch
new file mode 100644 (file)
index 0000000..17cf362
--- /dev/null
@@ -0,0 +1,96 @@
+From ede27f8e832d3ce5dc6bf2a8be78f34abddcc885 Mon Sep 17 00:00:00 2001
+From: Arron Wang <arron.wang@intel.com>
+Date: Fri, 12 Oct 2012 10:10:28 +0800
+Subject: [PATCH 13/32] Tizen: Fix wifi enterprise to support SIM and AKA
+
+Revise Wi-Fi enterprise to enable PEAP, TLS, TTLS
+Fix wifi enterprise to support SIM and AKA
+
+Change-Id: Ib9c10615fd0668b2ebca57eac9285bf8a3564427
+---
+ gsupplicant/supplicant.c | 20 ++++++++++++++++++++
+ src/service.c            | 13 ++++++++++++-
+ 2 files changed, 32 insertions(+), 1 deletion(-)
+
+diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
+index d2e4a64..58a8c9f 100644
+--- a/gsupplicant/supplicant.c
++++ b/gsupplicant/supplicant.c
+@@ -4392,14 +4392,27 @@ static void add_network_security_eap(DBusMessageIter *dict,
+ {
+       char *eap_value;
++#if defined TIZEN_EXT
++      if (!ssid->eap)
++#else
+       if (!ssid->eap || !ssid->identity)
++#endif
+               return;
+       if (g_strcmp0(ssid->eap, "tls") == 0) {
+               add_network_security_tls(dict, ssid);
+       } else if (g_strcmp0(ssid->eap, "peap") == 0 ||
+                               g_strcmp0(ssid->eap, "ttls") == 0) {
++#if defined TIZEN_EXT
++              if (!ssid->identity)
++                      return;
++#endif
+               add_network_security_peap(dict, ssid);
++
++#if defined TIZEN_EXT
++      } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
++                      g_strcmp0(ssid->eap, "aka") == 0) {
++#endif
+       } else
+               return;
+@@ -4408,9 +4421,16 @@ static void add_network_security_eap(DBusMessageIter *dict,
+       supplicant_dbus_dict_append_basic(dict, "eap",
+                                               DBUS_TYPE_STRING,
+                                               &eap_value);
++#if defined TIZEN_EXT
++      if (ssid->identity != NULL)
++              supplicant_dbus_dict_append_basic(dict, "identity",
++                                                      DBUS_TYPE_STRING,
++                                                      &ssid->identity);
++#else
+       supplicant_dbus_dict_append_basic(dict, "identity",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->identity);
++#endif
+       g_free(eap_value);
+ }
+diff --git a/src/service.c b/src/service.c
+index 8d3c619..99bb35d 100644
+--- a/src/service.c
++++ b/src/service.c
+@@ -5912,13 +5912,24 @@ static int service_connect(struct connman_service *service)
+                       if (!service->eap)
+                               return -EINVAL;
++#if defined TIZEN_EXT
++                      /*
++                       * never request credentials if using EAP-TLS, EAP-SIM
++                       * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks
++                       * need to be fully provisioned)
++                       */
++                      if (g_str_equal(service->eap, "tls") ||
++                              g_str_equal(service->eap, "sim") ||
++                              g_str_equal(service->eap, "aka"))
++                              break;
++#else
+                       /*
+                        * never request credentials if using EAP-TLS
+                        * (EAP-TLS networks need to be fully provisioned)
+                        */
+                       if (g_str_equal(service->eap, "tls"))
+                               break;
+-
++#endif
+                       /*
+                        * Return -ENOKEY if either identity or passphrase is
+                        * missing. Agent provided credentials can be used as
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0014-Tizen-Check-some-telephony-flags-before-active-conte.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0014-Tizen-Check-some-telephony-flags-before-active-conte.patch
new file mode 100644 (file)
index 0000000..c2349e1
--- /dev/null
@@ -0,0 +1,50 @@
+From 1eb2741818fb2d2ec09ab055c8e4d1df1f2fb481 Mon Sep 17 00:00:00 2001
+From: "guoqiang.liu" <guoqiang.liu@archermind.com>
+Date: Fri, 27 Dec 2013 14:22:52 +0800
+Subject: [PATCH 14/32] Tizen: Check some telephony flags before active context
+
+Telephony active maybe fail if data_allowed or ps_attached is false,
+so check it before actived.
+
+When data_allowed is false, if connman starts to auto connect 3G
+service, it will result in 3G service auto connected fail, which
+leads to it will not be auto connected next time.
+
+Change-Id: Ibdd9c34fee7a612c1788a364c69550c4f7e79123
+Signed-off-by: guoqiang.liu <guoqiang.liu@archermind.com>
+---
+ plugins/telephony.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/plugins/telephony.c b/plugins/telephony.c
+index 63e7f6e..ea0bf65 100644
+--- a/plugins/telephony.c
++++ b/plugins/telephony.c
+@@ -323,6 +323,7 @@ static int __network_connect(struct connman_network *network)
+ {
+       struct connman_device *device;
+       struct telephony_modem *modem;
++      struct telephony_service *service;
+       DBG("network %p", network);
+@@ -334,9 +335,16 @@ static int __network_connect(struct connman_network *network)
+       if (modem == NULL)
+               return -ENODEV;
++      service = modem->s_service;
++      if (service == NULL)
++              return -ENOLINK;
++
+       if (modem->powered == FALSE)
+               return -ENOLINK;
++      if (modem->data_allowed == FALSE || service->ps_attached == FALSE)
++              return -ENOLINK;
++
+       return __request_network_activate(network);
+ }
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0015-Tizen-Unify-bluetooth-tethering-enable-logic.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0015-Tizen-Unify-bluetooth-tethering-enable-logic.patch
new file mode 100644 (file)
index 0000000..069eaf7
--- /dev/null
@@ -0,0 +1,32 @@
+From ee0652fae6fc8615408e0937f3f61ebd28f9c42c Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Tue, 25 Mar 2014 14:16:52 +0800
+Subject: [PATCH 15/32] Tizen: Unify bluetooth tethering enable logic
+
+In bluez 4.x plugin, when bluetooth tethering is enabled,
+set_tethering() returns 0, while in bluez 5.x plugin,
+it returns -EINPROGRESS, which is not compatiable for
+ConnMan to handle both of them, this patch makes bluez
+5.x tethering enable logic consistent with bluez 4.x.
+
+Change-Id: I618efd32b5f123fe9bdb58d10adb29c67a87796f
+---
+ plugins/bluetooth.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
+index 82217d0..28df406 100644
+--- a/plugins/bluetooth.c
++++ b/plugins/bluetooth.c
+@@ -880,7 +880,7 @@ static int bluetooth_tech_set_tethering(struct connman_technology *technology,
+       if (i == 0)
+               return -ENODEV;
+-       return -EINPROGRESS;
++      return 0;
+ }
+ static struct connman_technology_driver tech_driver = {
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0016-Tethering-Add-handling-for-wpa_supplicant-authorized.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0016-Tethering-Add-handling-for-wpa_supplicant-authorized.patch
new file mode 100644 (file)
index 0000000..721b649
--- /dev/null
@@ -0,0 +1,99 @@
+From 763bd791fc3a52dc6381b18da246b7c0656861fd Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyi1.zhao@archermind.com>
+Date: Wed, 10 Jul 2013 15:37:50 +0800
+Subject: [PATCH 16/32] Tethering: Add handling for wpa_supplicant
+ authorized/deauthorized signals
+
+Change-Id: Iff022e257ee9d2c5227585bf0b84e726914cc62b
+---
+ gsupplicant/gsupplicant.h |  2 ++
+ gsupplicant/supplicant.c  | 53 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 55 insertions(+)
+
+diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
+index 27826dc..1fab1ba 100644
+--- a/gsupplicant/gsupplicant.h
++++ b/gsupplicant/gsupplicant.h
+@@ -359,6 +359,8 @@ struct _GSupplicantCallbacks {
+       void (*network_removed) (GSupplicantNetwork *network);
+       void (*network_changed) (GSupplicantNetwork *network,
+                                       const char *property);
++      void (*add_station) (const char *mac);
++      void (*remove_station) (const char *mac);
+       void (*peer_found) (GSupplicantPeer *peer);
+       void (*peer_lost) (GSupplicantPeer *peer);
+       void (*peer_changed) (GSupplicantPeer *peer,
+diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
+index 58a8c9f..5ff9b3d 100644
+--- a/gsupplicant/supplicant.c
++++ b/gsupplicant/supplicant.c
+@@ -2609,6 +2609,56 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter)
+       supplicant_dbus_property_foreach(iter, wps_event_args, interface);
+ }
++static void signal_station_connected(const char *path, DBusMessageIter *iter)
++{
++      GSupplicantInterface *interface;
++      const char *sta_mac = NULL;
++
++      SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
++
++      if (callbacks_pointer->add_station == NULL)
++              return;
++
++      if (g_strcmp0(path, "/") == 0)
++              return;
++
++      interface = g_hash_table_lookup(interface_table, path);
++      if (interface == NULL)
++              return;
++
++      dbus_message_iter_get_basic(iter, &sta_mac);
++      if (sta_mac == NULL)
++              return;
++
++      SUPPLICANT_DBG("New station %s connected", sta_mac);
++      callbacks_pointer->add_station(sta_mac);
++}
++
++static void signal_station_disconnected(const char *path, DBusMessageIter *iter)
++{
++      GSupplicantInterface *interface;
++      const char *sta_mac = NULL;
++
++      SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
++
++      if (callbacks_pointer->remove_station == NULL)
++              return;
++
++      if (g_strcmp0(path, "/") == 0)
++              return;
++
++      interface = g_hash_table_lookup(interface_table, path);
++      if (interface == NULL)
++              return;
++
++      dbus_message_iter_get_basic(iter, &sta_mac);
++      if (sta_mac == NULL)
++              return;
++
++      SUPPLICANT_DBG("Station %s disconnected", sta_mac);
++      callbacks_pointer->remove_station(sta_mac);
++}
++
+ static void create_peer_identifier(GSupplicantPeer *peer)
+ {
+       const unsigned char test[ETH_ALEN] = {};
+@@ -3171,6 +3221,9 @@ static struct {
+       { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
+       { SUPPLICANT_INTERFACE ".Interface.WPS", "Event",       signal_wps_event       },
++      { SUPPLICANT_INTERFACE".Interface", "StaAuthorized", signal_station_connected      },
++      { SUPPLICANT_INTERFACE".Interface", "StaDeauthorized", signal_station_disconnected },
++
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost",  signal_peer_lost  },
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0017-Tethering-Add-station-information-management-feature.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0017-Tethering-Add-station-information-management-feature.patch
new file mode 100644 (file)
index 0000000..1aa4482
--- /dev/null
@@ -0,0 +1,186 @@
+From c7d7214b511b0fa8b43f21b3b87416051fa9ef29 Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyi1.zhao@archermind.com>
+Date: Wed, 10 Jul 2013 17:54:32 +0800
+Subject: [PATCH 17/32] Tethering: Add station information management feature
+
+Change-Id: I2f699e42ec5ce7f148b8c1d685b52ee32e2e236b
+---
+ include/technology.h |  4 +++
+ plugins/wifi.c       | 13 ++++++++
+ src/tethering.c      | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 104 insertions(+)
+
+diff --git a/include/technology.h b/include/technology.h
+index d7fcdde..b13d4ec 100644
+--- a/include/technology.h
++++ b/include/technology.h
+@@ -36,6 +36,10 @@ extern "C" {
+ struct connman_technology;
++int connman_technology_tethering_add_station(enum connman_service_type type,
++                                            const char *mac);
++int connman_technology_tethering_remove_station(const char *mac);
++
+ void connman_technology_tethering_notify(struct connman_technology *technology,
+                                                       bool enabled);
+ int connman_technology_set_regdom(const char *alpha2);
+diff --git a/plugins/wifi.c b/plugins/wifi.c
+index 69a0e23..b5bc3ba 100644
+--- a/plugins/wifi.c
++++ b/plugins/wifi.c
+@@ -2719,6 +2719,17 @@ static void apply_peer_services(GSupplicantPeer *peer,
+       }
+ }
++static void add_station(const char *mac)
++{
++      connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
++                                               mac);
++}
++
++static void remove_station(const char *mac)
++{
++      connman_technology_tethering_remove_station(mac);
++}
++
+ static void peer_found(GSupplicantPeer *peer)
+ {
+       GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
+@@ -2887,6 +2898,8 @@ static const GSupplicantCallbacks callbacks = {
+       .network_added          = network_added,
+       .network_removed        = network_removed,
+       .network_changed        = network_changed,
++      .add_station            = add_station,
++      .remove_station         = remove_station,
+       .peer_found             = peer_found,
+       .peer_lost              = peer_lost,
+       .peer_changed           = peer_changed,
+diff --git a/src/tethering.c b/src/tethering.c
+index ceeec74..0cbf06c 100644
+--- a/src/tethering.c
++++ b/src/tethering.c
+@@ -52,6 +52,9 @@
+ #define DEFAULT_MTU   1500
++#define CONNMAN_STATION_STR_INFO_LEN          64
++#define CONNMAN_STATION_MAC_INFO_LEN          32
++
+ static char *private_network_primary_dns = NULL;
+ static char *private_network_secondary_dns = NULL;
+@@ -60,6 +63,7 @@ static GDHCPServer *tethering_dhcp_server = NULL;
+ static struct connman_ippool *dhcp_ippool = NULL;
+ static DBusConnection *connection;
+ static GHashTable *pn_hash;
++static GHashTable *sta_hash;
+ struct connman_private_network {
+       char *owner;
+@@ -76,6 +80,84 @@ struct connman_private_network {
+       char *secondary_dns;
+ };
++struct connman_station_info {
++      bool is_connected;
++      char *path;
++      char *type;
++      char ip[CONNMAN_STATION_STR_INFO_LEN];
++      char mac[CONNMAN_STATION_MAC_INFO_LEN];
++      char hostname[CONNMAN_STATION_STR_INFO_LEN];
++};
++
++static void destroy_station(gpointer key, gpointer value, gpointer user_data)
++{
++      struct connman_station_info *station_info;
++
++      __sync_synchronize();
++
++      station_info = value;
++
++      g_free(station_info->path);
++      g_free(station_info->type);
++      g_free(station_info);
++}
++
++int connman_technology_tethering_add_station(enum connman_service_type type,
++                                                      const char *mac)
++{
++      const char *str_type;
++      char *lower_mac;
++      char *path;
++      struct connman_station_info *station_info;
++
++      __sync_synchronize();
++
++      DBG("type %d", type);
++
++      str_type = __connman_service_type2string(type);
++      if (str_type == NULL)
++              return 0;
++
++      path = g_strdup_printf("%s/technology/%s", CONNMAN_PATH, str_type);
++
++      station_info = g_try_new0(struct connman_station_info, 1);
++      if (station_info == NULL)
++              return -ENOMEM;
++
++      lower_mac = g_ascii_strdown(mac, -1);
++
++      memcpy(station_info->mac, lower_mac, strlen(lower_mac) + 1);
++      station_info->path = path;
++      station_info->type = g_strdup(str_type);
++
++      g_hash_table_insert(sta_hash, station_info->mac, station_info);
++
++      g_free(lower_mac);
++      return 0;
++}
++
++int connman_technology_tethering_remove_station(const char *mac)
++{
++      char *lower_mac;
++      struct connman_station_info *info_found;
++
++      __sync_synchronize();
++
++      lower_mac = g_ascii_strdown(mac, -1);
++
++      info_found = g_hash_table_lookup(sta_hash, lower_mac);
++      if (info_found == NULL)
++              return -EACCES;
++
++      g_free(lower_mac);
++      g_hash_table_remove(sta_hash, info_found->mac);
++      g_free(info_found->path);
++      g_free(info_found->type);
++      g_free(info_found);
++
++      return 0;
++}
++
+ const char *__connman_tethering_get_bridge(void)
+ {
+       int sk, err;
+@@ -534,6 +616,9 @@ int __connman_tethering_init(void)
+       pn_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                               NULL, remove_private_network);
++      sta_hash = g_hash_table_new_full(g_str_hash,
++                                       g_str_equal, NULL, NULL);
++
+       return 0;
+ }
+@@ -554,5 +639,7 @@ void __connman_tethering_cleanup(void)
+               return;
+       g_hash_table_destroy(pn_hash);
++      g_hash_table_foreach(sta_hash, destroy_station, NULL);
++      g_hash_table_destroy(sta_hash);
+       dbus_connection_unref(connection);
+ }
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0018-Tethering-Add-interface-that-save-lease-in-DHCP-info.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0018-Tethering-Add-interface-that-save-lease-in-DHCP-info.patch
new file mode 100644 (file)
index 0000000..04fb8cc
--- /dev/null
@@ -0,0 +1,277 @@
+From 5bd77bc62bc47d5752a9060cb887883a9d1b9844 Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyi1.zhao@archermind.com>
+Date: Wed, 10 Jul 2013 19:17:02 +0800
+Subject: [PATCH 18/32] Tethering: Add interface that save lease in DHCP
+ information
+
+Change-Id: Ia09c875954d8a20a3e6c39f87076780d8a6582e4
+---
+ gdhcp/client.c | 65 ----------------------------------------------------------
+ gdhcp/common.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ gdhcp/common.h |  1 +
+ gdhcp/gdhcp.h  |  5 +++++
+ gdhcp/server.c | 29 +++++++++++++++++++++++++-
+ 5 files changed, 99 insertions(+), 66 deletions(-)
+
+diff --git a/gdhcp/client.c b/gdhcp/client.c
+index 66c3a90..a72efb4 100644
+--- a/gdhcp/client.c
++++ b/gdhcp/client.c
+@@ -1808,71 +1808,6 @@ static char *get_ip(uint32_t ip)
+       return g_strdup(inet_ntoa(addr));
+ }
+-/* get a rough idea of how long an option will be */
+-static const uint8_t len_of_option_as_string[] = {
+-      [OPTION_IP] = sizeof("255.255.255.255 "),
+-      [OPTION_STRING] = 1,
+-      [OPTION_U8] = sizeof("255 "),
+-      [OPTION_U16] = sizeof("65535 "),
+-      [OPTION_U32] = sizeof("4294967295 "),
+-};
+-
+-static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
+-{
+-      return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
+-}
+-
+-/* Create "opt_value1 option_value2 ..." string */
+-static char *malloc_option_value_string(uint8_t *option, GDHCPOptionType type)
+-{
+-      unsigned upper_length;
+-      int len, optlen;
+-      char *dest, *ret;
+-
+-      len = option[OPT_LEN - OPT_DATA];
+-      type &= OPTION_TYPE_MASK;
+-      optlen = dhcp_option_lengths[type];
+-      if (optlen == 0)
+-              return NULL;
+-      upper_length = len_of_option_as_string[type] *
+-                      ((unsigned)len / (unsigned)optlen);
+-      dest = ret = g_malloc(upper_length + 1);
+-      if (!ret)
+-              return NULL;
+-
+-      while (len >= optlen) {
+-              switch (type) {
+-              case OPTION_IP:
+-                      dest += sprint_nip(dest, "", option);
+-                      break;
+-              case OPTION_U16: {
+-                      uint16_t val_u16 = get_be16(option);
+-                      dest += sprintf(dest, "%u", val_u16);
+-                      break;
+-              }
+-              case OPTION_U32: {
+-                      uint32_t val_u32 = get_be32(option);
+-                      dest += sprintf(dest, "%u", val_u32);
+-                      break;
+-              }
+-              case OPTION_STRING:
+-                      memcpy(dest, option, len);
+-                      dest[len] = '\0';
+-                      return ret;
+-              default:
+-                      break;
+-              }
+-              option += optlen;
+-              len -= optlen;
+-              if (len <= 0)
+-                      break;
+-              *dest++ = ' ';
+-              *dest = '\0';
+-      }
+-
+-      return ret;
+-}
+-
+ static GList *get_option_value_list(char *value, GDHCPOptionType type)
+ {
+       char *pos = value;
+diff --git a/gdhcp/common.c b/gdhcp/common.c
+index 45278a8..ac6b125 100644
+--- a/gdhcp/common.c
++++ b/gdhcp/common.c
+@@ -144,6 +144,71 @@ int dhcp_end_option(uint8_t *optionptr)
+       return i;
+ }
++/* get a rough idea of how long an option will be */
++static const uint8_t len_of_option_as_string[] = {
++      [OPTION_IP] = sizeof("255.255.255.255 "),
++      [OPTION_STRING] = 1,
++      [OPTION_U8] = sizeof("255 "),
++      [OPTION_U16] = sizeof("65535 "),
++      [OPTION_U32] = sizeof("4294967295 "),
++};
++
++static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
++{
++      return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
++}
++
++/* Create "opt_value1 option_value2 ..." string */
++char *malloc_option_value_string(uint8_t *option, GDHCPOptionType type)
++{
++      unsigned upper_length;
++      int len, optlen;
++      char *dest, *ret;
++
++      len = option[OPT_LEN - OPT_DATA];
++      type &= OPTION_TYPE_MASK;
++      optlen = dhcp_option_lengths[type];
++      if (optlen == 0)
++              return NULL;
++      upper_length = len_of_option_as_string[type] *
++                      ((unsigned)len / (unsigned)optlen);
++      dest = ret = g_malloc(upper_length + 1);
++      if (ret == NULL)
++              return NULL;
++
++      while (len >= optlen) {
++              switch (type) {
++              case OPTION_IP:
++                      dest += sprint_nip(dest, "", option);
++                      break;
++              case OPTION_U16: {
++                      uint16_t val_u16 = get_be16(option);
++                      dest += sprintf(dest, "%u", val_u16);
++                      break;
++              }
++              case OPTION_U32: {
++                      uint32_t val_u32 = get_be32(option);
++                      dest += sprintf(dest, "%u", val_u32);
++                      break;
++              }
++              case OPTION_STRING:
++                      memcpy(dest, option, len);
++                      dest[len] = '\0';
++                      return ret;
++              default:
++                      break;
++              }
++              option += optlen;
++              len -= optlen;
++              if (len <= 0)
++                      break;
++              *dest++ = ' ';
++              *dest = '\0';
++      }
++
++      return ret;
++}
++
+ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
+                       int code, uint16_t *option_len, int *option_count)
+ {
+diff --git a/gdhcp/common.h b/gdhcp/common.h
+index c692799..1ab9a7c 100644
+--- a/gdhcp/common.h
++++ b/gdhcp/common.h
+@@ -170,6 +170,7 @@ static const uint8_t dhcp_option_lengths[] = {
+       [OPTION_U32]    = 4,
+ };
++char *malloc_option_value_string(uint8_t *option, GDHCPOptionType type);
+ uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code);
+ uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
+                       int code, uint16_t *option_len, int *option_count);
+diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h
+index f3e47bf..f4ef292 100644
+--- a/gdhcp/gdhcp.h
++++ b/gdhcp/gdhcp.h
+@@ -205,6 +205,9 @@ struct _GDHCPServer;
+ typedef struct _GDHCPServer GDHCPServer;
++typedef void (*GDHCPSaveACKLeaseFunc) (char *hostname,
++                      unsigned char *mac, unsigned int nip);
++
+ GDHCPServer *g_dhcp_server_new(GDHCPType type,
+               int ifindex, GDHCPServerError *error);
+ int g_dhcp_server_start(GDHCPServer *server);
+@@ -223,6 +226,8 @@ void g_dhcp_server_set_lease_time(GDHCPServer *dhcp_server,
+                                               unsigned int lease_time);
+ void g_dhcp_server_set_save_lease(GDHCPServer *dhcp_server,
+                               GDHCPSaveLeaseFunc func, gpointer user_data);
++void g_dhcp_server_set_save_ack_lease(GDHCPServer *dhcp_server,
++                              GDHCPSaveACKLeaseFunc func, gpointer user_data);
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/gdhcp/server.c b/gdhcp/server.c
+index aa40488..0171b5f 100644
+--- a/gdhcp/server.c
++++ b/gdhcp/server.c
+@@ -65,6 +65,7 @@ struct _GDHCPServer {
+       GHashTable *nip_lease_hash;
+       GHashTable *option_hash; /* Options send to client */
+       GDHCPSaveLeaseFunc save_lease_func;
++      GDHCPSaveACKLeaseFunc save_ack_lease_func;
+       GDHCPDebugFunc debug_func;
+       gpointer debug_data;
+ };
+@@ -398,6 +399,7 @@ GDHCPServer *g_dhcp_server_new(GDHCPType type,
+       dhcp_server->listener_watch = -1;
+       dhcp_server->listener_channel = NULL;
+       dhcp_server->save_lease_func = NULL;
++      dhcp_server->save_ack_lease_func = NULL;
+       dhcp_server->debug_func = NULL;
+       dhcp_server->debug_data = NULL;
+@@ -646,9 +648,12 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
+       struct dhcp_packet packet;
+       struct dhcp_lease *lease;
+       uint32_t requested_nip = 0;
+-      uint8_t type, *server_id_option, *request_ip_option;
++      uint8_t type, *server_id_option, *request_ip_option, *host_name;
+       int re;
++      GDHCPOptionType option_type;
++      char *option_value;
++
+       if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+               dhcp_server->listener_watch = 0;
+               return FALSE;
+@@ -693,8 +698,21 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
+               if (lease && requested_nip == lease->lease_nip) {
+                       debug(dhcp_server, "Sending ACK");
++
++                      host_name = dhcp_get_option(&packet, DHCP_HOST_NAME);
++                      option_type = dhcp_get_code_type(DHCP_HOST_NAME);
++                      option_value = malloc_option_value_string(host_name,
++                                                              option_type);
+                       send_ACK(dhcp_server, &packet,
+                               lease->lease_nip);
++
++                      if (dhcp_server->save_ack_lease_func)
++                              dhcp_server->save_ack_lease_func(
++                                                      option_value,
++                                                      lease->lease_mac,
++                                                      lease->lease_nip);
++                      g_free(option_value);
++
+                       break;
+               }
+@@ -814,6 +832,15 @@ void g_dhcp_server_set_save_lease(GDHCPServer *dhcp_server,
+       dhcp_server->save_lease_func = func;
+ }
++void g_dhcp_server_set_save_ack_lease(GDHCPServer *dhcp_server,
++                              GDHCPSaveACKLeaseFunc func, gpointer user_data)
++{
++      if (dhcp_server == NULL)
++              return;
++
++      dhcp_server->save_ack_lease_func = func;
++}
++
+ GDHCPServer *g_dhcp_server_ref(GDHCPServer *dhcp_server)
+ {
+       if (!dhcp_server)
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0019-Tethering-Notify-listeners-when-station-connection-c.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0019-Tethering-Notify-listeners-when-station-connection-c.patch
new file mode 100644 (file)
index 0000000..20403c2
--- /dev/null
@@ -0,0 +1,160 @@
+From b846a12300fa054beb16e97add2d13cd8e2496ae Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyi1.zhao@archermind.com>
+Date: Wed, 10 Jul 2013 20:00:36 +0800
+Subject: [PATCH 19/32] Tethering: Notify listeners when station connection
+ changes
+
+Change-Id: I048c1a8a348b6f862ca104ad2fbe971f580fe180
+---
+ src/technology.c | 10 +++++++
+ src/tethering.c  | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 94 insertions(+), 1 deletion(-)
+
+diff --git a/src/technology.c b/src/technology.c
+index d80d9e6..a06efd3 100644
+--- a/src/technology.c
++++ b/src/technology.c
+@@ -1070,6 +1070,16 @@ static const GDBusMethodTable technology_methods[] = {
+ static const GDBusSignalTable technology_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
++      { GDBUS_SIGNAL("DhcpConnected",
++                      GDBUS_ARGS({ "aptype", "s" },
++                              { "ipaddr", "s" },
++                              { "macaddr", "s" },
++                              { "hostname", "s" })) },
++      { GDBUS_SIGNAL("DhcpLeaseDeleted",
++                      GDBUS_ARGS({ "aptype", "s" },
++                              { "ipaddr", "s" },
++                              { "macaddr", "s" },
++                              { "hostname", "s" })) },
+       { },
+ };
+diff --git a/src/tethering.c b/src/tethering.c
+index 0cbf06c..c0c9743 100644
+--- a/src/tethering.c
++++ b/src/tethering.c
+@@ -89,6 +89,32 @@ struct connman_station_info {
+       char hostname[CONNMAN_STATION_STR_INFO_LEN];
+ };
++static void emit_station_signal(char *action_str,
++                      const struct connman_station_info *station_info)
++{
++      char *ip, *mac, *hostname;
++
++      if (station_info->path == NULL || station_info->type == NULL
++              || station_info->ip == NULL || station_info->mac == NULL
++                      || station_info->hostname == NULL)
++              return;
++
++      ip = g_strdup(station_info->ip);
++      mac = g_strdup(station_info->mac);
++      hostname = g_strdup(station_info->hostname);
++
++      g_dbus_emit_signal(connection, station_info->path,
++                      CONNMAN_TECHNOLOGY_INTERFACE, action_str,
++                      DBUS_TYPE_STRING, &station_info->type,
++                      DBUS_TYPE_STRING, &ip,
++                      DBUS_TYPE_STRING, &mac,
++                      DBUS_TYPE_STRING, &hostname,
++                      DBUS_TYPE_INVALID);
++
++      g_free(ip);
++      g_free(mac);
++      g_free(hostname);
++}
+ static void destroy_station(gpointer key, gpointer value, gpointer user_data)
+ {
+       struct connman_station_info *station_info;
+@@ -97,11 +123,59 @@ static void destroy_station(gpointer key, gpointer value, gpointer user_data)
+       station_info = value;
++      if (station_info->is_connected) {
++              station_info->is_connected = FALSE;
++              emit_station_signal("DhcpLeaseDeleted", station_info);
++      }
++
+       g_free(station_info->path);
+       g_free(station_info->type);
+       g_free(station_info);
+ }
++static void save_dhcp_ack_lease_info(char *hostname,
++                                   unsigned char *mac, unsigned int nip)
++{
++      char *lower_mac;
++      const char *ip;
++      char sta_mac[CONNMAN_STATION_MAC_INFO_LEN];
++      struct connman_station_info *info_found;
++      struct in_addr addr;
++      int str_len;
++
++      __sync_synchronize();
++
++      snprintf(sta_mac, CONNMAN_STATION_MAC_INFO_LEN,
++               "%02x:%02x:%02x:%02x:%02x:%02x",
++               mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
++      lower_mac = g_ascii_strdown(sta_mac, -1);
++
++      info_found = g_hash_table_lookup(sta_hash, lower_mac);
++      if (info_found == NULL) {
++              g_free(lower_mac);
++              return;
++      }
++
++      /* get the ip */
++      addr.s_addr = nip;
++      ip = inet_ntoa(addr);
++      str_len = strlen(ip) + 1;
++      if (str_len > CONNMAN_STATION_STR_INFO_LEN)
++              str_len = CONNMAN_STATION_STR_INFO_LEN - 1;
++      memcpy(info_found->ip, ip, str_len);
++
++      /* get hostname */
++      str_len = strlen(hostname) + 1;
++      if (str_len > CONNMAN_STATION_STR_INFO_LEN)
++              str_len = CONNMAN_STATION_STR_INFO_LEN - 1;
++      memcpy(info_found->hostname, hostname, str_len);
++
++      /* emit a signal */
++      info_found->is_connected = TRUE;
++      emit_station_signal("DhcpConnected", info_found);
++      g_free(lower_mac);
++}
++
+ int connman_technology_tethering_add_station(enum connman_service_type type,
+                                                       const char *mac)
+ {
+@@ -146,9 +220,15 @@ int connman_technology_tethering_remove_station(const char *mac)
+       lower_mac = g_ascii_strdown(mac, -1);
+       info_found = g_hash_table_lookup(sta_hash, lower_mac);
+-      if (info_found == NULL)
++      if (info_found == NULL) {
++              g_free(lower_mac);
+               return -EACCES;
++      }
++      if (info_found->is_connected) {
++              info_found->is_connected = FALSE;
++              emit_station_signal("DhcpLeaseDeleted", info_found);
++      }
+       g_free(lower_mac);
+       g_hash_table_remove(sta_hash, info_found->mac);
+       g_free(info_found->path);
+@@ -243,6 +323,9 @@ static GDHCPServer *dhcp_server_start(const char *bridge,
+       g_dhcp_server_set_option(dhcp_server, G_DHCP_DNS_SERVER, dns);
+       g_dhcp_server_set_ip_range(dhcp_server, start_ip, end_ip);
++      g_dhcp_server_set_save_ack_lease(dhcp_server,
++                                       save_dhcp_ack_lease_info, NULL);
++
+       g_dhcp_server_start(dhcp_server);
+       return dhcp_server;
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0020-Tethering-Add-open-access-point-support-in-technolog.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0020-Tethering-Add-open-access-point-support-in-technolog.patch
new file mode 100644 (file)
index 0000000..2272504
--- /dev/null
@@ -0,0 +1,69 @@
+From d0fcec2219e62723f4ed4e67e1724b8dc2c1cd96 Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyi1.zhao@archermind.com>
+Date: Thu, 11 Jul 2013 09:12:01 +0800
+Subject: [PATCH 20/32] Tethering: Add open access point support in technology
+
+Change-Id: I86f4a22567f5df2fbd5d0c0c03c6cc5b6fc24a2d
+---
+ src/technology.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/src/technology.c b/src/technology.c
+index a06efd3..be66c3a 100644
+--- a/src/technology.c
++++ b/src/technology.c
+@@ -245,8 +245,7 @@ static int set_tethering(struct connman_technology *technology,
+       if (!bridge)
+               return -EOPNOTSUPP;
+-      if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
+-          (!ident || !passphrase))
++      if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && (!ident))
+               return -EINVAL;
+       for (tech_drivers = technology->driver_list; tech_drivers;
+@@ -912,19 +911,30 @@ static DBusMessage *set_property(DBusConnection *conn,
+               if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+                       return __connman_error_not_supported(msg);
+-              if (strlen(str) < 8 || strlen(str) > 63)
+-                      return __connman_error_passphrase_required(msg);
++              if (strlen(str) < 8 || strlen(str) > 63) {
++                      if (g_str_equal(str, "")) {
++                              technology->tethering_passphrase = NULL;
+-              if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
+-                      g_free(technology->tethering_passphrase);
+-                      technology->tethering_passphrase = g_strdup(str);
+-                      technology_save(technology);
++                              connman_dbus_property_changed_basic(technology->path,
++                                              CONNMAN_TECHNOLOGY_INTERFACE,
++                                              "TetheringPassphrase",
++                                              DBUS_TYPE_STRING,
++                                              &str);
++                      }
++                      else
++                              return __connman_error_passphrase_required(msg);
++              } else {
++                      if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
++                              g_free(technology->tethering_passphrase);
++                              technology->tethering_passphrase = g_strdup(str);
++                              technology_save(technology);
+-                      connman_dbus_property_changed_basic(technology->path,
+-                                      CONNMAN_TECHNOLOGY_INTERFACE,
+-                                      "TetheringPassphrase",
+-                                      DBUS_TYPE_STRING,
+-                                      &technology->tethering_passphrase);
++                              connman_dbus_property_changed_basic(technology->path,
++                                              CONNMAN_TECHNOLOGY_INTERFACE,
++                                              "TetheringPassphrase",
++                                              DBUS_TYPE_STRING,
++                                              &technology->tethering_passphrase);
++                      }
+               }
+       } else if (g_str_equal(name, "Powered")) {
+               dbus_bool_t enable;
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0021-Tethering-Add-hidden-access-point-support-in-technol.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0021-Tethering-Add-hidden-access-point-support-in-technol.patch
new file mode 100644 (file)
index 0000000..a12e98f
--- /dev/null
@@ -0,0 +1,275 @@
+From cdc3af7c29f82b71c2ce76fb6aa28dd6b3d9e5cd Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyi1.zhao@archermind.com>
+Date: Thu, 11 Jul 2013 10:00:31 +0800
+Subject: [PATCH 21/32] Tethering: Add hidden access point support in
+ technology
+
+Change-Id: I73fccf5f322ee2597f8f58d5e3d7f60ddeb0a641
+---
+ doc/technology-api.txt     |  5 +++++
+ gsupplicant/gsupplicant.h  |  7 +++++++
+ gsupplicant/supplicant.c   |  4 ++++
+ include/technology.h       |  2 +-
+ plugins/bluetooth.c        |  2 +-
+ plugins/bluetooth_legacy.c |  2 +-
+ plugins/ethernet.c         |  2 +-
+ plugins/gadget.c           |  2 +-
+ plugins/wifi.c             | 13 ++++++++++---
+ src/technology.c           | 33 ++++++++++++++++++++++++++++++++-
+ 10 files changed, 63 insertions(+), 9 deletions(-)
+
+diff --git a/doc/technology-api.txt b/doc/technology-api.txt
+index f97eac0..2fbc876 100644
+--- a/doc/technology-api.txt
++++ b/doc/technology-api.txt
+@@ -97,3 +97,8 @@ Properties   boolean Powered [readwrite]
+                       This property is only valid for the WiFi technology,
+                       and is then mapped to the WPA pre-shared key clients
+                       will have to use in order to establish a connection.
++
++              boolean Hidden [readwrite]
++
++                      This option allows to enable or disable the support
++                      for the hidden Wi-Fi tethering.
+diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
+index 1fab1ba..c5dad72 100644
+--- a/gsupplicant/gsupplicant.h
++++ b/gsupplicant/gsupplicant.h
+@@ -129,6 +129,12 @@ typedef enum {
+       G_SUPPLICANT_PEER_GROUP_FAILED,
+ } GSupplicantPeerState;
++enum GSupplicantAPHiddenSSID {
++      G_SUPPLICANT_AP_NO_SSID_HIDING,
++      G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_LEN,
++      G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS,
++};
++
+ struct _GSupplicantSSID {
+       const void *ssid;
+       unsigned int ssid_len;
+@@ -150,6 +156,7 @@ struct _GSupplicantSSID {
+       dbus_bool_t use_wps;
+       const char *pin_wps;
+       const char *bgscan;
++      int ignore_broadcast_ssid;
+ };
+ typedef struct _GSupplicantSSID GSupplicantSSID;
+diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
+index 5ff9b3d..59bf279 100644
+--- a/gsupplicant/supplicant.c
++++ b/gsupplicant/supplicant.c
+@@ -4659,6 +4659,10 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
+                                       DBUS_TYPE_BYTE, &ssid->ssid,
+                                               ssid->ssid_len);
++      supplicant_dbus_dict_append_basic(&dict, "ignore_broadcast_ssid",
++                                      DBUS_TYPE_INT32,
++                                      &ssid->ignore_broadcast_ssid);
++
+       supplicant_dbus_dict_close(iter, &dict);
+ }
+diff --git a/include/technology.h b/include/technology.h
+index b13d4ec..8efe9e7 100644
+--- a/include/technology.h
++++ b/include/technology.h
+@@ -63,7 +63,7 @@ struct connman_technology_driver {
+                                                               int index);
+       int (*set_tethering) (struct connman_technology *technology,
+                               const char *identifier, const char *passphrase,
+-                              const char *bridge, bool enabled);
++                              const char *bridge, bool enabled, bool hidden);
+       int (*set_regdom) (struct connman_technology *technology,
+                                               const char *alpha2);
+ };
+diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
+index 28df406..f8abeac 100644
+--- a/plugins/bluetooth.c
++++ b/plugins/bluetooth.c
+@@ -854,7 +854,7 @@ static void bluetooth_tech_remove(struct connman_technology *technology)
+ static int bluetooth_tech_set_tethering(struct connman_technology *technology,
+               const char *identifier, const char *passphrase,
+-              const char *bridge, bool enabled)
++              const char *bridge, bool enabled, bool hidden)
+ {
+       GHashTableIter hash_iter;
+       gpointer key, value;
+diff --git a/plugins/bluetooth_legacy.c b/plugins/bluetooth_legacy.c
+index 2d7a9e0..a9ff574 100644
+--- a/plugins/bluetooth_legacy.c
++++ b/plugins/bluetooth_legacy.c
+@@ -1234,7 +1234,7 @@ static void disable_nap(gpointer key, gpointer value, gpointer user_data)
+ static int tech_set_tethering(struct connman_technology *technology,
+                               const char *identifier, const char *passphrase,
+-                              const char *bridge, bool enabled)
++                              const char *bridge, bool enabled, bool hidden)
+ {
+       struct tethering_info info = {
+               .technology     = technology,
+diff --git a/plugins/ethernet.c b/plugins/ethernet.c
+index b8e52ce..4e71346 100644
+--- a/plugins/ethernet.c
++++ b/plugins/ethernet.c
+@@ -309,7 +309,7 @@ static void eth_tech_disable_tethering(struct connman_technology *technology,
+ static int eth_tech_set_tethering(struct connman_technology *technology,
+                               const char *identifier, const char *passphrase,
+-                              const char *bridge, bool enabled)
++                              const char *bridge, bool enabled, bool hidden)
+ {
+       if (!connman_technology_is_tethering_allowed(
+                       CONNMAN_SERVICE_TYPE_ETHERNET))
+diff --git a/plugins/gadget.c b/plugins/gadget.c
+index 94f6648..97807d8 100644
+--- a/plugins/gadget.c
++++ b/plugins/gadget.c
+@@ -291,7 +291,7 @@ static void gadget_tech_disable_tethering(struct connman_technology *technology,
+ static int gadget_tech_set_tethering(struct connman_technology *technology,
+                               const char *identifier, const char *passphrase,
+-                              const char *bridge, bool enabled)
++                              const char *bridge, bool enabled, bool hidden)
+ {
+       DBG("bridge %s enabled %d", bridge, enabled);
+diff --git a/plugins/wifi.c b/plugins/wifi.c
+index b5bc3ba..21f9912 100644
+--- a/plugins/wifi.c
++++ b/plugins/wifi.c
+@@ -2927,7 +2927,8 @@ struct wifi_tethering_info {
+       GSupplicantSSID *ssid;
+ };
+-static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
++static GSupplicantSSID *ssid_ap_init(const char *ssid,
++              const char *passphrase, bool hidden)
+ {
+       GSupplicantSSID *ap;
+@@ -2952,6 +2953,12 @@ static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
+              ap->passphrase = passphrase;
+       }
++      if (hidden)
++              ap->ignore_broadcast_ssid =
++                              G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
++      else
++              ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
++
+       return ap;
+ }
+@@ -3032,7 +3039,7 @@ static void sta_remove_callback(int result,
+ static int tech_set_tethering(struct connman_technology *technology,
+                               const char *identifier, const char *passphrase,
+-                              const char *bridge, bool enabled)
++                              const char *bridge, bool enabled, bool hidden)
+ {
+       GList *list;
+       GSupplicantInterface *interface;
+@@ -3085,7 +3092,7 @@ static int tech_set_tethering(struct connman_technology *technology,
+               info->wifi = wifi;
+               info->technology = technology;
+               info->wifi->bridge = bridge;
+-              info->ssid = ssid_ap_init(identifier, passphrase);
++              info->ssid = ssid_ap_init(identifier, passphrase, hidden);
+               if (!info->ssid) {
+                       g_free(info);
+                       continue;
+diff --git a/src/technology.c b/src/technology.c
+index be66c3a..679c779 100644
+--- a/src/technology.c
++++ b/src/technology.c
+@@ -66,6 +66,7 @@ struct connman_technology {
+                                             */
+       char *tethering_ident;
+       char *tethering_passphrase;
++      bool tethering_hidden;
+       bool enable_persistent; /* Save the tech state */
+@@ -177,6 +178,9 @@ static void technology_save(struct connman_technology *technology)
+       g_key_file_set_boolean(keyfile, identifier, "Tethering",
+                               technology->tethering_persistent);
++      g_key_file_set_boolean(keyfile, identifier, "Hidden",
++                              technology->tethering_hidden);
++
+       if (technology->tethering_ident)
+               g_key_file_set_string(keyfile, identifier,
+                                       "Tethering.Identifier",
+@@ -233,9 +237,11 @@ static int set_tethering(struct connman_technology *technology,
+       int err;
+       const char *ident, *passphrase, *bridge;
+       GSList *tech_drivers;
++      bool hidden;
+       ident = technology->tethering_ident;
+       passphrase = technology->tethering_passphrase;
++      hidden = technology->tethering_hidden;
+       __sync_synchronize();
+       if (!technology->enabled)
+@@ -256,7 +262,7 @@ static int set_tethering(struct connman_technology *technology,
+                       continue;
+               err = driver->set_tethering(technology, ident, passphrase,
+-                              bridge, enabled);
++                              bridge, enabled, hidden);
+               if (result == -EINPROGRESS)
+                       continue;
+@@ -523,6 +529,11 @@ static void append_properties(DBusMessageIter *iter,
+                                       DBUS_TYPE_STRING,
+                                       &technology->tethering_passphrase);
++      val = technology->tethering_hidden;
++      connman_dbus_dict_append_basic(&dict, "Hidden",
++                                      DBUS_TYPE_BOOLEAN,
++                                      &val);
++
+       connman_dbus_dict_close(iter, &dict);
+ }
+@@ -936,6 +947,25 @@ static DBusMessage *set_property(DBusConnection *conn,
+                                               &technology->tethering_passphrase);
+                       }
+               }
++      } else if (g_str_equal(name, "Hidden")) {
++              dbus_bool_t hidden;
++
++              if (type != DBUS_TYPE_BOOLEAN)
++                      return __connman_error_invalid_arguments(msg);
++
++              dbus_message_iter_get_basic(&value, &hidden);
++
++              if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
++                      return __connman_error_not_supported(msg);
++
++              technology->tethering_hidden = hidden;
++              technology_save(technology);
++
++              connman_dbus_property_changed_basic(technology->path,
++                                      CONNMAN_TECHNOLOGY_INTERFACE,
++                                      "Hidden",
++                                      DBUS_TYPE_BOOLEAN,
++                                      &hidden);
+       } else if (g_str_equal(name, "Powered")) {
+               dbus_bool_t enable;
+@@ -1204,6 +1234,7 @@ static struct connman_technology *technology_get(enum connman_service_type type)
+       technology->refcount = 1;
+       technology->type = type;
++      technology->tethering_hidden = FALSE;
+       technology->path = g_strdup_printf("%s/technology/%s",
+                                                       CONNMAN_PATH, str);
+       if (type == CONNMAN_SERVICE_TYPE_P2P) {
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0022-Tethering-Add-test-script-of-open-and-hidden-AP.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0022-Tethering-Add-test-script-of-open-and-hidden-AP.patch
new file mode 100644 (file)
index 0000000..c2bf003
--- /dev/null
@@ -0,0 +1,86 @@
+From 395d388931d37b6760d7b9f59a5710dfe42662c7 Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyi1.zhao@archermind.com>
+Date: Thu, 11 Jul 2013 10:29:38 +0800
+Subject: [PATCH 22/32] Tethering: Add test script of open and hidden AP
+
+Change-Id: I8dbeaeba5848c8a8739422a93786b2ca6ed31b21
+---
+ test/enable-tethering | 34 +++++++++++++++++++++++++++-------
+ 1 file changed, 27 insertions(+), 7 deletions(-)
+ mode change 100755 => 100644 test/enable-tethering
+
+diff --git a/test/enable-tethering b/test/enable-tethering
+old mode 100755
+new mode 100644
+index cbcd4e7..674b3c9
+--- a/test/enable-tethering
++++ b/test/enable-tethering
+@@ -3,8 +3,17 @@
+ import sys
+ import dbus
+-if (len(sys.argv) >= 3 and len(sys.argv) != 4 and sys.argv[1] == "wifi"):
+-      print "Usage: %s wifi [SSID] [passphrase]" % (sys.argv[0])
++if (len(sys.argv) >= 2 and len(sys.argv) < 4 and sys.argv[1] == "wifi"):
++      print "Usage: %s wifi [SSID] [passphrase] [hidden]" % (sys.argv[0])
++      print "Example:"
++      print "Create the open system access point:"
++      print "%s wifi abcd \"\"" % (sys.argv[0])
++      print "Create the security access point:"
++      print "%s wifi abcd 123456789" % (sys.argv[0])
++      print "Create the hidden access point:"
++      print "%s wifi abcd 123456789 hidden" % (sys.argv[0])
++      print "Create the open and hidden access point:"
++      print "%s wifi abcd \"\" hidden" % (sys.argv[0])
+       sys.exit(1)
+ elif (len(sys.argv) < 2):
+       print "Usage: %s type" % (sys.argv[0])
+@@ -15,7 +24,7 @@ bus = dbus.SystemBus()
+ manager = dbus.Interface(bus.get_object('net.connman', "/"),
+                                       'net.connman.Manager')
+-def technology_enable_tethering(path, tech_type, ssid, psk):
++def technology_enable_tethering(path, tech_type, ssid, psk, hidden):
+       tech = dbus.Interface(bus.get_object("net.connman", path),
+                                               "net.connman.Technology")
+@@ -27,9 +36,17 @@ def technology_enable_tethering(path, tech_type, ssid, psk):
+                               if len(ssid) > 0:
+                                       tech.SetProperty("TetheringIdentifier",
+                                                               ssid)
+-                              if len(psk) > 0:
+                                       tech.SetProperty("TetheringPassphrase",
+                                                               psk)
++                              if tech_type == "wifi":
++                                      if len(hidden) > 0:
++                                              if hidden == "hidden":
++                                                      tech.SetProperty("Hidden",dbus.Boolean(1))
++                                              else:
++                                                      tech.SetProperty("Hidden",dbus.Boolean(0))
++                                      else:
++                                              tech.SetProperty("Hidden",dbus.Boolean(0))
++
+                               print "Enabling %s tethering" % tech_type
+                               tech.SetProperty("Tethering", dbus.Boolean(1))
+@@ -41,11 +58,14 @@ technologies = manager.GetTechnologies()
+ tech = None
+ for path,_ in technologies:
+-      if (len(sys.argv) == 4):
++      if (len(sys.argv) == 5):
++              tech = technology_enable_tethering(path,
++                                      sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
++      elif (len(sys.argv) == 4):
+               tech = technology_enable_tethering(path,
+-                                      sys.argv[1], sys.argv[2], sys.argv[3])
++                                      sys.argv[1], sys.argv[2], sys.argv[3], "")
+       else:
+-              tech = technology_enable_tethering(path, sys.argv[1], "", "")
++              tech = technology_enable_tethering(path, sys.argv[1], "", "", "")
+       if tech != None:
+               break;
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0023-Tethering-Add-tethering-interfaces-description-to-te.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0023-Tethering-Add-tethering-interfaces-description-to-te.patch
new file mode 100644 (file)
index 0000000..3049ae1
--- /dev/null
@@ -0,0 +1,37 @@
+From 5eb028f4bdf85b35d8003f36ee95b15e48aa3fbc Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyi1.zhao@archermind.com>
+Date: Fri, 26 Jul 2013 14:58:32 +0800
+Subject: [PATCH 23/32] Tethering: Add tethering interfaces description to
+ technology-api.txt
+
+Change-Id: I59768258d5f2515311ed3dad5db91618b1c459ec
+---
+ doc/technology-api.txt | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/doc/technology-api.txt b/doc/technology-api.txt
+index 2fbc876..14245eb 100644
+--- a/doc/technology-api.txt
++++ b/doc/technology-api.txt
+@@ -45,6 +45,18 @@ Signals             PropertyChanged(string name, variant value)
+                       This signal indicates a changed value of the given
+                       property.
++              DhcpConnected(string aptype, string ipaddr,
++                                      string macaddr, string hostname)
++
++                      This signal indicates a station information that
++                      has connected to the AP(Access Point).
++
++              DhcpLeaseDeleted(string aptype, string ipaddr,
++                                      string macaddr, string hostname)
++
++                      This signal indicates a station information that
++                      has disconnected to the AP(Access Point).
++
+ Properties    boolean Powered [readwrite]
+                       Boolean representing the power state of the
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0024-Tethering-Watch-the-connection-and-disconnection-sig.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0024-Tethering-Watch-the-connection-and-disconnection-sig.patch
new file mode 100644 (file)
index 0000000..7c86d21
--- /dev/null
@@ -0,0 +1,138 @@
+From 4f74881432eee7f368ae6827aa2453115749734e Mon Sep 17 00:00:00 2001
+From: Chengyi Zhao <chengyix.zhao@gmail.com>
+Date: Sun, 22 Sep 2013 14:14:06 +0800
+Subject: [PATCH 24/32] Tethering: Watch the connection and disconnection
+ signal of Bluetooth
+
+Signed-off-by: Chengyi Zhao <chengyix.zhao@intel.com>
+
+Change-Id: I38bb9b799c3e4c4c25acd9d264a4225bf59401dc
+---
+ plugins/bluetooth_legacy.c | 75 ++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 72 insertions(+), 3 deletions(-)
+
+diff --git a/plugins/bluetooth_legacy.c b/plugins/bluetooth_legacy.c
+index a9ff574..5a9a395 100644
+--- a/plugins/bluetooth_legacy.c
++++ b/plugins/bluetooth_legacy.c
+@@ -51,6 +51,9 @@
+ #define ADAPTER_REMOVED                       "AdapterRemoved"
+ #define DEVICE_REMOVED                        "DeviceRemoved"
++#define PEER_CONNECTED                 "PeerConnected"
++#define PEER_DISCONNECTED              "PeerDisconnected"
++
+ #define PROPERTY_CHANGED              "PropertyChanged"
+ #define GET_PROPERTIES                        "GetProperties"
+ #define SET_PROPERTY                  "SetProperty"
+@@ -334,6 +337,53 @@ static gboolean network_changed(DBusConnection *conn,
+       return TRUE;
+ }
++static void parse_peer_device(DBusMessage *message, char **dev,
++                              char **address)
++{
++      const char *path = dbus_message_get_path(message);
++      DBusMessageIter iter;
++
++      DBG("path %s", path);
++
++      if (dbus_message_iter_init(message, &iter) == FALSE)
++              return;
++
++      dbus_message_iter_get_basic(&iter, dev);
++      dbus_message_iter_next(&iter);
++      dbus_message_iter_get_basic(&iter, address);
++}
++
++static gboolean peer_connected(DBusConnection *connection,
++                              DBusMessage *message, void *user_data)
++{
++      char *dev, *address;
++
++      parse_peer_device(message, &dev, &address);
++
++      DBG("connection device is %s", dev);
++      DBG("connection address is %s", address);
++
++      connman_technology_tethering_add_station(
++                      CONNMAN_SERVICE_TYPE_BLUETOOTH, address);
++
++      return TRUE;
++}
++
++static gboolean peer_disconnected(DBusConnection *connection,
++                              DBusMessage *message, void *user_data)
++{
++      char *dev, *address;
++
++      parse_peer_device(message, &dev, &address);
++
++      DBG("disconnection device is %s", dev);
++      DBG("disconnection address is %s", address);
++
++      connman_technology_tethering_remove_station(address);
++
++      return TRUE;
++}
++
+ static void extract_properties(DBusMessage *reply, const char **parent,
+                                               const char **address,
+                                               const char **name,
+@@ -1270,6 +1320,8 @@ static guint adapter_watch;
+ static guint device_watch;
+ static guint device_removed_watch;
+ static guint network_watch;
++static guint peerconnected_watch;
++static guint peerdisconnected_watch;
+ static int bluetooth_init(void)
+ {
+@@ -1313,10 +1365,23 @@ static int bluetooth_init(void)
+                                               PROPERTY_CHANGED, network_changed,
+                                               NULL, NULL);
++      peerconnected_watch = g_dbus_add_signal_watch(connection,
++                                              BLUEZ_SERVICE,
++                                              NULL, BLUEZ_NETWORK_SERVER,
++                                              PEER_CONNECTED, peer_connected,
++                                              NULL, NULL);
++
++      peerdisconnected_watch = g_dbus_add_signal_watch(connection,
++                                              BLUEZ_SERVICE,
++                                              NULL, BLUEZ_NETWORK_SERVER,
++                                              PEER_DISCONNECTED,
++                                              peer_disconnected,
++                                              NULL, NULL);
++
+       if (watch == 0 || added_watch == 0 || removed_watch == 0
+-                      || adapter_watch == 0 || network_watch == 0
+-                              || device_watch == 0
+-                                      || device_removed_watch == 0) {
++              || adapter_watch == 0 || network_watch == 0 || device_watch == 0
++              || peerconnected_watch == 0 || peerdisconnected_watch == 0
++              || device_removed_watch == 0) {
+               err = -EIO;
+               goto remove;
+       }
+@@ -1348,6 +1413,8 @@ remove:
+       g_dbus_remove_watch(connection, device_removed_watch);
+       g_dbus_remove_watch(connection, device_watch);
+       g_dbus_remove_watch(connection, network_watch);
++      g_dbus_remove_watch(connection, peerconnected_watch);
++      g_dbus_remove_watch(connection, peerdisconnected_watch);
+       dbus_connection_unref(connection);
+@@ -1363,6 +1430,8 @@ static void bluetooth_exit(void)
+       g_dbus_remove_watch(connection, device_removed_watch);
+       g_dbus_remove_watch(connection, device_watch);
+       g_dbus_remove_watch(connection, network_watch);
++      g_dbus_remove_watch(connection, peerconnected_watch);
++      g_dbus_remove_watch(connection, peerdisconnected_watch);
+       /*
+        * We unset the disabling of the Bluetooth device when shutting down
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0025-Tethering-Get-the-client-mac-info-of-Gadget-tether.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0025-Tethering-Get-the-client-mac-info-of-Gadget-tether.patch
new file mode 100644 (file)
index 0000000..6b5c090
--- /dev/null
@@ -0,0 +1,154 @@
+From 58bd810c3a61593a3c7494f843fc5dfc1d411769 Mon Sep 17 00:00:00 2001
+From: "guoqiang.liu" <guoqiang.liu@archermind.com>
+Date: Wed, 25 Sep 2013 16:36:21 +0800
+Subject: [PATCH 25/32] Tethering: Get the client mac info of Gadget tether
+
+Change-Id: Icfa6cd683c659e6728060d6201b90109c63fe56d
+---
+ plugins/gadget.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 87 insertions(+)
+
+diff --git a/plugins/gadget.c b/plugins/gadget.c
+index 97807d8..6bc37a7 100644
+--- a/plugins/gadget.c
++++ b/plugins/gadget.c
+@@ -25,6 +25,8 @@
+ #include <errno.h>
+ #include <net/if.h>
++#include <stdio.h>
++#include <string.h>
+ #ifndef IFF_LOWER_UP
+ #define IFF_LOWER_UP  0x10000
+@@ -226,6 +228,71 @@ static struct connman_device_driver gadget_dev_driver = {
+ };
+ static GList *cdc_interface_list = NULL;
++static GHashTable *cdc_mac_hash = NULL;
++
++static void add_station(int index)
++{
++      char *path, line[128] = {'\0'};
++      char *ifname = connman_inet_ifname(index);
++      char *mac;
++      FILE *f;
++
++      if (ifname == NULL)
++              return;
++
++      path = g_strdup_printf("/sys/class/usb_mode/%s/f_rndis/ethaddr",
++                                      ifname);
++
++      f = fopen(path, "re");
++
++      g_free(ifname);
++      g_free(path);
++
++      if (f == NULL)
++              return;
++
++      if (fgets(line, sizeof(line), f) == NULL) {
++              fclose(f);
++              return;
++      }
++
++      fclose(f);
++
++      mac = g_ascii_strdown(line, strlen(line) - 1);
++      DBG("Add station %s in Technology %d", mac,
++                                              CONNMAN_SERVICE_TYPE_GADGET);
++
++      g_hash_table_insert(cdc_mac_hash, GINT_TO_POINTER(index),
++                              mac);
++
++      connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_GADGET,
++                              mac);
++}
++
++static void remove_station(int index)
++{
++      char *mac;
++      mac = g_hash_table_lookup(cdc_mac_hash, GINT_TO_POINTER(index));
++      if (mac == NULL)
++              return;
++
++      connman_technology_tethering_remove_station(mac);
++
++      g_hash_table_remove(cdc_mac_hash, GINT_TO_POINTER(index));
++}
++
++static gboolean remove_all_station(gpointer key, gpointer value, gpointer user_data)
++{
++      char *mac;
++      mac = value;
++      if (mac == NULL)
++              return TRUE;
++
++      connman_technology_tethering_remove_station(mac);
++
++      return TRUE;
++}
++
+ static void gadget_tech_add_interface(struct connman_technology *technology,
+                       int index, const char *name, const char *ident)
+@@ -246,6 +313,8 @@ static void gadget_tech_remove_interface(struct connman_technology *technology,
+       cdc_interface_list = g_list_remove(cdc_interface_list,
+                                       GINT_TO_POINTER((int) index));
++
++      remove_station(index);
+ }
+ static void gadget_tech_enable_tethering(struct connman_technology *technology,
+@@ -270,6 +339,8 @@ static void gadget_tech_enable_tethering(struct connman_technology *technology,
+               connman_inet_ifup(index);
+               connman_inet_add_to_bridge(index, bridge);
++
++              add_station(index);
+       }
+ }
+@@ -283,6 +354,8 @@ static void gadget_tech_disable_tethering(struct connman_technology *technology,
+               connman_inet_remove_from_bridge(index, bridge);
++              remove_station(index);
++
+               connman_inet_ifdown(index);
+               connman_technology_tethering_notify(technology, false);
+@@ -305,14 +378,28 @@ static int gadget_tech_set_tethering(struct connman_technology *technology,
+ static int gadget_tech_probe(struct connman_technology *technology)
+ {
++      DBG("tech probe %p", technology);
++
++      cdc_mac_hash = g_hash_table_new_full(g_direct_hash,
++                                       g_direct_equal, NULL, g_free);
++
+       return 0;
+ }
+ static void gadget_tech_remove(struct connman_technology *technology)
+ {
++      DBG("tech remove %p", technology);
++
+       g_list_free(cdc_interface_list);
+       cdc_interface_list = NULL;
++
++      if (cdc_mac_hash) {
++              g_hash_table_foreach_remove(cdc_mac_hash, remove_all_station,
++                                              NULL);
++              g_hash_table_destroy(cdc_mac_hash);
++              cdc_mac_hash = NULL;
++      }
+ }
+ static struct connman_technology_driver gadget_tech_driver = {
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0026-multi-user-Add-function-to-get-dbus-user-id-synchron.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0026-multi-user-Add-function-to-get-dbus-user-id-synchron.patch
new file mode 100644 (file)
index 0000000..265e47c
--- /dev/null
@@ -0,0 +1,66 @@
+From 113ccd0ca92ab8fe8a6e6c2db190cbcbeebe912d Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Sat, 11 Oct 2014 15:06:14 +0800
+Subject: [PATCH 26/32] multi-user: Add function to get dbus user id
+ synchronously
+
+Change-Id: Ic41643e5f8b6e1a28ce00e0456d961fe2de7a7fb
+---
+ include/dbus.h |  4 ++++
+ src/dbus.c     | 25 +++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/include/dbus.h b/include/dbus.h
+index 26f94d6..3087fe4 100644
+--- a/include/dbus.h
++++ b/include/dbus.h
+@@ -180,6 +180,10 @@ int connman_dbus_get_connection_unix_user(DBusConnection *connection,
+                                connman_dbus_get_connection_unix_user_cb_t func,
+                                void *user_data);
++int connman_dbus_get_connection_unix_user_sync(DBusConnection *connection,
++                              const char *bus_name,
++                              unsigned int *user_id);
++
+ typedef void (* connman_dbus_get_context_cb_t) (const unsigned char *context,
+                                               void *user_data, int err);
+diff --git a/src/dbus.c b/src/dbus.c
+index d80a46c..260cec6 100644
+--- a/src/dbus.c
++++ b/src/dbus.c
+@@ -524,6 +524,31 @@ err:
+       return err;
+ }
++int connman_dbus_get_connection_unix_user_sync(DBusConnection *connection,
++                                              const char *bus_name,
++                                              unsigned int *user_id)
++{
++      unsigned long uid;
++      DBusError err;
++
++      dbus_error_init(&err);
++
++      uid = dbus_bus_get_unix_user(connection, bus_name, &err);
++
++      if (uid == (unsigned long)-1) {
++              DBG("Can not get unix user ID!");
++              if (dbus_error_is_set(&err)) {
++                      DBG("%s", err.message);
++                      dbus_error_free(&err);
++              }
++              return -1;
++      }
++
++      *user_id = (unsigned int)uid;
++
++      return 0;
++}
++
+ static unsigned char *parse_context(DBusMessage *msg)
+ {
+       DBusMessageIter iter, array;
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0027-multi-user-Add-multi-user-support-in-service.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0027-multi-user-Add-multi-user-support-in-service.patch
new file mode 100644 (file)
index 0000000..d8e8092
--- /dev/null
@@ -0,0 +1,302 @@
+From 44a0a44c579df0192ec33c291b2efdfabfe5c7eb Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Sat, 11 Oct 2014 15:08:18 +0800
+Subject: [PATCH 27/32] multi-user: Add multi-user support in service
+
+Use cases:
+
+Given 2 users: UserA and UserB
+
+1. If UserA is connected to a wifi service, then UserB is not allowed
+to connect wifi service, and not allowed to disconnect the service
+UserA connected.
+
+2. If UserA is connected to a wifi service, then UserB is allowed to
+use the same connection, but he is not allowed to modify the connection.
+
+3. If UserA is connected to a wifi service with security wep/wpa/psk,
+then UserA disconnects it, when UserB tries to connect the same wifi
+service, it must input passphrase to connect it.
+
+Change-Id: Id686ebd7d1f3490875a9d8f877219bd004907227
+---
+ src/connman.h |   3 ++
+ src/service.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 159 insertions(+), 1 deletion(-)
+
+diff --git a/src/connman.h b/src/connman.h
+index 4d78eab..386e8c8 100644
+--- a/src/connman.h
++++ b/src/connman.h
+@@ -791,6 +791,9 @@ void __connman_service_notify(struct connman_service *service,
+                       unsigned int rx_error, unsigned int tx_error,
+                       unsigned int rx_dropped, unsigned int tx_dropped);
++bool __connman_service_is_user_allowed(enum connman_service_type type,
++                                      uid_t uid);
++
+ int __connman_service_counter_register(const char *counter);
+ void __connman_service_counter_unregister(const char *counter);
+diff --git a/src/service.c b/src/service.c
+index 99bb35d..a1124ae 100644
+--- a/src/service.c
++++ b/src/service.c
+@@ -39,6 +39,9 @@
+ #define CONNECT_TIMEOUT               120
++#define USER_ROOT             0
++#define USER_NONE             (uid_t)-1
++
+ #if defined TIZEN_EXT
+ #define WIFI_BSSID_STR_LEN    18
+ #endif
+@@ -67,6 +70,11 @@ struct connman_stats_counter {
+       struct connman_stats stats_roaming;
+ };
++struct connman_service_user {
++      uid_t favorite_user;
++      uid_t current_user;
++};
++
+ struct connman_service {
+       int refcount;
+       char *identifier;
+@@ -89,6 +97,8 @@ struct connman_service {
+       char *name;
+       char *passphrase;
+       bool roaming;
++      bool request_passphrase_input;
++      struct connman_service_user user;
+       struct connman_ipconfig *ipconfig_ipv4;
+       struct connman_ipconfig *ipconfig_ipv6;
+       struct connman_network *network;
+@@ -351,6 +361,24 @@ static enum connman_service_proxy_method string2proxymethod(const char *method)
+               return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
+ }
++static bool
++connman_service_is_user_allowed(struct connman_service *service, uid_t uid)
++{
++      uid_t favorite_user = service->user.favorite_user;
++      uid_t current_user = uid;
++
++      DBG("Service favorite UID: %d, current UID: %d", favorite_user, current_user);
++      if (favorite_user == USER_NONE || current_user == USER_ROOT)
++              return true;
++
++      if (favorite_user != current_user || current_user == USER_NONE) {
++              DBG("Current user is not a favorite user to this service!");
++              return false;
++      }
++
++      return true;
++}
++
+ int __connman_service_load_modifiable(struct connman_service *service)
+ {
+       GKeyFile *keyfile;
+@@ -574,6 +602,8 @@ static int service_load(struct connman_service *service)
+       service->hidden_service = g_key_file_get_boolean(keyfile,
+                                       service->identifier, "Hidden", NULL);
++      service->user.favorite_user = g_key_file_get_integer(keyfile,
++                                      service->identifier, "UID", NULL);
+ done:
+       g_key_file_free(keyfile);
+@@ -619,6 +649,9 @@ static int service_save(struct connman_service *service)
+                       const unsigned char *ssid;
+                       unsigned int ssid_len = 0;
++                      g_key_file_set_integer(keyfile, service->identifier,
++                              "UID", service->user.favorite_user);
++
+                       ssid = connman_network_get_blob(service->network,
+                                                       "WiFi.SSID", &ssid_len);
+@@ -3236,6 +3269,21 @@ static DBusMessage *set_property(DBusConnection *conn,
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+               return __connman_error_invalid_arguments(msg);
++      if (service->type == CONNMAN_SERVICE_TYPE_WIFI && is_connected(service)) {
++              uid_t uid;
++              if (connman_dbus_get_connection_unix_user_sync(conn,
++                                              dbus_message_get_sender(msg),
++                                              &uid) < 0) {
++                      DBG("Can not get unix user id!");
++                      return __connman_error_permission_denied(msg);
++              }
++
++              if (!connman_service_is_user_allowed(service, uid)) {
++                      DBG("Not allow this user to operate this wifi service now!");
++                      return __connman_error_permission_denied(msg);
++              }
++      }
++
+       dbus_message_iter_get_basic(&iter, &name);
+       dbus_message_iter_next(&iter);
+@@ -3997,6 +4045,26 @@ static DBusMessage *connect_service(DBusConnection *conn,
+       if (service->pending)
+               return __connman_error_in_progress(msg);
++      if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
++              uid_t uid;
++              if (connman_dbus_get_connection_unix_user_sync(conn,
++                                              dbus_message_get_sender(msg),
++                                              &uid) < 0) {
++                      DBG("Can not get unix user id!");
++                      return __connman_error_permission_denied(msg);
++              }
++
++              if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
++                      DBG("Not allow this user to connect this wifi service now!");
++                      return __connman_error_permission_denied(msg);
++              }
++
++              if (uid != USER_ROOT && uid != service->user.favorite_user)
++                      service->request_passphrase_input = true;
++
++              service->user.current_user = uid;
++      }
++
+       index = __connman_service_get_index(service);
+       for (list = service_list; list; list = list->next) {
+@@ -4048,6 +4116,21 @@ static DBusMessage *disconnect_service(DBusConnection *conn,
+       DBG("service %p", service);
++      if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
++              uid_t uid;
++              if (connman_dbus_get_connection_unix_user_sync(conn,
++                                              dbus_message_get_sender(msg),
++                                              &uid) < 0) {
++                      DBG("Can not get unix user id!");
++                      return __connman_error_permission_denied(msg);
++              }
++
++              if (!connman_service_is_user_allowed(service, uid)) {
++                      DBG("Not allow this user to disconnect this wifi service now!");
++                      return __connman_error_permission_denied(msg);
++              }
++      }
++
+       service->ignore = true;
+       err = __connman_service_disconnect(service);
+@@ -4103,6 +4186,21 @@ static DBusMessage *remove_service(DBusConnection *conn,
+       DBG("service %p", service);
++      if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
++              uid_t uid;
++              if (connman_dbus_get_connection_unix_user_sync(conn,
++                                              dbus_message_get_sender(msg),
++                                              &uid) < 0) {
++                      DBG("Can not get unix user id!");
++                      return __connman_error_permission_denied(msg);
++              }
++
++              if (!connman_service_is_user_allowed(service, uid)) {
++                      DBG("Not allow this user to remove this wifi service now!");
++                      return __connman_error_permission_denied(msg);
++              }
++      }
++
+       if (!__connman_service_remove(service))
+               return __connman_error_not_supported(msg);
+@@ -4583,6 +4681,11 @@ static void service_initialize(struct connman_service *service)
+       service->ignore = false;
++      service->user.favorite_user = USER_NONE;
++      service->user.current_user = USER_NONE;
++
++      service->request_passphrase_input = false;
++
+       service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
+       service->order = 0;
+@@ -4809,6 +4912,40 @@ char *connman_service_get_interface(struct connman_service *service)
+ }
+ /**
++ * __connman_service_is_user_allowed:
++ * @type: service type
++ * @uid: user id
++ *
++ * Check a user is allowed to operate a type of service
++ */
++bool __connman_service_is_user_allowed(enum connman_service_type type,
++                                      uid_t uid)
++{
++      GList *list;
++      uid_t owner_user = USER_NONE;
++
++      for (list = service_list; list; list = list->next) {
++              struct connman_service *service = list->data;
++
++              if (service->type != type)
++                      continue;
++
++              if (is_connected(service)) {
++                      owner_user = service->user.favorite_user;
++                      break;
++              }
++      }
++
++      if (uid == USER_NONE ||
++                      (uid != USER_ROOT &&
++                      owner_user != USER_NONE &&
++                      owner_user != uid))
++              return false;
++
++      return true;
++}
++
++/**
+  * connman_service_get_network:
+  * @service: service structure
+  *
+@@ -5487,6 +5624,20 @@ static int service_indicate_state(struct connman_service *service)
+               default_changed();
+       }
++      if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
++              service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER &&
++              (new_state == CONNMAN_SERVICE_STATE_READY ||
++              new_state == CONNMAN_SERVICE_STATE_ONLINE)) {
++              if (service->user.favorite_user != service->user.current_user) {
++                      DBG("Now set service favorite user id from %d to %d",
++                      service->user.favorite_user, service->user.current_user);
++
++                      service->user.favorite_user = service->user.current_user;
++
++                      service_save(service);
++              }
++      }
++
+       return 0;
+ }
+@@ -5898,7 +6049,11 @@ static int service_connect(struct connman_service *service)
+               case CONNMAN_SERVICE_SECURITY_PSK:
+               case CONNMAN_SERVICE_SECURITY_WPA:
+               case CONNMAN_SERVICE_SECURITY_RSN:
+-                      if (!service->passphrase) {
++                      if (service->request_passphrase_input) {
++                              DBG("Now try to connect other user's favorite service");
++                              service->request_passphrase_input = false;
++                              return -ENOKEY;
++                      } else if (!service->passphrase) {
+                               if (!service->network)
+                                       return -EOPNOTSUPP;
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0028-multi-user-Add-multi-user-support-in-technology.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0028-multi-user-Add-multi-user-support-in-technology.patch
new file mode 100644 (file)
index 0000000..ebb04a0
--- /dev/null
@@ -0,0 +1,46 @@
+From 37cbead2d2cbea4b9bd9f7180caf26a4b653662d Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Sat, 11 Oct 2014 15:09:09 +0800
+Subject: [PATCH 28/32] multi-user: Add multi-user support in technology
+
+Use case:
+
+Given 2 users: UserA and UserB
+
+If UserA is connected to a wifi service, then UserB is not allowed
+to set wifi technology properties.
+
+Change-Id: Ia783b22bc28e9e487ddfa3a4c249c9d1ea76bde8
+---
+ src/technology.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/technology.c b/src/technology.c
+index 679c779..70732f6 100644
+--- a/src/technology.c
++++ b/src/technology.c
+@@ -862,6 +862,21 @@ static DBusMessage *set_property(DBusConnection *conn,
+       DBG("property %s", name);
++      if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && technology->connected) {
++              uid_t uid;
++              if (connman_dbus_get_connection_unix_user_sync(conn,
++                                              dbus_message_get_sender(msg),
++                                              &uid) < 0) {
++                      DBG("Can not get unix user id!");
++                      return __connman_error_permission_denied(msg);
++              }
++
++              if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
++                      DBG("Not allow this user to operate wifi technology now!");
++                      return __connman_error_permission_denied(msg);
++              }
++      }
++
+       if (g_str_equal(name, "Tethering")) {
+               dbus_bool_t tethering;
+               int err;
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0029-multi-user-Add-multi-user-support-in-manager.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0029-multi-user-Add-multi-user-support-in-manager.patch
new file mode 100644 (file)
index 0000000..efcffd6
--- /dev/null
@@ -0,0 +1,45 @@
+From 9235632fd02062efa3a1af7eb1957fdd364f4a8c Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 17 Oct 2014 11:21:37 +0800
+Subject: [PATCH 29/32] multi-user: Add multi-user support in manager
+
+Use case:
+
+Given 2 users: UserA and UserB
+
+If UserA is connected to a wifi service, then UserB is not allowed
+to turn on offline mode.
+
+Change-Id: I54b108beb580a805c7fa2d3ae9dac192b836ba77
+---
+ src/manager.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/src/manager.c b/src/manager.c
+index d15ce20..bd52f39 100644
+--- a/src/manager.c
++++ b/src/manager.c
+@@ -102,6 +102,20 @@ static DBusMessage *set_property(DBusConnection *conn,
+               dbus_message_iter_get_basic(&value, &offlinemode);
++              if (offlinemode) {
++                      uid_t uid;
++                      if (connman_dbus_get_connection_unix_user_sync(conn,
++                                              dbus_message_get_sender(msg),
++                                              &uid) < 0) {
++                              DBG("Can not get unix user id!");
++                              return __connman_error_permission_denied(msg);
++                      }
++
++                      if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
++                              DBG("Not allow this user to turn on offlinemode now!");
++                              return __connman_error_permission_denied(msg);
++                      }
++              }
+               __connman_technology_set_offlinemode(offlinemode);
+       } else if (g_str_equal(name, "SessionMode")) {
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0030-multi-user-Add-multi-user-support-for-auto-connect-s.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0030-multi-user-Add-multi-user-support-for-auto-connect-s.patch
new file mode 100644 (file)
index 0000000..c7d6817
--- /dev/null
@@ -0,0 +1,106 @@
+From 96469b8ff2cd0e7dc77b7974c431f1dd97981356 Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Sat, 11 Oct 2014 16:46:50 +0800
+Subject: [PATCH 30/32] multi-user: Add multi-user support for auto connect
+ service
+
+Use case:
+
+For wifi auto connect mechamnism, only when the user who owns the
+wifi service login, the service is allowed to be auto connected.
+
+Change-Id: I99135117facafda41532e0280c89194b27baac16
+---
+ src/service.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 62 insertions(+)
+
+diff --git a/src/service.c b/src/service.c
+index a1124ae..55cf02c 100644
+--- a/src/service.c
++++ b/src/service.c
+@@ -30,6 +30,8 @@
+ #include <gdbus.h>
+ #include <ctype.h>
+ #include <stdint.h>
++#include <pwd.h>
++#include <utmpx.h>
+ #include <connman/storage.h>
+ #include <connman/setting.h>
+@@ -379,6 +381,61 @@ connman_service_is_user_allowed(struct connman_service *service, uid_t uid)
+       return true;
+ }
++static GList *connman_service_get_login_users()
++{
++      struct utmpx *utmp;
++      struct passwd *pwd;
++      GList *user_list = NULL;
++
++      setutxent();
++
++      while ((utmp = getutxent()) != NULL) {
++              if (utmp->ut_user != USER_ROOT && utmp->ut_type != USER_PROCESS)
++                      continue;
++
++              pwd = getpwnam(utmp->ut_user);
++
++              if (!g_list_find(user_list, GUINT_TO_POINTER(pwd->pw_uid)))
++                      user_list = g_list_append(user_list,
++                                              GUINT_TO_POINTER(pwd->pw_uid));
++
++              DBG("User Name: %s, UID: %d", utmp->ut_user, pwd->pw_uid);
++      }
++
++      endutxent();
++
++      return user_list;
++}
++
++static bool is_service_owner_user_login(struct connman_service *service)
++{
++      GList *list, *user_list;
++      bool ret = false;
++
++      /* Here we only care about wifi service */
++      if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
++              return true;
++
++      user_list = connman_service_get_login_users();
++
++      DBG("service favorite user id is: %d", service->user.favorite_user);
++
++      for (list = user_list; list; list = list->next) {
++              uid_t uid = GPOINTER_TO_UINT(list->data);
++
++              DBG("login user id is %d", uid);
++
++              if (service->user.favorite_user == uid) {
++                      ret = true;
++                      break;
++              }
++      }
++
++      g_list_free(user_list);
++
++      return ret;
++}
++
+ int __connman_service_load_modifiable(struct connman_service *service)
+ {
+       GKeyFile *keyfile;
+@@ -3800,6 +3857,11 @@ static bool auto_connect_service(GList *services,
+                       continue;
+               }
++              if (!is_service_owner_user_login(service)) {
++                      DBG("favorite user not login, wifi auto connect denied");
++                      continue;
++              }
++
+               DBG("service %p %s %s", service, service->name,
+                       (preferred) ? "preferred" : reason2string(reason));
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0031-multi-user-Expose-function-to-check-service-user-fav.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0031-multi-user-Expose-function-to-check-service-user-fav.patch
new file mode 100644 (file)
index 0000000..4945b38
--- /dev/null
@@ -0,0 +1,81 @@
+From 9d476728838e2442d349adb679147581a963f8e9 Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Wed, 19 Nov 2014 09:50:45 +0800
+Subject: [PATCH 31/32] multi-user: Expose function to check service user
+ favorite
+
+Expose the function to check whether the service is favorite
+to the current user.
+
+Change-Id: Ib232f16c652ec94ef2e10b199a638a98554a1066
+---
+ doc/service-api.txt |  7 +++++++
+ src/service.c       | 27 +++++++++++++++++++++++++++
+ 2 files changed, 34 insertions(+)
+
+diff --git a/doc/service-api.txt b/doc/service-api.txt
+index 74c8345..0238d22 100644
+--- a/doc/service-api.txt
++++ b/doc/service-api.txt
+@@ -122,6 +122,13 @@ Methods           dict GetProperties()  [deprecated]
+                       Possible Errors: None
++              boolean GetUserFavorite() [experimental]
++
++                      This function is used to check whether this service
++                      is favorite to the current user.
++
++                      Possible Errors: None
++
+ Signals               PropertyChanged(string name, variant value)
+                       This signal indicates a changed value of the given
+diff --git a/src/service.c b/src/service.c
+index 55cf02c..5eca970 100644
+--- a/src/service.c
++++ b/src/service.c
+@@ -4472,6 +4472,30 @@ static DBusMessage *reset_counters(DBusConnection *conn,
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
++static DBusMessage *get_user_favorite(DBusConnection *conn,
++                                      DBusMessage *msg, void *user_data)
++{
++      DBusMessage *reply;
++      uid_t uid = USER_NONE;
++      dbus_bool_t user_favorite = false;
++      struct connman_service *service = user_data;
++
++      connman_dbus_get_connection_unix_user_sync(conn,
++                                      dbus_message_get_sender(msg),
++                                      &uid);
++      if (uid == USER_ROOT)
++              user_favorite = service->favorite;
++      else if (uid != USER_NONE && uid == service->user.favorite_user) {
++              DBG("The service is favorite to this user!");
++              user_favorite = true;
++      }
++
++      reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
++      dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN,
++                              &user_favorite, DBUS_TYPE_INVALID);
++      return reply;
++}
++
+ static struct _services_notify {
+       int id;
+       GHashTable *add;
+@@ -4613,6 +4637,9 @@ static const GDBusMethodTable service_methods[] = {
+                       GDBUS_ARGS({ "service", "o" }), NULL,
+                       move_after) },
+       { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
++      { GDBUS_METHOD("GetUserFavorite",
++                      NULL, GDBUS_ARGS({ "value", "v" }),
++                      get_user_favorite) },
+       { },
+ };
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0032-multi-user-Fix-service-load-save-issues.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0032-multi-user-Fix-service-load-save-issues.patch
new file mode 100644 (file)
index 0000000..450580a
--- /dev/null
@@ -0,0 +1,109 @@
+From 7d48e7bfd2d9d371766ddb36bb3da99111dd3935 Mon Sep 17 00:00:00 2001
+From: Zhang zhengguang <zhengguang.zhang@intel.com>
+Date: Fri, 21 Nov 2014 16:34:11 +0800
+Subject: [PATCH 32/32] multi-user: Fix service load/save issues
+
+Refine service load/save to be multi-user complicant.
+
+Change-Id: Icc8a0507826f4cae72319191e4fdbebe548434fc
+---
+ src/service.c | 47 +++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 39 insertions(+), 8 deletions(-)
+
+diff --git a/src/service.c b/src/service.c
+index 5eca970..86dffaf 100644
+--- a/src/service.c
++++ b/src/service.c
+@@ -484,6 +484,23 @@ int __connman_service_load_modifiable(struct connman_service *service)
+       return 0;
+ }
++static int service_load_passphrase(struct connman_service *service)
++{
++      GKeyFile *keyfile;
++      gchar *str;
++
++      keyfile = connman_storage_load_service(service->identifier);
++      if (!keyfile)
++              return -EIO;
++
++      str = g_key_file_get_string(keyfile,
++                              service->identifier, "Passphrase", NULL);
++      if (str)
++              service->passphrase = str;
++
++      return 0;
++}
++
+ static int service_load(struct connman_service *service)
+ {
+       GKeyFile *keyfile;
+@@ -659,7 +676,8 @@ static int service_load(struct connman_service *service)
+       service->hidden_service = g_key_file_get_boolean(keyfile,
+                                       service->identifier, "Hidden", NULL);
+-      service->user.favorite_user = g_key_file_get_integer(keyfile,
++      if (g_key_file_has_key(keyfile, service->identifier, "UID", NULL))
++              service->user.favorite_user = g_key_file_get_integer(keyfile,
+                                       service->identifier, "UID", NULL);
+ done:
+       g_key_file_free(keyfile);
+@@ -706,8 +724,12 @@ static int service_save(struct connman_service *service)
+                       const unsigned char *ssid;
+                       unsigned int ssid_len = 0;
+-                      g_key_file_set_integer(keyfile, service->identifier,
+-                              "UID", service->user.favorite_user);
++                      if (service->user.favorite_user == USER_NONE)
++                              g_key_file_remove_key(keyfile, service->identifier,
++                                                      "UID", NULL);
++                      else
++                              g_key_file_set_integer(keyfile, service->identifier,
++                                                      "UID", service->user.favorite_user);
+                       ssid = connman_network_get_blob(service->network,
+                                                       "WiFi.SSID", &ssid_len);
+@@ -764,12 +786,14 @@ static int service_save(struct connman_service *service)
+               g_free(str);
+       }
+-      if (service->passphrase && strlen(service->passphrase) > 0)
+-              g_key_file_set_string(keyfile, service->identifier,
++      if (service->user.current_user == service->user.favorite_user) {
++              if (service->passphrase && strlen(service->passphrase) > 0)
++                      g_key_file_set_string(keyfile, service->identifier,
+                                       "Passphrase", service->passphrase);
+-      else
+-              g_key_file_remove_key(keyfile, service->identifier,
+-                                                      "Passphrase", NULL);
++              else
++                      g_key_file_remove_key(keyfile, service->identifier,
++                                      "Passphrase", NULL);
++      }
+       if (service->ipconfig_ipv4)
+               __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
+@@ -4125,6 +4149,11 @@ static DBusMessage *connect_service(DBusConnection *conn,
+                       service->request_passphrase_input = true;
+               service->user.current_user = uid;
++
++              if (!service->passphrase && uid == service->user.favorite_user) {
++                      DBG("Now load this favorite user's passphrase.");
++                      service_load_passphrase(service);
++              }
+       }
+       index = __connman_service_get_index(service);
+@@ -4232,6 +4261,8 @@ bool __connman_service_remove(struct connman_service *service)
+       service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
++      service->user.favorite_user = USER_NONE;
++
+       __connman_service_set_favorite(service, false);
+       __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
+-- 
+1.8.1.4
+
diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman_%.bbappend b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman_%.bbappend
new file mode 100644 (file)
index 0000000..16d6828
--- /dev/null
@@ -0,0 +1,34 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Add-bootstrap-files.patch"
+SRC_URI += "file://0002-Add-package-build-spec-file.patch"
+SRC_URI += "file://0003-Add-systemd-service-to-manager-ConnMan-NTP.patch"
+SRC_URI += "file://0004-Set-manifest-request-domain-to-floor.patch"
+SRC_URI += "file://0005-Set-ConnMan-default-settings-in-config-files.patch"
+SRC_URI += "file://0006-Enable-ConnMan-NTP-configurable-in-spec-file.patch"
+SRC_URI += "file://0007-Enable-ConnMan-VPND-OpenVPN-OpenConnect-configurable.patch"
+SRC_URI += "file://0008-Add-connmanctl-to-the-built-rpm.patch"
+SRC_URI += "file://0009-Tizen-Export-more-wifi-info-in-ConnMan-network-API.patch"
+SRC_URI += "file://0010-Tizen-Append-extra-wifi-service-property.patch"
+SRC_URI += "file://0011-Tizen-Export-network-proxy-API-for-telephony-plugin.patch"
+SRC_URI += "file://0012-Tizen-Integrate-telephony-plugin.patch"
+SRC_URI += "file://0013-Tizen-Fix-wifi-enterprise-to-support-SIM-and-AKA.patch"
+SRC_URI += "file://0014-Tizen-Check-some-telephony-flags-before-active-conte.patch"
+SRC_URI += "file://0015-Tizen-Unify-bluetooth-tethering-enable-logic.patch"
+SRC_URI += "file://0016-Tethering-Add-handling-for-wpa_supplicant-authorized.patch"
+SRC_URI += "file://0017-Tethering-Add-station-information-management-feature.patch"
+SRC_URI += "file://0018-Tethering-Add-interface-that-save-lease-in-DHCP-info.patch"
+SRC_URI += "file://0019-Tethering-Notify-listeners-when-station-connection-c.patch"
+SRC_URI += "file://0020-Tethering-Add-open-access-point-support-in-technolog.patch"
+SRC_URI += "file://0021-Tethering-Add-hidden-access-point-support-in-technol.patch"
+SRC_URI += "file://0022-Tethering-Add-test-script-of-open-and-hidden-AP.patch"
+SRC_URI += "file://0023-Tethering-Add-tethering-interfaces-description-to-te.patch"
+SRC_URI += "file://0024-Tethering-Watch-the-connection-and-disconnection-sig.patch"
+SRC_URI += "file://0025-Tethering-Get-the-client-mac-info-of-Gadget-tether.patch"
+SRC_URI += "file://0026-multi-user-Add-function-to-get-dbus-user-id-synchron.patch"
+SRC_URI += "file://0027-multi-user-Add-multi-user-support-in-service.patch"
+SRC_URI += "file://0028-multi-user-Add-multi-user-support-in-technology.patch"
+SRC_URI += "file://0029-multi-user-Add-multi-user-support-in-manager.patch"
+SRC_URI += "file://0030-multi-user-Add-multi-user-support-for-auto-connect-s.patch"
+SRC_URI += "file://0031-multi-user-Expose-function-to-check-service-user-fav.patch"
+SRC_URI += "file://0032-multi-user-Fix-service-load-save-issues.patch"