diff options
author | Michael Zanetti <michael.zanetti@nokia.com> | 2011-08-24 14:09:22 +1000 |
---|---|---|
committer | Rohan McGovern <rohan.mcgovern@nokia.com> | 2011-08-24 14:10:36 +1000 |
commit | 29ba8297443cf76d4f647bde329d62c2a567c709 (patch) | |
tree | 88875199053cd88b3b3521c829277f209e815159 | |
download | qtconnectivity-29ba8297443cf76d4f647bde329d62c2a567c709.tar.gz |
Initial commit.
From qt5connectivity.tar.gz, md5 317c149d6f8c07d09632353188582834
313 files changed, 52301 insertions, 0 deletions
diff --git a/config.tests/bluez/bluez.pro b/config.tests/bluez/bluez.pro new file mode 100644 index 00000000..bb5fa2dd --- /dev/null +++ b/config.tests/bluez/bluez.pro @@ -0,0 +1,8 @@ +TEMPLATE = app + +CONFIG += link_pkgconfig +PKGCONFIG += bluez + +TARGET = bluez + +SOURCES += main.cpp diff --git a/config.tests/bluez/main.cpp b/config.tests/bluez/main.cpp new file mode 100644 index 00000000..58d5015c --- /dev/null +++ b/config.tests/bluez/main.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <bluetooth/bluetooth.h> + +int main() +{ + return 0; +} diff --git a/connectivity.pro.user b/connectivity.pro.user new file mode 100644 index 00000000..2f5777b6 --- /dev/null +++ b/connectivity.pro.user @@ -0,0 +1,306 @@ +<!DOCTYPE QtCreatorProject> +<qtcreator> + <data> + <variable>ProjectExplorer.Project.ActiveTarget</variable> + <value type="int">0</value> + </data> + <data> + <variable>ProjectExplorer.Project.EditorSettings</variable> + <valuemap type="QVariantMap"> + <value key="EditorConfiguration.AutoIndent" type="bool">true</value> + <value key="EditorConfiguration.AutoSpacesForTabs" type="bool">false</value> + <value key="EditorConfiguration.Codec" type="QByteArray">UTF-8</value> + <value key="EditorConfiguration.DoubleIndentBlocks" type="bool">false</value> + <value key="EditorConfiguration.IndentBraces" type="bool">false</value> + <value key="EditorConfiguration.IndentSize" type="int">4</value> + <value key="EditorConfiguration.MouseNavigation" type="bool">true</value> + <value key="EditorConfiguration.PaddingMode" type="int">1</value> + <value key="EditorConfiguration.ScrollWheelZooming" type="bool">true</value> + <value key="EditorConfiguration.SmartBackspace" type="bool">false</value> + <value key="EditorConfiguration.SpacesForTabs" type="bool">true</value> + <value key="EditorConfiguration.TabKeyBehavior" type="int">0</value> + <value key="EditorConfiguration.TabSize" type="int">8</value> + <value key="EditorConfiguration.UseGlobal" type="bool">true</value> + <value key="EditorConfiguration.Utf8BomBehavior" type="int">1</value> + <value key="EditorConfiguration.addFinalNewLine" type="bool">true</value> + <value key="EditorConfiguration.cleanIndentation" type="bool">true</value> + <value key="EditorConfiguration.cleanWhitespace" type="bool">true</value> + <value key="EditorConfiguration.inEntireDocument" type="bool">false</value> + </valuemap> + </data> + <data> + <variable>ProjectExplorer.Project.Target.0</variable> + <valuemap type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.DesktopTarget</value> + <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value> + <value key="ProjectExplorer.Target.ActiveDeployConfiguration" type="int">0</value> + <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Qt in PATH Debug</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/mzanetti/Develop/connectivity-build-desktop</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Qt in PATH Release</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/mzanetti/Develop/connectivity-build-desktop</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.2" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop Qt 4.7.3 for GCC (Qt SDK) Release</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/mzanetti/Develop/connectivity-build-desktop</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">13</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.3" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop Qt 4.7.3 for GCC (Qt SDK) Debug</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/mzanetti/Develop/connectivity-build-desktop</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">13</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value> + </valuemap> + <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">4</value> + <valuemap key="ProjectExplorer.Target.DeployConfiguration.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">0</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Deploy</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Deploy</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">No deployment</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.DefaultDeployConfiguration</value> + </valuemap> + <value key="ProjectExplorer.Target.DeployConfigurationCount" type="int">1</value> + <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments" type="QString"></value> + <value key="ProjectExplorer.CustomExecutableRunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="ProjectExplorer.CustomExecutableRunConfiguration.Executable" type="QString"></value> + <value key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="ProjectExplorer.CustomExecutableRunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory" type="QString">%{buildDir}</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Custom Executable</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.CustomExecutableRunConfiguration</value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value> + </valuemap> + </data> + <data> + <variable>ProjectExplorer.Project.TargetCount</variable> + <value type="int">1</value> + </data> + <data> + <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable> + <value type="QString">{5bb02f12-fd48-41eb-b4ce-5b80d68e4d7c}</value> + </data> + <data> + <variable>ProjectExplorer.Project.Updater.FileVersion</variable> + <value type="int">9</value> + </data> +</qtcreator> diff --git a/modules/qt_bluetooth.pri b/modules/qt_bluetooth.pri new file mode 100644 index 00000000..86a0e87a --- /dev/null +++ b/modules/qt_bluetooth.pri @@ -0,0 +1,17 @@ +QT.bluetooth.VERSION = 5.0.0 +QT.bluetooth.MAJOR_VERSION = 5 +QT.bluetooth.MINOR_VERSION = 0 +QT.bluetooth.PATCH_VERSION = 0 + +QT.bluetooth.name = QtBluetooth +QT.bluetooth.bins = $$QT_MODULE_BIN_BASE +QT.bluetooth.includes = $$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/QtBluetooth +QT.bluetooth.private_includes = $$QT_MODULE_INCLUDE_BASE/QtBluetooth/$$QT.bluetooth.VERSION +QT.bluetooth.sources = $$QT_MODULE_BASE/src/bluetooth +QT.bluetooth.libs = $$QT_MODULE_LIB_BASE +QT.bluetooth.plugins = $$QT_MODULE_PLUGIN_BASE +QT.bluetooth.imports = $$QT_MODULE_IMPORT_BASE +QT.bluetooth.depends = core +QT.bluetooth.DEFINES = QT_BLUETOOTH_LIB + +QT_CONFIG += bluetooth diff --git a/modules/qt_nfc.pri b/modules/qt_nfc.pri new file mode 100644 index 00000000..47becc30 --- /dev/null +++ b/modules/qt_nfc.pri @@ -0,0 +1,17 @@ +QT.nfc.VERSION = 5.0.0 +QT.nfc.MAJOR_VERSION = 5 +QT.nfc.MINOR_VERSION = 0 +QT.nfc.PATCH_VERSION = 0 + +QT.nfc.name = QtNfc +QT.nfc.bins = $$QT_MODULE_BIN_BASE +QT.nfc.includes = $$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/QtNfc +QT.nfc.private_includes = $$QT_MODULE_INCLUDE_BASE/QtNfc/$$QT.nfc.VERSION +QT.nfc.sources = $$QT_MODULE_BASE/src/nfc +QT.nfc.libs = $$QT_MODULE_LIB_BASE +QT.nfc.plugins = $$QT_MODULE_PLUGIN_BASE +QT.nfc.imports = $$QT_MODULE_IMPORT_BASE +QT.nfc.depends = core +QT.nfc.DEFINES = QT_NFC_LIB + +QT_CONFIG += nfc diff --git a/qtconnectivity.pro b/qtconnectivity.pro new file mode 100644 index 00000000..13f8ac66 --- /dev/null +++ b/qtconnectivity.pro @@ -0,0 +1,24 @@ +TEMPLATE = subdirs +CONFIG += ordered + +module_qtconnectivity_src.subdir = src +module_qtconnectivity_src.target = module-qtconnectivity-src + +module_qtconnectivity_tests.subdir = tests +module_qtconnectivity_tests.target = module-qtconnectivity-tests +module_qtconnectivity_tests.depends = module_qtconnectivity_src +!contains(QT_BUILD_PARTS,tests) { + module_qtconnectivity_tests.CONFIG = no_default_target no_default_install +} + +module_qtconnectivity_examples.subdir = examples +module_qtconnectivity_examples.target = module-qtconnectivity-exampels +module_qtconnectivity_examples.depends = module_qtconnectivity_src +!contains(QT_BUILD_PARTS,examples) { + module_qtconnectivity_examples.CONFIG = no_default_target no_default_install + warning("No examples being used") +} + +SUBDIRS += module_qtconnectivity_src \ + module_qtconnectivity_tests \ + module_qtconnectivity_examples diff --git a/qtconnectivity.pro.user b/qtconnectivity.pro.user new file mode 100644 index 00000000..ffeb238b --- /dev/null +++ b/qtconnectivity.pro.user @@ -0,0 +1,839 @@ +<!DOCTYPE QtCreatorProject> +<qtcreator> + <data> + <variable>ProjectExplorer.Project.ActiveTarget</variable> + <value type="int">0</value> + </data> + <data> + <variable>ProjectExplorer.Project.EditorSettings</variable> + <valuemap type="QVariantMap"> + <value key="EditorConfiguration.AutoIndent" type="bool">true</value> + <value key="EditorConfiguration.AutoSpacesForTabs" type="bool">false</value> + <value key="EditorConfiguration.Codec" type="QByteArray">UTF-8</value> + <value key="EditorConfiguration.DoubleIndentBlocks" type="bool">false</value> + <value key="EditorConfiguration.IndentBraces" type="bool">false</value> + <value key="EditorConfiguration.IndentSize" type="int">4</value> + <value key="EditorConfiguration.MouseNavigation" type="bool">true</value> + <value key="EditorConfiguration.PaddingMode" type="int">1</value> + <value key="EditorConfiguration.ScrollWheelZooming" type="bool">true</value> + <value key="EditorConfiguration.SmartBackspace" type="bool">false</value> + <value key="EditorConfiguration.SpacesForTabs" type="bool">true</value> + <value key="EditorConfiguration.TabKeyBehavior" type="int">0</value> + <value key="EditorConfiguration.TabSize" type="int">8</value> + <value key="EditorConfiguration.UseGlobal" type="bool">true</value> + <value key="EditorConfiguration.Utf8BomBehavior" type="int">1</value> + <value key="EditorConfiguration.addFinalNewLine" type="bool">true</value> + <value key="EditorConfiguration.cleanIndentation" type="bool">true</value> + <value key="EditorConfiguration.cleanWhitespace" type="bool">true</value> + <value key="EditorConfiguration.inEntireDocument" type="bool">false</value> + </valuemap> + </data> + <data> + <variable>ProjectExplorer.Project.Target.0</variable> + <valuemap type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.DesktopTarget</value> + <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value> + <value key="ProjectExplorer.Target.ActiveDeployConfiguration" type="int">0</value> + <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">true</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Qt in PATH Debug</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/mzanetti/Develop/qtconnectivity-build-desktop</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Qt in PATH Release</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/mzanetti/Develop/qtconnectivity-build-desktop</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.2" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop Qt 4.7.3 for GCC (Qt SDK) Release</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/mzanetti/Develop/qtconnectivity-build-desktop</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">13</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.BuildConfiguration.3" type="QVariantMap"> + <value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qmake</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value> + <value key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary" type="bool">false</value> + <value key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QString"></value> + <value key="QtProjectManager.QMakeBuildStep.QMakeForced" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildStepList.Step.1" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString"></value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">2</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value> + </valuemap> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap"> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value> + <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value> + <value key="Qt4ProjectManager.MakeStep.MakeArguments" type="QString">clean</value> + <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value> + </valuemap> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value> + <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value> + <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop Qt 4.7.3 for GCC (Qt SDK) Debug</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/mzanetti/Develop/qtconnectivity-build-desktop</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">13</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value> + <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value> + </valuemap> + <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">4</value> + <valuemap key="ProjectExplorer.Target.DeployConfiguration.0" type="QVariantMap"> + <valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap"> + <value key="ProjectExplorer.BuildStepList.StepsCount" type="int">0</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Deploy</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Deploy</value> + </valuemap> + <value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">1</value> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">No deployment</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.DefaultDeployConfiguration</value> + </valuemap> + <value key="ProjectExplorer.Target.DeployConfigurationCount" type="int">1</value> + <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qllcpserver</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qllcpserver/qllcpserver.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.1" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">nfctestserver</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfctestserver/nfctestserver.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.10" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">btclient</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/btclient/btclient.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.11" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qnearfieldtagtype3</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qnearfieldtagtype3/qnearfieldtagtype3.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.12" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">bluetooth</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">src/bluetooth/bluetooth.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.13" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">nfc</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">src/nfc/nfc.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.14" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">src</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">src/src.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.2" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qnearfieldtagtype4</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qnearfieldtagtype4/qnearfieldtagtype4.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.3" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qnearfieldmanager</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qnearfieldmanager/qnearfieldmanager.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.4" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qnearfieldtagtype2</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qnearfieldtagtype2/qnearfieldtagtype2.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.5" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qllcpsocketremote</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qllcpsocketremote/qllcpsocketremote.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.6" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qnearfieldtagtype1</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qnearfieldtagtype1/qnearfieldtagtype1.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.7" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qllcpsocketlocal</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qllcpsocketlocal/qllcpsocketlocal.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.8" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">qllcpsockettype2</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/qllcpsockettype2/qllcpsockettype2.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <valuemap key="ProjectExplorer.Target.RunConfiguration.9" type="QVariantMap"> + <valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value> + <value key="Analyzer.Valgrind.NumCallers" type="int">25</value> + <valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/> + <value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value> + <value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value> + <valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList"> + <value type="int">0</value> + <value type="int">1</value> + <value type="int">2</value> + <value type="int">3</value> + <value type="int">4</value> + <value type="int">5</value> + <value type="int">6</value> + <value type="int">7</value> + <value type="int">8</value> + <value type="int">9</value> + <value type="int">10</value> + <value type="int">11</value> + <value type="int">12</value> + <value type="int">13</value> + <value type="int">14</value> + </valuelist> + <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">nfctestserviceprovider</value> + <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value> + <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QString"></value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.pro</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value> + <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/> + <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value> + <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value> + <value key="RunConfiguration.UseCppDebugger" type="bool">true</value> + <value key="RunConfiguration.UseQmlDebugger" type="bool">false</value> + </valuemap> + <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">15</value> + </valuemap> + </data> + <data> + <variable>ProjectExplorer.Project.TargetCount</variable> + <value type="int">1</value> + </data> + <data> + <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable> + <value type="QString">{5bb02f12-fd48-41eb-b4ce-5b80d68e4d7c}</value> + </data> + <data> + <variable>ProjectExplorer.Project.Updater.FileVersion</variable> + <value type="int">9</value> + </data> +</qtcreator> diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro new file mode 100644 index 00000000..f1b00b30 --- /dev/null +++ b/src/bluetooth/bluetooth.pro @@ -0,0 +1,162 @@ +load(qt_module) + +TARGET = QtBluetooth +QPRO_PWD = $PWD + +CONFIG += module +MODULE_PRI = ../../modules/qt_bluetooth.pri + +DEFINES += QT_BUILD_BT_LIB QT_MAKEDLL + +load(qt_module_config) + +PUBLIC_HEADERS += \ + qbluetoothaddress.h\ + qbluetoothuuid.h\ + qbluetoothdeviceinfo.h\ + qbluetoothserviceinfo.h\ + qbluetoothdevicediscoveryagent.h\ + qbluetoothservicediscoveryagent.h\ + qbluetoothsocket.h\ + qrfcommserver.h \ + ql2capserver.h \ + qbluetooth.h \ + qbluetoothlocaldevice.h \ + ql2capsocket.h \ + qrfcommsocket.h \ + qbluetoothtransfermanager.h \ + qbluetoothtransferrequest.h \ + qbluetoothtransferreply.h + +PRIVATE_HEADERS += \ + qbluetoothaddress_p.h\ + qbluetoothdeviceinfo_p.h\ + qbluetoothserviceinfo_p.h\ + qbluetoothdevicediscoveryagent_p.h\ + qbluetoothservicediscoveryagent_p.h\ + qbluetoothsocket_p.h\ + qrfcommserver_p.h \ + ql2capserver_p.h \ + qbluetoothtransferreply_p.h \ + qbluetoothtransferrequest_p.h + +SOURCES += \ + qbluetoothaddress.cpp\ + qbluetoothuuid.cpp\ + qbluetoothdeviceinfo.cpp\ + qbluetoothserviceinfo.cpp\ + qbluetoothdevicediscoveryagent.cpp\ + qbluetoothservicediscoveryagent.cpp\ + qbluetoothsocket.cpp\ + qrfcommserver.cpp \ + ql2capserver.cpp \ + qbluetoothlocaldevice.cpp \ + qbluetooth.cpp \ + ql2capsocket.cpp \ + qrfcommsocket.cpp \ + qbluetoothtransfermanager.cpp \ + qbluetoothtransferrequest.cpp \ + qbluetoothtransferreply.cpp + +symbian { + contains(S60_VERSION, 3.1) | contains(S60_VERSION, 3.2) { + DEFINES += DO_NOT_BUILD_BLUETOOTH_SYMBIAN_BACKEND + message("S60 3.1 or 3.2 sdk not supported by bluetooth") + SOURCES += \ + qbluetoothdevicediscoveryagent_p.cpp \ + qbluetoothlocaldevice_p.cpp \ + qbluetoothserviceinfo_p.cpp \ + qbluetoothservicediscoveryagent_p.cpp \ + qbluetoothsocket_p.cpp \ + ql2capserver_p.cpp \ + qrfcommserver_p.cpp \ + qbluetoothtransfermanager_p.cpp + } +} + +symbian { + !contains(DEFINES, DO_NOT_BUILD_BLUETOOTH_SYMBIAN_BACKEND) { + DEFINES += QT_SYMBIAN_BLUETOOTH + INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE + include(symbian/symbian.pri) + + PRIVATE_HEADERS += \ + qbluetoothtransferreply_symbian_p.h \ + qbluetoothlocaldevice_p.h + + SOURCES += \ + qbluetoothserviceinfo_symbian.cpp\ + qbluetoothdevicediscoveryagent_symbian.cpp\ + qbluetoothservicediscoveryagent_symbian.cpp\ + qbluetoothsocket_symbian.cpp\ + qrfcommserver_symbian.cpp \ + qbluetoothlocaldevice_symbian.cpp \ + qbluetoothtransfermanager_symbian.cpp \ + qbluetoothtransferreply_symbian.cpp \ + ql2capserver_symbian.cpp + + contains(S60_VERSION, 5.0) { + message("NOTICE - START") + message("Bluetooth backend needs SDK plugin from Forum Nokia for 5.0 SDK") + message("NOTICE - END") + LIBS *= -lirobex + } else { + LIBS *= -lobex + } + LIBS *= -lesock \ + -lbluetooth \ + -lsdpagent \ + -lsdpdatabase \ + -lestlib \ + -lbtengsettings \ + -lbtmanclient \ + -lbtdevice + } +} else:contains(config_test_bluez, yes):contains(QT_CONFIG, dbus) { + QT *= dbus + DEFINES += QT_BLUEZ_BLUETOOTH + + include(bluez/bluez.pri) + + PRIVATE_HEADERS += \ + qbluetoothtransferreply_bluez_p.h \ + qbluetoothlocaldevice_p.h + + SOURCES += \ + qbluetoothserviceinfo_bluez.cpp \ + qbluetoothdevicediscoveryagent_bluez.cpp\ + qbluetoothservicediscoveryagent_bluez.cpp \ + qbluetoothsocket_bluez.cpp \ + qrfcommserver_bluez.cpp \ + qbluetoothlocaldevice_bluez.cpp \ + qbluetoothtransferreply_bluez.cpp \ + qbluetoothtransfermanager_bluez.cpp \ + ql2capserver_bluez.cpp + + exists(/usr/include/test_framework_4711.h) { + message(Activating Nokia Bluetooth Services) + DEFINES += NOKIA_BT_SERVICES + QT += serviceframework + } + +} else { + message("Unsupported bluetooth platform, will not build a working QBluetooth library") + message("Either no Qt dBus found, no bluez headers, or not symbian") + SOURCES += \ + qbluetoothdevicediscoveryagent_p.cpp \ + qbluetoothlocaldevice_p.cpp \ + qbluetoothserviceinfo_p.cpp \ + qbluetoothservicediscoveryagent_p.cpp \ + qbluetoothsocket_p.cpp \ + ql2capserver_p.cpp \ + qrfcommserver_p.cpp \ + qbluetoothtransfermanager_p.cpp + +} + +INCLUDEPATH += $$PWD +INCLUDEPATH += .. + +OTHER_FILES += + +HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS diff --git a/src/bluetooth/bluez/adapter.cpp b/src/bluetooth/bluez/adapter.cpp new file mode 100644 index 00000000..495360d7 --- /dev/null +++ b/src/bluetooth/bluez/adapter.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p adapter_p.h:adapter.cpp org.bluez.all.xml org.bluez.Adapter + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "adapter_p.h" + +/* + * Implementation of interface class OrgBluezAdapterInterface + */ + +OrgBluezAdapterInterface::OrgBluezAdapterInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezAdapterInterface::~OrgBluezAdapterInterface() +{ +} + diff --git a/src/bluetooth/bluez/adapter_p.h b/src/bluetooth/bluez/adapter_p.h new file mode 100644 index 00000000..b4ba2b12 --- /dev/null +++ b/src/bluetooth/bluez/adapter_p.h @@ -0,0 +1,157 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p adapter_p.h:adapter.cpp org.bluez.all.xml org.bluez.Adapter + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef ADAPTER_P_H_1273205927 +#define ADAPTER_P_H_1273205927 + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.bluez.Adapter + */ +class OrgBluezAdapterInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.Adapter"; } + +public: + OrgBluezAdapterInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~OrgBluezAdapterInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> CancelDeviceCreation(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("CancelDeviceCreation"), argumentList); + } + + inline QDBusPendingReply<QDBusObjectPath> CreateDevice(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("CreateDevice"), argumentList); + } + + inline QDBusPendingReply<QDBusObjectPath> CreatePairedDevice(const QString &in0, const QDBusObjectPath &in1, const QString &in2) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2); + return asyncCallWithArgumentList(QLatin1String("CreatePairedDevice"), argumentList); + } + + inline QDBusPendingReply<QDBusObjectPath> FindDevice(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("FindDevice"), argumentList); + } + + inline QDBusPendingReply<QVariantMap> GetProperties() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + } + + inline QDBusPendingReply<QList<QDBusObjectPath> > ListDevices() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("ListDevices"), argumentList); + } + + inline QDBusPendingReply<> RegisterAgent(const QDBusObjectPath &in0, const QString &in1) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); + return asyncCallWithArgumentList(QLatin1String("RegisterAgent"), argumentList); + } + + inline QDBusPendingReply<> ReleaseMode() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("ReleaseMode"), argumentList); + } + + inline QDBusPendingReply<> ReleaseSession() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("ReleaseSession"), argumentList); + } + + inline QDBusPendingReply<> RemoveDevice(const QDBusObjectPath &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("RemoveDevice"), argumentList); + } + + inline QDBusPendingReply<> RequestMode(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("RequestMode"), argumentList); + } + + inline QDBusPendingReply<> RequestSession() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("RequestSession"), argumentList); + } + + inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); + return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList); + } + + inline QDBusPendingReply<> StartDiscovery() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("StartDiscovery"), argumentList); + } + + inline QDBusPendingReply<> StopDiscovery() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("StopDiscovery"), argumentList); + } + + inline QDBusPendingReply<> UnregisterAgent(const QDBusObjectPath &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("UnregisterAgent"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void DeviceCreated(const QDBusObjectPath &in0); + void DeviceDisappeared(const QString &in0); + void DeviceFound(const QString &in0, const QVariantMap &in1); + void DeviceRemoved(const QDBusObjectPath &in0); + void PropertyChanged(const QString &in0, const QDBusVariant &in1); +}; + +namespace org { + namespace bluez { + typedef ::OrgBluezAdapterInterface Adapter; + } +} +#endif diff --git a/src/bluetooth/bluez/agent.cpp b/src/bluetooth/bluez/agent.cpp new file mode 100644 index 00000000..491bd1e9 --- /dev/null +++ b/src/bluetooth/bluez/agent.cpp @@ -0,0 +1,87 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -c OrgBluezAgentAdaptor -a agent_p.h:agent.cpp org.bluez.Agent.xml org.bluez.Agent + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "agent_p.h" +#include <QtCore/QMetaObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> + +/* + * Implementation of adaptor class OrgBluezAgentAdaptor + */ + +OrgBluezAgentAdaptor::OrgBluezAgentAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +OrgBluezAgentAdaptor::~OrgBluezAgentAdaptor() +{ + // destructor +} + +void OrgBluezAgentAdaptor::Authorize(const QDBusObjectPath &in0, const QString &in1) +{ + // handle method call org.bluez.Agent.Authorize + QMetaObject::invokeMethod(parent(), "Authorize", Q_ARG(QDBusObjectPath, in0), Q_ARG(QString, in1)); +} + +void OrgBluezAgentAdaptor::Cancel() +{ + // handle method call org.bluez.Agent.Cancel + QMetaObject::invokeMethod(parent(), "Cancel"); +} + +void OrgBluezAgentAdaptor::ConfirmModeChange(const QString &in0) +{ + // handle method call org.bluez.Agent.ConfirmModeChange + QMetaObject::invokeMethod(parent(), "ConfirmModeChange", Q_ARG(QString, in0)); +} + +void OrgBluezAgentAdaptor::DisplayPasskey(const QDBusObjectPath &in0, uint in1, uchar in2) +{ + // handle method call org.bluez.Agent.DisplayPasskey + QMetaObject::invokeMethod(parent(), "DisplayPasskey", Q_ARG(QDBusObjectPath, in0), Q_ARG(uint, in1), Q_ARG(uchar, in2)); +} + +void OrgBluezAgentAdaptor::Release() +{ + // handle method call org.bluez.Agent.Release + QMetaObject::invokeMethod(parent(), "Release"); +} + +void OrgBluezAgentAdaptor::RequestConfirmation(const QDBusObjectPath &in0, uint in1) +{ + // handle method call org.bluez.Agent.RequestConfirmation + QMetaObject::invokeMethod(parent(), "RequestConfirmation", Q_ARG(QDBusObjectPath, in0), Q_ARG(uint, in1)); +} + +uint OrgBluezAgentAdaptor::RequestPasskey(const QDBusObjectPath &in0) +{ + // handle method call org.bluez.Agent.RequestPasskey + uint out0; + QMetaObject::invokeMethod(parent(), "RequestPasskey", Q_RETURN_ARG(uint, out0), Q_ARG(QDBusObjectPath, in0)); + return out0; +} + +QString OrgBluezAgentAdaptor::RequestPinCode(const QDBusObjectPath &in0) +{ + // handle method call org.bluez.Agent.RequestPinCode + QString out0; + QMetaObject::invokeMethod(parent(), "RequestPinCode", Q_RETURN_ARG(QString, out0), Q_ARG(QDBusObjectPath, in0)); + return out0; +} + diff --git a/src/bluetooth/bluez/agent_p.h b/src/bluetooth/bluez/agent_p.h new file mode 100644 index 00000000..3725928e --- /dev/null +++ b/src/bluetooth/bluez/agent_p.h @@ -0,0 +1,78 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -c OrgBluezAgentAdaptor -a agent_p.h:agent.cpp org.bluez.Agent.xml org.bluez.Agent + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef AGENT_P_H_1291941396 +#define AGENT_P_H_1291941396 + +#include <QtCore/QObject> +#include <QtDBus/QtDBus> +class QByteArray; +template<class T> class QList; +template<class Key, class Value> class QMap; +class QString; +class QStringList; +class QVariant; + +/* + * Adaptor class for interface org.bluez.Agent + */ +class OrgBluezAgentAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.Agent") + Q_CLASSINFO("D-Bus Introspection", "" +" <interface name=\"org.bluez.Agent\">\n" +" <method name=\"Release\"/>\n" +" <method name=\"RequestPinCode\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" <arg direction=\"out\" type=\"s\"/>\n" +" </method>\n" +" <method name=\"RequestPasskey\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" <arg direction=\"out\" type=\"u\"/>\n" +" </method>\n" +" <method name=\"DisplayPasskey\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" <arg direction=\"in\" type=\"u\"/>\n" +" <arg direction=\"in\" type=\"y\"/>\n" +" </method>\n" +" <method name=\"RequestConfirmation\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" <arg direction=\"in\" type=\"u\"/>\n" +" </method>\n" +" <method name=\"Authorize\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" <arg direction=\"in\" type=\"s\"/>\n" +" </method>\n" +" <method name=\"ConfirmModeChange\">\n" +" <arg direction=\"in\" type=\"s\"/>\n" +" </method>\n" +" <method name=\"Cancel\"/>\n" +" </interface>\n" + "") +public: + OrgBluezAgentAdaptor(QObject *parent); + virtual ~OrgBluezAgentAdaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + void Authorize(const QDBusObjectPath &in0, const QString &in1); + void Cancel(); + void ConfirmModeChange(const QString &in0); + void DisplayPasskey(const QDBusObjectPath &in0, uint in1, uchar in2); + void Release(); + void RequestConfirmation(const QDBusObjectPath &in0, uint in1); + uint RequestPasskey(const QDBusObjectPath &in0); + QString RequestPinCode(const QDBusObjectPath &in0); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/src/bluetooth/bluez/bluez.pri b/src/bluetooth/bluez/bluez.pri new file mode 100644 index 00000000..234b5ba2 --- /dev/null +++ b/src/bluetooth/bluez/bluez.pri @@ -0,0 +1,23 @@ + +HEADERS += bluez/manager_p.h \ + bluez/adapter_p.h \ + bluez/device_p.h \ + bluez/service_p.h \ + bluez/agent_p.h \ + bluez/servicemap_p.h \ + bluez/obex_client_p.h \ + bluez/obex_agent_p.h \ + bluez/obex_transfer_p.h \ + bluez/obex_manager_p.h + + +SOURCES += bluez/manager.cpp \ + bluez/adapter.cpp \ + bluez/agent.cpp \ + bluez/device.cpp \ + bluez/service.cpp \ + bluez/servicemap.cpp \ + bluez/obex_client.cpp \ + bluez/obex_agent.cpp \ + bluez/obex_transfer.cpp \ + bluez/obex_manager.cpp diff --git a/src/bluetooth/bluez/device.cpp b/src/bluetooth/bluez/device.cpp new file mode 100644 index 00000000..fa3f7c44 --- /dev/null +++ b/src/bluetooth/bluez/device.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -i servicemap_p.h -p device_p.h:device.cpp org.bluez.Device.xml org.bluez.Device + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "device_p.h" + +/* + * Implementation of interface class OrgBluezDeviceInterface + */ + +OrgBluezDeviceInterface::OrgBluezDeviceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezDeviceInterface::~OrgBluezDeviceInterface() +{ +} + diff --git a/src/bluetooth/bluez/device_p.h b/src/bluetooth/bluez/device_p.h new file mode 100644 index 00000000..26a00828 --- /dev/null +++ b/src/bluetooth/bluez/device_p.h @@ -0,0 +1,104 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -i servicemap_p.h -p device_p.h:device.cpp org.bluez.Device.xml org.bluez.Device + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef DEVICE_P_H_1273205927 +#define DEVICE_P_H_1273205927 + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> +#include "servicemap_p.h" + +/* + * Proxy class for interface org.bluez.Device + */ +class OrgBluezDeviceInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.Device"; } + +public: + OrgBluezDeviceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~OrgBluezDeviceInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> CancelDiscovery() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("CancelDiscovery"), argumentList); + } + + inline QDBusPendingReply<QDBusObjectPath> CreateNode(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("CreateNode"), argumentList); + } + + inline QDBusPendingReply<> Disconnect() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("Disconnect"), argumentList); + } + + inline QDBusPendingReply<ServiceMap> DiscoverServices(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("DiscoverServices"), argumentList); + } + + inline QDBusPendingReply<QVariantMap> GetProperties() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + } + + inline QDBusPendingReply<QList<QDBusObjectPath> > ListNodes() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("ListNodes"), argumentList); + } + + inline QDBusPendingReply<> RemoveNode(const QDBusObjectPath &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("RemoveNode"), argumentList); + } + + inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); + return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void DisconnectRequested(); + void NodeCreated(const QDBusObjectPath &in0); + void NodeRemoved(const QDBusObjectPath &in0); + void PropertyChanged(const QString &in0, const QDBusVariant &in1); +}; + +namespace org { + namespace bluez { + typedef ::OrgBluezDeviceInterface Device; + } +} +#endif diff --git a/src/bluetooth/bluez/generate b/src/bluetooth/bluez/generate new file mode 100755 index 00000000..14bcaea8 --- /dev/null +++ b/src/bluetooth/bluez/generate @@ -0,0 +1,16 @@ +#!/bin/sh + +qdbusxml2cpp -p manager_p.h:manager.cpp org.bluez.Manager.xml org.bluez.Manager +qdbusxml2cpp -p adapter_p.h:adapter.cpp org.bluez.all.xml org.bluez.Adapter +qdbusxml2cpp -i servicemap_p.h -p device_p.h:device.cpp org.bluez.Device.xml org.bluez.Device +qdbusxml2cpp -p service_p.h:service.cpp org.bluez.all.xml org.bluez.Service +qdbusxml2cpp -c OrgBluezAgentAdaptor -a agent_p.h:agent.cpp org.bluez.Agent.xml org.bluez.Agent +qdbusxml2cpp -p obex_manager_p.h:obex_manager.cpp org.openobex.all.xml org.openobex.Manager +qdbusxml2cpp -p obex_client_p.h:obex_client.cpp org.openobex.client.xml org.openobex.Client +qdbusxml2cpp -p obex_transfer_p.h:obex_transfer.cpp org.openobex.transfer.xml org.openobex.Transfer +qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml org.openobex.Agent +#qdbusxml2cpp -p serialproxymanager_p.h:serialproxymanager.cpp org.bluez.all.xml org.bluez.SerialProxyManager +#qdbusxml2cpp -p networkpeer_p.h:networkpeer.cpp org.bluez.all.xml org.bluez.NetworkPeer +#qdbusxml2cpp -p networkhub_p.h:networkhub.cpp org.bluez.all.xml org.bluez.NetworkHub +#qdbusxml2cpp -p networkrouter_p.h:networkrouter.cpp org.bluez.all.xml org.bluez.NetworkRouter + diff --git a/src/bluetooth/bluez/manager.cpp b/src/bluetooth/bluez/manager.cpp new file mode 100644 index 00000000..474ed694 --- /dev/null +++ b/src/bluetooth/bluez/manager.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p manager_p.h:manager.cpp org.bluez.Manager.xml org.bluez.Manager + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "manager_p.h" + +/* + * Implementation of interface class OrgBluezManagerInterface + */ + +OrgBluezManagerInterface::OrgBluezManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezManagerInterface::~OrgBluezManagerInterface() +{ +} + diff --git a/src/bluetooth/bluez/manager_p.h b/src/bluetooth/bluez/manager_p.h new file mode 100644 index 00000000..da38f733 --- /dev/null +++ b/src/bluetooth/bluez/manager_p.h @@ -0,0 +1,69 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p manager_p.h:manager.cpp org.bluez.Manager.xml org.bluez.Manager + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef MANAGER_P_H_1273205927 +#define MANAGER_P_H_1273205927 + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.bluez.Manager + */ +class OrgBluezManagerInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.Manager"; } + +public: + OrgBluezManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~OrgBluezManagerInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<QDBusObjectPath> DefaultAdapter() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("DefaultAdapter"), argumentList); + } + + inline QDBusPendingReply<QDBusObjectPath> FindAdapter(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("FindAdapter"), argumentList); + } + + inline QDBusPendingReply<QList<QDBusObjectPath> > ListAdapters() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("ListAdapters"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void AdapterAdded(const QDBusObjectPath &in0); + void AdapterRemoved(const QDBusObjectPath &in0); + void DefaultAdapterChanged(const QDBusObjectPath &in0); +}; + +namespace org { + namespace bluez { + typedef ::OrgBluezManagerInterface Manager; + } +} +#endif diff --git a/src/bluetooth/bluez/obex_agent.cpp b/src/bluetooth/bluez/obex_agent.cpp new file mode 100644 index 00000000..c4895065 --- /dev/null +++ b/src/bluetooth/bluez/obex_agent.cpp @@ -0,0 +1,67 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "obex_agent_p.h" +#include <QtCore/QMetaObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> + +/* + * Implementation of adaptor class AgentAdaptor + */ + +AgentAdaptor::AgentAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +AgentAdaptor::~AgentAdaptor() +{ + // destructor +} + +void AgentAdaptor::Complete(const QDBusObjectPath &in0) +{ + // handle method call org.openobex.Agent.Complete + QMetaObject::invokeMethod(parent(), "Complete", Q_ARG(QDBusObjectPath, in0)); +} + +void AgentAdaptor::Error(const QDBusObjectPath &in0, const QString &in1) +{ + // handle method call org.openobex.Agent.Error + QMetaObject::invokeMethod(parent(), "Error", Q_ARG(QDBusObjectPath, in0), Q_ARG(QString, in1)); +} + +void AgentAdaptor::Progress(const QDBusObjectPath &in0, qulonglong in1) +{ + // handle method call org.openobex.Agent.Progress + QMetaObject::invokeMethod(parent(), "Progress", Q_ARG(QDBusObjectPath, in0), Q_ARG(qulonglong, in1)); +} + +void AgentAdaptor::Release() +{ + // handle method call org.openobex.Agent.Release + QMetaObject::invokeMethod(parent(), "Release"); +} + +QString AgentAdaptor::Request(const QDBusObjectPath &in0) +{ + // handle method call org.openobex.Agent.Request + QString out0; + QMetaObject::invokeMethod(parent(), "Request", Q_RETURN_ARG(QString, out0), Q_ARG(QDBusObjectPath, in0)); + return out0; +} + diff --git a/src/bluetooth/bluez/obex_agent_p.h b/src/bluetooth/bluez/obex_agent_p.h new file mode 100644 index 00000000..11630093 --- /dev/null +++ b/src/bluetooth/bluez/obex_agent_p.h @@ -0,0 +1,65 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef OBEX_AGENT_P_H_1291359033 +#define OBEX_AGENT_P_H_1291359033 + +#include <QtCore/QObject> +#include <QtDBus/QtDBus> +class QByteArray; +template<class T> class QList; +template<class Key, class Value> class QMap; +class QString; +class QStringList; +class QVariant; + +/* + * Adaptor class for interface org.openobex.Agent + */ +class AgentAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.openobex.Agent") + Q_CLASSINFO("D-Bus Introspection", "" +" <interface name=\"org.openobex.Agent\">\n" +" <method name=\"Release\"/>\n" +" <method name=\"Request\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" <arg direction=\"out\" type=\"s\"/>\n" +" </method>\n" +" <method name=\"Progress\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" <arg direction=\"in\" type=\"t\"/>\n" +" </method>\n" +" <method name=\"Complete\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" </method>\n" +" <method name=\"Error\">\n" +" <arg direction=\"in\" type=\"o\"/>\n" +" <arg direction=\"in\" type=\"s\"/>\n" +" </method>\n" +" </interface>\n" + "") +public: + AgentAdaptor(QObject *parent); + virtual ~AgentAdaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + void Complete(const QDBusObjectPath &in0); + void Error(const QDBusObjectPath &in0, const QString &in1); + void Progress(const QDBusObjectPath &in0, qulonglong in1); + void Release(); + QString Request(const QDBusObjectPath &in0); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/src/bluetooth/bluez/obex_client.cpp b/src/bluetooth/bluez/obex_client.cpp new file mode 100644 index 00000000..aaf63532 --- /dev/null +++ b/src/bluetooth/bluez/obex_client.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p obex_client_p.h:obex_client.cpp org.openobex.client.xml org.openobex.Client + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "obex_client_p.h" + +/* + * Implementation of interface class OrgOpenobexClientInterface + */ + +OrgOpenobexClientInterface::OrgOpenobexClientInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgOpenobexClientInterface::~OrgOpenobexClientInterface() +{ +} + diff --git a/src/bluetooth/bluez/obex_client_p.h b/src/bluetooth/bluez/obex_client_p.h new file mode 100644 index 00000000..fa6b1f67 --- /dev/null +++ b/src/bluetooth/bluez/obex_client_p.h @@ -0,0 +1,82 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p obex_client_p.h:obex_client.cpp org.openobex.client.xml org.openobex.Client + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef OBEX_CLIENT_P_H_1291349694 +#define OBEX_CLIENT_P_H_1291349694 + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.openobex.Client + */ +class OrgOpenobexClientInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.openobex.Client"; } + +public: + OrgOpenobexClientInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~OrgOpenobexClientInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<QDBusObjectPath> CreateSession(const QVariantMap &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("CreateSession"), argumentList); + } + + inline QDBusPendingReply<> ExchangeBusinessCards(const QVariantMap &in0, const QString &in1, const QString &in2) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2); + return asyncCallWithArgumentList(QLatin1String("ExchangeBusinessCards"), argumentList); + } + + inline QDBusPendingReply<QString> GetCapabilities(const QVariantMap &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("GetCapabilities"), argumentList); + } + + inline QDBusPendingReply<> PullBusinessCard(const QVariantMap &in0, const QString &in1) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); + return asyncCallWithArgumentList(QLatin1String("PullBusinessCard"), argumentList); + } + + inline QDBusPendingReply<> SendFiles(const QVariantMap &in0, const QStringList &in1, const QDBusObjectPath &in2) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2); + return asyncCallWithArgumentList(QLatin1String("SendFiles"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace openobex { + typedef ::OrgOpenobexClientInterface Client; + } +} +#endif diff --git a/src/bluetooth/bluez/obex_manager.cpp b/src/bluetooth/bluez/obex_manager.cpp new file mode 100644 index 00000000..7192aba8 --- /dev/null +++ b/src/bluetooth/bluez/obex_manager.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p obex_manager_p.h:obex_manager.cpp org.openobex.all.xml org.openobex.Manager + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "obex_manager_p.h" + +/* + * Implementation of interface class OrgOpenobexManagerInterface + */ + +OrgOpenobexManagerInterface::OrgOpenobexManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgOpenobexManagerInterface::~OrgOpenobexManagerInterface() +{ +} + diff --git a/src/bluetooth/bluez/obex_manager_p.h b/src/bluetooth/bluez/obex_manager_p.h new file mode 100644 index 00000000..673a0e7e --- /dev/null +++ b/src/bluetooth/bluez/obex_manager_p.h @@ -0,0 +1,65 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p obex_manager_p.h:obex_manager.cpp org.openobex.all.xml org.openobex.Manager + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef OBEX_MANAGER_P_H_1291186314 +#define OBEX_MANAGER_P_H_1291186314 + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.openobex.Manager + */ +class OrgOpenobexManagerInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.openobex.Manager"; } + +public: + OrgOpenobexManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~OrgOpenobexManagerInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> RegisterAgent(const QDBusObjectPath &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("RegisterAgent"), argumentList); + } + + inline QDBusPendingReply<> UnregisterAgent(const QDBusObjectPath &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("UnregisterAgent"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void SessionCreated(const QDBusObjectPath &in0); + void SessionRemoved(const QDBusObjectPath &in0); + void TransferCompleted(const QDBusObjectPath &in0, bool in1); + void TransferStarted(const QDBusObjectPath &in0); +}; + +namespace org { + namespace openobex { + typedef ::OrgOpenobexManagerInterface Manager; + } +} +#endif diff --git a/src/bluetooth/bluez/obex_transfer.cpp b/src/bluetooth/bluez/obex_transfer.cpp new file mode 100644 index 00000000..9fad44e1 --- /dev/null +++ b/src/bluetooth/bluez/obex_transfer.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p obex_transfer_p.h:obex_transfer.cpp org.openobex.transfer.xml org.openobex.Transfer + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "obex_transfer_p.h" + +/* + * Implementation of interface class OrgOpenobexTransferInterface + */ + +OrgOpenobexTransferInterface::OrgOpenobexTransferInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgOpenobexTransferInterface::~OrgOpenobexTransferInterface() +{ +} + diff --git a/src/bluetooth/bluez/obex_transfer_p.h b/src/bluetooth/bluez/obex_transfer_p.h new file mode 100644 index 00000000..8b4fe3fd --- /dev/null +++ b/src/bluetooth/bluez/obex_transfer_p.h @@ -0,0 +1,59 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p obex_transfer_p.h:obex_transfer.cpp org.openobex.transfer.xml org.openobex.Transfer + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef OBEX_TRANSFER_P_H_1291853849 +#define OBEX_TRANSFER_P_H_1291853849 + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.openobex.Transfer + */ +class OrgOpenobexTransferInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.openobex.Transfer"; } + +public: + OrgOpenobexTransferInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~OrgOpenobexTransferInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> Cancel() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("Cancel"), argumentList); + } + + inline QDBusPendingReply<QVariantMap> GetProperties() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace openobex { + typedef ::OrgOpenobexTransferInterface Transfer; + } +} +#endif diff --git a/src/bluetooth/bluez/org.bluez.Agent.xml b/src/bluetooth/bluez/org.bluez.Agent.xml new file mode 100644 index 00000000..9a77eb1b --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.Agent.xml @@ -0,0 +1,32 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/"> + <interface name="org.bluez.Agent"> + <method name="Release" /> + <method name="RequestPinCode"> + <arg type="o" direction="in"/> + <arg type="s" direction="out"/> + </method> + <method name="RequestPasskey"> + <arg type="o" direction="in"/> + <arg type="u" direction="out"/> + </method> + <method name="DisplayPasskey"> + <arg type="o" direction="in"/> + <arg type="u" direction="in"/> + <arg type="y" direction="in"/> + </method> + <method name="RequestConfirmation"> + <arg type="o" direction="in"/> + <arg type="u" direction="in"/> + </method> + <method name="Authorize"> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="ConfirmModeChange"> + <arg type="s" direction="in"/> + </method> + <method name="Cancel" /> + </interface> + <node name="org"/> +</node> diff --git a/src/bluetooth/bluez/org.bluez.Device.xml b/src/bluetooth/bluez/org.bluez.Device.xml new file mode 100644 index 00000000..42351c97 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.Device.xml @@ -0,0 +1,41 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/org/bluez/3003/hci0/dev_XX_XX_XX_XX_XX_XX"> + <interface name="org.bluez.Device"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <method name="DiscoverServices"> + <arg type="s" direction="in"/> + <arg type="a{us}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="ServiceMap"/> + </method> + <method name="CancelDiscovery"/> + <method name="Disconnect"/> + <method name="ListNodes"> + <arg type="ao" direction="out"/> + </method> + <method name="CreateNode"> + <arg type="s" direction="in"/> + <arg type="o" direction="out"/> + </method> + <method name="RemoveNode"> + <arg type="o" direction="in"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + <signal name="DisconnectRequested"/> + <signal name="NodeCreated"> + <arg type="o"/> + </signal> + <signal name="NodeRemoved"> + <arg type="o"/> + </signal> + </interface> +</node> diff --git a/src/bluetooth/bluez/org.bluez.Manager.xml b/src/bluetooth/bluez/org.bluez.Manager.xml new file mode 100644 index 00000000..60b9baba --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.Manager.xml @@ -0,0 +1,25 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/"> + <interface name="org.bluez.Manager"> + <method name="DefaultAdapter"> + <arg type="o" direction="out"/> + </method> + <method name="FindAdapter"> + <arg type="s" direction="in"/> + <arg type="o" direction="out"/> + </method> + <method name="ListAdapters"> + <arg type="ao" direction="out"/> + </method> + <signal name="AdapterAdded"> + <arg type="o"/> + </signal> + <signal name="AdapterRemoved"> + <arg type="o"/> + </signal> + <signal name="DefaultAdapterChanged"> + <arg type="o"/> + </signal> + </interface> + <node name="org"/> +</node> diff --git a/src/bluetooth/bluez/org.bluez.Service.xml b/src/bluetooth/bluez/org.bluez.Service.xml new file mode 100644 index 00000000..e18516a3 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.Service.xml @@ -0,0 +1,21 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/org/bluez/3003/any"> + <interface name="org.bluez.Service"> + <method name="AddRecord"> + <arg type="s" direction="in"/> + <arg type="u" direction="out"/> + </method> + <method name="UpdateRecord"> + <arg type="u" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="RemoveRecord"> + <arg type="u" direction="in"/> + </method> + <method name="RequestAuthorization"> + <arg type="s" direction="in"/> + <arg type="u" direction="in"/> + </method> + <method name="CancelAuthorization"/> + </interface> +</node> diff --git a/src/bluetooth/bluez/org.bluez.all.xml b/src/bluetooth/bluez/org.bluez.all.xml new file mode 100644 index 00000000..b48a01f3 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.all.xml @@ -0,0 +1,145 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/org/bluez/3003/hci0"> + <interface name="org.bluez.Adapter"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <method name="RequestMode"> + <arg type="s" direction="in"/> + </method> + <method name="ReleaseMode"/> + <method name="RequestSession"/> + <method name="ReleaseSession"/> + <method name="StartDiscovery"/> + <method name="StopDiscovery"/> + <method name="ListDevices"> + <arg type="ao" direction="out"/> + </method> + <method name="CreateDevice"> + <arg type="s" direction="in"/> + <arg type="o" direction="out"/> + </method> + <method name="CreatePairedDevice"> + <arg type="s" direction="in"/> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + <arg type="o" direction="out"/> + </method> + <method name="CancelDeviceCreation"> + <arg type="s" direction="in"/> + </method> + <method name="RemoveDevice"> + <arg type="o" direction="in"/> + </method> + <method name="FindDevice"> + <arg type="s" direction="in"/> + <arg type="o" direction="out"/> + </method> + <method name="RegisterAgent"> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="UnregisterAgent"> + <arg type="o" direction="in"/> + </method> + <signal name="DeviceCreated"> + <arg type="o"/> + </signal> + <signal name="DeviceRemoved"> + <arg type="o"/> + </signal> + <signal name="DeviceFound"> + <arg type="s"/> + <arg type="a{sv}"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QVariantMap"/> + </signal> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + <signal name="DeviceDisappeared"> + <arg type="s"/> + </signal> + </interface> + <interface name="org.bluez.Service"> + <method name="AddRecord"> + <arg type="s" direction="in"/> + <arg type="u" direction="out"/> + </method> + <method name="UpdateRecord"> + <arg type="u" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="RemoveRecord"> + <arg type="u" direction="in"/> + </method> + <method name="RequestAuthorization"> + <arg type="s" direction="in"/> + <arg type="u" direction="in"/> + </method> + <method name="CancelAuthorization"/> + </interface> + <interface name="org.bluez.SerialProxyManager"> + <method name="CreateProxy"> + <arg type="s" direction="in"/> + <arg type="s" direction="in"/> + <arg type="s" direction="out"/> + </method> + <method name="ListProxies"> + <arg type="as" direction="out"/> + </method> + <method name="RemoveProxy"> + <arg type="s" direction="in"/> + </method> + <signal name="ProxyCreated"> + <arg type="s"/> + </signal> + <signal name="ProxyRemoved"> + <arg type="s"/> + </signal> + </interface> + <interface name="org.bluez.NetworkPeer"> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + </interface> + <interface name="org.bluez.NetworkHub"> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + </interface> + <interface name="org.bluez.NetworkRouter"> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + </interface> +</node> diff --git a/src/bluetooth/bluez/org.openobex.agent.xml b/src/bluetooth/bluez/org.openobex.agent.xml new file mode 100644 index 00000000..d21f3149 --- /dev/null +++ b/src/bluetooth/bluez/org.openobex.agent.xml @@ -0,0 +1,24 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.openobex.Agent"> + <method name="Release"> + </method> + <method name="Request"> + <arg type="o" direction="in"/> + <arg type="s" direction="out"/> + </method> + <method name="Progress"> + <arg type="o" direction="in"/> + <arg type="t" direction="in"/> + </method> + <method name="Complete"> + <arg type="o" direction="in"/> + </method> + <method name="Error"> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + </method> + </interface> +</node> + diff --git a/src/bluetooth/bluez/org.openobex.all.xml b/src/bluetooth/bluez/org.openobex.all.xml new file mode 100644 index 00000000..4e5b65b2 --- /dev/null +++ b/src/bluetooth/bluez/org.openobex.all.xml @@ -0,0 +1,31 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/"> + <interface name="org.freedesktop.DBus.Introspectable"> + <method name="Introspect"> + <arg type="s" direction="out"/> + </method> + </interface> + <interface name="org.openobex.Manager"> + <method name="RegisterAgent"> + <arg type="o" direction="in"/> + </method> + <method name="UnregisterAgent"> + <arg type="o" direction="in"/> + </method> + <signal name="TransferStarted"> + <arg type="o"/> + </signal> + <signal name="TransferCompleted"> + <arg type="o"/> + <arg type="b"/> + </signal> + <signal name="SessionCreated"> + <arg type="o"/> + </signal> + <signal name="SessionRemoved"> + <arg type="o"/> + </signal> + </interface> +</node> + diff --git a/src/bluetooth/bluez/org.openobex.client.xml b/src/bluetooth/bluez/org.openobex.client.xml new file mode 100644 index 00000000..fad2f6ef --- /dev/null +++ b/src/bluetooth/bluez/org.openobex.client.xml @@ -0,0 +1,40 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/"> + <interface name="org.freedesktop.DBus.Introspectable"> + <method name="Introspect"> + <arg type="s" direction="out"/> + </method> + </interface> + <interface name="org.openobex.Client"> + <method name="SendFiles"> + <arg type="a{sv}" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QVariantMap"/> + <arg type="as" direction="in"/> + <arg type="o" direction="in"/> + </method> + <method name="PullBusinessCard"> + <arg type="a{sv}" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QVariantMap"/> + <arg type="s" direction="in"/> + </method> + <method name="ExchangeBusinessCards"> + <arg type="a{sv}" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QVariantMap"/> + <arg type="s" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="CreateSession"> + <arg type="a{sv}" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QVariantMap"/> + <arg type="o" direction="out"/> + </method> + <method name="GetCapabilities"> + <arg type="a{sv}" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QVariantMap"/> + <arg type="s" direction="out"/> + </method> + </interface> + <node name="org"/> +</node> + diff --git a/src/bluetooth/bluez/org.openobex.transfer.xml b/src/bluetooth/bluez/org.openobex.transfer.xml new file mode 100644 index 00000000..21033665 --- /dev/null +++ b/src/bluetooth/bluez/org.openobex.transfer.xml @@ -0,0 +1,19 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/"> + <interface name="org.freedesktop.DBus.Introspectable"> + <method name="Introspect"> + <arg type="s" direction="out"/> + </method> + </interface> + <interface name="org.openobex.Transfer"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="Cancel"> + </method> + </interface> + <node name="org"/> +</node> + diff --git a/src/bluetooth/bluez/service.cpp b/src/bluetooth/bluez/service.cpp new file mode 100644 index 00000000..811eb2fd --- /dev/null +++ b/src/bluetooth/bluez/service.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p service_p.h:service.cpp org.bluez.all.xml org.bluez.Service + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "service_p.h" + +/* + * Implementation of interface class OrgBluezServiceInterface + */ + +OrgBluezServiceInterface::OrgBluezServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezServiceInterface::~OrgBluezServiceInterface() +{ +} + diff --git a/src/bluetooth/bluez/service_p.h b/src/bluetooth/bluez/service_p.h new file mode 100644 index 00000000..dd0f69d6 --- /dev/null +++ b/src/bluetooth/bluez/service_p.h @@ -0,0 +1,81 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p service_p.h:service.cpp org.bluez.all.xml org.bluez.Service + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef SERVICE_P_H_1277421939 +#define SERVICE_P_H_1277421939 + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.bluez.Service + */ +class OrgBluezServiceInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.Service"; } + +public: + OrgBluezServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~OrgBluezServiceInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<uint> AddRecord(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("AddRecord"), argumentList); + } + + inline QDBusPendingReply<> CancelAuthorization() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("CancelAuthorization"), argumentList); + } + + inline QDBusPendingReply<> RemoveRecord(uint in0) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0); + return asyncCallWithArgumentList(QLatin1String("RemoveRecord"), argumentList); + } + + inline QDBusPendingReply<> RequestAuthorization(const QString &in0, uint in1) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); + return asyncCallWithArgumentList(QLatin1String("RequestAuthorization"), argumentList); + } + + inline QDBusPendingReply<> UpdateRecord(uint in0, const QString &in1) + { + QList<QVariant> argumentList; + argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); + return asyncCallWithArgumentList(QLatin1String("UpdateRecord"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + typedef ::OrgBluezServiceInterface Service; + } +} +#endif diff --git a/src/bluetooth/bluez/servicemap.cpp b/src/bluetooth/bluez/servicemap.cpp new file mode 100644 index 00000000..5e9a2995 --- /dev/null +++ b/src/bluetooth/bluez/servicemap.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "servicemap_p.h" + +const QDBusArgument &operator>>(const QDBusArgument &argument, ServiceMap &serviceMap) +{ + argument.beginMap(); + + while (!argument.atEnd()) { + quint32 uuid; + QString service; + + argument.beginMapEntry(); + argument >> uuid; + argument >> service; + argument.endMapEntry(); + + serviceMap.insert(uuid, service); + } + + argument.endMap(); + + return argument; +} diff --git a/src/bluetooth/bluez/servicemap_p.h b/src/bluetooth/bluez/servicemap_p.h new file mode 100644 index 00000000..4504d4d6 --- /dev/null +++ b/src/bluetooth/bluez/servicemap_p.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SERVICEMAP_P_H +#define SERVICEMAP_P_H + +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtDBus/QDBusArgument> + +typedef QMap<quint32, QString> ServiceMap; + +const QDBusArgument &operator>>(const QDBusArgument &argument, ServiceMap &serviceMap); + +Q_DECLARE_METATYPE(ServiceMap) + +#endif // SERVICEMAP_P_H diff --git a/src/bluetooth/qbluetooth.cpp b/src/bluetooth/qbluetooth.cpp new file mode 100644 index 00000000..89b6b89b --- /dev/null +++ b/src/bluetooth/qbluetooth.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetooth.h" + +/*! + \namespace QBluetooth + \brief The QBluetooth namespace contains functions and definitions related to Bluetooth. + \since 5.0 + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity +*/ + +/*! + \enum QBluetooth::Security + + This enum describe the security requirements of a Bluetooth service. + + \value NoSecurity The service does not require any security. + + \value Authorization The service requires authorization. Device does not + have to paired, the connection will be granted by prompting the user unless + the device is Authorized-Paired where the connection will be made + automatically. + + \value Authentication The service requires authentication. Device must + paired, the user maybe prompted on connection unless the device is + Authorized-Paired. + + \value Encryption The service requires that the communications link be + encrypted. This requires the device be paired. + + \value Secure The service requires that the communications link be secure. + Legacy pairing is not permitted, Simple Pairing from Bluetooth 2.1 or + greater is required. +*/ diff --git a/src/bluetooth/qbluetooth.h b/src/bluetooth/qbluetooth.h new file mode 100644 index 00000000..f79c71a9 --- /dev/null +++ b/src/bluetooth/qbluetooth.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QBLUETOOTH_H +#define QBLUETOOTH_H + +#include "../qtconnectivityglobal.h" + +QT_BEGIN_HEADER + +namespace QBluetooth { +enum Security { + NoSecurity = 0x00, + Authorization = 0x01, + Authentication = 0x02, + Encryption = 0x04, + Secure = 0x08 +}; + +Q_DECLARE_FLAGS(SecurityFlags, Security) + +Q_DECLARE_OPERATORS_FOR_FLAGS(SecurityFlags) + +} + +QT_END_HEADER + +#endif // QBLUETOOTH_H diff --git a/src/bluetooth/qbluetoothaddress.cpp b/src/bluetooth/qbluetoothaddress.cpp new file mode 100644 index 00000000..d5467b9f --- /dev/null +++ b/src/bluetooth/qbluetoothaddress.cpp @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothaddress.h" +#include "qbluetoothaddress_p.h" + +/*! + \class QBluetoothAddress + \brief The QBluetoothAddress class provides a Bluetooth address. + \since 5.0 + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + + This class holds a Bluetooth address in a platform- and protocol- independent manner. +*/ + +/*! + \fn inline bool QBluetoothAddress::operator!=(const QBluetoothAddress &other) const + + + Compares this Bluetooth address with \a other. + + Returns true if the Bluetooth addresses are not equal, otherwise returns false. +*/ + +namespace +{ +class BluetoothAddressRegisterMetaTypes +{ +public: + BluetoothAddressRegisterMetaTypes() + { + qRegisterMetaType<QBluetoothAddress>("QBluetoothAddress"); + } +} _registerBluetoothAddressMetaTypes; +} + +/*! + Constructs an null Bluetooth address. +*/ +QBluetoothAddress::QBluetoothAddress() + : d_ptr(new QBluetoothAddressPrivate) +{ +} + +/*! + Constructs a new Bluetooth address and assigns \a address to it. +*/ +QBluetoothAddress::QBluetoothAddress(quint64 address) + : d_ptr(new QBluetoothAddressPrivate) +{ + Q_D(QBluetoothAddress); + d->m_address = address; +} + +/*! + Constructs a new Bluetooth address and assigns \a address to it. + + The format of \a address can be either XX:XX:XX:XX:XX:XX or XXXXXXXXXXXX, + where X is a hexadecimal digit. Case is not important. +*/ +QBluetoothAddress::QBluetoothAddress(const QString &address) + : d_ptr(new QBluetoothAddressPrivate) +{ + Q_D(QBluetoothAddress); + + QString a = address; + + if (a.length() == 17) + a.remove(QLatin1Char(':')); + + if (a.length() == 12) { + bool ok; + d->m_address = a.toULongLong(&ok, 16); + if (!ok) + clear(); + } else { + d->m_address = 0; + } +} + +/*! + Constructs a new Bluetooth address which is a copy of \a other. +*/ +QBluetoothAddress::QBluetoothAddress(const QBluetoothAddress &other) + : d_ptr(new QBluetoothAddressPrivate) +{ + *this = other; +} + +/*! + Destroys the QBluetoothAddress. +*/ +QBluetoothAddress::~QBluetoothAddress() +{ + delete d_ptr; +} + +/*! + Assigns \a other to this Bluetooth address. +*/ +QBluetoothAddress &QBluetoothAddress::operator=(const QBluetoothAddress &other) +{ + Q_D(QBluetoothAddress); + + d->m_address = other.d_func()->m_address; + + return *this; +} + +/*! + Sets the Bluetooth address to 00:00:00:00:00:00. +*/ +void QBluetoothAddress::clear() +{ + Q_D(QBluetoothAddress); + d->m_address = 0; +} + +/*! + Returns true if the Bluetooth address is valid, otherwise returns false. +*/ +bool QBluetoothAddress::isNull() const +{ + Q_D(const QBluetoothAddress); + return d->m_address == 0; +} + +/*! + Returns true if the Bluetooth address is less than \a other; otherwise + returns false. +*/ +bool QBluetoothAddress::operator<(const QBluetoothAddress &other) const +{ + Q_D(const QBluetoothAddress); + return d->m_address < other.d_func()->m_address; +} + +/*! + Compares this Bluetooth address to \a other. + + Returns true if the Bluetooth address are equal, otherwise returns false. +*/ +bool QBluetoothAddress::operator==(const QBluetoothAddress &other) const +{ + Q_D(const QBluetoothAddress); + return d->m_address == other.d_func()->m_address; +} + +/*! + Returns this Bluetooth address as a quint64. +*/ +quint64 QBluetoothAddress::toUInt64() const +{ + Q_D(const QBluetoothAddress); + return d->m_address; +} + +/*! + Returns the Bluetooth address as a string of the form XX:XX:XX:XX:XX:XX. +*/ +QString QBluetoothAddress::toString() const +{ + QString s(QLatin1String("%1:%2:%3:%4:%5:%6")); + Q_D(const QBluetoothAddress); + + for (int i = 5; i >= 0; --i) { + const quint8 a = (d->m_address >> (i*8)) & 0xff; + s = s.arg(a, 2, 16, QLatin1Char('0')); + } + + return s.toUpper(); +} + +QBluetoothAddressPrivate::QBluetoothAddressPrivate() +{ + m_address = 0; +} diff --git a/src/bluetooth/qbluetoothaddress.h b/src/bluetooth/qbluetoothaddress.h new file mode 100644 index 00000000..1ba79bad --- /dev/null +++ b/src/bluetooth/qbluetoothaddress.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHADDRESS_H +#define QBLUETOOTHADDRESS_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QByteArray> +#include <QtCore/QString> +#include <QtCore/QMetaType> + +QT_BEGIN_HEADER + +class QBluetoothAddressPrivate; + +class Q_CONNECTIVITY_EXPORT QBluetoothAddress +{ +public: + QBluetoothAddress(); + explicit QBluetoothAddress(quint64 address); + explicit QBluetoothAddress(const QString &address); + QBluetoothAddress(const QBluetoothAddress &other); + ~QBluetoothAddress(); + + QBluetoothAddress &operator=(const QBluetoothAddress &other); + + bool isNull() const; + + void clear(); + + bool operator<(const QBluetoothAddress &other) const; + bool operator==(const QBluetoothAddress &other) const; + inline bool operator!=(const QBluetoothAddress &other) const { return !operator==(other); } + + quint64 toUInt64() const; + QString toString() const; + +private: + Q_DECLARE_PRIVATE(QBluetoothAddress) + QBluetoothAddressPrivate *d_ptr; +}; + +Q_DECLARE_METATYPE(QBluetoothAddress) + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothaddress_p.h b/src/bluetooth/qbluetoothaddress_p.h new file mode 100644 index 00000000..f7d1073e --- /dev/null +++ b/src/bluetooth/qbluetoothaddress_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHADDRESS_P_H +#define QBLUETOOTHADDRESS_P_H + +#include "qbluetoothaddress.h" + +QT_BEGIN_HEADER + +class QBluetoothAddressPrivate +{ +public: + QBluetoothAddressPrivate(); + + + quint64 m_address; + +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp new file mode 100644 index 00000000..342c8d3d --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdevicediscoveryagent_p.h" + +/*! + \class QBluetoothDeviceDiscoveryAgent + \brief The QBluetoothDeviceDiscoveryAgent class provides an API for discovering nearby + Bluetooth devices. + \since 5.0 + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + + To discovery nearby Bluetooth devices create an instance of QBluetoothDeviceDiscoveryAgent, + connect to either the deviceDiscovered() or finished() signals and call start(). + + \snippet snippets/connectivity/devicediscovery.cpp Device discovery + + To retrieve results asynchronously connect to the deviceDiscovered() signal. To get a list of + all discovered devices call discoveredDevices() after the finished() signal is emitted. +*/ + +/*! + \enum QBluetoothDeviceDiscoveryAgent::Error + + Indicates all possible error conditions found during Bluetooth device discovery. + + \value NoError No error has occurred. + \value PoweredOff Bluetooth adaptor is powered off, power it on before doing discovery. + \value IOFailure Writing or reading from device resulted in an error. + \value UnknownError An unknown error has occurred. +*/ + +/*! + \enum QBluetoothDeviceDiscoveryAgent::InquiryType + + This enum describes the inquiry type used when discovering Bluetooth devices. + + \value GeneralUnlimitedInquiry A general unlimited inquiry. Discovers all visible Bluetooth + devices in the local vicinity. + \value LimitedInquiry A limited inquiry. Only discovers devices that are in limited + inquiry mode. Not all platforms support limited inquiry. If + limited inquiry is requested on a platform that does not + support it general unlimited inquiry we be used instead. Setting + LimitedInquiry is useful for 2 games that wish to find each other + quickly. The phone scans for devices in LimitedInquiry and + Service Discovery is only done on one or two devices speeding up the + service scan. After the game has connected the device returns to + GeneralUnilimitedInquiry +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::deviceDiscovered(const QBluetoothDeviceInfo &info) + + This signal is emitted when the Bluetooth device described by \a info is discovered. +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::finished() + + This signal is emitted when Bluetooth device discovery completes. +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::error(QBluetoothDeviceDiscoveryAgent::Error error) + + This signal is emitted when an \a error occurs during Bluetooth device discovery. + + \sa error(), errorString() +*/ + +/*! + \fn void QBluetoothDeviceDiscoveryAgent::canceled() + + This signal is emitted when device discovery is aborted by a call to stop(). +*/ + +/*! + \fn bool QBluetoothDeviceDiscoveryAgent::isActive() const + + Returns true if the agent is currently discovering Bluetooth devices, other returns false. +*/ + +/*! + Constructs a new Bluetooth device discovery agent with parent \a parent. +*/ +QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(QObject *parent) +: QObject(parent), d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate) +{ + d_ptr->q_ptr = this; +} + +/*! + Destructor for ~QBluetoothDeviceDiscoveryAgent() +*/ +QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent() +{ + delete d_ptr; +} + +/*! + \property QBluetoothDeviceDiscoveryAgent::inquiryType + \brief type of inquiry scan to use when discovering devices + + This property affects the type of inquiry scan which is performed when discovering devices. + + By default, this property is set to GeneralUnlimitedInquiry. + + Not all platforms support LimitedInquiry. + + \sa InquiryType +*/ +QBluetoothDeviceDiscoveryAgent::InquiryType QBluetoothDeviceDiscoveryAgent::inquiryType() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + return d->inquiryType; +} + +void QBluetoothDeviceDiscoveryAgent::setInquiryType(QBluetoothDeviceDiscoveryAgent::InquiryType type) +{ + Q_D(QBluetoothDeviceDiscoveryAgent); + d->inquiryType = type; +} + +/*! + Returns a list of all discovered Bluetooth devices. +*/ +QList<QBluetoothDeviceInfo> QBluetoothDeviceDiscoveryAgent::discoveredDevices() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + return d->discoveredDevices; +} + +/*! + Starts Bluetooth device discovery, if it is not already started. + + The deviceDiscovered() signal is emitted as each device is discovered. The finished() signal + is emitted once device discovery is complete. +*/ +void QBluetoothDeviceDiscoveryAgent::start() +{ + Q_D(QBluetoothDeviceDiscoveryAgent); + if (!isActive()) + d->start(); +} + +/*! + Stops Bluetooth device discovery. The cancel() signal is emitted once the + device discovery is canceled. start() maybe called before the cancel signal is + received. Once start() has been called the cancel signal from the prior + discovery will be silently discarded. +*/ +void QBluetoothDeviceDiscoveryAgent::stop() +{ + Q_D(QBluetoothDeviceDiscoveryAgent); + if (isActive()) + d->stop(); +} + +bool QBluetoothDeviceDiscoveryAgent::isActive() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + return d->isActive(); +} + + +/*! + Returns the last error which has occurred. +*/ +QBluetoothDeviceDiscoveryAgent::Error QBluetoothDeviceDiscoveryAgent::error() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + + return d->lastError; +} + +/*! + Returns a human-readable description of the last error that occurred. +*/ +QString QBluetoothDeviceDiscoveryAgent::errorString() const +{ + Q_D(const QBluetoothDeviceDiscoveryAgent); + return d->errorString; +} + +#include "moc_qbluetoothdevicediscoveryagent.cpp" diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.h b/src/bluetooth/qbluetoothdevicediscoveryagent.h new file mode 100644 index 00000000..9502e900 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHDEVICEDISCOVERYAGENT_H +#define QBLUETOOTHDEVICEDISCOVERYAGENT_H + +#include "../qtconnectivityglobal.h" + +#include <QObject> + +#include <qbluetoothdeviceinfo.h> + +QT_BEGIN_HEADER + +class QBluetoothDeviceDiscoveryAgentPrivate; + +class Q_CONNECTIVITY_EXPORT QBluetoothDeviceDiscoveryAgent : public QObject +{ + Q_OBJECT + Q_PROPERTY(QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType READ inquiryType WRITE setInquiryType) + +public: + // FIXME: add more errors + // FIXME: add bluez error handling + enum Error { + NoError, + IOFailure, + PoweredOff, + UnknownError = 100 + }; + + enum InquiryType { + GeneralUnlimitedInquiry, + LimitedInquiry, + }; + + QBluetoothDeviceDiscoveryAgent(QObject *parent = 0); + ~QBluetoothDeviceDiscoveryAgent(); + + QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType() const; + void setInquiryType(QBluetoothDeviceDiscoveryAgent::InquiryType type); + + bool isActive() const; + + Error error() const; + QString errorString() const; + + QList<QBluetoothDeviceInfo> discoveredDevices() const; + +public slots: + void start(); + void stop(); + +signals: + void deviceDiscovered(const QBluetoothDeviceInfo &info); + void finished(); + void error(QBluetoothDeviceDiscoveryAgent::Error error); + void canceled(); + +private: + Q_DECLARE_PRIVATE(QBluetoothDeviceDiscoveryAgent) + QBluetoothDeviceDiscoveryAgentPrivate *d_ptr; + +#ifdef QT_BLUEZ_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_deviceFound(const QString &address, const QVariantMap &dict)); + Q_PRIVATE_SLOT(d_func(), void _q_propertyChanged(const QString &name, const QDBusVariant &value)); +#endif + +#ifdef QT_SYMBIAN_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_newDeviceFound(const QBluetoothDeviceInfo &device)) + Q_PRIVATE_SLOT(d_func(), void _q_setError(QBluetoothDeviceDiscoveryAgent::Error errorCode, QString errorDescription)) +#endif // QT_SYMBIAN_BLUETOOTH +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp new file mode 100644 index 00000000..3a510afa --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdevicediscoveryagent_p.h" +#include "qbluetoothaddress.h" +#include "qbluetoothuuid.h" + +#include "bluez/manager_p.h" +#include "bluez/adapter_p.h" +#include "bluez/device_p.h" + +//#define QTM_DEVICEDISCOVERY_DEBUG + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate() + : lastError(QBluetoothDeviceDiscoveryAgent::NoError), pendingCancel(false), pendingStart(false), adapter(0) +{ + manager = new OrgBluezManagerInterface(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + inquiryType = QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry; +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ + delete manager; +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + if(pendingStart) + return true; + if(pendingCancel) + return false; + return adapter != 0; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start() +{ + + if(pendingCancel == true) { + pendingStart = true; + return; + } + + discoveredDevices.clear(); + + QDBusPendingReply<QDBusObjectPath> reply = manager->DefaultAdapter(); + reply.waitForFinished(); + if (reply.isError()) { + errorString = reply.error().message(); +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO << "ERROR: " << errorString; +#endif + lastError = QBluetoothDeviceDiscoveryAgent::IOFailure; + Q_Q(QBluetoothDeviceDiscoveryAgent); + emit q->error(lastError); + return; + } + + adapter = new OrgBluezAdapterInterface(QLatin1String("org.bluez"), reply.value().path(), + QDBusConnection::systemBus()); + + Q_Q(QBluetoothDeviceDiscoveryAgent); + QObject::connect(adapter, SIGNAL(DeviceFound(QString,QVariantMap)), + q, SLOT(_q_deviceFound(QString,QVariantMap))); + QObject::connect(adapter, SIGNAL(PropertyChanged(QString,QDBusVariant)), + q, SLOT(_q_propertyChanged(QString,QDBusVariant))); + + QDBusPendingReply<QVariantMap> propertiesReply = adapter->GetProperties(); + propertiesReply.waitForFinished(); + if(propertiesReply.isError()) { +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO << "ERROR: " << errorString; +#endif + errorString = propertiesReply.error().message(); + lastError = QBluetoothDeviceDiscoveryAgent::IOFailure; + Q_Q(QBluetoothDeviceDiscoveryAgent); + emit q->error(lastError); + return; + } + + QDBusPendingReply<> discoveryReply = adapter->StartDiscovery(); + if (discoveryReply.isError()) { + delete adapter; + adapter = 0; + errorString = discoveryReply.error().message(); + lastError = QBluetoothDeviceDiscoveryAgent::IOFailure; + Q_Q(QBluetoothDeviceDiscoveryAgent); + emit q->error(lastError); +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO << "ERROR: " << errorString; +#endif + return; + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ + if (adapter) { +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO; +#endif + pendingCancel = true; + pendingStart = false; + QDBusPendingReply<> reply = adapter->StopDiscovery(); + reply.waitForFinished(); + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_deviceFound(const QString &address, + const QVariantMap &dict) +{ + const QBluetoothAddress btAddress(address); + const QString btName = dict.value(QLatin1String("Name")).toString(); + quint32 btClass = dict.value(QLatin1String("Class")).toUInt(); + +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << "Discovered: " << address << btName + << "Num UUIDs" << dict.value(QLatin1String("UUIDs")).toStringList().count() + << "total device" << discoveredDevices.count() << "cached" + << dict.value(QLatin1String("Cached")).toBool() + << "RSSI" << dict.value(QLatin1String("RSSI")).toInt(); +#endif + + QBluetoothDeviceInfo device(btAddress, btName, btClass); + if(dict.value(QLatin1String("RSSI")).isValid()) + device.setRssi(dict.value(QLatin1String("RSSI")).toInt()); + QList<QBluetoothUuid> uuids; + foreach (const QString &u, dict.value(QLatin1String("UUIDs")).toStringList()) { + uuids.append(QBluetoothUuid(u)); + } + device.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete); + device.setCached(dict.value(QLatin1String("Cached")).toBool()); + for(int i = 0; i < discoveredDevices.size(); i++){ + if(discoveredDevices[i].address() == device.address()) { + if(discoveredDevices[i] == device) { +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << "Duplicate: " << address; +#endif + return; + } + discoveredDevices.replace(i, device); + Q_Q(QBluetoothDeviceDiscoveryAgent); +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << "Updated: " << address; +#endif + + emit q->deviceDiscovered(device); + return; // this works if the list doesn't contain duplicates. Don't let it. + } + } +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << "Emit: " << address; +#endif + discoveredDevices.append(device); + Q_Q(QBluetoothDeviceDiscoveryAgent); + emit q->deviceDiscovered(device); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_propertyChanged(const QString &name, + const QDBusVariant &value) +{ +#ifdef QTM_DEVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO << name << value.variant(); +#endif + + if (name == QLatin1String("Discovering") && !value.variant().toBool()) { + Q_Q(QBluetoothDeviceDiscoveryAgent); + adapter->deleteLater(); + adapter = 0; + if(pendingCancel && !pendingStart){ + emit q->canceled(); + pendingCancel = false; + } + else if(pendingStart){ + pendingStart = false; + pendingCancel = false; + start(); + } + else { + emit q->finished(); + } + } +} diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp new file mode 100644 index 00000000..83b4a623 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdevicediscoveryagent_p.h" +#include "qbluetoothaddress.h" +#include "qbluetoothuuid.h" + +#define QTM_DEVICEDISCOVERY_DEBUG + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate() + +{ +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + return false; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start() +{ +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ +} +#ifdef QT_BLUEZ_BLUETOOTH +void QBluetoothDeviceDiscoveryAgentPrivate::_q_deviceFound(const QString &address, + const QVariantMap &dict) +{ + Q_UNUSED(address); + Q_UNUSED(dict); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_propertyChanged(const QString &name, + const QDBusVariant &value) +{ + Q_UNUSED(name); + Q_UNUSED(value); +} +#endif + +#ifdef QT_SYMBIAN_BLUETOOTH +void _q_newDeviceFound(const QBluetoothDeviceInfo &device) +{ + +} +#endif + diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h new file mode 100644 index 00000000..247ee1c8 --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHDEVICEDISCOVERYAGENT_P_H +#define QBLUETOOTHDEVICEDISCOVERYAGENT_P_H + +#include "qbluetoothdevicediscoveryagent.h" + +#include <QVariantMap> + +#ifdef QT_BLUEZ_BLUETOOTH +class OrgBluezManagerInterface; +class OrgBluezAdapterInterface; +class QDBusVariant; +#endif + +#ifdef QT_SYMBIAN_BLUETOOTH +#include "symbian/bluetoothlinkmanagerdevicediscoverer.h" +#include <es_sock.h> +#include <bt_sock.h> +#endif + +QT_BEGIN_HEADER + +class QBluetoothDeviceDiscoveryAgentPrivate +{ + Q_DECLARE_PUBLIC(QBluetoothDeviceDiscoveryAgent) +public: + QBluetoothDeviceDiscoveryAgentPrivate(); + ~QBluetoothDeviceDiscoveryAgentPrivate(); + + void start(); + void stop(); + bool isActive() const; + +#ifdef QT_SYMBIAN_BLUETOOTH +// private slots + void _q_newDeviceFound(const QBluetoothDeviceInfo &device); + void _q_setError(QBluetoothDeviceDiscoveryAgent::Error errorCode, + QString errorDescription); +#endif + +#ifdef QT_BLUEZ_BLUETOOTH + void _q_deviceFound(const QString &address, const QVariantMap &dict); + void _q_propertyChanged(const QString &name, const QDBusVariant &value); +#endif + +private: +#ifdef QT_SYMBIAN_BLUETOOTH + void allocate(); + uint inquiryTypeToIAC() const; +#endif + + QList<QBluetoothDeviceInfo> discoveredDevices; + QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType; + + QBluetoothDeviceDiscoveryAgent::Error lastError; + QString errorString; + + bool pendingCancel; + bool pendingStart; + +#ifdef QT_BLUEZ_BLUETOOTH + OrgBluezManagerInterface *manager; + OrgBluezAdapterInterface *adapter; +#endif + +#ifdef QT_SYMBIAN_BLUETOOTH + // shared socket servet among RHostResolvers + RSocketServ m_socketServer; + // active object for device discovery + BluetoothLinkManagerDeviceDiscoverer *m_deviceDiscovery; + +#endif + + QBluetoothDeviceDiscoveryAgent *q_ptr; + +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_symbian.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_symbian.cpp new file mode 100644 index 00000000..4afd33db --- /dev/null +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_symbian.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothdevicediscoveryagent_p.h" +#include "qbluetoothaddress.h" + +#include <bttypes.h> + +#include <QDebug> + +QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate() + : inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry) + , lastError(QBluetoothDeviceDiscoveryAgent::NoError) + , errorString(QString()) + , m_deviceDiscovery(0) +{ + /* connect to socker server */ + TInt result = m_socketServer.Connect(); + if (result != KErrNone) + _q_setError(QBluetoothDeviceDiscoveryAgent::UnknownError, + QString("RSocketServ.Connect() failed with error")); +} + +QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() +{ + delete m_deviceDiscovery; + if (m_socketServer.Handle() != NULL) + m_socketServer.Close(); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::allocate() +{ + Q_Q(QBluetoothDeviceDiscoveryAgent); + // create link manager device discoverer + if (m_socketServer.Handle() != NULL) { + // create new active object for querying devices + m_deviceDiscovery = new BluetoothLinkManagerDeviceDiscoverer(m_socketServer); + if (m_deviceDiscovery) { + QObject::connect(m_deviceDiscovery, SIGNAL(deviceDiscoveryComplete()), q, SIGNAL(finished())); + QObject::connect(m_deviceDiscovery, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)), + q, SLOT(_q_newDeviceFound(const QBluetoothDeviceInfo&))); + QObject::connect(m_deviceDiscovery, SIGNAL(linkManagerError(QBluetoothDeviceDiscoveryAgent::Error,QString)), + q, SLOT(_q_setError(QBluetoothDeviceDiscoveryAgent::Error,QString))); + QObject::connect(m_deviceDiscovery, SIGNAL(canceled()), q, SIGNAL(canceled())); + } else { + _q_setError(QBluetoothDeviceDiscoveryAgent::UnknownError, + QString("Cannot allocate BluetoothLinkManagerDeviceDiscoverer: failed with error")); + } + } +} + +void QBluetoothDeviceDiscoveryAgentPrivate::start() +{ + + // clear list of found devices + discoveredDevices.clear(); + if (!m_deviceDiscovery) { + allocate(); + } + m_deviceDiscovery->startDiscovery(inquiryTypeToIAC()); + +} + +void QBluetoothDeviceDiscoveryAgentPrivate::stop() +{ + if (m_deviceDiscovery) + m_deviceDiscovery->stopDiscovery(); +} + +bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const +{ + if (m_deviceDiscovery) + return m_deviceDiscovery->isReallyActive(); + return false; +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_setError(QBluetoothDeviceDiscoveryAgent::Error errorCode, + QString errorDescription) +{ + qDebug() << __PRETTY_FUNCTION__ << errorCode << errorDescription; + if (errorCode == KErrNone) + return; + + Q_Q(QBluetoothDeviceDiscoveryAgent); + + errorString = errorDescription; + emit q->error(errorCode); +} + +void QBluetoothDeviceDiscoveryAgentPrivate::_q_newDeviceFound(const QBluetoothDeviceInfo &device) +{ + // add found device to the list of devices + discoveredDevices.append(device); + Q_Q(QBluetoothDeviceDiscoveryAgent); + emit q->deviceDiscovered(device); +} + +uint QBluetoothDeviceDiscoveryAgentPrivate::inquiryTypeToIAC() const +{ + return inquiryType == QBluetoothDeviceDiscoveryAgent::LimitedInquiry ? KLIAC : KGIAC; +} diff --git a/src/bluetooth/qbluetoothdeviceinfo.cpp b/src/bluetooth/qbluetoothdeviceinfo.cpp new file mode 100644 index 00000000..4f3ee079 --- /dev/null +++ b/src/bluetooth/qbluetoothdeviceinfo.cpp @@ -0,0 +1,529 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothdeviceinfo_p.h" + +#include <QDebug> + +/*! + \class QBluetoothDeviceInfo + \brief The QBluetoothDeviceInfo class provides information about Bluetooth devices. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + QBluetoothDeviceInfo provides information about a Bluetooth device's name, address and class of device. +*/ + +/*! + \enum QBluetoothDeviceInfo::MajorDeviceClass + + This enum describes a Bluetooth device's major device class. + + \value MiscellaneousDevice A miscellaneous device. + \value ComputerDevice A computer device or PDA. + \value PhoneDevice A telephone device. + \value LANAccessDevice A device that provides access to a local area network. + \value AudioVideoDevice A device capable of playback or capture of audio and/or video. + \value PeripheralDevice A peripheral device such as a keyboard, mouse, etc. + \value ImagingDevice An imaging device such as a display, printer, scanner or camera. + \value WearableDevice A wearable device such as a watch or pager. + \value ToyDevice A toy. + \value HealthDevice A health reated device such as heart rate, or temperature. + \value UncategorizedDevice A device that does not fit into any of the other device classes. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorMiscellaneousClass + + This enum describes the minor device classes for miscellaneous Bluetooth devices. + + \value UncategorizedMiscellaneous An uncategorized miscellaneous device. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorComputerClass + + This enum describes the minor device classes for computer devices. + + \value UncategorizedComputer An uncategorized computer device. + \value DesktopComputer A desktop computer. + \value ServerComputer A server computer. + \value LaptopComputer A laptop computer. + \value HandheldClamShellComputer A clamshell handheld computer or PDA. + \value HandheldComputer A handheld computer or PDA. + \value WearableComputer A wearable computer. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorPhoneClass + + This enum describes the minor device classes for phone devices. + + \value UncategorizedPhone An uncategorized phone device. + \value CellularPhone A cellular phone. + \value CordlessPhone A cordless phone. + \value SmartPhone A smart phone. + \value WiredModemOrVoiceGatewayPhone A wired modem or voice gateway. + \value CommonIsdnAccessPhone A device that provides ISDN access. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorNetworkClass + + This enum describes the minor device classes for local area network access devices. Local area + network access devices use the minor device class to specify the current network utilization. + + \value NetworkFullService 100% of the total bandwidth is available. + \value NetworkLoadFactorOne 0 - 17% of the total bandwidth is currently being used. + \value NetworkLoadFactorTwo 17 - 33% of the total bandwidth is currently being used. + \value NetworkLoadFactorThree 33 - 50% of the total bandwidth is currently being used. + \value NetworkLoadFactorFour 50 - 67% of the total bandwidth is currently being used. + \value NetworkLoadFactorFive 67 - 83% of the total bandwidth is currently being used. + \value NetworkLoadFactorSix 83 - 99% of the total bandwidth is currently being used. + \value NetworkNoService No network service available. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorAudioVideoClass + + This enum describes the minor device classes for audio/video devices. + + \value UncategorizedAudioVideoDevice An uncategorized audio/video device. + \value WearableHeadsetDevice A wearable headset device. + \value HandsFreeDevice A hands free device. + \value Microphone A microphone. + \value Loudspeaker A loudspeaker. + \value Headphones Headphones. + \value PortableAudioDevice A portable audio device. + \value CarAudio A car audio device. + \value SetTopBox A set top box. + \value HiFiAudioDevice A HiFi audio device. + \value Vcr A video cassette recorder. + \value VideoCamera A video camera. + \value Camcorder A video camera. + \value VideoMonitor A video monitor. + \value VideoDisplayAndLoudspeaker A video display with built-in loudspeaker. + \value VideoConferencing A video conferencing device. + \value GamingDevice A gaming device. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorPeripheralClass + + This enum describes the minor device classes for peripheral devices. + + \value UncategorizedPeripheral An uncategorized peripheral device. + \value KeyboardPeripheral A keyboard. + \value PointingDevicePeripheral A pointing device, for example a mouse. + \value KeyboardWithPointingDevicePeripheral A keyboard with built-in pointing device. + \value JoystickPeripheral A joystick. + \value GamepadPeripheral A game pad. + \value RemoteControlPeripheral A remote control. + \value SensingDevicePeripheral A sensing device. + \value DigitizerTabletPeripheral A digitizer tablet peripheral. + \value CardReaderPeripheral A card reader peripheral. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorImagingClass + + This enum describes the minor device classes for imaging devices. + + \value UncategorizedImagingDevice An uncategorized imaging device. + \value ImageDisplay A device capable of displaying images. + \value ImageCamera A camera. + \value ImageScanner An image scanner. + \value ImagePrinter A printer. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorWearableClass + + This enum describes the minor device classes for wearable devices. + + \value UncategorizedWearableDevice An uncategorized wearable device. + \value WearableWristWatch A wristwatch. + \value WearablePager A pager. + \value WearableJacket A jacket. + \value WearableHelmet A helmet. + \value WearableGlasses A pair of glasses. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorToyClass + + This enum describes the minor device classes for toy devices. + + \value UncategorizedToy An uncategorized toy. + \value ToyRobot A toy robot. + \value ToyVehicle A toy vehicle. + \value ToyDoll A toy doll or action figure. + \value ToyController A controller. + \value ToyGame A game. +*/ + +/*! + \enum QBluetoothDeviceInfo::MinorHealthClass + + This enum describes the minor device classes for health devices. + + \value UncategorizedHealthDevice An uncategorized health device. + \value HealthBloodPressureMonitor A blood pressure monitor. + \value HealthThermometer A Thermometer. + \value HealthWeightScale A scale. + \value HealthGlucoseMeter A glucose meter. + \value HealthPulseOximeter A blood oxygen saturation meter. + \value HealthDataDisplay A data display. + \value HealthStepCounter A pedometer. +*/ + + +/*! + \enum QBluetoothDeviceInfo::ServiceClass + + This enum describes the service class of the Bluetooth device. The service class is used as a + rudimentary form of service discovery. It is meant to provide a rudimentary list of the types + of services that the device might provide. + + \value NoService The device does not provide any services. + \value PositioningService The device provides positioning services. + \value NetworkingService The device provides networking services. + \value RenderingService The device provides rendering services. + \value CapturingService The device provides capturing services. + \value ObjectTransferService The device provides object transfer services. + \value AudioService The device provides audio services. + \value TelephonyService The device provides telephony services. + \value InformationService The device provides information services. + \value AllServices The device provides services of all types. +*/ + +/*! + \enum QBluetoothDeviceInfo::DataCompleteness + + This enum describes the completeness of the received data. + + \value DataComplete The data is complete. + \value DataIncomplete The data is incomplete. Addition datum is available via other + interfaces. + \value DataUnavailable No data is available. +*/ + +QBluetoothDeviceInfoPrivate::QBluetoothDeviceInfoPrivate() + : valid(false), cached(false), rssi(1), + serviceClasses(QBluetoothDeviceInfo::NoService), + majorDeviceClass(QBluetoothDeviceInfo::MiscellaneousDevice), + minorDeviceClass(0), + serviceUuidsCompleteness(QBluetoothDeviceInfo::DataUnavailable) +{ +} + +/*! + Constructs an invalid QBluetoothDeviceInfo object. +*/ +QBluetoothDeviceInfo::QBluetoothDeviceInfo() +: d_ptr(new QBluetoothDeviceInfoPrivate) +{ +} + +/*! + Constructs a QBluetoothDeviceInfo object with Bluetooth address \a address, device name + \a name and the encoded class of device \a classOfDevice. + + The \a classOfDevice parameter is encoded in the following format + + \table + \header \o Bits \o Size \o Description + \row \o 0 - 1 \o 2 \o Unused, set to 0. + \row \o 2 - 7 \o 6 \o Minor device class. + \row \o 8 - 12 \o 5 \o Major device class. + \row \o 13 - 23 \o 11 \o Service class. + \endtable +*/ +QBluetoothDeviceInfo::QBluetoothDeviceInfo(const QBluetoothAddress &address, const QString &name, quint32 classOfDevice) +: d_ptr(new QBluetoothDeviceInfoPrivate) +{ + Q_D(QBluetoothDeviceInfo); + + d->address = address; + d->name = name; + + d->minorDeviceClass = static_cast<quint8>((classOfDevice >> 2) & 0x3f); + d->majorDeviceClass = static_cast<MajorDeviceClass>((classOfDevice >> 8) & 0x1f); + d->serviceClasses = static_cast<ServiceClasses>((classOfDevice >> 13) & 0x7ff); + + d->serviceUuidsCompleteness = DataUnavailable; + + d->valid = true; + d->cached = false; + d->rssi = 0; +} + +/*! + Constructs a QBluetoothDeviceInfo that is a copy of \a other. +*/ +QBluetoothDeviceInfo::QBluetoothDeviceInfo(const QBluetoothDeviceInfo &other) +: d_ptr(new QBluetoothDeviceInfoPrivate) +{ + *this = other; +} + +/*! + Destroys the QBluetoothDeviceInfo. +*/ +QBluetoothDeviceInfo::~QBluetoothDeviceInfo() +{ + delete d_ptr; +} + +/*! + Returns true if the QBluetoothDeviceInfo object is valid, otherwise returns false. +*/ +bool QBluetoothDeviceInfo::isValid() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->valid; +} +/*! + Returns the signal strength when the device was last scanned + */ +qint16 QBluetoothDeviceInfo::rssi() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->rssi; +} + +/*! + Set the \a signal strength value, used internally. + */ +void QBluetoothDeviceInfo::setRssi(qint16 signal) +{ + Q_D(QBluetoothDeviceInfo); + d->rssi = signal; +} + +/*! + Makes a copy of the \a other and assigns it to this QBluetoothDeviceInfo object. +*/ +QBluetoothDeviceInfo &QBluetoothDeviceInfo::operator=(const QBluetoothDeviceInfo &other) +{ + Q_D(QBluetoothDeviceInfo); + + d->address = other.d_func()->address; + d->name = other.d_func()->name; + d->minorDeviceClass = other.d_func()->minorDeviceClass; + d->majorDeviceClass = other.d_func()->majorDeviceClass; + d->serviceClasses = other.d_func()->serviceClasses; + d->valid = other.d_func()->valid; + d->cached = other.d_func()->cached; + d->serviceUuidsCompleteness = other.d_func()->serviceUuidsCompleteness; + d->serviceUuids = other.d_func()->serviceUuids; + d->rssi = other.d_func()->rssi; + + return *this; +} + +/*! + Returns true if the \a other QBluetoothDeviceInfo object and this are identical + */ +bool QBluetoothDeviceInfo::operator==(const QBluetoothDeviceInfo &other) const +{ + Q_D(const QBluetoothDeviceInfo); + + if(d->cached != other.d_func()->cached) + return false; + if(d->valid != other.d_func()->valid) + return false; + if(d->majorDeviceClass != other.d_func()->majorDeviceClass) + return false; + if(d->minorDeviceClass != other.d_func()->minorDeviceClass) + return false; + if(d->serviceClasses != other.d_func()->serviceClasses) + return false; + if(d->name != other.d_func()->name) + return false; + if(d->address != other.d_func()->address) + return false; + if(d->serviceUuidsCompleteness != other.d_func()->serviceUuidsCompleteness) + return false; + if(d->serviceUuids.count() != other.d_func()->serviceUuids.count()) + return false; + if(d->serviceUuids != other.d_func()->serviceUuids) + return false; + + return true; + +} + +/*! + Returns the address of the device. +*/ +QBluetoothAddress QBluetoothDeviceInfo::address() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->address; +} + +/*! + Returns the name assigned to the device. +*/ +QString QBluetoothDeviceInfo::name() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->name; +} + +/*! + Returns the service class of the device. +*/ +QBluetoothDeviceInfo::ServiceClasses QBluetoothDeviceInfo::serviceClasses() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->serviceClasses; +} + +/*! + Returns the major device class of the device. +*/ +QBluetoothDeviceInfo::MajorDeviceClass QBluetoothDeviceInfo::majorDeviceClass() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->majorDeviceClass; +} + +/*! + Returns the minor device class of the device. +*/ +quint8 QBluetoothDeviceInfo::minorDeviceClass() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->minorDeviceClass; +} + +/*! + Sets the list of service UUIDs to \a uuids and the completeness of the data to \a completeness. +*/ +void QBluetoothDeviceInfo::setServiceUuids(const QList<QBluetoothUuid> &uuids, DataCompleteness completeness) +{ + Q_D(QBluetoothDeviceInfo); + + d->serviceUuids = uuids; + d->serviceUuidsCompleteness = completeness; +} + +/*! + Returns the list of service UUIDS supported by the device. If \a completeness is not 0 it will + be set to DataComplete if the returned list is the complete list of UUIDs supported by the + device. DataIncomplete if additional service UUIDs are supported by the device and + DataUnavailable if no service UUID information is available. + + This function requires both Bluetooth devices to support the 2.1 specification. +*/ +QList<QBluetoothUuid> QBluetoothDeviceInfo::serviceUuids(DataCompleteness *completeness) const +{ + Q_D(const QBluetoothDeviceInfo); + + if (completeness) + *completeness = d->serviceUuidsCompleteness; + + return d->serviceUuids; +} + +/*! + Returns the completeness of the service UUID list. If DataComplete is returned then + serviceUuids() will return a complete list of service UUIDs supported by the device. Otherwise + serviceUuids() will only return a partial or empty list of service UUIDs. To get a full list + of services supported by the device a full service discovery needs to be performed. +*/ +QBluetoothDeviceInfo::DataCompleteness QBluetoothDeviceInfo::serviceUuidsCompleteness() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->serviceUuidsCompleteness; +} + +/*! + Sets the manufacturer specific data returned by Extended Inquiry Responses to \a data. +*/ +void QBluetoothDeviceInfo::setManufacturerSpecificData(const QByteArray &data) +{ + Q_UNUSED(data); +} + +/*! + Returns the manufacturer specific data. If \a available is not 0 it is set to true if + manufacturer specific data is available; otherwise it is set to false. +*/ +QByteArray QBluetoothDeviceInfo::manufacturerSpecificData(bool *available) const +{ + Q_UNUSED(available); + return QByteArray(); +} + +/*! + Returns true if the QBluetoothDeviceInfo object is created from cached data +*/ +bool QBluetoothDeviceInfo::isCached() const +{ + Q_D(const QBluetoothDeviceInfo); + + return d->cached; +} + +/*! + Used by the system to set the \a cached flag if the QBluetoothDeviceInfo is created from cached data. Cached information + may not be as accurate as data read from a live device. + */ +void QBluetoothDeviceInfo::setCached(bool cached) +{ + Q_D(QBluetoothDeviceInfo); + + d->cached = cached; +} diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h new file mode 100644 index 00000000..2dc6212f --- /dev/null +++ b/src/bluetooth/qbluetoothdeviceinfo.h @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHDEVICEINFO_H +#define QBLUETOOTHDEVICEINFO_H + +#include "../qtconnectivityglobal.h" + +#include <QString> + +QT_BEGIN_HEADER + +class QBluetoothDeviceInfoPrivate; +class QBluetoothAddress; +class QBluetoothUuid; + +class Q_CONNECTIVITY_EXPORT QBluetoothDeviceInfo +{ +public: + enum MajorDeviceClass { + MiscellaneousDevice = 0, + ComputerDevice = 1, + PhoneDevice = 2, + LANAccessDevice = 3, + AudioVideoDevice = 4, + PeripheralDevice = 5, + ImagingDevice = 6, + WearableDevice = 7, + ToyDevice = 8, + HealthDevice = 9, + UncategorizedDevice = 31, + }; + + enum MinorMiscellaneousClass { + UncategorizedMiscellaneous = 0, + }; + + enum MinorComputerClass { + UncategorizedComputer = 0, + DesktopComputer = 1, + ServerComputer = 2, + LaptopComputer = 3, + HandheldClamShellComputer = 4, + HandheldComputer = 5, + WearableComputer = 6, + }; + + enum MinorPhoneClass { + UncategorizedPhone = 0, + CellularPhone = 1, + CordlessPhone = 2, + SmartPhone = 3, + WiredModemOrVoiceGatewayPhone = 4, + CommonIsdnAccessPhone = 5, + }; + + enum MinorNetworkClass { + NetworkFullService = 0x00, + NetworkLoadFactorOne = 0x08, + NetworkLoadFactorTwo = 0x10, + NetworkLoadFactorThree = 0x18, + NetworkLoadFactorFour = 0x20, + NetworkLoadFactorFive = 0x28, + NetworkLoadFactorSix = 0x30, + NetworkNoService = 0x38, + }; + + enum MinorAudioVideoClass { + UncategorizedAudioVideoDevice = 0, + WearableHeadsetDevice = 1, + HandsFreeDevice = 2, + // reserved = 3, + Microphone = 4, + Loudspeaker = 5, + Headphones = 6, + PortableAudioDevice = 7, + CarAudio = 8, + SetTopBox = 9, + HiFiAudioDevice = 10, + Vcr = 11, + VideoCamera = 12, + Camcorder = 13, + VideoMonitor = 14, + VideoDisplayAndLoudspeaker = 15, + VideoConferencing = 16, + // reserved = 17, + GamingDevice = 18, + }; + + enum MinorPeripheralClass { + UncategorizedPeripheral = 0, + KeyboardPeripheral = 0x10, + PointingDevicePeripheral = 0x20, + KeyboardWithPointingDevicePeripheral = 0x30, + + JoystickPeripheral = 0x01, + GamepadPeripheral = 0x02, + RemoteControlPeripheral = 0x03, + SensingDevicePeripheral = 0x04, + DigitizerTabletPeripheral = 0x05, + CardReaderPeripheral = 0x06, + }; + + enum MinorImagingClass { + UncategorizedImagingDevice = 0, + ImageDisplay = 0x04, + ImageCamera = 0x08, + ImageScanner = 0x10, + ImagePrinter = 0x20 + }; + + enum MinorWearableClass { + UncategorizedWearableDevice = 0, + WearableWristWatch = 1, + WearablePager = 2, + WearableJacket = 3, + WearableHelmet = 4, + WearableGlasses = 5, + }; + + enum MinorToyClass { + UncategorizedToy = 0, + ToyRobot = 1, + ToyVehicle = 2, + ToyDoll = 3, + ToyController = 4, + ToyGame = 5, + }; + + enum MinorHealthClass { + UncategorizedHealthDevice = 0, + HealthBloodPressureMonitor = 0x1, + HealthThermometer = 0x2, + HealthWeightScale = 0x3, + HealthGlucoseMeter = 0x4, + HealthPulseOximeter = 0x5, + HealthDataDisplay = 0x7, + HealthStepCounter = 0x8 + }; + + enum ServiceClass { + NoService = 0x0000, + PositioningService = 0x0001, + NetworkingService = 0x0002, + RenderingService = 0x0004, + CapturingService = 0x0008, + ObjectTransferService = 0x0010, + AudioService = 0x0020, + TelephonyService = 0x0040, + InformationService = 0x0080, + AllServices = 0x07ff, + }; + Q_DECLARE_FLAGS(ServiceClasses, ServiceClass) + + enum DataCompleteness { + DataComplete, + DataIncomplete, + DataUnavailable, + }; + + QBluetoothDeviceInfo(); + QBluetoothDeviceInfo(const QBluetoothAddress &address, const QString &name, quint32 classOfDevice); + QBluetoothDeviceInfo(const QBluetoothDeviceInfo &other); + ~QBluetoothDeviceInfo(); + + bool isValid() const; + bool isCached() const; + + void setCached(bool cached); + + QBluetoothDeviceInfo &operator=(const QBluetoothDeviceInfo &other); + bool operator==(const QBluetoothDeviceInfo &other) const; + + QBluetoothAddress address() const; + QString name() const; + + ServiceClasses serviceClasses() const; + MajorDeviceClass majorDeviceClass() const; + quint8 minorDeviceClass() const; + + qint16 rssi() const; + void setRssi(qint16 signal); + +// bool matchesMinorClass(MinorComputerClass minor) const; +// bool matchesMinorClass(MinorPhoneClass minor) const; +// bool matchesMinorClass(MinorNetworkClass minor) const; +// bool matchesMinorClass(MinorAudioVideoClass minor) const; +// bool matchesMinorClass(MinorPeripheralClass minor) const; +// bool matchesMinorClass(MinorImagingClass minor) const; + + void setServiceUuids(const QList<QBluetoothUuid> &uuids, DataCompleteness completeness); + QList<QBluetoothUuid> serviceUuids(DataCompleteness *completeness = 0) const; + DataCompleteness serviceUuidsCompleteness() const; + + void setManufacturerSpecificData(const QByteArray &data); + QByteArray manufacturerSpecificData(bool *available = 0) const; + +protected: + QBluetoothDeviceInfoPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QBluetoothDeviceInfo) +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothdeviceinfo_p.h b/src/bluetooth/qbluetoothdeviceinfo_p.h new file mode 100644 index 00000000..21864741 --- /dev/null +++ b/src/bluetooth/qbluetoothdeviceinfo_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHDEVICEINFO_P_H +#define QBLUETOOTHDEVICEINFO_P_H + +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothaddress.h" +#include "qbluetoothuuid.h" + +#include <QString> + +QT_BEGIN_HEADER + +class QBluetoothDeviceInfoPrivate +{ +public: + QBluetoothDeviceInfoPrivate(); + + bool valid; + bool cached; + + QBluetoothAddress address; + QString name; + + qint16 rssi; + + QBluetoothDeviceInfo::ServiceClasses serviceClasses; + QBluetoothDeviceInfo::MajorDeviceClass majorDeviceClass; + quint8 minorDeviceClass; + + QBluetoothDeviceInfo::DataCompleteness serviceUuidsCompleteness; + QList<QBluetoothUuid> serviceUuids; +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp new file mode 100644 index 00000000..8cba00e7 --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice.cpp @@ -0,0 +1,239 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothlocaldevice.h" +#include "qbluetoothlocaldevice_p.h" +#include "qbluetoothaddress.h" + +#include <QtCore/QString> +#include <QDebug> + +/*! + \class QBluetoothLocalDevice + \brief The QBluetoothLocalDevice class provides access to local Bluetooth devices. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + QBluetoothLocalDevice provides functions for getting and setting the state of local Bluetooth + devices. +*/ + +/*! + \enum QBluetoothLocalDevice::Pairing + + This enum describes the pairing state between two Bluetooth devices. + + \value Unpaired The Bluetooth devices are not paired. + \value Paired The Bluetooth devices are paired. The system will prompt the user for + authorization when the remote device initiates a connection to the + local device. + \value AuthorizedPaired The Bluetooth devices are paired. The system will not prompt the user + for authorization when the remote device initiates a connection to the + local device. +*/ + +/*! + \enum QBluetoothLocalDevice::Error + + This enum describes errors that maybe returned + + \value NoError No known error + \value PairingError Error in pairing + \value UnknownError Unknown error + +*/ + +/*! + \enum QBluetoothLocalDevice::HostMode + + This enum describes the most of the local Bluetooth device. + + \value HostPoweredOff Powers the device down + \value HostConnectable Remote Bluetooth devices can connect to the local Bluetooth device + if they have previously been paired with it or otherwise know its + address. This powers up the device if it was powered off. + \value HostDiscoverable Remote Bluetooth devices can discover the presence of the local + Bluetooth device. The device will also be connectable, and powered on. + \value HostDiscoverableLimitedInquiry Remote Bluetooth devices can discover the presence of the local + Bluetooth device when performing a limited inquiry. This should be used for + locating services that are only made discoverable for a limited period of time. + This can speed up discovery between games for example, since service + discovery can be skipped on devices not in limited enquiry more. This + is not supported on all platforms. The device will also be connectable, and powered on. + +*/ + +namespace +{ +class LocalDeviceRegisterMetaTypes +{ +public: + LocalDeviceRegisterMetaTypes() + { + qRegisterMetaType<QBluetoothLocalDevice::HostMode>("QBluetoothLocalDevice::HostMode"); + qRegisterMetaType<QBluetoothLocalDevice::Pairing>("QBluetoothLocalDevice::Pairing"); + qRegisterMetaType<QBluetoothLocalDevice::Error>("QBluetoothLocalDevice::Error"); + } +} _registerLocalDeviceMetaTypes; +} + +/*! + Destroys the QBluetoothLocalDevice. +*/ +QBluetoothLocalDevice::~QBluetoothLocalDevice() +{ + delete d_ptr; +} + +/*! + Returns true the QBluetoothLocalDevice represents an available local Bluetooth device; + otherwise return false. +*/ +bool QBluetoothLocalDevice::isValid() const +{ + return d_ptr; +} + +/*! + \fn void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) + + Sets the host mode the this local Bluetooth device to \a mode. +*/ + +/*! + \fn QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const + + Returns the current host mode of this local Bluetooth device. +*/ + +/*! + \fn QBluetoothLocalDevice::name() const + + Returns the name assgined by the user to this Bluetooth device. +*/ + +/*! + \fn QBluetoothLocalDevice::address() const + + Returns the MAC address of this Bluetooth device. +*/ + +/*! + \fn QList<QBluetoothLocalDevice> QBluetoothLocalDevice::allDevices() + + Returns a list of all available local Bluetooth devices. +*/ + +/*! + \fn QBluetoothLocalDevice::powerOn() + + Powers on the device on returning it to the hostMode() state is was in when powered down +*/ + +/*! + \fn QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) + Constructs a QBluetoothLocalDevice with \a parent. +*/ + +/*! + \fn QBluetoothLocalDevice::hostModeStateChanged(QBluetoothLocalDevice::HostMode state) + The \a state of the host has transitioned to a different HostMode +*/ + +/*! + \fn QBluetoothLocalDevice::pairingStatus(const QBluetoothAddress &address) const + + Returns the current bluetooth pairing status of \a address, if it's unpaired, paired, or paired and authorized. +*/ + + +/*! + \fn QBluetoothLocalDevice::pairingDisplayConfirmation(const QBluetoothAddress &address, QString pin) + + Signal by some platforms to display a pairing confirmation dialog for \a address. The user + is asked to confirm the \a pin is the same on both devices. QBluetoothLocalDevice::pairingConfirmation(bool) + must be called to indicate if the user accepts or rejects the displayed pin. +*/ + +/*! + \fn QBluetoothLocalDevice::pairingConfirmation(bool accept) + + To be called after getting a pairingDisplayConfirmation(). The \a accept parameter either + accepts the pairing or rejects it. +*/ + +/*! + \fn QBluetoothLocalDevice::pairingDisplayPinCode(const QBluetoothAddress &address, QString pin) + + Signal by some platforms to display the \a pin to the user for \a address. The pin is automatically + generated, and does not need to be confirmed. +*/ + +/*! + \fn QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) + + Set the \a pairing status with \a address. The results are returned via + the signal pairingFinished(). Caution: creating a pairing may take minutes, and can require + the user to acknowledge dialogs. +*/ + +/*! + \fn QBluetoothLocalDevice::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing) + + Pairing has completed with \a address. Current pairing status is in \a pairing. +*/ + +/*! + \fn QBluetoothLocalDevice::error(QBluetoothLocalDevice::Error error) + Signal emitted for pairing if there's an exceptional \a error +*/ + + +/*! + \fn QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = 0) + + Construct new QBluetoothLocalDevice for \a address. +*/ + + +#include "moc_qbluetoothlocaldevice.cpp" diff --git a/src/bluetooth/qbluetoothlocaldevice.h b/src/bluetooth/qbluetoothlocaldevice.h new file mode 100644 index 00000000..41530819 --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice.h @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QBLUETOOTHLOCALDEVICE_H +#define QBLUETOOTHLOCALDEVICE_H + +#include "../qtconnectivityglobal.h" + +#include <QObject> +#include <QtCore/QList> +#include <QString> + +#include "qbluetoothaddress.h" + +QT_BEGIN_HEADER + +class QBluetoothLocalDevicePrivate; + +class Q_CONNECTIVITY_EXPORT QBluetoothHostInfo +{ +public: + QBluetoothHostInfo() { }; + QBluetoothHostInfo(const QBluetoothHostInfo &other) { + m_address = other.m_address; + m_name = other.m_name; + }; + + QBluetoothAddress getAddress() const { return m_address; } + void setAddress(const QBluetoothAddress &address) { m_address = address; } + + QString getName() const { return m_name; } + void setName(const QString &name){ m_name = name; } + +private: + QBluetoothAddress m_address; + QString m_name; + +}; + + +class Q_CONNECTIVITY_EXPORT QBluetoothLocalDevice : public QObject +{ + Q_OBJECT + Q_ENUMS(Pairing) + Q_ENUMS(HostMode) + Q_ENUMS(Error) +public: + enum Pairing { + Unpaired, + Paired, + AuthorizedPaired + }; + + enum HostMode { + HostPoweredOff, + HostConnectable, + HostDiscoverable, + HostDiscoverableLimitedInquiry + }; + + enum Error { + NoError, + PairingError, + UnknownError = 100 + }; + QBluetoothLocalDevice(QObject *parent = 0); + explicit QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = 0); + virtual ~QBluetoothLocalDevice(); + + bool isValid() const; + + void requestPairing(const QBluetoothAddress &address, Pairing pairing); + Pairing pairingStatus(const QBluetoothAddress &address) const; + + void setHostMode(QBluetoothLocalDevice::HostMode mode); + HostMode hostMode() const; + + void powerOn(); + + QString name() const; + QBluetoothAddress address() const; + + static QList<QBluetoothHostInfo> allDevices(); + +public Q_SLOTS: + void pairingConfirmation(bool confirmation); + +Q_SIGNALS: + void hostModeStateChanged(QBluetoothLocalDevice::HostMode state); + void pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + + void pairingDisplayPinCode(const QBluetoothAddress &address, QString pin); + void pairingDisplayConfirmation(const QBluetoothAddress &address, QString pin); + void error(QBluetoothLocalDevice::Error error); + +private: + Q_DECLARE_PRIVATE(QBluetoothLocalDevice) + QBluetoothLocalDevicePrivate *d_ptr; +#ifdef QT_SYMBIAN_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_pairingFinished(const QBluetoothAddress &, QBluetoothLocalDevice::Pairing)) + Q_PRIVATE_SLOT(d_func(), void _q_registryError(int error)) + Q_PRIVATE_SLOT(d_func(), void _q_pairingError(int error)) +#endif //QT_SYMBIAN_BLUETOOTH +}; + +Q_DECLARE_METATYPE(QBluetoothLocalDevice::HostMode) +Q_DECLARE_METATYPE(QBluetoothLocalDevice::Pairing) +Q_DECLARE_METATYPE(QBluetoothLocalDevice::Error) + +QT_END_HEADER + +#endif // QBLUETOOTHLOCALDEVICE_H diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp new file mode 100644 index 00000000..124a18b0 --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp @@ -0,0 +1,518 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QDBusContext> + +#include "qbluetoothlocaldevice.h" +#include "qbluetoothaddress.h" +#include "qbluetoothlocaldevice_p.h" + +#include "bluez/manager_p.h" +#include "bluez/adapter_p.h" +#include "bluez/agent_p.h" +#include "bluez/device_p.h" + +static const QLatin1String agentPath("/qt/agent"); + +QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) +: QObject(parent) +{ + OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> reply = manager.DefaultAdapter(); + reply.waitForFinished(); + if (reply.isError()) + return; + + OrgBluezAdapterInterface *adapter = new OrgBluezAdapterInterface(QLatin1String("org.bluez"), + reply.value().path(), + QDBusConnection::systemBus()); + + this->d_ptr = new QBluetoothLocalDevicePrivate; + this->d_ptr->adapter = adapter; + this->d_ptr->q_ptr = this; + this->d_ptr->agent = 0x0; + this->d_ptr->msgConnection = 0x0; + this->d_ptr->currentMode = static_cast<QBluetoothLocalDevice::HostMode>(-1); + + connect(adapter, SIGNAL(PropertyChanged(QString,QDBusVariant)), + this->d_ptr, SLOT(PropertyChanged(QString,QDBusVariant))); + +// connect(d_ptr, SIGNAL(pairingFinished(const QBluetoothAddress&,QBluetoothLocalDevice::Pairing)), this, SIGNAL(pairingFinished(const QBluetoothAddress&,QBluetoothLocalDevice::Pairing))); +// connect(this->d_ptr, SIGNAL(pairingDisplayPinCode(const QBluetoothAddress &,QString)), +// this, SIGNAL(pairingDisplayPinCode(const QBluetoothAddress &,QString))); + + qsrand(QTime::currentTime().msec()); + this->d_ptr->agent_path = agentPath; + this->d_ptr->agent_path.append(QString::fromLatin1("/%1").arg(qrand())); + +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) +: QObject(parent) +{ + OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QList<QDBusObjectPath> > reply = manager.ListAdapters(); + reply.waitForFinished(); + if (reply.isError()) + return; + + + foreach (const QDBusObjectPath &path, reply.value()) { + OrgBluezAdapterInterface *adapter = new OrgBluezAdapterInterface(QLatin1String("org.bluez"), + path.path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QVariantMap> reply = adapter->GetProperties(); + reply.waitForFinished(); + if (reply.isError()) + continue; + + QBluetoothAddress path_address(reply.value().value(QLatin1String("Address")).toString()); + + if(path_address == address){ + this->d_ptr = new QBluetoothLocalDevicePrivate; + this->d_ptr->adapter = adapter; + break; + } + else { + delete adapter; + } + } +} + +QString QBluetoothLocalDevice::name() const +{ + if (!d_ptr) + return QString(); + + QDBusPendingReply<QVariantMap> reply = d_ptr->adapter->GetProperties(); + reply.waitForFinished(); + if (reply.isError()) + return QString(); + + return reply.value().value(QLatin1String("Name")).toString(); +} + +QBluetoothAddress QBluetoothLocalDevice::address() const +{ + if (!d_ptr) + return QBluetoothAddress(); + + QDBusPendingReply<QVariantMap> reply = d_ptr->adapter->GetProperties(); + reply.waitForFinished(); + if (reply.isError()) + return QBluetoothAddress(); + + return QBluetoothAddress(reply.value().value(QLatin1String("Address")).toString()); +} + +void QBluetoothLocalDevice::powerOn() +{ + if (!d_ptr) + return; + + d_ptr->adapter->SetProperty(QLatin1String("Powered"), QDBusVariant(QVariant::fromValue(true))); +} + +void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) +{ + if (!d_ptr) + return; + + switch (mode) { + case HostDiscoverableLimitedInquiry: + case HostDiscoverable: + d_ptr->adapter->SetProperty(QLatin1String("Powered"), QDBusVariant(QVariant::fromValue(true))); + d_ptr->adapter->SetProperty(QLatin1String("Discoverable"), + QDBusVariant(QVariant::fromValue(true))); + break; + case HostConnectable: + d_ptr->adapter->SetProperty(QLatin1String("Powered"), QDBusVariant(QVariant::fromValue(true))); + d_ptr->adapter->SetProperty(QLatin1String("Discoverable"), + QDBusVariant(QVariant::fromValue(false))); + break; + case HostPoweredOff: + d_ptr->adapter->SetProperty(QLatin1String("Powered"), + QDBusVariant(QVariant::fromValue(false))); +// d->adapter->SetProperty(QLatin1String("Discoverable"), +// QDBusVariant(QVariant::fromValue(false))); + break; + } +} + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const +{ + if (!d_ptr) + return HostPoweredOff; + + QDBusPendingReply<QVariantMap> reply = d_ptr->adapter->GetProperties(); + reply.waitForFinished(); + if (reply.isError()) + return HostPoweredOff; + + if (!reply.value().value(QLatin1String("Powered")).toBool()) + return HostPoweredOff; + else if (reply.value().value(QLatin1String("Discoverable")).toBool()) + return HostDiscoverable; + else if (reply.value().value(QLatin1String("Powered")).toBool()) + return HostConnectable; + + return HostPoweredOff; +} + +QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices() +{ + QList<QBluetoothHostInfo> localDevices; + + OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QList<QDBusObjectPath> > reply = manager.ListAdapters(); + reply.waitForFinished(); + if (reply.isError()) + return localDevices; + + + foreach (const QDBusObjectPath &path, reply.value()) { + QBluetoothHostInfo hostinfo; + OrgBluezAdapterInterface adapter(QLatin1String("org.bluez"), path.path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QVariantMap> reply = adapter.GetProperties(); + reply.waitForFinished(); + if (reply.isError()) + continue; + + hostinfo.setAddress(QBluetoothAddress(reply.value().value(QLatin1String("Address")).toString())); + hostinfo.setName(reply.value().value(QLatin1String("Name")).toString()); + + localDevices.append(hostinfo); + } + + return localDevices; +} + +static inline OrgBluezDeviceInterface *getDevice(const QBluetoothAddress &address, QBluetoothLocalDevicePrivate *d_ptr){ + QDBusPendingReply<QDBusObjectPath> reply = d_ptr->adapter->FindDevice(address.toString()); + reply.waitForFinished(); + if(reply.isError()){ + qDebug() << Q_FUNC_INFO << "reply failed" << reply.error(); + return 0; + } + + QDBusObjectPath path = reply.value(); + + return new OrgBluezDeviceInterface(QLatin1String("org.bluez"), path.path(), + QDBusConnection::systemBus()); +} + +void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + + if(pairing == Paired || pairing == AuthorizedPaired) { + + d_ptr->address = address; + d_ptr->pairing = pairing; + + if(!d_ptr->agent){ + d_ptr->agent = new OrgBluezAgentAdaptor(d_ptr); + bool res = QDBusConnection::systemBus().registerObject(d_ptr->agent_path, d_ptr); + if(!res){ + qDebug() << "Failed to register agent"; + return; + } + } + + Pairing current_pairing = pairingStatus(address); + if(current_pairing == Paired && pairing == AuthorizedPaired){ + OrgBluezDeviceInterface *device = getDevice(address, d_ptr); + if(!device) + return; + QDBusPendingReply<> deviceReply = device->SetProperty(QLatin1String("Trusted"), QDBusVariant(true)); + deviceReply.waitForFinished(); + if(deviceReply.isError()){ + qDebug() << Q_FUNC_INFO << "reply failed" << deviceReply.error(); + return; + } + delete device; + QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection, Q_ARG(QBluetoothAddress, address), + Q_ARG(QBluetoothLocalDevice::Pairing, QBluetoothLocalDevice::AuthorizedPaired)); + } + else if(current_pairing == AuthorizedPaired && pairing == Paired){ + OrgBluezDeviceInterface *device = getDevice(address, d_ptr); + if(!device) + return; + QDBusPendingReply<> deviceReply = device->SetProperty(QLatin1String("Trusted"), QDBusVariant(false)); + deviceReply.waitForFinished(); + if(deviceReply.isError()){ + qDebug() << Q_FUNC_INFO << "reply failed" << deviceReply.error(); + return; + } + delete device; + QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection, Q_ARG(QBluetoothAddress, address), + Q_ARG(QBluetoothLocalDevice::Pairing, QBluetoothLocalDevice::Paired)); + } + else { + QDBusPendingReply<QDBusObjectPath> reply = + d_ptr->adapter->CreatePairedDevice(address.toString(), + QDBusObjectPath(d_ptr->agent_path), + QLatin1String("NoInputNoOutput")); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), d_ptr, SLOT(pairingCompleted(QDBusPendingCallWatcher*))); + + if(reply.isError()) + qDebug() << Q_FUNC_INFO << reply.error() << d_ptr->agent_path; + } + } + else if(pairing == Unpaired) { + QDBusPendingReply<QDBusObjectPath> reply = this->d_ptr->adapter->FindDevice(address.toString()); + reply.waitForFinished(); + if(reply.isError()) { + qDebug() << Q_FUNC_INFO << "failed to find device" << reply.error(); + return; + } + QDBusPendingReply<> removeReply = this->d_ptr->adapter->RemoveDevice(reply.value()); + removeReply.waitForFinished(); + if(removeReply.isError()){ + qDebug() << Q_FUNC_INFO << "failed to remove device" << removeReply.error(); + } + return; + } + return; +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(const QBluetoothAddress &address) const +{ + OrgBluezDeviceInterface *device = getDevice(address, d_ptr); + + if(!device) + return Unpaired; + + QDBusPendingReply<QVariantMap> deviceReply = device->GetProperties(); + deviceReply.waitForFinished(); + if (deviceReply.isError()) + return Unpaired; + + QVariantMap map = deviceReply.value(); + +// qDebug() << "Paired: " << map.value("Paired"); + + + if (map.value(QLatin1String("Trusted")).toBool() && map.value(QLatin1String("Paired")).toBool()) + return AuthorizedPaired; + else if (map.value(QLatin1String("Paired")).toBool()) + return Paired; + else + return Unpaired; + +} + +QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate() + : adapter(0), agent(0), msgConnection(0) +{ + +} + +QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate() +{ + delete msgConnection; + delete adapter; + delete agent; +} + +void QBluetoothLocalDevicePrivate::RequestConfirmation(const QDBusObjectPath &in0, uint in1) +{ + Q_UNUSED(in0); + Q_Q(QBluetoothLocalDevice); + setDelayedReply(true); + msgConfirmation = message(); + msgConnection = new QDBusConnection(connection()); + emit q->pairingDisplayConfirmation(address, QString::fromLatin1("%1").arg(in1)); + return; +} + +void QBluetoothLocalDevice::pairingConfirmation(bool confirmation) +{ + if(!d_ptr || + !d_ptr->msgConfirmation.isReplyRequired() || + !d_ptr->msgConnection) + return; + + if(confirmation){ + QDBusMessage msg = d_ptr->msgConfirmation.createReply(QVariant(true)); + d_ptr->msgConnection->send(msg); + } + else { + QDBusMessage error = + d_ptr->msgConfirmation.createErrorReply(QDBusError::AccessDenied, + QLatin1String("Pairing rejected")); + d_ptr->msgConnection->send(error); + } + delete d_ptr->msgConnection; + d_ptr->msgConnection = 0; +} + +QString QBluetoothLocalDevicePrivate::RequestPinCode(const QDBusObjectPath &in0) +{ + Q_Q(QBluetoothLocalDevice); + qDebug() << Q_FUNC_INFO << in0.path(); + // seeded in constructor, 6 digit pin + QString pin = QString::fromLatin1("%1").arg(qrand()&1000000); + pin = QString::fromLatin1("%1").arg(pin, 6, QLatin1Char('0')); + + emit q->pairingDisplayPinCode(address, pin); + return pin; +} + +void QBluetoothLocalDevicePrivate::pairingCompleted(QDBusPendingCallWatcher *watcher) +{ + Q_Q(QBluetoothLocalDevice); + QDBusPendingReply<> reply = *watcher; + + if(reply.isError()) { + qDebug() << Q_FUNC_INFO << "failed to create pairing" << reply.error(); + emit q->pairingFinished(address, QBluetoothLocalDevice::Unpaired); + delete watcher; + return; + } + + QDBusPendingReply<QDBusObjectPath> findReply = adapter->FindDevice(address.toString()); + findReply.waitForFinished(); + if(findReply.isError()) { + qDebug() << Q_FUNC_INFO << "failed to find device" << findReply.error(); + emit q->pairingFinished(address, QBluetoothLocalDevice::Unpaired); + delete watcher; + return; + } + + OrgBluezDeviceInterface device(QLatin1String("org.bluez"), findReply.value().path(), + QDBusConnection::systemBus()); + + if(pairing == QBluetoothLocalDevice::AuthorizedPaired) { + device.SetProperty(QLatin1String("Trusted"), QDBusVariant(QVariant(true))); + emit q->pairingFinished(address, QBluetoothLocalDevice::AuthorizedPaired); + } + else { + device.SetProperty(QLatin1String("Trusted"), QDBusVariant(QVariant(false))); + emit q->pairingFinished(address, QBluetoothLocalDevice::Paired); + } + delete watcher; + +} + +void QBluetoothLocalDevicePrivate::Authorize(const QDBusObjectPath &in0, const QString &in1) +{ + qDebug() << "Got authorize for" << in0.path() << in1; +} + +void QBluetoothLocalDevicePrivate::Cancel() +{ + qDebug() << Q_FUNC_INFO; +} + +void QBluetoothLocalDevicePrivate::Release() +{ + qDebug() << Q_FUNC_INFO; +} + + +void QBluetoothLocalDevicePrivate::ConfirmModeChange(const QString &in0) +{ + qDebug() << Q_FUNC_INFO << in0; +} + +void QBluetoothLocalDevicePrivate::DisplayPasskey(const QDBusObjectPath &in0, uint in1, uchar in2) +{ + qDebug() << Q_FUNC_INFO << in0.path() << in1 << in2; +} + +uint QBluetoothLocalDevicePrivate::RequestPasskey(const QDBusObjectPath &in0) +{ + Q_UNUSED(in0); + qDebug() << Q_FUNC_INFO; + return qrand()&0x1000000; +} + + +void QBluetoothLocalDevicePrivate::PropertyChanged(QString property, QDBusVariant value) +{ + Q_UNUSED(value); + + if (property != QLatin1String("Powered") && + property != QLatin1String("Discoverable")) + return; + + Q_Q(QBluetoothLocalDevice); + QBluetoothLocalDevice::HostMode mode; + + QDBusPendingReply<QVariantMap> reply = adapter->GetProperties(); + reply.waitForFinished(); + if (reply.isError()){ + qWarning() << "Failed to get bluetooth properties for mode change"; + return; + } + + QVariantMap map = reply.value(); + + if(!map.value(QLatin1String("Powered")).toBool()){ + mode = QBluetoothLocalDevice::HostPoweredOff; + } + else { + if (map.value(QLatin1String("Discoverable")).toBool()) + mode = QBluetoothLocalDevice::HostDiscoverable; + else + mode = QBluetoothLocalDevice::HostConnectable; + } + + if(mode != currentMode) + emit q->hostModeStateChanged(mode); + + currentMode = mode; +} + +//#include "qbluetoothlocaldevice.moc" +#include "moc_qbluetoothlocaldevice_p.cpp" diff --git a/src/bluetooth/qbluetoothlocaldevice_p.cpp b/src/bluetooth/qbluetoothlocaldevice_p.cpp new file mode 100644 index 00000000..8173d26e --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_p.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qbluetoothlocaldevice.h" +#include "qbluetoothaddress.h" + + +QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) +: QObject(parent) +{ +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) +: QObject(parent) +{ +} + +QString QBluetoothLocalDevice::name() const +{ + return QString(); +} + +QBluetoothAddress QBluetoothLocalDevice::address() const +{ + return QBluetoothAddress(); +} + +void QBluetoothLocalDevice::powerOn() +{ +} + +void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) +{ + Q_UNUSED(mode); +} + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const +{ + return HostPoweredOff; +} + +QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices() +{ + QList<QBluetoothHostInfo> localDevices; + return localDevices; +} + +void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + Q_UNUSED(address); + Q_UNUSED(pairing); +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(const QBluetoothAddress &address) const +{ + Q_UNUSED(address); + return Unpaired; +} + +void QBluetoothLocalDevice::pairingConfirmation(bool confirmation) +{ + Q_UNUSED(confirmation); +} + diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h new file mode 100644 index 00000000..ae461907 --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_p.h @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHLOCALDEVICE_P_H +#define QBLUETOOTHLOCALDEVICE_P_H + +#include "../qtconnectivityglobal.h" + +#include "qbluetoothlocaldevice.h" + +#ifdef QT_SYMBIAN_BLUETOOTH +#include <e32base.h> +#include <btengsettings.h> +#endif + +#ifdef QT_BLUEZ_BLUETOOTH +#include <QObject> +#include <QDBusContext> +#include <QDBusObjectPath> +#include <QDBusMessage> + +class OrgBluezAdapterInterface; +class OrgBluezAgentAdaptor; +class QDBusPendingCallWatcher; +#endif + +QT_BEGIN_HEADER + +class QBluetoothAddress; + +#ifdef QT_BLUEZ_BLUETOOTH +class QBluetoothLocalDevicePrivate : public QObject, + protected QDBusContext +{ + Q_OBJECT + Q_DECLARE_PUBLIC(QBluetoothLocalDevice) +public: + QBluetoothLocalDevicePrivate(); + ~QBluetoothLocalDevicePrivate(); + + OrgBluezAdapterInterface *adapter; + OrgBluezAgentAdaptor *agent; + QString agent_path; + QBluetoothAddress address; + QBluetoothLocalDevice::Pairing pairing; + QBluetoothLocalDevice::HostMode currentMode; + +public Q_SLOTS: // METHODS + void Authorize(const QDBusObjectPath &in0, const QString &in1); + void Cancel(); + void ConfirmModeChange(const QString &in0); + void DisplayPasskey(const QDBusObjectPath &in0, uint in1, uchar in2); + void Release(); + uint RequestPasskey(const QDBusObjectPath &in0); + + void RequestConfirmation(const QDBusObjectPath &in0, uint in1); + QString RequestPinCode(const QDBusObjectPath &in0); + + void pairingCompleted(QDBusPendingCallWatcher*); + + void PropertyChanged(QString,QDBusVariant); + +private: + QDBusMessage msgConfirmation; + QDBusConnection *msgConnection; + + QBluetoothLocalDevice *q_ptr; +}; +#endif + +#ifdef QT_SYMBIAN_BLUETOOTH +class QBluetoothLocalDevicePrivate + : public MBTEngSettingsObserver +{ + Q_DECLARE_PUBLIC(QBluetoothLocalDevice) +public: + QBluetoothLocalDevicePrivate(); + ~QBluetoothLocalDevicePrivate(); + + static QString name(); + static QBluetoothAddress address(); + + void powerOn(); + void powerOff(); + void setHostMode(QBluetoothLocalDevice::HostMode mode); + QBluetoothLocalDevice::HostMode hostMode() const; + + void requestPairing(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + QBluetoothLocalDevice::Pairing pairingStatus(const QBluetoothAddress &address) const; + + void pairingConfirmation(bool confirmation); + //slots exposed for the public api. + void _q_pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + void _q_registryError(int error); + void _q_pairingError(int error); + +private: + //From MBTEngSettingsObserver + void PowerStateChanged(TBTPowerStateValue aState); + void VisibilityModeChanged(TBTVisibilityMode aState); + +private: + CBTEngSettings *m_settings; + +protected: + QBluetoothLocalDevice *q_ptr; + +}; +#endif + +QT_END_HEADER + +#endif // QBLUETOOTHLOCALDEVICE_P_H diff --git a/src/bluetooth/qbluetoothlocaldevice_symbian.cpp b/src/bluetooth/qbluetoothlocaldevice_symbian.cpp new file mode 100644 index 00000000..d842d3dc --- /dev/null +++ b/src/bluetooth/qbluetoothlocaldevice_symbian.cpp @@ -0,0 +1,421 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothlocaldevice_p.h" + +#include "qbluetoothlocaldevice.h" +#include <QtCore/QString> +#include "symbian/utils_symbian_p.h" +#include <bttypes.h> +#include <bt_subscribe.h> +#ifdef USING_BTENGCONNMAN +#include "bluetoothsymbianpairingadapter.h" +#endif //USING_BTENGCONNMAN +#ifdef USING_BTENGDEVMAN +#include "bluetoothsymbianregistryadapter.h" +#endif //USING_BTENGDEVMAN + + +QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate() + : m_settings(NULL) +{ + TRAPD(err, m_settings = CBTEngSettings::NewL(this)); + if (err != KErrNone) { + Q_Q(QBluetoothLocalDevice); + emit q->error(QBluetoothLocalDevice::UnknownError); + m_settings = NULL; + } +} + +QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate() +{ + delete m_settings; +} + +QString QBluetoothLocalDevicePrivate::name() +{ + CBTEngSettings *settings = NULL; + TRAPD(err, settings = CBTEngSettings::NewL()); + if (err != KErrNone) + return QString(); + HBufC *localName = NULL; + TRAPD(error, localName = HBufC::NewL(256)); + if (error != KErrNone) { + delete settings; + return QString(); + } + TPtr localPtr = localName->Des(); + TInt errorCode = settings->GetLocalName(localPtr); + QString name; + if (errorCode == KErrNone) + name = s60DescToQString(localPtr); + + delete localName; + delete settings; + return name; +} + +QBluetoothAddress QBluetoothLocalDevicePrivate::address() +{ + TBuf<20> bluetoothAddress; + TPckgBuf<TBTDevAddr> addressPackage; + + TInt error = RProperty::Get(KUidSystemCategory, KPropertyKeyBluetoothGetLocalDeviceAddress, addressPackage); + + if (error != KErrNone) + return QBluetoothAddress(); + + addressPackage().GetReadable(bluetoothAddress, KNullDesC, _L(":"), KNullDesC); + + return QBluetoothAddress(s60DescToQString(bluetoothAddress)); +} + +void QBluetoothLocalDevicePrivate::powerOn() +{ + if (!m_settings) + return; + TBTPowerStateValue powerState; + TInt error = m_settings->GetPowerState(powerState); + if (error == KErrNone && powerState == EBTPowerOff) + m_settings->SetPowerState(EBTPowerOn); + else if (error != KErrNone) { + Q_Q(QBluetoothLocalDevice); + emit q->error(QBluetoothLocalDevice::UnknownError); + } +} +void QBluetoothLocalDevicePrivate::powerOff() +{ + if (!m_settings) + return; + TBTPowerStateValue powerState; + TInt error = m_settings->GetPowerState(powerState); + if (error == KErrNone && powerState == EBTPowerOn) + m_settings->SetPowerState(EBTPowerOff); + else if (error != KErrNone) { + Q_Q(QBluetoothLocalDevice); + emit q->error(QBluetoothLocalDevice::UnknownError); + } +} +void QBluetoothLocalDevicePrivate::setHostMode(QBluetoothLocalDevice::HostMode mode) +{ + if (!m_settings) + return; + + TInt error = KErrNone; + switch (mode) { + case QBluetoothLocalDevice::HostPoweredOff: + powerOff(); + break; + case QBluetoothLocalDevice::HostConnectable: { + TBTPowerStateValue powerState; + error = m_settings->GetPowerState(powerState); + if (error == KErrNone) { + if (powerState == EBTPowerOff) { + error = m_settings->SetPowerState(EBTPowerOn); + } + TBTVisibilityMode visibilityMode; + error = m_settings->GetVisibilityMode(visibilityMode); + if (visibilityMode != EBTVisibilityModeHidden) { + error = m_settings->SetVisibilityMode(EBTVisibilityModeHidden); + } + } + break; + } + case QBluetoothLocalDevice::HostDiscoverable: { + TBTPowerStateValue powerState; + error = m_settings->GetPowerState(powerState); + if (error == KErrNone) { + if (powerState == EBTPowerOff) { + error = m_settings->SetPowerState(EBTPowerOn); + } + TBTVisibilityMode visibilityMode; + error = m_settings->GetVisibilityMode(visibilityMode); + if (visibilityMode != EBTVisibilityModeGeneral) { + error = m_settings->SetVisibilityMode(EBTVisibilityModeGeneral); + } + } + break; + } + } + if (error != KErrNone) { + Q_Q(QBluetoothLocalDevice); + emit q->error(QBluetoothLocalDevice::UnknownError); + } +} + + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevicePrivate::hostMode() const +{ + if (!m_settings) + return QBluetoothLocalDevice::HostPoweredOff; + + TBTVisibilityMode visibilityMode; + TInt error = m_settings->GetVisibilityMode(visibilityMode); + + if (error != KErrNone) + return QBluetoothLocalDevice::HostPoweredOff; + + //If we are powered off then we don't are neither connectable or discoverable + TBTPowerStateValue powerState; + error = m_settings->GetPowerState(powerState); + if (error == KErrNone && powerState == EBTPowerOff) + return QBluetoothLocalDevice::HostPoweredOff; + + switch (visibilityMode) { + case EBTVisibilityModeHidden: + return QBluetoothLocalDevice::HostConnectable; + case EBTVisibilityModeGeneral: + case EBTVisibilityModeTemporary: + return QBluetoothLocalDevice::HostDiscoverable; + default: + // default value, also includes these new values from Symbian^3 onwards + // case EBTVisibilityModeNoScans: + // case EBTVisibilityModeInquiryScanOnly: + return QBluetoothLocalDevice::HostPoweredOff; + } +} + +void QBluetoothLocalDevicePrivate::PowerStateChanged(TBTPowerStateValue aState) +{ + QBluetoothLocalDevice::HostMode hostMode; + switch (aState) { + case EBTPowerOn: + hostMode = this->hostMode(); + break; + case EBTPowerOff: + default: + hostMode = QBluetoothLocalDevice::HostPoweredOff; + break; + } + Q_Q(QBluetoothLocalDevice); + emit q->hostModeStateChanged(hostMode); +} + +void QBluetoothLocalDevicePrivate::VisibilityModeChanged(TBTVisibilityMode aState) +{ + QBluetoothLocalDevice::HostMode hostMode; + switch (aState) { + case EBTVisibilityModeHidden: + hostMode = QBluetoothLocalDevice::HostConnectable; + break; + case EBTVisibilityModeGeneral: + case EBTVisibilityModeTemporary: + hostMode = QBluetoothLocalDevice::HostDiscoverable; + break; + default: + // default value, also includes these new values from Symbian^3 onwards + // case EBTVisibilityModeNoScans: + // case EBTVisibilityModeInquiryScanOnly: + hostMode = QBluetoothLocalDevice::HostPoweredOff; + break; + } + Q_Q(QBluetoothLocalDevice); + emit q->hostModeStateChanged(hostMode); +} + +void QBluetoothLocalDevicePrivate::requestPairing(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing) +{ +//#ifdef USING_BTENGCONNMAN +#ifdef USING_BTENGDEVMAN + Q_Q(QBluetoothLocalDevice); + + BluetoothSymbianRegistryAdapter *registryAdapter = new BluetoothSymbianRegistryAdapter(address,q); + // do nothing if everything is uptodate. + if (registryAdapter->pairingStatus() == pairing) { + _q_pairingFinished(address, pairing); + return; + } + // pass q pointer so that adapter gets deleted when q object is deleted. Not optimal though. + BluetoothSymbianPairingAdapter *pairingAdapter = new BluetoothSymbianPairingAdapter(address,q); + + // After pairing has completed we emit pairingFinished signal in every case. + // earlier we checked pairing status from Symbian Bluetooth registry at this point but it + // was not updated and the result was that we emitted wrong pairing status. + QObject::connect(pairingAdapter, SIGNAL(pairingFinished(const QBluetoothAddress&,QBluetoothLocalDevice::Pairing)), + q, SLOT(_q_pairingFinished(const QBluetoothAddress&,QBluetoothLocalDevice::Pairing))); + // if pairing status changes then emit pairing finished. + // Currently this is used after removing a paired device from Symbian Bluetooth registry + QObject::connect(registryAdapter, SIGNAL(pairingStatusChanged(const QBluetoothAddress&,QBluetoothLocalDevice::Pairing)), + q, SLOT(_q_pairingFinished(const QBluetoothAddress&,QBluetoothLocalDevice::Pairing))); + // if there are pairing errors, emit them + QObject::connect(registryAdapter, SIGNAL(registryHandlingError(int)), + q, SLOT(_q_registryError(int))); + QObject::connect(pairingAdapter, SIGNAL(pairingError(int)), + q, SLOT(_q_pairingError(int))); + + switch (pairing) { + case QBluetoothLocalDevice::Unpaired: + // this is async method + registryAdapter->removePairing(); + break; + case QBluetoothLocalDevice::Paired: + case QBluetoothLocalDevice::AuthorizedPaired: + // this is async method + // Note: currently Symbian pairing function puts up a user dialog to confirm authorization; + // due to this, we cannot be sure if authorization is done or not, since it depends on user response + pairingAdapter->startPairing(pairing); + break; + default: + ASSERT(0); + break; + } +#endif //USING_BTENGDEVMAN +//#endif USING_BTENGCONNMAN +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevicePrivate::pairingStatus(const QBluetoothAddress &address) const +{ +#ifdef USING_BTENGDEVMAN + QScopedPointer<BluetoothSymbianRegistryAdapter> registryAdapter (new BluetoothSymbianRegistryAdapter(address)); + return registryAdapter->pairingStatus(); +#endif //USING_BTENGDEVMAN +} + +void QBluetoothLocalDevicePrivate::pairingConfirmation(bool confirmation) +{ +} + +void QBluetoothLocalDevicePrivate::_q_pairingFinished(const QBluetoothAddress &address,QBluetoothLocalDevice::Pairing pairing) +{ + Q_Q(QBluetoothLocalDevice); + emit q->pairingFinished(address, pairing); +} +void QBluetoothLocalDevicePrivate::_q_registryError(int error) +{ + Q_Q(QBluetoothLocalDevice); + //TODO Add more errorCodes to LocalDevice api and map them to Symbian errorcodes + emit q->error(QBluetoothLocalDevice::UnknownError); +} +void QBluetoothLocalDevicePrivate::_q_pairingError(int error) +{ + Q_Q(QBluetoothLocalDevice); + //TODO Add more errorCodes to LocalDevice api and map them to Symbian errorcodes + emit q->error(QBluetoothLocalDevice::PairingError); +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) +: QObject(parent), d_ptr(new QBluetoothLocalDevicePrivate()) +{ + d_ptr->q_ptr = this; + if (this->d_ptr->m_settings == NULL) { + delete this->d_ptr; + this->d_ptr = NULL; + } +} + +QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) +: QObject(parent), d_ptr(new QBluetoothLocalDevicePrivate()) +{ + d_ptr->q_ptr = this; + if (this->d_ptr->m_settings == NULL || address != this->d_ptr->address()) { + delete this->d_ptr; + this->d_ptr = NULL; + } +} + +QString QBluetoothLocalDevice::name() const +{ + if (!d_ptr) + return QString(); + return d_ptr->name(); +} + +QBluetoothAddress QBluetoothLocalDevice::address() const +{ + if (!d_ptr) + return QBluetoothAddress(); + return d_ptr->address(); +} + +void QBluetoothLocalDevice::powerOn() +{ + if (!d_ptr) + return; + d_ptr->powerOn(); +} + +void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) +{ + if (!d_ptr) + return; + d_ptr->setHostMode(mode); +} + +QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const +{ + if (!d_ptr) + return HostPoweredOff; + return d_ptr->hostMode(); +} + +QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices() +{ + QList<QBluetoothHostInfo> localDevices; + QBluetoothHostInfo hostInfo; + hostInfo.setName(QBluetoothLocalDevicePrivate::name()); + hostInfo.setAddress(QBluetoothLocalDevicePrivate::address()); + localDevices.append(hostInfo); + return localDevices; +} + +void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) +{ + if (!d_ptr) + return; + + return d_ptr->requestPairing(address, pairing); +} + +QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(const QBluetoothAddress &address) const +{ + if (!d_ptr) + return QBluetoothLocalDevice::Unpaired; + + return d_ptr->pairingStatus(address); +} + +void QBluetoothLocalDevice::pairingConfirmation(bool confirmation) +{ + if (!d_ptr) + return; + + return d_ptr->pairingConfirmation(confirmation); +} diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.cpp b/src/bluetooth/qbluetoothservicediscoveryagent.cpp new file mode 100644 index 00000000..754e07e0 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent.cpp @@ -0,0 +1,412 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothservicediscoveryagent_p.h" + +#include "qbluetoothdevicediscoveryagent.h" + +/*! + \class QBluetoothServiceDiscoveryAgent + \brief The QBluetoothServiceDiscoveryAgent class provides an API for querying the services + provided by a Bluetooth device. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + To query the services provided by all contactable Bluetooth devices create an instance of + QBluetoothServiceDiscoveryAgent, connect to either the serviceDiscovered() or finished() + signals and call start(). + + \snippet snippets/connectivity/servicediscovery.cpp Service discovery + + By default a minimal service discovery is performed. In this mode the QBluetotohServiceInfo + objects returned are guaranteed to contain only device and service UUID information. Depending + on platform and device capabilities other service information may also be available. For most + use cases this is adequate as QBluetoothSocket::connectToService() will perform additional + discovery if required. If full service information is required pass \l FullDiscovery as the + discoveryMode parameter to start(). +*/ + +/*! + \enum QBluetoothServiceDiscoveryAgent::Error + + This enum describes errors that can occur during service discovery. + + \value NoError No error. + \value DeviceDiscoveryError Error occurred during device discovery. + \value UnknownError An unidentified error occurred. +*/ + +/*! + \enum QBluetoothServiceDiscoveryAgent::DiscoveryMode + + This enum describes the service discovery mode. + + \value MinimalDiscovery Performs a minimal service discovery. The QBluetoothServiceInfo + objects returned may be incomplete and are only guaranteed to + contain device and service UUID information. + \value FullDiscovery Performs a full service discovery. +*/ + +/*! + \fn QBluetoothServiceDiscoveryAgent::serviceDiscovered(const QBluetoothServiceInfo &info) + + This signal is emitted when the Bluetooth service described by \a info is discovered. +*/ + +/*! + \fn QBluetoothServiceDiscoveryAgent::finished() + + This signal is emitted when Bluetooth service discovery completes. +*/ + +/*! + \fn void QBluetoothServiceDiscoveryAgent::error(QBluetoothServiceDiscoveryAgent::Error error) + + This signal is emitted when an error occurs. The \a error parameter describes the error that + occurred. +*/ + +/*! + Constructs a new QBluetoothServiceDiscoveryAgent with \a parent. Services will be discovered on all + contactable devices. +*/ +QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(QObject *parent) +: QObject(parent), d_ptr(new QBluetoothServiceDiscoveryAgentPrivate(QBluetoothAddress())) +{ + d_ptr->q_ptr = this; +} + +/*! + Constructs a new QBluetoothServiceDiscoveryAgent for \a remoteAddress and with \a parent. + + If \a remoteAddress is null services will be discovred on all contactable Bluetooth + devices. +*/ +QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &remoteAddress, QObject *parent) +: QObject(parent), d_ptr(new QBluetoothServiceDiscoveryAgentPrivate(remoteAddress)) +{ + d_ptr->q_ptr = this; + if (!remoteAddress.isNull()) { + d_ptr->singleDevice = true; + } +} + +/*! + + Destructor for QBluetoothServiceDiscoveryAgent + +*/ + +QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent() +{ + delete d_ptr; +} + +/*! + Returns the list of all discovered services. +*/ +QList<QBluetoothServiceInfo> QBluetoothServiceDiscoveryAgent::discoveredServices() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + + return d->discoveredServices; +} +/*! + Sets the UUID filter to \a uuids. Only services matching the UUIDs in \a uuids will be + returned. + + An empty UUID list is equivalent to a list containing only QBluetoothUuid::PublicBrowseGroup. + + \sa uuidFilter() +*/ +void QBluetoothServiceDiscoveryAgent::setUuidFilter(const QList<QBluetoothUuid> &uuids) +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + d->uuidFilter = uuids; +} + +/*! + This is an overloaded member function, provided for convenience. + + Sets the UUID filter to a list containing the single element \a uuid. + + \sa uuidFilter() +*/ +void QBluetoothServiceDiscoveryAgent::setUuidFilter(const QBluetoothUuid &uuid) +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + d->uuidFilter.clear(); + d->uuidFilter.append(uuid); +} + +/*! + Returns the UUID filter. + + \sa setUuidFilter() +*/ +QList<QBluetoothUuid> QBluetoothServiceDiscoveryAgent::uuidFilter() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + + return d->uuidFilter; +} + +/*! + Starts service discovery. \a mode specifies the type of service discovery to perform. + + \sa DiscoveryMode +*/ +void QBluetoothServiceDiscoveryAgent::start(DiscoveryMode mode) +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + if (d->discoveryState() == QBluetoothServiceDiscoveryAgentPrivate::Inactive) { + d->setDiscoveryMode(mode); + if (d->deviceAddress.isNull()) { + d->startDeviceDiscovery(); + } else { + d->discoveredDevices << QBluetoothDeviceInfo(d->deviceAddress, QString(), 0); + d->startServiceDiscovery(); + } + } +} + +/*! + Stops service discovery. +*/ +void QBluetoothServiceDiscoveryAgent::stop() +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + switch (d->discoveryState()) { + case QBluetoothServiceDiscoveryAgentPrivate::DeviceDiscovery: + d->stopDeviceDiscovery(); + break; + case QBluetoothServiceDiscoveryAgentPrivate::ServiceDiscovery: + d->stopServiceDiscovery(); + default: + ; + } + + d->discoveredDevices.clear(); +} + +/*! + Clears the results of a previous service discovery. +*/ +void QBluetoothServiceDiscoveryAgent::clear() +{ + Q_D(QBluetoothServiceDiscoveryAgent); + + d->discoveredDevices.clear(); + d->discoveredServices.clear(); + d->uuidFilter.clear(); +} + +/*! + Returns true if service discovery is currently active, otherwise returns false. +*/ +bool QBluetoothServiceDiscoveryAgent::isActive() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + + return d->state != QBluetoothServiceDiscoveryAgentPrivate::Inactive; +} + +/*! + Returns the type of error that last occurred. If service discovery is done + on a signle address it will returns errors when trying to discover services + on that device. If the alternate constructor is used and devices are + discovered by a scan, then errors doing service discovery on individual + devices are not saved and no signals are emitted. In this case errors are + fairly normal since some devices may not respond to discovery or + may no longer be in range. As such errors are surpressed. If no services + are returned, it can be assumed no services could be discovered. + +*/ +QBluetoothServiceDiscoveryAgent::Error QBluetoothServiceDiscoveryAgent::error() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + + return d->error; +} + +/*! + Returns a human-readable description of the last error that occurred when + doing service discovery on a single device. +*/ +QString QBluetoothServiceDiscoveryAgent::errorString() const +{ + Q_D(const QBluetoothServiceDiscoveryAgent); + return d->errorString; +} + + +/*! + \fn QBluetoothServiceDiscoveryAgent::canceled() + Signals the cancellation of the service discovery. + */ + + +/*! + Starts device discovery. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::startDeviceDiscovery() +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + if (!deviceDiscoveryAgent) { + deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent; + QObject::connect(deviceDiscoveryAgent, SIGNAL(finished()), + q, SLOT(_q_deviceDiscoveryFinished())); + QObject::connect(deviceDiscoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), + q, SLOT(_q_deviceDiscovered(QBluetoothDeviceInfo))); + + } + + setDiscoveryState(DeviceDiscovery); + + deviceDiscoveryAgent->start(); +} + +/*! + Stops device discovery. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::stopDeviceDiscovery() +{ + deviceDiscoveryAgent->stop(); + delete deviceDiscoveryAgent; + deviceDiscoveryAgent = 0; + + setDiscoveryState(Inactive); + + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->canceled(); +} + +/*! + Called when device discovery finishes. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryFinished() +{ + if (deviceDiscoveryAgent->error() != QBluetoothDeviceDiscoveryAgent::NoError) { + error = QBluetoothServiceDiscoveryAgent::DeviceDiscoveryError; + + setDiscoveryState(Inactive); + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->finished(); + return; + } + +// discoveredDevices = deviceDiscoveryAgent->discoveredDevices(); + + delete deviceDiscoveryAgent; + deviceDiscoveryAgent = 0; + + startServiceDiscovery(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered(const QBluetoothDeviceInfo &info) +{ + if(mode == QBluetoothServiceDiscoveryAgent::FullDiscovery) { + // look for duplicates, and cached entries + for(int i = 0; i < discoveredDevices.count(); i++){ + if(discoveredDevices.at(i).address() == info.address()){ + discoveredDevices.removeAt(i); + } + } + discoveredDevices.prepend(info); + } + else { + for(int i = 0; i < discoveredDevices.count(); i++){ + if(discoveredDevices.at(i).address() == info.address()){ + discoveredDevices.removeAt(i); + } + } + discoveredDevices.prepend(info); + } +} + +/*! + Starts service discovery for the next device. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::startServiceDiscovery() +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + setDiscoveryState(ServiceDiscovery); + + if (discoveredDevices.isEmpty()) { + setDiscoveryState(Inactive); + emit q->finished(); + return; + } + + setDiscoveryState(ServiceDiscovery); + start(discoveredDevices.at(0).address()); +} + +/*! + Stops service discovery. +*/ +void QBluetoothServiceDiscoveryAgentPrivate::stopServiceDiscovery() +{ + stop(); + + setDiscoveryState(Inactive); +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_serviceDiscoveryFinished() +{ + if(!discoveredDevices.isEmpty()) { + discoveredDevices.removeFirst(); + } + + startServiceDiscovery(); +} + + +#include "moc_qbluetoothservicediscoveryagent.cpp" diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.h b/src/bluetooth/qbluetoothservicediscoveryagent.h new file mode 100644 index 00000000..042ef190 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHSERVICEDISCOVERYAGENT_H +#define QBLUETOOTHSERVICEDISCOVERYAGENT_H + +#include "../qtconnectivityglobal.h" + +#include <QObject> + +#include <qbluetoothserviceinfo.h> +#include <qbluetoothuuid.h> + +QT_BEGIN_HEADER + +class QBluetoothAddress; +class QBluetoothServiceDiscoveryAgentPrivate; + +class Q_CONNECTIVITY_EXPORT QBluetoothServiceDiscoveryAgent : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QBluetoothServiceDiscoveryAgent) + +public: + enum Error { + NoError, + DeviceDiscoveryError, + UnknownError = 100 + }; + + enum DiscoveryMode { + MinimalDiscovery, + FullDiscovery + }; + + QBluetoothServiceDiscoveryAgent(QObject *parent = 0); + explicit QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &remoteAddress, QObject *parent = 0); + ~QBluetoothServiceDiscoveryAgent(); + + bool isActive() const; + + Error error() const; + QString errorString() const; + + QList<QBluetoothServiceInfo> discoveredServices() const; + + void setUuidFilter(const QList<QBluetoothUuid> &uuids); + void setUuidFilter(const QBluetoothUuid &uuid); + QList<QBluetoothUuid> uuidFilter() const; + +public slots: + void start(DiscoveryMode mode = MinimalDiscovery); + void stop(); + void clear(); + +signals: + void serviceDiscovered(const QBluetoothServiceInfo &info); + void finished(); + void canceled(); + void error(QBluetoothServiceDiscoveryAgent::Error error); + +private: + QBluetoothServiceDiscoveryAgentPrivate *d_ptr; + + Q_PRIVATE_SLOT(d_func(), void _q_deviceDiscovered(const QBluetoothDeviceInfo &info)) + Q_PRIVATE_SLOT(d_func(), void _q_deviceDiscoveryFinished()) + Q_PRIVATE_SLOT(d_func(), void _q_serviceDiscoveryFinished()) +#ifdef QT_BLUEZ_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_discoveredServices(QDBusPendingCallWatcher*)) + Q_PRIVATE_SLOT(d_func(), void _q_createdDevice(QDBusPendingCallWatcher*)) +#endif +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp new file mode 100644 index 00000000..abcaa23d --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothservicediscoveryagent_p.h" + +#include "bluez/manager_p.h" +#include "bluez/adapter_p.h" +#include "bluez/device_p.h" + +#include <QtDBus/QDBusPendingCallWatcher> + +//#define QTM_SERVICEDISCOVERY_DEBUG + +#ifdef QTM_SERVICEDISCOVERY_DEBUG +#include <QtCore/QDebug> +#endif + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &address) +: error(QBluetoothServiceDiscoveryAgent::NoError), state(Inactive), deviceAddress(address), + deviceDiscoveryAgent(0), mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), + singleDevice(false), manager(0), device(0) +{ + qRegisterMetaType<ServiceMap>("ServiceMap"); + qDBusRegisterMetaType<ServiceMap>(); +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ + delete device; + delete manager; +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << "Full discovery on: " << address.toString(); +#endif + + manager = new OrgBluezManagerInterface(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> reply = manager->DefaultAdapter(); + reply.waitForFinished(); + if (reply.isError()) { + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::DeviceDiscoveryError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Unable to find default adapter"); + emit q->error(error); + } + _q_serviceDiscoveryFinished(); + return; + } + + adapter = new OrgBluezAdapterInterface(QLatin1String("org.bluez"), reply.value().path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter->CreateDevice(address.toString()); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(deviceObjectPath, q); + watcher->setProperty("_q_BTaddress", QVariant::fromValue(address)); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + q, SLOT(_q_createdDevice(QDBusPendingCallWatcher*))); + +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO << "Stop called"; +#endif + if(device){ + QDBusPendingReply<> reply = device->CancelDiscovery(); + reply.waitForFinished(); + + discoveredDevices.clear(); + setDiscoveryState(Inactive); + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->canceled(); + +// qDebug() << "Stop done"; + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWatcher *watcher) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + const QBluetoothAddress &address = watcher->property("_q_BTaddress").value<QBluetoothAddress>(); + +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO << "created" << address.toString(); +#endif + + QDBusPendingReply<QDBusObjectPath> deviceObjectPath = *watcher; + if (deviceObjectPath.isError()) { + if (deviceObjectPath.error().name() != QLatin1String("org.bluez.Error.AlreadyExists")) { + _q_serviceDiscoveryFinished(); +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << "Create device failed Error: " << error << deviceObjectPath.error().name(); +#endif + return; + } + + deviceObjectPath = adapter->FindDevice(address.toString()); + deviceObjectPath.waitForFinished(); + if (deviceObjectPath.isError()) { + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::DeviceDiscoveryError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Unable to access device"); + emit q->error(error); + } + _q_serviceDiscoveryFinished(); +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << "Can't find device after creation Error: " << error << deviceObjectPath.error().name(); +#endif + return; + } + } + + device = new OrgBluezDeviceInterface(QLatin1String("org.bluez"), + deviceObjectPath.value().path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QVariantMap> deviceReply = device->GetProperties(); + deviceReply.waitForFinished(); + if(deviceReply.isError()) + return; + QVariantMap v = deviceReply.value(); + QStringList device_uuids = v.value(QLatin1String("UUIDs")).toStringList(); + + QString pattern; + foreach (const QBluetoothUuid &uuid, uuidFilter) + pattern += uuid.toString().remove(QLatin1Char('{')).remove(QLatin1Char('}')) + QLatin1Char(' '); + +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO << "Discover: " << pattern.trimmed(); +#endif + QDBusPendingReply<ServiceMap> discoverReply = device->DiscoverServices(pattern.trimmed()); + watcher = new QDBusPendingCallWatcher(discoverReply, q); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + q, SLOT(_q_discoveredServices(QDBusPendingCallWatcher*))); + +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredServices(QDBusPendingCallWatcher *watcher) +{ +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << Q_FUNC_INFO; +#endif + + QDBusPendingReply<ServiceMap> reply = *watcher; + if (reply.isError()) { +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << "discoveredServices error: " << error << reply.error().message(); +#endif + watcher->deleteLater(); + if (singleDevice) { + Q_Q(QBluetoothServiceDiscoveryAgent); + error = QBluetoothServiceDiscoveryAgent::UnknownError; + errorString = reply.error().message(); + emit q->error(error); + } + _q_serviceDiscoveryFinished(); + return; + } + + ServiceMap map = reply.value(); + +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << "Parsing xml" << discoveredDevices.at(0).address().toString() << discoveredDevices.count() << map.count(); +#endif + + foreach (const QString &record, reply.value()) { + QXmlStreamReader xml(record); + +#ifdef QTM_SERVICEDISCOVERY_DEBUG + // qDebug() << "Service xml" << record; +#endif + + QBluetoothServiceInfo serviceInfo; + serviceInfo.setDevice(discoveredDevices.at(0)); + + while (!xml.atEnd()) { + xml.readNext(); + + if (xml.tokenType() == QXmlStreamReader::StartElement && + xml.name() == QLatin1String("attribute")) { + quint16 attributeId = + xml.attributes().value(QLatin1String("id")).toString().toUShort(0, 0); + + if (xml.readNextStartElement()) { + QVariant value = readAttributeValue(xml); + + serviceInfo.setAttribute(attributeId, value); + } + } + } + + if (!serviceInfo.isValid()) + continue; + + Q_Q(QBluetoothServiceDiscoveryAgent); + + discoveredServices.append(serviceInfo); +#ifdef QTM_SERVICEDISCOVERY_DEBUG + qDebug() << "Discovered services" << discoveredDevices.at(0).address().toString(); +#endif + emit q->serviceDiscovered(serviceInfo); + // could stop discovery, check for state + if(discoveryState() == Inactive){ + qDebug() << "Exit discovery after stop"; + break; + } + } + + watcher->deleteLater(); + + _q_serviceDiscoveryFinished(); +} + +QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamReader &xml) +{ + if (xml.name() == QLatin1String("boolean")) { + const QString value = xml.attributes().value(QLatin1String("value")).toString(); + xml.skipCurrentElement(); + return value == QLatin1String("true"); + } else if (xml.name() == QLatin1String("uint8")) { + quint8 value = xml.attributes().value(QLatin1String("value")).toString().toUShort(0, 0); + xml.skipCurrentElement(); + return value; + } else if (xml.name() == QLatin1String("uint16")) { + quint16 value = xml.attributes().value(QLatin1String("value")).toString().toUShort(0, 0); + xml.skipCurrentElement(); + return value; + } else if (xml.name() == QLatin1String("uint32")) { + quint32 value = xml.attributes().value(QLatin1String("value")).toString().toUInt(0, 0); + xml.skipCurrentElement(); + return value; + } else if (xml.name() == QLatin1String("uint64")) { + quint64 value = xml.attributes().value(QLatin1String("value")).toString().toULongLong(0, 0); + xml.skipCurrentElement(); + return value; + } else if (xml.name() == QLatin1String("uuid")) { + QBluetoothUuid uuid; + const QString value = xml.attributes().value(QLatin1String("value")).toString(); + if (value.startsWith(QLatin1String("0x"))) { + if (value.length() == 6) { + quint16 v = value.toUShort(0, 0); + uuid = QBluetoothUuid(v); + } else if (value.length() == 10) { + quint32 v = value.toUInt(0, 0); + uuid = QBluetoothUuid(v); + } + } else { + uuid = QBluetoothUuid(value); + } + xml.skipCurrentElement(); + return QVariant::fromValue(uuid); + } else if (xml.name() == QLatin1String("text")) { + QString value = xml.attributes().value(QLatin1String("value")).toString(); + if (xml.attributes().value(QLatin1String("encoding")) == QLatin1String("hex")) + value = QString::fromUtf8(QByteArray::fromHex(value.toAscii())); + xml.skipCurrentElement(); + return value; + } else if (xml.name() == QLatin1String("sequence")) { + QBluetoothServiceInfo::Sequence sequence; + + while (xml.readNextStartElement()) { + QVariant value = readAttributeValue(xml); + sequence.append(value); + } + + return QVariant::fromValue<QBluetoothServiceInfo::Sequence>(sequence); + } else { + qWarning("unknown attribute type %s %s", + xml.name().toString().toLocal8Bit().constData(), + xml.attributes().value(QLatin1String("value")).toString().toLocal8Bit().constData()); + Q_ASSERT(false); + xml.skipCurrentElement(); + return QVariant(); + } +} diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp new file mode 100644 index 00000000..fd82a5d3 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothservicediscoveryagent_p.h" + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &address) +{ + Q_UNUSED(address); +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + Q_UNUSED(address); +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ +} diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h new file mode 100644 index 00000000..e60a1ae3 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHSERVICEDISCOVERYAGENT_P_H +#define QBLUETOOTHSERVICEDISCOVERYAGENT_P_H + +#include "qbluetoothaddress.h" +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothserviceinfo.h" +#include "qbluetoothservicediscoveryagent.h" + +#include <QStack> + +#ifdef QT_SYMBIAN_BLUETOOTH +#include <btsdp.h> +#endif + +#ifdef QT_BLUEZ_BLUETOOTH +class OrgBluezManagerInterface; +class OrgBluezAdapterInterface; +class OrgBluezDeviceInterface; +class QDBusPendingCallWatcher; +class QXmlStreamReader; +#endif + +QT_BEGIN_HEADER + +class QBluetoothDeviceDiscoveryAgent; + +class QBluetoothServiceDiscoveryAgentPrivate +#ifdef QT_SYMBIAN_BLUETOOTH +: public MSdpAgentNotifier, public MSdpAttributeValueVisitor +#endif +{ + Q_DECLARE_PUBLIC(QBluetoothServiceDiscoveryAgent) + +public: + enum DiscoveryState { + Inactive, + DeviceDiscovery, + ServiceDiscovery, + }; + + QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &address); + ~QBluetoothServiceDiscoveryAgentPrivate(); + + void startDeviceDiscovery(); + void stopDeviceDiscovery(); + void startServiceDiscovery(); + void stopServiceDiscovery(); + + void setDiscoveryState(DiscoveryState s) { state = s; } + DiscoveryState discoveryState() { return state; } + + void setDiscoveryMode(QBluetoothServiceDiscoveryAgent::DiscoveryMode m) { mode = m; } + QBluetoothServiceDiscoveryAgent::DiscoveryMode DiscoveryMode() { return mode; } + + // private slots + void _q_deviceDiscoveryFinished(); + void _q_deviceDiscovered(const QBluetoothDeviceInfo &info); + void _q_serviceDiscoveryFinished(); +#ifdef QT_BLUEZ_BLUETOOTH + void _q_discoveredServices(QDBusPendingCallWatcher *watcher); + void _q_createdDevice(QDBusPendingCallWatcher *watcher); +#endif + +#ifdef QT_SYMBIAN_BLUETOOTH + /* MSdpAgentNotifier virtual functions */ + void NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount); + void AttributeRequestResult(TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID, CSdpAttrValue *aAttrValue); + void AttributeRequestComplete(TSdpServRecordHandle, TInt aError); + + /* MSdpAttributeValueVisitor virtual functions */ + void VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType); + void StartListL(CSdpAttrValueList &); + void EndListL(); +#endif + +private: + void start(const QBluetoothAddress &address); + void stop(); + +#ifdef QT_SYMBIAN_BLUETOOTH + void startL(const QBluetoothAddress &address); + void initL(const QBluetoothAddress &address); +#elif defined(QT_BLUEZ_BLUETOOTH) + QVariant readAttributeValue(QXmlStreamReader &xml); +#endif + +public: + QBluetoothServiceDiscoveryAgent::Error error; + QString errorString; + + QList<QBluetoothServiceInfo> discoveredServices; + QList<QBluetoothDeviceInfo> discoveredDevices; + +private: + DiscoveryState state; + QBluetoothAddress deviceAddress; + QList<QBluetoothUuid> uuidFilter; + + QBluetoothDeviceDiscoveryAgent *deviceDiscoveryAgent; + + QBluetoothServiceDiscoveryAgent::DiscoveryMode mode; + + bool singleDevice; + +#ifdef QT_SYMBIAN_BLUETOOTH + CSdpAgent *m_sdpAgent; + CSdpSearchPattern *m_filter; + CSdpAttrIdMatchList *m_attributes; + QBluetoothServiceInfo m_serviceInfo; + TSdpAttributeID m_currentAttributeId; + + QStack<QVariant> m_stack; +#elif defined(QT_BLUEZ_BLUETOOTH) + OrgBluezManagerInterface *manager; + OrgBluezAdapterInterface *adapter; + OrgBluezDeviceInterface *device; +#endif + +protected: + QBluetoothServiceDiscoveryAgent *q_ptr; +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_symbian.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_symbian.cpp new file mode 100644 index 00000000..da84c0d0 --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_symbian.cpp @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothservicediscoveryagent_p.h" + +#include <QUrl> +#include <QtEndian> + +#include <arpa/inet.h> +#include <netinet/in.h> + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &address) + : error(QBluetoothServiceDiscoveryAgent::NoError) + , state(Inactive) + , deviceAddress(address) + , deviceDiscoveryAgent(0) + , mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery) + , singleDevice(false) + , m_sdpAgent(NULL) + , m_filter(NULL) + , m_attributes(NULL) +{ + +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ + qDebug() << "QBluetoothServiceDiscoveryAgent being destroyed"; + delete m_filter; + delete m_attributes; + delete m_sdpAgent; +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + TRAPD(err, startL(address)); + if (err != KErrNone && singleDevice) { + qDebug() << "Service discovery start failed" << err; + error = QBluetoothServiceDiscoveryAgent::UnknownError; + emit q->error(error); + } + qDebug() << "Service discovery started"; +} + +void QBluetoothServiceDiscoveryAgentPrivate::startL(const QBluetoothAddress &address) +{ + initL(address); + + if (uuidFilter.isEmpty()) { + m_filter->AddL(QBluetoothUuid::PublicBrowseGroup); + } else { + foreach (const QBluetoothUuid &uuid, uuidFilter) { + if (uuid.minimumSize() == 2) { + TUUID sUuid(uuid.toUInt16()); + m_filter->AddL(sUuid); + } else if (uuid.minimumSize() == 4) { + TUUID sUuid(uuid.toUInt32()); + m_filter->AddL(sUuid); + } else if (uuid.minimumSize() == 16) { + TUint32 *dataPointer = (TUint32*)uuid.toUInt128().data; + TUint32 hH = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 hL = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 lH = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 lL = qToBigEndian<quint32>(*(dataPointer)); + TUUID sUuid(hH, hL, lH, lL); + m_filter->AddL(sUuid); + } else { + // filter size can be 0 on error cases, searching all services + m_filter->AddL(QBluetoothUuid::PublicBrowseGroup); + } + } + } + m_sdpAgent->SetRecordFilterL(*m_filter); + m_sdpAgent->NextRecordRequestL(); + qDebug() << "Service discovery started, in startL"; +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ + qDebug() << "Stop discovery called"; + delete m_sdpAgent; + m_sdpAgent = NULL; + delete m_filter; + m_filter = NULL; + delete m_attributes; + m_attributes = NULL; + Q_Q(QBluetoothServiceDiscoveryAgent); + emit q->canceled(); +} + +void QBluetoothServiceDiscoveryAgentPrivate::initL(const QBluetoothAddress &address) +{ + TBTDevAddr btAddress(address.toUInt64()); + stop(); + + //Trapped in Start + m_sdpAgent = q_check_ptr(CSdpAgent::NewL(*this, btAddress)); + m_filter = q_check_ptr(CSdpSearchPattern::NewL()); + m_attributes = q_check_ptr(CSdpAttrIdMatchList::NewL()); + m_attributes->AddL(KAttrRangeAll); + +} + +void QBluetoothServiceDiscoveryAgentPrivate::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount) +{ + qDebug() << "NextRecordRequestComplete"; + Q_Q(QBluetoothServiceDiscoveryAgent); + if (aError == KErrNone && aTotalRecordsCount > 0 && m_sdpAgent && m_attributes) { + // request attributes + TRAPD(err, m_sdpAgent->AttributeRequestL(aHandle, *m_attributes)); + if (err && singleDevice) { + error = QBluetoothServiceDiscoveryAgent::UnknownError; + emit q->error(error); + } + } else if (aError == KErrEof) { + _q_serviceDiscoveryFinished(); + } else { + _q_serviceDiscoveryFinished(); + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::AttributeRequestResult(TSdpServRecordHandle, TSdpAttributeID aAttrID, CSdpAttrValue *aAttrValue) +{ + qDebug() << "AttributeRequestResult"; + Q_Q(QBluetoothServiceDiscoveryAgent); + m_currentAttributeId = aAttrID; + TRAPD(err, aAttrValue->AcceptVisitorL(*this)); + if (m_stack.size() != 1) { + if(singleDevice) + { + error = QBluetoothServiceDiscoveryAgent::UnknownError; + emit q->error(error); + } + delete aAttrValue; + return; + } + + m_serviceInfo.setAttribute(aAttrID, m_stack.pop()); + + if (err != KErrNone && singleDevice) { + error = QBluetoothServiceDiscoveryAgent::UnknownError; + emit q->error(error); + } + delete aAttrValue; +} + +void QBluetoothServiceDiscoveryAgentPrivate::AttributeRequestComplete(TSdpServRecordHandle, TInt aError) +{ + qDebug() << "AttributeRequestComplete"; + Q_Q(QBluetoothServiceDiscoveryAgent); + + if (aError == KErrNone && m_sdpAgent) { + m_serviceInfo.setDevice(discoveredDevices.at(0)); + discoveredServices.append(m_serviceInfo); + m_serviceInfo = QBluetoothServiceInfo(); + if (discoveredServices.last().isValid()) + { + emit q->serviceDiscovered(discoveredServices.last()); + } + TRAPD(err, m_sdpAgent->NextRecordRequestL()); + if (err != KErrNone && singleDevice) { + error = QBluetoothServiceDiscoveryAgent::UnknownError; + emit q->error(error); + } + } else if (aError != KErrEof && singleDevice) { + error = QBluetoothServiceDiscoveryAgent::UnknownError; + emit q->error(error); + } + + +} + +void QBluetoothServiceDiscoveryAgentPrivate::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType) +{ + qDebug() << "VisitAttributeValueL"; + QVariant var; + TUint datasize = aValue.DataSize(); + + switch (aType) { + case ETypeNil: + break; + case ETypeUint: + if (datasize == 8) { + TUint64 value; + aValue.Uint64(value); + var = QVariant::fromValue(value); + } else + var = QVariant::fromValue(aValue.Uint()); + break; + case ETypeInt: + var = QVariant::fromValue(aValue.Int()); + break; + case ETypeUUID: { + TPtrC8 shortForm(aValue.UUID().ShortestForm()); + if (shortForm.Size() == 2) { + QBluetoothUuid uuid(ntohs(*reinterpret_cast<const quint16 *>(shortForm.Ptr()))); + var = QVariant::fromValue(uuid); + } else if (shortForm.Size() == 4) { + QBluetoothUuid uuid(ntohl(*reinterpret_cast<const quint32 *>(shortForm.Ptr()))); + var = QVariant::fromValue(uuid); + } else if (shortForm.Size() == 16) { + QBluetoothUuid uuid(*reinterpret_cast<const quint128 *>(shortForm.Ptr())); + var = QVariant::fromValue(uuid); + } + break; + } + case ETypeString: { + TPtrC8 stringBuffer = aValue.Des(); + var = QVariant::fromValue(QString::fromLocal8Bit(reinterpret_cast<const char *>(stringBuffer.Ptr()), stringBuffer.Size())); + break; + } + case ETypeBoolean: + var = QVariant::fromValue(static_cast<bool>(aValue.Bool())); + break; + case ETypeDES: + m_stack.push(QVariant::fromValue(QBluetoothServiceInfo::Sequence())); + break; + case ETypeDEA: + m_stack.push(QVariant::fromValue(QBluetoothServiceInfo::Alternative())); + break; + case ETypeURL: { + TPtrC8 stringBuffer = aValue.Des(); + var = QVariant::fromValue(QUrl(QString::fromLocal8Bit(reinterpret_cast<const char *>(stringBuffer.Ptr()), stringBuffer.Size()))); + break; + } + case ETypeEncoded: + qWarning() << "Don't know how to handle encoded type."; + break; + default: + qWarning() << "Don't know how to handle type" << aType; + } + + if (aType != ETypeDES && aType != ETypeDEA) { + if (m_stack.size() == 0) { + // single value attribute, just push onto stack + m_stack.push(var); + } else if (m_stack.size() >= 1) { + // sequence or alternate attribute, add non-DES -DEA values to DES or DEA + if (m_stack.top().canConvert<QBluetoothServiceInfo::Sequence>()) { + QBluetoothServiceInfo::Sequence *sequence = static_cast<QBluetoothServiceInfo::Sequence *>(m_stack.top().data()); + sequence->append(var); + } else if (m_stack.top().canConvert<QBluetoothServiceInfo::Alternative>()) { + QBluetoothServiceInfo::Alternative *alternative = static_cast<QBluetoothServiceInfo::Alternative *>(m_stack.top().data()); + alternative->append(var); + } else { + qWarning("Unknown type in the QVariant, should be either a QBluetoothServiceInfo::Sequence or an QBluetoothServiceInfo::Alternative"); + } + } + } +} + +void QBluetoothServiceDiscoveryAgentPrivate::StartListL(CSdpAttrValueList &) +{ + +} + +void QBluetoothServiceDiscoveryAgentPrivate::EndListL() +{ + if (m_stack.size() > 1) { + // finished a sequence or alternative add it to the parent sequence or alternative + QVariant var = m_stack.pop(); + if (m_stack.top().canConvert<QBluetoothServiceInfo::Sequence>()) { + QBluetoothServiceInfo::Sequence *sequence = static_cast<QBluetoothServiceInfo::Sequence *>(m_stack.top().data()); + sequence->append(var); + } else if (m_stack.top().canConvert<QBluetoothServiceInfo::Alternative>()) { + QBluetoothServiceInfo::Alternative *alternative = static_cast<QBluetoothServiceInfo::Alternative *>(m_stack.top().data()); + alternative->append(var); + } else { + qWarning("Unknown type in the QVariant, should be either a QBluetoothServiceInfo::Sequence or an QBluetoothServiceInfo::Alternative"); + } + } +} diff --git a/src/bluetooth/qbluetoothserviceinfo.cpp b/src/bluetooth/qbluetoothserviceinfo.cpp new file mode 100644 index 00000000..efd9d4bf --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo.cpp @@ -0,0 +1,604 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" + +#include <QUrl> + +/*! + \class QBluetoothServiceInfo::Sequence + \brief The Sequence class provides a data type for Bluetooth Data + Element Sequence attributes. + \since 5.0 + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity +*/ + +/*! + \fn QBluetoothServiceInfo::Sequence::Sequence() + + Constructs a new empty sequence. +*/ + +/*! + \fn QBluetoothServiceInfo::Sequence::Sequence(const QList<QVariant> &list) + + Constructs a new sequence that is a copy of \a list. +*/ + +/*! + \class QBluetoothServiceInfo::Alternative + \brief The Alternative class provides a data type for Bluetooth Data + Element Alternative attributes. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity +*/ + +/*! + \fn QBluetoothServiceInfo::Alternative::Alternative() + + Constructs a new empty alternative. +*/ + +/*! + \fn QBluetoothServiceInfo::Alternative::Alternative(const QList<QVariant> &list) + + Constructs a new alternative that is a copy of \a list. +*/ + +/*! + \class QBluetoothServiceInfo + \brief The QBluetoothServiceInfo class provides information about services. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + + QBluetoothServiceInfo provides information about a service offered by a Bluetooth device. +*/ + +/*! + \enum QBluetoothServiceInfo::AttributeId + + Bluetooth service attributes. + + \value ServiceClassIds UUIDs of service classes that the service conforms to. + \value ServiceId UUID that uniquely identifies the service. + \value ProtocolDescriptorList List of protocols used by the service. + \value BrowseGroupList List of browse groups the service is in. + \value ServiceAvailability Value indicating the availability of the service. + \value PrimaryLanguageBase Base index for primary language text descriptors. + \value ServiceRecordHandle Specifies a service record from which attributes can be retrieved + \value ServiceName Name of the Bluetooth service in the primary language. + \value ServiceDescription Description of the Bluetooth service in the primary language. + \value ServiceProvider Name of the company / entity that provides the Bluetooth + service primary language. +*/ + +/*! + \enum QBluetoothServiceInfo::Protocol + + This enum describes the socket protocol used by the service. + + \value UnknownProtocol The service uses an unknown socket protocol. + \value L2capProtocol The service uses the L2CAP socket protocol. + \value RfcommProtocol The service uses the RFCOMM socket protocol. +*/ + +/*! + \fn bool QBluetoothServiceInfo::isRegistered() const + + Returns true if the service info is registered with the platforms service discovery protocol + (SDP) implementation; otherwise returns false. +*/ + +/*! + \fn bool QBluetoothServiceInfo::registerService() const + + Registers this service with the platforms service discovery protocol (SDP) implementation, + making it findable by other devices when they perform service discovery. Returns true if the + service is successfully registered, otherwise returns false. Once registered changes to the record + cannot be made. The service must be unregistered and registered. +*/ + +/*! + \fn bool QBluetoothServiceInfo::unregisterService() const + + Unregisters this service with the platforms service discovery protocol (SDP) implementation. + + This service will not longer be findable by other devices via service discovery. + + Returns true if the service is successfully unregistered, otherwise returns false. +*/ + +/*! + \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothUuid &value) + + This is a convenience function. + + Sets the attribute identified by \a attributeId to \a value. +*/ + +/*! + \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Sequence &value) + + This is a convenience function. + + Sets the attribute identified by \a attributeId to \a value. +*/ + +/*! + \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Alternative &value) + + This is a convenience function. + + Sets the attribute identified by \a attributeId to \a value. +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceName(const QString &name) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceName, name). + + Sets the service name in the primary language to \a name. + + \sa serviceName(), setAttribute() +*/ + +/*! + \fn QString QBluetoothServiceInfo::serviceName() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceName).toString(). + + Returns the service name in the primary language. + + \sa setServiceName(), attribute() +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceDescription(const QString &description) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceDescription, description). + + Sets the service description in the primary language to \a description. + + \sa serviceDescription(), setAttribute() +*/ + +/*! + \fn QString QBluetoothServiceInfo::serviceDescription() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceDescription).toString(). + + Returns the service description in the primary language. + + \sa setServiceDescription(), attribute() +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceProvider(const QString &provider) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceProvider, provider). + + Sets the service provider in the primary language to \a provider. + + \sa serviceProvider(), setAttribute() +*/ + +/*! + \fn QString QBluetoothServiceInfo::serviceProvider() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceProvider).toString(). + + Returns the service provider in the primary language. + + \sa setServiceProvider(), attribute() +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceAvailability(quint8 availability) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceAvailability, availability). + + Sets the availabiltiy of the service to \a availability. + + \sa serviceAvailability(), setAttribute() +*/ + +/*! + \fn quint8 QBluetoothServiceInfo::serviceAvailability() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceAvailability).toUInt(). + + Returns the availability of the service. + + \sa setServiceAvailability(), attribute() +*/ + +/*! + \fn void QBluetoothServiceInfo::setServiceUuid(const QBluetoothUuid &uuid) + + This is a convenience function. It is equivalent to calling + setAttribute(QBluetoothServiceInfo::ServiceId, uuid). + + Sets the service UUID to \a uuid. + + \sa serviceUuid(), setAttribute() +*/ + +/*! + \fn QBluetoothUuid QBluetoothServiceInfo::serviceUuid() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceId).value<QBluetoothUuid>(). + + Returns the UUID of the service. + + \sa setServiceUuid(), attribute() +*/ + +/*! + \fn QList<QBluetoothUuid> QBluetoothServiceInfo::serviceClassUuids() const + + This is a convenience function. It is equivalent to calling + attribute(QBluetoothServiceInfo::ServiceClassIds).value<QList<QBluetoothUuid> >(). + + Returns a list of UUIDs describing the service classes that this service conforms to. + + \sa attribute() +*/ + + +/*! + Construct a new invalid QBluetoothServiceInfo; +*/ +QBluetoothServiceInfo::QBluetoothServiceInfo() +: d_ptr(new QBluetoothServiceInfoPrivate) +{ + d_ptr->q_ptr = this; +} + +/*! + Construct a new QBluetoothServiceInfo that is a copy of \a other. +*/ +QBluetoothServiceInfo::QBluetoothServiceInfo(const QBluetoothServiceInfo &other) +: d_ptr(new QBluetoothServiceInfoPrivate) +{ + d_ptr->q_ptr = this; + *this = other; +} + +/*! + Destroys the QBluetoothServiceInfo object. +*/ +QBluetoothServiceInfo::~QBluetoothServiceInfo() +{ + delete d_ptr; +} + +/*! + Returns true if the Bluetooth service info object is valid; otherwise returns false. + + An invalid Bluetooth service info has no attributes. +*/ +bool QBluetoothServiceInfo::isValid() const +{ + Q_D(const QBluetoothServiceInfo); + + return !d->attributes.isEmpty(); +} + +/*! + Returns true if the Bluetooth service info object is considered complete; otherwise returns false. + + A complete service info contains a ProtocolDescriptorList attribute. +*/ +bool QBluetoothServiceInfo::isComplete() const +{ + Q_D(const QBluetoothServiceInfo); + + return d->attributes.keys().contains(ProtocolDescriptorList); +} + +/*! + Returns the address of the Bluetooth device that provides this service. +*/ +QBluetoothDeviceInfo QBluetoothServiceInfo::device() const +{ + Q_D(const QBluetoothServiceInfo); + + return d->deviceInfo; +} + +/*! + Sets the Bluetooth device that provides this service to \a device. +*/ +void QBluetoothServiceInfo::setDevice(const QBluetoothDeviceInfo &device) +{ + Q_D(QBluetoothServiceInfo); + + d->deviceInfo = device; +} + +/*! + Sets the attribute identified by \a attributeId to \a value. + + IF the service info is registered with the platforms SDP database the database entry is also + updated. + + \sa isRegistered(), registerService() +*/ +void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QVariant &value) +{ + Q_D(QBluetoothServiceInfo); + + if (value.type() == QVariant::List) + qDebug() << "tried attribute with type QVariantList" << value; + + d->attributes[attributeId] = value; + + if (isRegistered()) + d->setRegisteredAttribute(attributeId, value); +} + +/*! + Returns the value of the attribute \a attributeId. +*/ +QVariant QBluetoothServiceInfo::attribute(quint16 attributeId) const +{ + Q_D(const QBluetoothServiceInfo); + + return d->attributes[attributeId]; +} + +/*! + Returns a list of all attribute ids that this service info has. +*/ +QList<quint16> QBluetoothServiceInfo::attributes() const +{ + Q_D(const QBluetoothServiceInfo); + + return d->attributes.keys(); +} + +/*! + Returns true if the service info contains the attribute \a attributeId; otherwise returns + false. +*/ +bool QBluetoothServiceInfo::contains(quint16 attributeId) const +{ + Q_D(const QBluetoothServiceInfo); + + return d->attributes.contains(attributeId); +} + +/*! + Removes the attribute \a attributeId from this service info. +*/ +void QBluetoothServiceInfo::removeAttribute(quint16 attributeId) +{ + Q_D(QBluetoothServiceInfo); + + d->attributes.remove(attributeId); + + if (isRegistered()) + d->removeRegisteredAttribute(attributeId); +} + +/*! + Returns the protocol that this service uses. +*/ +QBluetoothServiceInfo::Protocol QBluetoothServiceInfo::socketProtocol() const +{ + QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::Rfcomm); + if (!parameters.isEmpty()) + return RfcommProtocol; + + parameters = protocolDescriptor(QBluetoothUuid::L2cap); + if (!parameters.isEmpty()) + return L2capProtocol; + + return UnknownProtocol; +} + +/*! + This is a convenience function. Returns the protocol/service multiplexer for services which + support the L2CAP protocol. Otherwise returns -1. + + This function is equivalent to extracting the information from the + QBluetoothServiceInfo::Sequence returned from + QBluetoothServiceInfo::attribute(QBluetoothServiceInfo::ProtocolDescriptorList). +*/ +int QBluetoothServiceInfo::protocolServiceMultiplexer() const +{ + QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::L2cap); + + if (parameters.isEmpty()) + return -1; + else if (parameters.count() == 1) + return 0; + else + return parameters.at(1).toUInt(); +} + +/*! + This is a convenience function. Returns the server channel for services which support the + RFCOMM protocol. Otherwise returns -1. + + This function is equivalent to extracting the information from the + QBluetoothServiceInfo::Sequence returned from + QBluetoothServiceInfo::attribute(QBluetootherServiceInfo::ProtocolDescriptorList). +*/ +int QBluetoothServiceInfo::serverChannel() const +{ + QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::Rfcomm); + + if (parameters.isEmpty()) + return -1; + else if (parameters.count() == 1) + return 0; + else + return parameters.at(1).toUInt(); +} + +/*! + Returns the protocol parameters as a QBluetoothServiceInfo::Sequence for protocol \a protocol. + + An empty QBluetoothServiceInfo::Sequence is returned if \a protocol is not supported. +*/ +QBluetoothServiceInfo::Sequence QBluetoothServiceInfo::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const +{ + if (!contains(QBluetoothServiceInfo::ProtocolDescriptorList)) + return QBluetoothServiceInfo::Sequence(); + + foreach (const QVariant &v, attribute(QBluetoothServiceInfo::ProtocolDescriptorList).value<QBluetoothServiceInfo::Sequence>()) { + QBluetoothServiceInfo::Sequence parameters = v.value<QBluetoothServiceInfo::Sequence>(); + if(parameters.empty()) + continue; + if (parameters.at(0).userType() == qMetaTypeId<QBluetoothUuid>()) { + if (parameters.at(0).value<QBluetoothUuid>() == protocol) + return parameters; + } + } + + return QBluetoothServiceInfo::Sequence(); +} + +/*! + Makes a copy of the \a other and assigns it to this QBluetoothServiceInfo object. +*/ +QBluetoothServiceInfo &QBluetoothServiceInfo::operator=(const QBluetoothServiceInfo &other) +{ + Q_D(QBluetoothServiceInfo); + + d->attributes = other.d_func()->attributes; + d->deviceInfo = other.d_func()->deviceInfo; + + return *this; +} + +static void dumpAttributeVariant(const QVariant &var, const QString indent) +{ + switch (var.type()) { + case QMetaType::Void: + qDebug("%sEmpty", indent.toLocal8Bit().constData()); + break; + case QMetaType::UChar: + qDebug("%suchar %u", indent.toLocal8Bit().constData(), var.toUInt()); + break; + case QMetaType::UShort: + qDebug("%sushort %u", indent.toLocal8Bit().constData(), var.toUInt()); + case QMetaType::UInt: + qDebug("%suint %u", indent.toLocal8Bit().constData(), var.toUInt()); + break; + case QMetaType::Char: + qDebug("%schar %d", indent.toLocal8Bit().constData(), var.toInt()); + break; + case QMetaType::Short: + qDebug("%sshort %d", indent.toLocal8Bit().constData(), var.toInt()); + break; + case QMetaType::Int: + qDebug("%sint %d", indent.toLocal8Bit().constData(), var.toInt()); + break; + case QMetaType::QString: + qDebug("%sstring %s", indent.toLocal8Bit().constData(), var.toString().toLocal8Bit().constData()); + break; + case QMetaType::Bool: + qDebug("%sbool %d", indent.toLocal8Bit().constData(), var.toBool()); + break; + case QMetaType::QUrl: + qDebug("%surl %s", indent.toLocal8Bit().constData(), var.toUrl().toString().toLocal8Bit().constData()); + break; + case QVariant::UserType: + if (var.userType() == qMetaTypeId<QBluetoothUuid>()) { + QBluetoothUuid uuid = var.value<QBluetoothUuid>(); + switch (uuid.minimumSize()) { + case 0: + qDebug("%suuid NULL", indent.toLocal8Bit().constData()); + break; + case 2: + qDebug("%suuid %04x", indent.toLocal8Bit().constData(), uuid.toUInt16()); + break; + case 4: + qDebug("%suuid %08x", indent.toLocal8Bit().constData(), uuid.toUInt32()); + break; + case 16: + qDebug("%suuid %s", indent.toLocal8Bit().constData(), QByteArray(reinterpret_cast<const char *>(uuid.toUInt128().data), 16).toHex().constData()); + break; + default: + qDebug("%suuid ???", indent.toLocal8Bit().constData()); + ; + } + } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) { + qDebug("%sSequence", indent.toLocal8Bit().constData()); + const QBluetoothServiceInfo::Sequence *sequence = static_cast<const QBluetoothServiceInfo::Sequence *>(var.data()); + foreach (const QVariant &v, *sequence) + dumpAttributeVariant(v, indent + QLatin1Char('\t')); + } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) { + qDebug("%sAlternative", indent.toLocal8Bit().constData()); + const QBluetoothServiceInfo::Alternative *alternative = static_cast<const QBluetoothServiceInfo::Alternative *>(var.data()); + foreach (const QVariant &v, *alternative) + dumpAttributeVariant(v, indent + QLatin1Char('\t')); + } + break; + default: + qDebug("%sunknown variant type %d", indent.toLocal8Bit().constData(), var.userType()); + } +} + + +QDebug operator<<(QDebug dbg, const QBluetoothServiceInfo &info) +{ + foreach (quint16 id, info.attributes()) { + dumpAttributeVariant(info.attribute(id), QString::fromLatin1("(%1)\t").arg(id)); + } + return dbg; +} diff --git a/src/bluetooth/qbluetoothserviceinfo.h b/src/bluetooth/qbluetoothserviceinfo.h new file mode 100644 index 00000000..f05ed565 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo.h @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHSERVICEINFO_H +#define QBLUETOOTHSERVICEINFO_H + +#include "../qtconnectivityglobal.h" + +#include <qbluetoothuuid.h> + +#include <QtCore/QMetaType> +#include <QtCore/QList> +#include <QtCore/QVariant> + +#include <QtCore/QDebug> + +QT_BEGIN_HEADER + +class QBluetoothServiceInfoPrivate; +class QBluetoothDeviceInfo; + +class Q_CONNECTIVITY_EXPORT QBluetoothServiceInfo +{ +public: + enum AttributeId { + ServiceRecordHandle = 0x0000, + ServiceClassIds = 0x0001, + ServiceId = 0x0003, + ProtocolDescriptorList = 0x0004, + BrowseGroupList = 0x0005, + ServiceAvailability = 0x0008, + PrimaryLanguageBase = 0x0100, + ServiceName = PrimaryLanguageBase + 0x0000, + ServiceDescription = PrimaryLanguageBase + 0x0001, + ServiceProvider = PrimaryLanguageBase + 0x0002, + }; + + enum Protocol { + UnknownProtocol, + L2capProtocol, + RfcommProtocol + }; + + class Sequence : public QList<QVariant> + { + public: + Sequence() { } + Sequence(const QList<QVariant> &list) : QList<QVariant>(list) { } + }; + + class Alternative : public QList<QVariant> + { + public: + Alternative() { } + Alternative(const QList<QVariant> &list) : QList<QVariant>(list) { } + }; + + QBluetoothServiceInfo(); + QBluetoothServiceInfo(const QBluetoothServiceInfo &other); + ~QBluetoothServiceInfo(); + + bool isValid() const; + bool isComplete() const; + + void setDevice(const QBluetoothDeviceInfo &info); + QBluetoothDeviceInfo device() const; + + void setAttribute(quint16 attributeId, const QVariant &value); + void setAttribute(quint16 attributeId, const QBluetoothUuid &value); + void setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Sequence &value); + void setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Alternative &value); + QVariant attribute(quint16 attributeId) const; + QList<quint16> attributes() const; + bool contains(quint16 attributeId) const; + void removeAttribute(quint16 attributeId); + + inline void setServiceName(const QString &name); + inline QString serviceName() const; + inline void setServiceDescription(const QString &description); + inline QString serviceDescription() const; + inline void setServiceProvider(const QString &provider); + inline QString serviceProvider() const; + + QBluetoothServiceInfo::Protocol socketProtocol() const; + int protocolServiceMultiplexer() const; + int serverChannel() const; + + QBluetoothServiceInfo::Sequence protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const; + + inline void setServiceAvailability(quint8 availability); + inline quint8 serviceAvailability() const; + + inline void setServiceUuid(const QBluetoothUuid &uuid); + inline QBluetoothUuid serviceUuid() const; + + inline QList<QBluetoothUuid> serviceClassUuids() const; + + QBluetoothServiceInfo &operator=(const QBluetoothServiceInfo &other); + + bool isRegistered() const; + bool registerService() const; + bool unregisterService() const; + +protected: + friend Q_CONNECTIVITY_EXPORT QDebug operator<<(QDebug, const QBluetoothServiceInfo &); + +protected: + QBluetoothServiceInfoPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QBluetoothServiceInfo) +}; + +Q_DECLARE_METATYPE(QBluetoothServiceInfo) +Q_DECLARE_METATYPE(QBluetoothServiceInfo::Sequence) +Q_DECLARE_METATYPE(QBluetoothServiceInfo::Alternative) +Q_DECLARE_METATYPE(QList<QBluetoothUuid>) + +inline void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothUuid &value) +{ + setAttribute(attributeId, QVariant::fromValue(value)); +} + +inline void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Sequence &value) +{ + setAttribute(attributeId, QVariant::fromValue(value)); +} + +inline void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Alternative &value) +{ + setAttribute(attributeId, QVariant::fromValue(value)); +} + +inline void QBluetoothServiceInfo::setServiceName(const QString &name) +{ + setAttribute(ServiceName, QVariant::fromValue(name)); +} + +inline QString QBluetoothServiceInfo::serviceName() const +{ + return attribute(ServiceName).toString(); +} + +inline void QBluetoothServiceInfo::setServiceDescription(const QString &description) +{ + setAttribute(ServiceDescription, QVariant::fromValue(description)); +} + +inline QString QBluetoothServiceInfo::serviceDescription() const +{ + return attribute(ServiceDescription).toString(); +} + +inline void QBluetoothServiceInfo::setServiceProvider(const QString &provider) +{ + setAttribute(ServiceProvider, QVariant::fromValue(provider)); +} + +inline QString QBluetoothServiceInfo::serviceProvider() const +{ + return attribute(ServiceProvider).toString(); +} + +inline void QBluetoothServiceInfo::setServiceAvailability(quint8 availability) +{ + setAttribute(ServiceAvailability, QVariant::fromValue(availability)); +} + +inline quint8 QBluetoothServiceInfo::serviceAvailability() const +{ + return attribute(ServiceAvailability).toUInt(); +} + +inline void QBluetoothServiceInfo::setServiceUuid(const QBluetoothUuid &uuid) +{ + setAttribute(ServiceId, uuid); +} + +inline QBluetoothUuid QBluetoothServiceInfo::serviceUuid() const +{ + return attribute(ServiceId).value<QBluetoothUuid>(); +} + +inline QList<QBluetoothUuid> QBluetoothServiceInfo::serviceClassUuids() const +{ + return attribute(ServiceClassIds).value<QList<QBluetoothUuid> >(); +} + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothserviceinfo_bluez.cpp b/src/bluetooth/qbluetoothserviceinfo_bluez.cpp new file mode 100644 index 00000000..1bf2b96e --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_bluez.cpp @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" + +#include "bluez/manager_p.h" +#include "bluez/service_p.h" + +#include <QtCore/QXmlStreamWriter> + +static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute) +{ + const QString unsignedFormat(QLatin1String("0x%1")); + + switch (attribute.type()) { + case QMetaType::Void: + stream->writeEmptyElement(QLatin1String("nil")); + break; + case QMetaType::UChar: + stream->writeEmptyElement(QLatin1String("uint8")); + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(attribute.value<quint8>(), 2, 16, + QLatin1Char('0'))); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::UShort: + stream->writeEmptyElement(QLatin1String("uint16")); + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(attribute.value<quint16>(), 4, 16, + QLatin1Char('0'))); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::UInt: + stream->writeEmptyElement(QLatin1String("uint32")); + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(attribute.value<quint32>(), 8, 16, + QLatin1Char('0'))); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::Char: + stream->writeEmptyElement(QLatin1String("int8")); + stream->writeAttribute(QLatin1String("value"), + QString::number(attribute.value<uchar>(), 16)); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::Short: + stream->writeEmptyElement(QLatin1String("int16")); + stream->writeAttribute(QLatin1String("value"), + QString::number(attribute.value<qint16>(), 16)); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::Int: + stream->writeEmptyElement(QLatin1String("int32")); + stream->writeAttribute(QLatin1String("value"), + QString::number(attribute.value<qint32>(), 16)); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::QString: + stream->writeEmptyElement(QLatin1String("text")); + if (/* require hex encoding */ false) { + stream->writeAttribute(QLatin1String("value"), QString::fromLatin1( + attribute.value<QString>().toUtf8().toHex().constData())); + stream->writeAttribute(QLatin1String("encoding"), QLatin1String("hex")); + } else { + stream->writeAttribute(QLatin1String("value"), attribute.value<QString>()); + stream->writeAttribute(QLatin1String("encoding"), QLatin1String("normal")); + } + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::Bool: + stream->writeEmptyElement(QLatin1String("boolean")); + if (attribute.value<bool>()) + stream->writeAttribute(QLatin1String("value"), QLatin1String("true")); + else + stream->writeAttribute(QLatin1String("value"), QLatin1String("false")); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::QUrl: + stream->writeEmptyElement(QLatin1String("url")); + stream->writeAttribute(QLatin1String("value"), attribute.value<QUrl>().toString()); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QVariant::UserType: + if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) { + stream->writeEmptyElement(QLatin1String("uuid")); + + QBluetoothUuid uuid = attribute.value<QBluetoothUuid>(); + switch (uuid.minimumSize()) { + case 0: + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(quint16(0), 4, 16, QLatin1Char('0'))); + break; + case 2: + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(uuid.toUInt16(), 4, 16, + QLatin1Char('0'))); + break; + case 4: + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(uuid.toUInt32(), 8, 16, + QLatin1Char('0'))); + break; + case 16: + stream->writeAttribute(QLatin1String("value"), uuid.toString().mid(1, 36)); + break; + default: + stream->writeAttribute(QLatin1String("value"), uuid.toString().mid(1, 36)); + } + } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) { + stream->writeStartElement(QLatin1String("sequence")); + const QBluetoothServiceInfo::Sequence *sequence = + static_cast<const QBluetoothServiceInfo::Sequence *>(attribute.data()); + foreach (const QVariant &v, *sequence) + writeAttribute(stream, v); + stream->writeEndElement(); + } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) { + const QBluetoothServiceInfo::Alternative *alternative = + static_cast<const QBluetoothServiceInfo::Alternative *>(attribute.data()); + foreach (const QVariant &v, *alternative) + writeAttribute(stream, v); + stream->writeEndElement(); + } + break; + default: + qDebug() << "Unknown variant type", attribute.userType(); + } +} + +bool QBluetoothServiceInfo::isRegistered() const +{ + Q_D(const QBluetoothServiceInfo); + + return d->registered; +} + +bool QBluetoothServiceInfo::registerService() const +{ + Q_D(const QBluetoothServiceInfo); + + return d->registerService(); +} + +bool QBluetoothServiceInfo::unregisterService() const +{ + Q_D(const QBluetoothServiceInfo); + + if (!d->registered) + return false; + + if (!d->ensureSdpConnection()) + return false; + + QDBusPendingReply<> reply = d->service->RemoveRecord(d->serviceRecord); + reply.waitForFinished(); + if (reply.isError()) + return false; + + d->serviceRecord = 0; + + d->registered = false; + return true; +} + +QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() +: service(0), serviceRecord(0), registered(false) +{ +} + +QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() +{ +} + +void QBluetoothServiceInfoPrivate::setRegisteredAttribute(quint16 attributeId, const QVariant &value) const +{ + Q_UNUSED(attributeId); + Q_UNUSED(value); + + registerService(); +} + +void QBluetoothServiceInfoPrivate::removeRegisteredAttribute(quint16 attributeId) const +{ + Q_UNUSED(attributeId); + + registerService(); +} + +bool QBluetoothServiceInfoPrivate::ensureSdpConnection() const +{ + if (service) + return true; + + OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> reply = manager.FindAdapter(QLatin1String("any")); + reply.waitForFinished(); + if (reply.isError()) + return false; + + service = new OrgBluezServiceInterface(QLatin1String("org.bluez"), reply.value().path(), + QDBusConnection::systemBus()); + + return true; +} + +bool QBluetoothServiceInfoPrivate::registerService() const +{ + if (!ensureSdpConnection()) + return false; + + QString xmlServiceRecord; + + QXmlStreamWriter stream(&xmlServiceRecord); + stream.setAutoFormatting(true); + + stream.writeStartDocument(QLatin1String("1.0")); + + stream.writeStartElement(QLatin1String("record")); + + const QString unsignedFormat(QLatin1String("0x%1")); + + QMap<quint16, QVariant>::ConstIterator i = attributes.constBegin(); + while (i != attributes.constEnd()) { + QString t = unsignedFormat.arg(i.key(), 4, QLatin1Char('0')); + stream.writeStartElement(QLatin1String("attribute")); + stream.writeAttribute(QLatin1String("id"), + unsignedFormat.arg(i.key(), 4, 16, QLatin1Char('0'))); + writeAttribute(&stream, i.value()); + stream.writeEndElement(); + + ++i; + } + + stream.writeEndElement(); + + stream.writeEndDocument(); + +// qDebug() << xmlServiceRecord; + + if (!registered) { + QDBusPendingReply<uint> reply = service->AddRecord(xmlServiceRecord); + reply.waitForFinished(); + if (reply.isError()) + return false; + + serviceRecord = reply.value(); + } else { + QDBusPendingReply<> reply = service->UpdateRecord(serviceRecord, xmlServiceRecord); + reply.waitForFinished(); + if (reply.isError()) + return false; + } + + registered = true; + return true; +} diff --git a/src/bluetooth/qbluetoothserviceinfo_p.cpp b/src/bluetooth/qbluetoothserviceinfo_p.cpp new file mode 100644 index 00000000..6eb40cab --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_p.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" + + +bool QBluetoothServiceInfo::isRegistered() const +{ + return false; +} + +bool QBluetoothServiceInfo::registerService() const +{ + return false; +} + +bool QBluetoothServiceInfo::unregisterService() const +{ + return false; +} + +QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() +{ +} + +QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() +{ +} + +void QBluetoothServiceInfoPrivate::setRegisteredAttribute(quint16 attributeId, const QVariant &value) const +{ + Q_UNUSED(attributeId); + Q_UNUSED(value); +} + +void QBluetoothServiceInfoPrivate::removeRegisteredAttribute(quint16 attributeId) const +{ + Q_UNUSED(attributeId); +} + +#ifdef QT_BLUEZ_BLUETOOTH +bool QBluetoothServiceInfoPrivate::registerService() const +{ + return false; +} +#endif diff --git a/src/bluetooth/qbluetoothserviceinfo_p.h b/src/bluetooth/qbluetoothserviceinfo_p.h new file mode 100644 index 00000000..13cbce1c --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHSERVICEINFO_P_H +#define QBLUETOOTHSERVICEINFO_P_H + +#include "qbluetoothuuid.h" +#include "qbluetoothdeviceinfo.h" + +#include <QMap> +#include <QVariant> + +#ifdef QT_SYMBIAN_BLUETOOTH +#include <btsdp.h> +#endif + +class OrgBluezServiceInterface; + +QT_BEGIN_HEADER + +class QBluetoothServiceInfo; + +class QBluetoothServiceInfoPrivate +{ + Q_DECLARE_PUBLIC(QBluetoothServiceInfo) +public: + QBluetoothServiceInfoPrivate(); + ~QBluetoothServiceInfoPrivate(); + + void setRegisteredAttribute(quint16 attributeId, const QVariant &value) const; + void removeRegisteredAttribute(quint16 attributeId) const; + + bool ensureSdpConnection() const; + +#ifdef QT_BLUEZ_BLUETOOTH + bool registerService() const; +#endif + + QBluetoothDeviceInfo deviceInfo; + QMap<quint16, QVariant> attributes; + +#ifdef QT_SYMBIAN_BLUETOOTH +private: + void setRegisteredAttributeL(quint16 attributeId, const QVariant &value) const; + +public: + mutable RSdp sdpSession; + mutable RSdpDatabase sdpDatabase; + mutable TSdpServRecordHandle serviceRecord; +#endif + +#ifdef QT_BLUEZ_BLUETOOTH + mutable OrgBluezServiceInterface *service; + mutable quint32 serviceRecord; + mutable bool registered; +#endif + +private: + QBluetoothServiceInfo *q_ptr; +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothserviceinfo_symbian.cpp b/src/bluetooth/qbluetoothserviceinfo_symbian.cpp new file mode 100644 index 00000000..939a74b5 --- /dev/null +++ b/src/bluetooth/qbluetoothserviceinfo_symbian.cpp @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothserviceinfo.h" +#include "qbluetoothserviceinfo_p.h" + +#include <QUrl> +#include <QtEndian> + +#include <QDebug> + + +QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() +:serviceRecord(0) +{ +} + +QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() +{ + // Closing the database session will cause all + // registered services removed from the SDP database. + if (sdpDatabase.SubSessionHandle() != 0) + sdpDatabase.Close(); + + if (sdpSession.Handle() != 0) + sdpSession.Close(); +} + +static void convertL(MSdpElementBuilder *list, const QList<QVariant> &vList) +{ + list->StartListL(); + + foreach (const QVariant &v, vList) { + switch (v.type()) { + case QMetaType::Void: + list->BuildNilL(); + break; + case QMetaType::UChar: + list->BuildUintL(TSdpIntBuf<unsigned char>(v.toUInt())); + break; + case QMetaType::UShort: + list->BuildUintL(TSdpIntBuf<unsigned short>(v.toUInt())); + break; + case QMetaType::UInt: + list->BuildUintL(TSdpIntBuf<uint>(v.toUInt())); + break; + case QMetaType::Char: + list->BuildIntL(TSdpIntBuf<char>(v.toInt())); + break; + case QMetaType::Short: + list->BuildIntL(TSdpIntBuf<short>(v.toInt())); + break; + case QMetaType::Int: + list->BuildIntL(TSdpIntBuf<int>(v.toInt())); + break; + case QMetaType::QString: + list->BuildStringL(TPtrC8(reinterpret_cast<const quint8*>(v.toString().toLocal8Bit().constData()))); + break; + case QMetaType::Bool: + list->BuildBooleanL(v.toBool()); + break; + case QMetaType::QUrl: + list->BuildURLL(TPtrC8(reinterpret_cast<const quint8*>(v.toUrl().toString().toLocal8Bit().constData()))); + break; + case QVariant::UserType: + if (v.userType() == qMetaTypeId<QBluetoothUuid>()) { + QBluetoothUuid uuid = v.value<QBluetoothUuid>(); + switch (uuid.minimumSize()) { + case 2: + list->BuildUUIDL(uuid.toUInt16()); + break; + case 4: + list->BuildUUIDL(uuid.toUInt32()); + break; + case 16: { + TUint32 *dataPointer = (TUint32*)uuid.toUInt128().data; + TUint32 hH = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 hL = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 lH = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 lL = qToBigEndian<quint32>(*(dataPointer)); + TUUID sUuid(hH, hL, lH, lL); + list->BuildUUIDL(sUuid); + break; + } + } + } else if (v.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) { + convertL(list->BuildDESL(), v.value<QBluetoothServiceInfo::Sequence>()); + } else if (v.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) { + convertL(list->BuildDEAL(), v.value<QBluetoothServiceInfo::Alternative>()); + } + break; + default: + qDebug() << __FUNCTION__ << "Don't know how to handle variant type" << v.type(); + } + } + + list->EndListL(); +} + +void QBluetoothServiceInfoPrivate::setRegisteredAttribute(quint16 attributeId, const QVariant &value) const +{ + TRAPD(err, setRegisteredAttributeL(attributeId, value)); + if (err != KErrNone) { + qWarning("Could not set attributes SDP session (error %d).", err); + } +} + +void QBluetoothServiceInfoPrivate::setRegisteredAttributeL(quint16 attributeId, const QVariant &value) const +{ + CSdpAttrValue *sdpValue = 0; + + switch (value.type()) { + case QMetaType::Void: + sdpValue = CSdpAttrValueNil::NewNilL(); + break; + case QMetaType::UChar: + sdpValue = CSdpAttrValueUint::NewUintL(TSdpIntBuf<unsigned char>(value.toUInt())); + break; + case QMetaType::UShort: + sdpValue = CSdpAttrValueUint::NewUintL(TSdpIntBuf<unsigned short>(value.toUInt())); + break; + case QMetaType::UInt: + sdpValue = CSdpAttrValueUint::NewUintL(TSdpIntBuf<uint>(value.toUInt())); + break; + case QMetaType::Char: + sdpValue = CSdpAttrValueInt::NewIntL(TSdpIntBuf<char>(value.toInt())); + break; + case QMetaType::Short: + sdpValue = CSdpAttrValueInt::NewIntL(TSdpIntBuf<short>(value.toInt())); + break; + case QMetaType::Int: + sdpValue = CSdpAttrValueInt::NewIntL(TSdpIntBuf<int>(value.toInt())); + break; + case QMetaType::QString: + sdpValue = CSdpAttrValueString::NewStringL(TPtrC8(reinterpret_cast<const quint8*>(value.toString().toLocal8Bit().constData()))); + break; + case QMetaType::Bool: + sdpValue = CSdpAttrValueBoolean::NewBoolL(value.toBool()); + break; + case QMetaType::QUrl: + sdpValue = CSdpAttrValueURL::NewURLL(TPtrC8(reinterpret_cast<const quint8*>(value.toUrl().toString().toLocal8Bit().constData()))); + break; + case QVariant::UserType: + if (value.userType() == qMetaTypeId<QBluetoothUuid>()) { + QBluetoothUuid uuid = value.value<QBluetoothUuid>(); + switch (uuid.minimumSize()) { + case 2: + sdpValue = CSdpAttrValueUUID::NewUUIDL(uuid.toUInt16()); + break; + case 4: + sdpValue = CSdpAttrValueUUID::NewUUIDL(uuid.toUInt32()); + break; + case 16: { + TUint32 *dataPointer = (TUint32*)uuid.toUInt128().data; + TUint32 hH = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 hL = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 lH = qToBigEndian<quint32>(*(dataPointer++)); + TUint32 lL = qToBigEndian<quint32>(*(dataPointer)); + TUUID sUuid(hH, hL, lH, lL); + sdpValue = CSdpAttrValueUUID::NewUUIDL(sUuid); + break; + } + } + } else if (value.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) { + CSdpAttrValueDES *sequence = CSdpAttrValueDES::NewDESL(0); + CleanupStack::PushL(sequence); + convertL(sequence, value.value<QBluetoothServiceInfo::Sequence>()); + sdpValue = sequence; + CleanupStack::Pop(sequence); + } else if (value.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) { + CSdpAttrValueDEA *alternative = CSdpAttrValueDEA::NewDEAL(0); + CleanupStack::PushL(alternative); + convertL(alternative, value.value<QBluetoothServiceInfo::Alternative>()); + sdpValue = alternative; + CleanupStack::Pop(alternative); + } + break; + default: + qDebug() << __FUNCTION__ << "Don't know how to handle variant type" << value.type(); + } + + if (sdpValue) { + CleanupStack::PushL(sdpValue); + sdpDatabase.UpdateAttributeL(serviceRecord, attributeId, *sdpValue); + CleanupStack::PopAndDestroy(sdpValue); + } +} + +void QBluetoothServiceInfoPrivate::removeRegisteredAttribute(quint16 attributeId) const +{ + TRAPD(err, sdpDatabase.DeleteAttributeL(serviceRecord, attributeId)); + if (err != KErrNone) { + qWarning("Could not remove registered attribute (error %d).", err); + } +} + +bool QBluetoothServiceInfoPrivate::ensureSdpConnection() const +{ + if (sdpSession.Handle() == 0) { + int error = sdpSession.Connect(); + if (error != KErrNone) { + qWarning("Could not open connection to SDP session (error %d).", error); + return false; + } + } + + if (sdpDatabase.SubSessionHandle() == 0) { + int error = sdpDatabase.Open(sdpSession); + if (error != KErrNone) { + qWarning("Could not open connection to SDP database (error %d).", error); + return false; + } + } + + return true; +} + +bool QBluetoothServiceInfo::isRegistered() const +{ + Q_D(const QBluetoothServiceInfo); + + return d->serviceRecord != 0; +} + +bool QBluetoothServiceInfo::registerService() const +{ + Q_D(const QBluetoothServiceInfo); + + if (d->serviceRecord != 0) + return false; + + if (!d->ensureSdpConnection()) + return false; + + TRAPD(err, d->sdpDatabase.CreateServiceRecordL(0, d->serviceRecord)); + if (err != KErrNone) + return false; + + foreach (quint16 id, d->attributes.keys()) { + // Changing service record handle causes serious problems + // on Symbian devices. Hence passing the value update. + if (id != ServiceRecordHandle) + d->setRegisteredAttribute(id, d->attributes[id]); + } + + return true; +} + +bool QBluetoothServiceInfo::unregisterService() const +{ + Q_D(const QBluetoothServiceInfo); + if(d->serviceRecord == 0) + return true; + + if (!d->ensureSdpConnection()) + return false; + + TRAPD(err, d->sdpDatabase.DeleteRecordL(d->serviceRecord)); + if (err != KErrNone) + return false; + + d->serviceRecord = 0; + return true; +} diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp new file mode 100644 index 00000000..d265cc22 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket.cpp @@ -0,0 +1,660 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_p.h" + +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothserviceinfo.h" +#include "qbluetoothservicediscoveryagent.h" + + +#include <QDebug> +#include <QSocketNotifier> + +/*! + \class QBluetoothSocket + \brief The QBluetoothSocket class provides a Bluetooth socket. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + QBluetoothSocket supports two socket types, \l {QBluetoothSocket::L2capSocket}{L2CAP} and + \l {QBluetoothSocket::RfcommSocket}{RFCOMM}. + + \l {QBluetoothSocket::L2capSocket}{L2CAP} is a low level datagram-oriented Bluetooth socket. + + \l {QBluetoothSocket::RfcommSocket}{RFCOMM} is a reliable, stream-oriented socket. RFCOMM + sockets emulate an RS-232 serial port. + + To create a connection to a Bluetooth service create a socket of the appropriate type and call + connectToService() passing the Bluetooth address and port number. QBluetoothSocket will emit + the connected() signal when the connection is established. + + +*/ + +/*! + \enum QBluetoothSocket::SocketType + + This enum describes the Bluetooth socket type. + + \value UnknownSocketType Unknown socket type. + \value L2capSocket L2CAP socket. + \value RfcommSocket RFCOMM socket. +*/ + +/*! + \enum QBluetoothSocket::SocketState + + This enum describes the state of the Bluetooth socket. + + \value UnconnectedState Socket is not connected. + \value ServiceLookupState Socket is querying connection parameters. + \value ConnectingState Socket is attempting to connect to a device. + \value ConnectedState Socket is connected to a device. + \value BoundState 242.nmp.nokia.com +_IceTransSocketUNIXConnect: Cannot connect to non-local host saisd Socket is bound to a local address and port. + \value ClosingState Socket is connected and will be closed once all pending data is + written to the socket. + \value ListeningState Socket is listening for incoming connections. +*/ + +/*! + \enum QBluetoothSocket::SocketError + + This enum describes Bluetooth socket error types. + + \value UnknownSocketError An unknown error has occurred. + \value NoSocketError No error. Used for testing. + \value ConnectionRefusedError Connection refused or device not available. + \value RemoteHostClosedError The remote host closed the socket + \value HostNotFoundError Could not find the remote host + \value ServiceNotFoundError Could not find the service UUID on remote host + \value NetworkError Attempt to read or write from socket returned an error +*/ + +/*! + \fn void QBluetoothSocket::connected() + + This signal is emitted when a connection is established. + + \sa QBluetoothSocket::ConnectedState, stateChanged() +*/ + +/*! + \fn void QBluetoothSocket::disconnected() + + This signal is emitted when the socket is disconnected. + + \sa QBluetoothSocket::UnconnectedState, stateChanged() +*/ + +/*! + \fn void QBluetoothSocket::error(QBluetoothSocket::SocketError error) + + This signal is emitted when an \a error occurs. + + \sa error() +*/ + +/*! + \fn QBluetoothSocket::stateChanged(QBluetoothSocket::SocketState state) + + This signal is emitted when the socket state changes to \a state. + + \sa connected(), disconnected(), state(), QBluetoothSocket::SocketState +*/ + +/*! + \fn void QBluetoothSocket::abort() + + Aborts the current connection and resets the socket. Unlike disconnectFromService(), this + function immediately closes the socket, discarding any pending data in the write buffer. + + \sa disconnectFromService(), close() +*/ + +/*! + \fn void QBluetoothSocket::close() + + Disconnects the socket's connection with the device. +*/ + +/*! + \fn void QBluetoothSocket::disconnectFromService() + + Attempts to close the socket. If there is pending data waiting to be written QBluetoothSocket + will enter ClosingState and wait until all data has been written. Eventually, it will enter + UnconnectedState and emit the disconnected() signal. + + \sa connectToService() +*/ + +/*! + \fn QString QBluetoothSocket::localName() const + + Returns the name of the local device. +*/ + +/*! + \fn QBluetoothAddress QBluetoothSocket::localAddress() const + + Returns the address of the local device. +*/ + +/*! + \fn quint16 QBluetoothSocket::localPort() const + + Returns the port number of the local socket if available; otherwise returns 0. +*/ + +/*! + \fn QString QBluetoothSocket::peerName() const + + Returns the name of the peer device. +*/ + +/*! + \fn QBluetoothAddress QBluetoothSocket::peerAddress() const + + Returns the address of the peer device. +*/ + +/*! + \fn quint16 QBluetoothSocket::peerPort() const + + Return the port number of the peer socket if available; otherwise returns 0. +*/ + +/*! + \fn qint64 QBluetoothSocket::readData(char *data, qint64 maxSize) + + \reimp +*/ + +/*! + \fn qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize) + + \reimp +*/ + +/*! + Constructs a Bluetooth socket of \a socketType type, with \a parent. +*/ +QBluetoothSocket::QBluetoothSocket(QBluetoothSocket::SocketType socketType, QObject *parent) +: QIODevice(parent), d_ptr(new QBluetoothSocketPrivate) +{ + d_ptr->q_ptr = this; + + Q_D(QBluetoothSocket); + d->ensureNativeSocket(socketType); + + setOpenMode(QIODevice::ReadWrite); +} + +/*! + Constructs a Bluetooth socket with \a parent. +*/ +QBluetoothSocket::QBluetoothSocket(QObject *parent) + : QIODevice(parent), d_ptr(new QBluetoothSocketPrivate) +{ + d_ptr->q_ptr = this; + setOpenMode(QIODevice::ReadWrite); +} + +/*! + Destroys the Bluetooth socket. +*/ +QBluetoothSocket::~QBluetoothSocket() +{ + delete d_ptr; + d_ptr = 0; +} + +/*! + \reimp +*/ +bool QBluetoothSocket::isSequential() const +{ + return true; +} + +/*! + Returns the number of incoming bytes that are waiting to be read. + + \sa bytesToWrite(), read() +*/ +qint64 QBluetoothSocket::bytesAvailable() const +{ + Q_D(const QBluetoothSocket); + return QIODevice::bytesAvailable() + d->bytesAvailable(); +} + +/*! + Returns the number of bytes that are waiting to be written. The bytes are written when control + goes back to the event loop. +*/ +qint64 QBluetoothSocket::bytesToWrite() const +{ + Q_D(const QBluetoothSocket); + return d->txBuffer.size(); +} + +/*! + Attempts to connect to the service described by \a service. + + The socket is opened in the given \a openMode. + + The socket first enters ConnectingState and attempts to connect to the device providing + \a service. If a connection is established, QBluetoothSocket enters ConnectedState and + emits connected(). + + At any point, the socket can emit error() to siganl that an error occurred. + + \sa state(), disconnectFromService() +*/ +void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode) +{ + Q_D(QBluetoothSocket); + setOpenMode(openMode); + + if (service.protocolServiceMultiplexer() > 0) { + if (!d->ensureNativeSocket(L2capSocket)) { + emit error(UnknownSocketError); + return; + } + d->connectToService(service.device().address(), service.protocolServiceMultiplexer(), openMode); + } else if (service.serverChannel() > 0) { + if (!d->ensureNativeSocket(RfcommSocket)) { + emit error(UnknownSocketError); + return; + } + d->connectToService(service.device().address(), service.serverChannel(), openMode); + } else { + // try doing service discovery to see if we can find the socket + if(service.serviceUuid().isNull()){ + qWarning() << "No port, no PSM, and no UUID provided, unable to connect"; + return; + } + qDebug() << "Need a port/psm, doing discovery"; + doDeviceDiscovery(service, openMode); + } +} + +/*! + Attempts to make a connection to the service identified by \a uuid on the device with address + \a address. + + The socket is opened in the given \a openMode. + + The socket first enters the ServiceLookupState and queries the connection parameters for + \a uuid. If the service parameters are successfully retrieved the socket enters + ConnectingState, and attempts to connect to \a address. If a connection is established, + QBluetoothSocket enters Connected State and emits connected(). + + At any point, the socket can emit error() to signal that an error occurred. + + \sa state(), disconnectFromService() +*/ +void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode) +{ + QBluetoothServiceInfo service; + QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice); + service.setDevice(device); + service.setServiceUuid(uuid); + doDeviceDiscovery(service, openMode); +} + +/*! + Attempts to make a connection with \a address on the given \a port. + + The socket is opened in the given \a openMode. + + The socket first enters ConnectingState, and attempts to connect to \a address. If a + connection is established, QBluetoothSocket enters ConnectedState and emits connected(). + + At any point, the socket can emit error() to signal that an error occurred. + + \sa state(), disconnectFromService() +*/ +void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode) +{ + Q_D(QBluetoothSocket); + setOpenMode(openMode); + + d->connectToService(address, port, openMode); +} + +/*! + Returns the socket type. +*/ +QBluetoothSocket::SocketType QBluetoothSocket::socketType() const +{ + Q_D(const QBluetoothSocket); + return d->socketType; +} + +/*! + Returns the current state of the socket. +*/ +QBluetoothSocket::SocketState QBluetoothSocket::state() const +{ + Q_D(const QBluetoothSocket); + return d->state; +} + +/*! + Returns the last error. +*/ +QBluetoothSocket::SocketError QBluetoothSocket::error() const +{ + Q_D(const QBluetoothSocket); + return d->socketError; +} + +/*! + Returns a user displayable text string for the error. + */ +QString QBluetoothSocket::errorString() const +{ + Q_D(const QBluetoothSocket); + return d->errorString; +} + +/*! + Sets the socket state to \a state. +*/ +void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state) +{ + Q_D(QBluetoothSocket); + SocketState old = d->state; + d->state = state; + if(old != d->state) + emit stateChanged(state); + if(state == ListeningState){ + // TODO: look at this, is this really correct? + // if we're a listening socket we can't handle connects? + if (d->readNotifier) { + d->readNotifier->setEnabled(false); + } + } +} + +/*! + Returns true if you can read at least one line from the device + */ + +bool QBluetoothSocket::canReadLine() const +{ + Q_D(const QBluetoothSocket); + return d->buffer.canReadLine() || QIODevice::canReadLine(); +} + +/*! + Sets the type of error that last occurred to \a error_. +*/ +void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError error_) +{ + Q_D(QBluetoothSocket); + d->socketError = error_; + emit error(error_); +} + +/*! + Start device discovery for \a service and open the socket with \a openMode. If the socket + is created with a service uuid device address we must use service discovery to find the + port number to connect to. +*/ + +void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode) +{ + Q_D(QBluetoothSocket); + + qDebug() << "Starting discovery"; + + if(d->discoveryAgent) { + delete d->discoveryAgent; + } + + d->discoveryAgent = new QBluetoothServiceDiscoveryAgent(service.device().address(),this); + + qDebug() << "Got agent"; + + connect(d->discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); + connect(d->discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished())); + + d->openMode = openMode; + + if(!service.serviceUuid().isNull()) + d->discoveryAgent->setUuidFilter(service.serviceUuid()); + + if(!service.serviceClassUuids().isEmpty()) + d->discoveryAgent->setUuidFilter(service.serviceClassUuids()); + + // we have to ID the service somehow + Q_ASSERT(!d->discoveryAgent->uuidFilter().isEmpty()); + + qDebug() << "UUID filter" << d->discoveryAgent->uuidFilter(); + + d->discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); +} + +void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service) +{ + Q_D(QBluetoothSocket); + qDebug() << "FOUND SERVICE!" << service; + if(service.protocolServiceMultiplexer() != 0 || service.serverChannel() != 0) { + connectToService(service, d->openMode); + d->discoveryAgent->deleteLater(); + d->discoveryAgent = 0; + } +} + +void QBluetoothSocket::discoveryFinished() +{ + qDebug() << "Socket discovery finished"; + Q_D(QBluetoothSocket); + if(d->discoveryAgent){ + qDebug() << "Didn't find any"; + emit error(QBluetoothSocket::ServiceNotFoundError); + d->discoveryAgent->deleteLater(); + d->discoveryAgent = 0; + } +} + +void QBluetoothSocket::abort() +{ + Q_D(QBluetoothSocket); + d->abort(); + setSocketState(QBluetoothSocket::UnconnectedState); +} + +void QBluetoothSocket::disconnectFromService() +{ + // TODO: is this all we need to do? + Q_D(QBluetoothSocket); + d->close(); +} + +QString QBluetoothSocket::localName() const +{ + Q_D(const QBluetoothSocket); + return d->localName(); +} + +QBluetoothAddress QBluetoothSocket::localAddress() const +{ + Q_D(const QBluetoothSocket); + return d->localAddress(); +} + +quint16 QBluetoothSocket::localPort() const +{ + Q_D(const QBluetoothSocket); + return d->localPort(); +} + +QString QBluetoothSocket::peerName() const +{ + Q_D(const QBluetoothSocket); + return d->peerName(); +} + +QBluetoothAddress QBluetoothSocket::peerAddress() const +{ + Q_D(const QBluetoothSocket); + return d->peerAddress(); +} + +quint16 QBluetoothSocket::peerPort() const +{ + Q_D(const QBluetoothSocket); + return d->peerPort(); +} + +qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize) +{ + Q_D(QBluetoothSocket); + return d->writeData(data, maxSize); +} + +qint64 QBluetoothSocket::readData(char *data, qint64 maxSize) +{ + Q_D(QBluetoothSocket); + return d->readData(data, maxSize); +} + +void QBluetoothSocket::close() +{ + Q_D(QBluetoothSocket); + setSocketState(ClosingState); + + d->close(); + + setSocketState(UnconnectedState); +} + +/*! + Set the socket to use \a socketDescriptor with a type of \a socketType + which is in state \a socketState and mode \a openMode. + + Returns true on success +*/ + + +bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, SocketType socketType, + SocketState socketState, OpenMode openMode) +{ + Q_D(QBluetoothSocket); + return d->setSocketDescriptor(socketDescriptor, socketType, socketState, openMode); +} + +/*! + Returns the platform specific socket descriptor, if available +*/ + +int QBluetoothSocket::socketDescriptor() const +{ + Q_D(const QBluetoothSocket); + return d->socket; +} + + + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, QBluetoothSocket::SocketError error) +{ + switch (error) { + case QBluetoothSocket::UnknownSocketError: + debug << "QBluetoothSocket::UnknownSocketError"; + break; + case QBluetoothSocket::ConnectionRefusedError: + debug << "QBluetoothSocket::ConnectionRefusedError"; + break; + case QBluetoothSocket::RemoteHostClosedError: + debug << "QBluetoothSocket::RemoteHostClosedError"; + break; + case QBluetoothSocket::HostNotFoundError: + debug << "QBluetoothSocket::HostNotFoundError"; + break; + case QBluetoothSocket::ServiceNotFoundError: + debug << "QBluetoothSocket::ServiceNotFoundError"; + break; + case QBluetoothSocket::NetworkError: + debug << "QBluetoothSocket::NetworkError"; + break; + default: + debug << "QBluetoothSocket::SocketError(" << (int)error << ")"; + } + return debug; +} + +QDebug operator<<(QDebug debug, QBluetoothSocket::SocketState state) +{ + switch (state) { + case QBluetoothSocket::UnconnectedState: + debug << "QBluetoothSocket::UnconnectedState"; + break; + case QBluetoothSocket::ConnectingState: + debug << "QBluetoothSocket::ConnectingState"; + break; + case QBluetoothSocket::ConnectedState: + debug << "QBluetoothSocket::ConnectedState"; + break; + case QBluetoothSocket::BoundState: + debug << "QBluetoothSocket::BoundState"; + break; + case QBluetoothSocket::ClosingState: + debug << "QBluetoothSocket::ClosingState"; + break; + case QBluetoothSocket::ListeningState: + debug << "QBluetoothSocket::ListeningState"; + break; + default: + debug << "QBluetoothSocket::SocketState(" << (int)state << ")"; + } + return debug; +} +#endif + +#include "moc_qbluetoothsocket.cpp" diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h new file mode 100644 index 00000000..8afea8ad --- /dev/null +++ b/src/bluetooth/qbluetoothsocket.h @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHSOCKET_H +#define QBLUETOOTHSOCKET_H + +#include "../qtconnectivityglobal.h" + +#include <qbluetoothaddress.h> +#include <qbluetoothuuid.h> + +#include <QIODevice> +#include <QtNetwork/QAbstractSocket> + +QT_BEGIN_HEADER + +class QBluetoothSocketPrivate; +class QBluetoothServiceInfo; + +class Q_CONNECTIVITY_EXPORT QBluetoothSocket : public QIODevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QBluetoothSocket) + + friend class QRfcommServer; + friend class QRfcommServerPrivate; + friend class QL2capServer; + friend class QL2capServerPrivate; + +public: + enum SocketType { + UnknownSocketType = -1, + L2capSocket, + RfcommSocket, + }; + + enum SocketState { + UnconnectedState = QAbstractSocket::UnconnectedState, + ServiceLookupState = QAbstractSocket::HostLookupState, + ConnectingState = QAbstractSocket::ConnectingState, + ConnectedState = QAbstractSocket::ConnectedState, + BoundState = QAbstractSocket::BoundState, + ClosingState = QAbstractSocket::ClosingState, + ListeningState = QAbstractSocket::ListeningState, + }; + + enum SocketError { + NoSocketError = -2, + UnknownSocketError = QAbstractSocket::UnknownSocketError, + ConnectionRefusedError = QAbstractSocket::ConnectionRefusedError, + RemoteHostClosedError = QAbstractSocket::RemoteHostClosedError, + HostNotFoundError = QAbstractSocket::HostNotFoundError, + ServiceNotFoundError = QAbstractSocket::SocketAddressNotAvailableError, + NetworkError = QAbstractSocket::NetworkError + }; + + explicit QBluetoothSocket(SocketType socketType, QObject *parent = 0); // create socket of type socketType + QBluetoothSocket(QObject *parent = 0); // create a blank socket + virtual ~QBluetoothSocket(); + + void abort(); + virtual void close(); + + bool isSequential() const; + + virtual qint64 bytesAvailable() const; + virtual qint64 bytesToWrite() const; + + virtual bool canReadLine() const; + + void connectToService(const QBluetoothServiceInfo &service, OpenMode openMode = ReadWrite); + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode = ReadWrite); + void connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode = ReadWrite); + void disconnectFromService(); + + //bool flush(); + //bool isValid() const; + + QString localName() const; + QBluetoothAddress localAddress() const; + quint16 localPort() const; + + QString peerName() const; + QBluetoothAddress peerAddress() const; + quint16 peerPort() const; + //QBluetoothServiceInfo peerService() const; + + //qint64 readBufferSize() const; + //void setReadBufferSize(qint64 size); + + bool setSocketDescriptor(int socketDescriptor, SocketType socketType, + SocketState socketState = ConnectedState, + OpenMode openMode = ReadWrite); + int socketDescriptor() const; + + SocketType socketType() const; + SocketState state() const; + SocketError error() const; + QString errorString() const; + + //bool waitForConnected(int msecs = 30000); + //bool waitForDisconnected(int msecs = 30000); + //virtual bool waitForReadyRead(int msecs = 30000); + +Q_SIGNALS: + void connected(); + void disconnected(); + void error(QBluetoothSocket::SocketError error); + void stateChanged(QBluetoothSocket::SocketState state); + +protected: + virtual qint64 readData(char *data, qint64 maxSize); + virtual qint64 writeData(const char *data, qint64 maxSize); + + void setSocketState(SocketState state); + void setSocketError(SocketError error); + + void doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode); + +private Q_SLOTS: + void serviceDiscovered(const QBluetoothServiceInfo &service); + void discoveryFinished(); + + +protected: + QBluetoothSocketPrivate *d_ptr; + +private: + Q_PRIVATE_SLOT(d_func(), void _q_readNotify()) + Q_PRIVATE_SLOT(d_func(), void _q_writeNotify()) +#ifdef QT_SYMBIAN_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_startReceive()) +#endif //QT_SYMBIAN_BLUETOOTH +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_CONNECTIVITY_EXPORT QDebug operator<<(QDebug, QBluetoothSocket::SocketError); +Q_CONNECTIVITY_EXPORT QDebug operator<<(QDebug, QBluetoothSocket::SocketState); +#endif + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp new file mode 100644 index 00000000..78c0d995 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_bluez.cpp @@ -0,0 +1,549 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_p.h" + +#include "bluez/manager_p.h" +#include "bluez/adapter_p.h" +#include "bluez/device_p.h" + +#include <qplatformdefs.h> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/rfcomm.h> +#include <bluetooth/l2cap.h> + +#include <errno.h> +#include <unistd.h> +#include <string.h> + +#include <QtCore/QSocketNotifier> + +QBluetoothSocketPrivate::QBluetoothSocketPrivate() + : socket(-1), + socketType(QBluetoothSocket::UnknownSocketType), + state(QBluetoothSocket::UnconnectedState), + readNotifier(0), + connectWriteNotifier(0), + connecting(false), + discoveryAgent(0) +{ +} + +QBluetoothSocketPrivate::~QBluetoothSocketPrivate() +{ + delete readNotifier; + readNotifier = 0; + delete connectWriteNotifier; + connectWriteNotifier = 0; +} + +bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothSocket::SocketType type) +{ + if (socket != -1) { + if (socketType == type) + return true; + + delete readNotifier; + readNotifier = 0; + delete connectWriteNotifier; + connectWriteNotifier = 0; + QT_CLOSE(socket); + } + + socketType = type; + + switch (type) { + case QBluetoothSocket::L2capSocket: + socket = ::socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + break; + case QBluetoothSocket::RfcommSocket: + socket = ::socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + break; + default: + socket = -1; + } + + if (socket == -1) + return false; + + int flags = fcntl(socket, F_GETFL, 0); + fcntl(socket, F_SETFL, flags | O_NONBLOCK); + + Q_Q(QBluetoothSocket); + readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read); + QObject::connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_readNotify())); + connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q); + QObject::connect(connectWriteNotifier, SIGNAL(activated(int)), q, SLOT(_q_writeNotify())); + + connectWriteNotifier->setEnabled(false); + readNotifier->setEnabled(false); + + + return true; +} + +void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + Q_UNUSED(openMode); + int result = -1; + + if (socketType == QBluetoothSocket::RfcommSocket) { + sockaddr_rc addr; + + memset(&addr, 0, sizeof(addr)); + addr.rc_family = AF_BLUETOOTH; + addr.rc_channel = port; + + convertAddress(address.toUInt64(), addr.rc_bdaddr.b); + + connectWriteNotifier->setEnabled(true); + readNotifier->setEnabled(true);QString(); + + result = ::connect(socket, (sockaddr *)&addr, sizeof(addr)); + } else if (socketType == QBluetoothSocket::L2capSocket) { + sockaddr_l2 addr; + + memset(&addr, 0, sizeof(addr)); + addr.l2_family = AF_BLUETOOTH; + addr.l2_psm = port; + + convertAddress(address.toUInt64(), addr.l2_bdaddr.b); + + connectWriteNotifier->setEnabled(true); + readNotifier->setEnabled(true); + + result = ::connect(socket, (sockaddr *)&addr, sizeof(addr)); + } + + if (result >= 0 || (result == -1 && errno == EINPROGRESS)) { + connecting = true; + q->setSocketState(QBluetoothSocket::ConnectingState); + } else { + errorString = QString::fromLocal8Bit(strerror(errno)); + q->setSocketError(QBluetoothSocket::UnknownSocketError); + } +} + +void QBluetoothSocketPrivate::_q_writeNotify() +{ + Q_Q(QBluetoothSocket); + if(connecting && state == QBluetoothSocket::ConnectingState){ + int errorno, len; + len = sizeof(errorno); + ::getsockopt(socket, SOL_SOCKET, SO_ERROR, &errorno, (socklen_t*)&len); + if(errorno) { + errorString = QString::fromLocal8Bit(strerror(errorno)); + emit q->error(QBluetoothSocket::UnknownSocketError); + return; + } + + q->setSocketState(QBluetoothSocket::ConnectedState); + emit q->connected(); + + connectWriteNotifier->setEnabled(false); + connecting = false; + } + else { + if (txBuffer.size() == 0) { + connectWriteNotifier->setEnabled(false); + return; + } + + char buf[1024]; + Q_Q(QBluetoothSocket); + + int size = txBuffer.read(buf, 1024); + + if (::write(socket, buf, size) != size) { + socketError = QBluetoothSocket::NetworkError; + emit q->error(socketError); + } + else { + emit q->bytesWritten(size); + } + + if (txBuffer.size()) { + connectWriteNotifier->setEnabled(true); + } + else if (state == QBluetoothSocket::ClosingState) { + connectWriteNotifier->setEnabled(false); + this->close(); + } + } +} + +// TODO: move to private backend? + +void QBluetoothSocketPrivate::_q_readNotify() +{ + Q_Q(QBluetoothSocket); + char *writePointer = buffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE); +// qint64 readFromDevice = q->readData(writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE); + int readFromDevice = ::read(socket, writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE); + if(readFromDevice <= 0){ + int errsv = errno; + readNotifier->setEnabled(false); + connectWriteNotifier->setEnabled(false); + errorString = QString::fromLocal8Bit(strerror(errsv)); + qDebug() << Q_FUNC_INFO << socket << "error:" << readFromDevice << errorString; + if(errsv == EHOSTDOWN) + emit q->error(QBluetoothSocket::HostNotFoundError); + else + emit q->error(QBluetoothSocket::UnknownSocketError); + + q->disconnectFromService(); + q->setSocketState(QBluetoothSocket::UnconnectedState); + } + else { + buffer.chop(QPRIVATELINEARBUFFER_BUFFERSIZE - (readFromDevice < 0 ? 0 : readFromDevice)); + + emit q->readyRead(); + } +} + +void QBluetoothSocketPrivate::abort() +{ + delete readNotifier; + readNotifier = 0; + delete connectWriteNotifier; + connectWriteNotifier = 0; + + // We don't transition through Closing for abort, so + // we don't call disconnectFromService or + // QBluetoothSocket::close + QT_CLOSE(socket); + + Q_Q(QBluetoothSocket); + emit q->disconnected(); +} + +QString QBluetoothSocketPrivate::localName() const +{ + if (!m_localName.isEmpty()) + return m_localName; + + const QBluetoothAddress address = localAddress(); + if (address.isNull()) + return QString(); + + OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> reply = manager.FindAdapter(address.toString()); + reply.waitForFinished(); + if (reply.isError()) + return QString(); + + OrgBluezAdapterInterface adapter(QLatin1String("org.bluez"), reply.value().path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QVariantMap> properties = adapter.GetProperties(); + properties.waitForFinished(); + if (properties.isError()) + return QString(); + + m_localName = properties.value().value(QLatin1String("Name")).toString(); + + return m_localName; +} + +QBluetoothAddress QBluetoothSocketPrivate::localAddress() const +{ + if (socketType == QBluetoothSocket::RfcommSocket) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0) { + quint64 bdaddr; + convertAddress(addr.rc_bdaddr.b, bdaddr); + return QBluetoothAddress(bdaddr); + } + } else if (socketType == QBluetoothSocket::L2capSocket) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0) { + quint64 bdaddr; + convertAddress(addr.l2_bdaddr.b, bdaddr); + return QBluetoothAddress(bdaddr); + } + } + + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivate::localPort() const +{ + if (socketType == QBluetoothSocket::RfcommSocket) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0) + return addr.rc_channel; + } else if (socketType == QBluetoothSocket::L2capSocket) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getsockname(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0) + return addr.l2_psm; + } + + return 0; +} + +QString QBluetoothSocketPrivate::peerName() const +{ + if (!m_peerName.isEmpty()) + return m_peerName; + + quint64 bdaddr; + + if (socketType == QBluetoothSocket::RfcommSocket) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) < 0) + return QString(); + + convertAddress(addr.rc_bdaddr.b, bdaddr); + } else if (socketType == QBluetoothSocket::L2capSocket) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) < 0) + return QString(); + + convertAddress(addr.l2_bdaddr.b, bdaddr); + } else { + qWarning("peerName() called on socket of known type"); + return QString(); + } + + const QString address = QBluetoothAddress(bdaddr).toString(); + + OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> reply = manager.DefaultAdapter(); + reply.waitForFinished(); + if (reply.isError()) + return QString(); + + OrgBluezAdapterInterface adapter(QLatin1String("org.bluez"), reply.value().path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter.CreateDevice(address); + deviceObjectPath.waitForFinished(); + if (deviceObjectPath.isError()) { + if (deviceObjectPath.error().name() != QLatin1String("org.bluez.Error.AlreadyExists")) + return QString(); + + deviceObjectPath = adapter.FindDevice(address); + deviceObjectPath.waitForFinished(); + if (deviceObjectPath.isError()) + return QString(); + } + + OrgBluezDeviceInterface device(QLatin1String("org.bluez"), deviceObjectPath.value().path(), + QDBusConnection::systemBus()); + + QDBusPendingReply<QVariantMap> properties = device.GetProperties(); + properties.waitForFinished(); + if (properties.isError()) + return QString(); + + m_peerName = properties.value().value(QLatin1String("Alias")).toString(); + + return m_peerName; +} + +QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const +{ + if (socketType == QBluetoothSocket::RfcommSocket) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0) { + quint64 bdaddr; + convertAddress(addr.rc_bdaddr.b, bdaddr); + return QBluetoothAddress(bdaddr); + } + } else if (socketType == QBluetoothSocket::L2capSocket) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0) { + quint64 bdaddr; + convertAddress(addr.l2_bdaddr.b, bdaddr); + return QBluetoothAddress(bdaddr); + } + } + + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivate::peerPort() const +{ + if (socketType == QBluetoothSocket::RfcommSocket) { + sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0) + return addr.rc_channel; + } else if (socketType == QBluetoothSocket::L2capSocket) { + sockaddr_l2 addr; + socklen_t addrLength = sizeof(addr); + + if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0) + return addr.l2_psm; + } + + return 0; +} + +qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize) +{ + Q_Q(QBluetoothSocket); + if (q->openMode() & QIODevice::Unbuffered) { + if (::write(socket, data, maxSize) != maxSize) { + socketError = QBluetoothSocket::NetworkError; + emit q->error(socketError); + } + + emit q->bytesWritten(maxSize); + + return maxSize; + } + else { + + if(!connectWriteNotifier) + return 0; + + if(txBuffer.size() == 0) { + connectWriteNotifier->setEnabled(true); + QMetaObject::invokeMethod(q, "_q_writeNotify", Qt::QueuedConnection); + } + + char *txbuf = txBuffer.reserve(maxSize); + memcpy(txbuf, data, maxSize); + + return maxSize; + } +} + +qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize) +{ + if(!buffer.isEmpty()){ + int i = buffer.read(data, maxSize); + return i; + + } + return 0; +} + +void QBluetoothSocketPrivate::close() +{ + Q_Q(QBluetoothSocket); + + // Only go through closing if the socket was fully opened + if(state == QBluetoothSocket::ConnectedState) + q->setSocketState(QBluetoothSocket::ClosingState); + + if(txBuffer.size() > 0 && + state == QBluetoothSocket::ClosingState){ + connectWriteNotifier->setEnabled(true); + } + else { + + delete readNotifier; + readNotifier = 0; + delete connectWriteNotifier; + connectWriteNotifier = 0; + + // We are disconnected now, so go to unconnected. + q->setSocketState(QBluetoothSocket::UnconnectedState); + emit q->disconnected(); + ::close(socket); + } + +} + +bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothSocket::SocketType socketType_, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + delete readNotifier; + readNotifier = 0; + delete connectWriteNotifier; + connectWriteNotifier = 0; + + socketType = socketType_; + socket = socketDescriptor; + + // ensure that O_NONBLOCK is set on new connections. + int flags = fcntl(socket, F_GETFL, 0); + if (!(flags & O_NONBLOCK)) + fcntl(socket, F_SETFL, flags | O_NONBLOCK); + + readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read); + QObject::connect(readNotifier, SIGNAL(activated(int)), q, SLOT(_q_readNotify())); + connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q); + QObject::connect(connectWriteNotifier, SIGNAL(activated(int)), q, SLOT(_q_writeNotify())); + + q->setSocketState(socketState); + q->setOpenMode(openMode); + + return true; +} + +int QBluetoothSocketPrivate::socketDescriptor() const +{ + return socket; +} + +qint64 QBluetoothSocketPrivate::bytesAvailable() const +{ + return buffer.size(); +} + diff --git a/src/bluetooth/qbluetoothsocket_p.cpp b/src/bluetooth/qbluetoothsocket_p.cpp new file mode 100644 index 00000000..3a893799 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_p.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_p.h" + +QBluetoothSocketPrivate::QBluetoothSocketPrivate() +{ +} + +QBluetoothSocketPrivate::~QBluetoothSocketPrivate() +{ +} + +bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothSocket::SocketType type) +{ + return false; +} + +void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_UNUSED(openMode); + Q_UNUSED(address); + Q_UNUSED(port); +} + +void QBluetoothSocketPrivate::_q_writeNotify() +{ +} + +void QBluetoothSocketPrivate::_q_readNotify() +{ +} + +void QBluetoothSocketPrivate::abort() +{ +} + +QString QBluetoothSocketPrivate::localName() const +{ + return QString(); +} + +QBluetoothAddress QBluetoothSocketPrivate::localAddress() const +{ + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivate::localPort() const +{ + return 0; +} + +QString QBluetoothSocketPrivate::peerName() const +{ + return QString(); +} + +QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const +{ + return QBluetoothAddress(); +} + +quint16 QBluetoothSocketPrivate::peerPort() const +{ + return 0; +} + +qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + return 0; +} + +qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + return 0; +} + +void QBluetoothSocketPrivate::close() +{ +} + +bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothSocket::SocketType socketType, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_UNUSED(socketDescriptor); + Q_UNUSED(socketType) + Q_UNUSED(socketState); + Q_UNUSED(openMode); + return false; +} + +int QBluetoothSocketPrivate::socketDescriptor() const +{ + return 0; +} + +qint64 QBluetoothSocketPrivate::bytesAvailable() const +{ + return 0; +} + diff --git a/src/bluetooth/qbluetoothsocket_p.h b/src/bluetooth/qbluetoothsocket_p.h new file mode 100644 index 00000000..302cf638 --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_p.h @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHSOCKET_P_H +#define QBLUETOOTHSOCKET_P_H + +#include "qbluetoothsocket.h" + +#ifndef QPRIVATELINEARBUFFER_BUFFERSIZE +#define QPRIVATELINEARBUFFER_BUFFERSIZE Q_INT64_C(16384) +#endif +#include "../qprivatelinearbuffer_p.h" + +#include <QtGlobal> + +#ifdef QT_SYMBIAN_BLUETOOTH +#include <es_sock.h> +#include <bt_sock.h> +#include <bttypes.h> +#endif + +QT_FORWARD_DECLARE_CLASS(QSocketNotifier) + +QT_BEGIN_HEADER + +class QBluetoothServiceDiscoveryAgent; + +class QSocketServerPrivate +{ +public: + QSocketServerPrivate(); + ~QSocketServerPrivate(); + +#ifdef QT_SYMBIAN_BLUETOOTH + RSocketServ socketServer; +#endif +}; + + + +class QBluetoothSocket; +class QBluetoothServiceDiscoveryAgent; + +class QBluetoothSocketPrivate +#ifdef QT_SYMBIAN_BLUETOOTH +: public MBluetoothSocketNotifier +#endif +{ + Q_DECLARE_PUBLIC(QBluetoothSocket) +public: + + QBluetoothSocketPrivate(); + ~QBluetoothSocketPrivate(); + + void connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode); + + bool ensureNativeSocket(QBluetoothSocket::SocketType type); + + QString localName() const; + QBluetoothAddress localAddress() const; + quint16 localPort() const; + + QString peerName() const; + QBluetoothAddress peerAddress() const; + quint16 peerPort() const; + //QBluetoothServiceInfo peerService() const; + + void abort(); + void close(); + + //qint64 readBufferSize() const; + //void setReadBufferSize(qint64 size); + + qint64 writeData(const char *data, qint64 maxSize); + qint64 readData(char *data, qint64 maxSize); + + bool setSocketDescriptor(int socketDescriptor, QBluetoothSocket::SocketType socketType, + QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState, + QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite); + int socketDescriptor() const; + + qint64 bytesAvailable() const; + +#ifdef QT_SYMBIAN_BLUETOOTH + void _q_startReceive(); + void startReceive(); + void startServerSideReceive(); + void receive(); + bool ensureBlankNativeSocket(QBluetoothSocket::SocketType type); + bool tryToSend(); + + /* MBluetoothSocketNotifier virtual functions */ + void HandleActivateBasebandEventNotifierCompleteL(TInt aErr, TBTBasebandEventNotification& aEventNotification); + void HandleAcceptCompleteL(TInt aErr); + void HandleConnectCompleteL(TInt aErr); + void HandleIoctlCompleteL(TInt aErr); + void HandleReceiveCompleteL(TInt aErr); + void HandleSendCompleteL(TInt aErr); + void HandleShutdownCompleteL(TInt aErr); +#endif + +public: + QPrivateLinearBuffer buffer; + QPrivateLinearBuffer txBuffer; + int socket; + QBluetoothSocket::SocketType socketType; + QBluetoothSocket::SocketState state; + QBluetoothSocket::SocketError socketError; + QSocketNotifier *readNotifier; + QSocketNotifier *connectWriteNotifier; + bool connecting; + + QBluetoothServiceDiscoveryAgent *discoveryAgent; + QBluetoothSocket::OpenMode openMode; + + +// QByteArray rxBuffer; +// qint64 rxOffset; + QString errorString; + +#ifdef QT_SYMBIAN_BLUETOOTH + CBluetoothSocket *iSocket; + TPtr8 rxDescriptor; + TPtrC8 txDescriptor; + QByteArray txArray; + TSockXfrLength rxLength; + TInt recvMTU; + TInt txMTU; + char* bufPtr; + bool transmitting; + quint64 writeSize; +#endif + + // private slots + void _q_readNotify(); + void _q_writeNotify(); + void _q_serviceDiscovered(const QBluetoothServiceInfo &service); + void _q_discoveryFinished(); + +protected: + QBluetoothSocket *q_ptr; + +private: + mutable QString m_localName; + mutable QString m_peerName; +}; + + +static inline void convertAddress(quint64 from, quint8 (&to)[6]) +{ + to[0] = (from >> 0) & 0xff; + to[1] = (from >> 8) & 0xff; + to[2] = (from >> 16) & 0xff; + to[3] = (from >> 24) & 0xff; + to[4] = (from >> 32) & 0xff; + to[5] = (from >> 40) & 0xff; +} + +static inline void convertAddress(quint8 (&from)[6], quint64 &to) +{ + to = (quint64(from[0]) << 0) | + (quint64(from[1]) << 8) | + (quint64(from[2]) << 16) | + (quint64(from[3]) << 24) | + (quint64(from[4]) << 32) | + (quint64(from[5]) << 40); +} + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qbluetoothsocket_symbian.cpp b/src/bluetooth/qbluetoothsocket_symbian.cpp new file mode 100644 index 00000000..d17a6f5c --- /dev/null +++ b/src/bluetooth/qbluetoothsocket_symbian.cpp @@ -0,0 +1,591 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothsocket_p.h" +#include "qbluetoothsocket.h" +#include "qbluetoothlocaldevice_p.h" +#include "symbian/utils_symbian_p.h" + +#include <QCoreApplication> + +#include <QDebug> + +#include <limits.h> +#include <bt_sock.h> +#include <es_sock.h> + +Q_GLOBAL_STATIC(QSocketServerPrivate, getSocketServer) + +QBluetoothSocketPrivate::QBluetoothSocketPrivate() + : socket(0) + , socketType(QBluetoothSocket::UnknownSocketType) + , state(QBluetoothSocket::UnconnectedState) + , readNotifier(0) + , connectWriteNotifier(0) + , discoveryAgent(0) + , iSocket(0) + , rxDescriptor(0, 0) + , txDescriptor(0, 0) + , recvMTU(0) + , txMTU(0) + , transmitting(false) + , writeSize(0) +{ +} + +QBluetoothSocketPrivate::~QBluetoothSocketPrivate() +{ + delete iSocket; +} + +void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) +{ + Q_Q(QBluetoothSocket); + Q_UNUSED(openMode); + + TBTSockAddr a; + + if(address.isNull()) + { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + return; + } + TInt err = KErrNone; + a.SetPort(port); + // Trap TBTDevAddr constructor which may panic + TRAP(err, a.SetBTAddr(TBTDevAddr(address.toUInt64()))); + if(err == KErrNone) + err = iSocket->Connect(a); + if (err == KErrNone) { + q->setSocketState(QBluetoothSocket::ConnectingState); + } else { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + } +} + +bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothSocket::SocketType type) +{ + if (iSocket) { + if (socketType == type) + { + return true; + } + else + { + delete iSocket; + iSocket = 0; + } + } + + socketType = type; + + switch (type) { + case QBluetoothSocket::L2capSocket: { + TRAPD(err, iSocket = CBluetoothSocket::NewL(*this, getSocketServer()->socketServer, _L("L2CAP"))); + Q_UNUSED(err); + break; + } + case QBluetoothSocket::RfcommSocket: { + TRAPD(err, iSocket = CBluetoothSocket::NewL(*this, getSocketServer()->socketServer, _L("RFCOMM"))); + Q_UNUSED(err); + break; + } + default: + iSocket = 0; + } + + if (iSocket) + return true; + else + return false; +} + +bool QBluetoothSocketPrivate::ensureBlankNativeSocket(QBluetoothSocket::SocketType type) +{ + if (iSocket) { + delete iSocket; + iSocket = 0; + } + socketType = type; + TRAPD(err, iSocket = CBluetoothSocket::NewL(*this, getSocketServer()->socketServer)); + Q_UNUSED(err); + if(iSocket) + return true; + else + return false; +} + +void QBluetoothSocketPrivate::startReceive() +{ + Q_Q(QBluetoothSocket); + if (!iSocket || state != QBluetoothSocket::ConnectedState) { + emit q->error(QBluetoothSocket::UnknownSocketError); + return; + } + TInt err = iSocket->GetOpt(KL2CAPInboundMTU, KSolBtL2CAP, recvMTU); + if(err != KErrNone) + { + emit q->error(QBluetoothSocket::UnknownSocketError); + return; + } + err = iSocket->GetOpt(KL2CAPNegotiatedOutboundMTU, KSolBtL2CAP, txMTU); + if(err != KErrNone) + { + emit q->error(QBluetoothSocket::UnknownSocketError); + return; + } + bufPtr = buffer.reserve(recvMTU); + // enable automatic power saving mode + iSocket->SetAutomaticSniffMode(ETrue); + // enable link down and link error notifications for proper disconnection + err = iSocket->ActivateBasebandEventNotifier(ENotifyPhysicalLinkDown |ENotifyPhysicalLinkError ); + if(err != KErrNone) + { + emit q->error(QBluetoothSocket::UnknownSocketError); + return; + } + receive(); +} + +void QBluetoothSocketPrivate::receive() +{ + Q_Q(QBluetoothSocket); + TInt err = KErrNone; + + if(!iSocket || bufPtr == 0 || recvMTU == 0 || socketType < 0 || state != QBluetoothSocket::ConnectedState) + { + emit q->error(QBluetoothSocket::UnknownSocketError); + return; + } + + TRAP(err, rxDescriptor.Set(reinterpret_cast<unsigned char *>(bufPtr), 0,recvMTU)); + if(err != KErrNone) + { + emit q->error(QBluetoothSocket::UnknownSocketError); + return; + } + if (socketType == QBluetoothSocket::RfcommSocket) { + // cancel any pending recv operation + iSocket->CancelRecv(); + err = iSocket->RecvOneOrMore(rxDescriptor, 0, rxLength); + if (err != KErrNone) { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + } + } else if (socketType == QBluetoothSocket::L2capSocket) { + // cancel any pending read operation + iSocket->CancelRead(); + err = iSocket->Read(rxDescriptor); + if (err != KErrNone) { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + } + } + } + +void QBluetoothSocketPrivate::HandleAcceptCompleteL(TInt aErr) +{ + qDebug() << __PRETTY_FUNCTION__ << ">> aErr=" << aErr; + Q_Q(QBluetoothSocket); + if(aErr != KErrNone) + { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + return; + } + emit q->connected(); +} + +void QBluetoothSocketPrivate::HandleActivateBasebandEventNotifierCompleteL(TInt aErr, TBTBasebandEventNotification& aEventNotification) +{ + qDebug() << __PRETTY_FUNCTION__; + Q_Q(QBluetoothSocket); + if(aErr != KErrNone) + { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + } + if(ENotifyPhysicalLinkDown & aEventNotification.EventType() || ENotifyPhysicalLinkError & aEventNotification.EventType()) + { + q->setSocketState(QBluetoothSocket::ClosingState); + emit q->disconnected(); + } +} + +void QBluetoothSocketPrivate::HandleConnectCompleteL(TInt aErr) +{ + qDebug() << __PRETTY_FUNCTION__ << ">> aErr=" << aErr; + Q_Q(QBluetoothSocket); + if (aErr == KErrNone) { + q->setSocketState(QBluetoothSocket::ConnectedState); + + emit q->connected(); + + startReceive(); + } else { + q->setSocketState(QBluetoothSocket::UnconnectedState); + + switch (aErr) { + case KErrCouldNotConnect: + socketError = QBluetoothSocket::ConnectionRefusedError; + break; + default: + qDebug() << __PRETTY_FUNCTION__ << aErr; + socketError = QBluetoothSocket::UnknownSocketError; + } + emit q->error(socketError); + } +} + +void QBluetoothSocketPrivate::HandleIoctlCompleteL(TInt aErr) +{ + qDebug() << __PRETTY_FUNCTION__; + Q_Q(QBluetoothSocket); + if(aErr != KErrNone) + { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + } +} + +void QBluetoothSocketPrivate::HandleReceiveCompleteL(TInt aErr) +{ + Q_Q(QBluetoothSocket); + if (aErr == KErrNone) { + if(buffer.size() == 0) + bufPtr = buffer.reserve(recvMTU); + if(bufPtr <= 0) + { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + return; + } + buffer.chop(recvMTU - rxDescriptor.Length()); + emit q->readyRead(); + } else { + // ignore disconnection it will be handled in baseband notification + if(aErr != KErrDisconnected) + { + socketError = QBluetoothSocket::UnknownSocketError; + writeSize = 0; + emit q->error(socketError); + } + } +} + +void QBluetoothSocketPrivate::HandleSendCompleteL(TInt aErr) +{ + Q_Q(QBluetoothSocket); + transmitting = false; + if (aErr == KErrNone) { + txArray.remove(0, writeSize); + emit q->bytesWritten(writeSize); + if (state == QBluetoothSocket::ClosingState) + { + writeSize = 0; + q->close(); + } + else + { + if(!tryToSend()) + { + socketError = QBluetoothSocket::UnknownSocketError; + writeSize = 0; + emit q->error(socketError); + } + } + } else { + socketError = QBluetoothSocket::UnknownSocketError; + writeSize = 0; + emit q->error(socketError); + } +} + +void QBluetoothSocketPrivate::HandleShutdownCompleteL(TInt aErr) +{ + Q_Q(QBluetoothSocket); + // It doesn't matter if aErr is KErrNone or something else + // we consider the socket to be closed. + q->setSocketState(QBluetoothSocket::UnconnectedState); + transmitting = false; + writeSize = 0; + iSocket->AsyncDelete(); + emit q->disconnected(); +} + +QSocketServerPrivate::QSocketServerPrivate() +{ + /* connect to socket server */ + TInt result = socketServer.Connect(); + if (result != KErrNone) { + qWarning("%s: RSocketServ.Connect() failed with error %d", __PRETTY_FUNCTION__, result); + return; + } +} + +QSocketServerPrivate::~QSocketServerPrivate() +{ + if (socketServer.Handle() != 0) + socketServer.Close(); +} + +QString QBluetoothSocketPrivate::localName() const +{ + return QBluetoothLocalDevicePrivate::name(); +} + +QBluetoothAddress QBluetoothSocketPrivate::localAddress() const +{ + TBTSockAddr address; + if(!iSocket) + { + // need to return something anyway + return QBluetoothAddress(); + } + iSocket->LocalName(address); + return qTBTDevAddrToQBluetoothAddress(address.BTAddr()); +} + +quint16 QBluetoothSocketPrivate::localPort() const +{ + if(!iSocket) + { + // need to return something anyway + return 0; + } + return iSocket->LocalPort(); +} + +QString QBluetoothSocketPrivate::peerName() const +{ + RHostResolver resolver; + + if(getSocketServer()->socketServer.Handle()== 0 || !iSocket || state != QBluetoothSocket::ConnectedState ) + { + // need to return something anyway + return QString(); + } + TInt err = resolver.Open(getSocketServer()->socketServer, KBTAddrFamily, KBTLinkManager); + if (err==KErrNone) + { + TNameEntry nameEntry; + TBTSockAddr sockAddr; + iSocket->RemoteName(sockAddr); + TInquirySockAddr address(sockAddr); + address.SetBTAddr(sockAddr.BTAddr()); + address.SetAction(KHostResName|KHostResIgnoreCache); // ignore name stored in cache + err = resolver.GetByAddress(address, nameEntry); + if(err == KErrNone) + { + TNameRecord name = nameEntry(); + QString qString((QChar*)name.iName.Ptr(),name.iName.Length()); + m_peerName = qString; + } + } + resolver.Close(); + + if(err != KErrNone) + { + // What is best? return an empty string or return the MAC address? + // In Symbian if we can't get the remote name we usually replace it with the MAC address + // but since Bluez implementation return an empty string we do the same here. + return QString(); + } + + return m_peerName; +} + +QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const +{ + TBTSockAddr address; + if(!iSocket) + { + // need to return something anyway + return QBluetoothAddress(); + } + iSocket->RemoteName(address); + return qTBTDevAddrToQBluetoothAddress(address.BTAddr()); +} + +quint16 QBluetoothSocketPrivate::peerPort() const +{ + TBTSockAddr address; + if(!iSocket) + { + // need to return something anyway + return 0; + } + iSocket->RemoteName(address); + return address.Port(); +} + +void QBluetoothSocketPrivate::close() +{ + Q_Q(QBluetoothSocket); + if(!iSocket || (state != QBluetoothSocket::ConnectedState && state != QBluetoothSocket::ListeningState)) + { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + return; + } + iSocket->CancelBasebandEventNotifier(); + q->setSocketState(QBluetoothSocket::ClosingState); + iSocket->Shutdown(RSocket::ENormal); +} + +void QBluetoothSocketPrivate::abort() +{ + Q_Q(QBluetoothSocket); + if(!iSocket) + { + socketError = QBluetoothSocket::UnknownSocketError; + emit q->error(socketError); + return; + } + iSocket->CancelWrite(); + transmitting = false; + writeSize = 0; + iSocket->CancelBasebandEventNotifier(); + iSocket->Shutdown(RSocket::EImmediate); + // force active object to run and shutdown socket. + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); +} + +qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize) +{ + Q_Q(QBluetoothSocket); + if(data == 0 || maxSize <= 0) + { + return -1; + } + qint64 size = buffer.read(data, maxSize); + QMetaObject::invokeMethod(q, "_q_startReceive", Qt::QueuedConnection); + return size; +} + +qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize) +{ + if(!iSocket || data == 0 || maxSize <= 0 || txMTU <= 0) { + return -1; + } + if (!txArray.isEmpty()) + { + txArray.append(QByteArray(data, maxSize)); + } + else + { + txArray = QByteArray(data, maxSize); + } + // we try to send the data to the remote device + if(tryToSend()) + { + // Warning : It doesn't mean the data have been sent + // to the remote device, it means that the data was + // at least stored in a local buffer. + return maxSize; + } + else + { + writeSize = 0; + return -1; + } +} + +void QBluetoothSocketPrivate::_q_readNotify() +{ +} + +void QBluetoothSocketPrivate::_q_writeNotify() +{ + +} + +bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothSocket::SocketType socketType, + QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) +{ + Q_UNUSED(socketDescriptor); + Q_UNUSED(socketType); + Q_UNUSED(socketState); + Q_UNUSED(openMode); + return false; +} + +void QBluetoothSocketPrivate::_q_startReceive() +{ + receive(); +} + +qint64 QBluetoothSocketPrivate::bytesAvailable() const +{ + return buffer.size(); +} + +bool QBluetoothSocketPrivate::tryToSend() +{ + if(txArray.isEmpty()) + return true; + + if(transmitting) + return transmitting; + + // we cannot write more than txMTU otherwise the extra data will just be lost + TInt dataLen = qMin(txArray.length(),txMTU); + + TRAPD(err, txDescriptor.Set(reinterpret_cast<const unsigned char *>(txArray.constData()),dataLen)); + if(err != KErrNone) + { + transmitting = false; + } + else + { + err = iSocket->Write(txDescriptor); + if (err != KErrNone) + { + transmitting = false; + } + writeSize = dataLen; + transmitting = true; + } + return transmitting; +} + diff --git a/src/bluetooth/qbluetoothtransfermanager.cpp b/src/bluetooth/qbluetoothtransfermanager.cpp new file mode 100644 index 00000000..a52f93df --- /dev/null +++ b/src/bluetooth/qbluetoothtransfermanager.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothtransfermanager.h" +#include "qbluetoothtransferrequest.h" + +/*! + \class QBluetoothTransferManager + \brief The QBluetoothTransferManager class allows the application to send data objects to other + devices. Currently implemented using OPP. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + QBluetoothTransferManager uses OBEX to send get and put commands to remote devices. +*/ + +/*! + \enum QBluetoothTransferManager::Operation + + This enum describes the type of operation that a transfer request is for. + + \value GetOperation The get operation is used to retrieve an object from a remote device. Not implemented. + \value PutOperation The put operation is used to send an object to a remote device. +*/ + +/*! + \fn QBluetoothTransferReply *QBluetoothTransferManager::put(const QBluetoothTransferRequest &request, QIODevice *data) + + Sends the contents of \a data to the remote device \a request and returns a new + QBluetoothTransferReply, that can be used to track the request's progress. +*/ + + + +/*! + \fn void QBluetoothTransferManager::finished(QBluetoothTransferReply *reply) + + This signal is emitted when the transfer for \a reply finishes. +*/ + +/*! + Constructs a new QBluetoothTransferManager with \a parent. +*/ +QBluetoothTransferManager::QBluetoothTransferManager(QObject *parent) +: QObject(parent) +{ +} + +/*! + Destroys the QBluetoothTransferManager. +*/ +QBluetoothTransferManager::~QBluetoothTransferManager() +{ +} + + +#include "moc_qbluetoothtransfermanager.cpp" diff --git a/src/bluetooth/qbluetoothtransfermanager.h b/src/bluetooth/qbluetoothtransfermanager.h new file mode 100644 index 00000000..099fa940 --- /dev/null +++ b/src/bluetooth/qbluetoothtransfermanager.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHTRANSFERMANAGER_H +#define QBLUETOOTHTRANSFERMANAGER_H + +#include "../qtconnectivityglobal.h" +#include <qbluetoothaddress.h> + +#include <QtCore/QObject> + +QT_FORWARD_DECLARE_CLASS(QIODevice) + +QT_BEGIN_HEADER + +class QBluetoothTransferReply; +class QBluetoothTransferRequest; +class QBluetoothTranferManagerPrivate; + +class Q_CONNECTIVITY_EXPORT QBluetoothTransferManager : public QObject +{ + Q_OBJECT + +public: + enum Operation { + GetOperation, + PutOperation + }; + + explicit QBluetoothTransferManager(QObject *parent = 0); + ~QBluetoothTransferManager(); + + QBluetoothTransferReply *put(const QBluetoothTransferRequest &request, QIODevice *data); + +signals: + void finished(QBluetoothTransferReply *reply); + +}; + +QT_END_HEADER + +#endif // QBLUETOOTHTRANSFERMANAGER_H diff --git a/src/bluetooth/qbluetoothtransfermanager_bluez.cpp b/src/bluetooth/qbluetoothtransfermanager_bluez.cpp new file mode 100644 index 00000000..fba6cea0 --- /dev/null +++ b/src/bluetooth/qbluetoothtransfermanager_bluez.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothtransfermanager.h" +#include "qbluetoothtransferrequest.h" +#include "qbluetoothtransferreply.h" +#include "qbluetoothtransferreply_bluez_p.h" + +QBluetoothTransferReply *QBluetoothTransferManager::put(const QBluetoothTransferRequest &request, + QIODevice *data) +{ + + QBluetoothTransferReplyBluez *rep = new QBluetoothTransferReplyBluez(data); + + rep->setAddress(request.address()); + + connect(rep, SIGNAL(finished(QBluetoothTransferReply*)), this, SIGNAL(finished(QBluetoothTransferReply*))); + + rep->start(); + + return rep; +} diff --git a/src/bluetooth/qbluetoothtransfermanager_p.cpp b/src/bluetooth/qbluetoothtransfermanager_p.cpp new file mode 100644 index 00000000..77a85187 --- /dev/null +++ b/src/bluetooth/qbluetoothtransfermanager_p.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothtransfermanager.h" +#include "qbluetoothtransferrequest.h" +#include "qbluetoothtransferreply.h" + +QBluetoothTransferReply *QBluetoothTransferManager::put(const QBluetoothTransferRequest &request, + QIODevice *data) +{ + return 0; +} diff --git a/src/bluetooth/qbluetoothtransfermanager_symbian.cpp b/src/bluetooth/qbluetoothtransfermanager_symbian.cpp new file mode 100644 index 00000000..73828dcd --- /dev/null +++ b/src/bluetooth/qbluetoothtransfermanager_symbian.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothtransfermanager.h" +#include "qbluetoothtransferrequest.h" +#include "qbluetoothtransferreply.h" +#include "qbluetoothtransferreply_symbian_p.h" + +QBluetoothTransferReply *QBluetoothTransferManager::put(const QBluetoothTransferRequest &request, + QIODevice *data) +{ + QBluetoothTransferReplySymbian *reply = + new QBluetoothTransferReplySymbian(data, QBluetoothTransferManager::PutOperation); + + reply->setAddress(request.address()); + + connect(reply, SIGNAL(finished(QBluetoothTransferReply*)), this, SIGNAL(finished(QBluetoothTransferReply*))); + + reply->start(); + + return reply; +} diff --git a/src/bluetooth/qbluetoothtransferreply.cpp b/src/bluetooth/qbluetoothtransferreply.cpp new file mode 100644 index 00000000..e8af9707 --- /dev/null +++ b/src/bluetooth/qbluetoothtransferreply.cpp @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qbluetoothtransferreply.h" +#include "qbluetoothtransferreply_p.h" +#include "qbluetoothaddress.h" + +/*! + \class QBluetoothTransferReply + \brief The QBluetoothTransferReply class contains the data and headers for a request sent with + QBluetoothTranferManager. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + In additional to a copy of the QBluetoothTransferRequest object used to create the request, + QBluetoothTransferReply contains the contents of the reply itself. + + QBluetoothTransferReply is a sequential-access QIODevice, which means that once data is read + from the object, it no longer kept by the device. It is therefore the application's + responsibility to keep this data if it needs to. Whenever more data is received and processed, + the readyRead() signal is emitted. + + The downloadProgress() signal is also emitted when data is received, but the number of bytes + contained in it may not represent the actual bytes received, if any transformation is done to + the contents (for example, decompressing and removing the protocol overhead). + + Even though QBluetoothTransferReply is a QIODevice connected to the contents of the reply, it + also emits the uploadProgress() signal, which indicates the progress of the upload for + operations that have such content. +*/ + +/*! + \enum QBluetoothTransferReply::TransferError + + This enum describes the type of error that occurred + + \value NoError No error. + \value UnknownError Unknown error, no better enum available + \value FileNotFoundError Unable to open the file specified + \value HostNotFoundError Unable to connect to the target host + \value UserCanceledTransferError User terminated the transfer +*/ + + + +/*! + \fn QBluetoothTransferReply::abort() + + Aborts this reply. +*/ +void QBluetoothTransferReply::abort() +{ + +} + +/*! + \fn void QBluetoothTransferReply::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) + + This signal is emitted whenever data is received. The \a bytesReceived parameter contains the + total number of bytes received so far out of \a bytesTotal expected for the entire transfer. +*/ + +/*! + \fn void QBluetoothTransferReply::finished(QBluetoothTransferReply *reply) + + This signal is emitted when the transfer is complete for \a reply. +*/ + +/*! + \fn void QBluetoothTransferReply::uploadProgress(qint64 bytesSent, qint64 bytesTotal) + + This signal is emitted whenever data is sent. The \a bytesSent parameter contains the total + number of bytes sent so far out of \a bytesTotal. +*/ + +/*! + Constructs a new QBluetoothTransferReply with parent \a parent. +*/ +QBluetoothTransferReply::QBluetoothTransferReply(QObject *parent) +: QObject(parent), d_ptr(new QBluetoothTransferReplyPrivate) +{ + qRegisterMetaType<QBluetoothTransferReply*>("QBluetoothTransferReply"); +} + +/*! + Destroys the QBluetoothTransferReply object. +*/ +QBluetoothTransferReply::~QBluetoothTransferReply() +{ + delete d_ptr; +} + +/*! + Returns the attribute associated with the code \a code. If the attribute has not been set, it + returns an invalid QVariant. +*/ +QVariant QBluetoothTransferReply::attribute(QBluetoothTransferRequest::Attribute code) const +{ + Q_D(const QBluetoothTransferReply); + return d->m_attributes[code]; +} + +/*! + \fn bool QBluetoothTransferReply::isFinished() const + + Returns true if this reply has finished; otherwise returns false. +*/ + +/*! + \fn bool QBluetoothTransferReply::isRunning() const + + Returns true if this reply is running; otherwise returns false. +*/ + +/*! + Returns the QBluetoothTransferManager that was used to create this QBluetoothTransferReply + object. +*/ +QBluetoothTransferManager *QBluetoothTransferReply::manager() const +{ + Q_D(const QBluetoothTransferReply); + return d->m_manager; +} + +/*! + Returns the type of operation that this reply is for. +*/ +QBluetoothTransferManager::Operation QBluetoothTransferReply::operation() const +{ + Q_D(const QBluetoothTransferReply); + return d->m_operation; +} + +/*! + Sets the operation of this QBluetoothTransferReply to \a operation. +*/ +void QBluetoothTransferReply::setOperation(QBluetoothTransferManager::Operation operation) +{ + Q_D(QBluetoothTransferReply); + d->m_operation = operation; +} + +/*! + \fn QBluetoothTransferReply::setAttribute(QBluetoothTransferRequest::Attribute code, const QVariant &value) + + Set the attribute associated with the code \a code to the value \a value. +*/ +void QBluetoothTransferReply::setAttribute(QBluetoothTransferRequest::Attribute code, const QVariant &value) +{ + Q_D(QBluetoothTransferReply); + d->m_attributes.insert(code, value); +} + +/*! + \fn QBluetoothTransferReply::setManager(QBluetoothTransferManager *manager) + + Set the reply's manager to manager \a manager. +*/ + +void QBluetoothTransferReply::setManager(QBluetoothTransferManager *manager) +{ + Q_D(QBluetoothTransferReply); + d->m_manager = manager; +} + +/*! + \fn QString QBluetoothTransferReply::errorString() const + + String describing the error. Can be displayed to the user. +*/ + +QBluetoothTransferReplyPrivate::QBluetoothTransferReplyPrivate() +{ +} + +#include "moc_qbluetoothtransferreply.cpp" diff --git a/src/bluetooth/qbluetoothtransferreply.h b/src/bluetooth/qbluetoothtransferreply.h new file mode 100644 index 00000000..c09be812 --- /dev/null +++ b/src/bluetooth/qbluetoothtransferreply.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHTRANSFERREPLY_H +#define QBLUETOOTHTRANSFERREPLY_H + +#include <QtCore/QIODevice> + +#include <qbluetoothtransferrequest.h> +#include <qbluetoothtransfermanager.h> + +QT_BEGIN_HEADER + +class QBluetoothTransferReplyPrivate; + +class Q_CONNECTIVITY_EXPORT QBluetoothTransferReply : public QObject +{ + Q_OBJECT + +public: + enum TransferError { + NoError = 0, + UnknownError, + FileNotFoundError, + HostNotFoundError, + UserCanceledTransferError + }; + + + ~QBluetoothTransferReply(); + + QVariant attribute(QBluetoothTransferRequest::Attribute code) const; + virtual bool isFinished() const = 0; + virtual bool isRunning() const = 0; + + QBluetoothTransferManager *manager() const; + + QBluetoothTransferManager::Operation operation() const; + + virtual TransferError error() const = 0; + virtual QString errorString() const = 0; + +public Q_SLOTS: + void abort(); + +Q_SIGNALS: + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + void finished(QBluetoothTransferReply *); + void uploadProgress(qint64 bytesSent, qint64 bytesTotal); + +protected: + explicit QBluetoothTransferReply(QObject *parent = 0); + void setAttribute(QBluetoothTransferRequest::Attribute code, const QVariant &value); + void setOperation(QBluetoothTransferManager::Operation operation); + void setManager(QBluetoothTransferManager *manager); +// void setRequest(QBluetoothTransferRequest *request); + +protected: + QBluetoothTransferReplyPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QBluetoothTransferReply) + +}; + +Q_DECLARE_METATYPE(QBluetoothTransferReply *); + +QT_END_HEADER + +#endif // QBLUETOOTHTRANSFERREPLY_H diff --git a/src/bluetooth/qbluetoothtransferreply_bluez.cpp b/src/bluetooth/qbluetoothtransferreply_bluez.cpp new file mode 100644 index 00000000..07f1fb7c --- /dev/null +++ b/src/bluetooth/qbluetoothtransferreply_bluez.cpp @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qbluetoothtransferreply_bluez_p.h" +#include "qbluetoothaddress.h" + +#include "bluez/obex_client_p.h" +#include "bluez/obex_manager_p.h" +#include "bluez/obex_agent_p.h" +#include "bluez/obex_transfer_p.h" +#include "qbluetoothtransferreply.h" + +#include <QFuture> +#include <QFutureWatcher> +#include <QtConcurrentRun> + +static const QLatin1String agentPath("/qt/agent"); + + +QBluetoothTransferReplyBluez::QBluetoothTransferReplyBluez(QIODevice *input, QObject *parent) +: QBluetoothTransferReply(parent), tempfile(0), source(input), + m_running(false), m_finished(false), m_size(0), + m_error(QBluetoothTransferReply::NoError), m_errorStr(), m_transfer_path() +{ + client = new OrgOpenobexClientInterface(QLatin1String("org.openobex.client"), QLatin1String("/"), + QDBusConnection::sessionBus()); + +// manager = new OrgOpenobexManagerInterface(QLatin1String("org.openobex"), QLatin1String("/"), +// QDBusConnection::sessionBus()); + + qsrand(QTime::currentTime().msec()); + m_agent_path = agentPath; + m_agent_path.append(QString::fromLatin1("/%1").arg(qrand())); + + agent = new AgentAdaptor(this); + + bool res = QDBusConnection::sessionBus().registerObject(m_agent_path, this); +// res = QDBusConnection::sessionBus().registerService("org.qt.bt"); + if(!res) + qDebug() << "Failed Creating dbus objects"; + +#ifdef NOKIA_BT_SERVICES + connectToObexServerService(); +#endif +} + +/*! + Destroys the QBluetoothTransferReply object. +*/ +QBluetoothTransferReplyBluez::~QBluetoothTransferReplyBluez() +{ + QDBusConnection::sessionBus().unregisterObject(m_agent_path); + delete client; +} + +bool QBluetoothTransferReplyBluez::start() +{ + m_running = true; + +// qDebug() << "Got a:" << source->metaObject()->className(); + QFile *file = qobject_cast<QFile *>(source); + + if(!file){ + tempfile = new QTemporaryFile(this ); + tempfile->open(); +// qDebug() << "Not a QFile, making a copy" << tempfile->fileName(); + + QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>(); + QObject::connect(watcher, SIGNAL(finished()), this, SLOT(copyDone())); + + QFuture<bool> results = QtConcurrent::run(QBluetoothTransferReplyBluez::copyToTempFile, tempfile, source); + watcher->setFuture(results); + } + else { + m_size = file->size(); + startOPP(file->fileName()); + } + return true; +} + +#ifdef NOKIA_BT_SERVICES +void QBluetoothTransferReplyBluez::connectToObexServerService() +{ + QServiceManager manager; + QServiceFilter filter("com.nokia.mt.obexserverservice.control"); +// filter.setServiceName("ObexServerServiceControl"); + + // find services complying with filter + QList<QServiceInterfaceDescriptor> foundServices; + foundServices = manager.findInterfaces(filter); + + if(foundServices.count()) { + m_obexService = manager.loadInterface(foundServices.at(0)); + } + if (m_obexService) { + qDebug() << "connected to service:" << m_obexService; + } else { + qDebug() << "failed to connect to Obex server service"; + } + + connect(m_obexService, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)), SLOT(sfwIPCError(QService::UnrecoverableIPCError))); +} +#endif + +bool QBluetoothTransferReplyBluez::copyToTempFile(QIODevice *to, QIODevice *from) +{ + char *block = new char[4096]; + int size; + + while((size = from->read(block, 4096))) { + if(size != to->write(block, size)){ + return false; + } + } + + delete[] block; + return true; +} + +void QBluetoothTransferReplyBluez::copyDone() +{ + m_size = tempfile->size(); + startOPP(tempfile->fileName()); + QObject::sender()->deleteLater(); +} + +#ifdef NOKIA_BT_SERVICES +void QBluetoothTransferReplyBluez::sfwIPCError(QService::UnrecoverableIPCError error) +{ + qDebug() << "Connection to Obex server broken:" << error << ". Trying to reconnect..."; + m_obexService->deleteLater(); + QMetaObject::invokeMethod(this, "connectToObexServerService", Qt::QueuedConnection); +} +#endif + +void QBluetoothTransferReplyBluez::startOPP(QString filename) +{ + QVariantMap device; + QStringList files; + + device.insert(QString::fromLatin1("Destination"), address.toString()); + files << filename; + + QDBusObjectPath path(m_agent_path); + QDBusPendingReply<> sendReply = client->SendFiles(device, files, path); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(sendReply, this); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(sendReturned(QDBusPendingCallWatcher*))); +} + +void QBluetoothTransferReplyBluez::sendReturned(QDBusPendingCallWatcher *watcher) +{ + + QDBusPendingReply<> sendReply = *watcher; + if(sendReply.isError()){ + qDebug() << "Failed to send file"<< sendReply.isError() << sendReply.error().message(); + m_finished = true; + m_running = false; + m_errorStr = sendReply.error().message(); + if(m_errorStr == QLatin1String("Could not open file for sending")) + m_error = QBluetoothTransferReply::FileNotFoundError; + else if(m_errorStr == QLatin1String("The transfer was canceled")) + m_error = QBluetoothTransferReply::UserCanceledTransferError; + else + m_error = QBluetoothTransferReply::UnknownError; + + // allow time for the developer to connect to the signal + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection, Q_ARG(QBluetoothTransferReply*, this)); + } +} + +QBluetoothTransferReply::TransferError QBluetoothTransferReplyBluez::error() const +{ + return m_error; +} + +QString QBluetoothTransferReplyBluez::errorString() const +{ + return m_errorStr; +} + +void QBluetoothTransferReplyBluez::Complete(const QDBusObjectPath &in0) +{ + Q_UNUSED(in0); + m_transfer_path.clear(); + m_finished = true; + m_running = false; + +#ifdef NOKIA_BT_SERVICES + if (m_obexService) + QMetaObject::invokeMethod(m_obexService, "setTransferFinished", Q_ARG(QString, in0.path()), Q_ARG(bool, true)); +#endif +} + +void QBluetoothTransferReplyBluez::Error(const QDBusObjectPath &in0, const QString &in1) +{ + Q_UNUSED(in0); + m_transfer_path.clear(); + m_finished = true; + m_running = false; + m_errorStr = in1; + if (in1 == QLatin1String("Could not open file for sending")) + m_error = QBluetoothTransferReply::FileNotFoundError; + else + m_error = QBluetoothTransferReply::UnknownError; + + emit finished(this); + +#ifdef NOKIA_BT_SERVICES + if (m_obexService) + QMetaObject::invokeMethod(m_obexService, "setTransferFinished", Q_ARG(QString, in0.path()), Q_ARG(bool, false)); +#endif +} + +void QBluetoothTransferReplyBluez::Progress(const QDBusObjectPath &in0, qulonglong in1) +{ + Q_UNUSED(in0); + emit uploadProgress(in1, m_size); + +#ifdef NOKIA_BT_SERVICES + if (m_obexService) + QMetaObject::invokeMethod(m_obexService, "setTransferProgress", Q_ARG(QString, in0.path()), Q_ARG(quint64, in1), Q_ARG(quint64, m_size)); +#endif +} + +void QBluetoothTransferReplyBluez::Release() +{ + if(m_errorStr.isEmpty()) + emit finished(this); +} + +QString QBluetoothTransferReplyBluez::Request(const QDBusObjectPath &in0) +{ + m_transfer_path = in0.path(); + +#ifdef NOKIA_BT_SERVICES + if (m_obexService) { + QFile *file = qobject_cast<QFile *>(source); + QMetaObject::invokeMethod(m_obexService, "outgoingFile", Q_ARG(QString, m_transfer_path), Q_ARG(QString, address.toString()), Q_ARG(QString, file->fileName()), Q_ARG(QString, QBluetoothTransferReply::attribute(QBluetoothTransferRequest::TypeAttribute).toString()), Q_ARG(quint64, m_size)); + QMetaObject::invokeMethod(m_obexService, "setTransferStarted", Q_ARG(QString, m_transfer_path)); + } +#endif + + return QString(); + +} + +/*! + Returns true if this reply has finished; otherwise returns false. +*/ +bool QBluetoothTransferReplyBluez::isFinished() const +{ + return m_finished; +} + +/*! + Returns true if this reply is running; otherwise returns false. +*/ +bool QBluetoothTransferReplyBluez::isRunning() const +{ + return m_running; +} + +void QBluetoothTransferReplyBluez::abort() +{ + if(!m_transfer_path.isEmpty()){ + OrgOpenobexTransferInterface *xfer = new OrgOpenobexTransferInterface(QLatin1String("org.openobex.client"), m_transfer_path, + QDBusConnection::sessionBus()); + QDBusPendingReply<> reply = xfer->Cancel(); + reply.waitForFinished(); + if(reply.isError()){ + qDebug() << "Failed to abort transfer" << reply.error(); + } + delete xfer; + +#ifdef NOKIA_BT_SERVICES + if (m_obexService) + QMetaObject::invokeMethod(m_obexService, "setTransferFinished", Q_ARG(QString, m_transfer_path), Q_ARG(bool, false)); +#endif + + } +} + +void QBluetoothTransferReplyBluez::setAddress(const QBluetoothAddress &destination) +{ + address = destination; +} + +qint64 QBluetoothTransferReplyBluez::readData(char*, qint64) +{ + return 0; +} + +qint64 QBluetoothTransferReplyBluez::writeData(const char*, qint64) +{ + return 0; +} + + +#include "moc_qbluetoothtransferreply_bluez_p.cpp" diff --git a/src/bluetooth/qbluetoothtransferreply_bluez_p.h b/src/bluetooth/qbluetoothtransferreply_bluez_p.h new file mode 100644 index 00000000..abc0b497 --- /dev/null +++ b/src/bluetooth/qbluetoothtransferreply_bluez_p.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHTRANSFERREPLY_BLUEZ_P_H +#define QBLUETOOTHTRANSFERREPLY_BLUEZ_P_H + +#include <QtCore/QIODevice> +#include <QtDBus/QtDBus> + +#include <qbluetoothtransferrequest.h> +#include <qbluetoothtransfermanager.h> + +#include "qbluetoothtransferreply.h" + +#ifdef NOKIA_BT_SERVICES +#include <QtServiceFramework/QServiceManager> +#endif + +QT_BEGIN_HEADER + +class OrgOpenobexClientInterface; +class OrgOpenobexManagerInterface; +class AgentAdaptor; + +class Q_CONNECTIVITY_EXPORT QBluetoothTransferReplyBluez : public QBluetoothTransferReply +{ + Q_OBJECT + +public: + explicit QBluetoothTransferReplyBluez(QIODevice *input, QObject *parent = 0); + ~QBluetoothTransferReplyBluez(); + + QVariant attribute(QBluetoothTransferRequest::Attribute code) const; + bool isFinished() const; + bool isRunning() const; + + bool start(); + + void startOPP(QString filename); + + void setAddress(const QBluetoothAddress &address); + + QBluetoothTransferReply::TransferError error() const; + QString errorString() const; + +protected: + qint64 readData(char*, qint64); + qint64 writeData(const char*, qint64); + +private: + OrgOpenobexClientInterface *client; + OrgOpenobexManagerInterface *manager; + AgentAdaptor *agent; + + QTemporaryFile *tempfile; + QIODevice *source; + + bool m_running; + bool m_finished; + + quint64 m_size; + + QBluetoothAddress address; + + QBluetoothTransferReply::TransferError m_error; + QString m_errorStr; + + QString m_agent_path; + + QString m_transfer_path; + +#ifdef NOKIA_BT_SERVICES + QObject *m_obexService; +#endif + + static bool copyToTempFile(QIODevice *to, QIODevice *from); + +private slots: + void copyDone(); + +#ifdef NOKIA_BT_SERVICES + void connectToObexServerService(); + void sfwIPCError(QService::UnrecoverableIPCError); +#endif + +public slots: + void abort(); + void Complete(const QDBusObjectPath &in0); + void Error(const QDBusObjectPath &in0, const QString &in1); + void Progress(const QDBusObjectPath &in0, qulonglong in1); + void Release(); + QString Request(const QDBusObjectPath &in0); + void sendReturned(QDBusPendingCallWatcher*); + +}; + +QT_END_HEADER + +#endif // QBLUETOOTHTRANSFERREPLY_H diff --git a/src/bluetooth/qbluetoothtransferreply_p.h b/src/bluetooth/qbluetoothtransferreply_p.h new file mode 100644 index 00000000..2e0058d4 --- /dev/null +++ b/src/bluetooth/qbluetoothtransferreply_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHTRANSFERREPLY_P_H +#define QBLUETOOTHTRANSFERREPLY_P_H + +#include "qbluetoothtransferreply.h" + +QT_BEGIN_HEADER + +class Q_CONNECTIVITY_EXPORT QBluetoothTransferReplyPrivate +{ +public: + QBluetoothTransferReplyPrivate(); + + QBluetoothTransferManager *m_manager; + QBluetoothTransferManager::Operation m_operation; + QMap<int, QVariant> m_attributes; + qint64 m_buffersize; + + QBluetoothTransferReply *q_ptr; + +}; + +QT_END_HEADER + +#endif // QBLUETOOTHTRANSFERREPLY_H diff --git a/src/bluetooth/qbluetoothtransferreply_symbian.cpp b/src/bluetooth/qbluetoothtransferreply_symbian.cpp new file mode 100644 index 00000000..e90c6017 --- /dev/null +++ b/src/bluetooth/qbluetoothtransferreply_symbian.cpp @@ -0,0 +1,315 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qbluetoothtransferreply_symbian_p.h" +#include "symbian/utils_symbian_p.h" +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothserviceinfo.h" +#include "qbluetoothuuid.h" + +#include <QDebug> +#include <QFile> +#include <QFileInfo> +#include <QDir> + +QBluetoothTransferReplySymbian::QBluetoothTransferReplySymbian(QIODevice *input, + QBluetoothTransferManager::Operation operation, QObject *parent) + : QBluetoothTransferReply(parent) + , CActive(EPriorityStandard) + , m_source(input) + , m_running(false) + , m_finished(false) + , m_client(NULL) + , m_object(NULL) + , m_error(QBluetoothTransferReply::NoError) + , m_errorStr() + , m_timer(new QTimer(this)) +{ + setOperation(operation); + + //add this active object to scheduler + CActiveScheduler::Add(this); + connect(m_timer, SIGNAL(timeout()), this, SLOT(updateProgress())); + +} + +/*! + Destroys the QBluetoothTransferReply object. +*/ +QBluetoothTransferReplySymbian::~QBluetoothTransferReplySymbian() +{ + Cancel(); + + if (m_timer->isActive()) + m_timer->stop(); + + delete m_object; + m_object = NULL; + + delete m_client; + m_client = NULL; +} + +void QBluetoothTransferReplySymbian::setAddress(const QBluetoothAddress &address) +{ + m_address = address; +} + +void QBluetoothTransferReplySymbian::serviceDiscovered(const QBluetoothServiceInfo &info) +{ + m_port = info.serverChannel(); +} + +void QBluetoothTransferReplySymbian::updateProgress() +{ + if (m_object) { + qint64 sent = m_object->BytesSent(); + emit uploadProgress(sent, m_fileSize); + } +} + +void QBluetoothTransferReplySymbian::serviceDiscoveryFinished() +{ + QMetaObject::invokeMethod(this, "startTransfer", Qt::QueuedConnection); +} + +bool QBluetoothTransferReplySymbian::start() +{ + if (m_address.isNull()) + return false; + + m_running = true; + + m_discoveryAgent = new QBluetoothServiceDiscoveryAgent(m_address); + + connect(m_discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), + this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); + connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(serviceDiscoveryFinished())); + // Automatically delete agent when device discovery finishes. + connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(deleteLater())); + + m_discoveryAgent->setUuidFilter(QBluetoothUuid(QBluetoothUuid::ObexObjectPush)); + m_discoveryAgent->start(); + + return true; +} + +void QBluetoothTransferReplySymbian::startTransfer() +{ + TObexBluetoothProtocolInfo protocolInfo; + TBTDevAddr deviceAddress(m_address.toUInt64()); + + protocolInfo.iTransport.Copy(KBTSProtocol); + protocolInfo.iAddr.SetBTAddr(deviceAddress); + protocolInfo.iAddr.SetPort(m_port); // TODO: set port if needed + + if ( m_client ) { + delete m_client; + m_client = NULL; + } + + TRAPD( err, m_client = CObexClient::NewL(protocolInfo)); + if (err) { + qDebug() << "Error in" << __FUNCTION__ << err; + m_error = err == KErrNotFound ? HostNotFoundError: UnknownError; + return; + } + + m_state = EConnecting; + m_client->Connect( iStatus ); + + SetActive(); +} + +/*! + Returns true if this reply has finished; otherwise returns false. +*/ +bool QBluetoothTransferReplySymbian::isFinished() const +{ + return m_finished; +} + +/*! + Returns true if this reply is running; otherwise returns false. +*/ +bool QBluetoothTransferReplySymbian::isRunning() const +{ + return m_running; +} + +void QBluetoothTransferReplySymbian::abort() +{ + if (m_timer->isActive()) + m_timer->stop(); + m_state = EIdle; + m_running = false; + // Deleting obexclient is the only way to cancel active requests + delete m_client; + m_client = NULL; + + delete m_object; + m_object = NULL; +} + +QBluetoothTransferReply::TransferError QBluetoothTransferReplySymbian::error() const +{ + return m_error; +} + +QString QBluetoothTransferReplySymbian::errorString() const +{ + return m_errorStr; +} + +void QBluetoothTransferReplySymbian::DoCancel() +{ + m_running = false; + // Deleting obexclient is the only way to cancel active requests + if ( m_client ) { + delete m_client; + m_client = NULL; + m_state = EIdle; + } + if (m_timer->isActive()) + m_timer->stop(); + m_error = UserCanceledTransferError; +} + +void QBluetoothTransferReplySymbian::RunL() +{ + if (iStatus.Int() != KErrNone) { + abort(); + emit finished(this); + } + + switch ( m_state ) { + case EConnecting: { + m_state = ESending; + QFile *file = qobject_cast<QFile *>(m_source); + + QString filename; + if (file) { + QFileInfo info(*file); + m_fileSize = info.size(); + filename = QDir::toNativeSeparators(info.absoluteFilePath()); + } else { + if (copyToTempFile(m_tempfile, m_source)) { + QFileInfo info(*m_tempfile); + m_fileSize = info.size(); + filename = QDir::toNativeSeparators(info.absoluteFilePath()); + } else { + m_state = EDisconnecting; + disconnect(); + } + } + sendObject(filename); + break; + } + case ESending: { + m_state = EDisconnecting; + disconnect(); + break; + } + case EDisconnecting: { + m_state = EIdle; + m_finished = true; + m_running = false; + emit finished(this); + break; + } + case EIdle: + default: + break; + } + +} + +void QBluetoothTransferReplySymbian::sendObject(QString filename) +{ + delete m_object; + m_object = NULL; + TRAPD(err, m_object = CObexFileObject::NewL()); + if (!err) { + TPtrC16 str(reinterpret_cast<const TUint16*>(filename.utf16())); + TRAPD(error, m_object->InitFromFileL( str )); + if (!error) { + m_client->Put( *m_object, iStatus ); + m_timer->start(1000); + emit uploadProgress(0, m_fileSize); + SetActive(); + } else { + qDebug() << "Error in" << __FUNCTION__ << error; + m_error = error == KErrNotFound ? FileNotFoundError: UnknownError; + disconnect(); + emit finished(this); + } + } +} + +void QBluetoothTransferReplySymbian::disconnect() +{ + if ( m_state == EDisconnecting || m_error != NoError) { + if (m_timer->isActive()) + m_timer->stop(); + delete m_object; + m_object = NULL; + m_client->Disconnect( iStatus ); + SetActive(); + } +} + +bool QBluetoothTransferReplySymbian::copyToTempFile(QIODevice *to, QIODevice *from) +{ + char *block = new char[4096]; + + while (!from->atEnd()) { + int size = from->read(block, 4096); + if (size != to->write(block, size)) { + return false; + } + } + + delete[] block; + return true; +} + +#include "moc_qbluetoothtransferreply_symbian_p.cpp" diff --git a/src/bluetooth/qbluetoothtransferreply_symbian_p.h b/src/bluetooth/qbluetoothtransferreply_symbian_p.h new file mode 100644 index 00000000..002451ac --- /dev/null +++ b/src/bluetooth/qbluetoothtransferreply_symbian_p.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHTRANSFERREPLYSYMBIAN_H +#define QBLUETOOTHTRANSFERREPLYSYMBIAN_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qbluetoothtransferreply.h" +#include <e32base.h> +#include <obex.h> + +#include <QTemporaryFile> +#include <QIODevice> +#include <QTimer> + +QT_BEGIN_HEADER + +class QBluetoothServiceDiscoveryAgent; +class QBluetoothServiceInfo; + +_LIT( KBTSProtocol, "RFCOMM" ); // The Bluetooth transport layer + +class QBluetoothTransferReplySymbian : public QBluetoothTransferReply, public CActive +{ + Q_OBJECT + +public: + enum state + { + EIdle, + EConnecting, + ESending, + EDisconnecting + }; + + QBluetoothTransferReplySymbian(QIODevice *input, QBluetoothTransferManager::Operation, QObject *parent = 0); + ~QBluetoothTransferReplySymbian(); + + void abort(); + bool isFinished() const; + bool isRunning() const; + + bool start(); + + void setAddress(const QBluetoothAddress &address); + + QBluetoothTransferReply::TransferError error() const; + QString errorString() const; + +private: + void sendObject(QString filename); + void disconnect(); + + //From CActive + void DoCancel(); + void RunL(); + + static bool copyToTempFile(QIODevice *to, QIODevice *from); + +private slots: + void startTransfer(); + + void serviceDiscovered(const QBluetoothServiceInfo &info); + void serviceDiscoveryFinished(); + + void updateProgress(); + +private: + QIODevice *m_source; + QTemporaryFile *m_tempfile; + + QBluetoothAddress m_address; + QBluetoothServiceDiscoveryAgent* m_discoveryAgent; + + bool m_running; + bool m_finished; + + CObexClient* m_client; + CObexFileObject* m_object; + + QBluetoothTransferReply::TransferError m_error; + QString m_errorStr; + + state m_state; + qint64 m_fileSize; + int m_port; + + QTimer *m_timer; +}; + +QT_END_HEADER + +#endif // QBLUETOOTHTRANSFERREPLYPRIVATE_H diff --git a/src/bluetooth/qbluetoothtransferrequest.cpp b/src/bluetooth/qbluetoothtransferrequest.cpp new file mode 100644 index 00000000..e7245436 --- /dev/null +++ b/src/bluetooth/qbluetoothtransferrequest.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothtransferrequest.h" +#include "qbluetoothaddress.h" +#include "qbluetoothtransferrequest_p.h" + + +/*! + \class QBluetoothTransferRequest + \brief The QBluetoothTransferRequest class holds a request to be sent with + QBluetoothTransferManager. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + QBluetoothTransferRequest is part of the Bluetooth Transfer API and is the class holding the + information necessary to initiate a transfer over Bluetooth. + + \sa QBluetoothTransferReply, QBluetoothTransferManager +*/ + +/*! + \enum QBluetoothTransferRequest::Attribute + + Attribute codes for QBluetoothTransferRequest and QBluetoothTransferReply. + + \value DescriptionAttribute A textural description of the object being transferred. May be + display in the UI of the remote device. + \value TimeAttribute Time attribute of the object being transferred. + \value TypeAttribute MIME type of the object being transferred. + \value LengthAttribute Length in bytes of the object being transferred. + \value NameAttribute Name of the object being transferred. May be displayed in the UI of + the remote device. +*/ + +/*! + Constructs a new Bluetooth transfer request to the device wit address \a address. +*/ +QBluetoothTransferRequest::QBluetoothTransferRequest(const QBluetoothAddress &address) +:d_ptr(new QBluetoothTransferRequestPrivate) +{ + Q_D(QBluetoothTransferRequest); + + d->m_address = address; +} + +/*! + Constructs a new Bluetooth transfer request that is a copy of \a other. +*/ +QBluetoothTransferRequest::QBluetoothTransferRequest(const QBluetoothTransferRequest &other) +:d_ptr(new QBluetoothTransferRequestPrivate) +{ + *this = other; +} + +/*! + Destorys the Bluetooth transfer request. +*/ +QBluetoothTransferRequest::~QBluetoothTransferRequest() +{ + delete d_ptr; +} + +/*! + Returns the attribute associated with code \a code. If the attribute has not been set, it + returns \a defaultValue. + + \sa setAttribute(), QBluetoothTransferRequest::Attribute +*/ +QVariant QBluetoothTransferRequest::attribute(Attribute code, const QVariant &defaultValue) const +{ + Q_D(const QBluetoothTransferRequest); + + if (d->m_parameters.contains((int)code)) { + return d->m_parameters.value((int)code); + } else { + return defaultValue; + } +} + +/*! + Sets the attribute associated with code \a code to be value \a value. If the attribute is + already set, the previous value is discarded. If \a value is an invalid QVariant, the attribute + is unset. + + \sa attribute(), QBluetoothTransferRequest::Attribute +*/ +void QBluetoothTransferRequest::setAttribute(Attribute code, const QVariant &value) +{ + Q_D(QBluetoothTransferRequest); + + d->m_parameters.insert((int)code, value); +} + +/*! + Returns the address associated with the Bluetooth transfer request. +*/ +QBluetoothAddress QBluetoothTransferRequest::address() const +{ + Q_D(const QBluetoothTransferRequest); + + return d->m_address; +} + + +/*! + Returns true if this object is not the same as \a other. + + \sa operator==() +*/ +bool QBluetoothTransferRequest::operator!=(const QBluetoothTransferRequest &other) const +{ + return !(*this == other); +} + +/*! + Creates a copy of \a other. +*/ +QBluetoothTransferRequest &QBluetoothTransferRequest::operator=(const QBluetoothTransferRequest &other) +{ + Q_D(QBluetoothTransferRequest); + + d->m_address = other.d_func()->m_address; + d->m_parameters = other.d_func()->m_parameters; + + return *this; +} + +/*! + Returns true if this object is the same as \a other. +*/ +bool QBluetoothTransferRequest::operator==(const QBluetoothTransferRequest &other) const +{ + Q_D(const QBluetoothTransferRequest); + if (d->m_address == other.d_func()->m_address && d->m_parameters == other.d_func()->m_parameters) { + return true; + } + return false; +} + +QBluetoothTransferRequestPrivate::QBluetoothTransferRequestPrivate() +{ +} + diff --git a/src/bluetooth/qbluetoothtransferrequest.h b/src/bluetooth/qbluetoothtransferrequest.h new file mode 100644 index 00000000..43322b22 --- /dev/null +++ b/src/bluetooth/qbluetoothtransferrequest.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHTRANSFERREQUEST_H +#define QBLUETOOTHTRANSFERREQUEST_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QtGlobal> +#include <QtCore/QVariant> + +QT_BEGIN_HEADER + +class QBluetoothAddress; +class QBluetoothTransferRequestPrivate; + +class Q_CONNECTIVITY_EXPORT QBluetoothTransferRequest +{ +public: + enum Attribute { + DescriptionAttribute, + TimeAttribute, + TypeAttribute, + LengthAttribute, + NameAttribute + }; + + QBluetoothTransferRequest(const QBluetoothAddress &address); + QBluetoothTransferRequest(const QBluetoothTransferRequest &other); + ~QBluetoothTransferRequest(); + + QVariant attribute(Attribute code, const QVariant &defaultValue = QVariant()) const; + void setAttribute(Attribute code, const QVariant &value); + + QBluetoothAddress address() const; + + bool operator!=(const QBluetoothTransferRequest &other) const; + QBluetoothTransferRequest &operator=(const QBluetoothTransferRequest &other); + bool operator==(const QBluetoothTransferRequest &other) const; + +protected: + QBluetoothTransferRequestPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QBluetoothTransferRequest) + +}; + +QT_END_HEADER + +#endif // QBLUETOOTHTRANSFERREQUEST_H diff --git a/src/bluetooth/qbluetoothtransferrequest_p.h b/src/bluetooth/qbluetoothtransferrequest_p.h new file mode 100644 index 00000000..decf939c --- /dev/null +++ b/src/bluetooth/qbluetoothtransferrequest_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHTRANSFERREQUESTPRIVATE_H +#define QBLUETOOTHTRANSFERREQUESTPRIVATE_H + +#include "../qtconnectivityglobal.h" +#include "qbluetoothtransferrequest.h" + +QT_BEGIN_HEADER + +class QBluetoothAddress; + +class QBluetoothTransferRequestPrivate +{ +public: + QBluetoothTransferRequestPrivate(); + + QBluetoothAddress m_address; + QMap<int, QVariant> m_parameters; +}; + +QT_END_HEADER + +#endif // QBLUETOOTHTRANSFERREQUESTPRIVATE_H diff --git a/src/bluetooth/qbluetoothuuid.cpp b/src/bluetooth/qbluetoothuuid.cpp new file mode 100644 index 00000000..c4b57c5b --- /dev/null +++ b/src/bluetooth/qbluetoothuuid.cpp @@ -0,0 +1,358 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothuuid.h" + +#include <QStringList> + +#include <QDebug> + +#include <QtEndian> + +//#include <arpa/inet.h> +//#include <netinet/in.h> +#include <string.h> + +// Bluetooth base UUID 00000000-0000-1000-8000-00805F9B34FB +// TODO: make more efficient +Q_GLOBAL_STATIC_WITH_ARGS(QUuid, baseUuid, ("{00000000-0000-1000-8000-00805F9B34FB}")) + +/*! + \class QBluetoothUuid + \brief The QBluetoothUuid class provides a Bluetooth UUID. + \since 5.0 + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity +*/ + +/*! + \enum QBluetoothUuid::ProtocolUuid + + This enum is a convienience type for Bluetooth protocol UUIDs. Values of this type will be + implicitly converted into a QBluetoothUuid when necessary. + + \value Sdp SDP protocol UUID. + \value Udp UDP protocol UUID. + \value Rfcomm RFCOMM protocol UUID. + \value Tcp TCP protocol UUID. + \value TcsBin Telephony Control Specification UUID. + \value TcsAt Telephony Control Specification AT UUID. + \value Obex OBEX protocol UUID. + \value Ip IP protocol UUID. + \value Ftp FTP protocol UUID. + \value Http HTTP protocol UUID. + \value Wsp WSP UUID + \value Bnep Bluetooth Network Encapsulation Protocol UUID + \value Upnp Extended Service Discovery Profile UUID + \value Hidp Human Interface Device Profile UUID + \value HardcopyControlChannel Hardcopy Cable Replacement Profile UUID + \value HardcopyDataChannel Hardcopy Cable Replacement Profile UUID + \value HardcopyNotification Hardcopy Cable Replacement Profile UUID + \value Avctp Audio/Video Control Transport Protocol UUID + \value Avdtp Audio/Video Distribution Transport Protocol UUID + \value Cmtp Common ISDN Access Profile + \value UdiCPlain UDI protocol UUID + \value McapControlChannel Multi-Channel Adaptation Protocol UUID + \value McapDataChannel Multi-Channel Adaptation Protocol UUID + \value L2cap L2CAP protocol UUID. +*/ + +/*! + \enum QBluetoothUuid::ServiceClassUuid + + This enum is a convienience type for Bluetooth service class UUIDs. Values of this type will be + implicitly converted into a QBluetoothUuid when necessary. + + \value PublicBrowseGroup Public browse group service class. Services which have the public + browse group in their + \l {QBluetoothServiceInfo::BrowseGroupList}{browse group list} are + discoverable by remote devices. + \value ObexObjectPush OBEX object push service UUID. + \value ServiceDiscoveryServer + \value BrowseGroupDescriptor Browser group descriptor + \value SerialPort Serial Port Profile UUID + \value LANAccessUsingPPP LAN Access Profile UUID + \value DialupNetworking Dial-up Networking Profile UUID + \value IrMCSync Synchronization Profile UUID + \value OBEXFileTransfer File Transfer Profile (FTP) UUID + \value IrMCSyncCommand Synchronization Profile UUID + \value Headset Headset Profile (HSP) UUID + \value AudioSource Advanced Audio Distribution Profile (A2DP) UUID + \value AudioSink Advanced Audio Distribution Profile (A2DP) UUID + \value AV_RemoteControlTarget Audio/Video Remote Control Profile (AVRCP) UUID + \value AdvancedAudioDistribution Advanced Audio Distribution Profile (A2DP) UUID + \value AV_RemoteControl Audio/Video Remote Control Profile (AVRCP) UUID + \value AV_RemoteControlController Audio/Video Remote Control Profile UUID + \value HeadsetAG Headset Profile (HSP) UUID + \value PANU Personal Area Networking Profile (PAN) UUID + \value NAP Personal Area Networking Profile (PAN) UUID + \value GN Personal Area Networking Profile (PAN) UUID + \value DirectPrinting Basic Printing Profile (BPP) UUID + \value ReferencePrinting Related to Basic Printing Profile (BPP) UUID + \value ImagingResponder Basic Imaging Profile (BIP) UUID + \value ImagingResponder Basic Imaging Profile (BIP) UUID + \value ImagingAutomaticArchive Basic Imaging Profile (BIP) UUID + \value Handsfree Hands-Free Profile (HFP) Service Class Identifier and Profile Identifier + \value HandsfreeAudioGateway Hands-free Profile (HFP) UUID + \value DirectPrintingReferenceObjectsService Basic Printing Profile (BPP) UUID + \value ReflectedUI Basic Printing Profile (BPP) UUID + \value BasicPrinting Basic Printing Profile (BPP) UUID + \value PrintingStatus Basic Printing Profile (BPP) UUID + \value HumanInterfaceDeviceService Human Interface Device (HID) UUID + \value HardcopyCableReplacement Hardcopy Cable Replacement Profile (HCRP) + \value HCRPrint Hardcopy Cable Replacement Profile (HCRP) + \value HCRScan Hardcopy Cable Replacement Profile (HCRP) + \value SIMAccess SIM Access Profile (SAP) UUID + \value PhonebookAccessPCE Phonebook Access Profile (PBAP) UUID + \value PhonebookAccessPSE Phonebook Access Profile (PBAP) UUID + \value PhonebookAccess Phonebook Access Profile (PBAP) + \value HeadsetHS Headset Profile (HSP) UUID + \value MessageAccessServer Message Access Profile (MAP) UUID + \value MessageNotificationServer Message Access Profile (MAP) UUID + \value MessageAccessProfile Message Access Profile (MAP) UUID + \value PnPInformation Device Identification (DID) UUID + \value GenericNetworking Generic networking + \value GenericFileTransfer Generic file transfer + \value GenericAudio Generic audio + \value GenericTelephony Generic telephone + \value VideoSource Video Distribution Profile (VDP) + \value VideoSink Video Distribution Profile (VDP) + \value VideoDistribution Video Distribution Profile (VDP) + \value HDP Health Device Profile + \value HDPSource Health Device Profile + \value HDPSink Health Device Profile +*/ + +/*! + Constructs a new null Bluetooth UUID. +*/ +QBluetoothUuid::QBluetoothUuid() +{ +} + +/*! + Constructs a new Bluetooth UUID from the protocol UUID \a uuid. +*/ +QBluetoothUuid::QBluetoothUuid(ProtocolUuid uuid) +: QUuid(uuid, baseUuid()->data2, + baseUuid()->data3, baseUuid()->data4[0], baseUuid()->data4[1], + baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], + baseUuid()->data4[6], baseUuid()->data4[7]) +{ +} + +/*! + Constructs a new Bluetooth UUID from the service class UUID \a uuid. +*/ +QBluetoothUuid::QBluetoothUuid(ServiceClassUuid uuid) +: QUuid(uuid, baseUuid()->data2, baseUuid()->data3, baseUuid()->data4[0], baseUuid()->data4[1], + baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], + baseUuid()->data4[6], baseUuid()->data4[7]) +{ +} + +/*! + Constructs a new Bluetooth UUID from the 16 bit UUID \a uuid. +*/ +QBluetoothUuid::QBluetoothUuid(quint16 uuid) +: QUuid(uuid, baseUuid()->data2, baseUuid()->data3, baseUuid()->data4[0], baseUuid()->data4[1], + baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], + baseUuid()->data4[6], baseUuid()->data4[7]) +{ +} + +/*! + Constructs a new Bluetooth UUID from the 32 bit UUID \a uuid. +*/ +QBluetoothUuid::QBluetoothUuid(quint32 uuid) +: QUuid(uuid, baseUuid()->data2, baseUuid()->data3, baseUuid()->data4[0], baseUuid()->data4[1], + baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], + baseUuid()->data4[6], baseUuid()->data4[7]) +{ +} + +/*! + Constructs a new Bluetooth UUID from the 128 bit UUID \a uuid. +*/ +QBluetoothUuid::QBluetoothUuid(quint128 uuid) +{ + // TODO: look at the memcpy(), should not be needed + quint32 tmp32; + memcpy(&tmp32, &uuid.data[0], 4); + data1 = qFromBigEndian<quint32>(tmp32); + + quint16 tmp16; + memcpy(&tmp16, &uuid.data[4], 2); + data2 = qFromBigEndian<quint16>(tmp16); + + memcpy(&tmp16, &uuid.data[6], 2); + data3 = qFromBigEndian<quint16>(tmp16); + + memcpy(data4, &uuid.data[8], 8); +} + +/*! + Constructs a new Bluetooth UUID from the string \a uuid. + + The string must be in the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. +*/ +QBluetoothUuid::QBluetoothUuid(const QString &uuid) +: QUuid(uuid) +{ +} + +/*! + Constructs a new Bluetooth UUID that is a copy of \a uuid. +*/ +QBluetoothUuid::QBluetoothUuid(const QBluetoothUuid &uuid) +: QUuid(uuid) +{ +} + +/*! + Constructs a new Bluetooth UUID that is a copy of \a uuid. +*/ +QBluetoothUuid::QBluetoothUuid(const QUuid &uuid) +: QUuid(uuid) +{ +} + +/*! + Destroys the Bluetooth UUID. +*/ +QBluetoothUuid::~QBluetoothUuid() +{ +} + +/*! + Returns the minimum size in bytes that this UUID can be represented in. For non-null UUIDs 2, + 4 or 16 is returned. 0 is returned for null UUIDs. + + \sa isNull(), toUInt16(), toUInt32(), toUInt128() +*/ +int QBluetoothUuid::minimumSize() const +{ + if (data2 == baseUuid()->data2 && data3 == baseUuid()->data3 && + memcmp(data4, baseUuid()->data4, 8) == 0) { + // 16 or 32 bit Bluetooth UUID + if (data1 & 0xFFFF0000) + return 4; + else + return 2; + } + + if (isNull()) + return 0; + + return 16; +} + +/*! + Returns the 16 bit representation of this UUID. If \a ok is passed it is set to true if the + conversion is possible otherwise it is set to false. The return value is undefined if \a ok is + set to false. +*/ +quint16 QBluetoothUuid::toUInt16(bool *ok) const +{ + if (data1 & 0xFFFF0000 || data2 != baseUuid()->data2 || data3 != baseUuid()->data3 || + memcmp(data4, baseUuid()->data4, 8) != 0) { + // not convertable to 16 bit Bluetooth UUID. + if (ok) + *ok = false; + return 0; + } + + if (ok) + *ok = true; + + return data1; +} + +/*! + Returns the 32 bit representation of this UUID. If \a ok is passed it is set to true if the + conversion is possible otherwise it is set to false. The return value is undefined if \a ok is + set to false. +*/ +quint32 QBluetoothUuid::toUInt32(bool *ok) const +{ + if (data2 != baseUuid()->data2 || data3 != baseUuid()->data3 || + memcmp(data4, baseUuid()->data4, 8) != 0) { + // not convertable to 32 bit Bluetooth UUID. + if (ok) + *ok = false; + return 0; + } + + if (ok) + *ok = true; + + return data1; +} + +/*! + Returns the 128 bit representation of this UUID. +*/ +quint128 QBluetoothUuid::toUInt128() const +{ + quint128 uuid; + + quint32 tmp32 = qToBigEndian<quint32>(data1); + memcpy(&uuid.data[0], &tmp32, 4); + + quint16 tmp16 = qToBigEndian<quint16>(data2); + memcpy(&uuid.data[4], &tmp16, 2); + + tmp16 = qToBigEndian<quint16>(data3); + memcpy(&uuid.data[6], &tmp16, 2); + + memcpy(&uuid.data[8], data4, 8); + + return uuid; +} + +/*! + Returns true if \a other is equal to this Bluetooth UUID; otherwise returns false. +*/ +bool QBluetoothUuid::operator==(const QBluetoothUuid &other) const +{ + return QUuid::operator==(other); +} diff --git a/src/bluetooth/qbluetoothuuid.h b/src/bluetooth/qbluetoothuuid.h new file mode 100644 index 00000000..09e0db65 --- /dev/null +++ b/src/bluetooth/qbluetoothuuid.h @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBLUETOOTHUUID_H +#define QBLUETOOTHUUID_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QtGlobal> +#include <QtCore/QMetaType> +#include <QtCore/QUuid> + +#include <QtCore/QDebug> + +QT_BEGIN_HEADER + +struct quint128 +{ + quint8 data[16]; +}; + +class Q_CONNECTIVITY_EXPORT QBluetoothUuid : public QUuid +{ +public: + enum ProtocolUuid { + Sdp = 0x0001, + Udp = 0x0002, + Rfcomm = 0x0003, + Tcp = 0x0004, + TcsBin = 0x0005, + TcsAt = 0x0006, + Obex = 0x0008, + Ip = 0x0009, + Ftp = 0x000A, + Http = 0x000C, + Wsp = 0x000E, + Bnep = 0x000F, + Upnp = 0x0010, + Hidp = 0x0011, + HardcopyControlChannel = 0x0012, + HardcopyDataChannel = 0x0014, + HardcopyNotification = 0x0016, + Avctp = 0x0017, + Avdtp = 0x0019, + Cmtp = 0x001B, + UdiCPlain = 0x001D, + McapControlChannel = 0x001E, + McapDataChannel = 0x001F, + L2cap = 0x0100, + }; + + enum ServiceClassUuid { + ServiceDiscoveryServer = 0x1000, + BrowseGroupDescriptor = 0x1001, + PublicBrowseGroup = 0x1002, + SerialPort = 0x1101, + LANAccessUsingPPP = 0x1102, + DialupNetworking = 0x1103, + IrMCSync = 0x1104, + ObexObjectPush = 0x1105, + OBEXFileTransfer = 0x1106, + IrMCSyncCommand = 0x1107, + Headset = 0x1108, + AudioSource = 0x110a, + AudioSink = 0x110b, + AV_RemoteControlTarget = 0x110c, + AdvancedAudioDistribution = 0x110d, + AV_RemoteControl = 0x110e, + AV_RemoteControlController = 0x110f, + HeadsetAG = 0x1112, + PANU = 0x1115, + NAP = 0x1116, + GN = 0x1117, + DirectPrinting = 0x1118, + ReferencePrinting = 0x1119, + ImagingResponder = 0x111b, + ImagingAutomaticArchive = 0x111c, + Handsfree = 0x111d, + HandsfreeAudioGateway = 0x111f, + DirectPrintingReferenceObjectsService = 0x1120, + ReflectedUI = 0x1121, + BasicPrinting = 0x1122, + PrintingStatus = 0x1123, + HumanInterfaceDeviceService = 0x1124, + HardcopyCableReplacement = 0x1125, + HCRPrint = 0x1126, + HCRScan = 0x1127, + SIMAccess = 0x112d, + PhonebookAccessPCE = 0x112e, + PhonebookAccessPSE = 0x112f, + PhonebookAccess = 0x1130, + HeadsetHS = 0x1131, + MessageAccessServer = 0x1132, + MessageNotificationServer = 0x1133, + MessageAccessProfile = 0x1134, + PnPInformation = 0x1135, + GenericNetworking = 0x1201, + GenericFileTransfer = 0x1202, + GenericAudio = 0x1203, + GenericTelephony = 0x1204, + VideoSource = 0x1303, + VideoSink = 0x1304, + VideoDistribution = 0x1305, + HDP = 0x1400, + HDPSource = 0x1401, + HDPSink = 0x1402 + }; + + QBluetoothUuid(); + QBluetoothUuid(ProtocolUuid uuid); + QBluetoothUuid(ServiceClassUuid uuid); + explicit QBluetoothUuid(quint16 uuid); + explicit QBluetoothUuid(quint32 uuid); + explicit QBluetoothUuid(quint128 uuid); + explicit QBluetoothUuid(const QString &uuid); + QBluetoothUuid(const QBluetoothUuid &uuid); + QBluetoothUuid(const QUuid &uuid); + ~QBluetoothUuid(); + + bool operator==(const QBluetoothUuid &other) const; + + int minimumSize() const; + + quint16 toUInt16(bool *ok = 0) const; + quint32 toUInt32(bool *ok = 0) const; + quint128 toUInt128() const; +}; + +inline QDebug operator<<(QDebug debug, const QBluetoothUuid &uuid) +{ + debug << uuid.toString(); + return debug; +} + +Q_DECLARE_METATYPE(QBluetoothUuid) + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/ql2capserver.cpp b/src/bluetooth/ql2capserver.cpp new file mode 100644 index 00000000..97676c2e --- /dev/null +++ b/src/bluetooth/ql2capserver.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ql2capserver.h" +#include "ql2capserver_p.h" +#include "qbluetoothsocket.h" + +/*! + \class QL2capServer + \brief The QL2capServer class provides an L2CAP server. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + QL2capServer is used to implement Bluetooth services over L2CAP. + + Start listening for incoming connections with listen(). The newConnection() signal is emitted + when a new connection is established. Call nextPendingConnection() to get a QBluetoothSocket + for the new connection. + + to enable other devices to find your service create a QBluetoothServiceInfo with the applicable + attributes for your service and register it with QBluetoothServiceInfo::registerService(). Call + serverPort() to get the L2CAP port number that is being used. + + \sa QBluetoothServiceInfo, QBluetoothSocket +*/ + +/*! + \fn void QL2capServer::newConnection() + + This signal is emitted when a new connection is available. + + The connected slot should call nextPendingConnection() to get a QBluetoothSocket object to send + and receive data over the connection. + + \sa nextPendingConnection(), hasPendingConnections() +*/ + +/*! + \fn void QL2capServer::close() + + Closes and resets the listening socket. +*/ + +/*! + \fn bool QL2capServer::listen(const QBluetoothAddress &address, quint16 port) + + Start listening for incoming connections to \a address on \a port. + + Returns true if the operation succeeded and the L2CAP server is listening for incoming + connections; otherwise returns false. + + \sa isListening(), newConnection() +*/ + +/*! + \fn void QL2capServer::setMaxPendingConnections(int numConnections) + + Sets the maximum number of pending connections to \a numConnections. + + \sa maxPendingConnections() +*/ + +/*! + \fn bool QL2capServer::hasPendingConnections() const + + Returns true if a connection is pending; otherwise returns false. +*/ + +/*! + \fn QBluetoothSocket *QL2capServer::nextPendingConnection() + + Returns a pointer to a QBluetoothSocket for the next pending connection. It is the callers + responsibility to delete the pointer. +*/ + +/*! + \fn QBluetoothAddress QL2capServer::serverAddress() const + + Returns the server address. +*/ + +/*! + \fn quint16 QL2capServer::serverPort() const + + Returns the server's port number. +*/ + +/*! + Constructs an L2CAP server with \a parent. +*/ +QL2capServer::QL2capServer(QObject *parent) +: QObject(parent), d_ptr(new QL2capServerPrivate) +{ + d_ptr->q_ptr = this; +} + +/*! + Destorys the L2CAP server. +*/ +QL2capServer::~QL2capServer() +{ + delete d_ptr; +} + +/*! + Returns true if the L2CAP server is listening for incoming connections; otherwise returns + false. +*/ +bool QL2capServer::isListening() const +{ + Q_D(const QL2capServer); + + return d->socket->state() == QBluetoothSocket::ListeningState; +} + +/*! + Returns the maximum number of pending connections. + + \sa setMaxPendingConnections() +*/ +int QL2capServer::maxPendingConnections() const +{ + Q_D(const QL2capServer); + + return d->maxPendingConnections; +} + +/*! + \fn void QL2capServer::setSecurityFlags(QBluetooth::SecurityFlags security) + Sets the Bluetooth security flags to \a security. This function must be called prior to calling + listen(). +*/ + +/*! + \fn QBluetooth::SecurityFlags QL2capServer::securityFlags() const + + Returns the Bluetooth security flags. +*/ + +#include "moc_ql2capserver.cpp" diff --git a/src/bluetooth/ql2capserver.h b/src/bluetooth/ql2capserver.h new file mode 100644 index 00000000..23155ef3 --- /dev/null +++ b/src/bluetooth/ql2capserver.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QL2CAPSERVER_H +#define QL2CAPSERVER_H + +#include "../qtconnectivityglobal.h" + +#include <QObject> + +#include <qbluetoothaddress.h> +#include <qbluetooth.h> +#include <qbluetoothsocket.h> + +QT_BEGIN_HEADER + +class QL2capServerPrivate; +class QBluetoothSocket; + +class Q_CONNECTIVITY_EXPORT QL2capServer : public QObject +{ + Q_OBJECT + +public: + QL2capServer(QObject *parent = 0); + ~QL2capServer(); + + void close(); + + bool listen(const QBluetoothAddress &address = QBluetoothAddress(), quint16 port = 0); + bool isListening() const; + + void setMaxPendingConnections(int numConnections); + int maxPendingConnections() const; + + bool hasPendingConnections() const; + QBluetoothSocket *nextPendingConnection(); + + QBluetoothAddress serverAddress() const; + quint16 serverPort() const; + + void setSecurityFlags(QBluetooth::SecurityFlags security); + QBluetooth::SecurityFlags securityFlags() const; + +signals: + void newConnection(); + +protected: + QL2capServerPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QL2capServer) + +#ifdef QT_SYMBIAN_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_connected()) + Q_PRIVATE_SLOT(d_func(), void _q_socketError(QBluetoothSocket::SocketError err)) + Q_PRIVATE_SLOT(d_func(), void _q_disconnected()) +#endif //QT_SYMBIAN_BLUETOOTH + +#ifdef QT_BLUEZ_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_newConnection()) +#endif + +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/ql2capserver_bluez.cpp b/src/bluetooth/ql2capserver_bluez.cpp new file mode 100644 index 00000000..7f02c521 --- /dev/null +++ b/src/bluetooth/ql2capserver_bluez.cpp @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ql2capserver.h" +#include "ql2capserver_p.h" +#include "qbluetoothsocket.h" + +#include <QtCore/QSocketNotifier> + +#include <QtCore/QDebug> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/l2cap.h> + +#include <errno.h> + +static inline void convertAddress(quint64 from, quint8 (&to)[6]) +{ + to[0] = (from >> 0) & 0xff; + to[1] = (from >> 8) & 0xff; + to[2] = (from >> 16) & 0xff; + to[3] = (from >> 24) & 0xff; + to[4] = (from >> 32) & 0xff; + to[5] = (from >> 40) & 0xff; +} + +QL2capServerPrivate::QL2capServerPrivate() +: pending(false), maxPendingConnections(1), socketNotifier(0) +{ + socket = new QBluetoothSocket(QBluetoothSocket::L2capSocket); +} + +QL2capServerPrivate::~QL2capServerPrivate() +{ + qDebug() << "Deleted"; + delete socketNotifier; + + delete socket; +} + +void QL2capServerPrivate::_q_newConnection() +{ + // disable socket notifier until application calls nextPendingConnection(). + socketNotifier->setEnabled(false); + + emit q_ptr->newConnection(); +} + +void QL2capServer::close() +{ + Q_D(QL2capServer); + + d->socket->close(); +} + +bool QL2capServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_D(QL2capServer); + + int sock = d->socket->socketDescriptor(); + if (sock < 0) + return false; + + sockaddr_l2 addr; + + memset(&addr, 0, sizeof(sockaddr_l2)); + addr.l2_family = AF_BLUETOOTH; + addr.l2_psm = port; + + if (!address.isNull()) + convertAddress(address.toUInt64(), addr.l2_bdaddr.b); + else + convertAddress(Q_UINT64_C(0), addr.l2_bdaddr.b); + + if (::bind(sock, reinterpret_cast<sockaddr *>(&addr), sizeof(sockaddr_l2)) < 0) + return false; + + if (::listen(sock, d->maxPendingConnections) < 0) + return false; + + d->socket->setSocketState(QBluetoothSocket::ListeningState); + + delete d->socketNotifier; + + d->socketNotifier = new QSocketNotifier(d->socket->socketDescriptor(), + QSocketNotifier::Read); + connect(d->socketNotifier, SIGNAL(activated(int)), this, SLOT(_q_newConnection())); + + return true; +} + +void QL2capServer::setMaxPendingConnections(int numConnections) +{ + Q_D(QL2capServer); + + if (d->socket->state() == QBluetoothSocket::UnconnectedState) + d->maxPendingConnections = numConnections; +} + +bool QL2capServer::hasPendingConnections() const +{ + Q_D(const QL2capServer); + + if (!d || !d->socketNotifier) + return false; + + // if the socket notifier is disable there is a pending connection waiting for us to accept. + return !d->socketNotifier->isEnabled(); +} + +QBluetoothSocket *QL2capServer::nextPendingConnection() +{ + Q_D(QL2capServer); + + if (!hasPendingConnections()) + return 0; + + sockaddr_l2 addr; + socklen_t length = sizeof(sockaddr_l2); + + int pending = ::accept(d->socket->socketDescriptor(), + reinterpret_cast<sockaddr *>(&addr), &length); + if (pending >= 0) { + QBluetoothSocket *newSocket = new QBluetoothSocket; + newSocket->setSocketDescriptor(pending, QBluetoothSocket::L2capSocket); + + d->socketNotifier->setEnabled(true); + + return newSocket; + } else { +// qDebug() << "Hmm, could have sworn there was a connection waiting to be accepted!" << errno; + d->socketNotifier->setEnabled(true); + } + + return 0; +} + +QBluetoothAddress QL2capServer::serverAddress() const +{ + Q_D(const QL2capServer); + + return d->socket->localAddress(); +} + +quint16 QL2capServer::serverPort() const +{ + Q_D(const QL2capServer); + + return d->socket->localPort(); +} + +void QL2capServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_D(QL2capServer); + + int lm = 0; + if(security == QBluetooth::NoSecurity){ + lm = 0; + } + if(security.testFlag(QBluetooth::Authorization)){ + lm |= L2CAP_LM_AUTH; + } + if(security.testFlag(QBluetooth::Authentication)){ + lm |= L2CAP_LM_TRUSTED; + } + if(security.testFlag(QBluetooth::Encryption)){ + lm |= L2CAP_LM_ENCRYPT; + } + if(security.testFlag(QBluetooth::Secure)){ + lm |= L2CAP_LM_SECURE; + } + + if(setsockopt(d->socket->socketDescriptor(), SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm)) < 0){ + qWarning() << "Failed to set socket option, closing socket for safety" << errno; + qWarning() << "Error: " << strerror(errno); + d->socket->close(); + } +} + +QBluetooth::SecurityFlags QL2capServer::securityFlags() const +{ + Q_D(const QL2capServer); + + int lm = 0; + int len = sizeof(lm); + int security = QBluetooth::NoSecurity; + + if(getsockopt(d->socket->socketDescriptor(), SOL_L2CAP, L2CAP_LM, &lm, (socklen_t *)&len) < 0) { + qWarning() << "Failed to get security flags" << strerror(errno); + return QBluetooth::NoSecurity; + } + + if(lm & L2CAP_LM_SECURE) + security |= QBluetooth::Secure; + + if(lm & L2CAP_LM_ENCRYPT) + security |= QBluetooth::Encryption; + + if(lm & L2CAP_LM_TRUSTED) + security |= QBluetooth::Authentication; + + if(lm & L2CAP_LM_AUTH) + security |= QBluetooth::Authorization; + + return static_cast<QBluetooth::SecurityFlags>(security); +} + diff --git a/src/bluetooth/ql2capserver_p.cpp b/src/bluetooth/ql2capserver_p.cpp new file mode 100644 index 00000000..0a284ced --- /dev/null +++ b/src/bluetooth/ql2capserver_p.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ql2capserver.h" +#include "ql2capserver_p.h" +#include "qbluetoothsocket.h" + +QL2capServerPrivate::QL2capServerPrivate() +{ +} + +QL2capServerPrivate::~QL2capServerPrivate() +{ +} + +void QL2capServer::close() +{ +} + +bool QL2capServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_UNUSED(address); + Q_UNUSED(port); + + return false; +} + +void QL2capServer::setMaxPendingConnections(int numConnections) +{ + Q_UNUSED(numConnections); +} + +bool QL2capServer::hasPendingConnections() const +{ + return false; +} + +QBluetoothSocket *QL2capServer::nextPendingConnection() +{ + return 0; +} + +QBluetoothAddress QL2capServer::serverAddress() const +{ + return QBluetoothAddress(); +} + +quint16 QL2capServer::serverPort() const +{ + return 0; +} + +void QL2capServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ +} + +QBluetooth::SecurityFlags QL2capServer::securityFlags() const +{ + return QBluetooth::NoSecurity; +} + + + +#ifdef QT_BLUEZ_BLUETOOTH +void QL2capServerPrivate::_q_newConnection() +{ +} +#endif diff --git a/src/bluetooth/ql2capserver_p.h b/src/bluetooth/ql2capserver_p.h new file mode 100644 index 00000000..b8f056d8 --- /dev/null +++ b/src/bluetooth/ql2capserver_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QL2CAPSERVER_P_H +#define QL2CAPSERVER_P_H + +#include "../qtconnectivityglobal.h" +#include <qbluetoothsocket.h> + +#ifdef QT_SYMBIAN_BLUETOOTH +#include <es_sock.h> +#include <bt_sock.h> +#endif //QT_SYMBIAN_BLUETOOTH + +#ifdef QT_BLUEZ_BLUETOOTH +QT_FORWARD_DECLARE_CLASS(QSocketNotifier) +#endif + +QT_BEGIN_HEADER + +class QBluetoothAddress; +class QBluetoothSocket; + +#ifdef QT_SYMBIAN_BLUETOOTH +class QBluetoothSocketPrivate; +#endif + +class QL2capServer; + +class QL2capServerPrivate +{ + Q_DECLARE_PUBLIC(QL2capServer) + +public: + QL2capServerPrivate(); + ~QL2capServerPrivate(); + +#ifdef QT_SYMBIAN_BLUETOOTH + // private slots + void _q_connected(); + void _q_socketError(QBluetoothSocket::SocketError err); + void _q_disconnected(); +#endif //QT_SYMBIAN_BLUETOOTH + +#ifdef QT_BLUEZ_BLUETOOTH + void _q_newConnection(); +#endif + + +public: + QBluetoothSocket *socket; + bool pending; + + int maxPendingConnections; + QBluetooth::SecurityFlags securityFlags; + +#ifdef QT_SYMBIAN_BLUETOOTH + mutable QList<QBluetoothSocket *> activeSockets; + QBluetoothSocketPrivate *ds; +#endif //QT_SYMBIAN_BLUETOOTH + +protected: + QL2capServer *q_ptr; + +private: +#ifdef QT_BLUEZ_BLUETOOTH + QSocketNotifier *socketNotifier; +#endif +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/ql2capserver_symbian.cpp b/src/bluetooth/ql2capserver_symbian.cpp new file mode 100644 index 00000000..1b35740b --- /dev/null +++ b/src/bluetooth/ql2capserver_symbian.cpp @@ -0,0 +1,285 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ql2capserver.h" +#include "ql2capserver_p.h" +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_p.h" +#include "symbian/utils_symbian_p.h" + +#include <QTimer> +#include <QCoreApplication> + +#include <QDebug> + +QL2capServerPrivate::QL2capServerPrivate() +: socket(0),pending(false),maxPendingConnections(1),securityFlags(QBluetooth::NoSecurity) +{ +} + +QL2capServerPrivate::~QL2capServerPrivate() +{ + delete socket; +} + +void QL2capServer::close() +{ + Q_D(QL2capServer); + if(!d->socket) + { + // there is no way to propagate the error to user + // so just ignore the problem. + return; + } + d->socket->setSocketState(QBluetoothSocket::ClosingState); + d->socket->close(); + // force active object (socket) to run and shutdown socket. + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); +} + +bool QL2capServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_D(QL2capServer); + // listen has already been called before + if(d->socket) + return true; + + d->socket = new QBluetoothSocket(QBluetoothSocket::L2capSocket,this); + + if(!d->socket) + { + return false; + } + + d->ds = d->socket->d_ptr; + + if(!d->ds) + { + delete d->socket; + d->socket = 0; + return false; + } + + TL2CAPSockAddr addr; + + if(!address.isNull()) + { + // TBTDevAddr constructor may panic + TRAPD(err,addr.SetBTAddr(TBTDevAddr(address.toUInt64()))); + if(err != KErrNone) + { + delete d->socket; + d->socket = 0; + return false; + } + } + + if (port == 0) + addr.SetPort(KL2CAPPassiveAutoBind); + else + addr.SetPort(port); + + TBTServiceSecurity security; + switch (d->securityFlags) { + case QBluetooth::Authentication: + security.SetAuthentication(EMitmDesired); + break; + case QBluetooth::Authorization: + security.SetAuthorisation(ETrue); + break; + case QBluetooth::Encryption: + // "Secure" is BlueZ specific we just make sure the code remain compatible + case QBluetooth::Secure: + // authentication required + security.SetAuthentication(EMitmDesired); + security.SetEncryption(ETrue); + break; + case QBluetooth::NoSecurity: + default: + break; + } + addr.SetSecurity(security); + if(d->ds->iSocket->Bind(addr) == KErrNone) + { + d->socket->setSocketState(QBluetoothSocket::BoundState); + } + else + { + delete d->socket; + d->socket = 0; + return false; + } + + if(d->ds->iSocket->Listen(d->maxPendingConnections) != KErrNone) + { + delete d->socket; + d->socket = 0; + return false; + } + // unknown socket type is used for blank socket + QBluetoothSocket *pendingSocket = new QBluetoothSocket(QBluetoothSocket::UnknownSocketType, this); + if(!pendingSocket) + { + delete d->socket; + d->socket = 0; + return false; + } + QBluetoothSocketPrivate *pd = pendingSocket->d_ptr; + pd->ensureBlankNativeSocket(QBluetoothSocket::L2capSocket); + connect(d->socket, SIGNAL(disconnected()), this, SLOT(disconnected())); + connect(d->socket, SIGNAL(connected()), this, SLOT(connected())); + connect(d->socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socketError(QBluetoothSocket::SocketError))); + if (d->ds->iSocket->Accept(*pd->iSocket) == KErrNone) + { + d->socket->setSocketState(QBluetoothSocket::ListeningState); + d->activeSockets.append(pendingSocket); + return true; + } + else + { + delete d->socket, pendingSocket; + d->socket = 0; + return false; + } +} + +void QL2capServer::setMaxPendingConnections(int numConnections) +{ + Q_D(QL2capServer); + d->maxPendingConnections = numConnections; +} + +bool QL2capServer::hasPendingConnections() const +{ + Q_D(const QL2capServer); + return !d->activeSockets.isEmpty(); +} + +QBluetoothSocket *QL2capServer::nextPendingConnection() +{ + Q_D(QL2capServer); + + if (d->activeSockets.isEmpty()) + return 0; + + QBluetoothSocket *next = d->activeSockets.takeFirst(); + return next; +} + +QBluetoothAddress QL2capServer::serverAddress() const +{ + Q_D(const QL2capServer); + if(d->socket) + return d->socket->localAddress(); + else + return QBluetoothAddress(); +} + +quint16 QL2capServer::serverPort() const +{ + Q_D(const QL2capServer); + if(d->socket) + return d->socket->localPort(); + else + return 0; +} + +void QL2capServerPrivate::_q_connected() +{ + Q_Q(QL2capServer); + if(!activeSockets.isEmpty()) + { + // update state of the pending socket and start receiving + (activeSockets.last())->setSocketState(QBluetoothSocket::ConnectedState); + (activeSockets.last())->d_ptr->startReceive(); + } + else + return; + emit q->newConnection(); + QBluetoothSocket *pendingSocket = new QBluetoothSocket(QBluetoothSocket::UnknownSocketType); + if(!pendingSocket) + { + delete socket; + socket = 0; + return; + } + QBluetoothSocketPrivate *pd = pendingSocket->d_ptr; + pd->ensureBlankNativeSocket(QBluetoothSocket::L2capSocket); + if (ds->iSocket->Accept(*pd->iSocket) == KErrNone) + { + socket->setSocketState(QBluetoothSocket::ListeningState); + activeSockets.append(pendingSocket); + return; + } + else + { + // we might reach this statement if we have reach + // maxPendingConnections + qDebug() << "QL2capServer::connected accept failed"; + delete socket, pendingSocket; + socket = 0; + return; + } +} + +void QL2capServerPrivate::_q_disconnected() +{ + delete socket; + socket = 0; +} + +void QL2capServerPrivate::_q_socketError(QBluetoothSocket::SocketError err) +{ + delete socket; + socket = 0; +} + +void QL2capServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_D(QL2capServer); + d->securityFlags = security; +} + +QBluetooth::SecurityFlags QL2capServer::securityFlags() const +{ + Q_D(const QL2capServer); + return d->securityFlags; +} diff --git a/src/bluetooth/ql2capsocket.cpp b/src/bluetooth/ql2capsocket.cpp new file mode 100644 index 00000000..dda5af05 --- /dev/null +++ b/src/bluetooth/ql2capsocket.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ql2capsocket.h" + +QL2capSocket::QL2capSocket(QObject *parent) +: QBluetoothSocket(parent) +{ +} + +#include "moc_ql2capsocket.cpp" diff --git a/src/bluetooth/ql2capsocket.h b/src/bluetooth/ql2capsocket.h new file mode 100644 index 00000000..cf63b62e --- /dev/null +++ b/src/bluetooth/ql2capsocket.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QL2CAPSOCKET_H +#define QL2CAPSOCKET_H + +#include <qbluetoothsocket.h> +#include <qbluetoothaddress.h> + +#include <QtCore/QObject> + +QT_BEGIN_HEADER + +class QL2capSocket : public QBluetoothSocket +{ + Q_OBJECT + +public: + explicit QL2capSocket(QObject *parent = 0); + + bool hasPendingDatagrams() const; + qint64 pendingDatagramSize() const; + qint64 readDatagram(char *data, qint64 maxlen, QBluetoothAddress *host = 0, quint16 *port = 0); + qint64 writeDatagram(const char *data, qint64 len, const QBluetoothAddress &host, + quint16 port); + inline qint64 writeDatagram(const QByteArray &datagram, const QBluetoothAddress &host, + quint16 port) + { return writeDatagram(datagram.constData(), datagram.size(), host, port); } + +private: + Q_DISABLE_COPY(QL2capSocket) +}; + +QT_END_HEADER + +#endif // QL2CAPSOCKET_H diff --git a/src/bluetooth/qrfcommserver.cpp b/src/bluetooth/qrfcommserver.cpp new file mode 100644 index 00000000..cc3e4e35 --- /dev/null +++ b/src/bluetooth/qrfcommserver.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qrfcommserver.h" +#include "qrfcommserver_p.h" +#include "qbluetoothsocket.h" + +/*! + \class QRfcommServer + \brief The QRfcommServer class provides an RFCOMM server. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \since 5.0 + + QRfcommServer is used to implement Bluetooth services over RFCOMM. + + Start listening for incoming connections with listen(). The newConnection() signal is emitted + when a new connection is established. Call nextPendingConnection() to get a QBluetoothSocket + for the new connection. + + To enable other devices to find your service create a QBluetoothServiceInfo with the + applicable attributes for your service and register it with + QBluetoothServiceInfo::registerService(). Call serverPort() to get the RFCOMM channel number + that is being used. + + \sa QBluetoothServiceInfo, QBluetoothSocket +*/ + +/*! + \fn void QRfcommServer::newConnection() + + This signal is emitted when a new connection is available. + + The connected slot should call nextPendingConnection() to get a QBluetoothSocket object to + send and receive data over the connection. + + \sa nextPendingConnection(), hasPendingConnections() +*/ + +/*! + \fn void QRfcommServer::close() + + Closes and resets the listening socket. +*/ + +/*! + \fn bool QRfcommServer::listen(const QBluetoothAddress &address, quint16 port) + + Start listening for incoming connections to \a address on \a port. + + Returns true if the operation succeeded and the RFCOMM server is listening for + incoming connections; otherwise returns false. + + \sa isListening(), newConnection() +*/ + +/*! + \fn void QRfcommServer::setMaxPendingConnections(int numConnections) + + Sets the maximum number of pending connections to \a numConnections. + + \sa maxPendingConnections() +*/ + +/*! + \fn bool QRfcommServer::hasPendingConnections() const + Returns true if a connection is pending; otherwise returns false. +*/ + +/*! + \fn QBluetoothSocket *QRfcommServer::nextPendingConnection() + + Returns a pointer QBluetoothSocket for the next pending connection. It is the callers + responsibility to delete pointer. +*/ + +/*! + \fn QBluetoothAddress QRfcommServer::serverAddress() const + + Returns the server address. +*/ + +/*! + \fn quint16 QRfcommServer::serverPort() const + + Returns the server's port number. +*/ + +/*! + Constructs an RFCOMM server with \a parent. +*/ +QRfcommServer::QRfcommServer(QObject *parent) + : QObject(parent), d_ptr(new QRfcommServerPrivate) +{ + d_ptr->q_ptr = this; +} + +/*! + Destroys the RFCOMM server. +*/ +QRfcommServer::~QRfcommServer() +{ + delete d_ptr; +} + +/*! + Returns true if the RFCOMM server is listening for incoming connections; otherwise returns + false. +*/ +bool QRfcommServer::isListening() const +{ + Q_D(const QRfcommServer); + + return d->socket->state() == QBluetoothSocket::ListeningState; +} + +/*! + Returns the maximum number of pending connections. + + \sa setMaxPendingConnections() +*/ +int QRfcommServer::maxPendingConnections() const +{ + Q_D(const QRfcommServer); + + return d->maxPendingConnections; +} + +/*! + \fn QRfcommServer::setSecurityFlags(QBluetooth::SecurityFlags security) + Sets the Bluetooth security flags to \a security. This function must be called prior to calling + listen(). +*/ + +/*! + \fn QBluetooth::SecurityFlags QRfcommServer::securityFlags() const + Returns the Bluetooth security flags. +*/ + +#include "moc_qrfcommserver.cpp" diff --git a/src/bluetooth/qrfcommserver.h b/src/bluetooth/qrfcommserver.h new file mode 100644 index 00000000..87676649 --- /dev/null +++ b/src/bluetooth/qrfcommserver.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRFCOMMSERVER_H +#define QRFCOMMSERVER_H + +#include "../qtconnectivityglobal.h" + +#include <QObject> + +#include <qbluetoothaddress.h> +#include <qbluetooth.h> +#include <qbluetoothsocket.h> + +QT_BEGIN_HEADER + +class QRfcommServerPrivate; +class QBluetoothSocket; + +class Q_CONNECTIVITY_EXPORT QRfcommServer : public QObject +{ + Q_OBJECT + +public: + QRfcommServer(QObject *parent = 0); + ~QRfcommServer(); + + void close(); + + bool listen(const QBluetoothAddress &address = QBluetoothAddress(), quint16 port = 0); + bool isListening() const; + + void setMaxPendingConnections(int numConnections); + int maxPendingConnections() const; + + bool hasPendingConnections() const; + QBluetoothSocket *nextPendingConnection(); + + QBluetoothAddress serverAddress() const; + quint16 serverPort() const; + + void setSecurityFlags(QBluetooth::SecurityFlags security); + QBluetooth::SecurityFlags securityFlags() const; + +signals: + void newConnection(); + +protected: + QRfcommServerPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QRfcommServer) + +#ifdef QT_SYMBIAN_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_connected()) + Q_PRIVATE_SLOT(d_func(), void _q_socketError(QBluetoothSocket::SocketError err)) + Q_PRIVATE_SLOT(d_func(), void _q_disconnected()) +#endif //QT_SYMBIAN_BLUETOOTH + +#ifdef QT_BLUEZ_BLUETOOTH + Q_PRIVATE_SLOT(d_func(), void _q_newConnection()) +#endif +}; + + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qrfcommserver_bluez.cpp b/src/bluetooth/qrfcommserver_bluez.cpp new file mode 100644 index 00000000..0f5dff02 --- /dev/null +++ b/src/bluetooth/qrfcommserver_bluez.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qrfcommserver.h" +#include "qrfcommserver_p.h" +#include "qbluetoothsocket.h" + +#include <QtCore/QSocketNotifier> + +#include <QtCore/QDebug> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/rfcomm.h> + +#include <errno.h> + +static inline void convertAddress(quint64 from, quint8 (&to)[6]) +{ + to[0] = (from >> 0) & 0xff; + to[1] = (from >> 8) & 0xff; + to[2] = (from >> 16) & 0xff; + to[3] = (from >> 24) & 0xff; + to[4] = (from >> 32) & 0xff; + to[5] = (from >> 40) & 0xff; +} + +QRfcommServerPrivate::QRfcommServerPrivate() +: maxPendingConnections(1), socketNotifier(0) +{ + socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket); +} + +QRfcommServerPrivate::~QRfcommServerPrivate() +{ + delete socketNotifier; + + delete socket; +} + +void QRfcommServerPrivate::_q_newConnection() +{ + // disable socket notifier until application calls nextPendingConnection(). + socketNotifier->setEnabled(false); + + emit q_ptr->newConnection(); +} + +void QRfcommServer::close() +{ + Q_D(QRfcommServer); + + delete d->socketNotifier; + d->socketNotifier = 0; + + d->socket->close(); +} + +bool QRfcommServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_D(QRfcommServer); + + int sock = d->socket->socketDescriptor(); + if (sock < 0) + return false; + + sockaddr_rc addr; + + addr.rc_family = AF_BLUETOOTH; + addr.rc_channel = port; + + if (!address.isNull()) + convertAddress(address.toUInt64(), addr.rc_bdaddr.b); + else + convertAddress(Q_UINT64_C(0), addr.rc_bdaddr.b); + + if (::bind(sock, reinterpret_cast<sockaddr *>(&addr), sizeof(sockaddr_rc)) < 0) + return false; + + if (::listen(sock, d->maxPendingConnections) < 0) + return false; + + d->socket->setSocketState(QBluetoothSocket::ListeningState); + + if (!d->socketNotifier) { + d->socketNotifier = new QSocketNotifier(d->socket->socketDescriptor(), + QSocketNotifier::Read); + connect(d->socketNotifier, SIGNAL(activated(int)), this, SLOT(_q_newConnection())); + } + + return true; +} + +void QRfcommServer::setMaxPendingConnections(int numConnections) +{ + Q_D(QRfcommServer); + + if (d->socket->state() == QBluetoothSocket::UnconnectedState) + d->maxPendingConnections = numConnections; +} + +bool QRfcommServer::hasPendingConnections() const +{ + Q_D(const QRfcommServer); + + if (!d || !d->socketNotifier) + return false; + + // if the socket notifier is disable there is a pending connection waiting for us to accept. + return !d->socketNotifier->isEnabled(); +} + +QBluetoothSocket *QRfcommServer::nextPendingConnection() +{ + Q_D(QRfcommServer); + + if (!hasPendingConnections()) + return 0; + + sockaddr_rc addr; + socklen_t length = sizeof(sockaddr_rc); + + int pending = ::accept(d->socket->socketDescriptor(), + reinterpret_cast<sockaddr *>(&addr), &length); + if (pending >= 0) { + QBluetoothSocket *newSocket = new QBluetoothSocket; + newSocket->setSocketDescriptor(pending, QBluetoothSocket::RfcommSocket); + + d->socketNotifier->setEnabled(true); + + return newSocket; + } else { + qDebug() << "Hmm, could have sworn there was a connection waiting to be accepted!"; + d->socketNotifier->setEnabled(true); + } + + return 0; +} + +QBluetoothAddress QRfcommServer::serverAddress() const +{ + Q_D(const QRfcommServer); + + return d->socket->localAddress(); +} + +quint16 QRfcommServer::serverPort() const +{ + Q_D(const QRfcommServer); + + return d->socket->localPort(); +} + +void QRfcommServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_D(QRfcommServer); + + int lm = 0; + if(security == QBluetooth::NoSecurity){ + lm = 0; + } + if(security.testFlag(QBluetooth::Authorization)){ + lm |= RFCOMM_LM_AUTH; + } + if(security.testFlag(QBluetooth::Authentication)) { + lm |= RFCOMM_LM_TRUSTED; + } + if(security.testFlag(QBluetooth::Encryption)){ + lm |= RFCOMM_LM_ENCRYPT; + } + if(security.testFlag(QBluetooth::Secure)){ + lm |= RFCOMM_LM_SECURE; + } + + qDebug() << hex << "Setting lm to" << lm << security; + + if(setsockopt(d->socket->socketDescriptor(), SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0){ + qWarning() << "Failed to set socket option, closing socket for safety" << errno; + qWarning() << "Error: " << strerror(errno); + d->socket->close(); + } +} + +QBluetooth::SecurityFlags QRfcommServer::securityFlags() const +{ + Q_D(const QRfcommServer); + + int lm = 0; + int len = sizeof(lm); + int security = QBluetooth::NoSecurity; + + if(getsockopt(d->socket->socketDescriptor(), SOL_RFCOMM, RFCOMM_LM, &lm, (socklen_t *)&len) < 0) { + qWarning() << "Failed to get security flags" << strerror(errno); + return QBluetooth::NoSecurity; + } + + if(lm & RFCOMM_LM_SECURE) + security |= QBluetooth::Secure; + + if(lm & RFCOMM_LM_ENCRYPT) + security |= QBluetooth::Encryption; + + if(lm & RFCOMM_LM_TRUSTED) + security |= QBluetooth::Authentication; + + if(lm & RFCOMM_LM_AUTH) + security |= QBluetooth::Authorization; + + return static_cast<QBluetooth::Security>(security); +} + diff --git a/src/bluetooth/qrfcommserver_p.cpp b/src/bluetooth/qrfcommserver_p.cpp new file mode 100644 index 00000000..6b7d1aab --- /dev/null +++ b/src/bluetooth/qrfcommserver_p.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qrfcommserver.h" +#include "qrfcommserver_p.h" +#include "qbluetoothsocket.h" + +QRfcommServerPrivate::QRfcommServerPrivate() +{ +} + +QRfcommServerPrivate::~QRfcommServerPrivate() +{ +} + +void QRfcommServer::close() +{ +} + +bool QRfcommServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_UNUSED(address); + Q_UNUSED(port); + return false; +} + +void QRfcommServer::setMaxPendingConnections(int numConnections) +{ + Q_UNUSED(numConnections); +} + +bool QRfcommServer::hasPendingConnections() const +{ + return false; +} + +QBluetoothSocket *QRfcommServer::nextPendingConnection() +{ + return 0; +} + +QBluetoothAddress QRfcommServer::serverAddress() const +{ + return QBluetoothAddress(); +} + +quint16 QRfcommServer::serverPort() const +{ + return 0; +} + + +#ifdef QT_BLUEZ_BLUETOOTH +void QRfcommServerPrivate::_q_newConnection() +{ +} +#endif + + +#ifdef QT_SYMBIAN_BLUETOOTH +void QRfcommServerPrivate::HandleAcceptCompleteL(TInt aErr) +{ +} +void QRfcommServerPrivate::HandleActivateBasebandEventNotifierCompleteL(TInt aErr, TBTBasebandEventNotification &aEventNotification) +{ +} +void QRfcommServerPrivate::HandleConnectCompleteL(TInt aErr) +{ +} +void QRfcommServerPrivate::HandleIoctlCompleteL(TInt aErr) +{ +} +void QRfcommServerPrivate::HandleReceiveCompleteL(TInt aErr) +{ +} +void QRfcommServerPrivate::HandleSendCompleteL(TInt aErr) +{ +} +void QRfcommServerPrivate::HandleShutdownCompleteL(TInt aErr) +{ +} +#endif + +void QRfcommServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ +} + +QBluetooth::SecurityFlags QRfcommServer::securityFlags() const +{ + return QBluetooth::NoSecurity; +} + diff --git a/src/bluetooth/qrfcommserver_p.h b/src/bluetooth/qrfcommserver_p.h new file mode 100644 index 00000000..a4ea301e --- /dev/null +++ b/src/bluetooth/qrfcommserver_p.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRFCOMMSERVER_P_H +#define QRFCOMMSERVER_P_H + +#include <QtGlobal> +#include <QList> +#include <qbluetoothsocket.h> + +#ifdef QT_SYMBIAN_BLUETOOTH +#include <es_sock.h> +#include <bt_sock.h> +#endif + +#ifdef QT_BLUEZ_BLUETOOTH +QT_FORWARD_DECLARE_CLASS(QSocketNotifier) +#endif + +QT_BEGIN_HEADER + +class QBluetoothAddress; +class QBluetoothSocket; + +#ifdef QT_SYMBIAN_BLUETOOTH +class QBluetoothSocketPrivate; +#endif + +class QRfcommServer; + +class QRfcommServerPrivate +{ + Q_DECLARE_PUBLIC(QRfcommServer) + +public: + QRfcommServerPrivate(); + ~QRfcommServerPrivate(); + +#ifdef QT_SYMBIAN_BLUETOOTH + // private slots + void _q_connected(); + void _q_socketError(QBluetoothSocket::SocketError err); + void _q_disconnected(); +#endif //QT_SYMBIAN_BLUETOOTH + +#ifdef QT_BLUEZ_BLUETOOTH + void _q_newConnection(); +#endif + +public: + QBluetoothSocket *socket; + +#ifdef QT_SYMBIAN_BLUETOOTH + mutable QList<QBluetoothSocket *> activeSockets; + QBluetoothSocketPrivate *ds; +#endif + + int maxPendingConnections; + QBluetooth::SecurityFlags securityFlags; + +protected: + QRfcommServer *q_ptr; + +private: +#ifdef QT_BLUEZ_BLUETOOTH + QSocketNotifier *socketNotifier; +#endif +}; + +QT_END_HEADER + +#endif diff --git a/src/bluetooth/qrfcommserver_symbian.cpp b/src/bluetooth/qrfcommserver_symbian.cpp new file mode 100644 index 00000000..0f5c4506 --- /dev/null +++ b/src/bluetooth/qrfcommserver_symbian.cpp @@ -0,0 +1,284 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qrfcommserver.h" +#include "qrfcommserver_p.h" +#include "qbluetoothsocket.h" +#include "qbluetoothsocket_p.h" +#include "qbluetoothlocaldevice.h" +#include "symbian/utils_symbian_p.h" + +#include <QTimer> +#include <QCoreApplication> + +#include <QDebug> + +QRfcommServerPrivate::QRfcommServerPrivate() +: socket(0),maxPendingConnections(1),securityFlags(QBluetooth::NoSecurity) +{ +} + +QRfcommServerPrivate::~QRfcommServerPrivate() +{ + delete socket; +} + +void QRfcommServer::close() +{ + Q_D(QRfcommServer); + if(!d->socket) + { + // there is no way to propagate the error to user + // so just ignore the problem. + return; + } + d->socket->setSocketState(QBluetoothSocket::ClosingState); + d->socket->close(); + // force active object (socket) to run and shutdown socket. + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); +} + +bool QRfcommServer::listen(const QBluetoothAddress &address, quint16 port) +{ + Q_D(QRfcommServer); + // listen has already been called before + if(d->socket) + return true; + + d->socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket,this); + + if(!d->socket) + { + return false; + } + + d->ds = d->socket->d_ptr; + + if(!d->ds) + { + delete d->socket; + d->socket = 0; + return false; + } + + d->ds->ensureNativeSocket(QBluetoothSocket::RfcommSocket); + + TRfcommSockAddr addr; + if(!address.isNull()) + { + // TBTDevAddr constructor may panic + TRAPD(err,addr.SetBTAddr(TBTDevAddr(address.toUInt64()))); + if(err != KErrNone) + { + delete d->socket; + d->socket = 0; + return false; + } + } + + if (port == 0) + addr.SetPort(KRfcommPassiveAutoBind); + else + addr.SetPort(port); + + TBTServiceSecurity security; + switch (d->securityFlags) { + case QBluetooth::Authentication: + security.SetAuthentication(EMitmDesired); + break; + case QBluetooth::Authorization: + security.SetAuthorisation(ETrue); + break; + case QBluetooth::Encryption: + // "Secure" is BlueZ specific we just make sure the code remain compatible + case QBluetooth::Secure: + // authentication required + security.SetAuthentication(EMitmDesired); + security.SetEncryption(ETrue); + break; + case QBluetooth::NoSecurity: + default: + break; + } + if(d->ds->iSocket->Bind(addr) == KErrNone) + { + d->socket->setSocketState(QBluetoothSocket::BoundState); + } + else + { + delete d->socket; + d->socket = 0; + return false; + } + + if(d->ds->iSocket->Listen(d->maxPendingConnections) != KErrNone) + { + delete d->socket; + d->socket = 0; + return false; + } + + QBluetoothSocket *pendingSocket = new QBluetoothSocket(QBluetoothSocket::UnknownSocketType, this); + if(!pendingSocket) + { + delete d->socket; + d->socket = 0; + return false; + } + QBluetoothSocketPrivate *pd = pendingSocket->d_ptr; + pd->ensureBlankNativeSocket(QBluetoothSocket::RfcommSocket); + connect(d->socket, SIGNAL(disconnected()), this, SLOT(_q_disconnected())); + connect(d->socket, SIGNAL(connected()), this, SLOT(_q_connected())); + connect(d->socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(_q_socketError(QBluetoothSocket::SocketError))); + if (d->ds->iSocket->Accept(*pd->iSocket) == KErrNone) + { + d->socket->setSocketState(QBluetoothSocket::ListeningState); + d->activeSockets.append(pendingSocket); + return true; + } + else + { + delete d->socket, pendingSocket; + d->socket = 0; + return false; + } +} + +void QRfcommServer::setMaxPendingConnections(int numConnections) +{ + Q_D(QRfcommServer); + d->maxPendingConnections = numConnections; +} + +QBluetoothAddress QRfcommServer::serverAddress() const +{ + Q_D(const QRfcommServer); + if(d->socket) + return d->socket->localAddress(); + else + return QBluetoothAddress(); +} + +quint16 QRfcommServer::serverPort() const +{ + Q_D(const QRfcommServer); + if(d->socket) + return d->socket->localPort(); + else + return 0; +} + +bool QRfcommServer::hasPendingConnections() const +{ + Q_D(const QRfcommServer); + return !d->activeSockets.isEmpty(); +} + +QBluetoothSocket *QRfcommServer::nextPendingConnection() +{ + Q_D(QRfcommServer); + if (d->activeSockets.isEmpty()) + return 0; + + QBluetoothSocket *next = d->activeSockets.takeFirst(); + return next; +} + +void QRfcommServerPrivate::_q_connected() +{ + Q_Q(QRfcommServer); + if(!activeSockets.isEmpty()) + { + // update state of the pending socket and start receiving + (activeSockets.last())->setSocketState(QBluetoothSocket::ConnectedState); + (activeSockets.last())->d_ptr->startReceive(); + } + else + return; + emit q->newConnection(); + QBluetoothSocket *pendingSocket = new QBluetoothSocket(QBluetoothSocket::UnknownSocketType); + if(!pendingSocket) + { + delete socket; + socket = 0; + return; + } + QBluetoothSocketPrivate *pd = pendingSocket->d_ptr; + pd->ensureBlankNativeSocket(QBluetoothSocket::RfcommSocket); + if (ds->iSocket->Accept(*pd->iSocket) == KErrNone) + { + socket->setSocketState(QBluetoothSocket::ListeningState); + activeSockets.append(pendingSocket); + return; + } + else + { + // we might reach this statement if we have reach + // maxPendingConnections + delete socket, pendingSocket; + socket = 0; + return; + } +} + +void QRfcommServerPrivate::_q_disconnected() +{ + delete socket; + socket = 0; +} + +void QRfcommServerPrivate::_q_socketError(QBluetoothSocket::SocketError err) +{ + delete socket; + socket = 0; +} + +void QRfcommServer::setSecurityFlags(QBluetooth::SecurityFlags security) +{ + Q_D(QRfcommServer); + d->securityFlags = security; +} + +QBluetooth::SecurityFlags QRfcommServer::securityFlags() const +{ + Q_D(const QRfcommServer); + return d->securityFlags; +} diff --git a/src/bluetooth/qrfcommsocket.cpp b/src/bluetooth/qrfcommsocket.cpp new file mode 100644 index 00000000..0c9b4ba3 --- /dev/null +++ b/src/bluetooth/qrfcommsocket.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qrfcommsocket.h" + +QRfcommSocket::QRfcommSocket(QObject *parent) +: QBluetoothSocket(parent) +{ +} + +#include "moc_qrfcommsocket.cpp" diff --git a/src/bluetooth/qrfcommsocket.h b/src/bluetooth/qrfcommsocket.h new file mode 100644 index 00000000..eaf25514 --- /dev/null +++ b/src/bluetooth/qrfcommsocket.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRFCOMMSOCKET_H +#define QRFCOMMSOCKET_H + +#include <qbluetoothsocket.h> + +QT_BEGIN_HEADER + +class QRfcommSocket : public QBluetoothSocket +{ + Q_OBJECT + +public: + explicit QRfcommSocket(QObject *parent = 0); + +private: + Q_DISABLE_COPY(QRfcommSocket) +}; + +QT_END_HEADER + +#endif // QRFCOMMSOCKET_H diff --git a/src/bluetooth/qtbluetoothversion.h b/src/bluetooth/qtbluetoothversion.h new file mode 100644 index 00000000..346b28e1 --- /dev/null +++ b/src/bluetooth/qtbluetoothversion.h @@ -0,0 +1,9 @@ +/* This file was generated by syncqt with the info from sync.profile. */ +#ifndef QT_QTBLUETOOTH_VERSION_H +#define QT_QTBLUETOOTH_VERSION_H + +#define QTBLUETOOTH_VERSION_STR "5.0.0" + +#define QTBLUETOOTH_VERSION 0x050000 + +#endif // QT_QTBLUETOOTH_VERSION_H diff --git a/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp b/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp new file mode 100644 index 00000000..96fa4245 --- /dev/null +++ b/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp @@ -0,0 +1,387 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// INCLUDE FILES +#include "bluetoothlinkmanagerdevicediscoverer.h" +#include "qbluetoothaddress.h" +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothuuid.h" + +#include <qstring.h> +#ifdef EIR_SUPPORTED +#include <arpa/inet.h> +#include <netinet/in.h> +#endif +#include "utils_symbian_p.h" +#include <qdebug.h> + +/*! \internal + \class BluetoothLinkManagerDeviceDiscoverer + \brief The BluetoothLinkManagerDeviceDiscoverer class searches other bluetooth devices. + \since 5.0 + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \internal + + BluetoothLinkManagerDeviceDiscoverer is an Symbian ActiveObject derived class that discovers + other Bluetooth devices using "BTLinkManager" protocol. + + When Bluetoothdevices are found signal deviceDiscovered(QBluetoothDeviceInfo &) is emitted. When + all devices are found (or none) signal deviceDiscoveryComplete() is emitted. + + In case of an error signal linkManagerError(int error) is emitted. In the case of errorSignal + one should consider deleting this class and creating it again. +*/ + +_LIT(KBTLinkManagerTxt,"BTLinkManager"); + +BluetoothLinkManagerDeviceDiscoverer::BluetoothLinkManagerDeviceDiscoverer(RSocketServ &socketServer,QObject *parent) + : QObject(parent) + , CActive(CActive::EPriorityStandard) + , m_socketServer(socketServer) + , m_pendingCancel(false), m_pendingStart(false), m_discoveryType (0) +{ + TInt result; + + /* find Bluetooth protocol */ + TProtocolDesc protocol; + result = m_socketServer.FindProtocol(KBTLinkManagerTxt(),protocol); + if (result == KErrNone) { + /* Create and initialise an RHostResolver */ + result = m_hostResolver.Open(m_socketServer, protocol.iAddrFamily, protocol.iProtocol); + } + // check possible error + if (result != KErrNone) { + setError(result); + } + + //add this active object to scheduler + CActiveScheduler::Add(this); +} + +BluetoothLinkManagerDeviceDiscoverer::~BluetoothLinkManagerDeviceDiscoverer() +{ + // cancel active object + Cancel(); + m_hostResolver.Close(); +} +/*! + Starts up device discovery. When devices are discovered signal deviceDiscovered is emitted. + After signal deviceDiscoveryComplete() is emitted new discovery request can be made. +*/ +void BluetoothLinkManagerDeviceDiscoverer::startDiscovery(const uint discoveryType) +{ + m_discoveryType = discoveryType; + + if(m_pendingCancel == true) { + m_pendingStart = true; + m_pendingCancel = false; + return; + } + if (!IsActive()) { + m_addr.SetIAC( discoveryType ); +#ifdef EIR_SUPPORTED + m_addr.SetAction(KHostResInquiry | KHostResName | KHostResIgnoreCache | KHostResEir); +#else + m_addr.SetAction(KHostResInquiry | KHostResName | KHostResIgnoreCache); +#endif + m_hostResolver.GetByAddress(m_addr, m_entry, iStatus); + SetActive(); + } +} + +void BluetoothLinkManagerDeviceDiscoverer::stopDiscovery() +{ + m_pendingStart = false; + if (IsActive() && !m_pendingCancel) { + m_pendingCancel = true; + m_hostResolver.Cancel(); + } +} + +/*! + Informs that our request has been prosessed and the data is available to be used. +*/ +void BluetoothLinkManagerDeviceDiscoverer::RunL() +{ + qDebug() << __PRETTY_FUNCTION__ << iStatus.Int(); + switch (iStatus.Int()) { + case KErrNone: // found device + if (m_pendingCancel && !m_pendingStart) { + m_pendingCancel = false; + emit canceled(); + } else { + m_pendingCancel = false; + m_pendingStart = false; + // get next (possible) discovered device + m_hostResolver.Next(m_entry, iStatus); + SetActive(); + emit deviceDiscovered(currentDeviceDataToQBluetoothDeviceInfo()); + } + break; + case KErrHostResNoMoreResults: // done with search + if (m_pendingCancel && !m_pendingStart){ // search was canceled prior to finishing + m_pendingCancel = false; + m_pendingStart = false; + emit canceled(); + } + else if (m_pendingStart){ // search was restarted just prior to finishing + m_pendingStart = false; + m_pendingCancel = false; + startDiscovery(m_discoveryType); + } else { // search completed normally + m_pendingStart = false; + m_pendingCancel = false; + emit deviceDiscoveryComplete(); + } + break; + case KErrCancel: // user canceled search + if (m_pendingStart){ // user activated search after cancel + m_pendingStart = false; + m_pendingCancel = false; + startDiscovery(m_discoveryType); + } else { // standard user cancel case + m_pendingCancel = false; + emit canceled(); + } + break; + default: + m_pendingStart = false; + m_pendingCancel = false; + setError(iStatus.Int()); + } +} +/*! + Cancel current request. +*/ +void BluetoothLinkManagerDeviceDiscoverer::DoCancel() +{ + m_hostResolver.Cancel(); +} + +TInt BluetoothLinkManagerDeviceDiscoverer::RunError(TInt aError) +{ + setError(aError); + return KErrNone; +} + +bool BluetoothLinkManagerDeviceDiscoverer::isReallyActive() const +{ + if(m_pendingStart) + return true; + if(m_pendingCancel) + return false; + return IsActive(); +} + +/*! + Transforms Symbian device name, address and service classes to QBluetootDeviceInfo. +*/ +QBluetoothDeviceInfo BluetoothLinkManagerDeviceDiscoverer::currentDeviceDataToQBluetoothDeviceInfo() const +{ + // extract device information from results and map them to QBluetoothDeviceInfo +#ifdef EIR_SUPPORTED + TBluetoothNameRecordWrapper eir(m_entry()); + TInt bufferlength = 0; + TInt err = KErrNone; + QString deviceName; + bufferlength = eir.GetDeviceNameLength(); + + if (bufferlength > 0) { + TBool nameComplete; + HBufC *deviceNameBuffer = 0; + TRAP(err,deviceNameBuffer = HBufC::NewL(bufferlength)); + if(err) + deviceName = QString(); + else + { + TPtr ptr = deviceNameBuffer->Des(); + err = eir.GetDeviceName(ptr,nameComplete); + if (err == KErrNone /*&& nameComplete*/) + { + if(!nameComplete) + qWarning() << "device name incomplete"; + // isn't it better to get an incomplete name than getting nothing? + deviceName = QString::fromUtf16(ptr.Ptr(), ptr.Length()).toUpper(); + } + else + deviceName = QString(); + delete deviceNameBuffer; + } + } + + QList<QBluetoothUuid> serviceUidList; + RExtendedInquiryResponseUUIDContainer uuidContainer; + QBluetoothDeviceInfo::DataCompleteness completenes = QBluetoothDeviceInfo::DataUnavailable; + + if (eir.GetServiceClassUuids(uuidContainer) == KErrNone) { + TInt uuidCount = uuidContainer.UUIDs().Count(); + if (uuidCount > 0) { + for (int i = 0; i < uuidCount; ++i) { + TPtrC8 shortFormUUid(uuidContainer.UUIDs()[i].ShortestForm()); + if (shortFormUUid.Size() == 2) { + QBluetoothUuid uuid(ntohs(*reinterpret_cast<const quint16 *>(shortFormUUid.Ptr()))); + if (uuidContainer.GetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID16)) + completenes = QBluetoothDeviceInfo::DataComplete; + else + completenes = QBluetoothDeviceInfo::DataIncomplete; + serviceUidList.append(uuid); + }else if (shortFormUUid.Size() == 4) { + QBluetoothUuid uuid(ntohl(*reinterpret_cast<const quint32 *>(shortFormUUid.Ptr()))); + if (uuidContainer.GetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID32)) + completenes = QBluetoothDeviceInfo::DataComplete; + else + completenes = QBluetoothDeviceInfo::DataIncomplete; + serviceUidList.append(uuid); + }else if (shortFormUUid.Size() == 16) { + QBluetoothUuid uuid(*reinterpret_cast<const quint128 *>(shortFormUUid.Ptr())); + if (uuidContainer.GetCompleteness(RExtendedInquiryResponseUUIDContainer::EUUID128)) + completenes = QBluetoothDeviceInfo::DataComplete; + else + completenes = QBluetoothDeviceInfo::DataIncomplete; + serviceUidList.append(uuid); + } + } + } + } + uuidContainer.Close(); + + bufferlength = 0; + QByteArray manufacturerData; + bufferlength = eir.GetVendorSpecificDataLength(); + + if (bufferlength > 0) { + HBufC8 *msd = 0; + TRAP(err,msd = HBufC8::NewL(bufferlength)); + if(err) + manufacturerData = QByteArray(); + else + { + TPtr8 temp = msd->Des(); + if (eir.GetVendorSpecificData(temp)) + manufacturerData = s60Desc8ToQByteArray(temp); + else + manufacturerData = QByteArray(); + delete msd; + } + } + + // Get transmission power level + TInt8 transmissionPowerLevel = 0; + eir.GetTxPowerLevel(transmissionPowerLevel); + + // unique address of the device + const TBTDevAddr symbianDeviceAddress = static_cast<TBTSockAddr> (m_entry().iAddr).BTAddr(); + QBluetoothAddress bluetoothAddress = qTBTDevAddrToQBluetoothAddress(symbianDeviceAddress); + + // format symbian major/minor numbers + quint32 deviceClass = qTPackSymbianDeviceClass(m_addr); + + QBluetoothDeviceInfo deviceInfo(bluetoothAddress, deviceName, deviceClass); + + deviceInfo.setRssi(transmissionPowerLevel); + deviceInfo.setServiceUuids(serviceUidList, completenes); + deviceInfo.setManufacturerSpecificData(manufacturerData); +#else + // device name + THostName symbianDeviceName = m_entry().iName; + QString deviceName = QString::fromUtf16(symbianDeviceName.Ptr(), symbianDeviceName.Length()).toUpper(); + + // unique address of the device + const TBTDevAddr symbianDeviceAddress = static_cast<TBTSockAddr> (m_entry().iAddr).BTAddr(); + QBluetoothAddress bluetoothAddress = qTBTDevAddrToQBluetoothAddress(symbianDeviceAddress); + + // format symbian major/minor numbers + quint32 deviceClass = qTPackSymbianDeviceClass(m_addr); + + QBluetoothDeviceInfo deviceInfo(bluetoothAddress, deviceName, deviceClass); + + if (m_addr.Rssi()) + deviceInfo.setRssi(m_addr.Rssi()); +#endif + if (!deviceInfo.rssi()) + deviceInfo.setRssi(1); + + deviceInfo.setCached(false); //TODO cache support missing from devicediscovery API + //qDebug()<< "Discovered device: name="<< deviceName <<", address=" << bluetoothAddress.toString() <<", class=" << deviceClass; + return deviceInfo; +} + +void BluetoothLinkManagerDeviceDiscoverer::setError(int errorCode) +{ + qDebug() << __PRETTY_FUNCTION__ << "errorCode=" << errorCode; + QString errorString; + switch (errorCode) { + case KLinkManagerErrBase: + errorString.append("Link manager base error value or Insufficient baseband resources error value"); + emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString); + break; + case KErrProxyWriteNotAvailable: + errorString.append("Proxy write not available error value"); + emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString); + break; + case KErrReflexiveBluetoothLink: + errorString.append("Reflexive BT link error value"); + emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString); + break; + case KErrPendingPhysicalLink: + errorString.append("Physical link connection already pending when trying to connect the physical link"); + emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString); + break; + case KErrNotReady: + errorString.append("KErrNotReady"); + emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString); + case KErrCancel: + errorString.append("KErrCancel"); + qDebug() << "emitting canceled"; + emit canceled(); + break; + case KErrNone: + // do nothing + break; + default: + errorString = QString("Symbian errorCode = %1").arg(errorCode); + emit linkManagerError(QBluetoothDeviceDiscoveryAgent::UnknownError, errorString); + break; + } +} +#include "moc_bluetoothlinkmanagerdevicediscoverer.cpp" diff --git a/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.h b/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.h new file mode 100644 index 00000000..328222c9 --- /dev/null +++ b/src/bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLUETOOTHLINKMANAGERDEVICEDISCOVERER_H +#define BLUETOOTHLINKMANAGERDEVICEDISCOVERER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qconnectivityglobal.h> +#include <QtCore/QObject> +#include "qbluetoothdevicediscoveryagent.h" + +#include <es_sock.h> +#include <e32base.h> +#include <btdevice.h> +#include <bt_sock.h> +#include <btsdp.h> + + + +QT_BEGIN_HEADER + +class QBluetoothDeviceInfo; + +class BluetoothLinkManagerDeviceDiscoverer : public QObject, public CActive +{ + Q_OBJECT + +public: + + explicit BluetoothLinkManagerDeviceDiscoverer(RSocketServ& aSocketServ, QObject *parent = 0); + ~BluetoothLinkManagerDeviceDiscoverer(); + + void startDiscovery(const uint discoveryType); + void stopDiscovery(); + bool isReallyActive() const; + +protected: // From CActive + void RunL(); + void DoCancel(); + TInt RunError(TInt aError); + +private: + + void setError(int error); + +private: // private helper functions + + QBluetoothDeviceInfo currentDeviceDataToQBluetoothDeviceInfo() const; + +Q_SIGNALS: // SIGNALS + void deviceDiscoveryComplete(); + void deviceDiscovered(const QBluetoothDeviceInfo &device); + void linkManagerError(QBluetoothDeviceDiscoveryAgent::Error error, QString errorString); + void canceled(); + +private: + + // socket server handle + RSocketServ &m_socketServer; + + RHostResolver m_hostResolver; + TInquirySockAddr m_addr; + TNameEntry m_entry; + + TBool m_LIAC; + bool m_pendingCancel; + bool m_pendingStart; + uint m_discoveryType; +}; + +QT_END_HEADER + +#endif //BLUETOOTHLINKMANAGERDEVICEDISCOVERER_H diff --git a/src/bluetooth/symbian/bluetoothsymbianpairingadapter.cpp b/src/bluetooth/symbian/bluetoothsymbianpairingadapter.cpp new file mode 100644 index 00000000..963f45ff --- /dev/null +++ b/src/bluetooth/symbian/bluetoothsymbianpairingadapter.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// INCLUDE FILES +#include "bluetoothsymbianpairingadapter.h" +#include "qbluetoothaddress.h" +#include "qbluetoothdeviceinfo.h" +#include "qbluetoothlocaldevice.h" +#include <qstring.h> +#include <btdevice.h> +#include "utils_symbian_p.h" +#include "bluetoothsymbianregistryadapter.h" +#include <QDebug> + +/*Dedicated bonding attempt failure when the remote device responds with No-Bonding */ +const static TInt BTKErrRemoteDeviceIndicatedNoBonding = KLinkManagerErrBase-4; +/*! \internal + \class BluetoothSymbianPairingAdapter + \brief The BluetoothSymbianPairingAdapter class is an adapter for bluetooth pairing functionality. + + The BluetoothSymbianPairingAdapter is constructed to use for a one QBluetoothAddress. + It uses following Symbian class CBTEngConnMan for native operations. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \internal +*/ + +BluetoothSymbianPairingAdapter::BluetoothSymbianPairingAdapter(const QBluetoothAddress &address, QObject *parent) + : QObject(parent) + , m_pairingEngine(0) + , m_address(address) + , m_pairingOngoing(false) + , m_errorCode(0) + , m_pairingErrorString() +{ + TRAP(m_errorCode, m_pairingEngine = CBTEngConnMan::NewL(this)) + + if (m_errorCode != KErrNone) + emit pairingError(m_errorCode); +} +BluetoothSymbianPairingAdapter::~BluetoothSymbianPairingAdapter() +{ + delete m_pairingEngine; +} + +int BluetoothSymbianPairingAdapter::errorCode() const +{ + return m_errorCode; +} + +QString BluetoothSymbianPairingAdapter::pairingErrorString() const +{ + return m_pairingErrorString; +} + +void BluetoothSymbianPairingAdapter::startPairing(QBluetoothLocalDevice::Pairing pairing) +{ + TBTDevAddr btAddress(m_address.toUInt64()); + // start async pairing process + m_pairingOngoing = true; + int error = KErrBadHandle; + + if (m_pairingEngine) { + error =KErrNone; + error = m_pairingEngine->PairDevice(btAddress); + } + + if (error != KErrNone) { + PairingComplete(btAddress, error); + } +} + +void BluetoothSymbianPairingAdapter::ConnectComplete( TBTDevAddr& aAddr, TInt aErr, + RBTDevAddrArray* aConflicts ) +{ + Q_UNUSED(aAddr); + Q_UNUSED(aErr); + Q_UNUSED(aConflicts); +} + +void BluetoothSymbianPairingAdapter::DisconnectComplete( TBTDevAddr& aAddr, TInt aErr ) +{ + Q_UNUSED(aAddr); + Q_UNUSED(aErr); +} + +void BluetoothSymbianPairingAdapter::PairingComplete( TBTDevAddr& aAddr, TInt aErr ) +{ + m_pairingErrorString.clear(); + m_pairingOngoing = false; + + switch (aErr) { + case KErrNone: { + // need to figure out if authorized or not + QBluetoothLocalDevice::Pairing pairingStatus = QBluetoothLocalDevice::Paired; + BluetoothSymbianRegistryAdapter *registryAdapter = new BluetoothSymbianRegistryAdapter( + qTBTDevAddrToQBluetoothAddress(aAddr),NULL); + if (registryAdapter) { + pairingStatus = registryAdapter->pairingStatus(); + delete registryAdapter; + } + qDebug() << "pairingStatus = " << static_cast<int>(pairingStatus); + emit pairingFinished(qTBTDevAddrToQBluetoothAddress(aAddr),pairingStatus); + } + break; + case BTKErrRemoteDeviceIndicatedNoBonding: + m_pairingErrorString.append("Dedicated bonding attempt failure when the remote device responds with No-Bonding"); + break; + default: + m_pairingErrorString.append("Symbian pairing error=") + aErr; + break; + } + if (aErr != KErrNone) + emit pairingError(aErr); + +} + +#include "moc_bluetoothsymbianpairingadapter.cpp" diff --git a/src/bluetooth/symbian/bluetoothsymbianpairingadapter.h b/src/bluetooth/symbian/bluetoothsymbianpairingadapter.h new file mode 100644 index 00000000..68be17d5 --- /dev/null +++ b/src/bluetooth/symbian/bluetoothsymbianpairingadapter.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLUETOOTHSYMBIANPAIRINGADAPTER_H +#define BLUETOOTHSYMBIANPAIRINGADAPTER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qconnectivityglobal.h> +#include <QtCore/QObject> + +#include <e32base.h> +#include <btdevice.h> +#include <bt_sock.h> +#include <btengconnman.h> +#include "qbluetoothlocaldevice.h" + +QT_BEGIN_HEADER + +class QBluetoothAddress; + +class BluetoothSymbianPairingAdapter : public QObject, public MBTEngConnObserver +{ + Q_OBJECT +public: + + explicit BluetoothSymbianPairingAdapter(const QBluetoothAddress &address, QObject *parent = 0); + ~BluetoothSymbianPairingAdapter(); + + void startPairing(QBluetoothLocalDevice::Pairing pairing); + + int errorCode() const; + QString pairingErrorString() const; + +public: //from MBTEngConnObserver + virtual void ConnectComplete( TBTDevAddr& aAddr, TInt aErr, + RBTDevAddrArray* aConflicts = NULL ); + virtual void DisconnectComplete( TBTDevAddr& aAddr, TInt aErr ); + + virtual void PairingComplete( TBTDevAddr& aAddr, TInt aErr ); + +Q_SIGNALS: // SIGNALS + void pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + void pairingDisplayPinCode(const QBluetoothAddress &address, QString pin); + void pairingError(int errorCode); +private: + + // socket server handle + CBTEngConnMan *m_pairingEngine; + const QBluetoothAddress &m_address; + bool m_pairingOngoing; + int m_errorCode; + QString m_pairingErrorString; +}; + +QT_END_HEADER + +#endif //BLUETOOTHSYMBIANPAIRINGADAPTER_H diff --git a/src/bluetooth/symbian/bluetoothsymbianregistryadapter.cpp b/src/bluetooth/symbian/bluetoothsymbianregistryadapter.cpp new file mode 100644 index 00000000..4652cb42 --- /dev/null +++ b/src/bluetooth/symbian/bluetoothsymbianregistryadapter.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// INCLUDE FILES +#include "bluetoothsymbianregistryadapter.h" +#include "qbluetoothaddress.h" +#include "qbluetoothdeviceinfo.h" +#include <qstring.h> +#include <btdevice.h> +#include "utils_symbian_p.h" + +/*! \internal + \class BluetoothSymbianRegistryAdapter + \brief The BluetoothSymbianRegistryAdapter class is an adapter for handling Symbian Bluetooth + Registry. + + The BluetoothSymbianRegistryAdapter is constructed to use for a one QBluetoothAddress. + It uses following Symbian class CBTEngDevMan for native operations. + + \ingroup connectivity-bluetooth + \inmodule QtConnectivity + \internal + + @internalComponent + +*/ + +BluetoothSymbianRegistryAdapter::BluetoothSymbianRegistryAdapter(const QBluetoothAddress &address, QObject *parent) + : QObject(parent) + , m_bluetoothDeviceManager(0) + , m_address(address) + , m_operation(NoOp) +{ + TRAP(m_errorCode, m_bluetoothDeviceManager = CBTEngDevMan::NewL(this)) + if (m_errorCode != KErrNone) + emit registryHandlingError(m_errorCode); +} +BluetoothSymbianRegistryAdapter::~BluetoothSymbianRegistryAdapter() +{ + delete m_bluetoothDeviceManager; +} + +int BluetoothSymbianRegistryAdapter::errorCode() const +{ + return m_errorCode; +} + +QString BluetoothSymbianRegistryAdapter::pairingErrorString() const +{ + return m_pairingErrorString; +} + +QBluetoothLocalDevice::Pairing BluetoothSymbianRegistryAdapter::remoteDevicePairingStatus() +{ + QBluetoothLocalDevice::Pairing returnValue = QBluetoothLocalDevice::Unpaired; + // if the address provided is not valid + if (m_address.isNull()) { + emit registryHandlingError((int)KErrArgument); + return returnValue; + } + int errorCode = 0; + // use Symbian registry to get a current pairing status of a device + // do not pass observer for this method -> use sync version of GetDevices() + CBTEngDevMan *btDeviceManager = NULL; + TRAPD(deviceManagerCreationErr, btDeviceManager = CBTEngDevMan::NewL(NULL)); + if (deviceManagerCreationErr != KErrNone) { + emit registryHandlingError((int)deviceManagerCreationErr); + return returnValue; + } + + // Spesify search criteria + TBTRegistrySearch lSearchCriteria; + TBTDevAddr btAddress(m_address.toUInt64()); + lSearchCriteria.FindAddress(btAddress); + + CBTDeviceArray *listOfDevices = NULL; + TRAPD(arrayCreationErr,listOfDevices = createDeviceArrayL()); + if (arrayCreationErr !=KErrNone) { + emit registryHandlingError((int)arrayCreationErr); + // cleanup manager before returning + delete btDeviceManager; + return returnValue; + } + errorCode = btDeviceManager->GetDevices(lSearchCriteria,listOfDevices); + if (errorCode != KErrNone) { + emit registryHandlingError(errorCode); + return returnValue; + } + if ( listOfDevices->Count() == 1) { + CBTDevice *device= listOfDevices->At(0); + bool isValidDevicePaired = device->IsValidPaired(); + bool isDevicePaired = device->IsPaired(); + //TODO Check whether check is correct? + if (isValidDevicePaired || isDevicePaired) { + if (device->GlobalSecurity().NoAuthorise()) + returnValue = QBluetoothLocalDevice::AuthorizedPaired; + else + returnValue = QBluetoothLocalDevice::Paired; + } + else if (!isValidDevicePaired && !isDevicePaired) { + returnValue = QBluetoothLocalDevice::Unpaired; + } + + } else { + returnValue = QBluetoothLocalDevice::Unpaired; + } + //cleanup + listOfDevices->ResetAndDestroy(); + delete listOfDevices; + delete btDeviceManager; + return returnValue; +} +CBTDeviceArray* BluetoothSymbianRegistryAdapter::createDeviceArrayL() const +{ + return q_check_ptr(new CBTDeviceArray(10)); +} + +void BluetoothSymbianRegistryAdapter::removePairing() +{ + // setup current values + int errorCode = 0; + m_operation = RemovePairing; + // Spesify search criteria + TBTRegistrySearch searchCriteria; + TBTDevAddr btAddress(m_address.toUInt64()); + searchCriteria.FindAddress(btAddress); + errorCode = m_bluetoothDeviceManager->DeleteDevices(searchCriteria); + // if there is error then manually call callback for error routines + if (errorCode != KErrNone) + HandleDevManComplete(errorCode); + +} + +QBluetoothLocalDevice::Pairing BluetoothSymbianRegistryAdapter::pairingStatus() +{ + m_operation = PairingStatus; // only needed for uniformity + QBluetoothLocalDevice::Pairing pairStatus = remoteDevicePairingStatus(); + m_operation = NoOp; + + return pairStatus; +} + +void BluetoothSymbianRegistryAdapter::HandleDevManComplete( TInt aErr ) +{ + m_errorCode = aErr; + if (aErr != KErrNone) { + emit registryHandlingError(aErr); + } + if (m_operation == RemovePairing) { + emit pairingStatusChanged(m_address, QBluetoothLocalDevice::Unpaired); + m_operation = NoOp; + } + +} + +void BluetoothSymbianRegistryAdapter::HandleGetDevicesComplete( TInt aErr,CBTDeviceArray* aDeviceArray ) +{ + Q_UNUSED(aErr); + Q_UNUSED(aDeviceArray); +} + +#include "moc_bluetoothsymbianregistryadapter.cpp" diff --git a/src/bluetooth/symbian/bluetoothsymbianregistryadapter.h b/src/bluetooth/symbian/bluetoothsymbianregistryadapter.h new file mode 100644 index 00000000..9733533d --- /dev/null +++ b/src/bluetooth/symbian/bluetoothsymbianregistryadapter.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLUETOOTHSYMBIANREGISTRYADAPTER_H +#define BLUETOOTHSYMBIANREGISTRYADAPTER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qconnectivityglobal.h> +#include <QtCore/QObject> + +#include <e32base.h> +#include <btdevice.h> +#include <bt_sock.h> +#include <btengdevman.h> +#include "qbluetoothlocaldevice.h" + +QT_BEGIN_HEADER + +class QBluetoothDeviceInfo; +class QBluetoothAddress; + +class BluetoothSymbianRegistryAdapter : public QObject, public MBTEngDevManObserver +{ + Q_OBJECT +public: + + explicit BluetoothSymbianRegistryAdapter(const QBluetoothAddress &address, QObject *parent = 0); + ~BluetoothSymbianRegistryAdapter(); + + void removePairing(); + QBluetoothLocalDevice::Pairing pairingStatus(); + int errorCode() const; + QString pairingErrorString() const; + +public: //from MBTEngDevManObserver + virtual void HandleDevManComplete( TInt aErr ); + virtual void HandleGetDevicesComplete( TInt aErr,CBTDeviceArray* aDeviceArray ); + + +private: + QBluetoothLocalDevice::Pairing remoteDevicePairingStatus(); + CBTDeviceArray* createDeviceArrayL() const; + +Q_SIGNALS: // SIGNALS + void registryHandlingError(int errorCode); + void pairingStatusChanged(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + +private: + enum Operation { + NoOp, + PairingStatus, + RemovePairing + }; +private: + // Symbian registry hander + CBTEngDevMan *m_bluetoothDeviceManager; + const QBluetoothAddress &m_address; + Operation m_operation; + + int m_errorCode; + QString m_pairingErrorString; +}; + +QT_END_HEADER + +#endif //BLUETOOTHSYMBIANREGISTRYADAPTER_H diff --git a/src/bluetooth/symbian/symbian.pri b/src/bluetooth/symbian/symbian.pri new file mode 100644 index 00000000..d45ce209 --- /dev/null +++ b/src/bluetooth/symbian/symbian.pri @@ -0,0 +1,30 @@ + +contains(SYMBIAN_VERSION, Symbian3) { + message("Extended Inquiry Request supported") + DEFINES += EIR_SUPPORTED +} + +PRIVATE_HEADERS += \ + bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.h \ + bluetooth/symbian/utils_symbian_p.h + +SOURCES += \ + bluetooth/symbian/bluetoothlinkmanagerdevicediscoverer.cpp + +contains(btengconnman_symbian_enabled, yes) { + DEFINES += USING_BTENGCONNMAN + LIBS *=-lbtengconnman + PRIVATE_HEADERS += \ + bluetooth/symbian/bluetoothsymbianpairingadapter.h + SOURCES += \ + bluetooth/symbian/bluetoothsymbianpairingadapter.cpp +} + +contains(btengdevman_symbian_enabled, yes) { + DEFINES += USING_BTENGDEVMAN + LIBS *=-lbtengdevman + PRIVATE_HEADERS += \ + bluetooth/symbian/bluetoothsymbianregistryadapter.h + SOURCES += \ + bluetooth/symbian/bluetoothsymbianregistryadapter.cpp +} diff --git a/src/bluetooth/symbian/utils_symbian_p.h b/src/bluetooth/symbian/utils_symbian_p.h new file mode 100644 index 00000000..5f7a3dc9 --- /dev/null +++ b/src/bluetooth/symbian/utils_symbian_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef UTILS_SYMBIAN_P_H +#define UTILS_SYMBIAN_P_H + +#include <bttypes.h> +#include <bt_sock.h> + +QT_BEGIN_HEADER + +inline QBluetoothAddress qTBTDevAddrToQBluetoothAddress(const TBTDevAddr &address) +{ + return QBluetoothAddress(QString(QByteArray((const char *)address.Des().Ptr(), 6).toHex().toUpper())); +} +inline quint32 qTPackSymbianDeviceClass(const TInquirySockAddr &address) +{ + TUint8 minorClass = address.MinorClassOfDevice(); + TUint8 majorClass = address.MajorClassOfDevice(); + TUint16 serviceClass = address.MajorServiceClass(); + quint32 deviceClass = (0 << 2) | (minorClass << 6 ) | (majorClass <<5) | serviceClass; + return deviceClass; +} +inline QString s60DescToQString(const TDesC &desc) +{ + return QString::fromUtf16(desc.Ptr(), desc.Length()); +} +inline QByteArray s60Desc8ToQByteArray(const TDesC8 &desc) +{ + return QByteArray((const char*)desc.Ptr(), desc.Length()); +} + +QT_END_HEADER + +#endif diff --git a/src/nfc/checksum_p.h b/src/nfc/checksum_p.h new file mode 100644 index 00000000..48b761b9 --- /dev/null +++ b/src/nfc/checksum_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHECKSUM_P_H +#define CHECKSUM_P_H + +// Copied from qbytearray.cpp +// Modified to initialise the crc with 0x6363 instead of 0xffff and to not invert the final result. +static const quint16 crc_tbl[16] = { + 0x0000, 0x1081, 0x2102, 0x3183, + 0x4204, 0x5285, 0x6306, 0x7387, + 0x8408, 0x9489, 0xa50a, 0xb58b, + 0xc60c, 0xd68d, 0xe70e, 0xf78f +}; + +quint16 qNfcChecksum(const char *data, uint len) +{ + register quint16 crc = 0x6363; + uchar c; + const uchar *p = reinterpret_cast<const uchar *>(data); + while (len--) { + c = *p++; + crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)]; + c >>= 4; + crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)]; + } + return crc; +} + +#endif // CHECKSUM_P_H diff --git a/src/nfc/maemo6/adapter_interface.cpp b/src/nfc/maemo6/adapter_interface.cpp new file mode 100644 index 00000000..bb50f38e --- /dev/null +++ b/src/nfc/maemo6/adapter_interface.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p adapter_interface_p.h:adapter_interface.cpp com.nokia.nfc.Adapter.xml + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "adapter_interface_p.h" + +/* + * Implementation of interface class ComNokiaNfcAdapterInterface + */ + +ComNokiaNfcAdapterInterface::ComNokiaNfcAdapterInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +ComNokiaNfcAdapterInterface::~ComNokiaNfcAdapterInterface() +{ +} + diff --git a/src/nfc/maemo6/adapter_interface_p.h b/src/nfc/maemo6/adapter_interface_p.h new file mode 100644 index 00000000..57df898d --- /dev/null +++ b/src/nfc/maemo6/adapter_interface_p.h @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 and then hand edited + * Command line was: qdbusxml2cpp -p adapter_interface_p.h:adapter_interface.cpp com.nokia.nfc.Adapter.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + */ + +#ifndef ADAPTER_INTERFACE_P_H +#define ADAPTER_INTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface com.nokia.nfc.Adapter + */ +class ComNokiaNfcAdapterInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "com.nokia.nfc.Adapter"; } + +public: + ComNokiaNfcAdapterInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~ComNokiaNfcAdapterInterface(); + + Q_PROPERTY(bool Discovering READ discovering) + inline bool discovering() { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return false; + + return reply.value().value(QLatin1String("Discovering")).toBool(); + } + + Q_PROPERTY(QString State READ state WRITE setState) + inline QString state() { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return QString(); + + return reply.value().value(QLatin1String("State")).toString(); + } + + inline void setState(const QString &value) + { SetProperty(QLatin1String("State"), QDBusVariant(qVariantFromValue(value))); } + + Q_PROPERTY(QStringList TagTechnologies READ tagTechnologies) + inline QStringList tagTechnologies() + { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return QStringList(); + + return reply.value().value(QLatin1String("TagTechnologies")).toStringList(); + } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> CancelAccessRequest(const QDBusObjectPath &in0, const QString &in1) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QLatin1String("CancelAccessRequest"), argumentList); + } + + inline QDBusPendingReply<> CancelHandoverRequest(const QString &in0) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QLatin1String("CancelHandoverRequest"), argumentList); + } + + inline QDBusPendingReply<QVariantMap> GetProperties() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + } + + inline QDBusPendingReply<> RegisterUIAgent(const QDBusObjectPath &in0) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QLatin1String("RegisterUIAgent"), argumentList); + } + + inline QDBusPendingReply<> RequestAccess(const QDBusObjectPath &in0, const QString &in1) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QLatin1String("RequestAccess"), argumentList); + } + + inline QDBusPendingReply<> RequestHandover(const QDBusObjectPath &in0, const QString &in1, const QString &in2) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2); + return asyncCallWithArgumentList(QLatin1String("RequestHandover"), argumentList); + } + + inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList); + } + + inline QDBusPendingReply<> UnregisterUIAgent(const QDBusObjectPath &in0) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QLatin1String("UnregisterUIAgent"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void HandoverCarrierSelected(const QString &in0); + void HandoverCompleted(const QString &in0, const QDBusVariant &in1); + void HandoverFailed(const QString &in0); + void HandoverStarted(); + void PropertyChanged(const QString &in0, const QDBusVariant &in1); + void TargetDetected(const QDBusObjectPath &in0); + void TargetLost(const QDBusObjectPath &in0); +}; + +namespace com { + namespace nokia { + namespace nfc { + typedef ::ComNokiaNfcAdapterInterface Adapter; + } + } +} +#endif diff --git a/src/nfc/maemo6/com.nokia.nfc.AccessRequestor.xml b/src/nfc/maemo6/com.nokia.nfc.AccessRequestor.xml new file mode 100644 index 00000000..655448d2 --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.AccessRequestor.xml @@ -0,0 +1,14 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/foo"> + <interface name="com.nokia.nfc.AccessRequestor"> + <method name="AccessFailed"> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="AccessGranted"> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + </method> + </interface> +</node> diff --git a/src/nfc/maemo6/com.nokia.nfc.Adapter.xml b/src/nfc/maemo6/com.nokia.nfc.Adapter.xml new file mode 100644 index 00000000..3e3d3c85 --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.Adapter.xml @@ -0,0 +1,59 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/com/nokia/nfc/0/nfc0"> + <interface name="com.nokia.nfc.Adapter"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <method name="RequestHandover"> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="CancelHandoverRequest"> + <arg type="s" direction="in"/> + </method> + <method name="RequestAccess"> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="CancelAccessRequest"> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="RegisterUIAgent"> + <arg type="o" direction="in"/> + </method> + <method name="UnregisterUIAgent"> + <arg type="o" direction="in"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + <signal name="TargetDetected"> + <arg type="o"/> + </signal> + <signal name="TargetLost"> + <arg type="o"/> + </signal> + <signal name="HandoverStarted"/> + <signal name="HandoverCarrierSelected"> + <arg type="s"/> + </signal> + <signal name="HandoverCompleted"> + <arg type="s"/> + <arg type="v"/> + </signal> + <signal name="HandoverFailed"> + <arg type="s"/> + </signal> + <property name="State" type="s" access="readwrite"/> + <property name="Discovering" type="b" access="read"/> + <property name="TagTechnologies" type="as" access="read"/> + </interface> +</node> diff --git a/src/nfc/maemo6/com.nokia.nfc.Device.xml b/src/nfc/maemo6/com.nokia.nfc.Device.xml new file mode 100644 index 00000000..17acc5d0 --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.Device.xml @@ -0,0 +1,19 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/com/nokia/nfc/0/nfc0/target_DE_AD_BE_EF"> + <interface name="com.nokia.nfc.Device"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + <property name="UID" type="s" access="read"/> + </interface> +</node> + diff --git a/src/nfc/maemo6/com.nokia.nfc.LLCPRequestor.xml b/src/nfc/maemo6/com.nokia.nfc.LLCPRequestor.xml new file mode 100644 index 00000000..cf4f625a --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.LLCPRequestor.xml @@ -0,0 +1,22 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/foo"> + <interface name="com.nokia.nfc.LLCPRequestor"> + <method name="Accept"> + <arg type="v" direction="in"/> + <arg type="v" direction="in"/> + <arg type="h" direction="in"/> + <arg type="a{sv}" direction="in"/> + </method> + <method name="Connect"> + <arg type="v" direction="in"/> + <arg type="v" direction="in"/> + <arg type="h" direction="in"/> + <arg type="a{sv}" direction="in"/> + </method> + <method name="Socket"> + <arg type="v" direction="in"/> + <arg type="h" direction="in"/> + <arg type="a{sv}" direction="in"/> + </method> + </interface> +</node> diff --git a/src/nfc/maemo6/com.nokia.nfc.Manager.xml b/src/nfc/maemo6/com.nokia.nfc.Manager.xml new file mode 100644 index 00000000..cdc8fae8 --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.Manager.xml @@ -0,0 +1,47 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/"> + <interface name="com.nokia.nfc.Manager"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <method name="ListAdapters"> + <arg type="ao" direction="out"/> + </method> + <method name="FindAdapter"> + <arg type="s" direction="in"/> + <arg type="o" direction="out"/> + </method> + <method name="DefaultAdapter"> + <arg type="o" direction="out"/> + </method> + <method name="RegisterNDEFHandler"> + <arg type="s" direction="in"/> + <arg type="s" direction="in"/> + <arg type="o" direction="in"/> + <arg type="s" direction="in"/> + <arg type="s" direction="in"/> + <arg type="s" direction="in"/> + </method> + <method name="UnregisterNDEFHandler"> + <arg type="s" direction="in"/> + <arg type="s" direction="in"/> + <arg type="o" direction="in"/> + </method> + <signal name="AdapterAdded"> + <arg type="o"/> + </signal> + <signal name="AdapterRemoved"> + <arg type="o"/> + </signal> + <signal name="DefaultAdapterChanged"> + <arg type="o"/> + </signal> + <property name="LogLevel" type="s" access="readwrite"/> + </interface> +</node> + diff --git a/src/nfc/maemo6/com.nokia.nfc.NDEFHandler.xml b/src/nfc/maemo6/com.nokia.nfc.NDEFHandler.xml new file mode 100644 index 00000000..8b4fdd45 --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.NDEFHandler.xml @@ -0,0 +1,10 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/foo"> + <interface name="com.nokia.nfc.NDEFHandler"> + <method name="NDEFData"> + <arg type="o" direction="in"/> + <arg type="ay" direction="in"/> + </method> + </interface> +</node> + diff --git a/src/nfc/maemo6/com.nokia.nfc.SecureElement.xml b/src/nfc/maemo6/com.nokia.nfc.SecureElement.xml new file mode 100644 index 00000000..702f3b2a --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.SecureElement.xml @@ -0,0 +1,34 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/com/nokia/nfc/0/nfc0/se0"> + <interface name="com.nokia.nfc.SecureElement"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="RequestAccess"/> + <method name="ReleaseAccess"/> + <method name="Activate"/> + <method name="Deactivate"/> + <method name="SetActivationLevel"> + <arg type="v" direction="in"/> + </method> + <method name="RawRequest"> + <arg type="ay" direction="in"/> + <arg type="ay" direction="out"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + <signal name="TransactionStarted"> + <arg type="s"/> + </signal> + <signal name="TransactionEnded"> + <arg type="s"/> + <arg type="s"/> + </signal> + <property name="State" type="s" access="read"/> + <property name="ActivationLevel" type="s" access="read"/> + </interface> +</node> + diff --git a/src/nfc/maemo6/com.nokia.nfc.Tag.xml b/src/nfc/maemo6/com.nokia.nfc.Tag.xml new file mode 100644 index 00000000..4d24850f --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.Tag.xml @@ -0,0 +1,28 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/com/nokia/nfc/0/nfc0/target_DE_AD_BE_EF"> + <interface name="com.nokia.nfc.Tag"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <method name="ReadNDEFData"> + <arg type="aay" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QList<QByteArray>"/> + </method> + <method name="WriteNDEFData"> + <arg type="aay" direction="in"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QList<QByteArray>"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + <property name="UID" type="s" access="read"/> + <property name="Technology" type="s" access="read"/> + </interface> +</node> + diff --git a/src/nfc/maemo6/com.nokia.nfc.Target.xml b/src/nfc/maemo6/com.nokia.nfc.Target.xml new file mode 100644 index 00000000..a5fa2308 --- /dev/null +++ b/src/nfc/maemo6/com.nokia.nfc.Target.xml @@ -0,0 +1,20 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/com/nokia/nfc/0/nfc0/target_DE_AD_BE_EF"> + <interface name="com.nokia.nfc.Target"> + <method name="GetProperties"> + <arg type="a{sv}" direction="out"/> + <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <method name="SetProperty"> + <arg type="s" direction="in"/> + <arg type="v" direction="in"/> + </method> + <signal name="PropertyChanged"> + <arg type="s"/> + <arg type="v"/> + </signal> + <property name="Type" type="s" access="read"/> + <property name="State" type="s" access="read"/> + </interface> +</node> + diff --git a/src/nfc/maemo6/device_interface.cpp b/src/nfc/maemo6/device_interface.cpp new file mode 100644 index 00000000..69b2c930 --- /dev/null +++ b/src/nfc/maemo6/device_interface.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p device_interface_p.h:device_interface.cpp com.nokia.nfc.Device.xml + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "device_interface_p.h" + +/* + * Implementation of interface class ComNokiaNfcDeviceInterface + */ + +ComNokiaNfcDeviceInterface::ComNokiaNfcDeviceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +ComNokiaNfcDeviceInterface::~ComNokiaNfcDeviceInterface() +{ +} + diff --git a/src/nfc/maemo6/device_interface_p.h b/src/nfc/maemo6/device_interface_p.h new file mode 100644 index 00000000..ff2d5604 --- /dev/null +++ b/src/nfc/maemo6/device_interface_p.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 and then hand edited + * Command line was: qdbusxml2cpp -p device_interface_p.h:device_interface.cpp com.nokia.nfc.Device.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + */ + +#ifndef DEVICE_INTERFACE_P_H +#define DEVICE_INTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface com.nokia.nfc.Device + */ +class ComNokiaNfcDeviceInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "com.nokia.nfc.Device"; } + +public: + ComNokiaNfcDeviceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~ComNokiaNfcDeviceInterface(); + + Q_PROPERTY(QString UID READ uID) + inline QString uID() { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return QString(); + + return reply.value().value(QLatin1String("UID")).toString(); + } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<QVariantMap> GetProperties() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + } + + inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void PropertyChanged(const QString &in0, const QDBusVariant &in1); +}; + +namespace com { + namespace nokia { + namespace nfc { + typedef ::ComNokiaNfcDeviceInterface Device; + } + } +} +#endif diff --git a/src/nfc/maemo6/generate b/src/nfc/maemo6/generate new file mode 100755 index 00000000..fa7260d5 --- /dev/null +++ b/src/nfc/maemo6/generate @@ -0,0 +1,8 @@ +#!/bin/sh + +qdbusxml2cpp -p adapter_interface_p.h:adapter_interface.cpp com.nokia.nfc.Adapter.xml + +qdbusxml2cpp -p target_interface_p.h:target_interface.cpp com.nokia.nfc.Target.xml +qdbusxml2cpp -p tag_interface_p.h:tag_interface.cpp com.nokia.nfc.Tag.xml +qdbusxml2cpp -p device_interface_p.h:device_interface.cpp com.nokia.nfc.Device.xml + diff --git a/src/nfc/maemo6/socketrequestor.cpp b/src/nfc/maemo6/socketrequestor.cpp new file mode 100644 index 00000000..b7595bc8 --- /dev/null +++ b/src/nfc/maemo6/socketrequestor.cpp @@ -0,0 +1,704 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "socketrequestor_p.h" + +#include <QtCore/QMutex> +#include <QtCore/QHash> +#include <QtCore/QSocketNotifier> +#include <QtCore/QStringList> +#include <QtCore/QElapsedTimer> +#include <QtCore/QCoreApplication> +#include <QtDBus/QDBusObjectPath> + +#include <dbus/dbus.h> + +#include <sys/select.h> +#include <errno.h> + +struct WatchNotifier +{ + DBusWatch *watch; + QSocketNotifier *readNotifier; + QSocketNotifier *writeNotifier; +}; + +static QVariant getVariantFromDBusMessage(DBusMessageIter *iter) +{ + dbus_bool_t bool_data; + dbus_int32_t int32_data; + dbus_uint32_t uint32_data; + dbus_int64_t int64_data; + dbus_uint64_t uint64_data; + char *str_data; + char char_data; + int argtype = dbus_message_iter_get_arg_type(iter); + + switch (argtype) { + case DBUS_TYPE_BOOLEAN: { + dbus_message_iter_get_basic(iter, &bool_data); + QVariant variant((bool)bool_data); + return variant; + } + case DBUS_TYPE_ARRAY: { + // Handle all arrays here + int elem_type = dbus_message_iter_get_element_type(iter); + DBusMessageIter array_iter; + + dbus_message_iter_recurse(iter, &array_iter); + + if (elem_type == DBUS_TYPE_BYTE) { + QByteArray byte_array; + do { + dbus_message_iter_get_basic(&array_iter, &char_data); + byte_array.append(char_data); + } while (dbus_message_iter_next(&array_iter)); + QVariant variant(byte_array); + return variant; + } else if (elem_type == DBUS_TYPE_STRING) { + QStringList str_list; + do { + dbus_message_iter_get_basic(&array_iter, &str_data); + str_list.append(str_data); + } while (dbus_message_iter_next(&array_iter)); + QVariant variant(str_list); + return variant; + } else { + QVariantList variantList; + do { + variantList << getVariantFromDBusMessage(&array_iter); + } while (dbus_message_iter_next(&array_iter)); + QVariant variant(variantList); + return variant; + } + break; + } + case DBUS_TYPE_BYTE: { + dbus_message_iter_get_basic(iter, &char_data); + QChar ch(char_data); + QVariant variant(ch); + return variant; + } + case DBUS_TYPE_INT32: { + dbus_message_iter_get_basic(iter, &int32_data); + QVariant variant((int)int32_data); + return variant; + } + case DBUS_TYPE_UINT32: { + dbus_message_iter_get_basic(iter, &uint32_data); + QVariant variant((uint)uint32_data); + return variant; + } + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_STRING: { + dbus_message_iter_get_basic(iter, &str_data); + QString str(str_data); + QVariant variant(str); + return variant; + } + case DBUS_TYPE_INT64: { + dbus_message_iter_get_basic(iter, &int64_data); + QVariant variant((qlonglong)int64_data); + return variant; + } + case DBUS_TYPE_UINT64: { + dbus_message_iter_get_basic(iter, &uint64_data); + QVariant variant((qulonglong)uint64_data); + return variant; + } + case DBUS_TYPE_DICT_ENTRY: + case DBUS_TYPE_STRUCT: { + // Handle all structs here + DBusMessageIter struct_iter; + dbus_message_iter_recurse(iter, &struct_iter); + + QVariantList variantList; + do { + variantList << getVariantFromDBusMessage(&struct_iter); + } while (dbus_message_iter_next(&struct_iter)); + QVariant variant(variantList); + return variant; + } + case DBUS_TYPE_VARIANT: { + DBusMessageIter variant_iter; + dbus_message_iter_recurse(iter, &variant_iter); + + return getVariantFromDBusMessage(&variant_iter); + } + case DBUS_TYPE_UNIX_FD: { + dbus_message_iter_get_basic(iter, &uint32_data); + QVariant variant((uint)uint32_data); + return variant; + } + + default: + qWarning("Unsupported DBUS type: %d\n", argtype); + } + + return QVariant(); +} + +class SocketRequestorPrivate : public QObject +{ + Q_OBJECT + +public: + SocketRequestorPrivate(); + ~SocketRequestorPrivate(); + + DBusHandlerResult messageFilter(DBusConnection *connection, DBusMessage *message); + void addWatch(DBusWatch *watch); + + void registerObject(const QString &path, SocketRequestor *object); + void unregisterObject(const QString &path); + + Q_INVOKABLE void sendRequestAccess(const QString &adaptor, const QString &path, + const QString &kind); + Q_INVOKABLE void sendCancelAccessRequest(const QString &adaptor, const QString &path, + const QString &kind); + + bool waitForDBusSignal(int msecs); + +private: + bool parseAccessFailed(DBusMessage *message, SocketRequestor *socketRequestor); + bool parseAccessGranted(DBusMessage *message, SocketRequestor *socketRequestor); + bool parseAcceptConnect(DBusMessage *message, SocketRequestor *socketRequestor, + const char *member); + bool parseSocket(DBusMessage *message, SocketRequestor *socketRequestor, const char *member); + bool parseErrorDenied(DBusMessage *message, SocketRequestor *socketRequestor); + +private slots: + void socketRead(); + void socketWrite(); + +private: + QMutex m_mutex; + DBusConnection *m_dbusConnection; + QHash<QString, SocketRequestor *> m_dbusObjects; + QMap<quint32, SocketRequestor *> m_pendingCalls; + QList<WatchNotifier> m_watchNotifiers; +}; + +Q_GLOBAL_STATIC(SocketRequestorPrivate, socketRequestorPrivate) + +static DBusHandlerResult dbusFilter(DBusConnection *connection, DBusMessage *message, + void *userData) +{ + SocketRequestorPrivate *s = static_cast<SocketRequestorPrivate *>(userData); + return s->messageFilter(connection, message); +} + +static dbus_bool_t dbusWatch(DBusWatch *watch, void *data) +{ + SocketRequestorPrivate *s = static_cast<SocketRequestorPrivate *>(data); + s->addWatch(watch); + + return true; +} + +SocketRequestorPrivate::SocketRequestorPrivate() +{ + DBusError error; + dbus_error_init(&error); + m_dbusConnection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); + dbus_connection_add_filter(m_dbusConnection, &dbusFilter, this, 0); + dbus_connection_set_watch_functions(m_dbusConnection, dbusWatch, 0, 0, this, 0); + dbus_error_free(&error); +} + +SocketRequestorPrivate::~SocketRequestorPrivate() +{ + dbus_connection_close(m_dbusConnection); + dbus_connection_unref(m_dbusConnection); +} + +DBusHandlerResult SocketRequestorPrivate::messageFilter(DBusConnection *connection, + DBusMessage *message) +{ + QMutexLocker locker(&m_mutex); + + foreach (const WatchNotifier &watchNotifier, m_watchNotifiers) + watchNotifier.writeNotifier->setEnabled(true); + + if (connection != m_dbusConnection) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + SocketRequestor *socketRequestor; + const QString path = QString::fromUtf8(dbus_message_get_path(message)); + quint32 serial = dbus_message_get_reply_serial(message); + if (!path.isEmpty() && serial == 0) + socketRequestor = m_dbusObjects.value(path); + else if (path.isEmpty() && serial != 0) + socketRequestor = m_pendingCalls.take(serial); + else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + enum { + NotHandled, + Handled, + HandledSendReply + } handled; + + if (dbus_message_is_method_call(message, "com.nokia.nfc.AccessRequestor", "AccessFailed")) + handled = parseAccessFailed(message, socketRequestor) ? HandledSendReply : NotHandled; + else if (dbus_message_is_method_call(message, "com.nokia.nfc.AccessRequestor", "AccessGranted")) + handled = parseAccessGranted(message, socketRequestor) ? HandledSendReply : NotHandled; + else if (dbus_message_is_method_call(message, "com.nokia.nfc.LLCPRequestor", "Accept")) + handled = parseAcceptConnect(message, socketRequestor, "accept") ? HandledSendReply : NotHandled; + else if (dbus_message_is_method_call(message, "com.nokia.nfc.LLCPRequestor", "Connect")) + handled = parseAcceptConnect(message, socketRequestor, "connect") ? HandledSendReply : NotHandled; + else if (dbus_message_is_method_call(message, "com.nokia.nfc.LLCPRequestor", "Socket")) + handled = parseSocket(message, socketRequestor, "socket") ? HandledSendReply : NotHandled; + else if (dbus_message_is_error(message, "com.nokia.nfc.Error.Denied")) + handled = parseErrorDenied(message, socketRequestor) ? Handled : NotHandled; + else + handled = NotHandled; + + if (handled == NotHandled) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (handled == HandledSendReply) { + DBusMessage *reply = dbus_message_new_method_return(message); + quint32 serial; + dbus_connection_send(connection, reply, &serial); + } + + return DBUS_HANDLER_RESULT_HANDLED; +} + +bool SocketRequestorPrivate::parseErrorDenied(DBusMessage *message, + SocketRequestor *socketRequestor) +{ + Q_UNUSED(message); + + QMetaObject::invokeMethod(socketRequestor, "accessFailed", + Q_ARG(QDBusObjectPath, QDBusObjectPath()), + Q_ARG(QString, QLatin1String("")), + Q_ARG(QString, QLatin1String("Access denied"))); + return true; +} + +bool SocketRequestorPrivate::parseAccessFailed(DBusMessage *message, + SocketRequestor *socketRequestor) +{ + Q_UNUSED(message); + + // m_mutex is locked in messageFilter() + + DBusMessageIter args; + + if (!dbus_message_iter_init(message, &args)) + return false; + + // read DBus Object Path + QVariant objectPath = getVariantFromDBusMessage(&args); + + if (!dbus_message_iter_next(&args)) + return false; + + // read DBus kind string + QVariant kind = getVariantFromDBusMessage(&args); + + if (!dbus_message_iter_next(&args)) + return false; + + // read DBus error string + QVariant errorString = getVariantFromDBusMessage(&args); + + QMetaObject::invokeMethod(socketRequestor, "accessFailed", + Q_ARG(QDBusObjectPath, QDBusObjectPath(objectPath.toString())), + Q_ARG(QString, kind.toString()), + Q_ARG(QString, errorString.toString())); + return true; +} + +bool SocketRequestorPrivate::parseAccessGranted(DBusMessage *message, + SocketRequestor *socketRequestor) +{ + Q_UNUSED(message); + + // m_mutex is locked in messageFilter() + + DBusMessageIter args; + + if (!dbus_message_iter_init(message, &args)) + return false; + + // read DBus Object Path + QVariant objectPath = getVariantFromDBusMessage(&args); + + if (!dbus_message_iter_next(&args)) + return false; + + // read access kind + QVariant kind = getVariantFromDBusMessage(&args); + + QMetaObject::invokeMethod(socketRequestor, "accessGranted", + Q_ARG(QDBusObjectPath, QDBusObjectPath(objectPath.toString())), + Q_ARG(QString, kind.toString())); + return true; +} + +bool SocketRequestorPrivate::parseAcceptConnect(DBusMessage *message, + SocketRequestor *socketRequestor, + const char *member) +{ + // m_mutex is locked in messageFilter() + + DBusMessageIter args; + + if (!dbus_message_iter_init(message, &args)) + return false; + + // read DBus Variant (lsap) + QVariant lsap = getVariantFromDBusMessage(&args); + + if (!dbus_message_iter_next(&args)) + return false; + // read DBus Variant (rsap) + QVariant rsap = getVariantFromDBusMessage(&args); + + if (!dbus_message_iter_next(&args)) + return false; + + // read socket fd + QVariant fd = getVariantFromDBusMessage(&args); + + if (!dbus_message_iter_next(&args)) + return false; + + // read DBus a{sv} into QVariantMap + QVariant prop = getVariantFromDBusMessage(&args); + QVariantMap properties; + foreach (const QVariant &v, prop.toList()) { + QVariantList vl = v.toList(); + if (vl.length() != 2) + continue; + + properties.insert(vl.first().toString(), vl.at(1)); + } + + QMetaObject::invokeMethod(socketRequestor, member, Q_ARG(QDBusVariant, QDBusVariant(lsap)), + Q_ARG(QDBusVariant, QDBusVariant(rsap)), + Q_ARG(int, fd.toInt()), Q_ARG(QVariantMap, properties)); + + return true; +} + +bool SocketRequestorPrivate::parseSocket(DBusMessage *message, SocketRequestor *socketRequestor, + const char *member) +{ + // m_mutex is locked in messageFilter() + + DBusMessageIter args; + + if (!dbus_message_iter_init(message, &args)) + return false; + + // read DBus Variant (lsap) + QVariant lsap = getVariantFromDBusMessage(&args); + + if (!dbus_message_iter_next(&args)) + return false; + + // read socket fd + QVariant fd = getVariantFromDBusMessage(&args); + + if (!dbus_message_iter_next(&args)) + return false; + + // read DBus a{sv} into QVariantMap + QVariant prop = getVariantFromDBusMessage(&args); + QVariantMap properties; + foreach (const QVariant &v, prop.toList()) { + QVariantList vl = v.toList(); + if (vl.length() != 2) + continue; + + properties.insert(vl.first().toString(), vl.at(1)); + } + + QMetaObject::invokeMethod(socketRequestor, member, Q_ARG(QDBusVariant, QDBusVariant(lsap)), + Q_ARG(int, fd.toInt()), Q_ARG(QVariantMap, properties)); + + return true; +} + +void SocketRequestorPrivate::addWatch(DBusWatch *watch) +{ + QMutexLocker locker(&m_mutex); + + int fd = dbus_watch_get_unix_fd(watch); + + WatchNotifier watchNotifier; + watchNotifier.watch = watch; + + watchNotifier.readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(watchNotifier.readNotifier, SIGNAL(activated(int)), this, SLOT(socketRead())); + watchNotifier.writeNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); + connect(watchNotifier.writeNotifier, SIGNAL(activated(int)), this, SLOT(socketWrite())); + + m_watchNotifiers.append(watchNotifier); +} + +void SocketRequestorPrivate::socketRead() +{ + QMutexLocker locker(&m_mutex); + + QList<DBusWatch *> pendingWatches; + + foreach (const WatchNotifier &watchNotifier, m_watchNotifiers) { + if (watchNotifier.readNotifier != sender()) + continue; + + pendingWatches.append(watchNotifier.watch); + } + + DBusConnection *connection = m_dbusConnection; + locker.unlock(); + + foreach (DBusWatch *watch, pendingWatches) + dbus_watch_handle(watch, DBUS_WATCH_READABLE); + + while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); +} + +void SocketRequestorPrivate::socketWrite() +{ + QMutexLocker locker(&m_mutex); + + QList<DBusWatch *> pendingWatches; + + foreach (const WatchNotifier &watchNotifier, m_watchNotifiers) { + if (watchNotifier.writeNotifier != sender()) + continue; + + watchNotifier.writeNotifier->setEnabled(false); + pendingWatches.append(watchNotifier.watch); + } + + locker.unlock(); + + foreach (DBusWatch *watch, pendingWatches) + dbus_watch_handle(watch, DBUS_WATCH_WRITABLE); +} + +void SocketRequestorPrivate::registerObject(const QString &path, SocketRequestor *object) +{ + QMutexLocker locker(&m_mutex); + + m_dbusObjects.insert(path, object); +} + +void SocketRequestorPrivate::unregisterObject(const QString &path) +{ + QMutexLocker locker(&m_mutex); + + m_dbusObjects.remove(path); +} + +void SocketRequestorPrivate::sendRequestAccess(const QString &adaptor, const QString &path, + const QString &kind) +{ + QMutexLocker locker(&m_mutex); + + foreach (const WatchNotifier &watchNotifier, m_watchNotifiers) + watchNotifier.writeNotifier->setEnabled(true); + + DBusMessage *message; + DBusMessageIter args; + + message = dbus_message_new_method_call("com.nokia.nfc", adaptor.toLocal8Bit(), + "com.nokia.nfc.Adapter", "RequestAccess"); + + if (!message) + return; + + dbus_message_iter_init_append(message, &args); + const QByteArray p = path.toUtf8(); + const char *pData = p.constData(); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_OBJECT_PATH, &pData)) { + dbus_message_unref(message); + return; + } + + const QByteArray k = kind.toUtf8(); + const char *kData = k.constData(); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &kData)) { + dbus_message_unref(message); + return; + } + + quint32 serial; + dbus_connection_send(m_dbusConnection, message, &serial); + + dbus_message_unref(message); + + m_pendingCalls.insert(serial, m_dbusObjects.value(path)); +} + +void SocketRequestorPrivate::sendCancelAccessRequest(const QString &adaptor, const QString &path, + const QString &kind) +{ + QMutexLocker locker(&m_mutex); + + foreach (const WatchNotifier &watchNotifier, m_watchNotifiers) + watchNotifier.writeNotifier->setEnabled(true); + + DBusMessage *message; + DBusMessageIter args; + + message = dbus_message_new_method_call("com.nokia.nfc", adaptor.toLocal8Bit(), + "com.nokia.nfc.Adapter", "CancelAccessRequest"); + + if (!message) + return; + + dbus_message_iter_init_append(message, &args); + const QByteArray p = path.toUtf8(); + const char *pData = p.constData(); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_OBJECT_PATH, &pData)) { + dbus_message_unref(message); + return; + } + + const QByteArray k = kind.toUtf8(); + const char *kData = k.constData(); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &kData)) { + dbus_message_unref(message); + return; + } + + quint32 serial; + dbus_connection_send(m_dbusConnection, message, &serial); + + dbus_message_unref(message); +} + +bool SocketRequestorPrivate::waitForDBusSignal(int msecs) +{ + dbus_connection_flush(m_dbusConnection); + + fd_set rfds; + FD_ZERO(&rfds); + + int nfds = -1; + foreach (const WatchNotifier &watchNotifier, m_watchNotifiers) { + FD_SET(watchNotifier.readNotifier->socket(), &rfds); + nfds = qMax(nfds, watchNotifier.readNotifier->socket()); + } + + timeval timeout; + timeout.tv_sec = msecs / 1000; + timeout.tv_usec = (msecs % 1000) * 1000; + + // timeout can not be 0 or else select will return an error + if (msecs == 0) + timeout.tv_usec = 1000; + + int result = -1; + // on Linux timeout will be updated by select, but _not_ on other systems + result = ::select(nfds + 1, &rfds, 0, 0, &timeout); + if (result == -1 && errno != EINTR) + return false; + + foreach (const WatchNotifier &watchNotifier, m_watchNotifiers) { + if (FD_ISSET(watchNotifier.readNotifier->socket(), &rfds)) { + QMetaObject::invokeMethod(watchNotifier.readNotifier, "activated", + Q_ARG(int, watchNotifier.readNotifier->socket())); + } + } + + return true; +} + + +SocketRequestor::SocketRequestor(const QString &adaptor, QObject *parent) +: QObject(parent), m_adaptor(adaptor) +{ + + +} + +SocketRequestor::~SocketRequestor() +{ +} + +void SocketRequestor::requestAccess(const QString &path, const QString &kind) +{ + SocketRequestorPrivate *s = socketRequestorPrivate(); + + s->registerObject(path, this); + + QMetaObject::invokeMethod(s, "sendRequestAccess", Qt::QueuedConnection, + Q_ARG(QString, m_adaptor), Q_ARG(QString, path), + Q_ARG(QString, kind)); +} + +void SocketRequestor::cancelAccessRequest(const QString &path, const QString &kind) +{ + SocketRequestorPrivate *s = socketRequestorPrivate(); + + s->unregisterObject(path); + + QMetaObject::invokeMethod(s, "sendCancelAccessRequest", Qt::QueuedConnection, + Q_ARG(QString, m_adaptor), Q_ARG(QString, path), + Q_ARG(QString, kind)); +} + +bool SocketRequestor::waitForDBusSignal(int msecs) +{ + SocketRequestorPrivate *s = socketRequestorPrivate(); + + // Send queued method calls, i.e. requestAccess() and cancelAccessRequest(). + QCoreApplication::sendPostedEvents(s, QEvent::MetaCall); + + // Wait for DBus signal. + bool result = socketRequestorPrivate()->waitForDBusSignal(msecs); + + // Send queued method calls, i.e. those from DBus. + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); + + return result; +} + +#include <moc_socketrequestor_p.cpp> +#include <socketrequestor.moc> diff --git a/src/nfc/maemo6/socketrequestor_p.h b/src/nfc/maemo6/socketrequestor_p.h new file mode 100644 index 00000000..25c46865 --- /dev/null +++ b/src/nfc/maemo6/socketrequestor_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + The private API defined in this file is temporary. It should be removed when Qt can handle + passing unix file descriptors over DBus. Most likely in Qt 4.8. +*/ + +#ifndef SOCKETREQUESTOR_P_H +#define SOCKETREQUESTOR_P_H + +#include <qconnectivityglobal.h> + +#include <QtCore/QObject> +#include <QtCore/QVariantMap> + +QT_FORWARD_DECLARE_CLASS(QDBusObjectPath) +QT_FORWARD_DECLARE_CLASS(QDBusVariant) + +class DBusConnection; + +QT_BEGIN_HEADER + +class SocketRequestor : public QObject +{ + Q_OBJECT + +public: + explicit SocketRequestor(const QString &adaptor, QObject *parent = 0); + ~SocketRequestor(); + + void requestAccess(const QString &path, const QString &kind); + void cancelAccessRequest(const QString &path, const QString &kind); + + bool waitForDBusSignal(int msecs); + +signals: + void accessFailed(const QDBusObjectPath &targetPath, const QString &kind, + const QString &error); + void accessGranted(const QDBusObjectPath &targetPath, const QString &accessKind); + + void accept(const QDBusVariant &lsap, const QDBusVariant &rsap, int fd, const QVariantMap &properties); + void connect(const QDBusVariant &lsap, const QDBusVariant &rsap, int fd, const QVariantMap &properties); + void socket(const QDBusVariant &lsap, int fd, const QVariantMap &properties); + +private: + const QString m_adaptor; +}; + +QT_END_HEADER + +#endif // SOCKETREQUESTOR_P_H diff --git a/src/nfc/maemo6/tag_interface.cpp b/src/nfc/maemo6/tag_interface.cpp new file mode 100644 index 00000000..61f3b05c --- /dev/null +++ b/src/nfc/maemo6/tag_interface.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p tag_interface_p.h:tag_interface.cpp com.nokia.nfc.Tag.xml + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "tag_interface_p.h" + +/* + * Implementation of interface class ComNokiaNfcTagInterface + */ + +ComNokiaNfcTagInterface::ComNokiaNfcTagInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +ComNokiaNfcTagInterface::~ComNokiaNfcTagInterface() +{ +} + diff --git a/src/nfc/maemo6/tag_interface_p.h b/src/nfc/maemo6/tag_interface_p.h new file mode 100644 index 00000000..f7bdec57 --- /dev/null +++ b/src/nfc/maemo6/tag_interface_p.h @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 and then hand edited + * Command line was: qdbusxml2cpp -p tag_interface_p.h:tag_interface.cpp com.nokia.nfc.Tag.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + */ + +#ifndef TAG_INTERFACE_P_H +#define TAG_INTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +Q_DECLARE_METATYPE(QList<QByteArray>) + +/* + * Proxy class for interface com.nokia.nfc.Tag + */ +class ComNokiaNfcTagInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "com.nokia.nfc.Tag"; } + +public: + ComNokiaNfcTagInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~ComNokiaNfcTagInterface(); + + Q_PROPERTY(uint Size READ size) + inline uint size() + { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return 0; + + return reply.value().value(QLatin1String("Size")).toUInt(); + } + + Q_PROPERTY(QString Technology READ technology) + inline QString technology() + { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return QString(); + + return reply.value().value(QLatin1String("Technology")).toString(); + } + + Q_PROPERTY(QString UID READ uID) + inline QString uID() + { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return QString(); + + return reply.value().value(QLatin1String("UID")).toString(); + } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<QVariantMap> GetProperties() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + } + + inline QDBusPendingReply<QList<QByteArray> > ReadNDEFData() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("ReadNDEFData"), argumentList); + } + + inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList); + } + + inline QDBusPendingReply<> WriteNDEFData(const QList<QByteArray> &in0) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QLatin1String("WriteNDEFData"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void PropertyChanged(const QString &in0, const QDBusVariant &in1); +}; + +namespace com { + namespace nokia { + namespace nfc { + typedef ::ComNokiaNfcTagInterface Tag; + } + } +} +#endif diff --git a/src/nfc/maemo6/target_interface.cpp b/src/nfc/maemo6/target_interface.cpp new file mode 100644 index 00000000..ce64a6f2 --- /dev/null +++ b/src/nfc/maemo6/target_interface.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -p target_interface_p.h:target_interface.cpp com.nokia.nfc.Target.xml + * + * qdbusxml2cpp is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "target_interface_p.h" + +/* + * Implementation of interface class ComNokiaNfcTargetInterface + */ + +ComNokiaNfcTargetInterface::ComNokiaNfcTargetInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +ComNokiaNfcTargetInterface::~ComNokiaNfcTargetInterface() +{ +} + diff --git a/src/nfc/maemo6/target_interface_p.h b/src/nfc/maemo6/target_interface_p.h new file mode 100644 index 00000000..a4a7dced --- /dev/null +++ b/src/nfc/maemo6/target_interface_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 and then hand edited + * Command line was: qdbusxml2cpp -p target_interface_p.h:target_interface.cpp com.nokia.nfc.Target.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + */ + +#ifndef TARGET_INTERFACE_P_H +#define TARGET_INTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface com.nokia.nfc.Target + */ +class ComNokiaNfcTargetInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "com.nokia.nfc.Target"; } + +public: + ComNokiaNfcTargetInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~ComNokiaNfcTargetInterface(); + + Q_PROPERTY(QString State READ state) + inline QString state() + { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return QString(); + + return reply.value().value(QLatin1String("State")).toString(); + } + + Q_PROPERTY(QString Type READ type) + inline QString type() + { + QDBusReply<QVariantMap> reply = GetProperties(); + if (!reply.isValid()) + return QString(); + + return reply.value().value(QLatin1String("Type")).toString(); + } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<QVariantMap> GetProperties() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + } + + inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void PropertyChanged(const QString &in0, const QDBusVariant &in1); +}; + +namespace com { + namespace nokia { + namespace nfc { + typedef ::ComNokiaNfcTargetInterface Target; + } + } +} +#endif diff --git a/src/nfc/nfc.pro b/src/nfc/nfc.pro new file mode 100644 index 00000000..2616e096 --- /dev/null +++ b/src/nfc/nfc.pro @@ -0,0 +1,210 @@ +load(qt_module) + +TARGET = QtNfc +QPRO_PWD = $PWD + +CONFIG += module +MODULE_PRI = ../../modules/qt_nfc.pri + +QT = core + +DEFINES += QT_BUILD_NFC_LIB QT_MAKEDLL + +load(qt_module_config) + +PUBLIC_HEADERS += \ + qnearfieldmanager.h \ + qnearfieldtarget.h \ + qndefrecord.h \ + qndefnfctextrecord.h \ + qndefmessage.h \ + qndeffilter.h \ + qndefnfcurirecord.h \ + qnearfieldtagtype1.h \ + qnearfieldtagtype2.h \ + qllcpsocket.h \ + qnearfieldtagtype3.h \ + qnearfieldtagtype4.h \ + qllcpserver.h \ + qdeclarativendefrecord.h + +PRIVATE_HEADERS += \ + qndefrecord_p.h \ + qnearfieldtarget_p.h \ + qnearfieldmanager_p.h \ + qtlv_p.h \ + checksum_p.h + +SOURCES += \ + qnearfieldmanager.cpp \ + qnearfieldtarget.cpp \ + qndefrecord.cpp \ + qndefnfctextrecord.cpp \ + qndefmessage.cpp \ + qndeffilter.cpp \ + qndefnfcurirecord.cpp \ + qnearfieldtagtype1.cpp \ + qnearfieldtagtype2.cpp \ + qnearfieldtagtype3.cpp \ + qllcpsocket.cpp \ + qnearfieldtagtype4.cpp \ + qtlv.cpp \ + qllcpserver.cpp \ + qdeclarativendefrecord.cpp + +maemo6|meego { + NFC_BACKEND_AVAILABLE = yes + + QT *= dbus + + DBUS_INTERFACES += \ + maemo6/com.nokia.nfc.Manager.xml + + DBUS_ADAPTORS += \ + maemo6/com.nokia.nfc.AccessRequestor.xml \ + maemo6/com.nokia.nfc.NDEFHandler.xml + + # work around bug in Qt + dbus_interface_source.depends = ${QMAKE_FILE_OUT_BASE}.h + dbus_adaptor_source.depends = ${QMAKE_FILE_OUT_BASE}.h + + # Link against libdbus until Qt has support for passing file descriptors over DBus. + CONFIG += link_pkgconfig + DEFINES += DBUS_API_SUBJECT_TO_CHANGE + PKGCONFIG += dbus-1 + + PRIVATE_HEADERS += \ + qnearfieldmanager_maemo6_p.h \ + qnearfieldtarget_maemo6_p.h \ + qllcpsocket_maemo6_p.h \ + qllcpserver_maemo6_p.h \ + maemo6/adapter_interface_p.h \ + maemo6/target_interface_p.h \ + maemo6/tag_interface_p.h \ + maemo6/device_interface_p.h \ + maemo6/socketrequestor_p.h + + SOURCES += \ + qnearfieldmanager_maemo6.cpp \ + qnearfieldtarget_maemo6.cpp \ + qllcpsocket_maemo6_p.cpp \ + qllcpserver_maemo6_p.cpp \ + maemo6/adapter_interface.cpp \ + maemo6/target_interface.cpp \ + maemo6/tag_interface.cpp \ + maemo6/device_interface.cpp \ + maemo6/socketrequestor.cpp + + OTHER_FILES += \ + $$DBUS_INTERFACES \ + $$DBUS_ADAPTORS \ + maemo6/com.nokia.nfc.Adapter.xml \ + maemo6/com.nokia.nfc.Target.xml \ + maemo6/com.nokia.nfc.Tag.xml \ + maemo6/com.nokia.nfc.Device.xml \ + maemo6/com.nokia.nfc.LLCPRequestor.xml + + # Add OUT_PWD to INCLUDEPATH so that creator picks up headers for generated files + # This is not needed for the build otherwise. + INCLUDEPATH += $$OUT_PWD +} + +simulator { + NFC_BACKEND_AVAILABLE = yes + + QT *= gui + + PRIVATE_HEADERS += \ + qnearfieldmanagervirtualbase_p.h \ + qnearfieldmanager_simulator_p.h \ + qllcpsocket_simulator_p.h \ + qllcpserver_simulator_p.h + + SOURCES += \ + qnearfieldmanagervirtualbase.cpp \ + qnearfieldmanager_simulator.cpp \ + qllcpsocket_simulator_p.cpp \ + qllcpserver_simulator_p.cpp +} + +contains(nfc_symbian_enabled, yes):symbian { + NFC_BACKEND_AVAILABLE = yes + + QT += serviceframework + + PRIVATE_HEADERS += \ + qnearfieldmanager_symbian_p.h \ + qnearfieldtagtype1_symbian_p.h \ + qnearfieldtagtype2_symbian_p.h \ + qllcpsocket_symbian_p.h \ + qllcpserver_symbian_p.h \ + qllcpstate_symbian_p.h \ + qnearfieldtagtype3_symbian_p.h \ + qnearfieldtagtype4_symbian_p.h \ + qnearfieldtagmifare_symbian_p.h \ + qnearfieldllcpdevice_symbian_p.h \ + symbian/nearfieldmanager_symbian.h \ + symbian/nearfieldtag_symbian.h \ + symbian/nearfieldndeftarget_symbian.h \ + symbian/nearfieldtargetfactory_symbian.h \ + symbian/nearfieldutility_symbian.h \ + symbian/llcpserver_symbian.h \ + symbian/llcpsockettype1_symbian.h \ + symbian/llcpsockettype2_symbian.h \ + symbian/nearfieldtagimpl_symbian.h \ + symbian/nearfieldtagasyncrequest_symbian.h \ + symbian/nearfieldtagndefoperationcallback_symbian.h \ + symbian/nearfieldtagoperationcallback_symbian.h \ + symbian/nearfieldtagndefrequest_symbian.h \ + symbian/nearfieldtagcommandrequest_symbian.h \ + symbian/nearfieldtagcommandsrequest_symbian.h \ + symbian/debug.h \ + symbian/nearfieldtagimplcommon_symbian.h + + SOURCES += \ + qnearfieldmanager_symbian.cpp \ + qnearfieldtagtype1_symbian.cpp \ + qnearfieldtagtype2_symbian.cpp \ + qllcpsocket_symbian_p.cpp \ + qllcpserver_symbian_p.cpp \ + qllcpstate_symbian_p.cpp \ + qnearfieldtagtype3_symbian.cpp \ + qnearfieldtagtype4_symbian.cpp \ + qnearfieldtagmifare_symbian.cpp \ + qnearfieldllcpdevice_symbian.cpp \ + symbian/nearfieldmanager_symbian.cpp \ + symbian/nearfieldtag_symbian.cpp \ + symbian/nearfieldndeftarget_symbian.cpp \ + symbian/nearfieldtargetfactory_symbian.cpp \ + symbian/nearfieldutility_symbian.cpp \ + symbian/llcpserver_symbian.cpp \ + symbian/llcpsockettype1_symbian.cpp \ + symbian/llcpsockettype2_symbian.cpp \ + symbian/nearfieldtagasyncrequest_symbian.cpp \ + symbian/nearfieldtagndefrequest_symbian.cpp \ + symbian/nearfieldtagcommandrequest_symbian.cpp \ + symbian/nearfieldtagcommandsrequest_symbian.cpp \ + symbian/nearfieldtagimplcommon_symbian.cpp + + INCLUDEPATH += $${EPOCROOT}epoc32/include/mw + + LIBS += -lnfc -lndef -lndefaccess -lnfcdiscoveryservice -lllcp -lnfctagextension +} + +isEmpty(NFC_BACKEND_AVAILABLE) { + # unsupported platform stub + + PRIVATE_HEADERS += \ + qllcpsocket_p.h \ + qllcpserver_p.h \ + qnearfieldmanagerimpl_p.h + + SOURCES += \ + qllcpsocket_p.cpp \ + qllcpserver_p.cpp \ + qnearfieldmanagerimpl_p.cpp +} + +INCLUDEPATH += $$PWD + +HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS diff --git a/src/nfc/qdeclarativendefrecord.cpp b/src/nfc/qdeclarativendefrecord.cpp new file mode 100644 index 00000000..6b974084 --- /dev/null +++ b/src/nfc/qdeclarativendefrecord.cpp @@ -0,0 +1,272 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativendefrecord.h" + +#include <QtCore/QMap> +#include <QtCore/QRegExp> + +/*! + \class QDeclarativeNdefRecord + \brief The QDeclarativeNdefRecord class implements the NdefRecord element in QML. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + \sa NdefRecord + + The QDeclarativeNdefRecord class is the base class for all NdefRecord elements in QML. To + support a new NDEF record type in QML subclass this class and expose new properties, member + functions and signals appropriate for the new record type. The following must be done to + create a new NDEF record type in QML: + + \list + \o The subclass must have a Q_OBJECT macro in its declaration. + \o The subclass must have an \l {Q_INVOKABLE}{invokable} constructor that takes a + QNdefRecord and a QObject pointer. + \o The subclass must be declared as an NDEF record by expanding the Q_DECLARE_NDEFRECORD() + macro in the implementation file of the subclass. + \o The subclass must be registered with QML. + \endlist + + For example the declaration of such a class may look like the following. + + \snippet snippets/connectivity/foorecord.h Foo declaration + + Within the implementation file the Q_DECLARE_NDEFRECORD() macro is expanded: + + \snippet snippets/connectivity/foorecord.cpp Declare foo record + + Finially the application or plugin code calls qmlRegisterType(): + + \code + qmlRegisterType<QDeclarativeNdefFooRecord>(uri, 1, 0, "NdefFooRecord"); + \endcode +*/ + +/*! + \qmlclass NdefRecord QDeclarativeNdefRecord + \brief The NdefRecord element represents a record in an NDEF message. + + \ingroup connectivity-qml + \inmodule QtConnectivity + + \sa NdefFilter + \sa NearField + + \sa QNdefRecord + + The NdefRecord element is the base element for all NDEF record elements in QML. It contains + a single property holding the type of record. + + This class is not intended to be used directly, but extended from C++. + + \sa QDeclarativeNdefRecord +*/ + +/*! + \qmlproperty string NdefRecord::recordType + + This property holds the fully qualified record type of the NDEF record. The fully qualified + record type includes the NIS and NSS prefixes. +*/ + +/*! + \fn void QDeclarativeNdefRecord::recordTypeChanged() + + This signal is emitted when the record type changes. +*/ + +/*! + \property QDeclarativeNdefRecord::recordType + + This property hold the record type of the NDEF record that this class represents. +*/ + +/*! + \macro Q_DECLARE_NDEFRECORD(className, typeNameFormat, type) + \relates QDeclarativeNdefRecord + + This macro ensures that \a className is declared as the class implementing the NDEF record + identified by \a typeNameFormat and \a type. + + This macro should be expanded in the implementation file for \a className. +*/ + +static QMap<QString, const QMetaObject *> registeredNdefRecordTypes; + +class QDeclarativeNdefRecordPrivate +{ +public: + QNdefRecord record; +}; + +static QString urnForRecordType(QNdefRecord::TypeNameFormat typeNameFormat, const QByteArray &type) +{ + switch (typeNameFormat) { + case QNdefRecord::NfcRtd: + return QLatin1String("urn:nfc:wkt:") + type; + case QNdefRecord::ExternalRtd: + return QLatin1String("urn:nfc:ext:") + type; + case QNdefRecord::Mime: + return QLatin1String("urn:nfc:mime:") + type; + default: + return QString(); + } +} + +/*! + \internal +*/ +void qRegisterNdefRecordTypeHelper(const QMetaObject *metaObject, + QNdefRecord::TypeNameFormat typeNameFormat, + const QByteArray &type) +{ + registeredNdefRecordTypes.insert(urnForRecordType(typeNameFormat, type), metaObject); +} + +/*! + \internal +*/ +QDeclarativeNdefRecord *qNewDeclarativeNdefRecordForNdefRecord(const QNdefRecord &record) +{ + const QString urn = urnForRecordType(record.typeNameFormat(), record.type()); + + QMapIterator<QString, const QMetaObject *> i(registeredNdefRecordTypes); + while (i.hasNext()) { + i.next(); + + QRegExp ex(i.key()); + if (!ex.exactMatch(urn)) + continue; + + const QMetaObject *metaObject = i.value(); + if (!metaObject) + continue; + + return static_cast<QDeclarativeNdefRecord *>(metaObject->newInstance( + Q_ARG(QNdefRecord, record), Q_ARG(QObject *, 0))); + } + + return new QDeclarativeNdefRecord(record); +} + +/*! + Constructs a new empty QDeclarativeNdefRecord with \a parent. +*/ +QDeclarativeNdefRecord::QDeclarativeNdefRecord(QObject *parent) +: QObject(parent), d_ptr(new QDeclarativeNdefRecordPrivate) +{ +} + +/*! + Constructs a new QDeclarativeNdefRecord representing \a record. The parent of the newly + constructed object will be set to \a parent. +*/ +QDeclarativeNdefRecord::QDeclarativeNdefRecord(const QNdefRecord &record, QObject *parent) +: QObject(parent), d_ptr(new QDeclarativeNdefRecordPrivate) +{ + d_ptr->record = record; +} + +/*! + Returns the fully qualified record type of the record. The fully qualified record type + includes both the NIS and NSS prefixes. +*/ +QString QDeclarativeNdefRecord::recordType() const +{ + Q_D(const QDeclarativeNdefRecord); + + if (d->record.typeNameFormat() == QNdefRecord::Empty) + return QString(); + + return urnForRecordType(d->record.typeNameFormat(), d->record.type()); +} + +/*! + Sets the record type to \a type if it is not currently equal to \a type; otherwise does + nothing. If the record type is set the recordTypeChanged() signal will be emitted. +*/ +void QDeclarativeNdefRecord::setRecordType(const QString &type) +{ + if (type == recordType()) + return; + + Q_D(QDeclarativeNdefRecord); + + if (type.startsWith(QLatin1String("urn:nfc:wkt:"))) { + d->record.setTypeNameFormat(QNdefRecord::NfcRtd); + d->record.setType(type.mid(12).toUtf8()); + } else if (type.startsWith(QLatin1String("urn:nfc:ext:"))) { + d->record.setTypeNameFormat(QNdefRecord::ExternalRtd); + d->record.setType(type.mid(12).toUtf8()); + } else if (type.startsWith(QLatin1String("urn:nfc:mime:"))) { + d->record.setTypeNameFormat(QNdefRecord::Mime); + d->record.setType(type.mid(13).toUtf8()); + } else { + qWarning("Don't know how to decode NDEF type %s\n", qPrintable(type)); + } + + emit recordTypeChanged(); +} + +/*! + Returns a copy of the record. +*/ +QNdefRecord QDeclarativeNdefRecord::record() const +{ + Q_D(const QDeclarativeNdefRecord); + + return d->record; +} + +/*! + Sets the record to \a record. +*/ +void QDeclarativeNdefRecord::setRecord(const QNdefRecord &record) +{ + Q_D(QDeclarativeNdefRecord); + + d->record = record; +} + +#include "moc_qdeclarativendefrecord.cpp" diff --git a/src/nfc/qdeclarativendefrecord.h b/src/nfc/qdeclarativendefrecord.h new file mode 100644 index 00000000..8448b196 --- /dev/null +++ b/src/nfc/qdeclarativendefrecord.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVENDEFRECORD_P_H +#define QDECLARATIVENDEFRECORD_P_H + +#include <QtCore/QObject> +#include <QtCore/QMetaType> + +#include <qndefrecord.h> + +QT_BEGIN_HEADER + +class QDeclarativeNdefRecordPrivate; + +class Q_CONNECTIVITY_EXPORT QDeclarativeNdefRecord : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeNdefRecord) + + Q_PROPERTY(QString recordType READ recordType WRITE setRecordType NOTIFY recordTypeChanged) + +public: + explicit QDeclarativeNdefRecord(QObject *parent = 0); + explicit QDeclarativeNdefRecord(const QNdefRecord &record, QObject *parent = 0); + + QString recordType() const; + void setRecordType(const QString &t); + + QNdefRecord record() const; + void setRecord(const QNdefRecord &record); + +signals: + void recordTypeChanged(); + +private: + QDeclarativeNdefRecordPrivate *d_ptr; +}; + +void Q_CONNECTIVITY_EXPORT qRegisterNdefRecordTypeHelper(const QMetaObject *metaObject, + QNdefRecord::TypeNameFormat typeNameFormat, + const QByteArray &type); + +Q_CONNECTIVITY_EXPORT QDeclarativeNdefRecord *qNewDeclarativeNdefRecordForNdefRecord(const QNdefRecord &record); + +template<typename T> +bool qRegisterNdefRecordType(QNdefRecord::TypeNameFormat typeNameFormat, const QByteArray &type) +{ + qRegisterNdefRecordTypeHelper(&T::staticMetaObject, typeNameFormat, type); + return true; +} + +#define Q_DECLARE_NDEFRECORD(className, typeNameFormat, type) \ +static bool _q_##className##_registered = qRegisterNdefRecordType<className>(typeNameFormat, type); + +QT_END_HEADER + +#endif // QDECLARATIVENDEFRECORD_P_H diff --git a/src/nfc/qllcpserver.cpp b/src/nfc/qllcpserver.cpp new file mode 100644 index 00000000..f7f165e6 --- /dev/null +++ b/src/nfc/qllcpserver.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpserver.h" + +#if defined(QT_SIMULATOR) +#include "qllcpserver_simulator_p.h" +#elif defined(Q_OS_SYMBIAN) +#include "qllcpserver_symbian_p.h" +#elif defined(Q_WS_MAEMO_6) || defined(Q_WS_MEEGO) +#include "qllcpserver_maemo6_p.h" +#else +#include "qllcpserver_p.h" +#endif + +/*! + \class QLlcpServer + \brief The QLlcpServer class provides an NFC LLCP socket based server. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + This class makes it possible to accept incoming LLCP socket connections. + + Call listen() to have the server start listening for incoming connections on a specified port. + The newConnection() signal is then emitted each time a client connects to the server. + + Call nextPendingConnection() to accept the pending connection as a connected QLlcpSocket. The + function returns a pointer to a QLlcpSocket that can be used for communicating with the client. + + If an error occurs, serverError() returns the type of error, and errorString() can be called to + get a human readable description of what happened. + + When listening for connections, the port which the server is listening on is available through + serverPort(). + + Calling close() makes QLlcpServer stop listening for incoming connections. +*/ + +/*! + \fn QLlcpServer::newConnection() + + This signal is emitted every time a new connection is available. + + \sa hasPendingConnections(), nextPendingConnection() +*/ + +/*! + Constructs a new NFC LLCP server with \a parent. +*/ +QLlcpServer::QLlcpServer(QObject *parent) +: QObject(parent), d_ptr(new QLlcpServerPrivate(this)) +{ +} + +/*! + Destroys the NFC LLCP server. +*/ +QLlcpServer::~QLlcpServer() +{ + delete d_ptr; +} + +/*! + Tells the server to listen for incoming connections on \a serviceUri. If the server is + currently listening then it will return false. Returns true on success; otherwise returns + false. + + serviceUri() will return the \a serviceUri that is passed into listen. + + serverPort() will return the port that is assigned to the server. + + \sa serverPort(), isListening(), close() +*/ +bool QLlcpServer::listen(const QString &serviceUri) +{ + Q_D(QLlcpServer); + + return d->listen(serviceUri); +} + +/*! + Returns true if the server is listening for incoming connections; otherwise returns false. +*/ +bool QLlcpServer::isListening() const +{ + Q_D(const QLlcpServer); + + return d->isListening(); +} + +/*! + Stops listening for incoming connections. +*/ +void QLlcpServer::close() +{ + Q_D(QLlcpServer); + + d->close(); +} + +/*! + Returns the LLCP service URI that the server is listening on. +*/ +QString QLlcpServer::serviceUri() const +{ + Q_D(const QLlcpServer); + + return d->serviceUri(); +} + +/*! + Returns the LLCP port associated with the service URI that the server is listening on. + + \note This call is not supported on all platforms and will return 0 on these platforms. +*/ +quint8 QLlcpServer::serverPort() const +{ + Q_D(const QLlcpServer); + + return d->serverPort(); +} + +/*! + Returns true if the server has a pending connection; otherwise returns false. + + \sa nextPendingConnection() +*/ +bool QLlcpServer::hasPendingConnections() const +{ + Q_D(const QLlcpServer); + + return d->hasPendingConnections(); +} + +/*! + Returns the next pending connection as a connected QLlcpSocket object. + + The socket is created as a child of the server, which means that it is automatically deleted + when the QLlcpServer object is destroyed. It is still a good idea to delete the object + explicitly when you are done with it, to avoid wasting memory. + + 0 is returned if this function is called when there are no pending connections. + + \sa hasPendingConnections(), newConnection() +*/ +QLlcpSocket *QLlcpServer::nextPendingConnection() +{ + Q_D(QLlcpServer); + + return d->nextPendingConnection(); +} + +/*! + Returns the last error that occurred. +*/ +QLlcpSocket::SocketError QLlcpServer::serverError() const +{ + Q_D(const QLlcpServer); + + return d->serverError(); +} + +#include "moc_qllcpserver.cpp" diff --git a/src/nfc/qllcpserver.h b/src/nfc/qllcpserver.h new file mode 100644 index 00000000..7a43b237 --- /dev/null +++ b/src/nfc/qllcpserver.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSERVER_H +#define QLLCPSERVER_H + +#include "../qtconnectivityglobal.h" + +#include <qllcpsocket.h> + +#include <QtCore/QObject> + +QT_BEGIN_HEADER + +class QLlcpServerPrivate; + +class Q_CONNECTIVITY_EXPORT QLlcpServer : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QLlcpServer) + +public: + explicit QLlcpServer(QObject *parent = 0); + virtual ~QLlcpServer(); + + bool listen(const QString &serviceUri); + bool isListening() const; + + void close(); + + QString serviceUri() const; + quint8 serverPort() const; + + virtual bool hasPendingConnections() const; + virtual QLlcpSocket *nextPendingConnection(); + + QLlcpSocket::SocketError serverError() const; + +Q_SIGNALS: + void newConnection(); + +private: + QLlcpServerPrivate *d_ptr; +}; + +QT_END_HEADER + +#endif // QLLCPSERVER_H diff --git a/src/nfc/qllcpserver_maemo6_p.cpp b/src/nfc/qllcpserver_maemo6_p.cpp new file mode 100644 index 00000000..2b964bc1 --- /dev/null +++ b/src/nfc/qllcpserver_maemo6_p.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpserver_maemo6_p.h" + +#include "manager_interface.h" +#include "maemo6/adapter_interface_p.h" +#include "qllcpsocket_maemo6_p.h" +#include "maemo6/socketrequestor_p.h" + +using namespace com::nokia::nfc; + +static QAtomicInt requestorId = 0; +static const char * const requestorBasePath = "/com/nokia/nfc/llcpserver/"; + +QLlcpServerPrivate::QLlcpServerPrivate(QLlcpServer *q) +: q_ptr(q), + m_connection(QDBusConnection::connectToBus(QDBusConnection::SystemBus, QUuid::createUuid())), + m_socketRequestor(0) +{ +} + +bool QLlcpServerPrivate::listen(const QString &serviceUri) +{ + if (m_requestorPath.isEmpty()) { + m_requestorPath = QLatin1String(requestorBasePath) + + QString::number(requestorId.fetchAndAddOrdered(1)); + } + + Manager manager(QLatin1String("com.nokia.nfc"), QLatin1String("/"), m_connection); + QDBusObjectPath defaultAdapterPath = manager.DefaultAdapter(); + + if (!m_socketRequestor) { + m_socketRequestor = new SocketRequestor(defaultAdapterPath.path(), this); + + connect(m_socketRequestor, SIGNAL(accessFailed(QDBusObjectPath,QString,QString)), + this, SLOT(AccessFailed(QDBusObjectPath,QString,QString))); + connect(m_socketRequestor, SIGNAL(accessGranted(QDBusObjectPath,QString)), + this, SLOT(AccessGranted(QDBusObjectPath,QString))); + connect(m_socketRequestor, SIGNAL(accept(QDBusVariant,QDBusVariant,int,QVariantMap)), + this, SLOT(Accept(QDBusVariant,QDBusVariant,int,QVariantMap))); + connect(m_socketRequestor, SIGNAL(connect(QDBusVariant,QDBusVariant,int,QVariantMap)), + this, SLOT(Connect(QDBusVariant,QDBusVariant,int,QVariantMap))); + connect(m_socketRequestor, SIGNAL(socket(QDBusVariant,int,QVariantMap)), + this, SLOT(Socket(QDBusVariant,int,QVariantMap))); + } + + if (m_socketRequestor) { + QString accessKind(QLatin1String("device.llcp.co.server:") + serviceUri); + m_socketRequestor->requestAccess(m_requestorPath, accessKind); + + m_serviceUri = serviceUri; + } else { + m_error = QLlcpSocket::SocketResourceError; + + m_serviceUri.clear(); + } + + return !m_serviceUri.isEmpty(); +} + +bool QLlcpServerPrivate::isListening() const +{ + return !m_serviceUri.isEmpty(); +} + +void QLlcpServerPrivate::close() +{ + QString accessKind(QLatin1String("device.llcp.co.server:") + m_serviceUri); + + m_socketRequestor->cancelAccessRequest(m_requestorPath, accessKind); + + m_serviceUri.clear(); +} + +QString QLlcpServerPrivate::serviceUri() const +{ + return m_serviceUri; +} + +quint8 QLlcpServerPrivate::serverPort() const +{ + return 0; +} + +bool QLlcpServerPrivate::hasPendingConnections() const +{ + return !m_pendingSockets.isEmpty(); +} + +QLlcpSocket *QLlcpServerPrivate::nextPendingConnection() +{ + if (m_pendingSockets.isEmpty()) + return 0; + + QPair<int, QVariantMap> parameters = m_pendingSockets.takeFirst(); + + QLlcpSocketPrivate *socketPrivate = + new QLlcpSocketPrivate(m_connection, parameters.first, parameters.second); + + QLlcpSocket *socket = new QLlcpSocket(socketPrivate, 0); + + return socket; +} + +QLlcpSocket::SocketError QLlcpServerPrivate::serverError() const +{ + return QLlcpSocket::UnknownSocketError; +} + +void QLlcpServerPrivate::AccessFailed(const QDBusObjectPath &targetPath, const QString &kind, + const QString &error) +{ + Q_UNUSED(targetPath); + Q_UNUSED(kind); + Q_UNUSED(error); + + m_serviceUri.clear(); + + m_error = QLlcpSocket::SocketAccessError; +} + +void QLlcpServerPrivate::AccessGranted(const QDBusObjectPath &targetPath, + const QString &accessKind) +{ + Q_UNUSED(targetPath); + Q_UNUSED(accessKind); +} + +void QLlcpServerPrivate::Accept(const QDBusVariant &lsap, const QDBusVariant &rsap, + int fd, const QVariantMap &properties) +{ + Q_UNUSED(lsap); + Q_UNUSED(rsap); + Q_UNUSED(properties); + + Q_Q(QLlcpServer); + + m_pendingSockets.append(qMakePair(fd, properties)); + + emit q->newConnection(); +} + +void QLlcpServerPrivate::Connect(const QDBusVariant &lsap, const QDBusVariant &rsap, + int readFd, const QVariantMap &properties) +{ + Q_UNUSED(lsap); + Q_UNUSED(rsap); + Q_UNUSED(readFd); + Q_UNUSED(properties); +} + +void QLlcpServerPrivate::Socket(const QDBusVariant &lsap, int fd, const QVariantMap &properties) +{ + Q_UNUSED(lsap); + Q_UNUSED(fd); + Q_UNUSED(properties); +} + +#include "moc_qllcpserver_maemo6_p.cpp" diff --git a/src/nfc/qllcpserver_maemo6_p.h b/src/nfc/qllcpserver_maemo6_p.h new file mode 100644 index 00000000..0543f321 --- /dev/null +++ b/src/nfc/qllcpserver_maemo6_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSERVER_MAEMO6_P_H +#define QLLCPSERVER_MAEMO6_P_H + +#include <qconnectivityglobal.h> + +#include "qllcpserver.h" + +#include <QtDBus/QDBusConnection> + +QT_FORWARD_DECLARE_CLASS(QDBusObjectPath) +QT_FORWARD_DECLARE_CLASS(QDBusVariant) + +class AccessRequestorAdaptor; +class LLCPRequestorAdaptor; + +class SocketRequestor; + +class QLlcpServerPrivate : public QObject +{ + Q_OBJECT + + Q_DECLARE_PUBLIC(QLlcpServer) + +public: + QLlcpServerPrivate(QLlcpServer *q); + + bool listen(const QString &serviceUri); + bool isListening() const; + + void close(); + + QString serviceUri() const; + quint8 serverPort() const; + + bool hasPendingConnections() const; + QLlcpSocket *nextPendingConnection(); + + QLlcpSocket::SocketError serverError() const; + +private slots: + // com.nokia.nfc.AccessRequestor + void AccessFailed(const QDBusObjectPath &targetPath, const QString &kind, + const QString &error); + void AccessGranted(const QDBusObjectPath &targetPath, const QString &accessKind); + + // com.nokia.nfc.LLCPRequestor + void Accept(const QDBusVariant &lsap, const QDBusVariant &rsap, int fd, + const QVariantMap &properties); + void Connect(const QDBusVariant &lsap, const QDBusVariant &rsap, int fd, + const QVariantMap &properties); + void Socket(const QDBusVariant &lsap, int fd, const QVariantMap &properties); + +private: + QLlcpServer *q_ptr; + + QDBusConnection m_connection; + + QString m_serviceUri; + + QString m_requestorPath; + SocketRequestor *m_socketRequestor; + + QList<QPair<int, QVariantMap> > m_pendingSockets; + + QLlcpSocket::SocketError m_error; +}; + +#endif // QLLCPSERVER_MAEMO6_P_H diff --git a/src/nfc/qllcpserver_p.cpp b/src/nfc/qllcpserver_p.cpp new file mode 100644 index 00000000..1e21ee34 --- /dev/null +++ b/src/nfc/qllcpserver_p.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpserver_p.h" + +QLlcpServerPrivate::QLlcpServerPrivate(QLlcpServer *q) +: q_ptr(q) +{ +} + +QLlcpServerPrivate::~QLlcpServerPrivate() +{ +} + +bool QLlcpServerPrivate::listen(const QString &serviceUri) +{ + Q_UNUSED(serviceUri); + + return false; +} + +bool QLlcpServerPrivate::isListening() const +{ + return false; +} + +void QLlcpServerPrivate::close() +{ +} + +QString QLlcpServerPrivate::serviceUri() const +{ + return QString(); +} + +quint8 QLlcpServerPrivate::serverPort() const +{ + return 0; +} + +bool QLlcpServerPrivate::hasPendingConnections() const +{ + return false; +} + +QLlcpSocket *QLlcpServerPrivate::nextPendingConnection() +{ + return 0; +} + +QLlcpSocket::SocketError QLlcpServerPrivate::serverError() const +{ + return QLlcpSocket::UnknownSocketError; +} diff --git a/src/nfc/qllcpserver_p.h b/src/nfc/qllcpserver_p.h new file mode 100644 index 00000000..e0a57ec3 --- /dev/null +++ b/src/nfc/qllcpserver_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSERVER_P_H +#define QLLCPSERVER_P_H + +#include "../qtconnectivityglobal.h" + +#include "qllcpserver.h" + +class QLlcpServerPrivate +{ + Q_DECLARE_PUBLIC(QLlcpServer) + +public: + QLlcpServerPrivate(QLlcpServer *q); + ~QLlcpServerPrivate(); + + bool listen(const QString &serviceUri); + bool isListening() const; + + void close(); + + QString serviceUri() const; + quint8 serverPort() const; + + bool hasPendingConnections() const; + QLlcpSocket *nextPendingConnection(); + + QLlcpSocket::SocketError serverError() const; + +private: + QLlcpServer *q_ptr; +}; + +#endif // QLLCPSERVER_P_H diff --git a/src/nfc/qllcpserver_simulator_p.cpp b/src/nfc/qllcpserver_simulator_p.cpp new file mode 100644 index 00000000..5ef6f963 --- /dev/null +++ b/src/nfc/qllcpserver_simulator_p.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpserver_simulator_p.h" + +QLlcpServerPrivate::QLlcpServerPrivate(QLlcpServer *q) +: q_ptr(q) +{ +} + +bool QLlcpServerPrivate::listen(const QString &serviceUri) +{ + Q_UNUSED(serviceUri); + + return false; +} + +bool QLlcpServerPrivate::isListening() const +{ + return false; +} + +void QLlcpServerPrivate::close() +{ +} + +QString QLlcpServerPrivate::serviceUri() const +{ + return QString(); +} + +quint8 QLlcpServerPrivate::serverPort() const +{ + return 0; +} + +bool QLlcpServerPrivate::hasPendingConnections() const +{ + return false; +} + +QLlcpSocket *QLlcpServerPrivate::nextPendingConnection() +{ + return 0; +} + +QLlcpSocket::SocketError QLlcpServerPrivate::serverError() const +{ + return QLlcpSocket::UnknownSocketError; +} diff --git a/src/nfc/qllcpserver_simulator_p.h b/src/nfc/qllcpserver_simulator_p.h new file mode 100644 index 00000000..dfda5b5d --- /dev/null +++ b/src/nfc/qllcpserver_simulator_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSERVER_P_H +#define QLLCPSERVER_P_H + +#include <qconnectivityglobal.h> + +#include "qllcpserver.h" + +class QLlcpServerPrivate +{ +public: + QLlcpServerPrivate(QLlcpServer *q); + + bool listen(const QString &serviceUri); + bool isListening() const; + + void close(); + + QString serviceUri() const; + quint8 serverPort() const; + + bool hasPendingConnections() const; + QLlcpSocket *nextPendingConnection(); + + QLlcpSocket::SocketError serverError() const; + +private: + QLlcpServer *q_ptr; +}; + +#endif // QLLCPSERVER_P_H diff --git a/src/nfc/qllcpserver_symbian_p.cpp b/src/nfc/qllcpserver_symbian_p.cpp new file mode 100644 index 00000000..4497ae15 --- /dev/null +++ b/src/nfc/qllcpserver_symbian_p.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpserver_symbian_p.h" +#include "symbian/llcpserver_symbian.h" +#include "symbian/llcpsockettype2_symbian.h" +#include "symbian/nearfieldutility_symbian.h" + +#include "symbian/debug.h" + +QLlcpServerPrivate::QLlcpServerPrivate(QLlcpServer *q) + :q_ptr(q) +{ + BEGIN + QT_TRAP_THROWING(m_symbianbackend = CLlcpServer::NewL(*this)); + END +} +QLlcpServerPrivate::~QLlcpServerPrivate() +{ + BEGIN + close(); + delete m_symbianbackend; + END +} + +bool QLlcpServerPrivate::listen(const QString &serviceUri) +{ + BEGIN + LOG(serviceUri); + HBufC8* uri = NULL; + TRAPD(err, uri = QNFCNdefUtility::QString2HBufC8L(serviceUri)); + if(err != KErrNone) + { + return false; + } + bool ret = m_symbianbackend->Listen(*uri); + + delete uri; + END + return ret; +} + +bool QLlcpServerPrivate::isListening() const +{ + BEGIN + END + return m_symbianbackend->isListening(); +} + +/*! + Stops listening for incoming connections. +*/ +void QLlcpServerPrivate::close() +{ + BEGIN + m_symbianbackend->StopListening(); + qDeleteAll(m_pendingConnections); + m_pendingConnections.clear(); + END +} + +QString QLlcpServerPrivate::serviceUri() const +{ + BEGIN + const TDesC8& uri= m_symbianbackend->serviceUri(); + + QString ret = QNFCNdefUtility::TDesC82QStringL(uri); + LOG("QLlcpServerPrivate::serviceUri() ret="<<ret); + END + return ret; + +} + +quint8 QLlcpServerPrivate::serverPort() const +{ + BEGIN + END + return 0; +} + +bool QLlcpServerPrivate::hasPendingConnections() const +{ + BEGIN + END + return m_symbianbackend->hasPendingConnections(); +} + +void QLlcpServerPrivate::invokeNewConnection() +{ + BEGIN + Q_Q(QLlcpServer); + emit q->newConnection(); + END +} + +QLlcpSocket *QLlcpServerPrivate::nextPendingConnection() +{ + BEGIN + QLlcpSocket* qSocket = NULL; + CLlcpSocketType2* socket_symbian = m_symbianbackend->nextPendingConnection(); + if (socket_symbian) + { + QLlcpSocketPrivate *qSocket_p = new QLlcpSocketPrivate(socket_symbian); + qSocket = new QLlcpSocket(qSocket_p,NULL); + qSocket_p->attachCallbackHandler(qSocket); + socket_symbian->AttachCallbackHandler(qSocket_p); + QPointer<QLlcpSocket> p(qSocket); + m_pendingConnections.append(p); + } + END + return qSocket; +} + +QLlcpSocket::SocketError QLlcpServerPrivate::serverError() const +{ + BEGIN + END + return QLlcpSocket::UnknownSocketError; +} + +//EOF + diff --git a/src/nfc/qllcpserver_symbian_p.h b/src/nfc/qllcpserver_symbian_p.h new file mode 100644 index 00000000..e8d67654 --- /dev/null +++ b/src/nfc/qllcpserver_symbian_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSERVER_SYMBIAN_P_H +#define QLLCPSERVER_SYMBIAN_P_H + +#include <qconnectivityglobal.h> +#include "qllcpserver.h" +#include <QList> +#include <QPointer> + +class CLlcpServer; +class CLlcpSocketType2; +class QLlcpSocket; + +QT_BEGIN_HEADER + +class QLlcpServerPrivate +{ + Q_DECLARE_PUBLIC(QLlcpServer) +public: + QLlcpServerPrivate(QLlcpServer *q); + ~QLlcpServerPrivate(); + + bool listen(const QString &serviceUri); + bool isListening() const; + + void close(); + + QString serviceUri() const; + quint8 serverPort() const; + + bool hasPendingConnections() const; + QLlcpSocket *nextPendingConnection(); + QLlcpSocket::SocketError serverError() const; + +public: + void invokeNewConnection(); + +private: + CLlcpServer* m_symbianbackend; + QLlcpServer *q_ptr; + QList<QPointer<QLlcpSocket> > m_pendingConnections; +}; + +QT_END_HEADER + +#endif // QLLCPSERVER_P_H diff --git a/src/nfc/qllcpsocket.cpp b/src/nfc/qllcpsocket.cpp new file mode 100644 index 00000000..5b7e9e65 --- /dev/null +++ b/src/nfc/qllcpsocket.cpp @@ -0,0 +1,404 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpsocket.h" + +#if defined(QT_SIMULATOR) +#include "qllcpsocket_simulator_p.h" +#elif defined(Q_OS_SYMBIAN) +#include "qllcpsocket_symbian_p.h" +#elif defined(Q_WS_MAEMO_6) || defined(Q_WS_MEEGO) +#include "qllcpsocket_maemo6_p.h" +#else +#include "qllcpsocket_p.h" +#endif + +/*! + \class QLlcpSocket + \brief The QLlcpSocket class provides an NFC LLCP socket. + \since 5.0 + + \ingroup connectivity-nfc + \inmodule QtConnectivity + + NFC LLCP protocol is a peer-to-peer communication protocol between two NFC compliant devices. +*/ + +/*! + \enum QLlcpSocket::SocketError + + This enum describes the errors that can occur. The most recent error can be retrieved through a + call to error(). + + \value UnknownSocketError An unidentified error has occurred. + \value RemoteHostClosedError The remote host closed the connection. + \value SocketAccessError The socket operation failed because the application lacked the + required privileges. + \value SocketResourceError The local system ran out of resources (e.g., too many sockets). +*/ + +/*! + \enum QLlcpSocket::SocketState + + This enum describes the different state in which a socket can be. + + \value UnconnectedState The socket is not connected. + \value ConnectingState The socket has started establishing a connection. + \value ConnectedState A connection is established. + \value ClosingState The socket is about to close. + \value BoundState The socket is bound to a local port (for servers). + \value ListeningState The socket is listening for incoming connections (for internal use). +*/ + +/*! + \fn QLlcpSocket::connected() + + This signal is emitted after connectToService() has been called and a connection has been + successfully established. + + \sa connectToService(), disconnected() +*/ + +/*! + \fn QLlcpSocket::disconnected() + + This signal is emitted when the socket has been disconnected. + + \sa disconnectFromService(), +*/ + +/*! + \fn QLlcpSocket::error(QLlcpSocket::SocketError socketError) + + This signal is emitted when an error occurs. The \a socketError parameter describes the error. +*/ + +/*! + \fn QLlcpSocket::stateChanged(QLlcpSocket::SocketState socketState) + + This signal is emitted when the state of the socket changes. The \a socketState parameter + describes the new state. +*/ + +/*! + Construct a new unconnected LLCP socket with \a parent. +*/ +QLlcpSocket::QLlcpSocket(QObject *parent) +: QIODevice(parent), d_ptr(new QLlcpSocketPrivate(this)) +{ + setOpenMode(QIODevice::NotOpen); +} + +/*! + \internal +*/ +QLlcpSocket::QLlcpSocket(QLlcpSocketPrivate *d, QObject *parent) +: QIODevice(parent), d_ptr(d) +{ + setOpenMode(QIODevice::ReadWrite); + d_ptr->q_ptr = this; +} + +/*! + Destroys the LLCP socket. +*/ +QLlcpSocket::~QLlcpSocket() +{ + delete d_ptr; +} + +/*! + Connects to the service identified by the URI \a serviceUri on \a target. +*/ +void QLlcpSocket::connectToService(QNearFieldTarget *target, const QString &serviceUri) +{ + Q_D(QLlcpSocket); + + d->connectToService(target, serviceUri); +} + +/*! + Disconnects the socket. +*/ +void QLlcpSocket::disconnectFromService() +{ + Q_D(QLlcpSocket); + + d->disconnectFromService(); +} + +/*! + Disconnects the socket. +*/ +void QLlcpSocket::close() +{ + Q_D(QLlcpSocket); + + QIODevice::close(); + + d->disconnectFromService(); +} + +/*! + Binds the LLCP socket to local \a port. Returns true on success; otherwise returns false. +*/ +bool QLlcpSocket::bind(quint8 port) +{ + Q_D(QLlcpSocket); + + return d->bind(port); +} + +/*! + Returns true if at least one datagram (service data units) is waiting to be read; otherwise + returns false. + + \sa pendingDatagramSize(), readDatagram() +*/ +bool QLlcpSocket::hasPendingDatagrams() const +{ + Q_D(const QLlcpSocket); + + return d->hasPendingDatagrams(); +} + +/*! + Returns the size of the first pending datagram (service data unit). If there is no datagram + available, this function returns -1. + + \sa hasPendingDatagrams(), readDatagram() +*/ +qint64 QLlcpSocket::pendingDatagramSize() const +{ + Q_D(const QLlcpSocket); + + return d->pendingDatagramSize(); +} + +/*! + Sends the datagram at \a data of size \a size to the service that this socket is connected to. + Returns the number of bytes sent on success; otherwise return -1; +*/ +qint64 QLlcpSocket::writeDatagram(const char *data, qint64 size) +{ + Q_D(QLlcpSocket); + + return d->writeDatagram(data, size); +} + +/*! + \reimp + + Always returns true. +*/ +bool QLlcpSocket::isSequential() const +{ + return true; +} + +/*! + \overload + + Sends the datagram \a datagram to the service that this socket is connected to. +*/ +qint64 QLlcpSocket::writeDatagram(const QByteArray &datagram) +{ + Q_D(QLlcpSocket); + + return d->writeDatagram(datagram); +} + +/*! + Receives a datagram no larger than \a maxSize bytes and stores it in \a data. The sender's + details are stored in \a target and \a port (unless the pointers are 0). + + Returns the size of the datagram on success; otherwise returns -1. + + If maxSize is too small, the rest of the datagram will be lost. To avoid loss of data, call + pendingDatagramSize() to determine the size of the pending datagram before attempting to read + it. If maxSize is 0, the datagram will be discarded. + + \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize() +*/ +qint64 QLlcpSocket::readDatagram(char *data, qint64 maxSize, QNearFieldTarget **target, + quint8 *port) +{ + Q_D(QLlcpSocket); + + return d->readDatagram(data, maxSize, target, port); +} + +/*! + Sends the datagram at \a data of size \a size to the service identified by the URI + \a port on \a target. Returns the number of bytes sent on success; otherwise returns -1. + + \sa readDatagram() +*/ +qint64 QLlcpSocket::writeDatagram(const char *data, qint64 size, QNearFieldTarget *target, + quint8 port) +{ + Q_D(QLlcpSocket); + + return d->writeDatagram(data, size, target, port); +} + +/*! + \overload + + Sends the datagram \a datagram to the service identified by the URI \a port on \a target. +*/ +qint64 QLlcpSocket::writeDatagram(const QByteArray &datagram, QNearFieldTarget *target, + quint8 port) +{ + Q_D(QLlcpSocket); + + return d->writeDatagram(datagram, target, port); +} + +/*! + Returns the type of error that last occurred. +*/ +QLlcpSocket::SocketError QLlcpSocket::error() const +{ + Q_D(const QLlcpSocket); + + return d->error(); +} + +/*! + Returns the state of the socket. +*/ +QLlcpSocket::SocketState QLlcpSocket::state() const +{ + Q_D(const QLlcpSocket); + + return d->state(); +} + +/*! + \reimp +*/ +qint64 QLlcpSocket::bytesAvailable() const +{ + Q_D(const QLlcpSocket); + + return d->bytesAvailable() + QIODevice::bytesAvailable(); +} + +/*! + \reimp +*/ +bool QLlcpSocket::canReadLine() const +{ + Q_D(const QLlcpSocket); + + return d->canReadLine() || QIODevice::canReadLine(); +} + +/*! + \reimp +*/ +bool QLlcpSocket::waitForReadyRead(int msecs) +{ + Q_D(QLlcpSocket); + + return d->waitForReadyRead(msecs); +} + +/*! + \reimp +*/ +bool QLlcpSocket::waitForBytesWritten(int msecs) +{ + Q_D(QLlcpSocket); + + return d->waitForBytesWritten(msecs); +} + +/*! + Waits until the socket is connected, up to \a msecs milliseconds. If the connection has been + established, this function returns true; otherwise it returns false. In the case where it + returns false, you can call error() to determine the cause of the error. + + If msecs is -1, this function will not time out. +*/ +bool QLlcpSocket::waitForConnected(int msecs) +{ + Q_D(QLlcpSocket); + + return d->waitForConnected(msecs); +} + +/*! + Waits until the socket is disconnected, up to \a msecs milliseconds. If the connection has been + disconnected, this function returns true; otherwise it returns false. In the case where it + returns false, you can call error() to determine the cause of the error. + + If msecs is -1, this function will not time out. +*/ +bool QLlcpSocket::waitForDisconnected(int msecs) +{ + Q_D(QLlcpSocket); + + return d->waitForDisconnected(msecs); +} + +/*! + \internal +*/ +qint64 QLlcpSocket::readData(char *data, qint64 maxlen) +{ + Q_D(QLlcpSocket); + + return d->readData(data, maxlen); +} + +/*! + \internal +*/ +qint64 QLlcpSocket::writeData(const char *data, qint64 len) +{ + Q_D(QLlcpSocket); + + return d->writeData(data, len); +} + +#include <moc_qllcpsocket.cpp> diff --git a/src/nfc/qllcpsocket.h b/src/nfc/qllcpsocket.h new file mode 100644 index 00000000..7e916b95 --- /dev/null +++ b/src/nfc/qllcpsocket.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSOCKET_H +#define QLLCPSOCKET_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QIODevice> +#include <QtNetwork/QAbstractSocket> + +QT_BEGIN_HEADER + +class QNearFieldTarget; +class QLlcpSocketPrivate; + +class Q_CONNECTIVITY_EXPORT QLlcpSocket : public QIODevice +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QLlcpSocket) + + friend class QLlcpServerPrivate; + +public: + enum SocketState { + UnconnectedState = QAbstractSocket::UnconnectedState, + ConnectingState = QAbstractSocket::ConnectingState, + ConnectedState = QAbstractSocket::ConnectedState, + ClosingState = QAbstractSocket::ClosingState, + BoundState = QAbstractSocket::BoundState, + ListeningState = QAbstractSocket::ListeningState + }; + + enum SocketError { + UnknownSocketError = QAbstractSocket::UnknownSocketError, + RemoteHostClosedError = QAbstractSocket::RemoteHostClosedError, + SocketAccessError = QAbstractSocket::SocketAccessError, + SocketResourceError = QAbstractSocket::SocketResourceError + }; + + explicit QLlcpSocket(QObject *parent = 0); + ~QLlcpSocket(); + + void connectToService(QNearFieldTarget *target, const QString &serviceUri); + void disconnectFromService(); + + void close(); + + bool bind(quint8 port); + + bool hasPendingDatagrams() const; + qint64 pendingDatagramSize() const; + + qint64 writeDatagram(const char *data, qint64 size); + qint64 writeDatagram(const QByteArray &datagram); + + qint64 readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target = 0, quint8 *port = 0); + qint64 writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port); + qint64 writeDatagram(const QByteArray &datagram, QNearFieldTarget *target, quint8 port); + + SocketError error() const; + SocketState state() const; + + qint64 bytesAvailable() const; + bool canReadLine() const; + + bool waitForReadyRead(int msecs = 30000); + bool waitForBytesWritten(int msecs = 30000); + virtual bool waitForConnected(int msecs = 30000); + virtual bool waitForDisconnected(int msecs = 30000); + bool isSequential() const; + +Q_SIGNALS: + void connected(); + void disconnected(); + void error(QLlcpSocket::SocketError socketError); + void stateChanged(QLlcpSocket::SocketState socketState); + +protected: + qint64 readData(char *data, qint64 maxlen); + qint64 writeData(const char *data, qint64 len); + +private: + QLlcpSocket(QLlcpSocketPrivate *d, QObject *parent); + + QLlcpSocketPrivate *d_ptr; +}; + +QT_END_HEADER + +#endif // QLLCPSOCKET_H diff --git a/src/nfc/qllcpsocket_maemo6_p.cpp b/src/nfc/qllcpsocket_maemo6_p.cpp new file mode 100644 index 00000000..a2cd15f6 --- /dev/null +++ b/src/nfc/qllcpsocket_maemo6_p.cpp @@ -0,0 +1,638 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpsocket_maemo6_p.h" + +#include "manager_interface.h" +#include "maemo6/adapter_interface_p.h" +#include "maemo6/socketrequestor_p.h" + +#include <QtCore/QSocketNotifier> +#include <QtCore/QAtomicInt> + +#include <errno.h> +#include <signal.h> + +using namespace com::nokia::nfc; + +static QAtomicInt requestorId = 0; +static const char * const requestorBasePath = "/com/nokia/nfc/llcpclient/"; + +QLlcpSocketPrivate::QLlcpSocketPrivate(QLlcpSocket *q) +: q_ptr(q), + m_connection(QDBusConnection::connectToBus(QDBusConnection::SystemBus, QUuid::createUuid())), + m_port(0), m_socketRequestor(0), m_fd(-1), m_readNotifier(0), m_writeNotifier(0), + m_pendingBytes(0), m_state(QLlcpSocket::UnconnectedState), + m_error(QLlcpSocket::UnknownSocketError) +{ +} + +QLlcpSocketPrivate::QLlcpSocketPrivate(const QDBusConnection &connection, int fd, + const QVariantMap &properties) +: q_ptr(0), m_properties(properties), m_connection(connection), m_port(0), m_socketRequestor(0), + m_fd(fd), m_pendingBytes(0), + m_state(QLlcpSocket::ConnectedState), m_error(QLlcpSocket::UnknownSocketError) +{ + m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(_q_readNotify())); + m_writeNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Write, this); + connect(m_writeNotifier, SIGNAL(activated(int)), this, SLOT(_q_bytesWritten())); +} + +QLlcpSocketPrivate::~QLlcpSocketPrivate() +{ + delete m_readNotifier; + delete m_writeNotifier; +} + +void QLlcpSocketPrivate::connectToService(QNearFieldTarget *target, const QString &serviceUri) +{ + Q_UNUSED(target); + + Q_Q(QLlcpSocket); + + m_state = QLlcpSocket::ConnectingState; + emit q->stateChanged(m_state); + + initializeRequestor(); + + if (m_socketRequestor) { + m_serviceUri = serviceUri; + m_port = 0; + + QString accessKind(QLatin1String("device.llcp.co.client:") + serviceUri); + + m_socketRequestor->requestAccess(m_requestorPath, accessKind); + } else { + setSocketError(QLlcpSocket::SocketResourceError); + + m_state = QLlcpSocket::UnconnectedState; + emit q->stateChanged(m_state); + } +} + +void QLlcpSocketPrivate::disconnectFromService() +{ + Q_Q(QLlcpSocket); + + m_state = QLlcpSocket::ClosingState; + emit q->stateChanged(m_state); + + delete m_readNotifier; + m_readNotifier = 0; + delete m_writeNotifier; + m_writeNotifier = 0; + m_pendingBytes = 0; + ::close(m_fd); + m_fd = -1; + + if (m_socketRequestor) { + QString accessKind(QLatin1String("device.llcp.co.client:") + m_serviceUri); + + Manager manager(QLatin1String("com.nokia.nfc"), QLatin1String("/"), m_connection); + QDBusObjectPath defaultAdapterPath = manager.DefaultAdapter(); + + m_socketRequestor->cancelAccessRequest(m_requestorPath, accessKind); + } + + m_state = QLlcpSocket::UnconnectedState; + q->setOpenMode(QIODevice::NotOpen); + emit q->stateChanged(m_state); + emit q->disconnected(); +} + +bool QLlcpSocketPrivate::bind(quint8 port) +{ + initializeRequestor(); + + if (!m_socketRequestor) + return false; + + m_serviceUri.clear(); + m_port = port; + + const QString accessKind(QLatin1String("device.llcp.cl:") + QString::number(port)); + + m_socketRequestor->requestAccess(m_requestorPath, accessKind); + + return waitForBound(30000); +} + +bool QLlcpSocketPrivate::hasPendingDatagrams() const +{ + return !m_receivedDatagrams.isEmpty(); +} + +qint64 QLlcpSocketPrivate::pendingDatagramSize() const +{ + if (m_receivedDatagrams.isEmpty()) + return -1; + + if (m_state == QLlcpSocket::BoundState) + return m_receivedDatagrams.first().length() - 1; + else + return m_receivedDatagrams.first().length(); +} + +qint64 QLlcpSocketPrivate::writeDatagram(const char *data, qint64 size) +{ + if (m_state != QLlcpSocket::ConnectedState) + return -1; + + return writeData(data, size); +} + +qint64 QLlcpSocketPrivate::writeDatagram(const QByteArray &datagram) +{ + if (m_state != QLlcpSocket::ConnectedState) + return -1; + + if (uint(datagram.length()) > m_properties.value(QLatin1String("RemoteMIU"), 128).toUInt()) + return -1; + + return writeData(datagram.constData(), datagram.size()); +} + +qint64 QLlcpSocketPrivate::readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target, quint8 *port) +{ + Q_UNUSED(target); + + if (m_state == QLlcpSocket::ConnectedState) { + return readData(data, maxSize); + } else if (m_state == QLlcpSocket::BoundState) { + return readData(data, maxSize, port); + } + + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port) +{ + Q_UNUSED(target); + + if (m_state != QLlcpSocket::BoundState) + return -1; + + if (m_properties.value(QLatin1String("RemoteMIU"), 128).toUInt() < size) + return -1; + + if (m_properties.value(QLatin1String("LocalMIU"), 128).toUInt() < size) + return -1; + + QByteArray datagram; + datagram.append(port); + datagram.append(data, size); + + m_pendingBytes += datagram.size() - 1; + m_writeNotifier->setEnabled(true); + + return ::write(m_fd, datagram.constData(), datagram.size()) - 1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const QByteArray &datagram, + QNearFieldTarget *target, quint8 port) +{ + Q_UNUSED(target); + + if (m_state != QLlcpSocket::BoundState) + return -1; + + if (m_properties.value(QLatin1String("RemoteMIU"), 128).toInt() < datagram.size()) + return -1; + + if (m_properties.value(QLatin1String("LocalMIU"), 128).toInt() < datagram.size()) + return -1; + + QByteArray d; + d.append(port); + d.append(datagram); + + m_pendingBytes += datagram.size() - 1; + m_writeNotifier->setEnabled(true); + + return ::write(m_fd, d.constData(), d.size()) - 1; +} + +QLlcpSocket::SocketError QLlcpSocketPrivate::error() const +{ + return m_error; +} + +QLlcpSocket::SocketState QLlcpSocketPrivate::state() const +{ + return m_state; +} + +qint64 QLlcpSocketPrivate::readData(char *data, qint64 maxlen, quint8 *port) +{ + if (m_receivedDatagrams.isEmpty()) + return 0; + + const QByteArray datagram = m_receivedDatagrams.takeFirst(); + + if (m_state == QLlcpSocket::BoundState) { + if (port) + *port = datagram.at(0); + + qint64 size = qMin(maxlen, qint64(datagram.length() - 1)); + memcpy(data, datagram.constData() + 1, size); + return size; + } else { + if (port) + *port = 0; + + qint64 size = qMin(maxlen, qint64(datagram.length())); + memcpy(data, datagram.constData(), size); + return size; + } +} + +qint64 QLlcpSocketPrivate::writeData(const char *data, qint64 len) +{ + Q_Q(QLlcpSocket); + + qint64 remoteMiu = m_properties.value(QLatin1String("RemoteMIU"), 128).toLongLong(); + qint64 localMiu = m_properties.value(QLatin1String("LocalMIU"), 128).toLongLong(); + qint64 miu = qMin(remoteMiu, localMiu); + + m_writeNotifier->setEnabled(true); + + ssize_t wrote = ::write(m_fd, data, qMin(miu, len)); + if (wrote == -1) { + if (errno == EAGAIN) + return 0; + + setSocketError(QLlcpSocket::RemoteHostClosedError); + q->disconnectFromService(); + return -1; + } + + m_pendingBytes += wrote; + return wrote; +} + +qint64 QLlcpSocketPrivate::bytesAvailable() const +{ + qint64 available = 0; + foreach (const QByteArray &datagram, m_receivedDatagrams) + available += datagram.length(); + + // less source port + if (m_state == QLlcpSocket::BoundState) + available -= m_receivedDatagrams.count(); + + return available; +} + +bool QLlcpSocketPrivate::canReadLine() const +{ + if (m_state == QLlcpSocket::BoundState) + return false; + + foreach (const QByteArray &datagram, m_receivedDatagrams) { + if (datagram.contains('\n')) + return true; + } + + return false; +} + +bool QLlcpSocketPrivate::waitForReadyRead(int msec) +{ + if (bytesAvailable()) + return true; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(m_fd, &fds); + + timeval timeout; + timeout.tv_sec = msec / 1000; + timeout.tv_usec = (msec % 1000) * 1000; + + // timeout can not be 0 or else select will return an error. + if (0 == msec) + timeout.tv_usec = 1000; + + int result = -1; + // on Linux timeout will be updated by select, but _not_ on other systems. + QElapsedTimer timer; + timer.start(); + while (!bytesAvailable() && (-1 == msec || timer.elapsed() < msec)) { + result = ::select(m_fd + 1, &fds, 0, 0, &timeout); + if (result > 0) + _q_readNotify(); + + if (-1 == result && errno != EINTR) { + setSocketError(QLlcpSocket::UnknownSocketError); + break; + } + } + + return bytesAvailable(); +} + +bool QLlcpSocketPrivate::waitForBytesWritten(int msec) +{ + fd_set fds; + FD_ZERO(&fds); + FD_SET(m_fd, &fds); + + timeval timeout; + timeout.tv_sec = msec / 1000; + timeout.tv_usec = (msec % 1000) * 1000; + + // timeout can not be 0 or else select will return an error. + if (0 == msec) + timeout.tv_usec = 1000; + + int result = -1; + // on Linux timeout will be updated by select, but _not_ on other systems. + QElapsedTimer timer; + timer.start(); + while (-1 == msec || timer.elapsed() < msec) { + result = ::select(m_fd + 1, 0, &fds, 0, &timeout); + if (result > 0) + return true; + if (-1 == result && errno != EINTR) { + setSocketError(QLlcpSocket::UnknownSocketError); + return false; + } + } + + // timeout expired + return false; +} + +bool QLlcpSocketPrivate::waitForConnected(int msecs) +{ + if (m_state != QLlcpSocket::ConnectingState) + return m_state == QLlcpSocket::ConnectedState; + + QElapsedTimer timer; + timer.start(); + while (m_state == QLlcpSocket::ConnectingState && (msecs == -1 || timer.elapsed() < msecs)) { + if (!m_socketRequestor->waitForDBusSignal(qMax(msecs - timer.elapsed(), qint64(0)))) { + setSocketError(QLlcpSocket::UnknownSocketError); + break; + } + } + + // Possibly not needed. + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); + + return m_state == QLlcpSocket::ConnectedState; +} + +bool QLlcpSocketPrivate::waitForDisconnected(int msec) +{ + if (m_state == QLlcpSocket::UnconnectedState) + return true; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(m_fd, &fds); + + timeval timeout; + timeout.tv_sec = msec / 1000; + timeout.tv_usec = (msec % 1000) * 1000; + + // timeout can not be 0 or else select will return an error. + if (0 == msec) + timeout.tv_usec = 1000; + + int result = -1; + // on Linux timeout will be updated by select, but _not_ on other systems. + QElapsedTimer timer; + timer.start(); + while (m_state != QLlcpSocket::UnconnectedState && (-1 == msec || timer.elapsed() < msec)) { + result = ::select(m_fd + 1, &fds, 0, 0, &timeout); + if (result > 0) + _q_readNotify(); + + if (-1 == result && errno != EINTR) { + setSocketError(QLlcpSocket::UnknownSocketError); + break; + } + } + + return m_state == QLlcpSocket::UnconnectedState; +} + +bool QLlcpSocketPrivate::waitForBound(int msecs) +{ + if (m_state == QLlcpSocket::BoundState) + return true; + + QElapsedTimer timer; + timer.start(); + while (m_state != QLlcpSocket::BoundState && (msecs == -1 || timer.elapsed() < msecs)) { + if (!m_socketRequestor->waitForDBusSignal(qMax(msecs - timer.elapsed(), qint64(0)))) + return false; + } + + // Possibly not needed. + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); + + return m_state == QLlcpSocket::BoundState; +} + +void QLlcpSocketPrivate::AccessFailed(const QDBusObjectPath &targetPath, const QString &kind, + const QString &error) +{ + Q_UNUSED(targetPath); + Q_UNUSED(kind); + Q_UNUSED(error); + + Q_Q(QLlcpSocket); + + setSocketError(QLlcpSocket::SocketAccessError); + + m_state = QLlcpSocket::UnconnectedState; + emit q->stateChanged(m_state); +} + +void QLlcpSocketPrivate::AccessGranted(const QDBusObjectPath &targetPath, + const QString &accessKind) +{ + Q_UNUSED(targetPath); + Q_UNUSED(accessKind); +} + +void QLlcpSocketPrivate::Accept(const QDBusVariant &lsap, const QDBusVariant &rsap, + int fd, const QVariantMap &properties) +{ + Q_UNUSED(lsap); + Q_UNUSED(rsap); + Q_UNUSED(fd); + Q_UNUSED(properties); +} + +void QLlcpSocketPrivate::Connect(const QDBusVariant &lsap, const QDBusVariant &rsap, + int fd, const QVariantMap &properties) +{ + Q_UNUSED(lsap); + Q_UNUSED(rsap); + + m_fd = fd; + + m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(_q_readNotify())); + m_writeNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Write, this); + connect(m_writeNotifier, SIGNAL(activated(int)), this, SLOT(_q_bytesWritten())); + + m_properties = properties; + + Q_Q(QLlcpSocket); + + q->setOpenMode(QIODevice::ReadWrite); + + m_state = QLlcpSocket::ConnectedState; + emit q->stateChanged(m_state); + emit q->connected(); +} + +void QLlcpSocketPrivate::Socket(const QDBusVariant &lsap, int fd, const QVariantMap &properties) +{ + m_fd = fd; + m_port = lsap.variant().toUInt(); + + m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(_q_readNotify())); + m_writeNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Write, this); + connect(m_writeNotifier, SIGNAL(activated(int)), this, SLOT(_q_bytesWritten())); + + m_properties = properties; + + Q_Q(QLlcpSocket); + + m_state = QLlcpSocket::BoundState; + emit q->stateChanged(m_state); +} + +void QLlcpSocketPrivate::_q_readNotify() +{ + Q_Q(QLlcpSocket); + + QByteArray datagram; + datagram.resize(m_properties.value(QLatin1String("LocalMIU"), 128).toUInt()); + + int readFromDevice = ::read(m_fd, datagram.data(), datagram.size()); + if (readFromDevice <= 0) { + m_readNotifier->setEnabled(false); + + setSocketError(QLlcpSocket::RemoteHostClosedError); + + q->disconnectFromService(); + q->setOpenMode(QIODevice::NotOpen); + } else { + m_receivedDatagrams.append(datagram.left(readFromDevice)); + emit q->readyRead(); + } +} + +void QLlcpSocketPrivate::_q_bytesWritten() +{ + Q_Q(QLlcpSocket); + + m_writeNotifier->setEnabled(false); + + emit q->bytesWritten(m_pendingBytes); + m_pendingBytes = 0; +} + +void QLlcpSocketPrivate::setSocketError(QLlcpSocket::SocketError socketError) +{ + Q_Q(QLlcpSocket); + + QLatin1String c("QLlcpSocket"); + + m_error = socketError; + switch (socketError) { + case QLlcpSocket::UnknownSocketError: + q->setErrorString(QLlcpSocket::tr("%1: Unknown error %2").arg(c).arg(errno)); + break; + case QLlcpSocket::RemoteHostClosedError: + q->setErrorString(QLlcpSocket::tr("%1: Remote closed").arg(c)); + break; + case QLlcpSocket::SocketAccessError: + q->setErrorString(QLlcpSocket::tr("%1: Socket access error")); + break; + case QLlcpSocket::SocketResourceError: + q->setErrorString(QLlcpSocket::tr("%1: Socket resource error")); + break; + } + + emit q->error(m_error); +} + +void QLlcpSocketPrivate::initializeRequestor() +{ + if (m_socketRequestor) + return; + + if (m_requestorPath.isEmpty()) { + m_requestorPath = QLatin1String(requestorBasePath) + + QString::number(requestorId.fetchAndAddOrdered(1)); + } + + Manager manager(QLatin1String("com.nokia.nfc"), QLatin1String("/"), m_connection); + QDBusObjectPath defaultAdapterPath = manager.DefaultAdapter(); + + if (!m_socketRequestor) { + m_socketRequestor = new SocketRequestor(defaultAdapterPath.path(), this); + + connect(m_socketRequestor, SIGNAL(accessFailed(QDBusObjectPath,QString,QString)), + this, SLOT(AccessFailed(QDBusObjectPath,QString,QString))); + connect(m_socketRequestor, SIGNAL(accessGranted(QDBusObjectPath,QString)), + this, SLOT(AccessGranted(QDBusObjectPath,QString))); + connect(m_socketRequestor, SIGNAL(accept(QDBusVariant,QDBusVariant,int,QVariantMap)), + this, SLOT(Accept(QDBusVariant,QDBusVariant,int,QVariantMap))); + connect(m_socketRequestor, SIGNAL(connect(QDBusVariant,QDBusVariant,int,QVariantMap)), + this, SLOT(Connect(QDBusVariant,QDBusVariant,int,QVariantMap))); + connect(m_socketRequestor, SIGNAL(socket(QDBusVariant,int,QVariantMap)), + this, SLOT(Socket(QDBusVariant,int,QVariantMap))); + } +} + +#include "moc_qllcpsocket_maemo6_p.cpp" diff --git a/src/nfc/qllcpsocket_maemo6_p.h b/src/nfc/qllcpsocket_maemo6_p.h new file mode 100644 index 00000000..bfece31f --- /dev/null +++ b/src/nfc/qllcpsocket_maemo6_p.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSOCKET_MAEMO6_P_H +#define QLLCPSOCKET_MAEMO6_P_H + +#include <qconnectivityglobal.h> + +#include "qllcpsocket.h" + +#include <QtDBus/QDBusConnection> + +QT_FORWARD_DECLARE_CLASS(QDBusObjectPath) +QT_FORWARD_DECLARE_CLASS(QDBusVariant) +QT_FORWARD_DECLARE_CLASS(QSocketNotifier) + +class AccessRequestorAdaptor; +class LLCPRequestorAdaptor; + +class SocketRequestor; + +class QLlcpSocketPrivate : public QObject +{ + Q_OBJECT + + Q_DECLARE_PUBLIC(QLlcpSocket) + +public: + QLlcpSocketPrivate(QLlcpSocket *q); + QLlcpSocketPrivate(const QDBusConnection &connection, int fd, const QVariantMap &properties); + ~QLlcpSocketPrivate(); + + void connectToService(QNearFieldTarget *target, const QString &serviceUri); + void disconnectFromService(); + + bool bind(quint8 port); + + bool hasPendingDatagrams() const; + qint64 pendingDatagramSize() const; + + qint64 writeDatagram(const char *data, qint64 size); + qint64 writeDatagram(const QByteArray &datagram); + + qint64 readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target = 0, quint8 *port = 0); + qint64 writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port); + qint64 writeDatagram(const QByteArray &datagram, QNearFieldTarget *target, quint8 port); + + QLlcpSocket::SocketError error() const; + QLlcpSocket::SocketState state() const; + + qint64 readData(char *data, qint64 maxlex, quint8 *port = 0); + qint64 writeData(const char *data, qint64 len); + + qint64 bytesAvailable() const; + bool canReadLine() const; + + bool waitForReadyRead(int msecs); + bool waitForBytesWritten(int msecs); + bool waitForConnected(int msecs); + bool waitForDisconnected(int msecs); + bool waitForBound(int msecs); + +private slots: + // com.nokia.nfc.AccessRequestor + void AccessFailed(const QDBusObjectPath &targetPath, const QString &kind, + const QString &error); + void AccessGranted(const QDBusObjectPath &targetPath, const QString &accessKind); + + // com.nokia.nfc.LLCPRequestor + void Accept(const QDBusVariant &lsap, const QDBusVariant &rsap, int fd, const QVariantMap &properties); + void Connect(const QDBusVariant &lsap, const QDBusVariant &rsap, int fd, const QVariantMap &properties); + void Socket(const QDBusVariant &lsap, int fd, const QVariantMap &properties); + + void _q_readNotify(); + void _q_bytesWritten(); + +private: + void setSocketError(QLlcpSocket::SocketError socketError); + void initializeRequestor(); + + QLlcpSocket *q_ptr; + QVariantMap m_properties; + QList<QByteArray> m_receivedDatagrams; + + QDBusConnection m_connection; + + QString m_serviceUri; + quint8 m_port; + + QString m_requestorPath; + + SocketRequestor *m_socketRequestor; + + int m_fd; + QSocketNotifier *m_readNotifier; + QSocketNotifier *m_writeNotifier; + qint64 m_pendingBytes; + + QLlcpSocket::SocketState m_state; + QLlcpSocket::SocketError m_error; +}; + +#endif // QLLCPSOCKET_MAEMO6_P_H diff --git a/src/nfc/qllcpsocket_p.cpp b/src/nfc/qllcpsocket_p.cpp new file mode 100644 index 00000000..820cbb64 --- /dev/null +++ b/src/nfc/qllcpsocket_p.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpsocket_p.h" + +QLlcpSocketPrivate::QLlcpSocketPrivate(QLlcpSocket *q) +: q_ptr(q) +{ +} + +QLlcpSocketPrivate::~QLlcpSocketPrivate() +{ + +} + +void QLlcpSocketPrivate::connectToService(QNearFieldTarget *target, const QString &serviceUri) +{ + Q_UNUSED(target); + Q_UNUSED(serviceUri); +} + +void QLlcpSocketPrivate::disconnectFromService() +{ +} + +bool QLlcpSocketPrivate::bind(quint8 port) +{ + Q_UNUSED(port); + + return false; +} + +bool QLlcpSocketPrivate::hasPendingDatagrams() const +{ + return false; +} + +qint64 QLlcpSocketPrivate::pendingDatagramSize() const +{ + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const char *data, qint64 size) +{ + Q_UNUSED(data); + Q_UNUSED(size); + + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const QByteArray &datagram) +{ + Q_UNUSED(datagram); + + return -1; +} + +qint64 QLlcpSocketPrivate::readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target, quint8 *port) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + Q_UNUSED(target); + Q_UNUSED(port); + + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port) +{ + Q_UNUSED(data); + Q_UNUSED(size); + Q_UNUSED(target); + Q_UNUSED(port); + + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const QByteArray &datagram, + QNearFieldTarget *target, quint8 port) +{ + Q_UNUSED(datagram); + Q_UNUSED(target); + Q_UNUSED(port); + + return -1; +} + +QLlcpSocket::SocketError QLlcpSocketPrivate::error() const +{ + return QLlcpSocket::UnknownSocketError; +} + +QLlcpSocket::SocketState QLlcpSocketPrivate::state() const +{ + return QLlcpSocket::UnconnectedState; +} + +qint64 QLlcpSocketPrivate::readData(char *data, qint64 maxlen) +{ + Q_UNUSED(data); + Q_UNUSED(maxlen); + + return -1; +} + +qint64 QLlcpSocketPrivate::writeData(const char *data, qint64 len) +{ + Q_UNUSED(data); + Q_UNUSED(len); + + return -1; +} + +qint64 QLlcpSocketPrivate::bytesAvailable() const +{ + return 0; +} + +bool QLlcpSocketPrivate::canReadLine() const +{ + return false; +} + +bool QLlcpSocketPrivate::waitForReadyRead(int msecs) +{ + Q_UNUSED(msecs); + + return false; +} + +bool QLlcpSocketPrivate::waitForBytesWritten(int msecs) +{ + Q_UNUSED(msecs); + + return false; +} + +bool QLlcpSocketPrivate::waitForConnected(int msecs) +{ + Q_UNUSED(msecs); + + return false; +} + +bool QLlcpSocketPrivate::waitForDisconnected(int msecs) +{ + Q_UNUSED(msecs); + + return false; +} diff --git a/src/nfc/qllcpsocket_p.h b/src/nfc/qllcpsocket_p.h new file mode 100644 index 00000000..2dde2c1c --- /dev/null +++ b/src/nfc/qllcpsocket_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSOCKET_P_H +#define QLLCPSOCKET_P_H + +#include "../qtconnectivityglobal.h" + +#include "qllcpsocket.h" + +class QLlcpSocketPrivate +{ + Q_DECLARE_PUBLIC(QLlcpSocket) + +public: + QLlcpSocketPrivate(QLlcpSocket *q); + + ~QLlcpSocketPrivate(); + + void connectToService(QNearFieldTarget *target, const QString &serviceUri); + void disconnectFromService(); + + bool bind(quint8 port); + + bool hasPendingDatagrams() const; + qint64 pendingDatagramSize() const; + + qint64 writeDatagram(const char *data, qint64 size); + qint64 writeDatagram(const QByteArray &datagram); + + qint64 readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target = 0, quint8 *port = 0); + qint64 writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port); + qint64 writeDatagram(const QByteArray &datagram, QNearFieldTarget *target, quint8 port); + + QLlcpSocket::SocketError error() const; + QLlcpSocket::SocketState state() const; + + qint64 readData(char *data, qint64 maxlen); + qint64 writeData(const char *data, qint64 len); + + qint64 bytesAvailable() const; + bool canReadLine() const; + + bool waitForReadyRead(int msecs); + bool waitForBytesWritten(int msecs); + bool waitForConnected(int msecs); + bool waitForDisconnected(int msecs); + +private: + QLlcpSocket *q_ptr; +}; + +#endif // QLLCPSOCKET_P_H diff --git a/src/nfc/qllcpsocket_simulator_p.cpp b/src/nfc/qllcpsocket_simulator_p.cpp new file mode 100644 index 00000000..2749c250 --- /dev/null +++ b/src/nfc/qllcpsocket_simulator_p.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpsocket_simulator_p.h" + +QLlcpSocketPrivate::QLlcpSocketPrivate(QLlcpSocket *q) +: q_ptr(q) +{ +} + +void QLlcpSocketPrivate::connectToService(QNearFieldTarget *target, const QString &serviceUri) +{ + Q_UNUSED(target); + Q_UNUSED(serviceUri); +} + +void QLlcpSocketPrivate::disconnectFromService() +{ +} + +bool QLlcpSocketPrivate::bind(quint8 port) +{ + Q_UNUSED(port); + + return false; +} + +bool QLlcpSocketPrivate::hasPendingDatagrams() const +{ + return false; +} + +qint64 QLlcpSocketPrivate::pendingDatagramSize() const +{ + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const char *data, qint64 size) +{ + Q_UNUSED(data); + Q_UNUSED(size); + + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const QByteArray &datagram) +{ + Q_UNUSED(datagram); + + return -1; +} + +qint64 QLlcpSocketPrivate::readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target, quint8 *port) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + Q_UNUSED(target); + Q_UNUSED(port); + + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port) +{ + Q_UNUSED(data); + Q_UNUSED(size); + Q_UNUSED(target); + Q_UNUSED(port); + + return -1; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const QByteArray &datagram, + QNearFieldTarget *target, quint8 port) +{ + Q_UNUSED(datagram); + Q_UNUSED(target); + Q_UNUSED(port); + + return -1; +} + +QLlcpSocket::SocketError QLlcpSocketPrivate::error() const +{ + return QLlcpSocket::UnknownSocketError; +} + +QLlcpSocket::SocketState QLlcpSocketPrivate::state() const +{ + return QLlcpSocket::UnconnectedState; +} + +qint64 QLlcpSocketPrivate::readData(char *data, qint64 maxlen) +{ + Q_UNUSED(data); + Q_UNUSED(maxlen); + + return -1; +} + +qint64 QLlcpSocketPrivate::writeData(const char *data, qint64 len) +{ + Q_UNUSED(data); + Q_UNUSED(len); + + return -1; +} + +qint64 QLlcpSocketPrivate::bytesAvailable() const +{ + return 0; +} + +bool QLlcpSocketPrivate::canReadLine() const +{ + return false; +} + +bool QLlcpSocketPrivate::waitForReadyRead(int msecs) +{ + Q_UNUSED(msecs); + + return false; +} + +bool QLlcpSocketPrivate::waitForBytesWritten(int msecs) +{ + Q_UNUSED(msecs); + + return false; +} + +bool QLlcpSocketPrivate::waitForConnected(int msecs) +{ + Q_UNUSED(msecs); + + return false; +} + +bool QLlcpSocketPrivate::waitForDisconnected(int msecs) +{ + Q_UNUSED(msecs); + + return false; +} + diff --git a/src/nfc/qllcpsocket_simulator_p.h b/src/nfc/qllcpsocket_simulator_p.h new file mode 100644 index 00000000..e232eda8 --- /dev/null +++ b/src/nfc/qllcpsocket_simulator_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSOCKET_P_H +#define QLLCPSOCKET_P_H + +#include <qconnectivityglobal.h> + +#include "qllcpsocket.h" + +class QLlcpSocketPrivate +{ + Q_DECLARE_PUBLIC(QLlcpSocket) + +public: + QLlcpSocketPrivate(QLlcpSocket *q); + + void connectToService(QNearFieldTarget *target, const QString &serviceUri); + void disconnectFromService(); + + bool bind(quint8 port); + + bool hasPendingDatagrams() const; + qint64 pendingDatagramSize() const; + + qint64 writeDatagram(const char *data, qint64 size); + qint64 writeDatagram(const QByteArray &datagram); + + qint64 readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target = 0, quint8 *port = 0); + qint64 writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port); + qint64 writeDatagram(const QByteArray &datagram, QNearFieldTarget *target, quint8 port); + + QLlcpSocket::SocketError error() const; + QLlcpSocket::SocketState state() const; + + qint64 readData(char *data, qint64 maxlen); + qint64 writeData(const char *data, qint64 len); + + qint64 bytesAvailable() const; + bool canReadLine() const; + + bool waitForReadyRead(int msecs); + bool waitForBytesWritten(int msecs); + bool waitForConnected(int msecs); + bool waitForDisconnected(int msecs); + +private: + QLlcpSocket *q_ptr; +}; + +#endif // QLLCPSOCKET_P_H diff --git a/src/nfc/qllcpsocket_symbian_p.cpp b/src/nfc/qllcpsocket_symbian_p.cpp new file mode 100644 index 00000000..ccf637f0 --- /dev/null +++ b/src/nfc/qllcpsocket_symbian_p.cpp @@ -0,0 +1,409 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qllcpsocket_symbian_p.h" +#include "qllcpstate_symbian_p.h" +#include "symbian/llcpsockettype1_symbian.h" +#include "symbian/llcpsockettype2_symbian.h" +#include "symbian/nearfieldutility_symbian.h" +#include "symbian/debug.h" + +/*! + Constructor +*/ +QLlcpSocketPrivate::QLlcpSocketPrivate(QLlcpSocket *q) + : m_symbianSocketType1(NULL), + m_symbianSocketType2(NULL), + m_error(QLlcpSocket::UnknownSocketError), + q_ptr(q), + m_emittedReadyRead(false), + m_emittedBytesWritten(false), + m_writeDatagramRefCount(0) +{ + BEGIN + m_unconnectedState = new QLLCPUnconnected(this); + m_connectingState = new QLLCPConnecting(this); + m_connectedState = new QLLCPConnected(this); + m_bindState = new QLLCPBind(this); + + m_state = m_unconnectedState; + END +} + + +/*! + Destructor +*/ +QLlcpSocketPrivate::~QLlcpSocketPrivate() +{ + BEGIN + Q_Q(QLlcpSocket); + if (q->isOpen()) { + q->close(); + } + + delete m_unconnectedState; + delete m_connectingState; + delete m_connectedState; + delete m_bindState; + delete m_symbianSocketType1; + delete m_symbianSocketType2; + END +} + +/*! + Construct the socket and set as connected state from llcp server side +*/ +QLlcpSocketPrivate::QLlcpSocketPrivate(CLlcpSocketType2* socketType2_symbian) + : m_symbianSocketType1(NULL), + m_symbianSocketType2(socketType2_symbian), + m_error(QLlcpSocket::UnknownSocketError), + m_emittedReadyRead(false), + m_emittedBytesWritten(false), + m_writeDatagramRefCount(0) +{ + BEGIN + m_unconnectedState = new QLLCPUnconnected(this); + m_connectingState = new QLLCPConnecting(this); + m_connectedState = new QLLCPConnected(this); + m_bindState = new QLLCPBind(this); + + m_state = m_connectedState; + + END +} + +void QLlcpSocketPrivate::connectToService(QNearFieldTarget *target, const QString &serviceUri) +{ + BEGIN + Q_Q(QLlcpSocket); + if (!q->isOpen()) + { + bool ret = q->open(QIODevice::ReadWrite | QIODevice::Unbuffered); + if (false == ret) + invokeError(); + } + m_state->ConnectToService(target,serviceUri); + END +} + +void QLlcpSocketPrivate::disconnectFromService() +{ + BEGIN + m_state->DisconnectFromService(); + + Q_Q(QLlcpSocket); + if (q->isOpen()) + { + q->close(); + } + END +} + +void QLlcpSocketPrivate::invokeConnected() +{ + BEGIN + Q_Q(QLlcpSocket); + + if (m_state->state() == QLlcpSocket::ConnectingState) + { + changeState(getConnectedState()); + invokeStateChanged(QLlcpSocket::ConnectedState); + emit q->connected(); + } + END +} + +void QLlcpSocketPrivate::invokeReadyRead() +{ + BEGIN + Q_Q(QLlcpSocket); + //If called from within a slot connected to the readyRead() signal, + //readyRead() will not be reemitted. + LOG("m_emittedReadyRead: " << m_emittedReadyRead); + + if (!m_emittedReadyRead){ + m_emittedReadyRead = true; + LOG("readyRead signal has been emitted!"); + emit q->readyRead(); + m_emittedReadyRead = false; + } + END +} + +void QLlcpSocketPrivate::attachCallbackHandler(QLlcpSocket *q) +{ + BEGIN + q_ptr = q; + if (!q->isOpen()) + { + bool ret = q->open(QIODevice::ReadWrite | QIODevice::Unbuffered); + if (false == ret) + invokeError(); + } + END +} + +qint64 QLlcpSocketPrivate::bytesAvailable() const +{ + BEGIN + qint64 bytes = 0; + if (m_symbianSocketType2 != NULL) + { + bytes = m_symbianSocketType2->BytesAvailable(); + } + END + return bytes; +} + +bool QLlcpSocketPrivate::canReadLine() const +{ + return false; +} + +void QLlcpSocketPrivate::invokeBytesWritten(qint64 bytes) +{ + BEGIN + Q_Q(QLlcpSocket); + if (!m_emittedBytesWritten){ + m_emittedBytesWritten = true; + emit q->bytesWritten(bytes); + m_emittedBytesWritten = false; + } + END +} + +void QLlcpSocketPrivate::invokeStateChanged(QLlcpSocket::SocketState socketState) +{ + BEGIN + Q_Q(QLlcpSocket); + emit q->stateChanged(socketState); + END +} + +void QLlcpSocketPrivate::invokeError() +{ + BEGIN + Q_Q(QLlcpSocket); + emit q->error(QLlcpSocket::UnknownSocketError); + END +} + +void QLlcpSocketPrivate::invokeDisconnected() +{ + BEGIN + Q_Q(QLlcpSocket); + emit q->disconnected(); + END +} + +/*! + Only used at connectless mode, create type1 socket if necessary. +*/ +bool QLlcpSocketPrivate::bind(quint8 port) +{ + BEGIN_END + return m_state->Bind(port); +} + +/*! + Returns true if at least one datagram is waiting to be read; + otherwise returns false. +*/ +bool QLlcpSocketPrivate::hasPendingDatagrams() const +{ + BEGIN + bool val = false; + if (m_symbianSocketType1) + { + val = m_symbianSocketType1->HasPendingDatagrams(); + } + + END + return val; +} + +/*! + Returns the size of the first pending connectionless datagram. If there is + no datagram available, this function returns -1. +*/ +qint64 QLlcpSocketPrivate::pendingDatagramSize() const +{ + BEGIN + qint64 val = -1; + if (m_symbianSocketType1) + { + val = m_symbianSocketType1->PendingDatagramSize(); + } + + END + return val; +} + +CLlcpSocketType1* QLlcpSocketPrivate::socketType1Instance() +{ + if (NULL == m_symbianSocketType1) + { + TRAPD(err, m_symbianSocketType1 = CLlcpSocketType1::NewL(*this)); + if (KErrNone != err) { + m_symbianSocketType1 = NULL; + } + } + return m_symbianSocketType1; +} + +CLlcpSocketType2* QLlcpSocketPrivate::socketType2Instance() +{ + if (NULL == m_symbianSocketType2) + { + TRAPD(err, m_symbianSocketType2 = CLlcpSocketType2::NewL(this)); + if (KErrNone != err) { + m_symbianSocketType2 = NULL; + } + } + return m_symbianSocketType2; +} + +/*! + Connection-Oriented Style +*/ +qint64 QLlcpSocketPrivate::writeDatagram(const char *data, qint64 size) +{ + BEGIN + qint64 val = -1; + val = m_state->WriteDatagram(data,size); + END + return val; +} + +/*! + Connection-Oriented Style +*/ +qint64 QLlcpSocketPrivate::writeDatagram(const QByteArray &datagram) +{ + BEGIN_END + return writeDatagram(datagram.constData(),datagram.size()); +} + +/*! + Used for Both Connection-Less & Connection-Oriented Style + As for Connection-Oriented mode, can not pass in the port & target parameters. +*/ +qint64 QLlcpSocketPrivate::readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target, quint8 *port) +{ + BEGIN + qint64 val = m_state->ReadDatagram(data,maxSize,target,port); + END + return val; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port) +{ + BEGIN + qint64 val = m_state->WriteDatagram(data,size,target,port); + END + + return val; +} + +qint64 QLlcpSocketPrivate::writeDatagram(const QByteArray &datagram, + QNearFieldTarget *target, quint8 port) +{ + BEGIN_END + return writeDatagram(datagram.constData(),datagram.size(),target,port); +} + +QLlcpSocket::SocketError QLlcpSocketPrivate::error() const +{ + BEGIN_END + return m_error; +} + +QLlcpSocket::SocketState QLlcpSocketPrivate::state() const +{ + BEGIN_END + return m_state->state(); +} + +qint64 QLlcpSocketPrivate::readData(char *data, qint64 maxlen) +{ + BEGIN_END + return readDatagram(data,maxlen); +} + +qint64 QLlcpSocketPrivate::writeData(const char *data, qint64 len) +{ + BEGIN_END + return writeDatagram(data,len); +} + +bool QLlcpSocketPrivate::waitForReadyRead(int msecs) +{ + BEGIN_END + return m_state->WaitForReadyRead(msecs); +} + +bool QLlcpSocketPrivate::waitForBytesWritten(int msecs) +{ + BEGIN_END + return m_state->WaitForBytesWritten(msecs); +} + +bool QLlcpSocketPrivate::waitForConnected(int msecs) +{ + BEGIN_END + return m_state->WaitForConnected(msecs); +} + +bool QLlcpSocketPrivate::waitForDisconnected(int msecs) +{ + BEGIN_END + return m_state->WaitForDisconnected(msecs); +} + +void QLlcpSocketPrivate::changeState(QLLCPSocketState* state) +{ + m_state = state; + BEGIN_END +} + diff --git a/src/nfc/qllcpsocket_symbian_p.h b/src/nfc/qllcpsocket_symbian_p.h new file mode 100644 index 00000000..8b4cebe4 --- /dev/null +++ b/src/nfc/qllcpsocket_symbian_p.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSOCKET_P_H +#define QLLCPSOCKET_P_H + +#include <qconnectivityglobal.h> +#include "qllcpsocket.h" + +#include <QtCore/QObject> +#include <QSharedPointer> + +class CLlcpSocketType1; +class CLlcpSocketType2; + +QT_BEGIN_HEADER + +class QLLCPSocketState; + +class QLlcpSocketPrivate +{ + Q_DECLARE_PUBLIC(QLlcpSocket) + +public: + + QLlcpSocketPrivate(QLlcpSocket *q); + QLlcpSocketPrivate(CLlcpSocketType2* socketType2_symbian); + ~QLlcpSocketPrivate(); + +public: //Implementation of QLlcpSocket API + void connectToService(QNearFieldTarget *target, const QString &serviceUri); + void disconnectFromService(); + + bool bind(quint8 port); + + bool hasPendingDatagrams() const; + qint64 pendingDatagramSize() const; + + qint64 writeDatagram(const char *data, qint64 size); + qint64 writeDatagram(const QByteArray &datagram); + + qint64 readDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target = 0, quint8 *port = 0); + qint64 writeDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port); + qint64 writeDatagram(const QByteArray &datagram, QNearFieldTarget *target, quint8 port); + + QLlcpSocket::SocketError error() const; + QLlcpSocket::SocketState state() const; + + qint64 readData(char *data, qint64 maxlen); + qint64 writeData(const char *data, qint64 len); + + qint64 bytesAvailable() const; + bool canReadLine() const; + + bool waitForReadyRead(int msecs); + bool waitForBytesWritten(int msecs); + bool waitForConnected(int msecs); + bool waitForDisconnected(int msecs); + void attachCallbackHandler(QLlcpSocket *q); + +public: + CLlcpSocketType1* socketType1Instance(); + CLlcpSocketType2* socketType2Instance(); + CLlcpSocketType1* socketType1Handler() {return m_symbianSocketType1;} + CLlcpSocketType2* socketType2Handler() {return m_symbianSocketType2;} + + QLlcpSocket* qllcpsocket(CLlcpSocketType2*); + +public: + enum State { + ListeningState = QAbstractSocket::ListeningState, + }; + +public: + void invokeReadyRead(); + void invokeBytesWritten(qint64 bytes) ; + void invokeStateChanged(QLlcpSocket::SocketState socketState); + void invokeError(); + void invokeDisconnected(); + void invokeConnected(); + +// state machine part +public: + void changeState(QLLCPSocketState*); + QLLCPSocketState* getUnconnectedState() { return m_unconnectedState;} + QLLCPSocketState* getConnectedState() { return m_connectedState;} + QLLCPSocketState* getConnectingState() { return m_connectingState;} + QLLCPSocketState* getBindState() { return m_bindState;} + +private: + CLlcpSocketType1* m_symbianSocketType1; // own + CLlcpSocketType2* m_symbianSocketType2; // own + +private: + QLlcpSocket::SocketError m_error; + QLLCPSocketState* m_state; // not own + QLLCPSocketState* m_unconnectedState; // own + QLLCPSocketState* m_connectedState; // own + QLLCPSocketState* m_connectingState; // own + QLLCPSocketState* m_bindState; // own + + QLlcpSocket *q_ptr; // not own + + bool m_emittedReadyRead; + bool m_emittedBytesWritten; + +public: + int m_writeDatagramRefCount; +}; + +QT_END_HEADER + +#endif // QLLCPSOCKET_P_H diff --git a/src/nfc/qllcpstate_symbian_p.cpp b/src/nfc/qllcpstate_symbian_p.cpp new file mode 100644 index 00000000..35b03cc0 --- /dev/null +++ b/src/nfc/qllcpstate_symbian_p.cpp @@ -0,0 +1,551 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qllcpsocket_symbian_p.h" +#include "qllcpstate_symbian_p.h" +#include "symbian/llcpsockettype1_symbian.h" +#include "symbian/llcpsockettype2_symbian.h" +#include "symbian/nearfieldutility_symbian.h" + +#include "symbian/debug.h" + +QLLCPSocketState::QLLCPSocketState(QLlcpSocketPrivate* socket) + :m_socket(socket) +{} + +/*! + Connection-Less Mode +*/ +bool QLLCPUnconnected::Bind(quint8 port) +{ + BEGIN + bool ret = false; + if (connectionType2 == m_socketType) { + return ret; + } + + CLlcpSocketType1* socketHandler = m_socket->socketType1Instance(); + if (socketHandler != NULL ) + { + if (connectionUnknown == m_socketType) + { + m_socketType = connectionType1; + } + + if (socketHandler->Bind(port)) + { + ret = true; + m_socket->changeState(m_socket->getBindState()); + m_socket->invokeStateChanged(QLlcpSocket::BoundState); + } + } + END + return ret; +} + +/*! + Connection-Less Mode +*/ +bool QLLCPUnconnected::WaitForBytesWritten(int msecs) +{ + BEGIN + bool ret = false; + if (connectionType1 != m_socketType) { + return ret; + } + + ret = WaitForBytesWrittenType1Private(msecs); + END + return ret; +} + +bool QLLCPUnconnected::WaitForDisconnected(int msecs) +{ + Q_UNUSED(msecs); + BEGIN_END + return true; +} + +/*! + Connection-Less Mode +*/ +bool QLLCPBind::WaitForBytesWritten(int msecs) +{ + BEGIN + bool ret = WaitForBytesWrittenType1Private(msecs); + END + return ret; +} + +/*! + Failitator function for Connection-Less Mode +*/ +bool QLLCPSocketState::WaitForBytesWrittenType1Private(int msecs) +{ + bool ret = false; + + qDebug() << "m_writeDatagramRefCount: " << m_socket->m_writeDatagramRefCount; + if (m_socket->m_writeDatagramRefCount <= 0) + { + return ret; + } + + CLlcpSocketType1* socketHandler = m_socket->socketType1Instance(); + if (socketHandler != NULL) + { + ret = socketHandler->WaitForBytesWritten(msecs); + } + return ret; +} + +/*! + Connection-Less Mode +*/ +bool QLLCPBind::WaitForReadyRead(int msecs) +{ + BEGIN + bool ret = false; + CLlcpSocketType1* socketHandler = m_socket->socketType1Instance(); + if (socketHandler != NULL && socketHandler->HasPendingDatagrams()) + { + ret = true; + } + END + return ret; +} + +/*! + Connection-Less Mode +*/ +qint64 QLLCPUnconnected::WriteDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port) +{ + BEGIN + Q_UNUSED(target); + qint64 val = -1; + + if (connectionType2 == m_socketType){ + return val; + } + + CLlcpSocketType1* socketHandler = m_socket->socketType1Instance(); + + if (socketHandler != NULL) + { + if (connectionUnknown == m_socketType) + { + m_socketType = connectionType1; + } + TPtrC8 myDescriptor((const TUint8*)data, size); + val = socketHandler->StartWriteDatagram(myDescriptor, port); + } + END + + return val; +} + +/*! + Connection-Less Mode +*/ +qint64 QLLCPBind::WriteDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port) +{ + BEGIN + Q_UNUSED(target); + qint64 val = -1; + CLlcpSocketType1* socketHandler = m_socket->socketType1Instance(); + if (socketHandler != NULL) + { + TPtrC8 myDescriptor((const TUint8*)data, size); + val = socketHandler->StartWriteDatagram(myDescriptor, port); + } + END + return val; +} + +/*! + Connection-Oriented Mode - Client side socket write +*/ +qint64 QLLCPConnected::WriteDatagram(const char *data, qint64 size) +{ + BEGIN + qint64 val = -1; + CLlcpSocketType2* socketHandler = m_socket->socketType2Handler(); + if (socketHandler != NULL) + { + TPtrC8 myDescriptor((const TUint8*)data, size); + val = socketHandler->StartWriteDatagram(myDescriptor); + } + END + return val; +} + +/*! + Connection-Oriented Mode +*/ +bool QLLCPConnected::WaitForBytesWritten(int msecs) +{ + BEGIN + bool ret = false; + CLlcpSocketType2* socketHandler = m_socket->socketType2Handler(); + if (socketHandler != NULL) + { + ret = socketHandler->WaitForBytesWritten(msecs); + } + END + return ret; +} + +/*! + Connection-Oriented Mode +*/ +bool QLLCPConnected::WaitForReadyRead(int msecs) +{ + BEGIN + bool ret = false; + CLlcpSocketType2* socketHandler = m_socket->socketType2Handler(); + if (socketHandler != NULL) + { + ret = socketHandler->WaitForReadyRead(msecs); + } + END + return ret; +} + +/*! + Connection-Less Mode +*/ +qint64 QLLCPBind::ReadDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target, quint8 *port) +{ + BEGIN + + Q_UNUSED(target); + qint64 val = -1; + + CLlcpSocketType1* socketHandler = m_socket->socketType1Instance(); + + if (socketHandler != NULL) + { + TPtr8 ptr((TUint8*)data, (TInt)maxSize); + if (port == NULL){ + val = socketHandler->ReadDatagram(ptr); + } + else { + val = socketHandler->ReadDatagram(ptr, *port); + } + } + + END + return val; +} + + +/*! + Connection-Oriented Mode - Client side socket read +*/ +qint64 QLLCPConnected::ReadDatagram(char *data, qint64 maxSize,QNearFieldTarget **target, quint8 *port ) +{ + BEGIN + qint64 val = -1; + + if ( port != NULL || ( target != NULL && *target != NULL )) + { + return val; + } + + CLlcpSocketType2* socketHandler = m_socket->socketType2Handler(); + if (socketHandler != NULL) + { + // The length of the descriptor is set to zero + // and its maximum length is set to maxSize + TPtr8 ptr((TUint8*)data, (TInt)maxSize); + + bool ret = socketHandler->ReceiveData(ptr); + if(ret) { + val = ptr.Length(); + } + } + + END + return val; +} + +/*! + Connection-Oriented Mode +*/ +void QLLCPConnected::DisconnectFromService() +{ + BEGIN + DisconnectFromServiceType2Private(); + END + return; +} + +/*! + Connection-Oriented Mode +*/ +void QLLCPConnecting::DisconnectFromService() +{ + BEGIN + DisconnectFromServiceType2Private(); + END + return; +} + +void QLLCPSocketState::DisconnectFromServiceType2Private() +{ + BEGIN + CLlcpSocketType2* socketHandler = m_socket->socketType2Handler(); + if (NULL != socketHandler) + { + if (socketHandler->DisconnectFromService() == KErrNone) + { + m_socket->changeState(m_socket->getUnconnectedState()); + m_socket->invokeStateChanged(QLlcpSocket::UnconnectedState); + } + else + { + m_socket->invokeError(); + } + } + else + { + m_socket->invokeError(); + } + END +} + +/*! + Connection-Oriented Mode +*/ +void QLLCPUnconnected::DisconnectFromService() +{ + BEGIN_END + return; +} + +/*! + Connection-Oriented Mode +*/ +bool QLLCPConnecting::WaitForConnected(int msecs) +{ + BEGIN + bool ret = false; + CLlcpSocketType2* socketHandler = m_socket->socketType2Handler(); + if (socketHandler != NULL) + { + ret = socketHandler->WaitForConnected(msecs); + } + END + return ret; +} + +/*! + Connection-Oriented Mode +*/ +bool QLLCPConnecting::WaitForBytesWritten(int) +{ + return false; +} + +/*! + Connection-Oriented Mode +*/ +void QLLCPUnconnected::ConnectToService(QNearFieldTarget *target, const QString &serviceUri) +{ + BEGIN + if (connectionType1 == m_socketType){ + m_socket->invokeError(); + END + return; + } + + CLlcpSocketType2* socketHandler = m_socket->socketType2Instance(); + + if (socketHandler != NULL) + { + if (connectionUnknown == m_socketType) + { + m_socketType = connectionType2; + } + + TRAPD(err, socketHandler->ConnectToServiceL(serviceUri)); + if (KErrNone == err) + { + m_socket->changeState(m_socket->getConnectingState()); + m_socket->invokeStateChanged(QLlcpSocket::ConnectingState); + } + else + { + m_socket->invokeError(); + } + + } + else + { + m_socket->invokeError(); + } + + END +} + +/*! + Connection-Oriented Mode +*/ +void QLLCPConnecting::ConnectToService(QNearFieldTarget *target, const QString &serviceUri) + { + Q_UNUSED(target); + Q_UNUSED(serviceUri); + m_socket->invokeError(); + qWarning("QLlcpSocket::connectToService() called when already connecting"); + BEGIN_END + return; + } + +/*! + Connection-Oriented Mode +*/ +void QLLCPConnected::ConnectToService(QNearFieldTarget *target, const QString &serviceUri) + { + Q_UNUSED(target); + Q_UNUSED(serviceUri); + m_socket->invokeError(); + qWarning("QLlcpSocket::connectToService() called when already connected"); + BEGIN_END + return; + } + +/*! + Constructors +*/ +QLLCPUnconnected::QLLCPUnconnected(QLlcpSocketPrivate* aSocket) + :QLLCPSocketState(aSocket), + m_socketType(connectionUnknown) +{} + + +QLLCPBind::QLLCPBind(QLlcpSocketPrivate* aSocket) + :QLLCPSocketState(aSocket) +{} + +QLLCPConnecting::QLLCPConnecting(QLlcpSocketPrivate* aSocket) + :QLLCPSocketState(aSocket) +{} + +QLLCPConnected::QLLCPConnected(QLlcpSocketPrivate* aSocket) + :QLLCPSocketState(aSocket) +{} + +qint64 QLLCPSocketState::ReadDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target, quint8 *port) +{ + Q_UNUSED(data); + Q_UNUSED(maxSize); + Q_UNUSED(target); + Q_UNUSED(port); + BEGIN_END + return -1; +} + +/*! + State base class default implementation +*/ +qint64 QLLCPSocketState::WriteDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port) +{ + Q_UNUSED(data); + Q_UNUSED(size); + Q_UNUSED(target); + Q_UNUSED(port); + BEGIN_END + return -1; +} + +qint64 QLLCPSocketState::WriteDatagram(const char *data, qint64 size) +{ + Q_UNUSED(data); + Q_UNUSED(size); + BEGIN_END + return -1; +} + +bool QLLCPSocketState::Bind(quint8 port) +{ + Q_UNUSED(port); + BEGIN_END + return false; +} + + bool QLLCPSocketState::WaitForReadyRead(int msecs) + { + Q_UNUSED(msecs); + BEGIN_END + return false; + } + +bool QLLCPSocketState::WaitForConnected(int msecs) +{ + Q_UNUSED(msecs); + BEGIN_END + return false; +} + +bool QLLCPSocketState::WaitForDisconnected(int msecs) +{ + Q_UNUSED(msecs); + BEGIN_END + return false; +} + +void QLLCPSocketState::ConnectToService(QNearFieldTarget *target, const QString &serviceUri) +{ + Q_UNUSED(target); + Q_UNUSED(serviceUri); + m_socket->invokeError(); + BEGIN_END +} + +void QLLCPSocketState::DisconnectFromService() +{ + m_socket->invokeError(); + BEGIN_END +} + diff --git a/src/nfc/qllcpstate_symbian_p.h b/src/nfc/qllcpstate_symbian_p.h new file mode 100644 index 00000000..38d6bb17 --- /dev/null +++ b/src/nfc/qllcpstate_symbian_p.h @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLLCPSOCKETSTATE_P_H +#define QLLCPSOCKETSTATE_P_H + +#include <qconnectivityglobal.h> +#include "qllcpsocket.h" + +#include <QtCore/QObject> + +QT_BEGIN_HEADER + +class QLlcpSocketPrivate; + +/*! + \QLLCPSocketState +*/ +class QLLCPSocketState +{ +public: + explicit QLLCPSocketState(QLlcpSocketPrivate*); + +public: + virtual QLlcpSocket::SocketState state() const = 0; + virtual bool WaitForBytesWritten(int) = 0; + +public: + virtual qint64 ReadDatagram(char *data, qint64 maxSize, + QNearFieldTarget **target = NULL, quint8 *port = NULL); + virtual qint64 WriteDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port); + virtual qint64 WriteDatagram(const char *data, qint64 size); + + virtual bool Bind(quint8 port); + virtual void ConnectToService(QNearFieldTarget *target, const QString &serviceUri); + virtual void DisconnectFromService(); + virtual bool WaitForReadyRead(int); + virtual bool WaitForConnected(int); + virtual bool WaitForDisconnected(int); + +protected: + bool WaitForBytesWrittenType1Private(int); + void DisconnectFromServiceType2Private(); +public: + QLlcpSocketPrivate* m_socket; +}; + +/*! + \QLLCPUnconnected +*/ +class QLLCPUnconnected: public QLLCPSocketState +{ +public: + explicit QLLCPUnconnected(QLlcpSocketPrivate*); + +public: // from base class + QLlcpSocket::SocketState state() const {return QLlcpSocket::UnconnectedState;} + bool Bind(quint8 port); + void ConnectToService(QNearFieldTarget *target, const QString &serviceUri); + void DisconnectFromService(); + qint64 WriteDatagram(const char *data, qint64 size, + QNearFieldTarget *target, quint8 port); + bool WaitForBytesWritten(int); + bool WaitForDisconnected(int); + +public: +public: + enum SocketType + { + connectionType1 = 1, // ConnectionLess mode + connectionType2 = 2, // ConnectionOriented mode + connectionUnknown = -1 + }; + SocketType m_socketType; +}; + +/*! + \QLLCPConnecting +*/ +class QLLCPConnecting: public QLLCPSocketState +{ +public: + explicit QLLCPConnecting(QLlcpSocketPrivate*); + +public: + QLLCPSocketState* Instance(QLlcpSocketPrivate* aSocket); + +public: // from base class + QLlcpSocket::SocketState state() const {return QLlcpSocket::ConnectingState;} + void ConnectToService(QNearFieldTarget *target, const QString &serviceUri); + void DisconnectFromService(); + bool WaitForConnected(int); + bool WaitForBytesWritten(int); +}; + +/*! + \QLLCPConnecting +*/ +class QLLCPConnected: public QLLCPSocketState +{ +public: + explicit QLLCPConnected(QLlcpSocketPrivate*); + +public: // from base class + QLlcpSocket::SocketState state() const {return QLlcpSocket::ConnectedState;} + void ConnectToService(QNearFieldTarget *target, const QString &serviceUri); + void DisconnectFromService(); + qint64 WriteDatagram(const char *data, qint64 size); + qint64 ReadDatagram(char *data, qint64 maxSize, QNearFieldTarget **target = NULL, quint8 *port = NULL); + bool WaitForBytesWritten(int msecs); + bool WaitForReadyRead(int msecs); +}; + +/*! + \QLLCPBind +*/ +class QLLCPBind: public QLLCPSocketState + { +public: + explicit QLLCPBind(QLlcpSocketPrivate*); + +public://from base class + QLlcpSocket::SocketState state() const {return QLlcpSocket::BoundState;} + qint64 WriteDatagram(const char *data, qint64 size,QNearFieldTarget *target, quint8 port); + qint64 ReadDatagram(char *data, qint64 maxSize,QNearFieldTarget **target = 0, quint8 *port = 0); + bool WaitForBytesWritten(int msecs); + bool WaitForReadyRead(int msecs); + }; + +QT_END_HEADER + +#endif //QLLCPSTATE_P_H diff --git a/src/nfc/qndeffilter.cpp b/src/nfc/qndeffilter.cpp new file mode 100644 index 00000000..ce25c4ab --- /dev/null +++ b/src/nfc/qndeffilter.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qndeffilter.h" + +#include <QtCore/QList> + +/*! + \class QNdefFilter + \brief The QNdefFilter class provides a filter for matching NDEF messages. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + The QNdefFilter encapsulates the structure of an NDEF message and is used by + QNearFieldManager::registerNdefMessageHandler() to match NDEF message that have a particular + structure. + + The following filter matches NDEF messages that contain a single smart poster record: + + \code + QNdefFilter filter; + filter.append(QNdefRecord::NfcRtd, "Sp"); + \endcode + + The following filter matches NDEF messages that contain a URI, a localized piece of text and an + optional JPEG image. The order of the records must be in the order specified: + + \code + QNdefFilter filter; + filter.setOrderMatch(true); + filter.appendRecord(QNdefRecord::NfcRtd, "U"); + filter.appendRecord<QNdefNfcTextRecord>(); + filter.appendRecord(QNdefRecord::Mime, "image/jpeg", 0, 1); + \endcode +*/ + +/*! + \fn void QNdefFilter::appendRecord(unsigned int min, unsigned int max) + + Appends a record matching the template parameter to the NDEF filter. The record must occur + between \a min and \a max times in the NDEF message. +*/ + +class QNdefFilterPrivate : public QSharedData +{ +public: + QNdefFilterPrivate(); + + bool orderMatching; + QList<QNdefFilter::Record> filterRecords; +}; + +QNdefFilterPrivate::QNdefFilterPrivate() +: orderMatching(false) +{ +} + +/*! + Constructs a new NDEF filter. +*/ +QNdefFilter::QNdefFilter() +: d(new QNdefFilterPrivate) +{ +} + +/*! + constructs a new NDEF filter that is a copy of \a other. +*/ +QNdefFilter::QNdefFilter(const QNdefFilter &other) +: d(other.d) +{ +} + +/*! + Destroys the NDEF filter. +*/ +QNdefFilter::~QNdefFilter() +{ +} + +/*! + Assigns \a other to this filter and returns a reference to this filter. +*/ +QNdefFilter &QNdefFilter::operator=(const QNdefFilter &other) +{ + if (d != other.d) + d = other.d; + + return *this; +} + +/*! + Clears the filter. +*/ +void QNdefFilter::clear() +{ + d->orderMatching = false; + d->filterRecords.clear(); +} + +/*! + Sets the ording requirements of the filter. If \a on is true the filter will only match if the + order of records in the filter matches the order of the records in the NDEF message. If \a on + is false the order of the records is not taken into account when matching. + + By default record order is not taken into account. +*/ +void QNdefFilter::setOrderMatch(bool on) +{ + d->orderMatching = on; +} + +/*! + Returns true if the filter takes NDEF record order into account when matching; otherwise + returns false. +*/ +bool QNdefFilter::orderMatch() const +{ + return d->orderMatching; +} + +/*! + Appends a record with type name format \a typeNameFormat and type \a type to the NDEF filter. + The record must occur between \a min and \a max times in the NDEF message. +*/ +void QNdefFilter::appendRecord(QNdefRecord::TypeNameFormat typeNameFormat, const QByteArray &type, + unsigned int min, unsigned int max) +{ + QNdefFilter::Record record; + + record.typeNameFormat = typeNameFormat; + record.type = type; + record.minimum = min; + record.maximum = max; + + d->filterRecords.append(record); +} + +/*! + Appends \a record to the NDEF filter. +*/ +void QNdefFilter::appendRecord(const Record &record) +{ + d->filterRecords.append(record); +} + +/*! + Returns the NDEF record at index \a i. +*/ +QNdefFilter::Record QNdefFilter::recordAt(int i) const +{ + return d->filterRecords.at(i); +} + +/*! + Returns the number of NDEF records in the filter. +*/ +int QNdefFilter::recordCount() const +{ + return d->filterRecords.count(); +} + diff --git a/src/nfc/qndeffilter.h b/src/nfc/qndeffilter.h new file mode 100644 index 00000000..5cc92863 --- /dev/null +++ b/src/nfc/qndeffilter.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNDEFFILTER_H +#define QNDEFFILTER_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QSharedDataPointer> + +#include <qndefrecord.h> + +QT_BEGIN_HEADER + +class QNdefFilterPrivate; +class Q_CONNECTIVITY_EXPORT QNdefFilter +{ +public: + QNdefFilter(); + QNdefFilter(const QNdefFilter &other); + ~QNdefFilter(); + + void clear(); + + void setOrderMatch(bool on); + bool orderMatch() const; + + struct Record { + QNdefRecord::TypeNameFormat typeNameFormat; + QByteArray type; + unsigned int minimum; + unsigned int maximum; + }; + + template<typename T> + void appendRecord(unsigned int min = 1, unsigned int max = 1); + void appendRecord(QNdefRecord::TypeNameFormat typeNameFormat, const QByteArray &type, + unsigned int min = 1, unsigned int max = 1); + void appendRecord(const Record &record); + + int recordCount() const; + Record recordAt(int i) const; + + QNdefFilter &operator=(const QNdefFilter &other); + +private: + QSharedDataPointer<QNdefFilterPrivate> d; +}; + +template <typename T> +void QNdefFilter::appendRecord(unsigned int min, unsigned int max) +{ + T record; + + appendRecord(record.typeNameFormat(), record.type(), min, max); +} + +QT_END_HEADER + +#endif // QNDEFFILTER_H diff --git a/src/nfc/qndefmessage.cpp b/src/nfc/qndefmessage.cpp new file mode 100644 index 00000000..532e8bff --- /dev/null +++ b/src/nfc/qndefmessage.cpp @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qndefmessage.h" +#include "qndefrecord_p.h" + +/*! + \class QNdefMessage + \brief The QNdefMessage class provides an NFC NDEF message. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + A QNdefMessage is a collection of 0 or more QNdefRecords. QNdefMessage inherits from + QList<QNdefRecord> and therefore the standard QList functions can be used to manipulate the + NDEF records in the message. + + NDEF messages can be parsed from a byte array conforming to the NFC Data Exchange Format + technical specification by using the fromByteArray() static function. Conversely QNdefMessages + can be converted into a byte array with the toByteArray() function. +*/ + +/*! + \fn QNdefMessage::QNdefMessage() + + Constructs a new empty NDEF message. +*/ + +/*! + \fn QNdefMessage::QNdefMessage(const QNdefRecord &record) + + Constructs a new NDEF message containing a single record \a record. +*/ + +/*! + \fn QNdefMessage::QNdefMessage(const QNdefMessage &message) + + Constructs a new NDEF message that is a copy of \a message. +*/ + +/*! + \fn QNdefMessage::QNdefMessage(const QList<QNdefRecord> &records) + + Constructs a new NDEF message that contains all of the records in \a records. +*/ + +/*! + Returns an NDEF message parsed from the contents of \a message. + + The \a message parameter is interpreted as the raw message format defined in the NFC Data + Exchange Format technical specification. + + If a parse error occurs an empty NDEF message is returned. +*/ +QNdefMessage QNdefMessage::fromByteArray(const QByteArray &message) +{ + QNdefMessage result; + + bool seenMessageBegin = false; + bool seenMessageEnd = false; + + QByteArray partialChunk; + QNdefRecord record; + + QByteArray::const_iterator i = message.begin(); + while (i < message.constEnd()) { + quint8 flags = *i; + + bool messageBegin = flags & 0x80; + bool messageEnd = flags & 0x40; + + bool cf = flags & 0x20; + bool sr = flags & 0x10; + bool il = flags & 0x08; + quint8 typeNameFormat = flags & 0x07; + + if (messageBegin && seenMessageBegin) { + qWarning("Got message begin but already parsed some records"); + return QNdefMessage(); + } else if (!messageBegin && !seenMessageBegin) { + qWarning("Haven't got message begin yet"); + return QNdefMessage(); + } else if (messageBegin && !seenMessageBegin) { + seenMessageBegin = true; + } + if (messageEnd && seenMessageEnd) { + qWarning("Got message end but already parsed final record"); + return QNdefMessage(); + } else if (messageEnd && !seenMessageEnd) { + seenMessageEnd = true; + } + if (cf && (typeNameFormat != 0x06) && !partialChunk.isEmpty()) { + qWarning("partial chunk not empty or typeNameFormat not 0x06 as expected"); + return QNdefMessage(); + } + + int headerLength = 1; + headerLength += (sr) ? 1 : 4; + headerLength += (il) ? 1 : 0; + + if (i + headerLength >= message.constEnd()) { + qWarning("Unexpected end of message"); + return QNdefMessage(); + } + + quint8 typeLength = *(++i); + + if ((typeNameFormat == 0x06) && (typeLength != 0)) { + qWarning("Invalid chunked data, TYPE_LENGTH != 0"); + return QNdefMessage(); + } + + quint32 payloadLength; + if (sr) + payloadLength = *(++i); + else { + payloadLength = quint8(*(++i)) << 24; + payloadLength |= quint8(*(++i)) << 16; + payloadLength |= quint8(*(++i)) << 8; + payloadLength |= quint8(*(++i)) << 0; + } + + quint8 idLength; + if (il) + idLength = *(++i); + else + idLength = 0; + + int contentLength = typeLength + payloadLength + idLength; + if (i + contentLength >= message.constEnd()) { + qWarning("Unexpected end of message"); + return QNdefMessage(); + } + + if ((typeNameFormat == 0x06) && (idLength != 0)) { + qWarning("Invalid chunked data, IL != 0"); + return QNdefMessage(); + } + + if (typeNameFormat != 0x06) + record.setTypeNameFormat(QNdefRecord::TypeNameFormat(typeNameFormat)); + + if (typeLength > 0) { + QByteArray type(++i, typeLength); + record.setType(type); + i += typeLength - 1; + } + + if (idLength > 0) { + QByteArray id(++i, idLength); + record.setId(id); + i += idLength - 1; + } + + if (payloadLength > 0) { + QByteArray payload(++i, payloadLength); + + + if (cf) { + // chunked payload, except last + partialChunk.append(payload); + } else if (typeNameFormat == 0x06) { + // last chunk of chunked payload + record.setPayload(partialChunk + payload); + partialChunk.clear(); + } else { + // non-chunked payload + record.setPayload(payload); + } + + i += payloadLength - 1; + } + + if (!cf) + result.append(record); + + if (!cf && seenMessageEnd) + break; + + // move to start of next record + ++i; + } + + if (!seenMessageBegin && !seenMessageEnd) { + qWarning("Malformed NDEF Message, missing begin or end."); + return QNdefMessage(); + } + + return result; +} + +/*! + Returns true if this NDEF message is equivalent to \a other; otherwise returns false. + + An empty message (i.e. isEmpty() returns true) is equivalent to a NDEF message containing a + single record of type QNdefRecord::Empty. +*/ +bool QNdefMessage::operator==(const QNdefMessage &other) const +{ + // both records are empty + if (isEmpty() && other.isEmpty()) + return true; + + // compare empty to really empty + if (isEmpty() && other.count() == 1 && other.first().typeNameFormat() == QNdefRecord::Empty) + return true; + if (other.isEmpty() && count() == 1 && first().typeNameFormat() == QNdefRecord::Empty) + return true; + + if (count() != other.count()) + return false; + + for (int i = 0; i < count(); ++i) { + if (at(i) != other.at(i)) + return false; + } + + return true; +} + +/*! + Returns the NDEF message as a byte array. + + The return value of this function conforms to the format defined in the NFC Data Exchange + Format technical specification. +*/ +QByteArray QNdefMessage::toByteArray() const +{ + // An empty message is treated as a message containing a single empty record. + if (isEmpty()) + return QNdefMessage(QNdefRecord()).toByteArray(); + + QByteArray m; + + for (int i = 0; i < count(); ++i) { + const QNdefRecord &record = at(i); + + quint8 flags = record.typeNameFormat(); + + if (i == 0) + flags |= 0x80; + if (i == count() - 1) + flags |= 0x40; + + // cf (chunked records) not supported yet + + if (record.payload().length() < 255) + flags |= 0x10; + + if (!record.id().isEmpty()) + flags |= 0x08; + + m.append(flags); + m.append(record.type().length()); + + if (flags & 0x10) { + m.append(quint8(record.payload().length())); + } else { + quint32 length = record.payload().length(); + m.append(length >> 24); + m.append(length >> 16); + m.append(length >> 8); + m.append(length & 0x000000ff); + } + + if (flags & 0x08) + m.append(record.id().length()); + + if (!record.type().isEmpty()) + m.append(record.type()); + + if (!record.id().isEmpty()) + m.append(record.id()); + + if (!record.payload().isEmpty()) + m.append(record.payload()); + } + + return m; +} diff --git a/src/nfc/qndefmessage.h b/src/nfc/qndefmessage.h new file mode 100644 index 00000000..e6aef623 --- /dev/null +++ b/src/nfc/qndefmessage.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNDEFMESSAGE_H +#define QNDEFMESSAGE_H + +#include "../qtconnectivityglobal.h" + +#include <qndefrecord.h> + +#include <QtCore/QVector> +#include <QtCore/QSet> +#include <QtCore/QList> +#include <QtCore/QMetaType> + +QT_BEGIN_HEADER + +class Q_CONNECTIVITY_EXPORT QNdefMessage : public QList<QNdefRecord> +{ +public: + inline QNdefMessage() { } + inline explicit QNdefMessage(const QNdefRecord &record) { append(record); } + inline QNdefMessage(const QNdefMessage &message) : QList<QNdefRecord>(message) { } + inline QNdefMessage(const QList<QNdefRecord> &records) : QList<QNdefRecord>(records) { } + + bool operator==(const QNdefMessage &other) const; + + QByteArray toByteArray() const; + + static QNdefMessage fromByteArray(const QByteArray &message); +}; + +Q_DECLARE_METATYPE(QNdefMessage) + +QT_END_HEADER + +#endif // QNDEFMESSAGE_H diff --git a/src/nfc/qndefnfctextrecord.cpp b/src/nfc/qndefnfctextrecord.cpp new file mode 100644 index 00000000..b9146f9a --- /dev/null +++ b/src/nfc/qndefnfctextrecord.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qndefnfctextrecord.h> + +#include <QtCore/QTextCodec> +#include <QtCore/QLocale> + +/*! + \class QNdefNfcTextRecord + \brief The QNdefNfcTextRecord class provides an NFC RTD-Text + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + RTD-Text encapsulates a user displayable text record. +*/ + +/*! + \enum QNdefNfcTextRecord::Encoding + + This enum describes the text encoding standard used. + + \value Utf8 The text is encoded with UTF-8. + \value Utf16 The text is encoding with UTF-16. +*/ + +/*! + Returns the locale of the text record. +*/ +QString QNdefNfcTextRecord::locale() const +{ + const QByteArray p = payload(); + + if (p.isEmpty()) + return QString(); + + quint8 status = p.at(0); + + quint8 codeLength = status & 0x3f; + + return QString::fromAscii(p.constData() + 1, codeLength); +} + +/*! + Sets the locale of the text record to \a locale. +*/ +void QNdefNfcTextRecord::setLocale(const QString &locale) +{ + QByteArray p = payload(); + + quint8 status = p.isEmpty() ? 0 : p.at(0); + + quint8 codeLength = status & 0x3f; + + quint8 newStatus = (status & 0xd0) | locale.length(); + + p[0] = newStatus; + p.replace(1, codeLength, locale.toAscii()); + + setPayload(p); +} + +/*! + Returns the contents of the text record as a string. +*/ +QString QNdefNfcTextRecord::text() const +{ + const QByteArray p = payload(); + + if (p.isEmpty()) + return QString(); + + quint8 status = p.at(0); + + bool utf16 = status & 0x80; + quint8 codeLength = status & 0x3f; + + QTextCodec *codec = QTextCodec::codecForName(utf16 ? "UTF-16BE" : "UTF-8"); + + return codec->toUnicode(p.constData() + 1 + codeLength, p.length() - 1 - codeLength); +} + +/*! + Sets the contents of the text record to \a text. +*/ +void QNdefNfcTextRecord::setText(const QString text) +{ + if (payload().isEmpty()) + setLocale(QLocale().name()); + + QByteArray p = payload(); + + quint8 status = p.at(0); + + bool utf16 = status & 0x80; + quint8 codeLength = status & 0x3f; + + p.truncate(1 + codeLength); + + QTextCodec *codec = QTextCodec::codecForName(utf16 ? "UTF-16BE" : "UTF-8"); + + p += codec->fromUnicode(text); + + setPayload(p); +} + +/*! + Returns the encoding of the contents. +*/ +QNdefNfcTextRecord::Encoding QNdefNfcTextRecord::encoding() const +{ + if (payload().isEmpty()) + return Utf8; + + QByteArray p = payload(); + + quint8 status = p.at(0); + + bool utf16 = status & 0x80; + + if (utf16) + return Utf16; + else + return Utf8; +} + +/*! + Sets the enconding of the contents to \a encoding. +*/ +void QNdefNfcTextRecord::setEncoding(Encoding encoding) +{ + QByteArray p = payload(); + + quint8 status = p.isEmpty() ? 0 : p.at(0); + + QString string = text(); + + if (encoding == Utf8) + status &= ~0x80; + else + status |= 0x80; + + p[0] = status; + + setPayload(p); + + setText(string); +} + diff --git a/src/nfc/qndefnfctextrecord.h b/src/nfc/qndefnfctextrecord.h new file mode 100644 index 00000000..2333e3ff --- /dev/null +++ b/src/nfc/qndefnfctextrecord.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNDEFNFCTEXTRECORD_H +#define QNDEFNFCTEXTRECORD_H + +#include "../qtconnectivityglobal.h" + +#include <qndefrecord.h> + +QT_BEGIN_HEADER + +class Q_CONNECTIVITY_EXPORT QNdefNfcTextRecord : public QNdefRecord +{ +public: + Q_DECLARE_NDEF_RECORD(QNdefNfcTextRecord, QNdefRecord::NfcRtd, "T", QByteArray(1, char(0))) + + QString locale() const; + void setLocale(const QString &locale); + + QString text() const; + void setText(const QString text); + + enum Encoding { + Utf8, + Utf16 + }; + + Encoding encoding() const; + void setEncoding(Encoding encoding); +}; + +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(QNdefNfcTextRecord, QNdefRecord::NfcRtd, "T") + +QT_END_HEADER + +#endif // QNDEFNFCTEXTRECORD_H diff --git a/src/nfc/qndefnfcurirecord.cpp b/src/nfc/qndefnfcurirecord.cpp new file mode 100644 index 00000000..4a495d2d --- /dev/null +++ b/src/nfc/qndefnfcurirecord.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qndefnfcurirecord.h" + +#include <QtCore/QString> +#include <QtCore/QUrl> + +#include <QtCore/QDebug> + +/*! + \class QNdefNfcUriRecord + \brief The QNdefNfcUriRecord class provides an NFC RTD-URI + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + RTD-URI encapsulates a URI. +*/ + +static const char * const abbreviations[] = { + 0, + "http://www.", + "https://www.", + "http://", + "https://", + "tel:", + "mailto:", + "ftp://anonymous:anonymous@", + "ftp://ftp.", + "ftps://", + "sftp://", + "smb://", + "nfs://", + "ftp://", + "dav://", + "news:", + "telnet://", + "imap:", + "rtsp://", + "urn:", + "pop:", + "sip:", + "sips:", + "tftp:", + "btspp://", + "btl2cap://", + "btgoep://", + "tcpobex://", + "irdaobex://", + "file://", + "urn:epc:id:", + "urn:epc:tag:", + "urn:epc:pat:", + "urn:epc:raw:", + "urn:epc:", + "urn:nfc:", +}; + +/*! + Returns the URI of this URI record. +*/ +QUrl QNdefNfcUriRecord::uri() const +{ + const QByteArray p = payload(); + + if (p.isEmpty()) + return QUrl(); + + quint8 code = p.at(0); + if (code >= sizeof(abbreviations) / sizeof(*abbreviations)) + code = 0; + + return QUrl(QLatin1String(abbreviations[code]) + QString::fromUtf8(p.mid(1), p.length() - 1)); +} + +/*! + Sets the URI of this URI record to \a uri. +*/ +void QNdefNfcUriRecord::setUri(const QUrl &uri) +{ + int abbrevs = sizeof(abbreviations) / sizeof(*abbreviations); + + for (int i = 1; i < abbrevs; ++i) { + if (uri.toString().startsWith(QLatin1String(abbreviations[i]))) { + QByteArray p; + + p[0] = i; + p += uri.toString().mid(qstrlen(abbreviations[i])).toUtf8(); + + setPayload(p); + + return; + } + } + + QByteArray p; + p[0] = 0; + p += uri.toString().toUtf8(); + + setPayload(p); +} + diff --git a/src/nfc/qndefnfcurirecord.h b/src/nfc/qndefnfcurirecord.h new file mode 100644 index 00000000..10bddff7 --- /dev/null +++ b/src/nfc/qndefnfcurirecord.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNDEFNFCURIRECORD_H +#define QNDEFNFCURIRECORD_H + +#include "../qtconnectivityglobal.h" + +#include <qndefrecord.h> + +QT_FORWARD_DECLARE_CLASS(QUrl) + +QT_BEGIN_HEADER + +class Q_CONNECTIVITY_EXPORT QNdefNfcUriRecord : public QNdefRecord +{ +public: + Q_DECLARE_NDEF_RECORD(QNdefNfcUriRecord, QNdefRecord::NfcRtd, "U", QByteArray(0, char(0))) + + QUrl uri() const; + void setUri(const QUrl &uri); +}; + +Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(QNdefNfcUriRecord, QNdefRecord::NfcRtd, "U") + +QT_END_HEADER + +#endif // QNDEFNFCURIRECORD_H diff --git a/src/nfc/qndefrecord.cpp b/src/nfc/qndefrecord.cpp new file mode 100644 index 00000000..4db78e2b --- /dev/null +++ b/src/nfc/qndefrecord.cpp @@ -0,0 +1,349 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qndefrecord.h" +#include "qndefrecord_p.h" + +#include <QtCore/QHash> + +/*! + \class QNdefRecord + \brief The QNdefRecord class provides an NFC NDEF record. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + QNdefRecord and derived classes are used to parse the contents of + \l {QNdefMessage}{NDEF messages} and create new NDEF messages. + + Use typeNameFormat(), userTypeNameFormat(), setTypeNameFormat() and setUserTypeNameFormat() to + get and set the type name format of the NDEF record. + + Use type() and setType() to get and set the type of the NDEF record. + + Use id() and setId() to get and set the id of the NDEF record. + + Use payload() and setPayload() to get and set the NDEF record payload. isEmpty() can be used + to test if the payload is empty. + + QNdefRecord is an implicitly shared class. This means you can efficiently convert between + QNdefRecord and specialized record classes. The isRecordType() template function can be used + to test if a conversion is possible. The following example shows how to test if a QNdefRecord + is an NFC RTD Text record and extract the text information from it. + + \snippet snippets/connectivity/nfc.cpp Record conversion + + \section1 Creating specialized NDEF record classes + + Specialized NDEF record classes can be easily created with the Q_DECLARE_NDEF_RECORD() and + Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD() macros. The following example shows the class + declaration of the hypothetical \i {example.com:f} record type that encapsulates a single int + property foo. + + \snippet snippets/connectivity/nfc.cpp Specialized class definition + + The developer only needs to provide implementations for the \c {foo()} and \c {setFoo()} + functions that parse and set the contents of the NDEF record's payload. +*/ + +/*! + \enum QNdefRecord::TypeNameFormat + + This enum describes the type name format of an NDEF record. + + \value Empty An empty NDEF record, the record does not contain a payload + \value NfcRtd The NDEF record type is defined by an NFC RTD Specification + \value Mime The NDEF record type follows the construct described in RFC 2046 + \value Uri The NDEF record type follows the construct described in RFC 3986 + \value ExternalRtd The NDEF record type follows the construct for external type names + described the NFC RTD Specification + \value Unknown The type of the record is unknown and should be treated similar to content + with MIME type 'application/octet-stream' without further context +*/ + +/*! + \fn bool QNdefRecord::isRecordType() const + + Returns true if the NDEF record is of the specified record type; otherwise returns false. +*/ + +/*! + \fn bool QNdefRecord::operator!=(const QNdefRecord &other) const + + Returns true if this NDEF record does not equal \a other; otherwise return false. +*/ + +/*! + \macro Q_DECLARE_NDEF_RECORD(className, typeNameFormat, type, initialPayload) + \relates QNdefRecord + + This macro declares default and copy constructors for specialized NDEF record classes. + + \a className is the name of the specialized class, \a typeNameFormat is the appropriate + QNdefRecord::TypeNameFormat for the custom type and \a type is the type without the NID or NSS + prefixes. That is \i {example.com:f} not \i {urn:nfc:ext:example.com:f}. \a initialPayload + is the initial payload of an empty record, it must be a QByteArray or a type that can be + implicitly converted into a QByteArray. + + See the section on \l {Creating specialized NDEF record classes} for details. + + \sa Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD() +*/ + +/*! + \macro Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(className, typeNameFormat, type) + \relates QNdefRecord + + This macro declares a template specialization for the QNdefRecord::isRecordType() function. + + This macro should be used in the header file directly after the definition of a specialized + NDEF record class. + + \a className is the name of the specialized class, \a typeNameFormat is the appropriate + QNdefRecord::TypeNameFormat for the custom type and \a type is the type without the NID or NSS + prefixes. That is \i {example.com:f} not \i {urn:nfc:ext:example.com:f}. + + See the secton on \l {Creating specialized NDEF record classes} for details. + + \sa Q_DECLARE_NDEF_RECORD() +*/ + +uint qHash(const QNdefRecord &key) +{ + return qHash(key.type() + key.id() + key.payload()); +} + +/*! + Constructs a new empty NDEF record. +*/ +QNdefRecord::QNdefRecord() +{ +} + +/*! + Constructs a new NDEF record that is a copy of \a other. +*/ +QNdefRecord::QNdefRecord(const QNdefRecord &other) +{ + d = other.d; +} + +/*! + \internal + + Constructs an NDEF record that is a copy of \a other if \a other is of the expected type name + format identified by \a typeNameFormat and type as identified by \a type; otherwise an empty + NDEF record of the expected type name format and type is created. +*/ +QNdefRecord::QNdefRecord(const QNdefRecord &other, TypeNameFormat typeNameFormat, + const QByteArray &type) +{ + if (other.d->typeNameFormat == quint8(typeNameFormat) && other.d->type == type) { + d = other.d; + } else { + d = new QNdefRecordPrivate; + d->typeNameFormat = typeNameFormat; + d->type = type; + } +} + +/*! + \internal + + Constructs an NDEF record with a type name format identified by \a typeNameFormat and type as + identified by \a type. +*/ +QNdefRecord::QNdefRecord(TypeNameFormat typeNameFormat, const QByteArray &type) +: d(new QNdefRecordPrivate) +{ + d->typeNameFormat = typeNameFormat; + d->type = type; +} + +/*! + Destroys the NDEF record. +*/ +QNdefRecord::~QNdefRecord() +{ +} + +/*! + Assigns this NDEF record to \a other. +*/ +QNdefRecord &QNdefRecord::operator=(const QNdefRecord &other) +{ + if (this != &other) + d = other.d; + + return *this; +} + +/*! + Sets the type name format of the NDEF record to \a typeNameFormat. +*/ +void QNdefRecord::setTypeNameFormat(TypeNameFormat typeNameFormat) +{ + if (!d) + d = new QNdefRecordPrivate; + + d->typeNameFormat = typeNameFormat; +} + +/*! + Returns the type name format of the NDEF record. +*/ +QNdefRecord::TypeNameFormat QNdefRecord::typeNameFormat() const +{ + if (!d) + return Empty; + + if (d->typeNameFormat > 0x05) + return Unknown; + + return TypeNameFormat(d->typeNameFormat); +} + +/*! + Sets the type of the NDEF record to \a type. +*/ +void QNdefRecord::setType(const QByteArray &type) +{ + if (!d) + d = new QNdefRecordPrivate; + + d->type = type; +} + +/*! + Returns the type of the NDEF record. +*/ +QByteArray QNdefRecord::type() const +{ + if (!d) + return QByteArray(); + + return d->type; +} + +/*! + Sets the id of the NDEF record to \a id. +*/ +void QNdefRecord::setId(const QByteArray &id) +{ + if (!d) + d = new QNdefRecordPrivate; + + d->id = id; +} + +/*! + Returns the id of the NDEF record. +*/ +QByteArray QNdefRecord::id() const +{ + if (!d) + return QByteArray(); + + return d->id; +} + +/*! + Sets the payload of the NDEF record to \a payload. +*/ +void QNdefRecord::setPayload(const QByteArray &payload) +{ + if (!d) + d = new QNdefRecordPrivate; + + d->payload = payload; +} + +/*! + Returns the payload of the NDEF record. +*/ +QByteArray QNdefRecord::payload() const +{ + if (!d) + return QByteArray(); + + return d->payload; +} + +/*! + Returns true if the NDEF record contains an empty payload; otherwise return false. + + This is equivalent to calling \c {payload().isEmpty()}. +*/ +bool QNdefRecord::isEmpty() const +{ + if (!d) + return true; + + return d->payload.isEmpty(); +} + +/*! + Returns true if \a other and this NDEF record are the same. +*/ +bool QNdefRecord::operator==(const QNdefRecord &other) const +{ + if (d == other.d) + return true; + + if (!d || !other.d) + return false; + + if (d->typeNameFormat != other.d->typeNameFormat) + return false; + + if (d->type != other.d->type) + return false; + + if (d->id != other.d->id) + return false; + + if (d->payload != other.d->payload) + return false; + + return true; +} diff --git a/src/nfc/qndefrecord.h b/src/nfc/qndefrecord.h new file mode 100644 index 00000000..31d0e94c --- /dev/null +++ b/src/nfc/qndefrecord.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNDEFRECORD_H +#define QNDEFRECORD_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QSharedDataPointer> +#include <QtCore/QByteArray> + +QT_BEGIN_HEADER + +class QNdefRecordPrivate; + +class Q_CONNECTIVITY_EXPORT QNdefRecord +{ +public: + enum TypeNameFormat { + Empty = 0x00, + NfcRtd = 0x01, + Mime = 0x02, + Uri = 0x03, + ExternalRtd = 0x04, + Unknown = 0x05 + }; + + QNdefRecord(); + ~QNdefRecord(); + + QNdefRecord(const QNdefRecord &other); + QNdefRecord &operator=(const QNdefRecord &other); + + void setTypeNameFormat(TypeNameFormat typeNameFormat); + TypeNameFormat typeNameFormat() const; + + void setType(const QByteArray &type); + QByteArray type() const; + + void setId(const QByteArray &id); + QByteArray id() const; + + void setPayload(const QByteArray &payload); + QByteArray payload() const; + + bool isEmpty() const; + + template <typename T> + inline bool isRecordType() const + { + T dummy; + return (typeNameFormat() == dummy.typeNameFormat() && type() == dummy.type()); + } + + bool operator==(const QNdefRecord &other) const; + inline bool operator!=(const QNdefRecord &other) const { return !operator==(other); } + +protected: + QNdefRecord(const QNdefRecord &other, TypeNameFormat typeNameFormat, const QByteArray &type); + QNdefRecord(TypeNameFormat typeNameFormat, const QByteArray &type); + +private: + QSharedDataPointer<QNdefRecordPrivate> d; +}; + +#define Q_DECLARE_NDEF_RECORD(className, typeNameFormat, type, initialPayload) \ + className() : QNdefRecord(typeNameFormat, type) { setPayload(initialPayload); } \ + className(const QNdefRecord &other) : QNdefRecord(other, typeNameFormat, type) { } + +#define Q_DECLARE_ISRECORDTYPE_FOR_NDEF_RECORD(className, typeNameFormat_, type_) \ + template<> inline bool QNdefRecord::isRecordType<className>() const\ + { \ + return (typeNameFormat() == typeNameFormat_ && type() == type_); \ + } + +uint qHash(const QNdefRecord &key); + +QT_END_HEADER + +#endif // QNDEFRECORD_H diff --git a/src/nfc/qndefrecord_p.h b/src/nfc/qndefrecord_p.h new file mode 100644 index 00000000..ff279d68 --- /dev/null +++ b/src/nfc/qndefrecord_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QNDEFRECORD_P_H +#define QNDEFRECORD_P_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QSharedData> +#include <QtCore/QByteArray> + +class QNdefRecordPrivate : public QSharedData +{ +public: + //bool messageBegin : 1; + //bool messageEnd : 1; + unsigned int typeNameFormat : 3; + + QByteArray type; + QByteArray id; + QByteArray payload; +}; + +#endif // QNDEFRECORD_P_H diff --git a/src/nfc/qnearfieldllcpdevice_symbian.cpp b/src/nfc/qnearfieldllcpdevice_symbian.cpp new file mode 100644 index 00000000..38f9968c --- /dev/null +++ b/src/nfc/qnearfieldllcpdevice_symbian.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldllcpdevice_symbian_p.h" + +QNearFieldLlcpDeviceSymbian::QNearFieldLlcpDeviceSymbian(RNfcServer& nfcServer, QObject *parent) + : QNearFieldTarget(parent), mNfcServer(nfcServer) +{ + setAccessMethods(QNearFieldTarget::LlcpAccess); +} + +QByteArray QNearFieldLlcpDeviceSymbian::uid() const +{ + return QByteArray(); +} + +QNearFieldTarget::Type QNearFieldLlcpDeviceSymbian::type() const +{ + return QNearFieldTarget::NfcForumDevice; +} + +QNearFieldTarget::AccessMethods QNearFieldLlcpDeviceSymbian::accessMethods() const +{ + return QNearFieldTarget::LlcpAccess; +} + +void QNearFieldLlcpDeviceSymbian::setAccessMethods(const QNearFieldTarget::AccessMethods& accessMethods) +{ +} + +#include "moc_qnearfieldllcpdevice_symbian_p.cpp" diff --git a/src/nfc/qnearfieldllcpdevice_symbian_p.h b/src/nfc/qnearfieldllcpdevice_symbian_p.h new file mode 100644 index 00000000..e4ecb639 --- /dev/null +++ b/src/nfc/qnearfieldllcpdevice_symbian_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QNEARFIELDLLCPDEVICE_H +#define QNEARFIELDLLCPDEVICE_H + +#include <qnearfieldtarget.h> +#include <nfcserver.h> + +QT_BEGIN_HEADER + +class QNearFieldLlcpDeviceSymbian : public QNearFieldTarget +{ + Q_OBJECT +public: + explicit QNearFieldLlcpDeviceSymbian(RNfcServer& nfcServer, QObject *parent = 0); + QByteArray uid() const; + Type type() const; + AccessMethods accessMethods() const; + void setAccessMethods(const AccessMethods& accessMethods); + + RNfcServer& nfcServer() {return mNfcServer;} + +private: + RNfcServer& mNfcServer; +}; + +QT_END_HEADER + +#endif // QNEARFIELDLLCPDEVICE_H diff --git a/src/nfc/qnearfieldmanager.cpp b/src/nfc/qnearfieldmanager.cpp new file mode 100644 index 00000000..2d9fb60e --- /dev/null +++ b/src/nfc/qnearfieldmanager.cpp @@ -0,0 +1,554 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldmanager.h" +#include "qnearfieldmanager_p.h" + +#if defined(QT_SIMULATOR) +#include "qnearfieldmanager_simulator_p.h" +#elif defined(Q_OS_SYMBIAN) +#include "qnearfieldmanager_symbian_p.h" +#elif defined(Q_WS_MAEMO_6) || defined (Q_WS_MEEGO) +#include "qnearfieldmanager_maemo6_p.h" +#else +#include "qnearfieldmanagerimpl_p.h" +#endif + +#include <QtCore/QMetaType> +#include <QtCore/QMetaMethod> + +/*! + \class QNearFieldManager + \brief The QNearFieldManager class provides access to notifications for NFC events. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + NFC Forum devices support two modes of communications. The first mode, peer-to-peer + communications, is used to communicate between two NFC Forum devices. The second mode, + master/slave communications, is used to communicate between an NFC Forum device and an NFC + Forum Tag or Contactless Card. The targetDetected() signal is emitted when a target device + enters communications range. Communications can be initiated from the slot connected to this + signal. + + NFC Forum devices generally operate as the master in master/slave communications. Some devices + are also capable of operating as the slave, so called Card Emulation mode. In this mode the + local NFC device emulates a NFC Forum Tag or Contactless Card and can be used to perform + transactions. The transaction happens entirely within a secure element on the device and only a + notification of the transaction is provided. The transactionDetected() signal is emitted + whenever a transaction occurs. + + NFC Forum Tags can contain one or more messages in a standardized format. These messages are + encapsulated by the QNdefMessage class. Use the registerNdefMessageHandler() functions to + register message handlers with particular criteria. Handlers can be unregistered with the + unregisterNdefMessageHandler() function. + + Applications can connect to the targetDetected() and targetLost() signals to get notified when + an NFC Forum Device or NFC Forum Tag enters or leaves proximity. Before these signals are + emitted target detection must be started with the startTargetDetection() function, which takes + a parameter to limit the type of device or tags detected. Target detection can be stopped with + the stopTargetDetection() function. Before a detected target can be accessed it is necessary to + request access rights. This must be done before the target device is touched. The + setTargetAccessModes() function is used to set the types of access the application wants to + perform on the detected target. When access is no longer required the target access modes + should be set to NoTargetAccess as other applications may be blocked from accessing targets. + The current target access modes can be retried with the targetAccessModes() function. + + + \section2 Automatically launching NDEF message handlers + + It is possible to pre-register an application to receive NDEF messages matching a given + criteria. This is useful to get the system to automatically launch your application when a + matching NDEF message is received. This removes the need to have the user manually launch NDEF + handling applications, prior to touching a tag, or to have those applications always running + and using system resources. + + The process of registering the handler is different on each platform. The platform specifics + are documented in the sections below. Qt Mobility provides a tool, \c {ndefhandlergen}, to + generate the platform specific registration files. The output of \c {ndefhandlergen -help} is + reproduced here for convenience: + + \code + Generate platform specific NFC message handler registration files. + Usage: nfcxmlgen [options] + + -template TEMPLATE Template to use. + -appname APPNAME Name of the application. + -apppath APPPATH Path to installed application binary. + -datatype DATATYPE URN of the NDEF message type to match. + -match MATCHSTRING Platform specific match string. + + The -datatype and -match options are mutually exclusive. + + Available templates: maemo6, symbian + \endcode + + A typical invocation of the \c ndefhandlergen tool for Symbian^3 target: + + \code + ndefhandlergen -template symbian -appname myapplication -datatype urn:nfc:ext:com.example:f + \endcode + + and for Maemo6 target: + + \code + ndefhandlergen -template maemo6 -appname myapplication -apppath /usr/bin/myapplication -datatype urn:nfc:ext:com.example:f + \endcode + + Once the application has been registered as an NDEF message handler, the application only needs + to call the registerNdefMessageHandler() function: + + \code + QNearFieldManager *manager = new QNearFieldManager; + manager->registerNdefMessageHandler(this, + SLOT(handleNdefMessage(QNdefMessage,QNearFieldTarget))); + \endcode + + \section3 Symbian^3 + + On Symbian^3 an xml file needs to be created and installed into a particular directory on the + device. The format of the xml is given below. + + \quotefile tools/ndefhandlergen/templates/symbian/symbian.xml + + The \i {%APPNAME%} tags need to be changed to match the name of the application. The + \i description xml tags should be used to describe the application, however these values are + not used. The \i {%DATATYPE%} tag must be set with the NDEF record type to match For example + the following would be used to match NDEF messages that contain a RTD-URI record: + + \code + <customproperty key="datatype">urn:nfc:wkt:U</customproperty> + \endcode + + The following would be used to match NDEF messages that contain a custom type + urn:nfc:ext:example.com:f: + + \code + <customproperty key="datatype">urn:nfc:ext:com.example:f</customproperty> + \endcode + + The value of the \i customproperty xml tag can be set to any valid match string supported by + the Symbian^3 platform. + + It is recommended to name the xml file after the application package name. For example + myapplication.xml. To install the above xml file into the correct location the following should + be added to the application .pro file: + + \code + symbian { + ndefhandler.sources = myapplication.xml + ndefhandler.path = /private/2002AC7F/import/ + DEPLOYMENT += ndefhandler + } + \endcode + + \section3 Maemo6 + + On Maemo6 the NDEF message handler notifications are passed over D-Bus. Registration of the + NDEF message match criteria is done via a D-Bus call. The application must also ensure that it + has registered a D-Bus service name so that the application can be automatically launched when + a notification message is sent to the registered service. + + To register the D-Bus service the two files need to be created and installed into particular + directories on the device. The first file is the D-Bus bus configuration file: + + \quotefile tools/ndefhandlergen/templates/maemo6/maemo6.conf + + The \i {%APPNAME%} tag must be replaced with the name of your application binary. + + The second file is a D-Bus service file which is used by the D-Bus daemon to launch your + application. + + \quotefile tools/ndefhandlergen/templates/maemo6/maemo6.service + + The \i {%APPNAME%} tag must be replace with the name of your application binary and the + \i {%APPPATH%} tag must be replaced with the path to your installed application binary. + + It is recommended to name these files after the application package name. For example + myapplication.conf and myapplication.service. To install the above files into the correct + location the following should be added to the application .pro file: + + \code + maemo6 { + ndefhandler_conf.sources = myapplication.conf + ndefhandler_conf.path = /etc/dbus-1/system.d/ + + ndefhandler_service.sources = myapplication.service + ndefhandler_service.path = /usr/share/dbus-1/system-services/ + + DEPLOYMENT += ndefhandler_conf ndefhandler_service + } + \endcode + + The NDEF message handler is registered with the following D-Bus command. Applications should + ensure that the following command (or similar) is executed once at installation time. For + example in the packages post-installation script. + + \quotefile tools/ndefhandlergen/templates/maemo6/maemo6.postinst + + The \i {%APPNAME%} string must be replaced with the name of the application binary. The + \i {%DATATYPE%} string must be replaced with the NDEF record type to match. For example the + following would be used to match NDEF messages that contain a RTD-URI record: + + \code + string:"urn:nfc:wkt:U[1:*];" + \endcode + + The following would be used to match NDEF messages that contain a custom type + urn:nfc:ext:example.com:f: + + \code + string:"urn:nfc:ext:example.com:f[1:*];" + \endcode + + Note that \c {[1:*]} indicates one or more records of the specified type must be in the NDEF + message. The value of the datatype string argument can be set to any valid match string + supported by the Maemo6 platform. + + The NDEF message handler should be unregistered at uninstallation time. For example in the + packages pre-removal script. + + \quotefile tools/ndefhandlergen/templates/maemo6/maemo6.prerm + + The \i {%APPNAME%} string must be replace with the name of the application binary. +*/ + +/*! + \enum QNearFieldManager::TargetAccessMode + + This enum describes the different access modes an application can have. + + \value NoTargetAccess The application cannot access NFC capabilities. + \value NdefReadTargetAccess The application can read NDEF messages from targets by calling + QNearFieldTarget::readNdefMessages(). + \value NdefWriteTargetAccess The application can write NDEF messages to targets by calling + QNearFieldTarget::writeNdefMessages(). + \value TagTypeSpecificTargetAccess The application can access targets using raw commands by + calling QNearFieldTarget::sendCommand(). +*/ + +/*! + \fn void QNearFieldManager::targetDetected(QNearFieldTarget *target) + + This signal is emitted whenever a target is detected. The \a target parameter represents the + detected target. + + This signal will be emitted for all detected targets. + + QNearFieldManager maintains ownership of \a target, however, it will not be destroyed until + the QNearFieldManager destructor is called. Ownership may be transferred by calling + setParent(). + + Do not delete \a target from the slot connected to this signal, instead call deleteLater(). + + \note that if \a target is deleted before it moves out of proximity the targetLost() signal + will not be emitted. + + \sa targetLost() +*/ + +/*! + \fn void QNearFieldManager::targetLost(QNearFieldTarget *target) + + This signal is emitted whenever a target moves out of proximity. The \a target parameter + represents the lost target. + + Do not delete \a target from the slot connected to this signal, instead use deleteLater(). + + \sa QNearFieldTarget::disconnected() +*/ + +/*! + \fn void QNearFieldManager::transactionDetected(const QByteArray &applicationIdentifier) + + This signal is emitted when ever a transaction is performed with the application identified by + \a applicationIdentifier. + + The \a applicationIdentifier is a byte array of up to 16 bytes as defined by ISO 7816-4 and + uniquely identifies the application and application vendor that was involved in the + transaction. +*/ + +/*! + Constructs a new near field manager with \a parent. +*/ +QNearFieldManager::QNearFieldManager(QObject *parent) +: QObject(parent), d_ptr(new QNearFieldManagerPrivateImpl) +{ + connect(d_ptr, SIGNAL(targetDetected(QNearFieldTarget*)), + this, SIGNAL(targetDetected(QNearFieldTarget*))); + connect(d_ptr, SIGNAL(targetLost(QNearFieldTarget*)), + this, SIGNAL(targetLost(QNearFieldTarget*))); +} + +/*! + \internal + + Constructs a new near field manager with the specified \a backend and with \a parent. + + \note: This constructor is only enable for internal builds and is used for testing the + simulator backend. +*/ +QNearFieldManager::QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent) +: QObject(parent), d_ptr(backend) +{ + connect(d_ptr, SIGNAL(targetDetected(QNearFieldTarget*)), + this, SIGNAL(targetDetected(QNearFieldTarget*))); + connect(d_ptr, SIGNAL(targetLost(QNearFieldTarget*)), + this, SIGNAL(targetLost(QNearFieldTarget*))); +} + +/*! + Destroys the near field manager. +*/ +QNearFieldManager::~QNearFieldManager() +{ + delete d_ptr; +} + +/*! + Returns true if NFC functionality is available; otherwise returns false. +*/ +bool QNearFieldManager::isAvailable() const +{ + Q_D(const QNearFieldManager); + + return d->isAvailable(); +} + +/*! + Starts detecting targets of type \a targetTypes. Returns true if target detection is + successfully started; otherwise returns false. + + Causes the targetDetected() signal to be emitted when a target with a type in \a targetTypes is + within proximity. If \a targetTypes is empty targets of all types will be detected. + + \sa stopTargetDetection() +*/ +bool QNearFieldManager::startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes) +{ + Q_D(QNearFieldManager); + + if (targetTypes.isEmpty()) + return d->startTargetDetection(QList<QNearFieldTarget::Type>() << QNearFieldTarget::AnyTarget); + else + return d->startTargetDetection(targetTypes); +} + +/*! + \overload + + Starts detecting targets of type \a targetType. Returns true if target detection is + successfully started; otherwise returns false. Causes the targetDetected() signal to be emitted + when a target with the type \a targetType is within proximity. +*/ +bool QNearFieldManager::startTargetDetection(QNearFieldTarget::Type targetType) +{ + return startTargetDetection(QList<QNearFieldTarget::Type>() << targetType); +} + +/*! + Stops detecting targets. The targetDetected() signal will no longer be emitted until another + call to startTargetDetection() is made. +*/ +void QNearFieldManager::stopTargetDetection() +{ + Q_D(QNearFieldManager); + + d->stopTargetDetection(); +} + +static QMetaMethod methodForSignature(QObject *object, const char *method) +{ + QByteArray normalizedMethod = QMetaObject::normalizedSignature(method); + + if (!QMetaObject::checkConnectArgs(SIGNAL(targetDetected(QNdefMessage,QNearFieldTarget*)), + normalizedMethod)) { + qWarning("Signatures do not match: %s:%d\n", __FILE__, __LINE__); + return QMetaMethod(); + } + + quint8 memcode = (normalizedMethod.at(0) - '0') & 0x03; + normalizedMethod = normalizedMethod.mid(1); + + int index; + switch (memcode) { + case QSLOT_CODE: + index = object->metaObject()->indexOfSlot(normalizedMethod.constData()); + break; + case QSIGNAL_CODE: + index = object->metaObject()->indexOfSignal(normalizedMethod.constData()); + break; + case QMETHOD_CODE: + index = object->metaObject()->indexOfMethod(normalizedMethod.constData()); + break; + default: + index = -1; + } + + if (index == -1) + return QMetaMethod(); + + return object->metaObject()->method(index); +} + +/*! + Registers \a object to receive notifications on \a method when a tag has been detected and has + an NDEF record that matches \a typeNameFormat and \a type. The \a method on \a object should + have the prototype + 'void targetDetected(const QNdefMessage &message, QNearFieldTarget *target)'. + + Returns an identifier, which can be used to unregister the handler, on success; otherwise + returns -1. + + \note The \i target parameter of \a method may not be available on all platforms, in which case + \i target will be 0. +*/ + +int QNearFieldManager::registerNdefMessageHandler(QNdefRecord::TypeNameFormat typeNameFormat, + const QByteArray &type, + QObject *object, const char *method) +{ + QMetaMethod metaMethod = methodForSignature(object, method); + if (!metaMethod.enclosingMetaObject()) + return -1; + + QNdefFilter filter; + filter.appendRecord(typeNameFormat, type); + + Q_D(QNearFieldManager); + + return d->registerNdefMessageHandler(filter, object, metaMethod); +} + +/*! + \fn int QNearFieldManager::registerNdefMessageHandler(QObject *object, const char *method) + + Registers \a object to receive notifications on \a method when a tag has been detected and has + an NDEF message that matches a pre-registered message format. The \a method on \a object should + have the prototype + 'void targetDetected(const QNdefMessage &message, QNearFieldTarget *target)'. + + Returns an identifier, which can be used to unregister the handler, on success; otherwise + returns -1. + + This function is used to register a QNearFieldManager instance to receive notifications when a + NDEF message matching a pre-registered message format is received. See the section on + \l {Automatically launching NDEF message handlers}. + + \note The \i target parameter of \a method may not be available on all platforms, in which case + \i target will be 0. +*/ +int QNearFieldManager::registerNdefMessageHandler(QObject *object, const char *method) +{ + QMetaMethod metaMethod = methodForSignature(object, method); + if (!metaMethod.enclosingMetaObject()) + return -1; + + Q_D(QNearFieldManager); + + return d->registerNdefMessageHandler(object, metaMethod); +} + +/*! + Registers \a object to receive notifications on \a method when a tag has been detected and has + an NDEF message that matches \a filter is detected. The \a method on \a object should have the + prototype 'void targetDetected(const QNdefMessage &message, QNearFieldTarget *target)'. + + Returns an identifier, which can be used to unregister the handler, on success; otherwise + returns -1. + + \note The \i target parameter of \a method may not be available on all platforms, in which case + \i target will be 0. +*/ +int QNearFieldManager::registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, const char *method) +{ + QMetaMethod metaMethod = methodForSignature(object, method); + if (!metaMethod.enclosingMetaObject()) + return -1; + + Q_D(QNearFieldManager); + + return d->registerNdefMessageHandler(filter, object, metaMethod); +} + +/*! + Unregisters the target detect handler identified by \a handlerId. + + Returns true on success; otherwise returns false. +*/ +bool QNearFieldManager::unregisterNdefMessageHandler(int handlerId) +{ + Q_D(QNearFieldManager); + + return d->unregisterNdefMessageHandler(handlerId); +} + +/*! + Sets the requested target access modes to \a accessModes. +*/ +void QNearFieldManager::setTargetAccessModes(TargetAccessModes accessModes) +{ + Q_D(QNearFieldManager); + + TargetAccessModes removedModes = ~accessModes & d->m_requestedModes; + if (removedModes) + d->releaseAccess(removedModes); + + TargetAccessModes newModes = accessModes & ~d->m_requestedModes; + if (newModes) + d->requestAccess(newModes); +} + +/*! + Returns current requested target access modes. +*/ +QNearFieldManager::TargetAccessModes QNearFieldManager::targetAccessModes() const +{ + Q_D(const QNearFieldManager); + + return d->m_requestedModes; +} + +#include "moc_qnearfieldmanager.cpp" +#include "moc_qnearfieldmanager_p.cpp" diff --git a/src/nfc/qnearfieldmanager.h b/src/nfc/qnearfieldmanager.h new file mode 100644 index 00000000..9d3826de --- /dev/null +++ b/src/nfc/qnearfieldmanager.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGER_H +#define QNEARFIELDMANAGER_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QObject> + +#include <qnearfieldtarget.h> +#include <qndefrecord.h> +#include <qndeffilter.h> + +QT_BEGIN_HEADER + +class QNearFieldManagerPrivate; +class Q_CONNECTIVITY_EXPORT QNearFieldManager : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QNearFieldManager) + +public: + enum TargetAccessMode { + NoTargetAccess = 0x00, + NdefReadTargetAccess = 0x01, + NdefWriteTargetAccess = 0x02, + TagTypeSpecificTargetAccess = 0x04, + }; + Q_DECLARE_FLAGS(TargetAccessModes, TargetAccessMode) + + explicit QNearFieldManager(QObject *parent = 0); + explicit QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent = 0); + ~QNearFieldManager(); + + bool isAvailable() const; + + void setTargetAccessModes(TargetAccessModes accessModes); + TargetAccessModes targetAccessModes() const; + + bool startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes); + bool startTargetDetection(QNearFieldTarget::Type targetType = QNearFieldTarget::AnyTarget); + void stopTargetDetection(); + + template<typename T> + int registerNdefMessageHandler(QObject *object, const char *method); + int registerNdefMessageHandler(QObject *object, const char *method); + int registerNdefMessageHandler(QNdefRecord::TypeNameFormat typeNameFormat, + const QByteArray &type, + QObject *object, const char *method); + int registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, const char *method); + + bool unregisterNdefMessageHandler(int handlerId); + +Q_SIGNALS: + void targetDetected(QNearFieldTarget *target); + void targetLost(QNearFieldTarget *target); + void transactionDetected(const QByteArray &applicationIdentifier); + +private: + QNearFieldManagerPrivate *d_ptr; +}; + +template<typename T> +int QNearFieldManager::registerNdefMessageHandler(QObject *object, const char *method) +{ + T record; + + return registerNdefMessageHandler(record.userTypeNameFormat(), record.type(), + object, method); +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(QNearFieldManager::TargetAccessModes) + +QT_END_HEADER + +#endif // QNEARFIELDMANAGER_H diff --git a/src/nfc/qnearfieldmanager_emulator.cpp b/src/nfc/qnearfieldmanager_emulator.cpp new file mode 100644 index 00000000..0f42437c --- /dev/null +++ b/src/nfc/qnearfieldmanager_emulator.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldmanager_emulator_p.h" +#include "qnearfieldtarget_emulator_p.h" + +#include "qndefmessage.h" +#include "qtlv_p.h" + +#include <QtCore/QDebug> + +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() +{ + TagActivator *tagActivator = TagActivator::instance(); + + tagActivator->initialize(); + + connect(tagActivator, SIGNAL(tagActivated(TagBase*)), this, SLOT(tagActivated(TagBase*))); + connect(tagActivator, SIGNAL(tagDeactivated(TagBase*)), this, SLOT(tagDeactivated(TagBase*))); +} + +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ +} + +bool QNearFieldManagerPrivateImpl::isAvailable() const +{ + return true; +} + +void QNearFieldManagerPrivateImpl::reset() +{ + TagActivator::instance()->reset(); +} + +void QNearFieldManagerPrivateImpl::tagActivated(TagBase *tag) +{ + QNearFieldTarget *target = m_targets.value(tag).data(); + if (!target) { + if (dynamic_cast<NfcTagType1 *>(tag)) + target = new TagType1(tag, this); + else if (dynamic_cast<NfcTagType2 *>(tag)) + target = new TagType2(tag, this); + else + qFatal("Unknown emulator tag type"); + + m_targets.insert(tag, target); + } + + targetActivated(target); +} + +void QNearFieldManagerPrivateImpl::tagDeactivated(TagBase *tag) +{ + QNearFieldTarget *target = m_targets.value(tag).data(); + if (!target) { + m_targets.remove(tag); + return; + } + + targetDeactivated(target); +} + + diff --git a/src/nfc/qnearfieldmanager_emulator_p.h b/src/nfc/qnearfieldmanager_emulator_p.h new file mode 100644 index 00000000..4d303991 --- /dev/null +++ b/src/nfc/qnearfieldmanager_emulator_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGER_EMULATOR_H +#define QNEARFIELDMANAGER_EMULATOR_H + +#include "qnearfieldmanagervirtualbase_p.h" +#include "qnearfieldtarget.h" +#include "qndeffilter.h" + +#include <QtCore/QObject> +#include <QtCore/QWeakPointer> + +class TagBase; +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivateVirtualBase +{ + Q_OBJECT + +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl(); + + bool isAvailable() const; + + void reset(); + +private slots: + void tagActivated(TagBase *tag); + void tagDeactivated(TagBase *tag); + +private: + void ndefReceived(const QNdefMessage &message, QNearFieldTarget *target); + + QMap<TagBase *, QWeakPointer<QNearFieldTarget> > m_targets; + +}; + +#endif // QNEARFIELDMANAGER_EMULATOR_H diff --git a/src/nfc/qnearfieldmanager_maemo6.cpp b/src/nfc/qnearfieldmanager_maemo6.cpp new file mode 100644 index 00000000..a8c21bac --- /dev/null +++ b/src/nfc/qnearfieldmanager_maemo6.cpp @@ -0,0 +1,449 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldmanager_maemo6_p.h" +#include "qnearfieldtarget_maemo6_p.h" +#include "manager_interface.h" +#include "maemo6/adapter_interface_p.h" +#include "maemo6/target_interface_p.h" +#include "maemo6/tag_interface_p.h" +#include "ndefhandler_adaptor.h" +#include "accessrequestor_adaptor.h" + +#include <qnearfieldtagtype1.h> + +#include <QtDBus/QDBusConnection> + +using namespace com::nokia::nfc; + +static QAtomicInt handlerId = 0; +static const char * const registeredHandlerPath = "/com/nokia/nfc/ndefhandler"; +static const char * const accessRequesterPath = "/com/nokia/nfc/accessRequester/"; +static const char * const connectionUuid = "46a15ee4-b5ce-4395-9d76-c440cc3838c6"; + +static inline bool matchesTarget(QNearFieldTarget::Type type, + const QList<QNearFieldTarget::Type> &types) +{ + return types.contains(type) || types.contains(QNearFieldTarget::AnyTarget); +} + +NdefHandler::NdefHandler(QNearFieldManagerPrivateImpl *manager, const QString &serviceName, + const QString &path, QObject *object, const QMetaMethod &method) +: m_manager(manager), m_adaptor(0), m_object(object), m_method(method), + m_serviceName(serviceName), m_path(path) +{ + QDBusConnection handlerConnection = + QDBusConnection::connectToBus(QDBusConnection::SystemBus, connectionUuid); + if (serviceName != handlerConnection.baseService()) { + handlerConnection = QDBusConnection::connectToBus(QDBusConnection::SystemBus, serviceName); + + if (!handlerConnection.registerService(serviceName)) + return; + } + + m_adaptor = new NDEFHandlerAdaptor(this); + + if (!handlerConnection.registerObject(path, this)) { + delete m_adaptor; + m_adaptor = 0; + } +} + +NdefHandler::~NdefHandler() +{ + delete m_adaptor; +} + +bool NdefHandler::isValid() const +{ + return m_adaptor; +} + +QString NdefHandler::serviceName() const +{ + return m_serviceName; +} + +QString NdefHandler::path() const +{ + return m_path; +} + +void NdefHandler::NDEFData(const QDBusObjectPath &target, const QByteArray &message) +{ + m_method.invoke(m_object, Q_ARG(QNdefMessage, QNdefMessage::fromByteArray(message)), + Q_ARG(QNearFieldTarget *, m_manager->targetForPath(target.path()))); +} + +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() +: m_connection(QDBusConnection::connectToBus(QDBusConnection::SystemBus, + QLatin1String(connectionUuid))), + m_accessAgent(0) +{ + qDBusRegisterMetaType<QList<QByteArray> >(); + + m_manager = new Manager(QLatin1String("com.nokia.nfc"), QLatin1String("/"), m_connection); + + QDBusObjectPath defaultAdapterPath = m_manager->DefaultAdapter(); + + m_adapter = new Adapter(QLatin1String("com.nokia.nfc"), defaultAdapterPath.path(), + m_connection); + + if (!m_adapter->isValid()) + return; +} + +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ + foreach (int id, m_registeredHandlers.keys()) + unregisterNdefMessageHandler(id); + + delete m_manager; + delete m_adapter; +} + +bool QNearFieldManagerPrivateImpl::isAvailable() const +{ + return m_manager->isValid(); +} + +bool QNearFieldManagerPrivateImpl::startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes) +{ + m_detectTargetTypes = targetTypes; + + connect(m_adapter, SIGNAL(TargetDetected(QDBusObjectPath)), + this, SLOT(_q_targetDetected(QDBusObjectPath))); + connect(m_adapter, SIGNAL(TargetLost(QDBusObjectPath)), + this, SLOT(_q_targetLost(QDBusObjectPath))); + + return true; +} + +void QNearFieldManagerPrivateImpl::stopTargetDetection() +{ + m_detectTargetTypes.clear(); + + disconnect(m_adapter, SIGNAL(TargetDetected(QDBusObjectPath)), + this, SLOT(_q_targetDetected(QDBusObjectPath))); + disconnect(m_adapter, SIGNAL(TargetLost(QDBusObjectPath)), + this, SLOT(_q_targetLost(QDBusObjectPath))); +} + +QNearFieldTarget *QNearFieldManagerPrivateImpl::targetForPath(const QString &path) +{ + QNearFieldTarget *nearFieldTarget = m_targets.value(path).data(); + + if (!nearFieldTarget) { + Target *target = new Target(QLatin1String("com.nokia.nfc"), path, m_connection); + + const QString type = target->type(); + + if (type == QLatin1String("tag")) { + Tag *tag = new Tag(QLatin1String("com.nokia.nfc"), path, m_connection); + + const QString tagTechnology = tag->technology(); + if (tagTechnology == QLatin1String("jewel")) + nearFieldTarget = new TagType1(this, target, tag); + else if (tagTechnology == QLatin1String("mifare-ul")) + nearFieldTarget = new TagType2(this, target, tag); + else if (tagTechnology == QLatin1String("felica")) + nearFieldTarget = new TagType3(this, target, tag); + else if (tagTechnology == QLatin1String("iso-4a")) + nearFieldTarget = new TagType4(this, target, tag); + else + nearFieldTarget = new NearFieldTarget<QNearFieldTarget>(this, target, tag); + } else if (type == QLatin1String("device")) { + Device *device = new Device(QLatin1String("com.nokia.nfc"), path, m_connection); + nearFieldTarget = new NearFieldTarget<QNearFieldTarget>(this, target, device); + } + + if (nearFieldTarget) + m_targets.insert(path, nearFieldTarget); + } + + return nearFieldTarget; +} + +int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(const QString &filter, + QObject *object, + const QMetaMethod &method) +{ + int id = handlerId.fetchAndAddOrdered(1); + const QString handlerPath = + QLatin1String(registeredHandlerPath) + QLatin1Char('/') + QString::number(id); + + NdefHandler *handler = new NdefHandler(this, m_connection.baseService(), + handlerPath, object, method); + if (!handler->isValid()) { + delete handler; + return -1; + } + + QDBusPendingReply<> reply = + m_manager->RegisterNDEFHandler(QLatin1String("system"), + m_connection.baseService(), + QDBusObjectPath(handlerPath), + QLatin1String("any"), + filter, + QCoreApplication::applicationName()); + + if (reply.isError()) { + delete handler; + return -1; + } + + m_registeredHandlers[id] = handler; + + return id; +} + +int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(QObject *object, + const QMetaMethod &method) +{ + QFileInfo fi(qApp->applicationFilePath()); + const QString serviceName = QLatin1String("com.nokia.qt.nfc.") + fi.baseName(); + + int id = handlerId.fetchAndAddOrdered(1); + + const QString handlerPath = QLatin1String(registeredHandlerPath); + + NdefHandler *handler = new NdefHandler(this, serviceName, handlerPath, object, method); + if (!handler->isValid()) { + delete handler; + return -1; + } + + m_registeredHandlers[id] = handler; + + return id; +} + +int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, + const QMetaMethod &method) +{ + QString matchString; + + if (filter.orderMatch()) + matchString += QLatin1String("sequence:"); + else + matchString += QLatin1String("unordered:"); + + for (int i = 0; i < filter.recordCount(); ++i) { + QNdefFilter::Record record = filter.recordAt(i); + + QString type; + + switch (record.typeNameFormat) { + case QNdefRecord::NfcRtd: + type = QLatin1String("urn:nfc:wkt:") + record.type; + break; + case QNdefRecord::ExternalRtd: + type = QLatin1String("urn:nfc:ext:") + record.type; + break; + case QNdefRecord::Mime: + type = record.type; + break; + default: + qWarning("Unsupported filter type"); + return -1; + } + + matchString += QLatin1Char('\'') + type + QLatin1Char('\''); + matchString += QLatin1Char('['); + + if (record.minimum == UINT_MAX) + matchString += QLatin1Char('*'); + else + matchString += QString::number(record.minimum); + + matchString += QLatin1Char(':'); + + if (record.maximum == UINT_MAX) + matchString += QLatin1Char('*'); + else + matchString += QString::number(record.maximum); + + matchString += QLatin1Char(']'); + + if (i == filter.recordCount() - 1) + matchString += QLatin1Char(';'); + else + matchString += QLatin1Char(','); + } + + return registerNdefMessageHandler(matchString, object, method); +} + +bool QNearFieldManagerPrivateImpl::unregisterNdefMessageHandler(int id) +{ + if (id < 0) + return false; + + NdefHandler *handler = m_registeredHandlers.take(id); + + QDBusPendingReply<> reply = m_manager->UnregisterNDEFHandler(QLatin1String("system"), + handler->serviceName(), + QDBusObjectPath(handler->path())); + + delete handler; + + return true; +} + +static QStringList accessModesToKind(QNearFieldManager::TargetAccessModes accessModes) +{ + QStringList kind; + + if (accessModes & QNearFieldManager::NdefReadTargetAccess) + kind.append(QLatin1String("tag.ndef.read")); + + if (accessModes & QNearFieldManager::NdefWriteTargetAccess) + kind.append(QLatin1String("tag.ndef.write")); + + if (accessModes & QNearFieldManager::TagTypeSpecificTargetAccess) + kind.append(QLatin1String("tag.raw")); + + return kind; +} + +void QNearFieldManagerPrivateImpl::requestAccess(QNearFieldManager::TargetAccessModes accessModes) +{ + const QString requesterPath = + QLatin1String(accessRequesterPath) + QString::number(quintptr(this)); + + if (!m_accessAgent) { + m_accessAgent = new AccessRequestorAdaptor(this); + if (!m_connection.registerObject(requesterPath, this)) { + delete m_accessAgent; + m_accessAgent = 0; + return; + } + } + + foreach (const QString &kind, accessModesToKind(accessModes)) + m_adapter->RequestAccess(QDBusObjectPath(requesterPath), kind); + + QNearFieldManagerPrivate::requestAccess(accessModes); +} + +void QNearFieldManagerPrivateImpl::releaseAccess(QNearFieldManager::TargetAccessModes accessModes) +{ + const QString requesterPath = + QLatin1String(accessRequesterPath) + QString::number(quintptr(this)); + + foreach (const QString &kind, accessModesToKind(accessModes)) + m_adapter->CancelAccessRequest(QDBusObjectPath(requesterPath), kind); + + QNearFieldManagerPrivate::releaseAccess(accessModes); +} + +void QNearFieldManagerPrivateImpl::AccessFailed(const QDBusObjectPath &target, const QString &kind, + const QString &error) +{ + qDebug() << "Access for" << target.path() << kind << "failed with error:" << error; +} + +void QNearFieldManagerPrivateImpl::AccessGranted(const QDBusObjectPath &target, + const QString &kind) +{ + Q_UNUSED(kind); + + if (m_pendingDetectedTargets.contains(target.path())) { + m_pendingDetectedTargets[target.path()].stop(); + m_pendingDetectedTargets.remove(target.path()); + } + + emitTargetDetected(target.path()); +} + +void QNearFieldManagerPrivateImpl::timerEvent(QTimerEvent *event) +{ + QMutableMapIterator<QString, QBasicTimer> i(m_pendingDetectedTargets); + while (i.hasNext()) { + i.next(); + + if (i.value().timerId() == event->timerId()) { + i.value().stop(); + + const QString target = i.key(); + + i.remove(); + + emitTargetDetected(target); + + break; + } + } +} + +void QNearFieldManagerPrivateImpl::emitTargetDetected(const QString &targetPath) +{ + QNearFieldTarget *target = targetForPath(targetPath); + if (target && matchesTarget(target->type(), m_detectTargetTypes)) + emit targetDetected(target); +} + +void QNearFieldManagerPrivateImpl::_q_targetDetected(const QDBusObjectPath &targetPath) +{ + if (!m_requestedModes) + emitTargetDetected(targetPath.path()); + else + m_pendingDetectedTargets[targetPath.path()].start(500, this); +} + +void QNearFieldManagerPrivateImpl::_q_targetLost(const QDBusObjectPath &targetPath) +{ + QNearFieldTarget *nearFieldTarget = m_targets.value(targetPath.path()).data(); + + // haven't seen target so just drop this event + if (!nearFieldTarget) { + // We either haven't seen target (started after target was detected by system) or the + // application deleted the target. Remove from map and don't emit anything. + m_targets.remove(targetPath.path()); + return; + } + + if (matchesTarget(nearFieldTarget->type(), m_detectTargetTypes)) + emit targetLost(nearFieldTarget); +} + +#include "moc_qnearfieldmanager_maemo6_p.cpp" diff --git a/src/nfc/qnearfieldmanager_maemo6_p.h b/src/nfc/qnearfieldmanager_maemo6_p.h new file mode 100644 index 00000000..f342398a --- /dev/null +++ b/src/nfc/qnearfieldmanager_maemo6_p.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGER_MAEMO6_P_H +#define QNEARFIELDMANAGER_MAEMO6_P_H + +#include "qnearfieldmanager_p.h" +#include "qnearfieldmanager.h" +#include "qnearfieldtarget.h" + +#include <QtCore/QWeakPointer> +#include <QtCore/QMap> +#include <QtCore/QPair> +#include <QtCore/QMetaMethod> +#include <QtCore/QBasicTimer> + +#include <QtDBus/QDBusConnection> + +QT_FORWARD_DECLARE_CLASS(QDBusObjectPath) + +class ComNokiaNfcManagerInterface; +class ComNokiaNfcAdapterInterface; +class NDEFHandlerAdaptor; +class AccessRequestorAdaptor; + +class QNearFieldManagerPrivateImpl; + +class NdefHandler : public QObject +{ + Q_OBJECT + +public: + NdefHandler(QNearFieldManagerPrivateImpl *manager, const QString &serviceName, + const QString &path, QObject *object, const QMetaMethod &method); + ~NdefHandler(); + + bool isValid() const; + + QString serviceName() const; + QString path() const; + +private: + Q_INVOKABLE void NDEFData(const QDBusObjectPath &target, const QByteArray &message); + + QNearFieldManagerPrivateImpl *m_manager; + NDEFHandlerAdaptor *m_adaptor; + QObject *m_object; + QMetaMethod m_method; + QString m_serviceName; + QString m_path; +}; + +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate +{ + Q_OBJECT + +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl(); + + bool isAvailable() const; + + bool startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes); + void stopTargetDetection(); + + QNearFieldTarget *targetForPath(const QString &path); + + int registerNdefMessageHandler(const QString &filter, + QObject *object, const QMetaMethod &method); + int registerNdefMessageHandler(QObject *object, const QMetaMethod &method); + int registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, const QMetaMethod &method); + bool unregisterNdefMessageHandler(int handlerId); + + void requestAccess(QNearFieldManager::TargetAccessModes accessModes); + void releaseAccess(QNearFieldManager::TargetAccessModes accessModes); + + // Access Agent Adaptor + Q_INVOKABLE void AccessFailed(const QDBusObjectPath &target, const QString &kind, + const QString &error); + Q_INVOKABLE void AccessGranted(const QDBusObjectPath &target, const QString &kind); + +protected: + void timerEvent(QTimerEvent *event); + +private slots: + void emitTargetDetected(const QString &targetPath); + void _q_targetDetected(const QDBusObjectPath &targetPath); + void _q_targetLost(const QDBusObjectPath &targetPath); + +private: + QDBusConnection m_connection; + ComNokiaNfcManagerInterface *m_manager; + ComNokiaNfcAdapterInterface *m_adapter; + + QList<QNearFieldTarget::Type> m_detectTargetTypes; + QMap<QString, QWeakPointer<QNearFieldTarget> > m_targets; + + AccessRequestorAdaptor *m_accessAgent; + + QMap<int, NdefHandler *> m_registeredHandlers; + + QMap<QString, QBasicTimer> m_pendingDetectedTargets; +}; + +#endif // QNEARFIELDMANAGER_MAEMO6_P_H diff --git a/src/nfc/qnearfieldmanager_p.h b/src/nfc/qnearfieldmanager_p.h new file mode 100644 index 00000000..648a1978 --- /dev/null +++ b/src/nfc/qnearfieldmanager_p.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGER_P_H +#define QNEARFIELDMANAGER_P_H + +#include "qnearfieldmanager.h" +#include "qnearfieldtarget.h" +#include "qndefrecord.h" + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QObject> + +QT_BEGIN_HEADER + +class QNdefFilter; + +class QM_AUTOTEST_EXPORT QNearFieldManagerPrivate : public QObject +{ + Q_OBJECT + +public: + explicit QNearFieldManagerPrivate(QObject *parent = 0) + : QObject(parent) + { + } + + ~QNearFieldManagerPrivate() + { + } + + virtual bool isAvailable() const + { + return false; + } + + virtual bool startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes) + { + Q_UNUSED(targetTypes); + + return false; + } + + virtual void stopTargetDetection() + { + } + + virtual int registerNdefMessageHandler(QObject *object, const QMetaMethod &/*method*/) + { + Q_UNUSED(object); + + return -1; + } + + virtual int registerNdefMessageHandler(const QNdefFilter &/*filter*/, + QObject *object, const QMetaMethod &/*method*/) + { + Q_UNUSED(object); + + return -1; + } + + virtual bool unregisterNdefMessageHandler(int handlerId) + { + Q_UNUSED(handlerId); + + return false; + } + + virtual void requestAccess(QNearFieldManager::TargetAccessModes accessModes) + { + m_requestedModes |= accessModes; + } + + virtual void releaseAccess(QNearFieldManager::TargetAccessModes accessModes) + { + m_requestedModes &= ~accessModes; + } + +signals: + void targetDetected(QNearFieldTarget *target); + void targetLost(QNearFieldTarget *target); + +public: + QNearFieldManager::TargetAccessModes m_requestedModes; +}; + +QT_END_HEADER + +#endif // QNEARFIELDMANAGER_P_H diff --git a/src/nfc/qnearfieldmanager_simulator.cpp b/src/nfc/qnearfieldmanager_simulator.cpp new file mode 100644 index 00000000..1d7f5318 --- /dev/null +++ b/src/nfc/qnearfieldmanager_simulator.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldmanager_simulator_p.h" +#include "qnearfieldmanager.h" +#include "qnearfieldtarget_p.h" +#include "qnearfieldtagtype1.h" +#include "qndefmessage.h" + +#include <mobilityconnection_p.h> +#include <QtGui/private/qsimulatordata_p.h> + +#include <QtCore/QCoreApplication> + +using namespace QtSimulatorPrivate; + +namespace Simulator { + +class TagType1 : public QNearFieldTagType1 +{ +public: + TagType1(const QByteArray &uid, QObject *parent); + ~TagType1(); + + QByteArray uid() const; + + AccessMethods accessMethods() const; + + RequestId sendCommand(const QByteArray &command); + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + +private: + QByteArray m_uid; +}; + +TagType1::TagType1(const QByteArray &uid, QObject *parent) +: QNearFieldTagType1(parent), m_uid(uid) +{ +} + +TagType1::~TagType1() +{ +} + +QByteArray TagType1::uid() const +{ + return m_uid; +} + +QNearFieldTarget::AccessMethods TagType1::accessMethods() const +{ + return NdefAccess | TagTypeSpecificAccess; +} + +QNearFieldTarget::RequestId TagType1::sendCommand(const QByteArray &command) +{ + quint16 crc = qNfcChecksum(command.constData(), command.length()); + + RequestId id(new RequestIdPrivate); + + MobilityConnection *connection = MobilityConnection::instance(); + QByteArray response = + RemoteMetacall<QByteArray>::call(connection->sendSocket(), WaitSync, "nfcSendCommand", + command + char(crc & 0xff) + char(crc >> 8)); + + if (response.isEmpty()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, NoResponseError), + Q_ARG(QNearFieldTarget::RequestId, id)); + return id; + } + + // check crc + if (qNfcChecksum(response.constData(), response.length()) != 0) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, ChecksumMismatchError), + Q_ARG(QNearFieldTarget::RequestId, id)); + return id; + } + + response.chop(2); + + QMetaObject::invokeMethod(this, "handleResponse", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::RequestId, id), Q_ARG(QByteArray, response)); + + return id; +} + +bool TagType1::waitForRequestCompleted(const RequestId &id, int msecs) +{ + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); + + return QNearFieldTagType1::waitForRequestCompleted(id, msecs); +} + +class NfcConnection : public QObject +{ + Q_OBJECT + +public: + NfcConnection(); + virtual ~NfcConnection(); + +signals: + void targetEnteringProximity(const QByteArray &uid); + void targetLeavingProximity(const QByteArray &uid); +}; + +NfcConnection::NfcConnection() +: QObject(MobilityConnection::instance()) +{ + MobilityConnection *connection = MobilityConnection::instance(); + connection->addMessageHandler(this); + + RemoteMetacall<void>::call(connection->sendSocket(), NoSync, "setRequestsNfc"); +} + +NfcConnection::~NfcConnection() +{ +} + +} + +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() +: nfcConnection(new Simulator::NfcConnection) +{ + connect(nfcConnection, SIGNAL(targetEnteringProximity(QByteArray)), + this, SLOT(targetEnteringProximity(QByteArray))); + connect(nfcConnection, SIGNAL(targetLeavingProximity(QByteArray)), + this, SLOT(targetLeavingProximity(QByteArray))); +} + +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ + delete nfcConnection; +} + +bool QNearFieldManagerPrivateImpl::isAvailable() const +{ + return true; +} + +void QNearFieldManagerPrivateImpl::targetEnteringProximity(const QByteArray &uid) +{ + QNearFieldTarget *target = m_targets.value(uid).data(); + if (!target) { + target = new Simulator::TagType1(uid, this); + m_targets.insert(uid, target); + } + + targetActivated(target); +} + +void QNearFieldManagerPrivateImpl::targetLeavingProximity(const QByteArray &uid) +{ + QNearFieldTarget *target = m_targets.value(uid).data(); + if (!target) { + m_targets.remove(uid); + return; + } + + targetDeactivated(target); +} + +#include "qnearfieldmanager_simulator.moc" +#include "moc_qnearfieldmanager_simulator_p.cpp" diff --git a/src/nfc/qnearfieldmanager_simulator_p.h b/src/nfc/qnearfieldmanager_simulator_p.h new file mode 100644 index 00000000..a55f3e94 --- /dev/null +++ b/src/nfc/qnearfieldmanager_simulator_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGER_SIMULATOR_P_H +#define QNEARFIELDMANAGER_SIMULATOR_P_H + +#include "qnearfieldmanagervirtualbase_p.h" + +#include <QtCore/QWeakPointer> + +QT_BEGIN_HEADER + +namespace Simulator { +class NfcConnection; +} + +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivateVirtualBase +{ + Q_OBJECT + +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl(); + + bool isAvailable() const; + +private slots: + void targetEnteringProximity(const QByteArray &uid); + void targetLeavingProximity(const QByteArray &uid); + +private: + Simulator::NfcConnection *nfcConnection; + QMap<QByteArray, QWeakPointer<QNearFieldTarget> > m_targets; +}; + +QT_END_HEADER + +#endif // QNEARFIELDMANAGER_SIMULATOR_P_H diff --git a/src/nfc/qnearfieldmanager_symbian.cpp b/src/nfc/qnearfieldmanager_symbian.cpp new file mode 100644 index 00000000..8492d526 --- /dev/null +++ b/src/nfc/qnearfieldmanager_symbian.cpp @@ -0,0 +1,385 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qservicefilter.h> +#include <qservicemanager.h> +#include <QCoreApplication> +#include <ndefmessage.h> + +#include "qnearfieldmanager_symbian_p.h" +#include "qndefmessage.h" +#include "symbian/nearfieldmanager_symbian.h" +#include "symbian/debug.h" +#include "symbian/nearfieldutility_symbian.h" + +Proxy contentHandlerProxy; + +Proxy::Proxy(QObject* parent) : QObject (parent) +{ +} + +ContentHandlerInterface::ContentHandlerInterface(QObject* parent) + : QObject(parent) +{ +} +void ContentHandlerInterface::handleMessage(const QByteArray& btArray) +{ + // incoming message from ECOM content handler loader eventually cause object & method registered via below + // registerNdefMessageHandler to be invoked with message as parameter. i.e. MyContentHandler::handleMessage(message) + // from above. + + + QNdefMessage msg = QNdefMessage::fromByteArray(btArray); + QMetaObject::invokeMethod(&contentHandlerProxy, "handleMessage", Q_ARG(QNdefMessage, msg)); + + +} +/* + \class QNearFieldManagerPrivateImpl + \brief The QNearFieldManagerPrivateImpl class provides symbian backend access to NFC service. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + + A Qt-Symbian wrapper implementation class to support symbian NFC backend. +*/ + +/* + Constructs a new near field manager private implementation. +*/ +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl(): m_symbianbackend(NULL),m_target(NULL),m_serviceRegister(NULL) +{ + BEGIN + TRAPD(err, m_symbianbackend = CNearFieldManager::NewL(*this)); + END +} + +/* + Destroys the near field manager private implementation. +*/ +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ + BEGIN + delete m_target; + qDeleteAll(m_targetList); + delete m_serviceRegister; + delete m_symbianbackend; + END +} + +bool QNearFieldManagerPrivateImpl::isAvailable() const +{ + return m_symbianbackend; +} + +/* + Helper function to get the free handler id. +*/ +int QNearFieldManagerPrivateImpl::getFreeId() +{ + BEGIN + if (!m_freeIds.isEmpty()) + return m_freeIds.takeFirst(); + + m_registeredHandlers.append(Callback()); + END + return m_registeredHandlers.count() - 1; +} + +/* + Registers \a object to receive notifications on \a method when a tag with a tag type of + \a targetType has been detected and has an NDEF message is detected. The + \a method on \a object should have the prototype + 'void targetDetected(const QNdefMessage &message, QNearFieldTarget *target)'. + + Returns an identifier, which can be used to unregister the handler, on success; otherwise + returns -1. +*/ +int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(QObject *object, + const QMetaMethod &method) +{ + QServiceFilter filter("com.nokia.qt.nfc.NdefMessageHandler"); + QCoreApplication* app = QCoreApplication::instance(); + //The appfile path will return something like \sys\bin\nfcspserviceprovider.exe + //but we only need nfcspserviceprovider as service name + QString appfilepath = app->applicationFilePath(); + TInt lastseprator = appfilepath.lastIndexOf("\\"); + TInt lastdot = appfilepath.lastIndexOf("."); + QString servicename = appfilepath.mid(lastseprator+1, lastdot-lastseprator-1); + qDebug() << "application name: " << servicename << endl; + + filter.setServiceName(servicename); + QServiceManager sfManager; + + if (!sfManager.findInterfaces(filter).isEmpty()) + { + // This application has been registered as a content handler (via the xml at install time), start the service + m_chobject = object; + m_chmethod = method; + + connect(&contentHandlerProxy, SIGNAL(handleMessage(QNdefMessage)), + this, SLOT(_q_privateHandleMessageSlot(QNdefMessage))); + if ( !m_serviceRegister ) + { + m_serviceRegister = new QRemoteServiceRegister(); + QRemoteServiceRegister::Entry entry = + m_serviceRegister->createEntry<ContentHandlerInterface>(servicename, + "com.nokia.qt.nfc.NdefMessageHandler", + "1.0"); + entry.setInstantiationType(QRemoteServiceRegister::PrivateInstance); + m_serviceRegister->publishEntries(servicename); + } + return 0xffff; + + } else { + // not supported if not registered as a content handler using this API + return -1; + } +} + +/* + Registers \a object to receive notifications on \a method when a tag with a tag type of + \a targetType has been detected and has an NDEF message that matches \a filter is detected. The + \a method on \a object should have the prototype + 'void targetDetected(const QNdefMessage &message, QNearFieldTarget *target)'. + + Returns an identifier, which can be used to unregister the handler, on success; otherwise + returns -1. +*/ +int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, + const QMetaMethod &method) +{ + if (!m_symbianbackend) + return -1; + + BEGIN + int id = getFreeId(); + + Callback &callback = m_registeredHandlers[id]; + + callback.filter = filter; + callback.object = object; + callback.method = method; + + for( int i = 0; i < filter.recordCount(); ++i) + { + QNdefRecord::TypeNameFormat tnf = filter.recordAt(i).typeNameFormat; + QByteArray type = filter.recordAt(i).type; + if (m_symbianbackend->AddNdefSubscription( tnf, type ) < 0) + { + for (int j = 0; j < i; ++j)//rollback the previous subscriptions + { + QNdefRecord::TypeNameFormat n = filter.recordAt(j).typeNameFormat; + QByteArray t = filter.recordAt(j).type; + m_symbianbackend->RemoveNdefSubscription( n, t ); + } + m_freeIds.append(id);//push back the id to freeid list + END + return -1; + } + } + END + return id; +} + +/* + Unregisters the target detect handler identified by \a id. + + Returns true on success; otherwise returns false. +*/ +bool QNearFieldManagerPrivateImpl::unregisterNdefMessageHandler(int id) +{ + if (!m_symbianbackend) + return false; + + BEGIN + if ( 0xffff == id ) + { + disconnect(&contentHandlerProxy, SIGNAL(handleMessage(QNdefMessage)), + this, SLOT(_q_privateHandleMessageSlot(QNdefMessage))); + return true; + } + if (id < 0 || id >= m_registeredHandlers.count() || m_freeIds.contains(id)) + return false; + + m_freeIds.append(id); + + for ( int i = 0; i < m_registeredHandlers[id].filter.recordCount(); ++i) + { + QNdefRecord::TypeNameFormat tnf = m_registeredHandlers[id].filter.recordAt(i).typeNameFormat; + QByteArray type = m_registeredHandlers[id].filter.recordAt(i).type; + m_symbianbackend->RemoveNdefSubscription( tnf, type ); + } + + while (m_freeIds.contains(m_registeredHandlers.count() - 1)) { + m_freeIds.removeAll(m_registeredHandlers.count() - 1); + m_registeredHandlers.removeLast(); + } + END + return true; +} + +bool QNearFieldManagerPrivateImpl::startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes) +{ + if (!m_symbianbackend) + return false; + + BEGIN + TRAPD(err, m_symbianbackend->StartTargetDetectionL(targetTypes)); + END + return err == KErrNone; +} + +void QNearFieldManagerPrivateImpl::stopTargetDetection() +{ + BEGIN + if (m_symbianbackend) + m_symbianbackend->stopTargetDetection(); + END +} + +struct VerifyRecord +{ + QNdefFilter::Record filterRecord; + unsigned int count; +}; + +/* + Callback function when symbian NFC backend found the NFC \a target. +*/ +void QNearFieldManagerPrivateImpl::targetFound(QNearFieldTarget *target) +{ + BEGIN + if (!target){ + return; + } + if (m_target){ + m_targetList.append(m_target); + } + m_target = target; + emit targetDetected(target); + END +} + +/* + * Private slot to be invoked by QT content handler loader + */ +void QNearFieldManagerPrivateImpl::_q_privateHandleMessageSlot(QNdefMessage aMsg) + { + + m_chmethod.invoke(m_chobject, Q_ARG(QNdefMessage, aMsg), Q_ARG(QNearFieldTarget* , NULL)); + } + +/* + Helper function to invoke the filtered TargetDetectedHandler for a found \a target. +*/ + +void QNearFieldManagerPrivateImpl::invokeNdefMessageHandler(const QNdefMessage msg) +{ + BEGIN + for (int i = 0; i < m_registeredHandlers.count(); ++i) { + if (m_freeIds.contains(i)) + continue; + Callback &callback = m_registeredHandlers[i]; + bool matched = true; + QList<VerifyRecord> filterRecords; + for (int j = 0; j < callback.filter.recordCount(); ++j) { + VerifyRecord vr; + vr.count = 0; + vr.filterRecord = callback.filter.recordAt(j); + filterRecords.append(vr); + } + + foreach (const QNdefRecord &record, msg) { + for (int j = 0; matched && (j < filterRecords.count()); ++j) { + VerifyRecord &vr = filterRecords[j]; + + if (vr.filterRecord.typeNameFormat == record.typeNameFormat() && + vr.filterRecord.type == record.type()) { + ++vr.count; + break; + } else { + if (callback.filter.orderMatch()) { + if (vr.filterRecord.minimum <= vr.count && + vr.count <= vr.filterRecord.maximum) { + continue; + } else { + matched = false; + } + } + } + } + }//end of foreach (const QNdefRecord &record, msg) { + + for (int j = 0; matched && (j < filterRecords.count()); ++j) { + const VerifyRecord &vr = filterRecords.at(j); + + if (vr.filterRecord.minimum <= vr.count && vr.count <= vr.filterRecord.maximum) + continue; + else + matched = false; + } + + if (matched) { + callback.method.invoke(callback.object, Q_ARG(QNdefMessage, msg), + Q_ARG(QNearFieldTarget *, NULL)); + } + + } + END +} + +/* + Callback function when symbian NFC backend lost the NFC \a target. +*/ +void QNearFieldManagerPrivateImpl::targetDisconnected() +{ + BEGIN + if (m_target) + { + QMetaObject::invokeMethod(m_target, "disconnected"); + emit targetLost(m_target); + } + END +} + +#include "moc_qnearfieldmanager_symbian_p.cpp" diff --git a/src/nfc/qnearfieldmanager_symbian_p.h b/src/nfc/qnearfieldmanager_symbian_p.h new file mode 100644 index 00000000..d1df3397 --- /dev/null +++ b/src/nfc/qnearfieldmanager_symbian_p.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGER_SYMBIAN_P_H_ +#define QNEARFIELDMANAGER_SYMBIAN_P_H_ + + +#include "qnearfieldmanager_p.h" +#include "qnearfieldtarget.h" +#include "qndeffilter.h" + +#include <QtCore/QObject> +#include <QtCore/QMetaMethod> +#include <QPointer> +#include <QList> +#include <qremoteserviceregister.h> + +class CNearFieldManager; +class CNdefMessage; + +QT_BEGIN_HEADER + +class Proxy : public QObject +{ + Q_OBJECT +public: + Proxy(QObject* parent = 0); + +Q_SIGNALS: + void handleMessage(const QNdefMessage& message); +}; + +class ContentHandlerInterface : public QObject +{ + Q_OBJECT +public: + ContentHandlerInterface(QObject* parent = 0); + +public slots: + void handleMessage(const QByteArray& message); +}; + +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate +{ + Q_OBJECT + +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl(); + + bool isAvailable() const; + + int registerNdefMessageHandler(QObject *object, const QMetaMethod &method); + int registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, const QMetaMethod &method); + + bool unregisterNdefMessageHandler(int id); + + bool startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes); + void stopTargetDetection(); + +public://call back function by symbian backend implementation + void targetFound(QNearFieldTarget* target); + void targetDisconnected(); + +public://call back function by symbian backend implementation + void invokeNdefMessageHandler(const QNdefMessage msg); + + +private slots: + void _q_privateHandleMessageSlot(QNdefMessage msg); + +private: + struct Callback { + QNdefFilter filter; + QObject *object; + QMetaMethod method; + }; + + int getFreeId(); + + QList<Callback> m_registeredHandlers; + QList<int> m_freeIds; + + CNearFieldManager* m_symbianbackend; + + QPointer<QNearFieldTarget> m_target; + QList<QPointer<QNearFieldTarget> > m_targetList; + //For content handler purpose; + QObject *m_chobject; + QMetaMethod m_chmethod; + + QRemoteServiceRegister* m_serviceRegister ; +}; + +QT_END_HEADER +#endif /* QNEARFIELDMANAGER_SYMBIAN_P_H_ */ diff --git a/src/nfc/qnearfieldmanagerimpl_p.cpp b/src/nfc/qnearfieldmanagerimpl_p.cpp new file mode 100644 index 00000000..24609b30 --- /dev/null +++ b/src/nfc/qnearfieldmanagerimpl_p.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QCoreApplication> + +#include "qnearfieldmanagerimpl_p.h" + + +/* + Constructs a new near field manager private implementation. +*/ +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() +{ +} + +/* + Destroys the near field manager private implementation. +*/ +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ +} +//#include "moc_qnearfieldmanagerimpl_p.cpp" + diff --git a/src/nfc/qnearfieldmanagerimpl_p.h b/src/nfc/qnearfieldmanagerimpl_p.h new file mode 100644 index 00000000..fffcebd2 --- /dev/null +++ b/src/nfc/qnearfieldmanagerimpl_p.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGERIMPL_P_H +#define QNEARFIELDMANAGERIMPL_P_H + +#include "qnearfieldmanager_p.h" + +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate +{ +public: + QNearFieldManagerPrivateImpl(); + ~QNearFieldManagerPrivateImpl(); +}; + +#endif // QNEARFIELDMANAGERIMPL_P_H diff --git a/src/nfc/qnearfieldmanagervirtualbase.cpp b/src/nfc/qnearfieldmanagervirtualbase.cpp new file mode 100644 index 00000000..84b88f2f --- /dev/null +++ b/src/nfc/qnearfieldmanagervirtualbase.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldmanagervirtualbase_p.h" +#include "qndefmessage.h" +#include "qtlv_p.h" + +static inline bool matchesTarget(QNearFieldTarget::Type type, + const QList<QNearFieldTarget::Type> &types) +{ + return types.contains(type) || types.contains(QNearFieldTarget::AnyTarget); +} + +QNearFieldManagerPrivateVirtualBase::QNearFieldManagerPrivateVirtualBase() +{ +} + +QNearFieldManagerPrivateVirtualBase::~QNearFieldManagerPrivateVirtualBase() +{ +} + +bool QNearFieldManagerPrivateVirtualBase::startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes) +{ + m_detectTargetTypes = targetTypes; + return true; +} + +void QNearFieldManagerPrivateVirtualBase::stopTargetDetection() +{ + m_detectTargetTypes.clear(); +} + +int QNearFieldManagerPrivateVirtualBase::getFreeId() +{ + if (!m_freeIds.isEmpty()) + return m_freeIds.takeFirst(); + + m_registeredHandlers.append(Callback()); + return m_registeredHandlers.count() - 1; +} + +int QNearFieldManagerPrivateVirtualBase::registerNdefMessageHandler(QObject *object, + const QMetaMethod &method) +{ + int id = getFreeId(); + + Callback &callback = m_registeredHandlers[id]; + + callback.filter = QNdefFilter(); + callback.object = object; + callback.method = method; + + return id; +} + +int QNearFieldManagerPrivateVirtualBase::registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, + const QMetaMethod &method) +{ + int id = getFreeId(); + + Callback &callback = m_registeredHandlers[id]; + + callback.filter = filter; + callback.object = object; + callback.method = method; + + return id; +} + +bool QNearFieldManagerPrivateVirtualBase::unregisterNdefMessageHandler(int id) +{ + if (id < 0 || id >= m_registeredHandlers.count()) + return false; + + m_freeIds.append(id); + + while (m_freeIds.contains(m_registeredHandlers.count() - 1)) { + m_freeIds.removeAll(m_registeredHandlers.count() - 1); + m_registeredHandlers.removeLast(); + } + + return true; +} + +void QNearFieldManagerPrivateVirtualBase::targetActivated(QNearFieldTarget *target) +{ + if (matchesTarget(target->type(), m_detectTargetTypes)) + emit targetDetected(target); + + if (target->hasNdefMessage()) { + QTlvReader reader(target); + while (!reader.atEnd()) { + if (!reader.readNext()) { + if (!target->waitForRequestCompleted(reader.requestId())) + break; + else + continue; + } + + // NDEF Message TLV + if (reader.tag() == 0x03) + ndefReceived(QNdefMessage::fromByteArray(reader.data()), target); + } + } +} + +void QNearFieldManagerPrivateVirtualBase::targetDeactivated(QNearFieldTarget *target) +{ + emit targetLost(target); + QMetaObject::invokeMethod(target, "disconnected"); +} + +struct VerifyRecord +{ + QNdefFilter::Record filterRecord; + unsigned int count; +}; + +void QNearFieldManagerPrivateVirtualBase::ndefReceived(const QNdefMessage &message, + QNearFieldTarget *target) +{ + for (int i = 0; i < m_registeredHandlers.count(); ++i) { + if (m_freeIds.contains(i)) + continue; + + Callback &callback = m_registeredHandlers[i]; + + bool matched = true; + + QList<VerifyRecord> filterRecords; + for (int j = 0; j < callback.filter.recordCount(); ++j) { + VerifyRecord vr; + vr.count = 0; + vr.filterRecord = callback.filter.recordAt(j); + + filterRecords.append(vr); + } + + foreach (const QNdefRecord &record, message) { + for (int j = 0; matched && (j < filterRecords.count()); ++j) { + VerifyRecord &vr = filterRecords[j]; + + if (vr.filterRecord.typeNameFormat == record.typeNameFormat() && + vr.filterRecord.type == record.type()) { + ++vr.count; + break; + } else { + if (callback.filter.orderMatch()) { + if (vr.filterRecord.minimum <= vr.count && + vr.count <= vr.filterRecord.maximum) { + continue; + } else { + matched = false; + } + } + } + } + } + + for (int j = 0; matched && (j < filterRecords.count()); ++j) { + const VerifyRecord &vr = filterRecords.at(j); + + if (vr.filterRecord.minimum <= vr.count && vr.count <= vr.filterRecord.maximum) + continue; + else + matched = false; + } + + if (matched) { + callback.method.invoke(callback.object, Q_ARG(QNdefMessage, message), + Q_ARG(QNearFieldTarget *, target)); + } + } +} + +#include "moc_qnearfieldmanagervirtualbase_p.cpp" diff --git a/src/nfc/qnearfieldmanagervirtualbase_p.h b/src/nfc/qnearfieldmanagervirtualbase_p.h new file mode 100644 index 00000000..6dac5657 --- /dev/null +++ b/src/nfc/qnearfieldmanagervirtualbase_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGERVIRTUALBASE_P_H +#define QNEARFIELDMANAGERVIRTUALBASE_P_H + +#include "qnearfieldmanager_p.h" + +#include <QtCore/QMetaMethod> + +QT_BEGIN_HEADER + +class QNearFieldManagerPrivateVirtualBase : public QNearFieldManagerPrivate +{ + Q_OBJECT + +public: + QNearFieldManagerPrivateVirtualBase(); + ~QNearFieldManagerPrivateVirtualBase(); + + bool startTargetDetection(const QList<QNearFieldTarget::Type> &targetTypes); + void stopTargetDetection(); + + int registerNdefMessageHandler(QObject *object, const QMetaMethod &method); + int registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, const QMetaMethod &method); + + bool unregisterNdefMessageHandler(int id); + +protected: + struct Callback { + QNdefFilter filter; + + QObject *object; + QMetaMethod method; + }; + + void targetActivated(QNearFieldTarget *target); + void targetDeactivated(QNearFieldTarget *target); + +private: + int getFreeId(); + void ndefReceived(const QNdefMessage &message, QNearFieldTarget *target); + + QList<Callback> m_registeredHandlers; + QList<int> m_freeIds; + QList<QNearFieldTarget::Type> m_detectTargetTypes; +}; + +QT_END_HEADER + +#endif // QNEARFIELDMANAGERVIRTUALBASE_P_H diff --git a/src/nfc/qnearfieldtagmifare_symbian.cpp b/src/nfc/qnearfieldtagmifare_symbian.cpp new file mode 100644 index 00000000..14f13205 --- /dev/null +++ b/src/nfc/qnearfieldtagmifare_symbian.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <nfctag.h> +#include <QVariant> +#include "qnearfieldtagmifare_symbian_p.h" + +QNearFieldTagMifareSymbian::QNearFieldTagMifareSymbian(CNearFieldNdefTarget *tag, QObject *parent) + : QNearFieldTarget(parent), QNearFieldTagImpl(tag) +{ +} + +QNearFieldTagMifareSymbian::~QNearFieldTagMifareSymbian() +{ +} + +QByteArray QNearFieldTagMifareSymbian::uid() const +{ + return _uid(); +} + +bool QNearFieldTagMifareSymbian::hasNdefMessage() +{ + return _hasNdefMessage(); +} + +QNearFieldTarget::RequestId QNearFieldTagMifareSymbian::readNdefMessages() +{ + return _ndefMessages(); +} + +QNearFieldTarget::RequestId QNearFieldTagMifareSymbian::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + return _setNdefMessages(messages); +} + +QNearFieldTarget::RequestId QNearFieldTagMifareSymbian::sendCommand(const QByteArray &command) +{ + return _sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagMifareSymbian::sendCommands(const QList<QByteArray> &commands) +{ + return _sendCommands(commands); +} + +void QNearFieldTagMifareSymbian::handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted) +{ + Q_UNUSED(command); + QVariant decodedResponse = decodeResponse(command, response); + setResponseForRequest(id, decodedResponse, emitRequestCompleted); +} + +bool QNearFieldTagMifareSymbian::waitForRequestCompleted(const RequestId &id, int msecs) +{ + BEGIN + END + return _waitForRequestCompleted(id, msecs); +} +#include "moc_qnearfieldtagmifare_symbian_p.cpp" diff --git a/src/nfc/qnearfieldtagmifare_symbian_p.h b/src/nfc/qnearfieldtagmifare_symbian_p.h new file mode 100644 index 00000000..f9714e38 --- /dev/null +++ b/src/nfc/qnearfieldtagmifare_symbian_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QNEARFIELDTAGMIFARE_H +#define QNEARFIELDTAGMIFARE_H + +#include "qnearfieldtarget.h" +#include "symbian/nearfieldndeftarget_symbian.h" +#include "symbian/nearfieldtag_symbian.h" +#include "symbian/nearfieldtagimpl_symbian.h" + +QT_BEGIN_HEADER + +class QNdefMessage; + +class QNearFieldTagMifareSymbian : public QNearFieldTarget, private QNearFieldTagImpl<QNearFieldTagMifareSymbian> +{ + Q_OBJECT + +public: + explicit QNearFieldTagMifareSymbian(CNearFieldNdefTarget *tag, QObject *parent = 0); + + ~QNearFieldTagMifareSymbian(); + + QByteArray uid() const; + + QNearFieldTarget::Type type() const { return QNearFieldTarget::MifareTag; } + QNearFieldTarget::AccessMethods accessMethods() const + { + return _accessMethods(); + } + + void setAccessMethods(const QNearFieldTarget::AccessMethods& accessMethods) + { + _setAccessMethods(accessMethods); + } + // NdefAccess + bool hasNdefMessage(); + RequestId readNdefMessages(); + RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + + // TagTypeSpecificAccess + RequestId sendCommand(const QByteArray &command); + RequestId sendCommands(const QList<QByteArray> &commands); + bool isProcessingCommand() const { return _isProcessingRequest(); } + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + + void handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted); + QVariant decodeResponse(const QByteArray &/*command*/, const QByteArray &response) { return response; } +signals: + void disconnected(); + + friend class QNearFieldTagImpl<QNearFieldTagMifareSymbian>; +}; + +QT_END_HEADER + +#endif // QNEARFIELDTAGMIFARE_H diff --git a/src/nfc/qnearfieldtagtype1.cpp b/src/nfc/qnearfieldtagtype1.cpp new file mode 100644 index 00000000..eb1d6c7e --- /dev/null +++ b/src/nfc/qnearfieldtagtype1.cpp @@ -0,0 +1,735 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldtagtype1.h" +#include "qnearfieldtarget_p.h" +#include "qndefmessage.h" +#include "qtlv_p.h" + +#include <QtCore/QByteArray> +#include <QtCore/QVariant> + +#include <QtCore/QDebug> + +/*! + \class QNearFieldTagType1 + \brief The QNearFieldTagType1 class provides an interface for communicating with an NFC Tag + Type 1 tag. + \since 5.0 + + \ingroup connectivity-nfc + \inmodule QtConnectivity +*/ + +/*! + \enum QNearFieldTagType1::WriteMode + \brief This enum describes the write modes that are supported. + + \value EraseAndWrite The memory is erased before the new value is written. + \value WriteOnly The memory is not erased before the new value is written. The effect of + this mode is that the final value store is the bitwise or of the data + to be written and the original data value. +*/ + +/*! + \fn Type QNearFieldTagType1::type() const + \reimp +*/ + +class QNearFieldTagType1Private +{ + Q_DECLARE_PUBLIC(QNearFieldTagType1) + +public: + QNearFieldTagType1Private(QNearFieldTagType1 *q) + : q_ptr(q), m_readNdefMessageState(NotReadingNdefMessage), + m_tlvReader(0), + m_writeNdefMessageState(NotWritingNdefMessage) + { } + + QNearFieldTagType1 *q_ptr; + + QMap<QNearFieldTarget::RequestId, QByteArray> m_pendingInternalCommands; + + enum ReadNdefMessageState { + NotReadingNdefMessage, + NdefReadCheckingIdentification, + NdefReadCheckingNdefMagicNumber, + NdefReadReadingTlv + }; + + void progressToNextNdefReadMessageState(); + ReadNdefMessageState m_readNdefMessageState; + QNearFieldTarget::RequestId m_readNdefRequestId; + + QTlvReader *m_tlvReader; + QNearFieldTarget::RequestId m_nextExpectedRequestId; + + enum WriteNdefMessageState { + NotWritingNdefMessage, + NdefWriteCheckingIdentification, + NdefWriteCheckingNdefMagicNumber, + NdefWriteReadingTlv, + NdefWriteWritingTlv, + NdefWriteWritingTlvFlush + }; + + void progressToNextNdefWriteMessageState(); + WriteNdefMessageState m_writeNdefMessageState; + QNearFieldTarget::RequestId m_writeNdefRequestId; + QList<QNdefMessage> m_ndefWriteMessages; + + QTlvWriter *m_tlvWriter; + + typedef QPair<quint8, QByteArray> Tlv; + QList<Tlv> m_tlvs; +}; + +void QNearFieldTagType1Private::progressToNextNdefReadMessageState() +{ + Q_Q(QNearFieldTagType1); + + switch (m_readNdefMessageState) { + case NotReadingNdefMessage: + m_readNdefMessageState = NdefReadCheckingIdentification; + m_nextExpectedRequestId = q->readIdentification(); + break; + case NdefReadCheckingIdentification: { + const QByteArray data = q->requestResponse(m_nextExpectedRequestId).toByteArray(); + + if (data.isEmpty()) { + m_readNdefMessageState = NotReadingNdefMessage; + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + emit q->error(QNearFieldTarget::NdefReadError, m_readNdefRequestId); + m_readNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + quint8 hr0 = data.at(0); + + // Check if target is a NFC TagType1 tag + if (!(hr0 & 0x10)) { + m_readNdefMessageState = NotReadingNdefMessage; + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + emit q->error(QNearFieldTarget::NdefReadError, m_readNdefRequestId); + m_readNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + m_readNdefMessageState = NdefReadCheckingNdefMagicNumber; + m_nextExpectedRequestId = q->readByte(8); + break; + } + case NdefReadCheckingNdefMagicNumber: { + quint8 ndefMagicNumber = q->requestResponse(m_nextExpectedRequestId).toUInt(); + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + + if (ndefMagicNumber != 0xe1) { + m_readNdefMessageState = NotReadingNdefMessage; + emit q->error(QNearFieldTarget::NdefReadError, m_readNdefRequestId); + m_readNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + m_readNdefMessageState = NdefReadReadingTlv; + m_tlvReader = new QTlvReader(q); + + // fall through + } + case NdefReadReadingTlv: + while (!m_tlvReader->atEnd()) { + if (!m_tlvReader->readNext()) + break; + + // NDEF Message TLV + if (m_tlvReader->tag() == 0x03) { + Q_Q(QNearFieldTagType1); + + emit q->ndefMessageRead(QNdefMessage::fromByteArray(m_tlvReader->data())); + } + } + + m_nextExpectedRequestId = m_tlvReader->requestId(); + if (!m_nextExpectedRequestId.isValid()) { + delete m_tlvReader; + m_tlvReader = 0; + m_readNdefMessageState = NotReadingNdefMessage; + emit q->requestCompleted(m_readNdefRequestId); + m_readNdefRequestId = QNearFieldTarget::RequestId(); + } + break; + } +} + +void QNearFieldTagType1Private::progressToNextNdefWriteMessageState() +{ + Q_Q(QNearFieldTagType1); + + switch (m_writeNdefMessageState) { + case NotWritingNdefMessage: + m_writeNdefMessageState = NdefWriteCheckingIdentification; + m_nextExpectedRequestId = q->readIdentification(); + break; + case NdefWriteCheckingIdentification: { + const QByteArray data = q->requestResponse(m_nextExpectedRequestId).toByteArray(); + + if (data.isEmpty()) { + m_writeNdefMessageState = NotWritingNdefMessage; + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + emit q->error(QNearFieldTarget::NdefWriteError, m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + quint8 hr0 = data.at(0); + + // Check if target is a NFC TagType1 tag + if (!(hr0 & 0x10)) { + m_writeNdefMessageState = NotWritingNdefMessage; + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + emit q->error(QNearFieldTarget::NdefWriteError, m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + m_writeNdefMessageState = NdefWriteCheckingNdefMagicNumber; + m_nextExpectedRequestId = q->readByte(8); + break; + } + case NdefWriteCheckingNdefMagicNumber: { + quint8 ndefMagicNumber = q->requestResponse(m_nextExpectedRequestId).toUInt(); + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + + if (ndefMagicNumber != 0xe1) { + m_writeNdefMessageState = NotWritingNdefMessage; + emit q->error(QNearFieldTarget::NdefWriteError, m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + break; + } + + m_writeNdefMessageState = NdefWriteReadingTlv; + m_tlvReader = new QTlvReader(q); + + // fall through + } + case NdefWriteReadingTlv: + while (!m_tlvReader->atEnd()) { + if (!m_tlvReader->readNext()) + break; + + quint8 tag = m_tlvReader->tag(); + if (tag == 0x01 || tag == 0x02 || tag == 0xfd) + m_tlvs.append(qMakePair(tag, m_tlvReader->data())); + } + + m_nextExpectedRequestId = m_tlvReader->requestId(); + if (m_nextExpectedRequestId.isValid()) + break; + + delete m_tlvReader; + m_tlvReader = 0; + m_writeNdefMessageState = NdefWriteWritingTlv; + + // fall through + case NdefWriteWritingTlv: + m_tlvWriter = new QTlvWriter(q); + + // write old TLVs + foreach (const Tlv &tlv, m_tlvs) + m_tlvWriter->writeTlv(tlv.first, tlv.second); + + // write new NDEF message TLVs + foreach (const QNdefMessage &message, m_ndefWriteMessages) + m_tlvWriter->writeTlv(0x03, message.toByteArray()); + + // write terminator TLV + m_tlvWriter->writeTlv(0xfe); + + m_writeNdefMessageState = NdefWriteWritingTlvFlush; + + // fall through + case NdefWriteWritingTlvFlush: + // flush the writer + if (m_tlvWriter->process(true)) { + m_nextExpectedRequestId = QNearFieldTarget::RequestId(); + m_writeNdefMessageState = NotWritingNdefMessage; + delete m_tlvWriter; + m_tlvWriter = 0; + emit q->ndefMessagesWritten(); + emit q->requestCompleted(m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + } else { + m_nextExpectedRequestId = m_tlvWriter->requestId(); + if (!m_nextExpectedRequestId.isValid()) { + m_writeNdefMessageState = NotWritingNdefMessage; + delete m_tlvWriter; + m_tlvWriter = 0; + emit q->error(QNearFieldTarget::NdefWriteError, m_writeNdefRequestId); + m_writeNdefRequestId = QNearFieldTarget::RequestId(); + } + } + break; + } +} + +static QVariant decodeResponse(const QByteArray &command, const QByteArray &response) +{ + switch (command.at(0)) { + case 0x01: // READ + if (command.at(1) == response.at(0)) + return quint8(response.at(1)); + break; + case 0x53: { // WRITE-E + quint8 address = command.at(1); + quint8 data = command.at(2); + quint8 writeAddress = response.at(0); + quint8 writeData = response.at(1); + + return ((writeAddress == address) && (writeData == data)); + } + case 0x1a: { // WRITE-NE + quint8 address = command.at(1); + quint8 data = command.at(2); + quint8 writeAddress = response.at(0); + quint8 writeData = response.at(1); + + return ((writeAddress == address) && ((writeData & data) == data)); + } + case 0x10: { // RSEG + quint8 segmentAddress = quint8(command.at(1)) >> 4; + quint8 readSegmentAddress = quint8(response.at(0)) >> 4; + if (readSegmentAddress == segmentAddress) + return response.mid(1); + break; + } + case 0x02: { // READ8 + quint8 blockAddress = command.at(1); + quint8 readBlockAddress = response.at(0); + if (readBlockAddress == blockAddress) + return response.mid(1); + break; + } + case 0x54: { // WRITE-E8 + quint8 blockAddress = command.at(1); + QByteArray data = command.mid(2, 8); + quint8 writeBlockAddress = response.at(0); + QByteArray writeData = response.mid(1); + + return ((writeBlockAddress == blockAddress) && (writeData == data)); + } + case 0x1b: { // WRITE-NE8 + quint8 blockAddress = command.at(1); + QByteArray data = command.mid(2, 8); + quint8 writeBlockAddress = response.at(0); + QByteArray writeData = response.mid(1); + + if (writeBlockAddress != blockAddress) + return false; + + for (int i = 0; i < writeData.length(); ++i) { + if ((writeData.at(i) & data.at(i)) != data.at(i)) + return false; + } + + return true; + } + } + + return QVariant(); +} + +/*! + Constructs a new tag type 1 near field target with \a parent. +*/ +QNearFieldTagType1::QNearFieldTagType1(QObject *parent) +: QNearFieldTarget(parent), d_ptr(new QNearFieldTagType1Private(this)) +{ +} + +/*! + Destroys the tag type 1 near field target. +*/ +QNearFieldTagType1::~QNearFieldTagType1() +{ + delete d_ptr; +} + +/*! + \reimp +*/ +bool QNearFieldTagType1::hasNdefMessage() +{ + RequestId id = readAll(); + if (!waitForRequestCompleted(id)) + return false; + + const QByteArray data = requestResponse(id).toByteArray(); + + if (data.isEmpty()) + return false; + + quint8 hr0 = data.at(0); + + // Check if target is a NFC TagType1 tag + if (!(hr0 & 0x10)) + return false; + + // Check if NDEF Message Magic number is present + quint8 nmn = data.at(10); + if (nmn != 0xe1) + return false; + + // Check if TLV contains NDEF Message + return true; +} + +/*! + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readNdefMessages() +{ + Q_D(QNearFieldTagType1); + + d->m_readNdefRequestId = RequestId(new RequestIdPrivate); + + if (d->m_readNdefMessageState == QNearFieldTagType1Private::NotReadingNdefMessage) { + d->progressToNextNdefReadMessageState(); + } else { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, NdefReadError), + Q_ARG(QNearFieldTarget::RequestId, d->m_readNdefRequestId)); + } + + return d->m_readNdefRequestId; +} + +/*! + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + Q_D(QNearFieldTagType1); + + d->m_writeNdefRequestId = RequestId(new RequestIdPrivate); + + if (d->m_readNdefMessageState == QNearFieldTagType1Private::NotReadingNdefMessage && + d->m_writeNdefMessageState == QNearFieldTagType1Private::NotWritingNdefMessage) { + d->m_ndefWriteMessages = messages; + d->progressToNextNdefWriteMessageState(); + } else { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, NdefWriteError), + Q_ARG(QNearFieldTarget::RequestId, d->m_readNdefRequestId)); + } + + return d->m_writeNdefRequestId; +} + +/*! + Returns the NFC Tag Type 1 specification version number that the tag supports. +*/ +quint8 QNearFieldTagType1::version() +{ + RequestId id = readByte(9); + if (!waitForRequestCompleted(id)) + return 0; + + quint8 versionNumber = requestResponse(id).toUInt(); + return versionNumber; +} + +/*! + Returns the memory size in bytes of the tag. +*/ +int QNearFieldTagType1::memorySize() +{ + RequestId id = readByte(10); + if (!waitForRequestCompleted(id)) + return 0; + + quint8 tms = requestResponse(id).toUInt(); + + return 8 * (tms + 1); +} + +/*! + Requests the identification bytes from the target. Returns a request id which can be used to + track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray containing: HR0, + HR1, UID0, UID1, UID2 and UID3 in order. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readIdentification() +{ + QByteArray command; + command.append(char(0x78)); // RID + command.append(char(0x00)); // Address (unused) + command.append(char(0x00)); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + return sendCommand(command); +} + +/*! + Requests all data in the static memory area of the target. Returns a request id which can be + used to track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray containing: HR0 + and HR1 followed by the 120 bytes of data stored in the static memory area of the target. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readAll() +{ + QByteArray command; + command.append(char(0x00)); // RALL + command.append(char(0x00)); // Address (unused) + command.append(char(0x00)); // Data (unused) + command.append(uid().left(4));// 4 bytes of UID + + return sendCommand(command); +} + +/*! + Requests a single byte from the static memory area of the tag. The \a address parameter + specifices the linear byte address to read. Returns a request id which can be used to track + the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a quint8. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readByte(quint8 address) +{ + if (address & 0x80) + return RequestId(); + + QByteArray command; + command.append(char(0x01)); // READ + command.append(char(address)); // Address + command.append(char(0x00)); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Writes a single \a data byte to the linear byte \a address on the tag. If \a mode is + EraseAndWrite the byte will be erased before writing. If \a mode is WriteOnly the contents will + not be erased before writing. This is equivelant to writing the result of the bitwise OR of + \a data and the original value. + + Returns a request id which can be used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::writeByte(quint8 address, quint8 data, + WriteMode mode) +{ + if (address & 0x80) + return RequestId(); + + QByteArray command; + + if (mode == EraseAndWrite) + command.append(char(0x53)); // WRITE-E + else if (mode == WriteOnly) + command.append(char(0x1a)); // WRITE-NE + else + return RequestId(); + + command.append(char(address)); // Address + command.append(char(data)); // Data + command.append(uid().left(4)); // 4 bytes of UID + + RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Requests 128 bytes of data from the segment specified by \a segmentAddress. Returns a request + id which can be used to track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readSegment(quint8 segmentAddress) +{ + if (segmentAddress & 0xf0) + return RequestId(); + + QByteArray command; + command.append(char(0x10)); // RSEG + command.append(char(segmentAddress << 4)); // Segment address + command.append(QByteArray(8, char(0x00))); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Requests 8 bytes of data from the block specified by \a blockAddress. Returns a request id + which can be used to track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::readBlock(quint8 blockAddress) +{ + QByteArray command; + command.append(char(0x02)); // READ8 + command.append(char(blockAddress)); // Block address + command.append(QByteArray(8, char(0x00))); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Writes 8 bytes of \a data to the block specified by \a blockAddress. If \a mode is + EraseAndWrite the bytes will be erased before writing. If \a mode is WriteOnly the contents + will not be erased before writing. This is equivelant to writing the result of the bitwise OR + of \a data and the original value. + + Returns a request id which can be used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType1::writeBlock(quint8 blockAddress, + const QByteArray &data, + WriteMode mode) +{ + if (data.length() != 8) + return RequestId(); + + QByteArray command; + + if (mode == EraseAndWrite) + command.append(char(0x54)); // WRITE-E8 + else if (mode == WriteOnly) + command.append(char(0x1b)); // WRITE-NE8 + else + return RequestId(); + + command.append(char(blockAddress)); // Block address + command.append(data); // Data + command.append(uid().left(4)); // 4 bytes of UID + + RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType1); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + \reimp +*/ +bool QNearFieldTagType1::handleResponse(const QNearFieldTarget::RequestId &id, + const QByteArray &response) +{ + Q_D(QNearFieldTagType1); + + bool handled; + + if (d->m_pendingInternalCommands.contains(id)) { + const QByteArray command = d->m_pendingInternalCommands.take(id); + + QVariant decodedResponse = decodeResponse(command, response); + setResponseForRequest(id, decodedResponse); + + handled = true; + } else { + handled = QNearFieldTarget::handleResponse(id, response); + } + + // continue reading / writing NDEF message + if (d->m_nextExpectedRequestId == id) { + if (d->m_readNdefMessageState != QNearFieldTagType1Private::NotReadingNdefMessage) + d->progressToNextNdefReadMessageState(); + else if (d->m_writeNdefMessageState != QNearFieldTagType1Private::NotWritingNdefMessage) + d->progressToNextNdefWriteMessageState(); + } + + return handled; +} + +#include "moc_qnearfieldtagtype1.cpp" diff --git a/src/nfc/qnearfieldtagtype1.h b/src/nfc/qnearfieldtagtype1.h new file mode 100644 index 00000000..f925fda3 --- /dev/null +++ b/src/nfc/qnearfieldtagtype1.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGTYPE1_H +#define QNEARFIELDTAGTYPE1_H + +#include <qnearfieldtarget.h> + +QT_BEGIN_HEADER + +class QNearFieldTagType1Private; + +class Q_CONNECTIVITY_EXPORT QNearFieldTagType1 : public QNearFieldTarget +{ + Q_OBJECT + + Q_DECLARE_PRIVATE(QNearFieldTagType1) + +public: + enum WriteMode { + EraseAndWrite, + WriteOnly + }; + + explicit QNearFieldTagType1(QObject *parent = 0); + ~QNearFieldTagType1(); + + Type type() const { return NfcTagType1; } + + bool hasNdefMessage(); + RequestId readNdefMessages(); + RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + + quint8 version(); + virtual int memorySize(); + + // DIGPROTO + virtual RequestId readIdentification(); + + // static memory functions + virtual RequestId readAll(); + virtual RequestId readByte(quint8 address); + virtual RequestId writeByte(quint8 address, quint8 data, WriteMode mode = EraseAndWrite); + + // dynamic memory functions + virtual RequestId readSegment(quint8 segmentAddress); + virtual RequestId readBlock(quint8 blockAddress); + virtual RequestId writeBlock(quint8 blockAddress, const QByteArray &data, + WriteMode mode = EraseAndWrite); + +protected: + bool handleResponse(const QNearFieldTarget::RequestId &id, const QByteArray &response); + +private: + QNearFieldTagType1Private *d_ptr; +}; + +QT_END_HEADER + +#endif // QNEARFIELDTAGTYPE1_H diff --git a/src/nfc/qnearfieldtagtype1_symbian.cpp b/src/nfc/qnearfieldtagtype1_symbian.cpp new file mode 100644 index 00000000..fc7be21a --- /dev/null +++ b/src/nfc/qnearfieldtagtype1_symbian.cpp @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <nfctag.h> +#include <QVariant> +#include "symbian/nearfieldutility_symbian.h" +#include "qnearfieldtagtype1_symbian_p.h" +#include "debug.h" + +//#define SYMBIAN_BUG_NOT_FIX + +static void OutputByteArray(const QByteArray& data) +{ + for(int i = 0; i < data.count(); ++i) + { + LOG("data ["<<i<<"] = "<<((quint16)(data.at(i)))); + } +} + +QVariant QNearFieldTagType1Symbian::decodeResponse(const QByteArray &command, const QByteArray &response) +{ + BEGIN + OutputByteArray(response); + END + switch (command.at(0)) { + case 0x01: // READ +#ifndef SYMBIAN_BUG_NOT_FIX + if (command.at(1) == response.at(0)) + return quint8(response.at(1)); + break; +#else + return quint8(response.at(0)); +#endif + case 0x53: { // WRITE-E +#ifndef SYMBIAN_BUG_NOT_FIX + quint8 address = command.at(1); + quint8 data = command.at(2); + quint8 writeAddress = response.at(0); + quint8 writeData = response.at(1); + return ((writeAddress == address) && (writeData == data)); +#else + quint8 data = command.at(2); + + quint8 writeData = response.at(0); + return (writeData == data); +#endif + } + case 0x1a: { // WRITE-NE +#ifndef SYMBIAN_BUG_NOT_FIX + quint8 address = command.at(1); + quint8 data = command.at(2); + quint8 writeAddress = response.at(0); + quint8 writeData = response.at(1); + + return ((writeAddress == address) && ((writeData & data) == data)); +#else + quint8 data = command.at(2); + quint8 writeData = response.at(0); + return ((writeData & data) == data); +#endif + } + case 0x10: { // RSEG +#ifndef SYMBIAN_BUG_NOT_FIX + quint8 segmentAddress = quint8(command.at(1)) >> 4; + quint8 readSegmentAddress = quint8(response.at(0)) >> 4; + if (readSegmentAddress == segmentAddress) + return response.mid(1); + break; +#else + return response; +#endif + } + case 0x02: { // READ8 +#ifndef SYMBIAN_BUG_NOT_FIX + quint8 blockAddress = command.at(1); + quint8 readBlockAddress = response.at(0); + if (readBlockAddress == blockAddress) + return response.mid(1); + break; +#else + return response; +#endif + } + case 0x54: { // WRITE-E8 +#ifndef SYMBIAN_BUG_NOT_FIX + quint8 blockAddress = command.at(1); + QByteArray data = command.mid(2, 8); + quint8 writeBlockAddress = response.at(0); + QByteArray writeData = response.mid(1); + + return ((writeBlockAddress == blockAddress) && (writeData == data)); +#else + QByteArray data = command.mid(2, 8); + + return (response == data); +#endif + } + case 0x1b: { // WRITE-NE8 +#ifndef SYMBIAN_BUG_NOT_FIX + quint8 blockAddress = command.at(1); + QByteArray data = command.mid(2, 8); + quint8 writeBlockAddress = response.at(0); + QByteArray writeData = response.mid(1); + + if (writeBlockAddress != blockAddress) + return false; + + for (int i = 0; i < writeData.length(); ++i) { + if ((writeData.at(i) & data.at(i)) != data.at(i)) + return false; + } + return true; +#else + QByteArray data = command.mid(2, 8); + QByteArray writeData = response; + + for (int i = 0; i < writeData.length(); ++i) { + if ((writeData.at(i) & data.at(i)) != data.at(i)) + return false; + } + return true; +#endif + } + } + + return response; +} +/* + \class QNearFieldTagType1Symbian + \brief The QNearFieldTagType1Symbian class provides symbian backend implementation for communicating with an NFC Tag + Type 1 tag. + + \ingroup connectivity-nfc + \inmodule QtConnectivity +*/ + +/* + Constructs a new tag type 1 near field target with \a tag and \a parent. +*/ +QNearFieldTagType1Symbian::QNearFieldTagType1Symbian(CNearFieldNdefTarget *tag, QObject *parent) + : QNearFieldTagType1(parent), QNearFieldTagImpl(tag) +{ +} + +/* + Destructor +*/ +QNearFieldTagType1Symbian::~QNearFieldTagType1Symbian() +{ +} + +QByteArray QNearFieldTagType1Symbian::uid() const +{ + return _uid(); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::readIdentification() +{ + BEGIN + QByteArray command; + command.append(char(0x78)); // RID + command.append(char(0x00)); // Address (unused) + command.append(char(0x00)); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + END + return sendCommand(command); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::readAll() +{ + BEGIN + QByteArray command; + command.append(char(0x00)); // RALL + command.append(char(0x00)); + command.append(char(0x00)); + command.append(uid().left(4)); // UID + END + return sendCommand(command); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::readByte(quint8 address) +{ + BEGIN + // MSB must be 0 + if (address & 0x80) + return QNearFieldTarget::RequestId(); + + QByteArray command; + command.append(char(0x01)); // READ + command.append(char(address)); // Address + command.append(char(0x00)); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + END + return sendCommand(command); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::writeByte(quint8 address, quint8 data, WriteMode mode) +{ + BEGIN + // MSB must be 0 + if (address & 0x80) + { + END + return QNearFieldTarget::RequestId(); + } + + QByteArray command; + + if (mode == EraseAndWrite) + command.append(char(0x53)); // WRITE-E + else + command.append(char(0x1a)); // WRITE-NE + + command.append(char(address)); // Address + command.append(char(data)); // Data + command.append(uid().left(4)); // 4 bytes of UID + + END + return sendCommand(command); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::readSegment(quint8 segmentAddress) +{ + BEGIN + if (segmentAddress & 0xf0) + { + END + return QNearFieldTarget::RequestId(); + } + + QByteArray command; + command.append(char(0x10)); // RSEG + command.append(char(segmentAddress << 4)); // Segment address + command.append(QByteArray(8, char(0x00))); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UIDD + + END + return sendCommand(command); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::readBlock(quint8 blockAddress) +{ + BEGIN + QByteArray command; + command.append(char(0x02)); // READ8 + command.append(char(blockAddress)); // Block address + command.append(QByteArray(8, char(0x00))); // Data (unused) + command.append(uid().left(4)); // 4 bytes of UID + + END + return sendCommand(command); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::writeBlock(quint8 blockAddress, const QByteArray &data, + WriteMode mode) +{ + BEGIN + if (data.length() != 8) + { + END + return QNearFieldTarget::RequestId(); + } + + QByteArray command; + + if (mode == EraseAndWrite) + command.append(char(0x54)); // WRITE-E8 + else + command.append(char(0x1b)); // WRITE-NE8 + + command.append(char(blockAddress)); // Block address + command.append(data); // Data + command.append(uid().left(4)); // 4 bytes of UID + + END + return sendCommand(command); +} + +bool QNearFieldTagType1Symbian::hasNdefMessage() +{ + return _hasNdefMessage(); +} + +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::readNdefMessages() +{ + BEGIN + END + return _ndefMessages(); +} + +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + BEGIN + END + return _setNdefMessages(messages); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::sendCommand(const QByteArray &command) +{ + BEGIN + END + return _sendCommand(command); +} + +/* + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType1Symbian::sendCommands(const QList<QByteArray> &commands) +{ + BEGIN + END + return _sendCommands(commands); +} + +bool QNearFieldTagType1Symbian::waitForRequestCompleted(const RequestId &id, int msecs) +{ + BEGIN + END + return _waitForRequestCompleted(id, msecs); +} + +void QNearFieldTagType1Symbian::handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted) +{ + BEGIN + QVariant decodedResponse; + if (!response.isNull()) + { + decodedResponse = decodeResponse(command, response); + } + else + { + decodedResponse = response; + } + + setResponseForRequest(id, decodedResponse, emitRequestCompleted); + END +} + +#include "moc_qnearfieldtagtype1_symbian_p.cpp" diff --git a/src/nfc/qnearfieldtagtype1_symbian_p.h b/src/nfc/qnearfieldtagtype1_symbian_p.h new file mode 100644 index 00000000..cfcdbe70 --- /dev/null +++ b/src/nfc/qnearfieldtagtype1_symbian_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGTYPE1SYMBIAN_H +#define QNEARFIELDTAGTYPE1SYMBIAN_H + +#include <qnearfieldtagtype1.h> +#include "symbian/nearfieldndeftarget_symbian.h" +#include "symbian/nearfieldtag_symbian.h" +#include "symbian/nearfieldtagimpl_symbian.h" + +QT_BEGIN_HEADER + +class QNearFieldTagType1Symbian : public QNearFieldTagType1, private QNearFieldTagImpl<QNearFieldTagType1Symbian> +{ + Q_OBJECT + +public: + + explicit QNearFieldTagType1Symbian(CNearFieldNdefTarget *tag, QObject *parent = 0); + + ~QNearFieldTagType1Symbian(); + + virtual QByteArray uid() const; + + // DIGPROTO + RequestId readIdentification(); + + // static memory functions + RequestId readAll(); + RequestId readByte(quint8 address); + RequestId writeByte(quint8 address, quint8 data, WriteMode mode = EraseAndWrite); + + // dynamic memory functions + RequestId readSegment(quint8 segmentAddress); + RequestId readBlock(quint8 blockAddress); + RequestId writeBlock(quint8 blockAddress, const QByteArray &data, + WriteMode mode = EraseAndWrite); + + bool hasNdefMessage(); + RequestId readNdefMessages(); + RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + + bool isProcessingCommand() const { return _isProcessingRequest(); } + RequestId sendCommand(const QByteArray &command); + RequestId sendCommands(const QList<QByteArray> &commands); + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + + void setAccessMethods(const QNearFieldTarget::AccessMethods& accessMethods) + { + _setAccessMethods(accessMethods); + } + + QNearFieldTarget::AccessMethods accessMethods() const + { + return _accessMethods(); + } + + void handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted); + QVariant decodeResponse(const QByteArray &command, const QByteArray &response); + friend class QNearFieldTagImpl<QNearFieldTagType1Symbian>; +}; + +QT_END_HEADER + +#endif // QNEARFIELDTAGTYPE1SYMBIAN_H diff --git a/src/nfc/qnearfieldtagtype2.cpp b/src/nfc/qnearfieldtagtype2.cpp new file mode 100644 index 00000000..f54567ec --- /dev/null +++ b/src/nfc/qnearfieldtagtype2.cpp @@ -0,0 +1,348 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldtagtype2.h" +#include "qnearfieldtarget_p.h" + +#include <QtCore/QVariant> +#include <QtCore/QCoreApplication> +#include <QtCore/QTime> + +#include <QtCore/QDebug> + +/*! + \class QNearFieldTagType2 + \brief The QNearFieldTagType2 class provides an interface for communicating with an NFC Tag + Type 2 tag. + \since 5.0 + + \ingroup connectivity-nfc + \inmodule QtConnectivity +*/ + +/*! + \fn Type QNearFieldTagType2::type() const + \reimp +*/ + +struct SectorSelectState { + int timerId; // id of timer used for passive ack + quint8 sector; // sector being selected +}; + +class QNearFieldTagType2Private +{ +public: + QNearFieldTagType2Private() : m_currentSector(0) { } + + QMap<QNearFieldTarget::RequestId, QByteArray> m_pendingInternalCommands; + + quint8 m_currentSector; + + QMap<QNearFieldTarget::RequestId, SectorSelectState> m_pendingSectorSelectCommands; +}; + +static QVariant decodeResponse(const QByteArray &command, const QByteArray &response) +{ + quint8 opcode = command.at(0); + + switch (opcode) { + case 0xa2: // WRITE + return quint8(response.at(0)) == 0x0a; + case 0xc2: // SECTOR SELECT (Command Packet 1) + return quint8(response.at(0)) == 0x0a; + } + + return QVariant(); +} + +/*! + Constructs a new tag type 2 near field target with \a parent. +*/ +QNearFieldTagType2::QNearFieldTagType2(QObject *parent) +: QNearFieldTarget(parent), d_ptr(new QNearFieldTagType2Private) +{ +} + +/*! + Destroys the tag type 2 near field target. +*/ +QNearFieldTagType2::~QNearFieldTagType2() +{ + delete d_ptr; +} + +/*! + \reimp +*/ +bool QNearFieldTagType2::hasNdefMessage() +{ + qDebug() << Q_FUNC_INFO << "is unimplemeted"; + return false; +} + +/*! + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::readNdefMessages() +{ + return RequestId(); +} + +/*! + \reimp +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + Q_UNUSED(messages); + + return RequestId(); +} + +/*! + Returns the NFC Tag Type 2 specification version number that the tag supports. +*/ +quint8 QNearFieldTagType2::version() +{ + Q_D(QNearFieldTagType2); + if (d->m_currentSector != 0) { + RequestId id = selectSector(0); + if (!waitForRequestCompleted(id)) + return 0; + } + + RequestId id = readBlock(0); + if (!waitForRequestCompleted(id)) + return 0; + + const QByteArray data = requestResponse(id).toByteArray(); + return data.at(13); +} + +/*! + Returns the memory size in bytes of the tag. +*/ +int QNearFieldTagType2::memorySize() +{ + Q_D(QNearFieldTagType2); + if (d->m_currentSector != 0) { + RequestId id = selectSector(0); + if (!waitForRequestCompleted(id)) + return 0; + } + + RequestId id = readBlock(0); + if (!waitForRequestCompleted(id)) + return 0; + + const QByteArray data = requestResponse(id).toByteArray(); + return 8 * quint8(data.at(14)); +} + +/*! + Requests 16 bytes of data starting at \a blockAddress. Returns a request id which can be used + to track the completion status of the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::readBlock(quint8 blockAddress) +{ + QByteArray command; + command.append(char(0x30)); // READ + command.append(char(blockAddress)); // Block address + + return sendCommand(command); +} + +/*! + Writes 4 bytes of \a data to the block at \a blockAddress. Returns a request id which can be + used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + Returns true on success; otherwise returns false. +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::writeBlock(quint8 blockAddress, + const QByteArray &data) +{ + if (data.length() != 4) + return RequestId(); + + QByteArray command; + command.append(char(0xa2)); // WRITE + command.append(char(blockAddress)); // Block address + command.append(data); // Data + + RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType2); + + d->m_pendingInternalCommands.insert(id, command); + + return id; +} + +/*! + Selects the \a sector upon which subsequent readBlock() and writeBlock() operations will act. + + Returns a request id which can be used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \note this request has a passive acknowledgement mechanism. The operation is deemed successful + if no response is received within 1ms. It will therefore take a minimum of 1 millisecond for + the requestCompleted() signal to be emitted and calling waitForRequestCompleted() on the + returned request id may cause the current thread to block for up to 1 millisecond. +*/ +QNearFieldTarget::RequestId QNearFieldTagType2::selectSector(quint8 sector) +{ + QByteArray command; + command.append(char(0xc2)); // SECTOR SELECT (Command Packet 1) + command.append(char(0xff)); + + RequestId id = sendCommand(command); + + Q_D(QNearFieldTagType2); + + d->m_pendingInternalCommands.insert(id, command); + + SectorSelectState state; + state.timerId = -1; + state.sector = sector; + + d->m_pendingSectorSelectCommands.insert(id, state); + + return id; +} + +/*! + \reimp +*/ +bool QNearFieldTagType2::waitForRequestCompleted(const RequestId &id, int msecs) +{ + Q_D(QNearFieldTagType2); + + QTime timer; + timer.start(); + while (d->m_pendingSectorSelectCommands.contains(id)) { + QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents, 1); + + // detect passive ack + if (timer.elapsed() >= 1) + break; + } + + return QNearFieldTarget::waitForRequestCompleted(id, msecs); +} + +/*! + \reimp +*/ +bool QNearFieldTagType2::handleResponse(const QNearFieldTarget::RequestId &id, + const QByteArray &response) +{ + Q_D(QNearFieldTagType2); + + if (d->m_pendingInternalCommands.contains(id)) { + const QByteArray command = d->m_pendingInternalCommands.take(id); + + QVariant decodedResponse = decodeResponse(command, response); + if (quint8(command.at(0)) == 0xc2 && decodedResponse.toBool()) { + // SECTOR SELECT (Command Packet 2) + SectorSelectState &state = d->m_pendingSectorSelectCommands[id]; + + QByteArray packet2; + packet2.append(char(state.sector)); + packet2.append(QByteArray(3, 0x00)); + + sendCommand(packet2); + + state.timerId = startTimer(1); + } else { + setResponseForRequest(id, decodedResponse); + } + + return true; + } else if (d->m_pendingSectorSelectCommands.contains(id)) { + if (!response.isEmpty()) { + d->m_pendingSectorSelectCommands.remove(id); + setResponseForRequest(id, false); + + return true; + } + } + + return QNearFieldTarget::handleResponse(id, response); +} + +/*! + \internal +*/ +void QNearFieldTagType2::timerEvent(QTimerEvent *event) +{ + Q_D(QNearFieldTagType2); + + killTimer(event->timerId()); + + QMutableMapIterator<QNearFieldTarget::RequestId, SectorSelectState> i(d->m_pendingSectorSelectCommands); + while (i.hasNext()) { + i.next(); + + SectorSelectState &state = i.value(); + + if (state.timerId == event->timerId()) { + d->m_currentSector = state.sector; + + setResponseForRequest(i.key(), true); + + i.remove(); + + break; + } + } +} + +#include "moc_qnearfieldtagtype2.cpp" diff --git a/src/nfc/qnearfieldtagtype2.h b/src/nfc/qnearfieldtagtype2.h new file mode 100644 index 00000000..ad83fe8b --- /dev/null +++ b/src/nfc/qnearfieldtagtype2.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGTYPE2_H +#define QNEARFIELDTAGTYPE2_H + +#include <qnearfieldtarget.h> + +QT_BEGIN_HEADER + +class QNearFieldTagType2Private; + +class Q_CONNECTIVITY_EXPORT QNearFieldTagType2 : public QNearFieldTarget +{ + Q_OBJECT + + Q_DECLARE_PRIVATE(QNearFieldTagType2) + +public: + explicit QNearFieldTagType2(QObject *parent = 0); + ~QNearFieldTagType2(); + + Type type() const { return NfcTagType2; } + + bool hasNdefMessage(); + RequestId readNdefMessages(); + RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + + quint8 version(); + int memorySize(); + + virtual RequestId readBlock(quint8 blockAddress); + virtual RequestId writeBlock(quint8 blockAddress, const QByteArray &data); + virtual RequestId selectSector(quint8 sector); + + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + + void timerEvent(QTimerEvent *event); + +protected: + bool handleResponse(const QNearFieldTarget::RequestId &id, const QByteArray &response); + +private: + QNearFieldTagType2Private *d_ptr; +}; + +QT_END_HEADER + +#endif // QNEARFIELDTAGTYPE2_H diff --git a/src/nfc/qnearfieldtagtype2_symbian.cpp b/src/nfc/qnearfieldtagtype2_symbian.cpp new file mode 100644 index 00000000..adac6370 --- /dev/null +++ b/src/nfc/qnearfieldtagtype2_symbian.cpp @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <nfctag.h> +#include <QVariant> +#include "qnearfieldtagtype2_symbian_p.h" +#include <qnearfieldtarget_p.h> + +//#define SYMBIAN_NEED_CRC +//#define SYMBIAN_RETURN_CRC +//#define SYMBIAN_RETURN_NO_ACK + +static void OutputByteArray(const QByteArray& data) +{ + for(int i = 0; i < data.count(); ++i) + { + LOG("data ["<<i<<"] = "<<((quint16)(data.at(i)))); + } +} + +QNearFieldTagType2Symbian::QNearFieldTagType2Symbian(CNearFieldNdefTarget *tag, QObject *parent) + : QNearFieldTagType2(parent), QNearFieldTagImpl(tag), mCurrentSector(0) +{ +} + +QNearFieldTagType2Symbian::~QNearFieldTagType2Symbian() +{ + BEGIN + END +} + +QVariant QNearFieldTagType2Symbian::decodeResponse(const QByteArray& command, const QByteArray& response) +{ + BEGIN + OutputByteArray(response); + + QVariant result; + switch(command.at(0)) + { + case 0x30: + { + // read command +#ifdef SYMBIAN_RETURN_CRC + result = response.left(16); +#else + result = response; +#endif + break; + } + case 0xA2: + { +#ifdef SYMBIAN_RETURN_NO_ACK + result = true; +#else + // write command + result = (response.at(0) == 0x0A); +#endif + break; + } + default: + { +#ifdef SYMBIAN_RETURN_CRC + result = response.left(16); +#else + result = response; +#endif + } + } + END + return result; +} + +QNearFieldTarget::RequestId QNearFieldTagType2Symbian::readBlock(quint8 blockAddress) +{ + BEGIN + QByteArray command; + command.append(char(0x30)); // READ + command.append(char(blockAddress)); // Block address + +#ifdef SYMBIAN_NEED_CRC + // append CRC + quint16 crc = qNfcChecksum(command.constData(), command.count()); + command.append((unsigned char)(crc&0xFF)); + command.append((unsigned char)((crc>>8)&0xFF)); +#endif + END + return sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType2Symbian::writeBlock(quint8 blockAddress, const QByteArray &data) +{ + BEGIN + if (data.length() != 4) + { + END + return QNearFieldTarget::RequestId(); + } + QByteArray command; + command.append(char(0xa2)); // WRITE + command.append(char(blockAddress)); // Block address + command.append(data); // Data + +#ifdef SYMBIAN_NEED_CRC + // append CRC + quint16 crc = qNfcChecksum(command.constData(), command.count()); + command.append((unsigned char)(crc&0xFF)); + command.append((unsigned char)((crc>>8)&0xFF)); +#endif + + END + return sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType2Symbian::selectSector(quint8 sector) +{ + BEGIN + QByteArray command; + command.append(char(0xc2)); // SECTOR SELECT (Command Packet 1) + command.append(char(0xff)); + +#ifdef SYMBIAN_NEED_CRC + // append CRC + quint16 crc = qNfcChecksum(command.constData(), command.count()); + command.append((unsigned char)(crc&0xFF)); + command.append((unsigned char)((crc>>8)&0xFF)); +#endif + + RequestId id = sendCommand(command); + + if (!_waitForRequestCompletedNoSignal(id, 1)) + { + END + return QNearFieldTarget::RequestId(); + } + else + { + command.clear(); + command.append(char(sector)); // Sector number + command.append(QByteArray(3, char(0x00))); // RFU +#ifdef SYMBIAN_NEED_CRC + // append CRC + quint16 crc = qNfcChecksum(command.constData(), command.count()); + command.append((unsigned char)(crc&0xFF)); + command.append((unsigned char)((crc>>8)&0xFF)); +#endif + END + return sendCommand(command); + } +} + +QNearFieldTarget::RequestId QNearFieldTagType2Symbian::sendCommand(const QByteArray &command) +{ + BEGIN + END + return _sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType2Symbian::sendCommands(const QList<QByteArray> &commands) +{ + BEGIN + END + return _sendCommands(commands); +} + +bool QNearFieldTagType2Symbian::hasNdefMessage() +{ + return _hasNdefMessage(); +} + +QNearFieldTarget::RequestId QNearFieldTagType2Symbian::readNdefMessages() +{ + BEGIN + END + return _ndefMessages(); +} + +QNearFieldTarget::RequestId QNearFieldTagType2Symbian::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + BEGIN + END + return _setNdefMessages(messages); +} + +QByteArray QNearFieldTagType2Symbian::uid() const +{ + BEGIN + END + return _uid(); +} + +void QNearFieldTagType2Symbian::handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted) +{ + BEGIN + Q_UNUSED(command); + QVariant decodedResponse = decodeResponse(command, response); + setResponseForRequest(id, decodedResponse, emitRequestCompleted); + END +} + +bool QNearFieldTagType2Symbian::waitForRequestCompleted(const RequestId &id, int msecs) +{ + BEGIN + END + return _waitForRequestCompleted(id, msecs); +} + +#include "moc_qnearfieldtagtype2_symbian_p.cpp" diff --git a/src/nfc/qnearfieldtagtype2_symbian_p.h b/src/nfc/qnearfieldtagtype2_symbian_p.h new file mode 100644 index 00000000..10ac6066 --- /dev/null +++ b/src/nfc/qnearfieldtagtype2_symbian_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGTYPE2SYMBIAN_H +#define QNEARFIELDTAGTYPE2SYMBIAN_H + +#include <qnearfieldtagtype2.h> +#include "symbian/nearfieldndeftarget_symbian.h" +#include "symbian/nearfieldtag_symbian.h" +#include "symbian/nearfieldtagimpl_symbian.h" + +QT_BEGIN_HEADER + +class QNearFieldTagType2Symbian : public QNearFieldTagType2, private QNearFieldTagImpl<QNearFieldTagType2Symbian> +{ + Q_OBJECT +public: + explicit QNearFieldTagType2Symbian(CNearFieldNdefTarget * tag, QObject *parent = 0); + + ~QNearFieldTagType2Symbian(); + + QByteArray uid() const; + + RequestId readBlock(quint8 blockAddress); + RequestId writeBlock(quint8 blockAddress, const QByteArray &data); + RequestId selectSector(quint8 sector); + + RequestId sendCommand(const QByteArray &command); + RequestId sendCommands(const QList<QByteArray> &commands); + bool isProcessingCommand() const { return _isProcessingRequest(); } + + bool hasNdefMessage(); + RequestId readNdefMessages(); + RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + + void setAccessMethods(const QNearFieldTarget::AccessMethods& accessMethods) + { + _setAccessMethods(accessMethods); + } + + QNearFieldTarget::AccessMethods accessMethods() const + { + return _accessMethods(); + } + + void handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted); + QVariant decodeResponse(const QByteArray &command, const QByteArray &response); + + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + friend class QNearFieldTagImpl<QNearFieldTagType2Symbian>; + +private: + quint8 mCurrentSector; +}; + +QT_END_HEADER + +#endif //QNEARFIELDTAGTYPE2SYMBIAN_H diff --git a/src/nfc/qnearfieldtagtype3.cpp b/src/nfc/qnearfieldtagtype3.cpp new file mode 100644 index 00000000..2c751b09 --- /dev/null +++ b/src/nfc/qnearfieldtagtype3.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldtagtype3.h" + +/*! + \class QNearFieldTagType3 + \brief The QNearFieldTagType3 class provides an interface for communicating with an NFC Tag + Type 3 tag. + \since 5.0 + + \ingroup connectivity-nfc + \inmodule QtConnectivity +*/ + +/*! + \fn Type QNearFieldTagType3::type() const + \reimp +*/ + +/*! + Constructs a new tag type 3 near field target with \a parent. +*/ +QNearFieldTagType3::QNearFieldTagType3(QObject *parent) : + QNearFieldTarget(parent) +{ +} + +/*! + Returns the system code of the target. +*/ +quint16 QNearFieldTagType3::systemCode() +{ + return 0; +} + +/*! + Returns a list of available services. +*/ +QList<quint16> QNearFieldTagType3::services() +{ + return QList<quint16>(); +} + +/*! + Returns the memory size of the service specified by \a serviceCode. +*/ +int QNearFieldTagType3::serviceMemorySize(quint16 serviceCode) +{ + Q_UNUSED(serviceCode); + + return 0; +} + +/*! + Requests the data contents of the service specified by \a serviceCode. Returns a request id + which can be used to track the completion status of the request. + + Once the request completes successfully the service data can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType3::serviceData(quint16 serviceCode) +{ + Q_UNUSED(serviceCode); + + return RequestId(); +} + +/*! + Writes \a data to the the service specified by \a serviceCode. Returns a request id which can + be used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType3::writeServiceData(quint16 serviceCode, + const QByteArray &data) +{ + Q_UNUSED(serviceCode); + Q_UNUSED(data); + + return RequestId(); +} + +/*! + Sends the \i check request to the target. Requests the service data blocks specified by + \a serviceBlockList. Returns a request id which can be used to track the completion status of + the request. + + The \a serviceBlockList parameter is a map with the key being the service code and the value + being a list of block indexes to retrieve. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a QMap<quint16, QByteArray>, with the key being the + service code and the value being the concatenated blocks retrieved for that service. + + This is a low level function, to retrieve the entire data contents of a service use + serviceData(). + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType3::check(const QMap<quint16, QList<quint16> > &serviceBlockList) +{ + Q_UNUSED(serviceBlockList); + + return RequestId(); +} + +/*! + Sends the \i update request to the target. Writes \a data to the services and block indexes + sepecified by \a serviceBlockList. Returns a request id which can be used to track the + completion status of the request. + + The \a serviceBlockList parameter is a map with the key being the service code and the value + being a list of block indexes to write to. + + Once the request completes the response can be retried from the requestResponse() function. The + response of this request will be a boolean value, true for success; otherwise false. + + This is a low level function, to write the entire data contents of a service use + writeServiceData(). + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType3::update(const QMap<quint16, QList<quint16> > &serviceBlockList, + const QByteArray &data) +{ + Q_UNUSED(serviceBlockList); + Q_UNUSED(data); + + return RequestId(); +} + +/*! + \reimp +*/ +bool QNearFieldTagType3::handleResponse(const QNearFieldTarget::RequestId &id, + const QByteArray &response) +{ + return QNearFieldTarget::handleResponse(id, response); +} + +#include "moc_qnearfieldtagtype3.cpp" diff --git a/src/nfc/qnearfieldtagtype3.h b/src/nfc/qnearfieldtagtype3.h new file mode 100644 index 00000000..7ab9721d --- /dev/null +++ b/src/nfc/qnearfieldtagtype3.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGTYPE3_H +#define QNEARFIELDTAGTYPE3_H + +#include <qnearfieldtarget.h> + +#include <QtCore/QList> +#include <QtCore/QMap> + +QT_BEGIN_HEADER + +class Q_CONNECTIVITY_EXPORT QNearFieldTagType3 : public QNearFieldTarget +{ + Q_OBJECT + +public: + explicit QNearFieldTagType3(QObject *parent = 0); + + Type type() const { return NfcTagType3; } + + quint16 systemCode(); + QList<quint16> services(); + int serviceMemorySize(quint16 serviceCode); + + virtual RequestId serviceData(quint16 serviceCode); + virtual RequestId writeServiceData(quint16 serviceCode, const QByteArray &data); + + virtual RequestId check(const QMap<quint16, QList<quint16> > &serviceBlockList); + virtual RequestId update(const QMap<quint16, QList<quint16> > &serviceBlockList, + const QByteArray &data); + +protected: + bool handleResponse(const QNearFieldTarget::RequestId &id, const QByteArray &response); +}; + +QT_END_HEADER + +#endif // QNEARFIELDTAGTYPE3_H diff --git a/src/nfc/qnearfieldtagtype3_symbian.cpp b/src/nfc/qnearfieldtagtype3_symbian.cpp new file mode 100644 index 00000000..b7c66a6a --- /dev/null +++ b/src/nfc/qnearfieldtagtype3_symbian.cpp @@ -0,0 +1,504 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <nfctag.h> +#include "qnearfieldtagtype3_symbian_p.h" +#include <nfctype3connection.h> +#include <QtEndian> +#include <QVariant> + +/* For all #if 0 blocks: this is due to symbian RawModeAccess API is not + * available yet. After the RawModeAccess API is stable, those blocks + * should be enabled. + */ + +#define SYMBIAN_RESP_INCLUDE_LEN + +static void OutputByteArray(const QByteArray& data) +{ + for(int i = 0; i < data.count(); ++i) + { + LOG("data ["<<i<<"] = "<<((quint16)(data.at(i)))); + } +} + +static void OutputCmdMap(const QMap<quint16, QList<quint16> >& data) +{ + QList<quint16> mapKeys = data.keys(); + for(int i = 0; i < mapKeys.count(); ++i) + { + LOG("cmd Map key "<<mapKeys.at(i)<<" value "<<data.value(mapKeys.at(i))); + } +} + +static void OutputRspMap(const QMap<quint16, QByteArray>& data) +{ + QList<quint16> mapKeys = data.keys(); + for(int i = 0; i < mapKeys.count(); ++i) + { + LOG("rsp Map key "<<mapKeys.at(i)); + OutputByteArray(data.value(mapKeys.at(i))); + } +} + +QNearFieldTagType3Symbian::QNearFieldTagType3Symbian(CNearFieldNdefTarget *tag, QObject *parent) + : QNearFieldTagType3(parent), QNearFieldTagImpl(tag) +{ + // It's silly, but easy. + getIDm(); +} + +QNearFieldTagType3Symbian::~QNearFieldTagType3Symbian() +{ +} + +QByteArray QNearFieldTagType3Symbian::uid() const +{ + return _uid(); +} + +QVariant QNearFieldTagType3Symbian::decodeResponse(const QByteArray & command, const QByteArray &response) +{ + BEGIN + OutputByteArray(response); +#ifndef SYMBIAN_RESP_INCLUDE_LEN + QVariant result; + if (command.count() < 0) + { + END; + return result; + } + + switch(command.at(0)) + { + case 0x06: + { + // check command + result.setValue(checkResponse2ServiceBlockList(cmd2ServiceBlockList(command), response)); + break; + } + case 0x08: + { + result = (response.at(9) == 0); + break; + } + default: + { + result = response; + } + + } + END +#else + QVariant result; + if (command.count() < 0) + { + END; + return result; + } + QByteArray newResponse = response.right(response.count() - 1); + switch(command.at(0)) + { + case 0x06: + { + // check command + result.setValue(checkResponse2ServiceBlockList(cmd2ServiceBlockList(command), newResponse)); + break; + } + case 0x08: + { + result = (newResponse.at(9) == 0); + break; + } + default: + { + result = newResponse; + } + } + END +#endif + return result; +} + +bool QNearFieldTagType3Symbian::hasNdefMessage() +{ +#if 0 + BEGIN + bool hasNdef = false; + QList<quint16> blockList; + // first block + blockList.append(0); + // NDEF service + quint16 serviceCode = 0x0B; + + QMap<quint16, QList<quint16> > serviceBlockList; + serviceBlockList.insert(serviceCode, blockList); + + QNearFieldTarget::RequestId id = check(serviceBlockList); + + if (_waitForRequestCompletedNoSignal(id)) + { + QMap<quint16, QByteArray> result = requestResponse(id).value<QMap<quint16, QByteArray> >(); + if (result.contains(serviceCode)) + { + const QByteArray& lens = result.value(serviceCode); + if (!lens.isEmpty()) + { + quint32 len = lens.at(11); + len<<=8; + len |= lens.at(12); + len<<=8; + len |= lens.at(13); + hasNdef = (len > 0); + } + } + } + END + return hasNdef; +#endif + return _hasNdefMessage(); +} + +QNearFieldTarget::RequestId QNearFieldTagType3Symbian::readNdefMessages() +{ + return _ndefMessages(); +} + +QNearFieldTarget::RequestId QNearFieldTagType3Symbian::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + return _setNdefMessages(messages); +} + +QNearFieldTarget::RequestId QNearFieldTagType3Symbian::sendCommand(const QByteArray &command) +{ + return _sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType3Symbian::sendCommands(const QList<QByteArray> &commands) +{ + return _sendCommands(commands); +} + +#if 0 +quint16 QNearFieldTagType3Symbian::systemCode() +{ + return 0; +} + +QList<quint16> QNearFieldTagType3Symbian::services() +{ + return QList<quint16>(); +} + +int QNearFieldTagType3Symbian::serviceMemorySize(quint16 serviceCode) +{ + Q_UNUSED(serviceCode); + return 0; +} + +QNearFieldTarget::RequestId QNearFieldTagType3Symbian::serviceData(quint16 serviceCode) +{ + Q_UNUSED(serviceCode); + return QNearFieldTarget::RequestId(); +} + +QNearFieldTarget::RequestId QNearFieldTagType3Symbian::writeServiceData(quint16 serviceCode, const QByteArray &data) +{ + Q_UNUSED(serviceCode); + Q_UNUSED(data); + + return RequestId(); +} +#endif + +QNearFieldTarget::RequestId QNearFieldTagType3Symbian::check(const QMap<quint16, QList<quint16> > &serviceBlockList) +{ + BEGIN + quint8 numberOfBlocks; + QByteArray command; + command.append(0x06); // command code + command.append(serviceBlockList2CmdParam(serviceBlockList, numberOfBlocks, true)); + if (command.count() > 1) + { + END + return (_sendCommand(command)); + } + else + { + END + return QNearFieldTarget::RequestId(); + } +} + +QNearFieldTarget::RequestId QNearFieldTagType3Symbian::update(const QMap<quint16, QList<quint16> > &serviceBlockList, const QByteArray &data) +{ + BEGIN + quint8 numberOfBlocks; + QByteArray command; + command.append(0x08); // command code + command.append(serviceBlockList2CmdParam(serviceBlockList, numberOfBlocks, false)); + if (command.count() > 1) + { + command.append(data); + END + return (_sendCommand(command)); + } + else + { + END + return QNearFieldTarget::RequestId(); + } +} + +const QByteArray& QNearFieldTagType3Symbian::getIDm() +{ + BEGIN + if (mIDm.isEmpty()) + { + // this is the first time to get IDm + CNearFieldTag * tag = mTag->CastToTag(); + + if (tag) + { + CNfcType3Connection * connection = static_cast<CNfcType3Connection *>(tag->TagConnection()); + TBuf8<8> IDm; + TInt error = connection->GetIDm(IDm); + if (KErrNone == error) + { + mIDm = QNFCNdefUtility::TDesC2QByteArray(IDm); + } + } + } + OutputByteArray(mIDm); + END + return mIDm; +} + +QByteArray QNearFieldTagType3Symbian::serviceBlockList2CmdParam(const QMap<quint16, QList<quint16> > &serviceBlockList, quint8& numberOfBlocks, bool isCheckCommand) +{ + BEGIN + OutputCmdMap(serviceBlockList); + QByteArray command; + command.append(getIDm()); + numberOfBlocks = 0; + + if (command.isEmpty()) + { + // can't get IDm + END + return command; + } + + quint8 numberOfServices = serviceBlockList.keys().count(); + + if ((numberOfServices > 16) || (numberOfServices < 1)) + { + // out of range of services number + END + return QByteArray(); + } + else + { + command.append(numberOfServices); + } + + quint8 serviceCodeListOrder = 0; + QByteArray serviceCodeList; + QByteArray blockList; + foreach(const quint16 serviceCode, serviceBlockList.keys()) + { + serviceCodeList.append(reinterpret_cast<const char *>(&serviceCode), sizeof(quint16)); + + numberOfBlocks += serviceBlockList.value(serviceCode).count(); + LOG("numberOfBlocks "<<numberOfBlocks) + if ( (isCheckCommand && (numberOfBlocks > 12)) || + (!isCheckCommand && (numberOfBlocks > 8)) ) + { + // out of range of block number + LOG("out of range of block number"); + END + return QByteArray(); + } + + foreach(const quint16 blockNumber, serviceBlockList.value(serviceCode)) + { + if (blockNumber > 255) + { + // 3 bytes format + blockList.append(0x00 | (serviceCodeListOrder & 0x0F)); + quint16 blkNum = blockNumber; + blkNum = qToLittleEndian(blkNum); + blockList.append(reinterpret_cast<const char *>(&blkNum), sizeof(quint16)); + } + else // 2 bytes format + { + blockList.append(0x80 | (serviceCodeListOrder & 0x0F)); + quint8 blkNum = blockNumber; + blockList.append(blkNum); + } + } + } + + if (numberOfBlocks < 1) + { + // out of range of block number + LOG("out of range of block number, number of blocks < 1"); + END + return QByteArray(); + } + + command.append(serviceCodeList); + command.append(numberOfBlocks); + command.append(blockList); + OutputByteArray(command); + END + return command; +} + +QMap<quint16, QList<quint16> > QNearFieldTagType3Symbian::cmd2ServiceBlockList(const QByteArray& cmd) +{ + BEGIN + QMap<quint16, QList<quint16> > result; + // skip command code and IDm + QByteArray data = cmd.right(cmd.count() - 9); + + quint8 numberOfServices = data.at(0); + + QByteArray serviceCodeList = data.mid(1, 2 * numberOfServices); + + quint8 numberOfBlocks = data.at(2 * numberOfServices + 1); + + QByteArray blockList = data.right(data.count() - 1 - 2*numberOfServices - 1); + + QList<quint16> svcList; + for (int i = 0; i < numberOfServices; ++i) + { + unsigned char bytes[2]; + bytes[0] = serviceCodeList.at(i*2); + bytes[1] = serviceCodeList.at(i*2+1); + quint16 serviceCode = qFromLittleEndian<quint16>(bytes); + svcList.append(serviceCode); + } + + for (int j = 0, k = 0; j < numberOfBlocks; ++j, ++k) + { + quint8 byte0 = blockList.at(k); + quint8 serviceCodeListOrder = byte0 & 0x0F; + quint16 blockNumber = 0; + + if (byte0 & 0x80) + { + // two bytes format + blockNumber = blockList.at(++k); + } + else + { + // three bytes format + unsigned char bytes[2]; + bytes[0] = blockList.at(++k); + bytes[1] = blockList.at(++k); + blockNumber = qFromLittleEndian<quint16>(bytes); + } + + if (result.contains(svcList.at(serviceCodeListOrder))) + { + result[svcList.at(serviceCodeListOrder)].append(blockNumber); + } + else + { + QList<quint16> blocks; + blocks.append(blockNumber); + result.insert(svcList.at(serviceCodeListOrder), blocks); + } + } + + OutputCmdMap(result); + + END + return result; +} + +QMap<quint16, QByteArray> QNearFieldTagType3Symbian::checkResponse2ServiceBlockList(const QMap<quint16, QList<quint16> > &serviceBlockList, const QByteArray& response) +{ + BEGIN + OutputCmdMap(serviceBlockList); + QMap<quint16, QByteArray> result; + // at least, the response should contain resp code + IDM + status flags + if (response.count() < 11) + { + END + return result; + } + + if ((response.at(0) != 0x07) || (response.mid(1,8) != getIDm()) || (response.at(10) != 0)) + { + END + return result; + } + + quint32 index = 12; + foreach(const quint16 serviceCode, serviceBlockList.keys()) + { + quint8 blockCount = serviceBlockList.value(serviceCode).count(); + result.insert(serviceCode, response.mid(index, 16*blockCount)); + index+=16*blockCount; + } + OutputRspMap(result); + END + return result; +} + + +void QNearFieldTagType3Symbian::handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted) +{ + Q_UNUSED(command); + QVariant decodedResponse = decodeResponse(command, response); + setResponseForRequest(id, decodedResponse, emitRequestCompleted); +} + +bool QNearFieldTagType3Symbian::waitForRequestCompleted(const RequestId &id, int msecs) +{ + BEGIN + END + return _waitForRequestCompleted(id, msecs); +} + +#include "moc_qnearfieldtagtype3_symbian_p.cpp" diff --git a/src/nfc/qnearfieldtagtype3_symbian_p.h b/src/nfc/qnearfieldtagtype3_symbian_p.h new file mode 100644 index 00000000..a726ae8b --- /dev/null +++ b/src/nfc/qnearfieldtagtype3_symbian_p.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGTYPE3SYMBIAN_H +#define QNEARFIELDTAGTYPE3SYMBIAN_H + +#include <qnearfieldtagtype3.h> +#include "symbian/nearfieldtagimpl_symbian.h" +#include "symbian/nearfieldndeftarget_symbian.h" + +QT_BEGIN_HEADER + +class QNearFieldTagType3Symbian : public QNearFieldTagType3, private QNearFieldTagImpl<QNearFieldTagType3Symbian> +{ + Q_OBJECT +public: + + explicit QNearFieldTagType3Symbian(CNearFieldNdefTarget *tag, QObject *parent = 0); + + ~QNearFieldTagType3Symbian(); + + virtual QByteArray uid() const; + + void setAccessMethods(const QNearFieldTarget::AccessMethods& accessMethods) + { + _setAccessMethods(accessMethods); + } + + QNearFieldTarget::AccessMethods accessMethods() const + { + return _accessMethods(); + } + + bool hasNdefMessage(); + RequestId readNdefMessages(); + RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + +#if 0 + quint16 systemCode(); + QList<quint16> services(); + int serviceMemorySize(quint16 serviceCode); + + + RequestId serviceData(quint16 serviceCode); + RequestId writeServiceData(quint16 serviceCode, const QByteArray &data); +#endif + + RequestId check(const QMap<quint16, QList<quint16> > &serviceBlockList); + RequestId update(const QMap<quint16, QList<quint16> > &serviceBlockList, + const QByteArray &data); + + bool isProcessingCommand() const { return _isProcessingRequest(); } + RequestId sendCommand(const QByteArray &command); + RequestId sendCommands(const QList<QByteArray> &commands); + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); +private: + const QByteArray& getIDm(); + QByteArray serviceBlockList2CmdParam(const QMap<quint16, QList<quint16> > &serviceBlockList, quint8& numberOfBlocks, bool isCheckCommand); + QMap<quint16, QList<quint16> > cmd2ServiceBlockList(const QByteArray& cmd); + + QMap<quint16, QByteArray> checkResponse2ServiceBlockList(const QMap<quint16, QList<quint16> > &serviceBlockList, const QByteArray& response); + + void handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted); + QVariant decodeResponse(const QByteArray & command, const QByteArray &response); +private: + QByteArray mIDm; + friend class QNearFieldTagImpl<QNearFieldTagType3Symbian>; +}; + +typedef QMap<quint16,QByteArray> checkResponseType; +Q_DECLARE_METATYPE(checkResponseType) +QT_END_HEADER +#endif // QNEARFIELDTAGTYPE3SYMBIAN_H + diff --git a/src/nfc/qnearfieldtagtype4.cpp b/src/nfc/qnearfieldtagtype4.cpp new file mode 100644 index 00000000..19cf8b80 --- /dev/null +++ b/src/nfc/qnearfieldtagtype4.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldtagtype4.h" + +/*! + \class QNearFieldTagType4 + \brief The QNearFieldTagType4 class provides an interface for communicating with an NFC Tag + Type 4 tag. + \since 5.0 + + \ingroup connectivity-nfc + \inmodule QtConnectivity +*/ + +/*! + \fn Type QNearFieldTagType4::type() const + \reimp +*/ + +/*! + Constructs a new tag type 4 near field target with \a parent. +*/ +QNearFieldTagType4::QNearFieldTagType4(QObject *parent) +: QNearFieldTarget(parent) +{ +} + +/*! + Destroys the tag type 4 near field target. +*/ +QNearFieldTagType4::~QNearFieldTagType4() +{ +} + +/*! + Returns the NFC Tag Type 4 specification version number that the tag supports. +*/ +quint8 QNearFieldTagType4::version() +{ + return 0; +} + +/*! + Requests that the file specified by \a name be selected. Upon success calls to read() and + write() will act on the selected file. Returns a request id which can be used to track the + completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType4::select(const QByteArray &name) +{ + Q_UNUSED(name); + + return RequestId(); +} + +/*! + Requests that the file specified by \a fileIdentifier be selected. Upon success calls to read() + and write() will act on the selected file. Returns a request id which can be used to track the + completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType4::select(quint16 fileIdentifier) +{ + Q_UNUSED(fileIdentifier); + + return RequestId(); +} + +/*! + Requests that \a length bytes be read from the currently selected file starting from + \a startOffset. If \a length is 0 all data or the maximum read size bytes will be read, + whichever is smaller. Returns a request id which can be used to track the completion status of + the request. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType4::read(quint16 length, quint16 startOffset) +{ + Q_UNUSED(length); + Q_UNUSED(startOffset); + + return RequestId(); +} + +/*! + Writes \a data to the currently selected file starting at \a startOffset. Returns a request id + which can be used to track the completion status of the request. + + Once the request completes the response can be retrieved from the requestResponse() function. + The response of this request will be a boolean value, true for success; otherwise false. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTagType4::write(const QByteArray &data, quint16 startOffset) +{ + Q_UNUSED(data); + Q_UNUSED(startOffset); + + return RequestId(); +} + +/*! + \reimp +*/ +bool QNearFieldTagType4::handleResponse(const QNearFieldTarget::RequestId &id, + const QByteArray &response) +{ + return QNearFieldTarget::handleResponse(id, response); +} + +#include "moc_qnearfieldtagtype4.cpp" diff --git a/src/nfc/qnearfieldtagtype4.h b/src/nfc/qnearfieldtagtype4.h new file mode 100644 index 00000000..d280580c --- /dev/null +++ b/src/nfc/qnearfieldtagtype4.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGTYPE4_H +#define QNEARFIELDTAGTYPE4_H + +#include <qnearfieldtarget.h> + +QT_BEGIN_HEADER + +class Q_CONNECTIVITY_EXPORT QNearFieldTagType4 : public QNearFieldTarget +{ + Q_OBJECT + +public: + explicit QNearFieldTagType4(QObject *parent = 0); + ~QNearFieldTagType4(); + + Type type() const { return NfcTagType4; } + + quint8 version(); + + virtual RequestId select(const QByteArray &name); + virtual RequestId select(quint16 fileIdentifier); + + virtual RequestId read(quint16 length = 0, quint16 startOffset = 0); + virtual RequestId write(const QByteArray &data, quint16 startOffset = 0); + +protected: + bool handleResponse(const QNearFieldTarget::RequestId &id, const QByteArray &response); +}; + +QT_END_HEADER + +#endif // QNEARFIELDTAGTYPE4_H diff --git a/src/nfc/qnearfieldtagtype4_symbian.cpp b/src/nfc/qnearfieldtagtype4_symbian.cpp new file mode 100644 index 00000000..b1940b62 --- /dev/null +++ b/src/nfc/qnearfieldtagtype4_symbian.cpp @@ -0,0 +1,396 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <nfctag.h> +#include <QVariant> +#include <QtEndian> +#include "symbian/nearfieldutility_symbian.h" +#include "qnearfieldtagtype4_symbian_p.h" + +static void OutputByteArray(const QByteArray& data) +{ + for(int i = 0; i < data.count(); ++i) + { + LOG("data ["<<i<<"] = "<<((quint16)(data.at(i)))); + } +} + +QNearFieldTagType4Symbian::QNearFieldTagType4Symbian(CNearFieldNdefTarget *tag, QObject *parent) + : QNearFieldTagType4(parent), QNearFieldTagImpl(tag) +{ +} + +QNearFieldTagType4Symbian::~QNearFieldTagType4Symbian() +{ +} + +QByteArray QNearFieldTagType4Symbian::uid() const +{ + return _uid(); +} + +quint8 QNearFieldTagType4Symbian::version() +{ + BEGIN + quint8 result = 0; + QByteArray resp; + resp.append(char(0x90)); + resp.append(char(0x00)); + + QNearFieldTarget::RequestId id = selectNdefApplication(); + if (_waitForRequestCompletedNoSignal(id)) + { + if (requestResponse(id).toByteArray().right(2) == resp) + { + // response is ok + // select cc + LOG("select cc"); + QNearFieldTarget::RequestId id1 = selectCC(); + if (_waitForRequestCompletedNoSignal(id1)) + { + if (requestResponse(id1).toBool()) + { + // response is ok + // read cc + LOG("read cc"); + QNearFieldTarget::RequestId id2 = read(0x0001,0x0002); + if (_waitForRequestCompletedNoSignal(id2)) + { + if (requestResponse(id2).toByteArray().right(2) == resp) + { + // response is ok + result = requestResponse(id2).toByteArray().at(0); + } + } + } + } + } + } + LOG("version is "<<result); + END + return result; +} + +QVariant QNearFieldTagType4Symbian::decodeResponse(const QByteArray &command, const QByteArray &response) +{ + BEGIN + QVariant result; + + OutputByteArray(response); + if ((command.count() > 2) && (0x00 == command.at(0))) + { + if ( (0xA4 == command.at(1)) || (0xD6 == command.at(1)) ) + { + if (response.count() >= 2) + { + LOG("select or write command"); + QByteArray resp = response.right(2); + result = ((resp.at(0) == 0x90) && (resp.at(1) == 0x00)); + } + } + else + { + LOG("read command"); + result = response; + } + } + END + return result; +} + +bool QNearFieldTagType4Symbian::hasNdefMessage() +{ + BEGIN + QByteArray resp; + resp.append(char(0x90)); + resp.append(char(0x00)); + + QNearFieldTarget::RequestId id = selectNdefApplication(); + if (!_waitForRequestCompletedNoSignal(id)) + { + LOG("select NDEF application failed"); + END + return false; + } + + if (!requestResponse(id).toBool()) + { + LOG("select NDEF application response is not ok"); + END + return false; + } + + QNearFieldTarget::RequestId id1 = selectCC(); + if (!_waitForRequestCompletedNoSignal(id1)) + { + LOG("select CC failed"); + END + return false; + } + + if (!requestResponse(id1).toBool()) + { + LOG("select CC response is not ok"); + END + return false; + } + + QNearFieldTarget::RequestId id2 = read(0x000F,0x0000); + if (!_waitForRequestCompletedNoSignal(id2)) + { + LOG("read CC failed"); + END + return false; + } + + QByteArray ccContent = requestResponse(id2).toByteArray(); + if (ccContent.right(2) != resp) + { + LOG("read CC response is "<<ccContent.right(2)); + END + return false; + } + + if ((ccContent.count() != (15 + 2)) && (ccContent.at(1) != 0x0F)) + { + LOG("CC is invalid"<<ccContent); + END + return false; + } + + quint8 temp = ccContent.at(9); + quint16 fileId = 0; + fileId |= temp; + fileId<<=8; + + temp = ccContent.at(10); + fileId |= temp; + + temp = ccContent.at(11); + quint16 maxNdefLen = 0; + maxNdefLen |= temp; + maxNdefLen<<=8; + + temp = ccContent.at(12); + maxNdefLen |= temp; + + QNearFieldTarget::RequestId id3 = select(fileId); + if (!_waitForRequestCompletedNoSignal(id3)) + { + LOG("select NDEF failed"); + END + return false; + } + if (!requestResponse(id3).toBool()) + { + END + return false; + } + + QNearFieldTarget::RequestId id4 = read(0x0002, 0x0000); + if (!_waitForRequestCompletedNoSignal(id4)) + { + LOG("read NDEF failed"); + END + return false; + } + QByteArray ndefContent = requestResponse(id4).toByteArray(); + if (ndefContent.right(2) != resp) + { + LOG("read NDEF response is "<<ndefContent.right(2)); + END + return false; + } + + if (ndefContent.count() != (2 + 2)) + { + LOG("ndef content invalid"); + END + return false; + } + + temp = ndefContent.at(0); + quint16 nLen = 0; + nLen |= temp; + nLen<<=8; + + temp = ndefContent.at(1); + nLen |= temp; + + END + return ( (nLen > 0) && (nLen < maxNdefLen -2) ); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::readNdefMessages() +{ + return _ndefMessages(); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + return _setNdefMessages(messages); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::sendCommand(const QByteArray &command) +{ + return _sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::sendCommands(const QList<QByteArray> &commands) +{ + return _sendCommands(commands); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::select(const QByteArray &name) +{ + BEGIN + QByteArray command; + command.append(char(0x00)); // CLA + command.append(char(0xA4)); // INS + command.append(char(0x04)); // P1, select by name + command.append(char(0x00)); // First or only occurrence + command.append(char(0x07)); // Lc + command.append(name); + END + return _sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::select(quint16 fileIdentifier) +{ + BEGIN + QByteArray command; + command.append(char(0x00)); // CLA + command.append(char(0xA4)); // INS + command.append(char(0x00)); // P1, select by file identifier + command.append(char(0x00)); // First or only occurrence + command.append(char(0x02)); // Lc + quint16 temp = qToBigEndian<quint16>(fileIdentifier); + command.append(reinterpret_cast<const char*>(&temp), + sizeof(quint16)); + + END + return _sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::read(quint16 length, quint16 startOffset) +{ + BEGIN + QByteArray command; + command.append(char(0x00)); // CLA + command.append(char(0xB0)); // INS + quint16 temp = qToBigEndian<quint16>(startOffset); + command.append(reinterpret_cast<const char*>(&temp), + sizeof(quint16)); // P1/P2 offset + /*temp = qToBigEndian<quint16>(length); + command.append(reinterpret_cast<const char*>(&temp), + sizeof(quint16)); // Le*/ + command.append((quint8)length); + + END + return _sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::write(const QByteArray &data, quint16 startOffset) +{ + BEGIN + QByteArray command; + command.append(char(0x00)); // CLA + command.append(char(0xD6)); // INS + quint16 temp = qToBigEndian<quint16>(startOffset); + command.append(reinterpret_cast<const char *>(&temp), sizeof(quint16)); + quint16 length = data.count(); + if ((length > 0xFF) || (length < 0x01)) + { + END + return QNearFieldTarget::RequestId(); + } + else + { + /*quint16 temp = qToBigEndian<quint16>(length); + command.append(reinterpret_cast<const char *>(&temp), + sizeof(quint16));*/ + command.append((quint8)length); + } + + command.append(data); + END + return _sendCommand(command); +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::selectNdefApplication() +{ + BEGIN + QByteArray command; + command.append(char(0xD2)); + command.append(char(0x76)); + command.append(char(0x00)); + command.append(char(0x00)); + command.append(char(0x85)); + command.append(char(0x01)); + command.append(char(0x00)); + QNearFieldTarget::RequestId id = select(command); + END + return id; +} + +QNearFieldTarget::RequestId QNearFieldTagType4Symbian::selectCC() +{ + BEGIN + END + return select(0xe103); +} + +void QNearFieldTagType4Symbian::handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted) +{ + BEGIN + Q_UNUSED(command); + QVariant decodedResponse = decodeResponse(command, response); + setResponseForRequest(id, decodedResponse, emitRequestCompleted); + END +} + +bool QNearFieldTagType4Symbian::waitForRequestCompleted(const RequestId &id, int msecs) +{ + BEGIN + END + return _waitForRequestCompleted(id, msecs); +} +#include "moc_qnearfieldtagtype4_symbian_p.cpp" diff --git a/src/nfc/qnearfieldtagtype4_symbian_p.h b/src/nfc/qnearfieldtagtype4_symbian_p.h new file mode 100644 index 00000000..6bf8bf59 --- /dev/null +++ b/src/nfc/qnearfieldtagtype4_symbian_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGTYPE4SYMBIAN_H +#define QNEARFIELDTAGTYPE4SYMBIAN_H + +#include <qnearfieldtagtype4.h> +#include "symbian/nearfieldndeftarget_symbian.h" +#include "symbian/nearfieldtag_symbian.h" +#include "symbian/nearfieldtagimpl_symbian.h" +#include "symbian/debug.h" + +QT_BEGIN_HEADER + +class QNearFieldTagType4Symbian : public QNearFieldTagType4, private QNearFieldTagImpl<QNearFieldTagType4Symbian> +{ + Q_OBJECT + +public: + + explicit QNearFieldTagType4Symbian(CNearFieldNdefTarget *tag, QObject *parent = 0); + + ~QNearFieldTagType4Symbian(); + + virtual QByteArray uid() const; + Type type() const { return NfcTagType4; } + quint8 version(); + + bool hasNdefMessage(); + RequestId readNdefMessages(); + RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + + RequestId sendCommand(const QByteArray &command); + RequestId sendCommands(const QList<QByteArray> &commands); + + RequestId select(const QByteArray &name); + RequestId select(quint16 fileIdentifier); + + RequestId read(quint16 length = 0, quint16 startOffset = 0); + RequestId write(const QByteArray &data, quint16 startOffset = 0); + bool isProcessingCommand() const { return _isProcessingRequest(); } + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + + void setAccessMethods(const QNearFieldTarget::AccessMethods& accessMethods) + { + _setAccessMethods(accessMethods); + } + + QNearFieldTarget::AccessMethods accessMethods() const + { + return _accessMethods(); + } + + void handleTagOperationResponse(const RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted); + QVariant decodeResponse(const QByteArray &command, const QByteArray &response); + +private: + RequestId selectNdefApplication(); + RequestId selectCC(); + + friend class QNearFieldTagImpl<QNearFieldTagType4Symbian>; +}; + +QT_END_HEADER + +#endif // QNEARFIELDTAGTYPE4SYMBIAN_H diff --git a/src/nfc/qnearfieldtarget.cpp b/src/nfc/qnearfieldtarget.cpp new file mode 100644 index 00000000..8a7d25bc --- /dev/null +++ b/src/nfc/qnearfieldtarget.cpp @@ -0,0 +1,464 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldtarget.h" +#include "qnearfieldtarget_p.h" +#include "qndefmessage.h" + +#include <QtCore/QString> +#include <QtCore/QUrl> +#include <QtCore/QVariant> + +#include <QtCore/QDebug> + +/*! + \class QNearFieldTarget + \brief The QNearFieldTarget class provides an interface for communicating with a target + device. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + + QNearFieldTarget provides a generic interface for communicating with an NFC target device. + Both NFC Forum devices and NFC Forum Tag targets are supported by this class. All target + specific classes subclass this class. + + The type() function can be used to get the type of the target device. The uid() function + returns the unique identifier of the target. The AccessMethods flags returns from the + accessMethods() function can be tested to determine which access methods are supported by the + target. + + If the target supports NdefAccess, hasNdefMessage() can be called to test if the target has a + stored NDEF message, readNdefMessages() and writeNdefMessages() functions can be used to get + and set the NDEF message. + + If the target supports TagTypeSpecificAccess, sendCommand() can be used to send a single + proprietary command to the target and retrieve the response. sendCommands() can be used to + send multiple proprietary commands to the target and retrieve all of the responses. + + If the target supports LlcpAccess, the QLlcpSocket class can be used to connected to a + service provided by the target. +*/ + +/*! + \enum QNearFieldTarget::Type + + This enum describes the type of tag the target is detected as. + + \value AnyTarget This value is only used when registering handlers to indicate that any + compatible target can be used. + \value ProprietaryTag An unidentified proprietary target tag. + \value NfcTagType1 An NFC tag type 1 target. + \value NfcTagType2 An NFC tag type 2 target. + \value NfcTagType3 An NFC tag type 3 target. + \value NfcTagType4 An NFC tag type 4 target. + \value MifareTag A Mifare target. + \value NfcForumDevice An NFC Forum device target. +*/ + +/*! + \enum QNearFieldTarget::AccessMethod + + This enum describes the access methods a near field target supports. + + \value NdefAccess The target supports reading and writing NDEF messages using + readNdefMessages() and writeNdefMessages(). + \value TagTypeSpecificAccess The target supports sending tag type specific commands using + sendCommand() and sendCommands(). + \value LlcpAccess The target supports peer-to-peer LLCP communication. +*/ + +/*! + \enum QNearFieldTarget::Error + + This enum describes the error codes that that a near field target reports. + + \value NoError No error has occurred. + \value UnknownError An unidentified error occurred. + \value UnsupportedError The requested operation is unsupported by this near field + target. + \value TargetOutOfRangeError The target is no longer within range. + \value NoResponseError The target did not respond. + \value ChecksumMismatchError The checksum has detected a corrupted response. + \value InvalidParametersError Invalid parameters were passed to a tag type specific function. + \value NdefReadError Failed to read NDEF messages from the target. + \value NdefWriteError Failed to write NDEF messages to the target. +*/ + +/*! + \fn qNfcChecksum(const char *data, uint len) + + \relates QNearFieldTarget + + Returns the NFC checksum of the first \a len bytes of \a data. +*/ +#include "checksum_p.h" + +/*! + \fn void QNearFieldTarget::disconnected() + + This signal is emitted when the near field target moves out of proximity. +*/ + +/*! + \fn void QNearFieldTarget::ndefMessageRead(const QNdefMessage &message) + + This signal is emitted when a complete NDEF \a message has been read from the target. + + \sa readNdefMessages() +*/ + +/*! + \fn void QNearFieldTarget::ndefMessagesWritten() + + This signal is emitted when NDEF messages have been successfully written to the target. + + \sa writeNdefMessages() +*/ + +/*! + \fn void QNearFieldTarget::requestCompleted(const QNearFieldTarget::RequestId &id) + + This signal is emitted when a request \a id completes. + + \sa sendCommand() +*/ + +/*! + \fn void QNearFieldTarget::error(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id) + + This signal is emitted when an error occurs while processing request \a id. The \a error + parameter describes the error. +*/ + +/*! + Constructs a new invalid request id handle. +*/ +QNearFieldTarget::RequestId::RequestId() +{ +} + +/*! + Constructs a new request id handle that is a copy of \a other. +*/ +QNearFieldTarget::RequestId::RequestId(const RequestId &other) +: d(other.d) +{ +} + +/*! + \internal +*/ +QNearFieldTarget::RequestId::RequestId(RequestIdPrivate *p) +: d(p) +{ +} + +/*! + Destroys the request id handle. +*/ +QNearFieldTarget::RequestId::~RequestId() +{ +} + +/*! + Returns true if this is a valid request id; otherwise returns false. +*/ +bool QNearFieldTarget::RequestId::isValid() const +{ + return d; +} + +/*! + Returns the current reference count of the request id. +*/ +int QNearFieldTarget::RequestId::refCount() const +{ + if (d) + return d->ref; + + return 0; +} + +/*! + \internal +*/ +bool QNearFieldTarget::RequestId::operator<(const RequestId &other) const +{ + return d < other.d; +} + +/*! + \internal +*/ +bool QNearFieldTarget::RequestId::operator==(const RequestId &other) const +{ + return d == other.d; +} + +/*! + \internal +*/ +bool QNearFieldTarget::RequestId::operator!=(const RequestId &other) const +{ + return d != other.d; +} + +/*! + Assigns a copy of \a other to this request id and returns a reference to this request id. +*/ +QNearFieldTarget::RequestId &QNearFieldTarget::RequestId::operator=(const RequestId &other) +{ + d = other.d; + return *this; +} + +/*! + Constructs a new near field target with \a parent. +*/ +QNearFieldTarget::QNearFieldTarget(QObject *parent) +: QObject(parent), d_ptr(new QNearFieldTargetPrivate) +{ + qRegisterMetaType<RequestId>("QNearFieldTarget::RequestId"); + qRegisterMetaType<Error>("QNearFieldTarget::Error"); +} + +/*! + Destroys the near field target. +*/ +QNearFieldTarget::~QNearFieldTarget() +{ + delete d_ptr; +} + +/*! + \fn QByteArray QNearFieldTarget::uid() const = 0 + + Returns the UID of the near field target. +*/ + +/*! + Returns the URL of the near field target. +*/ +QUrl QNearFieldTarget::url() const +{ + return QUrl(); +} + +/*! + \fn QNearFieldTarget::Type QNearFieldTarget::type() const = 0 + + Returns the type of tag type of this near field target. +*/ + +/*! + \fn QNearFieldTarget::AccessMethods QNearFieldTarget::accessMethods() const = 0 + + Returns the access methods support by this near field target. +*/ + +/*! + Returns true if the target is processing commands; otherwise returns false. +*/ +bool QNearFieldTarget::isProcessingCommand() const +{ + return false; +} + +/*! + Returns true if at least one NDEF message is stored on the near field target; otherwise returns + false. +*/ +bool QNearFieldTarget::hasNdefMessage() +{ + return false; +} + +/*! + Starts reading NDEF messages stored on the near field target. Returns a request id which can + be used to track the completion status of the request. An invalid request id will be returned + if the target does not support reading NDEF messages. + + An ndefMessageRead() signal will be emitted for each NDEF message. The requestCompleted() + signal will be emitted was all NDEF messages have been read. The error() signal is emitted if + an error occurs. + + \note Symbian^3 and Maemo 6 only support read one NDEF message. +*/ +QNearFieldTarget::RequestId QNearFieldTarget::readNdefMessages() +{ + return RequestId(); +} + +/*! + Writes the NDEF messages in \a messages to the target. Returns a request id which can be used + to track the completion status of the request. An invalid request id will be returned if the + target does not support reading NDEF messages. + + The ndefMessagesWritten() signal will be emitted when the write operation completes + successfully; otherwise the error() signal is emitted. + + \note Symbian^3 and Maemo 6 only support writing one NDEF message. Only the first NDEF message + in the list will be written, others are silently dropped. +*/ +QNearFieldTarget::RequestId QNearFieldTarget::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + Q_UNUSED(messages); + + return RequestId(); +} + +/*! + Sends \a command to the near field target. Returns a request id which can be used to track the + completion status of the request. An invalid request id will be returned if the target does not + support sending tag type specific commands. + + The requestCompleted() signal will be emitted on successful completion of the request; + otherwise the error() signal will be emitted. + + Once the request completes successfully the response can be retrieved from the + requestResponse() function. The response of this request will be a QByteArray. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTarget::sendCommand(const QByteArray &command) +{ + Q_UNUSED(command); + + emit error(UnsupportedError, RequestId()); + + return RequestId(); +} + +/*! + Sends multiple \a commands to the near field target. Returns a request id which can be used to + track the completion status of the request. An invalid request id will be returned if the + target does not support sending tag type specific commands. + + If all commands complete successfully the requestCompleted() signal will be emitted; otherwise + the error() signal will be emitted. If a command fails succeeding commands from this call will + not be processed. + + Once the request completes the response for successfully completed requests can be retrieved + from the requestResponse() function. The response of this request will be a QList<QByteArray>. + + \sa requestCompleted(), waitForRequestCompleted() +*/ +QNearFieldTarget::RequestId QNearFieldTarget::sendCommands(const QList<QByteArray> &commands) +{ + Q_UNUSED(commands); + + emit error(UnsupportedError, RequestId()); + + return RequestId(); +} + +/*! + Waits up to \a msecs milliseconds for the request \a id to complete. Returns true if the + request completes successfully and the requestCompeted() signal is emitted; otherwise returns + false. +*/ +bool QNearFieldTarget::waitForRequestCompleted(const RequestId &id, int msecs) +{ + Q_UNUSED(msecs); + + Q_D(QNearFieldTarget); + + return d->m_decodedResponses.contains(id); +} + +/*! + Returns the decoded response for request \a id. If the request is unknown or has not yet been + completed an invalid QVariant is returned. +*/ +QVariant QNearFieldTarget::requestResponse(const RequestId &id) +{ + Q_D(QNearFieldTarget); + + return d->m_decodedResponses.value(id); +} + +/*! + Sets the decoded response for request \a id to \a response. If \a emitRequestCompleted is true + the requestCompleted() signal will be emitted for \a id; otherwise no signal will be emitted. + + \sa requestResponse() +*/ +void QNearFieldTarget::setResponseForRequest(const QNearFieldTarget::RequestId &id, + const QVariant &response, bool emitRequestCompleted) +{ + Q_D(QNearFieldTarget); + + QMutableMapIterator<RequestId, QVariant> i(d->m_decodedResponses); + while (i.hasNext()) { + i.next(); + + // no more external references + if (i.key().refCount() == 1) + i.remove(); + } + + d->m_decodedResponses.insert(id, response); + + if (emitRequestCompleted) + emit requestCompleted(id); +} + +/*! + Handles the \a response received for the request \a id. Returns true if the response is + handled; otherwise returns false. + + Classes reimplementing this virtual function should call the base class implementation to + ensure that requests initiated by those classes are handled correctly. + + The default implementation stores the response such that it can be retrieved by + requestResponse(). +*/ +bool QNearFieldTarget::handleResponse(const QNearFieldTarget::RequestId &id, + const QByteArray &response) +{ + setResponseForRequest(id, response); + + return true; +} + +#include "moc_qnearfieldtarget.cpp" diff --git a/src/nfc/qnearfieldtarget.h b/src/nfc/qnearfieldtarget.h new file mode 100644 index 00000000..7e081660 --- /dev/null +++ b/src/nfc/qnearfieldtarget.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QNEARFIELDTARGET_H +#define QNEARFIELDTARGET_H + +#include "../qtconnectivityglobal.h" + +#include <QtCore/QObject> +#include <QtCore/QList> +#include <QtCore/QMetaType> +#include <QtCore/QSharedDataPointer> + +class QString; +class QUrl; + +QT_BEGIN_HEADER + +class QNdefMessage; +class QNearFieldTargetPrivate; + +class Q_CONNECTIVITY_EXPORT QNearFieldTarget : public QObject +{ + Q_OBJECT + + Q_DECLARE_PRIVATE(QNearFieldTarget) + +public: + enum Type { + AnyTarget, + ProprietaryTag, + NfcTagType1, + NfcTagType2, + NfcTagType3, + NfcTagType4, + MifareTag, + NfcForumDevice + }; + + enum AccessMethod { + NdefAccess, + TagTypeSpecificAccess, + LlcpAccess + }; + Q_DECLARE_FLAGS(AccessMethods, AccessMethod) + + enum Error { + NoError, + UnknownError, + UnsupportedError, + TargetOutOfRangeError, + NoResponseError, + ChecksumMismatchError, + InvalidParametersError, + NdefReadError, + NdefWriteError + }; + + class RequestIdPrivate; + class Q_CONNECTIVITY_EXPORT RequestId + { + public: + RequestId(); + RequestId(const RequestId &other); + RequestId(RequestIdPrivate *p); + ~RequestId(); + + bool isValid() const; + + int refCount() const; + + bool operator<(const RequestId &other) const; + bool operator==(const RequestId &other) const; + bool operator!=(const RequestId &other) const; + RequestId &operator=(const RequestId &other); + + QSharedDataPointer<RequestIdPrivate> d; + }; + + explicit QNearFieldTarget(QObject *parent = 0); + virtual ~QNearFieldTarget(); + + virtual QByteArray uid() const = 0; + virtual QUrl url() const; + + virtual Type type() const = 0; + virtual AccessMethods accessMethods() const = 0; + + bool isProcessingCommand() const; + + // NdefAccess + virtual bool hasNdefMessage(); + virtual RequestId readNdefMessages(); + virtual RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + + // TagTypeSpecificAccess + virtual RequestId sendCommand(const QByteArray &command); + virtual RequestId sendCommands(const QList<QByteArray> &commands); + + virtual bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + + QVariant requestResponse(const RequestId &id); + void setResponseForRequest(const QNearFieldTarget::RequestId &id, const QVariant &response, + bool emitRequestCompleted = true); + +protected: + Q_INVOKABLE virtual bool handleResponse(const QNearFieldTarget::RequestId &id, + const QByteArray &response); + +Q_SIGNALS: + void disconnected(); + + void ndefMessageRead(const QNdefMessage &message); + void ndefMessagesWritten(); + + void requestCompleted(const QNearFieldTarget::RequestId &id); + + void error(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id); + +private: + QNearFieldTargetPrivate *d_ptr; +}; + +Q_CONNECTIVITY_EXPORT quint16 qNfcChecksum(const char * data, uint len); + +Q_DECLARE_OPERATORS_FOR_FLAGS(QNearFieldTarget::AccessMethods) + +Q_DECLARE_METATYPE(QNearFieldTarget::RequestId) +Q_DECLARE_METATYPE(QNearFieldTarget::Error) + +QT_END_HEADER + +#endif // QNEARFIELDTARGET_H diff --git a/src/nfc/qnearfieldtarget_emulator.cpp b/src/nfc/qnearfieldtarget_emulator.cpp new file mode 100644 index 00000000..2a05a6e3 --- /dev/null +++ b/src/nfc/qnearfieldtarget_emulator.cpp @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldtarget_emulator_p.h" +#include "qnearfieldtarget_p.h" + +#include <QtCore/QDirIterator> +#include <QtCore/QSettings> +#include <QtCore/QMutex> +#include <QtCore/QCoreApplication> +#include <QtCore/QDateTime> + +#include <QtCore/QDebug> + +static QMutex tagMutex; +static QMap<TagBase *, bool> tagMap; +static TagActivator tagActivator; + + +TagType1::TagType1(TagBase *tag, QObject *parent) +: QNearFieldTagType1(parent), m_tag(tag) +{ +} + +TagType1::~TagType1() +{ +} + +QByteArray TagType1::uid() const +{ + QMutexLocker locker(&tagMutex); + + return m_tag->uid(); +} + +QNearFieldTarget::AccessMethods TagType1::accessMethods() const +{ + return NdefAccess | TagTypeSpecificAccess; +} + +QNearFieldTarget::RequestId TagType1::sendCommand(const QByteArray &command) +{ + QMutexLocker locker(&tagMutex); + + RequestId id(new RequestIdPrivate); + + // tag not in proximity + if (!tagMap.value(m_tag)) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, TargetOutOfRangeError), + Q_ARG(QNearFieldTarget::RequestId, id)); + return id; + } + + quint16 crc = qNfcChecksum(command.constData(), command.length()); + + QByteArray response = m_tag->processCommand(command + char(crc & 0xff) + char(crc >> 8)); + + if (response.isEmpty()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, NoResponseError), + Q_ARG(QNearFieldTarget::RequestId, id)); + return id; + } + + // check crc + if (qNfcChecksum(response.constData(), response.length()) != 0) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, ChecksumMismatchError), + Q_ARG(QNearFieldTarget::RequestId, id)); + return id; + } + + response.chop(2); + + QMetaObject::invokeMethod(this, "handleResponse", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::RequestId, id), Q_ARG(QByteArray, response)); + + return id; +} + +bool TagType1::waitForRequestCompleted(const RequestId &id, int msecs) +{ + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); + + return QNearFieldTagType1::waitForRequestCompleted(id, msecs); +} + + +TagType2::TagType2(TagBase *tag, QObject *parent) +: QNearFieldTagType2(parent), m_tag(tag) +{ +} + +TagType2::~TagType2() +{ +} + +QByteArray TagType2::uid() const +{ + QMutexLocker locker(&tagMutex); + + return m_tag->uid(); +} + +QNearFieldTarget::AccessMethods TagType2::accessMethods() const +{ + return NdefAccess | TagTypeSpecificAccess; +} + +QNearFieldTarget::RequestId TagType2::sendCommand(const QByteArray &command) +{ + QMutexLocker locker(&tagMutex); + + RequestId id(new RequestIdPrivate); + + // tag not in proximity + if (!tagMap.value(m_tag)) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, TargetOutOfRangeError), + Q_ARG(QNearFieldTarget::RequestId, id)); + return id; + } + + quint16 crc = qNfcChecksum(command.constData(), command.length()); + + QByteArray response = m_tag->processCommand(command + char(crc & 0xff) + char(crc >> 8)); + + if (response.isEmpty()) + return id; + + if (response.length() > 1) { + // check crc + if (qNfcChecksum(response.constData(), response.length()) != 0) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, ChecksumMismatchError), + Q_ARG(QNearFieldTarget::RequestId, id)); + return id; + } + + response.chop(2); + } + + QMetaObject::invokeMethod(this, "handleResponse", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::RequestId, id), Q_ARG(QByteArray, response)); + + return id; +} + +bool TagType2::waitForRequestCompleted(const RequestId &id, int msecs) +{ + QCoreApplication::sendPostedEvents(this, QEvent::MetaCall); + + return QNearFieldTagType2::waitForRequestCompleted(id, msecs); +} + + +TagActivator::TagActivator() +: timerId(-1) +{ + qRegisterMetaType<QNearFieldTarget::Error>("QNearFieldTarget::Error"); +} + +TagActivator::~TagActivator() +{ + QMutexLocker locker(&tagMutex); + qDeleteAll(tagMap.keys()); + tagMap.clear(); +} + +void TagActivator::initialize() +{ + QMutexLocker locker(&tagMutex); + + if (!tagMap.isEmpty()) + return; + + QDirIterator nfcTargets(QDir::currentPath(), QStringList(QLatin1String("*.nfc")), QDir::Files); + while (nfcTargets.hasNext()) { + const QString targetFilename = nfcTargets.next(); + + QSettings target(targetFilename, QSettings::IniFormat); + + target.beginGroup(QLatin1String("Target")); + + const QString tagType = target.value(QLatin1String("Type")).toString(); + + target.endGroup(); + + if (tagType == QLatin1String("TagType1")) { + qDebug() << "loading" << targetFilename << "as NfcTagType1"; + NfcTagType1 *tag = new NfcTagType1; + tag->load(&target); + + tagMap.insert(tag, false); + } else if (tagType == QLatin1String("TagType2")) { + qDebug() << "loading" << targetFilename << "as NfcTagType2"; + NfcTagType2 *tag = new NfcTagType2; + tag->load(&target); + + tagMap.insert(tag, false); + } else { + qWarning("Unknown tag type %s\n", qPrintable(tagType)); + } + } + + m_current = tagMap.end(); + + timerId = startTimer(1000); +} + +void TagActivator::reset() +{ + QMutexLocker locker(&tagMutex); + + killTimer(timerId); + timerId = -1; + + qDeleteAll(tagMap.keys()); + tagMap.clear(); +} + +TagActivator *TagActivator::instance() +{ + return &tagActivator; +} + +void TagActivator::timerEvent(QTimerEvent *e) +{ + Q_UNUSED(e); + + tagMutex.lock(); + + if (m_current != tagMap.end()) { + if (m_current.key()->lastAccessTime() + 1500 > QDateTime::currentMSecsSinceEpoch()) { + tagMutex.unlock(); + return; + } + + *m_current = false; + + tagMutex.unlock(); + emit tagDeactivated(m_current.key()); + tagMutex.lock(); + } + + ++m_current; + if (m_current == tagMap.end()) + m_current = tagMap.begin(); + + if (m_current != tagMap.end()) { + *m_current = true; + + tagMutex.unlock(); + + emit tagActivated(m_current.key()); + tagMutex.lock(); + } + + tagMutex.unlock(); +} + diff --git a/src/nfc/qnearfieldtarget_emulator_p.h b/src/nfc/qnearfieldtarget_emulator_p.h new file mode 100644 index 00000000..1867df89 --- /dev/null +++ b/src/nfc/qnearfieldtarget_emulator_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTARGET_EMULATOR_P_H +#define QNEARFIELDTARGET_EMULATOR_P_H + +#include "qnearfieldtagtype1.h" +#include "qnearfieldtagtype2.h" +#include "targetemulator_p.h" + +#include <QtCore/QMap> + +class TagType1 : public QNearFieldTagType1 +{ + Q_OBJECT + +public: + TagType1(TagBase *tag, QObject *parent); + ~TagType1(); + + QByteArray uid() const; + + AccessMethods accessMethods() const; + + RequestId sendCommand(const QByteArray &command); + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + +private: + TagBase *m_tag; +}; + +class TagType2 : public QNearFieldTagType2 +{ + Q_OBJECT + +public: + TagType2(TagBase *tag, QObject *parent); + ~TagType2(); + + QByteArray uid() const; + + AccessMethods accessMethods() const; + + RequestId sendCommand(const QByteArray &command); + bool waitForRequestCompleted(const RequestId &id, int msecs = 5000); + +private: + TagBase *m_tag; +}; + +class TagActivator : public QObject +{ + Q_OBJECT + +public: + TagActivator(); + ~TagActivator(); + + void initialize(); + void reset(); + + static TagActivator *instance(); + +protected: + void timerEvent(QTimerEvent *e); + +signals: + void tagActivated(TagBase *tag); + void tagDeactivated(TagBase *tag); + +private: + QMap<TagBase *, bool>::Iterator m_current; + int timerId; +}; + +#endif // QNEARFIELDTARGET_EMULATOR_P_H diff --git a/src/nfc/qnearfieldtarget_maemo6.cpp b/src/nfc/qnearfieldtarget_maemo6.cpp new file mode 100644 index 00000000..dddf8776d --- /dev/null +++ b/src/nfc/qnearfieldtarget_maemo6.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnearfieldtarget_maemo6_p.h" + +void PendingCallWatcher::addSendCommand(const QDBusPendingReply<QByteArray> &reply, + const QNearFieldTarget::RequestId &id) +{ + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(sendCommandFinished(QDBusPendingCallWatcher*))); + + m_pendingCommands.insert(watcher, id); +} + +void PendingCallWatcher::addReadNdefMessages(const QDBusPendingReply<QList<QByteArray> > &reply, + const QNearFieldTarget::RequestId &id) +{ + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(readNdefMessagesFinished(QDBusPendingCallWatcher*))); + + m_pendingNdefReads.insert(watcher, id); +} + +void PendingCallWatcher::addWriteNdefMessages(const QDBusPendingReply<> &reply, + const QNearFieldTarget::RequestId &id) +{ + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(writeNdefMessages(QDBusPendingCallWatcher*))); + + m_pendingNdefWrites.insert(watcher, id); +} + +void PendingCallWatcher::sendCommandFinished(QDBusPendingCallWatcher *watcher) +{ + QNearFieldTarget::RequestId id = m_pendingCommands.take(watcher); + + if (!id.isValid()) { + watcher->deleteLater(); + return; + } + + QDBusPendingReply<QByteArray> reply = *watcher; + if (reply.isError()) { + QMetaObject::invokeMethod(parent(), "error", + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnknownError), + Q_ARG(QNearFieldTarget::RequestId, id)); + } else { + const QByteArray data = reply.argumentAt<0>(); + QMetaObject::invokeMethod(parent(), "handleResponse", + Q_ARG(QNearFieldTarget::RequestId, id), + Q_ARG(QByteArray, data)); + } + + watcher->deleteLater(); +} + +void PendingCallWatcher::readNdefMessagesFinished(QDBusPendingCallWatcher *watcher) +{ + QNearFieldTarget::RequestId id = m_pendingNdefReads.take(watcher); + + if (!id.isValid()) { + watcher->deleteLater(); + return; + } + + QDBusPendingReply<QList<QByteArray> > reply = *watcher; + if (reply.isError()) { + QMetaObject::invokeMethod(parent(), "error", + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::NdefReadError), + Q_ARG(QNearFieldTarget::RequestId, id)); + } else { + const QList<QByteArray> data = reply.argumentAt<0>(); + foreach (const QByteArray &m, data) { + qDebug() << Q_FUNC_INFO << m.toHex(); + const QNdefMessage message = QNdefMessage::fromByteArray(m); + + qDebug() << "record count:" << message.count(); + foreach (const QNdefRecord &record, message) + qDebug() << record.typeNameFormat() << record.type() << record.payload().toHex(); + + QMetaObject::invokeMethod(parent(), "ndefMessageRead", Q_ARG(QNdefMessage, message)); + } + + QMetaObject::invokeMethod(parent(), "requestCompleted", + Q_ARG(QNearFieldTarget::RequestId, id)); + } + + watcher->deleteLater(); +} + +void PendingCallWatcher::writeNdefMessages(QDBusPendingCallWatcher *watcher) +{ + QNearFieldTarget::RequestId id = m_pendingNdefWrites.take(watcher); + + if (!id.isValid()) { + watcher->deleteLater(); + return; + } + + QDBusPendingReply<> reply = *watcher; + if (reply.isError()) { + QMetaObject::invokeMethod(parent(), "error", + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::NdefWriteError), + Q_ARG(QNearFieldTarget::RequestId, id)); + } else { + QMetaObject::invokeMethod(parent(), "ndefMessagesWritten"); + QMetaObject::invokeMethod(parent(), "requestCompleted", + Q_ARG(QNearFieldTarget::RequestId, id)); + } + + watcher->deleteLater(); +} + +int TagType1::memorySize() const +{ + return m_tag->size(); +} + +int TagType2::memorySize() const +{ + return m_tag->size(); +} + +int TagType3::memorySize() const +{ + return m_tag->size(); +} + +int TagType4::memorySize() const +{ + return m_tag->size(); +} + +#include <moc_qnearfieldtarget_maemo6_p.cpp> + diff --git a/src/nfc/qnearfieldtarget_maemo6_p.h b/src/nfc/qnearfieldtarget_maemo6_p.h new file mode 100644 index 00000000..5002a08e --- /dev/null +++ b/src/nfc/qnearfieldtarget_maemo6_p.h @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTARGET_MAEMO6_P_H +#define QNEARFIELDTARGET_MAEMO6_P_H + +#include <qconnectivityglobal.h> + +#include "qnearfieldmanager_maemo6_p.h" + +#include <qnearfieldtarget.h> +#include <qnearfieldtarget_p.h> +#include <qnearfieldtagtype1.h> +#include <qnearfieldtagtype2.h> +#include <qnearfieldtagtype3.h> +#include <qnearfieldtagtype4.h> +#include <qndefmessage.h> + +#include "maemo6/adapter_interface_p.h" +#include "maemo6/target_interface_p.h" +#include "maemo6/tag_interface_p.h" +#include "maemo6/device_interface_p.h" + +#include <QtDBus/QDBusPendingReply> + +using namespace com::nokia::nfc; + +class PendingCallWatcher : public QObject +{ + Q_OBJECT + +public: + PendingCallWatcher(QObject *parent) : QObject(parent) { } + + void addSendCommand(const QDBusPendingReply<QByteArray> &reply, + const QNearFieldTarget::RequestId &id); + void addReadNdefMessages(const QDBusPendingReply<QList<QByteArray> > &reply, + const QNearFieldTarget::RequestId &id); + void addWriteNdefMessages(const QDBusPendingReply<> &reply, + const QNearFieldTarget::RequestId &id); + +private slots: + void sendCommandFinished(QDBusPendingCallWatcher *watcher); + void readNdefMessagesFinished(QDBusPendingCallWatcher *watcher); + void writeNdefMessages(QDBusPendingCallWatcher *watcher); + +private: + QMap<QDBusPendingCallWatcher *, QNearFieldTarget::RequestId> m_pendingCommands; + QMap<QDBusPendingCallWatcher *, QNearFieldTarget::RequestId> m_pendingNdefReads; + QMap<QDBusPendingCallWatcher *, QNearFieldTarget::RequestId> m_pendingNdefWrites; +}; + +template <typename T> +class NearFieldTarget : public T +{ +public: + NearFieldTarget(QNearFieldManagerPrivateImpl *manager, Target *target, Tag *tag) + : T(manager), m_manager(manager), m_target(target), m_tag(tag), m_device(0), + m_callWatcher(new PendingCallWatcher(this)) + { + } + + NearFieldTarget(QNearFieldManagerPrivateImpl *manager, Target *target, Device *device) + : T(manager), m_manager(manager), m_target(target), m_tag(0), m_device(device), + m_callWatcher(new PendingCallWatcher(this)) + { + } + + ~NearFieldTarget() + { + delete m_device; + delete m_tag; + delete m_target; + } + + QByteArray uid() const + { + QStringList fields; + + if (m_tag) + fields = m_tag->uID().split(QLatin1Char(':')); + else if (m_device) + fields = m_device->uID().split(QLatin1Char(':')); + + QByteArray id; + foreach (const QString &f, fields) + id.append(char(f.toUInt(0, 16))); + + return id; + } + + QNearFieldTarget::Type type() const + { + if (m_device) + return QNearFieldTarget::NfcForumDevice; + + if (m_tag) { + const QString tagType = m_tag->technology(); + if (tagType == QLatin1String("jewel")) + return QNearFieldTarget::NfcTagType1; + else if (tagType == QLatin1String("mifare-ul")) + return QNearFieldTarget::NfcTagType2; + else if (tagType == QLatin1String("felica")) + return QNearFieldTarget::NfcTagType3; + else if (tagType == QLatin1String("iso-4a")) + return QNearFieldTarget::NfcTagType4; + else if (tagType == QLatin1String("mifare-1k")) + return QNearFieldTarget::MifareTag; + else + return QNearFieldTarget::ProprietaryTag; + } + + return QNearFieldTarget::ProprietaryTag; + } + + QNearFieldTarget::AccessMethods accessMethods() const + { + QNearFieldTarget::AccessMethods result = QNearFieldTarget::NdefAccess; +#ifdef MAEMO6_TAG_TYPE_SEPECIFIC_ACCESS_SUPPORTED + if (m_tag) + result |= QNearFieldTarget::TagTypeSpecificAccess; +#endif + if (!m_tag) + result |= QNearFieldTarget::LlcpAccess; + + return result; + } + + bool hasNdefMessage() + { + return true; + } + + QNearFieldTarget::RequestId readNdefMessages() + { + if (!m_tag) + return QNearFieldTarget::RequestId(); + + QNearFieldTarget::RequestId id(new QNearFieldTarget::RequestIdPrivate); + + QDBusPendingReply<QList<QByteArray> > reply = m_tag->ReadNDEFData(); + m_callWatcher->addReadNdefMessages(reply, id); + + return id; + } + + QNearFieldTarget::RequestId writeNdefMessages(const QList<QNdefMessage> &messages) + { + if (!m_tag) + return QNearFieldTarget::RequestId(); + + QNearFieldTarget::RequestId id(new QNearFieldTarget::RequestIdPrivate); + QList<QByteArray> rawMessages; + + foreach (const QNdefMessage &message, messages) + rawMessages.append(message.toByteArray()); + + QDBusPendingReply<> reply = m_tag->WriteNDEFData(rawMessages); + m_callWatcher->addWriteNdefMessages(reply, id); + + return id; + } + + QNearFieldTarget::RequestId sendCommand(const QByteArray &command) + { +#if 0 + quint16 crc = qNfcChecksum(command.constData(), command.length()); + + QNearFieldTarget::RequestId id(new QNearFieldTarget::RequestIdPrivate); + + QDBusPendingReply<QByteArray> reply = + m_tag->RawRequest(command + char(crc & 0xff) + char(crc >> 8)); + + m_callWatcher->addSendCommand(reply, id); + + return id; +#else + Q_UNUSED(command); + return QNearFieldTarget::RequestId(); +#endif + } + + QNearFieldTarget::RequestId sendCommands(const QList<QByteArray> &commands) + { +#if 0 + for (int i = 0; i < commandCount; ++i) { + reply[i] = m_tag->RawRequest(commands.at(i)); + } + + QList<QByteArray> results; + for (int i = 0; i < commandCount; ++i) { + reply[i].waitForFinished(); + results.append(reply[i].isError() ? QByteArray() : reply->value()); + } + + return results; +#else + Q_UNUSED(commands); + return QNearFieldTarget::RequestId(); +#endif + } + +protected: + QNearFieldManagerPrivateImpl *m_manager; + Target *m_target; + Tag *m_tag; + Device *m_device; + PendingCallWatcher *m_callWatcher; +}; + +class TagType1 : public NearFieldTarget<QNearFieldTagType1> +{ +public: + TagType1(QNearFieldManagerPrivateImpl *manager, Target *target, Tag *tag) + : NearFieldTarget<QNearFieldTagType1>(manager, target, tag) + { + } + + ~TagType1() + { + } + + int memorySize() const; +}; + +class TagType2 : public NearFieldTarget<QNearFieldTagType2> +{ +public: + TagType2(QNearFieldManagerPrivateImpl *manager, Target *target, Tag *tag) + : NearFieldTarget<QNearFieldTagType2>(manager, target, tag) + { + } + + ~TagType2() + { + } + + int memorySize() const; +}; + +class TagType3 : public NearFieldTarget<QNearFieldTagType3> +{ +public: + TagType3(QNearFieldManagerPrivateImpl *manager, Target *target, Tag *tag) + : NearFieldTarget<QNearFieldTagType3>(manager, target, tag) + { + } + + ~TagType3() + { + } + + int memorySize() const; +}; + +class TagType4 : public NearFieldTarget<QNearFieldTagType4> +{ +public: + TagType4(QNearFieldManagerPrivateImpl *manager, Target *target, Tag *tag) + : NearFieldTarget<QNearFieldTagType4>(manager, target, tag) + { + } + + ~TagType4() + { + } + + int memorySize() const; +}; + +#endif // QNEARFIELDTARGET_MAEMO6_P_H diff --git a/src/nfc/qnearfieldtarget_p.h b/src/nfc/qnearfieldtarget_p.h new file mode 100644 index 00000000..d3d98c9b --- /dev/null +++ b/src/nfc/qnearfieldtarget_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTARGET_P_H +#define QNEARFIELDTARGET_P_H + +#include "../qtconnectivityglobal.h" + +#include "qnearfieldtarget.h" + +#include <QtCore/QMap> +#include <QtCore/QSharedData> + +class QNearFieldTarget::RequestIdPrivate : public QSharedData +{ +}; + +class QNearFieldTargetPrivate +{ +public: + QMap<QNearFieldTarget::RequestId, QVariant> m_decodedResponses; +}; + +#endif // QNEARFIELDTARGET_P_H diff --git a/src/nfc/qtlv.cpp b/src/nfc/qtlv.cpp new file mode 100644 index 00000000..83c5d585 --- /dev/null +++ b/src/nfc/qtlv.cpp @@ -0,0 +1,528 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtlv_p.h" + +#include "qnearfieldtagtype1.h" + +#include <QtCore/QVariant> + +#include <QtCore/QDebug> + +QPair<int, int> qParseReservedMemoryControlTlv(const QByteArray &tlvData) +{ + quint8 position = tlvData.at(0); + int pageAddr = position >> 4; + int byteOffset = position & 0x0f; + + int size = quint8(tlvData.at(1)); + if (size == 0) + size = 256; + + quint8 pageControl = tlvData.at(2); + int bytesPerPage = pageControl & 0x0f; + + if (!bytesPerPage) + return qMakePair(0, 0); + + int byteAddress = pageAddr * (1 << bytesPerPage) + byteOffset; + return qMakePair(byteAddress, size); +} + +QPair<int, int> qParseLockControlTlv(const QByteArray &tlvData) +{ + quint8 position = tlvData.at(0); + int pageAddr = position >> 4; + int byteOffset = position & 0x0f; + + int size = quint8(tlvData.at(1)); + if (size == 0) + size = 256; + size = size / 8; + + quint8 pageControl = tlvData.at(2); + int bytesPerPage = pageControl & 0x0f; + + if (!bytesPerPage) + return qMakePair(0, 0); + + int byteAddress = pageAddr * (1 << bytesPerPage) + byteOffset; + return qMakePair(byteAddress, size); +} + +QTlvReader::QTlvReader(QNearFieldTarget *target) +: m_target(target), m_index(-1) +{ + if (qobject_cast<QNearFieldTagType1 *>(m_target)) { + addReservedMemory(0, 12); // skip uid, cc + addReservedMemory(104, 16); // skip reserved block D, lock block E + + addReservedMemory(120, 8); // skip reserved block F + } +} + +QTlvReader::QTlvReader(const QByteArray &data) +: m_target(0), m_rawData(data), m_index(-1) +{ +} + +void QTlvReader::addReservedMemory(int offset, int length) +{ + m_reservedMemory.insert(offset, length); +} + +/*! + Returns the number of bytes of reserved memory found so far. The actual number of reserved + bytes will not be known until atEnd() returns true. +*/ +int QTlvReader::reservedMemorySize() const +{ + int total = 0; + + QMap<int, int>::ConstIterator i; + for (i = m_reservedMemory.constBegin(); i != m_reservedMemory.constEnd(); ++i) + total += i.value(); + + return total; +} + +/*! + Returns the request id that the TLV reader is currently waiting on. +*/ +QNearFieldTarget::RequestId QTlvReader::requestId() const +{ + return m_requestId; +} + +bool QTlvReader::atEnd() const +{ + if (m_index == -1) + return false; + + if (m_requestId.isValid()) + return false; + + return (m_index == m_tlvData.length()) || (tag() == 0xfe); +} + +/*! + Moves to the next TLV. Returns true on success; otherwise returns false. +*/ +bool QTlvReader::readNext() +{ + if (atEnd()) + return false; + + // Move to next TLV + if (m_index == -1) { + m_index = 0; + } else if (m_requestId.isValid()) { + // do nothing + } else if (tag() == 0x00 || tag() == 0xfe) { + ++m_index; + } else { + int tlvLength = length(); + m_index += (tlvLength < 0xff) ? tlvLength + 2 : tlvLength + 4; + } + + // Ensure that tag byte is available + if (!readMoreData(m_index)) + return false; + + // Ensure that length byte(s) are available + if (length() == -1) + return false; + + // Ensure that data bytes are available + int tlvLength = length(); + + int dataOffset = (tlvLength < 0xff) ? m_index + 2 : m_index + 4; + + if (!readMoreData(dataOffset + tlvLength - 1)) + return false; + + switch (tag()) { + case 0x01: { // Lock Control TLV + QPair<int, int> locked = qParseLockControlTlv(data()); + addReservedMemory(locked.first, locked.second); + break; + } + case 0x02: { // Reserved Memory Control TLV + QPair<int, int> reserved = qParseReservedMemoryControlTlv(data()); + addReservedMemory(reserved.first, reserved.second); + break; + } + } + + return true; +} + +quint8 QTlvReader::tag() const +{ + return m_tlvData.at(m_index); +} + +int QTlvReader::length() +{ + if (tag() == 0x00 || tag() == 0xfe) + return 0; + + if (!readMoreData(m_index + 1)) + return -1; + + quint8 shortLength = m_tlvData.at(m_index + 1); + if (shortLength != 0xff) + return shortLength; + + if (!readMoreData(m_index + 3)) + return -1; + + quint16 longLength = (quint8(m_tlvData.at(m_index + 2)) << 8) | + quint8(m_tlvData.at(m_index + 3)); + + if (longLength < 0xff || longLength == 0xffff) { + qWarning("Invalid 3 byte length"); + return 0; + } + + return longLength; +} + +QByteArray QTlvReader::data() +{ + int tlvLength = length(); + + int dataOffset = (tlvLength < 0xff) ? m_index + 2 : m_index + 4; + + if (!readMoreData(dataOffset + tlvLength - 1)) + return QByteArray(); + + return m_tlvData.mid(dataOffset, tlvLength); +} + +bool QTlvReader::readMoreData(int sparseOffset) +{ + while (sparseOffset >= m_tlvData.length()) { + int absOffset = absoluteOffset(m_tlvData.length()); + + QByteArray data; + + if (!m_rawData.isEmpty()) { + data = m_rawData.mid(absOffset, dataLength(absOffset)); + } else if (QNearFieldTagType1 *tag = qobject_cast<QNearFieldTagType1 *>(m_target)) { + quint8 segment = absOffset / 128; + + if (m_requestId.isValid()) { + QVariant v = m_target->requestResponse(m_requestId); + if (!v.isValid()) + return false; + + m_requestId = QNearFieldTarget::RequestId(); + + data = v.toByteArray(); + + if (absOffset < 120) + data = data.mid(2); + + int length = dataLength(absOffset); + + data = data.mid(absOffset - (segment * 128), length); + } else { + m_requestId = (absOffset < 120) ? tag->readAll() : tag->readSegment(segment); + + return false; + } + } + + if (data.isEmpty() && sparseOffset >= m_tlvData.length()) + return false; + + m_tlvData.append(data); + } + + return true; +} + +int QTlvReader::absoluteOffset(int sparseOffset) const +{ + int absoluteOffset = sparseOffset; + foreach (int offset, m_reservedMemory.keys()) { + if (offset <= absoluteOffset) + absoluteOffset += m_reservedMemory.value(offset); + } + + return absoluteOffset; +} + +/*! + Returns the length of the contiguous non-reserved data block starting from absolute offset + \a startOffset. -1 is return as the length of the last contiguous data block. +*/ +int QTlvReader::dataLength(int startOffset) const +{ + foreach (int offset, m_reservedMemory.keys()) { + if (offset <= startOffset) + continue; + + return offset - startOffset; + } + + return -1; +} + + +QTlvWriter::QTlvWriter(QNearFieldTarget *target) +: m_target(target), m_rawData(0), m_index(0), m_tagMemorySize(-1) +{ + if (qobject_cast<QNearFieldTagType1 *>(m_target)) { + addReservedMemory(0, 12); // skip uid, cc + addReservedMemory(104, 16); // skip reserved block D, lock block E + + addReservedMemory(120, 8); // skip reserved block F + } +} + +QTlvWriter::QTlvWriter(QByteArray *data) +: m_target(0), m_rawData(data), m_index(0), m_tagMemorySize(-1) +{ +} + +QTlvWriter::~QTlvWriter() +{ + if (m_rawData) + process(true); +} + +void QTlvWriter::addReservedMemory(int offset, int length) +{ + m_reservedMemory.insert(offset, length); +} + +void QTlvWriter::writeTlv(quint8 tagType, const QByteArray &data) +{ + m_buffer.append(tagType); + + if (tagType != 0x00 && tagType != 0xfe) { + int length = data.length(); + if (length < 0xff) { + m_buffer.append(quint8(length)); + } else { + m_buffer.append(0xff); + m_buffer.append(quint16(length) >> 8); + m_buffer.append(quint16(length) & 0x00ff); + } + + m_buffer.append(data); + } + + process(); + + switch (tagType) { + case 0x01: { // Lock Control TLV + QPair<int, int> locked = qParseLockControlTlv(data); + addReservedMemory(locked.first, locked.second); + break; + } + case 0x02: { // Reserved Memory Control TLV + QPair<int, int> reserved = qParseReservedMemoryControlTlv(data); + addReservedMemory(reserved.first, reserved.second); + break; + } + } +} + +/*! + Processes more of the TLV writer process. Returns true if the TLVs have been successfully + written to the target or buffer; otherwise returns false. + + A false return value indicates that an NFC request is pending (if requestId() returns a valid + request identifier) or the write process has failed (requestId() returns an invalid request + identifier). +*/ +bool QTlvWriter::process(bool all) +{ + if (m_requestId.isValid()) { + QVariant v = m_target->requestResponse(m_requestId); + if (!v.isValid()) + return false; + } + + if (m_tagMemorySize == -1) { + if (m_rawData) + m_tagMemorySize = m_rawData->length(); + else if (QNearFieldTagType1 *tag = qobject_cast<QNearFieldTagType1 *>(m_target)) { + if (m_requestId.isValid()) { + m_tagMemorySize = 8 * (tag->requestResponse(m_requestId).toUInt() + 1); + m_requestId = QNearFieldTarget::RequestId(); + } else { + m_requestId = tag->readByte(10); + return false; + } + } + } + + while (!m_buffer.isEmpty()) { + int spaceRemaining = moveToNextAvailable(); + if (spaceRemaining < 1) + return false; + + int length = qMin(spaceRemaining, m_buffer.length()); + + if (m_rawData) { + m_rawData->replace(m_index, length, m_buffer); + m_index += length; + m_buffer = m_buffer.mid(length); + } else if (QNearFieldTagType1 *tag = qobject_cast<QNearFieldTagType1 *>(m_target)) { + int bufferIndex = 0; + + // static memory - can only use writeByte() + while (m_index < 120 && bufferIndex < length) { + if (m_requestId.isValid()) { + if (!m_target->requestResponse(m_requestId).toBool()) + return false; + + m_requestId = QNearFieldTarget::RequestId(); + + ++m_index; + ++bufferIndex; + } else { + m_requestId = tag->writeByte(m_index, m_buffer.at(bufferIndex)); + m_buffer = m_buffer.mid(bufferIndex); + return false; + } + } + + + // dynamic memory - writeBlock() full + while (m_index >= 120 && (m_index % 8 == 0) && bufferIndex + 8 < length) { + if (m_requestId.isValid()) { + if (!m_target->requestResponse(m_requestId).toBool()) + return false; + + m_requestId = QNearFieldTarget::RequestId(); + + m_index += 8; + bufferIndex += 8; + } else { + m_requestId = tag->writeBlock(m_index / 8, m_buffer.mid(bufferIndex, 8)); + m_buffer = m_buffer.mid(bufferIndex); + return false; + } + } + + // partial block + int currentBlock = m_index / 8; + int nextBlock = currentBlock + 1; + int currentBlockStart = currentBlock * 8; + int nextBlockStart = nextBlock * 8; + + int fillLength = qMin(nextBlockStart - m_index, spaceRemaining - bufferIndex); + + if (fillLength && (all || m_buffer.length() - bufferIndex >= fillLength) && + (m_buffer.length() != bufferIndex)) { + // sufficient data available + if (m_requestId.isValid()) { + const QVariant v = tag->requestResponse(m_requestId); + if (v.type() == QVariant::ByteArray) { + // read in block + QByteArray block = v.toByteArray(); + + int fill = qMin(fillLength, m_buffer.length() - bufferIndex); + + for (int i = m_index - currentBlockStart; i < fill; ++i) + block[i] = m_buffer.at(bufferIndex++); + + // now write block + m_requestId = tag->writeBlock(currentBlock, block); + return false; + } else if (v.type() == QVariant::Bool) { + m_requestId = QNearFieldTarget::RequestId(); + int fill = qMin(fillLength, m_buffer.length() - bufferIndex); + bufferIndex = fill - (m_index - currentBlockStart); + + // write complete + if (!v.toBool()) + return false; + } + } else { + // read in block + m_requestId = tag->readBlock(currentBlock); + m_buffer = m_buffer.mid(bufferIndex); + return false; + } + } + + m_buffer = m_buffer.mid(bufferIndex); + } + } + + return true; +} + +QNearFieldTarget::RequestId QTlvWriter::requestId() const +{ + return m_requestId; +} + +int QTlvWriter::moveToNextAvailable() +{ + int length = -1; + + // move index to next available byte + QMap<int, int>::ConstIterator i; + for (i = m_reservedMemory.constBegin(); i != m_reservedMemory.constEnd(); ++i) { + if (m_index < i.key()) { + length = i.key() - m_index; + break; + } else if (m_index == i.key()) { + m_index += i.value(); + } else if (m_index > i.key() && m_index < (i.key() + i.value())) { + m_index = i.key() + i.value(); + } + } + + if (length == -1) + return m_tagMemorySize - m_index; + + Q_ASSERT(length != -1); + + return length; +} diff --git a/src/nfc/qtlv_p.h b/src/nfc/qtlv_p.h new file mode 100644 index 00000000..a47d1a93 --- /dev/null +++ b/src/nfc/qtlv_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTLV_P_H +#define QTLV_P_H + +#include "../qtconnectivityglobal.h" + +#include "qnearfieldtarget.h" + +#include <QtCore/QByteArray> +#include <QtCore/QMap> +#include <QtCore/QPair> + +QT_BEGIN_HEADER + +class QNearFieldTarget; +class QM_AUTOTEST_EXPORT QTlvReader +{ +public: + explicit QTlvReader(QNearFieldTarget *target); + explicit QTlvReader(const QByteArray &data); + + void addReservedMemory(int offset, int length); + int reservedMemorySize() const; + + QNearFieldTarget::RequestId requestId() const; + + bool atEnd() const; + + bool readNext(); + + quint8 tag() const; + int length(); + QByteArray data(); + +private: + bool readMoreData(int sparseOffset); + int absoluteOffset(int sparseOffset) const; + int dataLength(int startOffset) const; + + QNearFieldTarget *m_target; + QByteArray m_rawData; + QNearFieldTarget::RequestId m_requestId; + + QByteArray m_tlvData; + int m_index; + QMap<int, int> m_reservedMemory; +}; + +class QTlvWriter +{ +public: + explicit QTlvWriter(QNearFieldTarget *target); + explicit QTlvWriter(QByteArray *data); + ~QTlvWriter(); + + void addReservedMemory(int offset, int length); + + void writeTlv(quint8 tag, const QByteArray &data = QByteArray()); + + bool process(bool all = false); + + QNearFieldTarget::RequestId requestId() const; + +private: + int moveToNextAvailable(); + + QNearFieldTarget *m_target; + QByteArray *m_rawData; + + int m_index; + int m_tagMemorySize; + QMap<int, int> m_reservedMemory; + + QByteArray m_buffer; + + QNearFieldTarget::RequestId m_requestId; +}; + +QPair<int, int> qParseReservedMemoryControlTlv(const QByteArray &tlvData); +QPair<int, int> qParseLockControlTlv(const QByteArray &tlvData); + +QT_END_HEADER + +#endif // QTLV_P_H diff --git a/src/nfc/qtnfcversion.h b/src/nfc/qtnfcversion.h new file mode 100644 index 00000000..e182a3f9 --- /dev/null +++ b/src/nfc/qtnfcversion.h @@ -0,0 +1,9 @@ +/* This file was generated by syncqt with the info from sync.profile. */ +#ifndef QT_QTNFC_VERSION_H +#define QT_QTNFC_VERSION_H + +#define QTNFC_VERSION_STR "5.0.0" + +#define QTNFC_VERSION 0x050000 + +#endif // QT_QTNFC_VERSION_H diff --git a/src/nfc/symbian/debug.h b/src/nfc/symbian/debug.h new file mode 100644 index 00000000..06a4de9b --- /dev/null +++ b/src/nfc/symbian/debug.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEBUG_H_ +#define DEBUG_H_ +#include <QDebug> + +//#define SYMBIAN_NFC_DEBUG + +#ifdef SYMBIAN_NFC_DEBUG +# define BEGIN qDebug()<<__PRETTY_FUNCTION__<<" Line: "<<__LINE__ <<" Begin"; +# define END qDebug()<<__PRETTY_FUNCTION__<<" Line: "<<__LINE__ <<" End"; +# define BEGIN_END qDebug()<<__PRETTY_FUNCTION__<<" Line: "<<__LINE__ <<" BEGIN_End"; +# define LOG(a) qDebug()<<__PRETTY_FUNCTION__<<" Line: "<<__LINE__ <<a; +#else +# define BEGIN +# define END +# define BEGIN_END +# define LOG(a) +#endif + +#endif /* DEBUG_H_ */ diff --git a/src/nfc/symbian/llcpserver_symbian.cpp b/src/nfc/symbian/llcpserver_symbian.cpp new file mode 100644 index 00000000..26f97874 --- /dev/null +++ b/src/nfc/symbian/llcpserver_symbian.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "llcpserver_symbian.h" +#include "llcpsockettype2_symbian.h" +#include "../qllcpserver_symbian_p.h" +#include "nearfieldutility_symbian.h" + +#include "debug.h" + +/* + CLlcpServer::NewL() +*/ +CLlcpServer* CLlcpServer::NewL(QLlcpServerPrivate& aCallback) + { + BEGIN + CLlcpServer* self = new (ELeave) CLlcpServer(aCallback); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + END + return self; + } + +/* + CLlcpServer::CLlcpServer() +*/ +CLlcpServer::CLlcpServer(QLlcpServerPrivate& aCallback) + :iLlcp( NULL ), + iSocketListening(EFalse), + iCallback(aCallback) + { + } + +/* + CLlcpServer::ContructL() +*/ +void CLlcpServer::ConstructL() + { + BEGIN + User::LeaveIfError(iNfcServer.Open()); + iLlcp = CLlcpProvider::NewL( iNfcServer ); + END + } + +/* + Destroys the LLCP socket. +*/ +CLlcpServer::~CLlcpServer() + { + BEGIN + StopListening(); + iLlcpSocketArray.ResetAndDestroy();//this should destroy before iLlcp + iLlcpSocketArray.Close(); + iServiceName.Close(); + + delete iLlcp; + iNfcServer.Close(); + END + } + +/* + Returns the next pending connection as a connected CLlcpSocketType2 + object. + + The socket is created as a child of the server, which means that + it is automatically deleted when the CLlcpServer object is + destroyed. It is still a good idea to delete the object + explicitly when you are done with it, to avoid wasting memory. +*/ +CLlcpSocketType2* CLlcpServer::nextPendingConnection() + { + // take first element + BEGIN + CLlcpSocketType2 *llcpSocket = NULL; + if (iLlcpSocketArray.Count() > 0) + { + llcpSocket = iLlcpSocketArray[0]; + iLlcpSocketArray.Remove(0); + } + END + return llcpSocket; + } + +TBool CLlcpServer::hasPendingConnections() const + { + BEGIN + END + return iLlcpSocketArray.Count() > 0 ? ETrue: EFalse; + } + +const TDesC8& CLlcpServer::serviceUri() const + { + BEGIN + END + return iServiceName; + } + +/* + Listen to the LLCP Socket by the URI \a serviceUri . +*/ +TBool CLlcpServer::Listen( const TDesC8& aServiceName) + { + BEGIN + TInt error = KErrNone; + + iServiceName.Zero(); + if (iServiceName.Create(aServiceName.Size()) < 0) + { + END + return EFalse; + } + iServiceName.Append(aServiceName); + + TRAP(error,iLlcp->StartListeningConnOrientedRequestL( *this, iServiceName )); + + error == KErrNone ? iSocketListening = ETrue : iSocketListening = EFalse; + END + return iSocketListening; + } + +void CLlcpServer::StopListening( ) + { + BEGIN + if (iSocketListening) + { + iLlcp->StopListeningConnOrientedRequest( iServiceName ); + iSocketListening = EFalse; + iLlcpSocketArray.ResetAndDestroy(); + } + END + } + + +TBool CLlcpServer::isListening() const + { + BEGIN + END + return iSocketListening; + } + +/* + Call back from MLlcpConnOrientedListener +*/ +void CLlcpServer::RemoteConnectRequest( MLlcpConnOrientedTransporter* aConnection ) + { + BEGIN + if (aConnection == NULL) + { + END + return; + } + + TInt error = KErrNone; + + // create remote connection for the iLlcpsocket + aConnection->AcceptConnectRequest(); + + CLlcpSocketType2 *llcpSocket = NULL; + TRAP(error,llcpSocket = CLlcpSocketType2::NewL(aConnection)); + // Creating wrapper for connection. + if (KErrNone == error) + { + iLlcpSocketArray.Append(llcpSocket); + //The newConnection() signal is then emitted each time a client connects to the server. + TInt error = KErrNone; + QT_TRYCATCH_ERROR(error, iCallback.invokeNewConnection()); + Q_UNUSED(error);//just skip the error + } + END + } +//EOF diff --git a/src/nfc/symbian/llcpserver_symbian.h b/src/nfc/symbian/llcpserver_symbian.h new file mode 100644 index 00000000..10e0771f --- /dev/null +++ b/src/nfc/symbian/llcpserver_symbian.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LLCPSERVER_SYMBIAN_H_ +#define LLCPSERVER_SYMBIAN_H_ + +#include <e32base.h> +#include <nfcserver.h> // RNfcServer +#include <llcpprovider.h> // CLlcpProvider +#include <llcpconnorientedlistener.h> // MLlcpConnOrientedListener +#include <qconnectivityglobal.h> +#include "../qllcpserver_symbian_p.h" + + +class CLlcpSocketType2; + +class CLlcpServer : public CBase, + public MLlcpConnOrientedListener + { +public: + /* + * Creates a new CLlcpServer object. + */ + static CLlcpServer* NewL(QLlcpServerPrivate&); + + /* + * Destructor + */ + ~CLlcpServer(); + +public: + TBool Listen( const TDesC8& aServiceName); + void StopListening(); + TBool isListening() const; + CLlcpSocketType2 *nextPendingConnection(); + TBool hasPendingConnections() const; + const TDesC8& serviceUri() const; + +private: // From MLlcpConnOrientedListener + void RemoteConnectRequest( MLlcpConnOrientedTransporter* aConnection ); + +private: + // Constructor + CLlcpServer(QLlcpServerPrivate&); + + // Second phase constructor + void ConstructL(); + +private: + + RPointerArray<CLlcpSocketType2> iLlcpSocketArray; + + /* + * Handle to NFC-server. + * Own. + */ + RNfcServer iNfcServer; + + /* + * Pointer to CLlcpProvider object. + * Own. + */ + CLlcpProvider* iLlcp; + + TBool iSocketListening; + + RBuf8 iServiceName; + + QLlcpServerPrivate& iCallback; + }; + +#endif /* LLCPSERVER_SYMBIAN_H_ */ diff --git a/src/nfc/symbian/llcpsockettype1_symbian.cpp b/src/nfc/symbian/llcpsockettype1_symbian.cpp new file mode 100644 index 00000000..3baf39fd --- /dev/null +++ b/src/nfc/symbian/llcpsockettype1_symbian.cpp @@ -0,0 +1,857 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <llcpprovider.h> // CLlcpProvider +#include <llcpconnlesstransporter.h> // MLlcpConnLessTransporter + +#include "nearfieldutility_symbian.h" +#include "llcpsockettype1_symbian.h" +#include "debug.h" + + +/* + CLlcpSocketType1::NewL() +*/ +CLlcpSocketType1* CLlcpSocketType1::NewL(QLlcpSocketPrivate& aCallback) + { + CLlcpSocketType1* self = CLlcpSocketType1::NewLC(aCallback); + CleanupStack::Pop(self); + return self; + } + +/* + CLlcpSocketType1::NewLC() +*/ +CLlcpSocketType1* CLlcpSocketType1::NewLC(QLlcpSocketPrivate& aCallback) + { + CLlcpSocketType1* self = new (ELeave) CLlcpSocketType1(aCallback); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +/* + CLlcpSocketType1::CLlcpSocketType1() +*/ +CLlcpSocketType1::CLlcpSocketType1(QLlcpSocketPrivate& aCallback) + : iWaitStatus(ENone), + iPortBinded(EFalse), + iCallback(aCallback) + { + } + +/* + CLlcpSocketPrivate::ContructL() +*/ +void CLlcpSocketType1::ConstructL() + { + User::LeaveIfError(iNfcServer.Open()); + iLlcp = CLlcpProvider::NewL(iNfcServer); + iWait = new (ELeave) CActiveSchedulerWait; + } + +/* + Destroys the LLCP socket. +*/ +CLlcpSocketType1::~CLlcpSocketType1() + { + BEGIN + // Destroy connection + Cleanup(); + + if (iLlcp) + { + iLlcp->StopListeningConnLessRequest(iLocalPort); + delete iLlcp; + } + iNfcServer.Close(); + delete iTimer; + delete iWait; + + END + } + +/* + Cancel the Receive/Transfer and destroy the local/remote connection. +*/ +void CLlcpSocketType1::Cleanup() + { + BEGIN + // Deleting connection + if (iConnectionWrapper) + { + iConnectionWrapper->TransferCancel(); + iConnectionWrapper->ReceiveCancel(); + delete iConnectionWrapper; + iConnectionWrapper = NULL; + } + END + } + +/* + Start to listen the port as given, set as local port which is used to read datagram +*/ +TBool CLlcpSocketType1::Bind(TUint8 aPortNum) + { + BEGIN + TBool bindOK = EFalse; + if (!iPortBinded) + { + TInt error = KErrNone; + TRAP(error, iLlcp->StartListeningConnLessRequestL(*this,aPortNum)); + if (KErrNone == error) + { + iPortBinded = ETrue; + iLocalPort = aPortNum; + bindOK = ETrue; + } + } + END + return bindOK; + } + +/* + Sends the datagram at aData to the service that this socket is connected to. + Returns the number of bytes sent on success; otherwise return -1; +*/ +TInt CLlcpSocketType1::StartWriteDatagram(const TDesC8& aData,TUint8 aPortNum) + { + BEGIN + TInt val = -1; + + if (iConnectionWrapper != NULL && iRemotePort != aPortNum) + { + return val; + } + + if (KErrNone == CreateConnection(aPortNum)) + { + TInt error = KErrNone; + QT_TRYCATCH_ERROR(error , iConnectionWrapper->TransferL(aData)); + + if (KErrNone == error) + { + iCallback.m_writeDatagramRefCount++; + val = 0; + } + } + END + return val; + } + + +TInt CLlcpSocketType1::ReadDatagram(TDes8& aData, TUint8& aRemotePortNum) + { + BEGIN + aRemotePortNum = iRemotePort; + TInt val = ReadDatagram(aData); + END + return val; + } + +TInt CLlcpSocketType1::ReadDatagram(TDes8& aData) + { + BEGIN + TInt readSize = -1; + if (NULL != iConnectionWrapper) + { + readSize = iConnectionWrapper->ReceiveDataFromBuf(aData); + + // Start receiving data again + TInt error = KErrNone; + error = iConnectionWrapper->Receive(); + if (KErrNone != error) + { + readSize = -1; + } + } + END + return readSize; + } + +TBool CLlcpSocketType1::HasPendingDatagrams() const + { + BEGIN + TBool val = EFalse; + if (NULL != iConnectionWrapper) + { + val = iConnectionWrapper->HasPendingDatagrams(); + } + END + return val; + } + +TInt64 CLlcpSocketType1::PendingDatagramSize() const + { + BEGIN + TInt64 val = -1; + if (NULL != iConnectionWrapper) + { + val = iConnectionWrapper->PendingDatagramSize(); + } + END + return val; + } + +/* + Call back from MLlcpConnLessListener +*/ +void CLlcpSocketType1::FrameReceived(MLlcpConnLessTransporter* aConnection) + { + BEGIN + iRemotePort = aConnection->SsapL(); +// StartTransportAndReceive(aConnection); + // Only accepting one incoming remote connection + TInt error = KErrNone; + if (iConnectionWrapper) + { + delete iConnectionWrapper; + iConnectionWrapper = NULL; + } + // Creating wrapper for connection. + TRAP(error, iConnectionWrapper = COwnLlcpConnectionWrapper::NewL(aConnection, *this)); + + if (error == KErrNone && iConnectionWrapper != NULL) + { + error = iConnectionWrapper->Receive(); + } + if (error != KErrNone) + { + QT_TRYCATCH_ERROR(error,iCallback.invokeError()); + } + END + } + +/* + Call back from MLlcpReadWriteCb +*/ +void CLlcpSocketType1::ReceiveComplete(TInt aError) + { + BEGIN + TInt err = KErrNone; + if (KErrNone == aError) + { + QT_TRYCATCH_ERROR(err,iCallback.invokeReadyRead()); + } + else + { + LOG("err = "<<err); + QT_TRYCATCH_ERROR(err,iCallback.invokeError()); + } + Q_UNUSED(err); + END + } + +/* + Call back from MLlcpReadWriteCb +*/ +void CLlcpSocketType1::WriteComplete(TInt aError, TInt aSize) + { + BEGIN + if (iWaitStatus == EWaitForBytesWritten) + { + StopWaitNow(EWaitForBytesWritten); + } + + TInt err = KErrNone; + if (KErrNone == aError) + { + iCallback.m_writeDatagramRefCount--; + QT_TRYCATCH_ERROR(err,iCallback.invokeBytesWritten(aSize)); + } + else + { + QT_TRYCATCH_ERROR(err,iCallback.invokeError()); + } + + if (err == aError && iConnectionWrapper != NULL + && iConnectionWrapper->HasQueuedWrittenDatagram()) + { + iConnectionWrapper->TransferQueued(); + } + END + } + +void CLlcpSocketType1::StopWaitNow(TWaitStatus aWaitStatus) + { + BEGIN + if (iWaitStatus == aWaitStatus) + { + if (iWait->IsStarted()) + { + iWait->AsyncStop(); + } + if (iTimer)//stop the timer + { + delete iTimer; + iTimer = NULL; + } + } + END + } + +/* + Creating MLlcpConnLessTransporter object if connection type connectionless, + Creating Creating wrapper for local peer connection. +*/ +TInt CLlcpSocketType1::CreateConnection(TUint8 portNum) + { + BEGIN + TInt error = KErrNone; + MLlcpConnLessTransporter* llcpConnection = NULL; + + if (iConnectionWrapper) + { + return error; + } + + TRAP(error, llcpConnection = iLlcp->CreateConnLessTransporterL(portNum)); + + if (error == KErrNone) + { + iRemotePort = portNum; + error = StartTransportAndReceive(llcpConnection); + } + END + return error; + } + +TInt CLlcpSocketType1::StartTransportAndReceive(MLlcpConnLessTransporter* aConnection) + { + BEGIN + TInt error = KErrNone; + + // Only accepting one incoming remote connection + if (!iConnectionWrapper) + { + // Creating wrapper for connection. + TRAP(error, iConnectionWrapper = COwnLlcpConnectionWrapper::NewL(aConnection, *this)); + } + + if (error == KErrNone && iConnectionWrapper != NULL) + { + error = iConnectionWrapper->Receive(); + } + END + return error; + } + + +TBool CLlcpSocketType1::WaitForBytesWritten(TInt aMilliSeconds) + { + BEGIN_END + return WaitForOperationReady(EWaitForBytesWritten, aMilliSeconds); + } + +TBool CLlcpSocketType1::WaitForOperationReady(TWaitStatus aWaitStatus,TInt aMilliSeconds) + { + BEGIN + TBool ret = EFalse; + if (iWaitStatus != ENone || iWait->IsStarted()) + { + return ret; + } + iWaitStatus = aWaitStatus; + + if (iTimer) + { + delete iTimer; + iTimer = NULL; + } + if (aMilliSeconds > 0) + { + TRAPD(err, iTimer = CLlcpTimer::NewL(*iWait)); + if (err != KErrNone) + { + return ret; + } + iTimer->Start(aMilliSeconds); + } + iWait->Start(); + + //control is back here when iWait->AsyncStop() is called by the timer or the callback function + iWaitStatus = ENone; + + if (!iTimer) + { + //iTimer == NULL means this CActiveSchedulerWait + //AsyncStop is fired by the call back of ReadyRead + ret = ETrue; + } + else + { + delete iTimer; + iTimer = NULL; + } + + END + return ret; + } + + +/* + Construct the wrapper for connectionLess transport. +*/ +COwnLlcpConnectionWrapper* COwnLlcpConnectionWrapper::NewL(MLlcpConnLessTransporter* aConnection + , MLlcpReadWriteCb& aCallBack) + { + COwnLlcpConnectionWrapper* self = COwnLlcpConnectionWrapper::NewLC(aConnection, aCallBack); + CleanupStack::Pop(self); + return self; + } + +/* + Construct the new wrapper for connectionLess transport. +*/ +COwnLlcpConnectionWrapper* COwnLlcpConnectionWrapper::NewLC(MLlcpConnLessTransporter* aConnection + , MLlcpReadWriteCb& aCallBack) + { + COwnLlcpConnectionWrapper* self = new (ELeave) COwnLlcpConnectionWrapper(aConnection); + CleanupStack::PushL(self); + self->ConstructL(aCallBack); + return self; + } + +/* + Constructor +*/ +COwnLlcpConnectionWrapper::COwnLlcpConnectionWrapper(MLlcpConnLessTransporter* aConnection) + : iConnection(aConnection) + { + } + +/* + ConstructL +*/ +void COwnLlcpConnectionWrapper::ConstructL(MLlcpReadWriteCb& aCallBack) + { + if (NULL == iConnection) + { + User::Leave(KErrArgument); + } + // Create the transmitter AO + iSenderAO = CLlcpSenderType1::NewL(*iConnection, aCallBack); + // Create the receiver AO + iReceiverAO = CLlcpReceiverType1::NewL(*iConnection, aCallBack); + } + +/* + Destroy the new wrapper for connectionLess transport. +*/ +COwnLlcpConnectionWrapper::~COwnLlcpConnectionWrapper() + { + BEGIN + iSendBufArray.ResetAndDestroy(); + iSendBufArray.Close(); + + delete iSenderAO; + delete iReceiverAO; + + if (iConnection) + { + delete iConnection; + iConnection = NULL; + } + END + } + +/* + Send data from queued buffer +*/ +bool COwnLlcpConnectionWrapper::TransferQueued() + { + BEGIN + bool ret = false; + if (iSendBufArray.Count() == 0 || iSenderAO->IsActive()) + return ret; + + HBufC8* bufRef = iSendBufArray[0]; + if (NULL == bufRef) + return ret; + + TPtrC8 ptr(bufRef->Ptr(), bufRef->Length()); + if(!iSenderAO->IsActive() && iSenderAO->Transfer(ptr) == KErrNone) + { + ret = true; + } + iSendBufArray.Remove(0); + delete bufRef; + bufRef = NULL; + + END + return ret; + } + +/* + Send data from local peer to remote peer via connectionLess transport +*/ +TInt COwnLlcpConnectionWrapper::TransferL(const TDesC8& aData) + { + BEGIN + TInt error = KErrNone; + // Pass message into transmitter AO + if (!iSenderAO->IsActive()) + { + error = iSenderAO->Transfer(aData); + } + else if (aData.Length() > 0) + { + HBufC8* buf = HBufC8::NewLC(aData.Length()); + buf->Des().Copy(aData); + error = iSendBufArray.Append(buf); + CleanupStack::Pop(buf); + } + END + return error; + } + + +/* + * Trigger the receiver AO to start receive datagram + Receive data from remote peer to local peer via connectionLess transport +*/ +TInt COwnLlcpConnectionWrapper::Receive() + { + BEGIN + TInt error = KErrInUse; + // Pass message on to transmit AO + if (!iReceiverAO->IsActive()) + { + error = iReceiverAO->Receive(); + } + + END + return error; + } + +/* + Retrieve data from the buffer of the connection less socket +*/ +TInt COwnLlcpConnectionWrapper::ReceiveDataFromBuf(TDes8& aData) + { + return iReceiverAO->ReceiveDataFromBuf(aData); + } + +bool COwnLlcpConnectionWrapper::HasPendingDatagrams() const + { + return iReceiverAO->HasPendingDatagrams(); + } + +bool COwnLlcpConnectionWrapper::HasQueuedWrittenDatagram() const + { + bool hasData = iSendBufArray.Count() > 0 ? true : false; + return hasData; + } + +TInt64 COwnLlcpConnectionWrapper::PendingDatagramSize() const + { + return iReceiverAO->PendingDatagramSize(); + } + +/* + Cancel data transfer from local peer to remote peer via connectionLess transport +*/ +void COwnLlcpConnectionWrapper::TransferCancel() + { + BEGIN + if (iSenderAO->IsActive()) + { + iSenderAO->Cancel(); + } + END + } + +/* + Cancel data receive from local peer to remote peer via connectionLess transport +*/ +void COwnLlcpConnectionWrapper::ReceiveCancel() + { + BEGIN + if (iReceiverAO->IsActive()) + { + iReceiverAO->Cancel(); + } + END + } + +/* + Start of implementation of Sender AO & Receiver AO for connection less mode (type1) +*/ + +/* + Constructor +*/ +CLlcpSenderType1::CLlcpSenderType1(MLlcpConnLessTransporter& aConnection, MLlcpReadWriteCb& aCallBack) + : CActive(CActive::EPriorityStandard) + , iConnection(aConnection) + , iSendObserver(aCallBack) + { + } + +/* + Constructor +*/ +CLlcpSenderType1* CLlcpSenderType1::NewL(MLlcpConnLessTransporter& iConnection, MLlcpReadWriteCb& aCallBack) + { + CLlcpSenderType1* self = new(ELeave) CLlcpSenderType1(iConnection, aCallBack); + CActiveScheduler::Add(self); + return self; + } + +/* + Destructor +*/ +CLlcpSenderType1::~CLlcpSenderType1() + { + BEGIN + Cancel(); // Cancel ANY outstanding request at time of destruction + iTransmitBuf.Close(); + iTempSendBuf.Close(); + END + } + +TInt CLlcpSenderType1::Transfer(const TDesC8& aData) + { + BEGIN + + if (aData.Length() == 0) + { + return KErrArgument; + } + + TInt supportedDataLength = iConnection.SupportedDataLength(); + if (supportedDataLength <= 0) + { + return KErrNotReady; + } + // Reset pos to start + iCurrentSendBufPos = 0; + TInt error = KErrNone; + // Copying data to internal buffer. + iTransmitBuf.Zero(); + error = iTransmitBuf.ReAlloc(aData.Length()); + + if (error == KErrNone) + { + iTransmitBuf.Append(aData); + + if (iTransmitBuf.Length() > supportedDataLength) + { + iCurrentSendBufPtr.Set(iTransmitBuf.Ptr(), supportedDataLength); + } + else + { + iCurrentSendBufPtr.Set(iTransmitBuf.Ptr(), iTransmitBuf.Length()); + } + iCurrentSendBufPos = iCurrentSendBufPtr.Length(); + // Sending data, don't need check active, external func has checked it + iTempSendBuf.Close(); + iTempSendBuf.Create(iCurrentSendBufPtr); + iConnection.Transmit(iStatus, iTempSendBuf); + SetActive(); + } + else + { + error = KErrNoMemory; + } + END + return error; + } + +void CLlcpSenderType1::RunL(void) + { + BEGIN + TInt error = iStatus.Int(); + // Sending error, notify user + if (KErrNone != error) + { + // Return buffer's length which has been sent successfully. + iSendObserver.WriteComplete(error, iCurrentSendBufPos - iCurrentSendBufPtr.Length()); + return; + } + + TInt bytesWritten = iCurrentSendBufPtr.Length(); + + // Still have some buffer need send, don't stop + if (iCurrentSendBufPos < iTransmitBuf.Length()) + { + TInt supportedDataLength = iConnection.SupportedDataLength(); + if (supportedDataLength <= 0) + { + iSendObserver.WriteComplete(KErrGeneral, iCurrentSendBufPtr.Length()); + return; + } + + if (iTransmitBuf.Length() > iCurrentSendBufPos + supportedDataLength) + { + // Still left some buffer + iCurrentSendBufPtr.Set(iTransmitBuf.Ptr() + iCurrentSendBufPos, supportedDataLength); + iCurrentSendBufPos += supportedDataLength; + } + else + { + // All buffer will be sent in this time + iCurrentSendBufPtr.Set(iTransmitBuf.Ptr() + iCurrentSendBufPos + , iTransmitBuf.Length() - iCurrentSendBufPos); + iCurrentSendBufPos = iTransmitBuf.Length(); + } + // Sending data + iTempSendBuf.Close(); + iTempSendBuf.Create(iCurrentSendBufPtr); + iConnection.Transmit(iStatus, iTempSendBuf); + SetActive(); + } + // Sent signal for each successful sending + iSendObserver.WriteComplete(error, bytesWritten); + END + } + +void CLlcpSenderType1::DoCancel(void) + { + BEGIN + // Cancel any outstanding write request on iSocket at this time. + iConnection.TransmitCancel(); + END + } + +/* + Start of implementation of Receiver AO for connection less mode (type1) - CLlcpReceiverType1 +*/ + +/* + Constructor +*/ +CLlcpReceiverType1::CLlcpReceiverType1(MLlcpConnLessTransporter& aConnection, MLlcpReadWriteCb& aCallBack) + : CActive(CActive::EPriorityStandard) + , iConnection(aConnection) + , iReceiveObserver(aCallBack) + { + } + +/* + Constructor +*/ +CLlcpReceiverType1* CLlcpReceiverType1::NewL(MLlcpConnLessTransporter& aConnection, MLlcpReadWriteCb& aCallBack) + { + CLlcpReceiverType1* self = new (ELeave) CLlcpReceiverType1(aConnection, aCallBack); + CActiveScheduler::Add(self); + return self; + } + + +/* + Set active for the receiver AO + Receive complete callback function "cb" registered +*/ +TInt CLlcpReceiverType1::Receive() + { + BEGIN + TInt error = KErrNotReady; + TInt length = 0; + length = iConnection.SupportedDataLength(); + iReceiveBuf.Zero(); + if (length > 0) + error = iReceiveBuf.ReAlloc(length); + + if (error == KErrNone) + { + iConnection.Receive(iStatus, iReceiveBuf); + SetActive(); + } + + END + return error; + } + +void CLlcpReceiverType1::RunL(void) + { + BEGIN + TInt error = iStatus.Int(); + // Call back functions of notifying the llcp receiver completed. + iReceiveObserver.ReceiveComplete(error); + END + } + +CLlcpReceiverType1::~CLlcpReceiverType1() + { + BEGIN + // cancel ANY outstanding request at time of destruction + Cancel(); + iReceiveBuf.Close(); + END + } + +TInt CLlcpReceiverType1::ReceiveDataFromBuf(TDes8& aData) + { + BEGIN + if (iReceiveBuf.Size() == 0) + return 0; + + TInt requiredLength = aData.MaxLength() - aData.Length(); + TInt bufLength = iReceiveBuf.Length(); + TInt readLength = requiredLength < bufLength ? requiredLength : bufLength; + + TPtrC8 ptr(iReceiveBuf.Ptr(),readLength); + aData.Append(ptr); + + //Empty the buffer as long as receive data request issued. + iReceiveBuf.Zero(); + END + return readLength; + } + +bool CLlcpReceiverType1::HasPendingDatagrams() const + { + return iReceiveBuf.Size() > 0 ? true : false; + } + +TInt64 CLlcpReceiverType1::PendingDatagramSize() const + { + return iReceiveBuf.Size(); + } + +void CLlcpReceiverType1::DoCancel(void) + { + BEGIN + // Cancel any outstanding write request on iSocket at this time. + iConnection.ReceiveCancel(); + END + } diff --git a/src/nfc/symbian/llcpsockettype1_symbian.h b/src/nfc/symbian/llcpsockettype1_symbian.h new file mode 100644 index 00000000..d45e20e9 --- /dev/null +++ b/src/nfc/symbian/llcpsockettype1_symbian.h @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LLCPSOCKETTYPE1_SYMBIAN_H_ +#define LLCPSOCKETTYPE1_SYMBIAN_H_ + +#include <e32base.h> +#include <nfcserver.h> // RNfcServer +#include <llcpconnlesslistener.h> // MLlcpConnLessListener + +/* + * FORWARD DECLARATIONS + */ +class COwnLlcpConnectionWrapper; +class CLlcpSenderType1; +class CLlcpReceiverType1; +class CLlcpTimer; +class CLlcpProvider; +class MLlcpConnLessTransporter; + +#include <qconnectivityglobal.h> +#include "../qllcpsocket_symbian_p.h" + +class MLlcpReadWriteCb + { +public: + + /* + * Empty Destructor. + */ + virtual ~MLlcpReadWriteCb() {}; + + /* + * Called + */ + virtual void ReceiveComplete(TInt aError) = 0; + virtual void WriteComplete(TInt aError, TInt aSize) = 0; + }; + +/* + * CLASS DECLARATION for CLlcpSocketType1 (ConnectLess Tran). + */ +class CLlcpSocketType1 : public CBase, + public MLlcpConnLessListener, + public MLlcpReadWriteCb + { +public: + /* + * Creates a new CLlcpSocketType1 object. + */ + static CLlcpSocketType1* NewL(QLlcpSocketPrivate&); + + /* + * Creates a new CLlcpSocketType1 object. + */ + static CLlcpSocketType1* NewLC(QLlcpSocketPrivate&); + + /* + * Destructor + */ + ~CLlcpSocketType1(); + +public: + TInt StartWriteDatagram(const TDesC8& aData,TUint8 portNum); + TInt ReadDatagram(TDes8& aData); + TInt ReadDatagram(TDes8& aData, TUint8& aRemotePortNum); + TBool Bind(TUint8 portNum); + + /* + Returns true if at least one datagram is waiting to be read; + otherwise returns false. + */ + TBool HasPendingDatagrams() const; + TInt64 PendingDatagramSize() const; + TBool WaitForBytesWritten(TInt aMilliSeconds); + +private: + enum TWaitStatus + { + ENone, + EWaitForBytesWritten + }; + +private: + TBool WaitForOperationReady(TWaitStatus aWaitStatus,TInt aMilliSeconds); + void StopWaitNow(TWaitStatus aWaitStatus); + +private: // from MLlcpReadWriteCb + void ReceiveComplete(TInt aError); + void WriteComplete(TInt aError, TInt aSize); + +private: // From MLlcpConnLessListener + void FrameReceived(MLlcpConnLessTransporter* aConnection); + +private: + // Constructor + CLlcpSocketType1(QLlcpSocketPrivate&); + + // Second phase constructor + void ConstructL(); + void Cleanup(); + + TInt CreateConnection(TUint8 portNum); + TInt StartTransportAndReceive(MLlcpConnLessTransporter* aConnection); + +private: + /* + * Handle to NFC-server. + * Own. + */ + RNfcServer iNfcServer; + + /* + * Pointer to CLlcpProvider object. + * Own. + */ + CLlcpProvider* iLlcp; // Own + + /* + * Pointer to MLlcpConnLessTransporter object. + * Own. + * + * This is used to send data to local device. + */ + COwnLlcpConnectionWrapper* iConnectionWrapper; // Own + + CActiveSchedulerWait * iWait; //Own + CLlcpTimer * iTimer; // Own + TWaitStatus iWaitStatus; + + bool iPortBinded; + TUint8 iLocalPort; + TUint8 iRemotePort; + + QLlcpSocketPrivate& iCallback; + }; + +/* + * CLASS DECLARATION for COwnLlcpConnectionWrapper. + * + */ +class COwnLlcpConnectionWrapper : public CBase + { +public: + + /* + * Creates a new COwnLlcpConnection object. + */ + static COwnLlcpConnectionWrapper* NewL(MLlcpConnLessTransporter* aTransporter + , MLlcpReadWriteCb& aCallBack); + + /* + * Creates a new COwnLlcpConnection object. + */ + static COwnLlcpConnectionWrapper* NewLC(MLlcpConnLessTransporter* aTransporter + , MLlcpReadWriteCb& aCallBack); + + /* + * Destructor. + */ + ~COwnLlcpConnectionWrapper(); + +public: + /* + * Transfer given data to remote device. + */ + TInt TransferL(const TDesC8& aData); + bool TransferQueued(); + void TransferCancel(); + TInt Receive(); + + /* + * Cancels COwnLlcpConnection::Receive() request. + */ + void ReceiveCancel(); + + TInt ReceiveDataFromBuf(TDes8& aData); + bool HasPendingDatagrams() const; + TInt64 PendingDatagramSize() const; + bool HasQueuedWrittenDatagram() const; + +private: + + // Constructor + COwnLlcpConnectionWrapper(MLlcpConnLessTransporter* aConnection); + // Second phase constructor + void ConstructL(MLlcpReadWriteCb& aCallBack); + +private: + MLlcpConnLessTransporter* iConnection; + CLlcpSenderType1* iSenderAO; + CLlcpReceiverType1* iReceiverAO; + RPointerArray<HBufC8> iSendBufArray; + }; + + +class CLlcpSenderType1 : public CActive + { +public: + static CLlcpSenderType1* NewL(MLlcpConnLessTransporter& aConnection, MLlcpReadWriteCb& aCallBack); + ~CLlcpSenderType1(); + +public: + /* + * Transfer given data to remote device. + */ + TInt Transfer(const TDesC8& aData); + + /* + * Cancels COwnLlcpConnection::Transfer() request. + */ + void TransferCancel(); + +public: // From CActive + void RunL(); + void DoCancel(); + +private: + CLlcpSenderType1(MLlcpConnLessTransporter& aConnection, MLlcpReadWriteCb& aCallBack); +private: + /* + Buffered data for transmitting data. + */ + MLlcpConnLessTransporter& iConnection; + MLlcpReadWriteCb& iSendObserver; + RBuf8 iTransmitBuf; + // Symbian have limitaion for sending buffer in one send, + // The variable used to record how many buffer have been sent so far + TInt iCurrentSendBufPos; + TPtrC8 iCurrentSendBufPtr; + RBuf8 iTempSendBuf; // Temp workround to avoid NFC server's bug, if use ptr, it will crash + }; + +class CLlcpReceiverType1 : public CActive + { +public: + static CLlcpReceiverType1* NewL(MLlcpConnLessTransporter& aConnection, MLlcpReadWriteCb& aCallBack); + ~CLlcpReceiverType1(); + +public: + /* + * Starts receive data from ConnLess. + */ + TInt Receive(); + + /* + * Cancels COwnLlcpConnection::Receive() request. + */ + void ReceiveCancel(); + TInt ReceiveDataFromBuf(TDes8& aData); + + bool HasPendingDatagrams() const; + TInt64 PendingDatagramSize() const; + +public: // From CActive + void RunL(); + void DoCancel(); + +private: + CLlcpReceiverType1(MLlcpConnLessTransporter& aConnection, MLlcpReadWriteCb& aCallBack); + +private: + RBuf8 iReceiveBuf; + MLlcpConnLessTransporter& iConnection; + MLlcpReadWriteCb& iReceiveObserver; + }; +#endif /* LLCPSOCKETTYPE1_SYMBIAN_H_ */ diff --git a/src/nfc/symbian/llcpsockettype2_symbian.cpp b/src/nfc/symbian/llcpsockettype2_symbian.cpp new file mode 100644 index 00000000..0cc92d2b --- /dev/null +++ b/src/nfc/symbian/llcpsockettype2_symbian.cpp @@ -0,0 +1,986 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nearfieldutility_symbian.h" +#include "llcpsockettype2_symbian.h" + +#include "debug.h" + +/* + CLlcpSocketType2::ContructL() +*/ +void CLlcpSocketType2::ConstructL() + { + BEGIN + User::LeaveIfError(iNfcServer.Open()); + iLlcp = CLlcpProvider::NewL( iNfcServer ); + iWait = new (ELeave) CActiveSchedulerWait; + END + } + +/* + CLlcpSocketType2::CLlcpSocketType2() +*/ +CLlcpSocketType2::CLlcpSocketType2(MLlcpConnOrientedTransporter* aTransporter, QLlcpSocketPrivate* aCallback) + : iLlcp( NULL ), + iTransporter(aTransporter), + iWaitStatus(ENone), + iCallback(aCallback) + { + } + +CLlcpSocketType2* CLlcpSocketType2::NewL(QLlcpSocketPrivate* aCallback) + { + BEGIN + CLlcpSocketType2* self = new (ELeave) CLlcpSocketType2(NULL,aCallback); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + END + return self; + } + +CLlcpSocketType2* CLlcpSocketType2::NewL(MLlcpConnOrientedTransporter* aTransporter, QLlcpSocketPrivate* aCallback) + { + BEGIN + CLlcpSocketType2* self = new (ELeave) CLlcpSocketType2(aTransporter,aCallback); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + END + return self; + } + +/* + Destroys the LLCP socket. +*/ +CLlcpSocketType2::~CLlcpSocketType2() + { + BEGIN + delete iConnecter; + delete iSender; + delete iReceiver; + delete iTransporter; + delete iLlcp; + delete iWait; + delete iTimer; + iReceiveBufArray.ResetAndDestroy(); + iReceiveBufArray.Close(); + iNfcServer.Close(); + END + } + +/* + Connects to the service identified by the URI \a serviceUri (on \a target). +*/ +void CLlcpSocketType2::ConnectToServiceL( const QString &serviceUri) + { + BEGIN + HBufC8* serviceName = QNFCNdefUtility::QString2HBufC8L(serviceUri); + + CleanupStack::PushL(serviceName); + ConnectToServiceL(serviceName->Des()) ; + CleanupStack::PopAndDestroy(serviceName); + END + } + +void CLlcpSocketType2::ConnectToServiceL( const TDesC8& aServiceName) + { + BEGIN + if ( !iConnecter && !iTransporter) + { + iTransporter = iLlcp->CreateConnOrientedTransporterL( aServiceName ); + iConnecter = CLlcpConnecterAO::NewL( *iTransporter, *this ); + } + iConnecter->ConnectL( aServiceName ); + END + } + +/* + Disconnects the socket. +*/ + +TInt CLlcpSocketType2::DisconnectFromService() + { + BEGIN + if (iSender && iSender->IsActive()) + { + WaitForBytesWritten(3000);//wait 3 seconds + } + if (iSender) + { + delete iSender; + iSender = NULL; + } + if (iReceiver) + { + delete iReceiver; + iReceiver = NULL; + } + + if (iConnecter) + { + iConnecter->Disconnect(); + delete iConnecter; + iConnecter = NULL; + } + if (iTransporter) + { + LOG("delete iTransporter;"); + delete iTransporter; + iTransporter = NULL; + } + END + return KErrNone; + } + +/* + Sends the datagram at aData to the service that this socket is connected to. + Returns the number of bytes sent on success; otherwise return -1; +*/ +TInt CLlcpSocketType2::StartWriteDatagram(const TDesC8& aData) + { + BEGIN + TInt val = -1; + if (!iTransporter) + { + END + return val; + } + + if (!iSender) + { + TRAPD(err,iSender = CLlcpSenderAO::NewL(*iTransporter, *this)); + if (err != KErrNone) + { + END + return val; + } + } + TInt error = KErrNone; + //asynchronous transfer + error = iSender->Send( aData); + if (KErrNone == error) + { + val = 0; + } + END + return val; + } + +TBool CLlcpSocketType2::ReceiveData(TDes8& aData) + { + //fetch data from internal buffer + BEGIN + TBool ret = EFalse; + HBufC8* buf = NULL; + TInt extBufferLength = aData.Length(); + TInt extBufferMaxLength = aData.MaxLength(); + while ( iReceiveBufArray.Count() > 0 ) + { + buf = iReceiveBufArray[ 0 ]; + if (buf->Length() - iBufferOffset <= extBufferMaxLength - extBufferLength ) + {//internal buffer's size <= available space of the user specified buffer + TPtrC8 ptr(buf->Ptr() + iBufferOffset, buf->Length() - iBufferOffset); + aData.Append( ptr ); + iReceiveBufArray.Remove( 0 ); + extBufferLength += buf->Length() - iBufferOffset; + delete buf; + buf = NULL; + iBufferOffset = 0; + } + else + { + TPtrC8 ptr(buf->Ptr() + iBufferOffset, extBufferMaxLength - extBufferLength); + aData.Append( ptr ); + iBufferOffset += extBufferMaxLength - extBufferLength; + ret = ETrue; + break; + } + ret = ETrue; + } + END + return ret; + } + +TInt64 CLlcpSocketType2::BytesAvailable() + { + BEGIN + TInt64 ret = 0; + for (TInt i = 0; i < iReceiveBufArray.Count(); ++i) + { + HBufC8* buf = iReceiveBufArray[ i ]; + if (!buf) + { + continue; + } + if ( i == 0) + { + ret += buf->Length() - iBufferOffset; + } + else + { + ret += buf->Length(); + } + } + END + return ret; + } + +TBool CLlcpSocketType2::WaitForOperationReady(TWaitStatus aWaitStatus,TInt aMilliSeconds) + { + BEGIN + TBool ret = EFalse; + if (iWaitStatus != ENone || iWait->IsStarted()) + { + END + return ret; + } + iWaitStatus = aWaitStatus; + + if (iTimer) + { + delete iTimer; + iTimer = NULL; + } + if (aMilliSeconds > 0) + { + TRAPD(err, iTimer = CLlcpTimer::NewL(*iWait)); + if (err != KErrNone) + { + END + return ret; + } + iTimer->Start(aMilliSeconds); + } + iWait->Start(); + //control is back here when iWait->AsyncStop() is called by the timer or the callback function + iWaitStatus = ENone; + + if (!iTimer) + { + //iTimer == NULL means this CActiveSchedulerWait + //AsyncStop is fired by the call back of ReadyRead + ret = ETrue; + } + else + { + delete iTimer; + iTimer = NULL; + } + END + return ret; + } + +/** + * Blocks until data is available for reading and the readyRead() + * signal has been emitted, or until msecs milliseconds have + * passed. If msecs is -1, this function will not time out. + * Returns true if data is available for reading; otherwise + * returns false (if the operation timed out or if an error + * occurred). + */ +TBool CLlcpSocketType2::WaitForReadyRead(TInt aMilliSeconds) + { + BEGIN + END + return WaitForOperationReady(EWaitForReadyRead, aMilliSeconds); + } + +TBool CLlcpSocketType2::WaitForBytesWritten(TInt aMilliSeconds) + { + BEGIN + END + return WaitForOperationReady(EWaitForBytesWritten, aMilliSeconds); + } +TBool CLlcpSocketType2::WaitForConnected(TInt aMilliSeconds) + { + BEGIN + END + return WaitForOperationReady(EWaitForConnected, aMilliSeconds); + } + +void CLlcpSocketType2::AttachCallbackHandler(QLlcpSocketPrivate* aCallback) + { + BEGIN + iCallback = aCallback; + if (iTransporter && iTransporter->IsConnected())//has connected llcp transporter + { + LOG("A server llcp type2 socket"); + if (!iReceiver) + { + TRAPD(err,iReceiver = CLlcpReceiverAO::NewL( *iTransporter, *this )); + if (err != KErrNone) + { + END + return; + } + } + if (!iConnecter) + { + TRAP_IGNORE(iConnecter = CLlcpConnecterAO::NewL( *iTransporter, *this )); + } + if (iReceiver->StartReceiveDatagram() != KErrNone) + { + Error(QLlcpSocket::UnknownSocketError); + } + } + END + } + +void CLlcpSocketType2::Error(QLlcpSocket::SocketError /*aSocketError*/) + { + BEGIN + //emit error + if ( iCallback ) + { + TInt error = KErrNone; + QT_TRYCATCH_ERROR(error,iCallback->invokeError()); + //can do nothing if there is an error,so just ignore it + Q_UNUSED(error); + } + END + } +void CLlcpSocketType2::StateChanged(QLlcpSocket::SocketState aSocketState) + { + BEGIN + if (aSocketState == QLlcpSocket::ConnectedState && iWaitStatus == EWaitForConnected) + { + StopWaitNow(EWaitForConnected); + } + TInt error = KErrNone; + if (aSocketState == QLlcpSocket::ConnectedState) + { + if ( iCallback) + { + QT_TRYCATCH_ERROR(error, iCallback->invokeConnected()); + Q_UNUSED(error); + } + if (!iReceiver) + { + TRAPD(err,iReceiver = CLlcpReceiverAO::NewL( *iTransporter, *this )); + if (err != KErrNone) + { + Error(QLlcpSocket::UnknownSocketError); + return; + } + } + if(iReceiver->StartReceiveDatagram() != KErrNone) + { + Error(QLlcpSocket::UnknownSocketError); + } + } + + if (aSocketState == QLlcpSocket::ClosingState && iCallback) + { + QT_TRYCATCH_ERROR(error, iCallback->invokeDisconnected()); + Q_UNUSED(error); + } + + END + } + +void CLlcpSocketType2::StopWaitNow(TWaitStatus aWaitStatus) + { + BEGIN + if ( iWaitStatus == aWaitStatus ) + { + if (iTimer)//stop the timer + { + delete iTimer; + iTimer = NULL; + } + if (iWait->IsStarted()) + { + iWait->AsyncStop(); + } + } + END + } +void CLlcpSocketType2::ReadyRead() + { + BEGIN + if (iWaitStatus == EWaitForReadyRead) + { + StopWaitNow(EWaitForReadyRead); + } + //emit readyRead() + if ( iCallback ) + { + TInt error = KErrNone; + QT_TRYCATCH_ERROR(error,iCallback->invokeReadyRead()); + //can do nothing if there is an error,so just ignore it + Q_UNUSED(error); + } + END + } +void CLlcpSocketType2::BytesWritten(qint64 aBytes) + { + BEGIN + if (iWaitStatus == EWaitForBytesWritten) + { + StopWaitNow(EWaitForBytesWritten); + } + //emit bytesWritten signal; + if ( iCallback ) + { + TInt error = KErrNone; + QT_TRYCATCH_ERROR(error,iCallback->invokeBytesWritten(aBytes)); + //can do nothing if there is an error,so just ignore it + Q_UNUSED(error); + } + END + } + +// connecter implementation +CLlcpConnecterAO* CLlcpConnecterAO::NewL( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ) + { + BEGIN + CLlcpConnecterAO* self = new (ELeave) CLlcpConnecterAO( aConnection, aSocket ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + END + return self; + } + +CLlcpConnecterAO::CLlcpConnecterAO( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ) + : CActive( EPriorityStandard ), + iConnection( aConnection ), + iSocket( aSocket ), + iConnState( ENotConnected ) + { + } +/* + ConstructL +*/ +void CLlcpConnecterAO::ConstructL() + { + BEGIN + CActiveScheduler::Add( this ); + if ( iConnection.IsConnected() ) + { + LOG("a LLCP server side socket"); + iConnState = EConnected; + // Starting listening disconnect event + iConnection.WaitForDisconnection( iStatus ); + SetActive(); + } + END + } + +/* + * Destructor. + */ +CLlcpConnecterAO::~CLlcpConnecterAO() + { + BEGIN + Cancel(); + if ( iConnState == EConnected ) + { + iConnection.Disconnect(); + } + END + } +/* + * Connect to remote peer as given service uri. + */ +void CLlcpConnecterAO::ConnectL(const TDesC8& /*aServiceName*/) + { + BEGIN + if ( iConnState == ENotConnected ) + { + // Starting connecting if is in idle state + iConnection.Connect( iStatus ); + SetActive(); + iConnState = EConnecting; + //emit connecting signal + iSocket.StateChanged(QLlcpSocket::ConnectingState); + } + END + } + +/* + * Disconnect with remote peer. + */ +void CLlcpConnecterAO::Disconnect() + { + BEGIN + if ( iConnState == ENotConnected ) + { + END + return; + } + Cancel(); + if ( iConnState == EConnected ) + { + iConnection.Disconnect(); + } + iConnState = ENotConnected; + + //emit QAbstractSocket::ClosingState; + iSocket.StateChanged(QLlcpSocket::ClosingState); + END + } +void CLlcpConnecterAO::RunL() + { + BEGIN + TInt error = iStatus.Int(); + + switch ( iConnState ) + { + // Handling connecting request + case EConnecting: + { + if ( error == KErrNone ) + { + LOG("Connected to LLCP server"); + // Updating state + iConnState = EConnected; + //emit connected signal + iSocket.StateChanged(QLlcpSocket::ConnectedState); + // Starting listening disconnect event + iConnection.WaitForDisconnection( iStatus ); + SetActive(); + } + else + { + LOG("!!Failed to Connected to LLCP server"); + //KErrNotSupported when remote peer has lost from the near field. + iConnState = ENotConnected; + //emit error signal + iSocket.Error(QLlcpSocket::UnknownSocketError); + } + } + break; + case EConnected: + { + //handling disconnect event + if ( error == KErrNone ) + { + LOG("Disconnected event received"); + // Updating state + iConnState = ENotConnected; + //emit disconnected signal + iSocket.StateChanged(QLlcpSocket::ClosingState); + } + else + { + iConnState = ENotConnected; + //emit error signal + iSocket.Error(QLlcpSocket::UnknownSocketError); + } + } + break; + default: + { + // Do nothing + } + break; + } + END + } +void CLlcpConnecterAO::DoCancel() + { + BEGIN + switch ( iConnState ) + { + case EConnecting: + { + iConnection.ConnectCancel(); + } + break; + + case EConnected: + { + iConnection.WaitForDisconnectionCancel(); + } + break; + + default: + { + // Do nothing + } + break; + } + END + } +//sender AO implementation + +CLlcpSenderAO* CLlcpSenderAO::NewL( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ) + { + BEGIN + CLlcpSenderAO* self = new (ELeave) CLlcpSenderAO( aConnection, aSocket ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + END + return self; + } + +CLlcpSenderAO::CLlcpSenderAO( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ) + : CActive( EPriorityStandard ), + iConnection( aConnection ), + iSocket( aSocket ) + { + } +/* + ConstructL +*/ +void CLlcpSenderAO::ConstructL() + { + BEGIN + CActiveScheduler::Add( this ); + END + } + +/* + * Destructor. + */ +CLlcpSenderAO::~CLlcpSenderAO() + { + BEGIN + Cancel(); + iSendBuf0.Close(); + iSendBuf1.Close(); + //todo + iCurrentSendBuf.Close(); + END + } +/* + * Transfer given data to remote device. + */ +TInt CLlcpSenderAO::Send( const TDesC8& aData ) + { + BEGIN + TInt error = KErrNone; + if (aData.Length() == 0) + { + END + return KErrArgument; + } + TInt supportedDataLength = iConnection.SupportedDataLength(); + if (supportedDataLength <= 0) + { + END + return KErrNotReady; + } + if ( !IsActive() ) + { + // Copying data to internal buffer. + iSendBuf0.Zero(); + iCurrentPos = 0; + error = iSendBuf0.ReAlloc( aData.Length() ); + + if ( error == KErrNone ) + { + iSendBuf0.Append( aData ); + + if (iSendBuf0.Length() > supportedDataLength) + { + iCurrentSendPtr.Set(iSendBuf0.Ptr(), supportedDataLength); + } + else + { + iCurrentSendPtr.Set(iSendBuf0.Ptr(), iSendBuf0.Length()); + } + // Sending data + //TODO defect in NFC server + iCurrentSendBuf.Close(); + iCurrentSendBuf.Create(iCurrentSendPtr); + iConnection.Transmit( iStatus, iCurrentSendBuf ); +// iConnection.Transmit( iStatus, iCurrentSendPtr ); + SetActive(); + iCurrentBuffer = EBuffer0; + } + } + else + { + if (iCurrentBuffer == EBuffer0) + { + error = iSendBuf1.ReAlloc( iSendBuf1.Length() + aData.Length() ); + if (error == KErrNone) + { + iSendBuf1.Append(aData); + } + } + else + { + error = iSendBuf0.ReAlloc( iSendBuf0.Length() + aData.Length() ); + if (error == KErrNone) + { + iSendBuf0.Append(aData); + } + } + } + END + return error; + } + +void CLlcpSenderAO::SendRestDataAndSwitchBuffer(RBuf8& aWorkingBuffer, RBuf8& aNextBuffer) + { + BEGIN + TInt supportedDataLength = iConnection.SupportedDataLength(); + if (iCurrentPos == aWorkingBuffer.Length()) + { + LOG("Current working buffer write finished"); + + aWorkingBuffer.Zero(); + if(aNextBuffer.Length() > 0) + { + + if (&aNextBuffer == &iSendBuf0) + { + iCurrentBuffer = EBuffer0; + LOG("Start switch to buffer 0"); + } + else + { + iCurrentBuffer = EBuffer1; + LOG("Start switch to buffer 1"); + } + + iCurrentPos = 0; + + if (supportedDataLength > 0) + { + if (aNextBuffer.Length() > supportedDataLength) + { + iCurrentSendPtr.Set(aNextBuffer.Ptr(), supportedDataLength); + } + else + { + iCurrentSendPtr.Set(aNextBuffer.Ptr(), aNextBuffer.Length()); + } + //TODO + iCurrentSendBuf.Close(); + iCurrentSendBuf.Create(iCurrentSendPtr); + iConnection.Transmit( iStatus, iCurrentSendBuf ); +// iConnection.Transmit( iStatus, iCurrentSendPtr ); + SetActive(); + } + else + { + LOG("SupportedDataLength is invalid, value="<<supportedDataLength); + iSendBuf0.Zero(); + iSendBuf1.Zero(); + iCurrentBuffer = EBuffer0; + iSocket.Error(QLlcpSocket::UnknownSocketError); + } + } + } + else //means current working buffer still have data need to be sent + { + LOG("Current working buffer still has data need to be sent"); + if (supportedDataLength > 0) + { + if (aWorkingBuffer.Length() - iCurrentPos > supportedDataLength) + { + iCurrentSendPtr.Set(aWorkingBuffer.Ptr() + iCurrentPos, supportedDataLength); + } + else + { + iCurrentSendPtr.Set(aWorkingBuffer.Ptr() + iCurrentPos, aWorkingBuffer.Length() - iCurrentPos); + } + // Sending data + //TODO + iCurrentSendBuf.Close(); + iCurrentSendBuf.Create(iCurrentSendPtr); + iConnection.Transmit( iStatus, iCurrentSendBuf ); + +// iConnection.Transmit( iStatus, iCurrentSendPtr ); + SetActive(); + } + else + { + LOG("SupportedDataLength is invalid, value="<<supportedDataLength); + iSendBuf0.Zero(); + iSendBuf1.Zero(); + iCurrentBuffer = EBuffer0; + iSocket.Error(QLlcpSocket::UnknownSocketError); + } + } + END + } +void CLlcpSenderAO::RunL() + { + BEGIN + TInt error = iStatus.Int(); + if ( error == KErrNone ) + { + TInt bytesWritten = iCurrentSendPtr.Length(); + + iCurrentPos += iCurrentSendPtr.Length(); + if (iCurrentBuffer == EBuffer0) + { + SendRestDataAndSwitchBuffer(iSendBuf0, iSendBuf1); + }//if (iCurrentBuffer == EBuffer0) + else //current working buffer is buffer1 + { + SendRestDataAndSwitchBuffer(iSendBuf1, iSendBuf0); + } + //emit BytesWritten signal + iSocket.BytesWritten(bytesWritten); + }//if ( error == KErrNone ) + else + { + LOG("iStatus.Int() = "<<error); + iSendBuf0.Zero(); + iSendBuf1.Zero(); + iCurrentBuffer = EBuffer0; + //emit error() signal + iSocket.Error(QLlcpSocket::UnknownSocketError); + } + END + } +void CLlcpSenderAO::DoCancel() + { + BEGIN + iConnection.TransmitCancel(); + END + } +//receiver implementation +CLlcpReceiverAO* CLlcpReceiverAO::NewL( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ) + { + BEGIN + CLlcpReceiverAO* self = new (ELeave) CLlcpReceiverAO( aConnection, aSocket ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + END + return self; + } + +CLlcpReceiverAO::CLlcpReceiverAO( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ) + : CActive( EPriorityStandard ), + iConnection( aConnection ), + iSocket( aSocket ) + { + } +/* + ConstructL +*/ +void CLlcpReceiverAO::ConstructL() + { + BEGIN + CActiveScheduler::Add( this ); + END + } + +/* + * Destructor. + */ +CLlcpReceiverAO::~CLlcpReceiverAO() + { + BEGIN + Cancel(); + iReceiveBuf.Close(); + END + } + +TInt CLlcpReceiverAO::StartReceiveDatagram() + { + BEGIN + TInt length = 0; + TInt error = KErrNone; + length = iConnection.SupportedDataLength(); + + if ( length > 0 ) + { + iReceiveBuf.Zero(); + error = iReceiveBuf.ReAlloc( length ); + + if ( error == KErrNone ) + { + iConnection.Receive( iStatus, iReceiveBuf ); + SetActive(); + } + } + else + { + // if length is 0 or negative, LLCP link is destroyed. + LOG("Error: length is"<<length); + error = KErrNotReady; + } + END + return error; + } + +void CLlcpReceiverAO::RunL() + { + BEGIN + TInt error = iStatus.Int(); + if ( error == KErrNone ) + { + //append to buffer + HBufC8* buf = NULL; + buf = HBufC8::NewLC( iReceiveBuf.Length() ); + buf->Des().Copy( iReceiveBuf ); + iSocket.iReceiveBufArray.AppendL( buf ); + CleanupStack::Pop( buf ); + + //emit readyRead() signal + iSocket.ReadyRead(); + //resend the Receive request to NFC server + if (StartReceiveDatagram() != KErrNone) + { + iSocket.Error(QLlcpSocket::UnknownSocketError); + } + } + else if ( error == KErrCancel ) + { + //just omit the KErrCancel + LOG(" iStatus = KErrCancel"); + } + else + { + //emit error() signal + iSocket.Error(QLlcpSocket::UnknownSocketError); + } + END + } +void CLlcpReceiverAO::DoCancel() + { + BEGIN + iConnection.ReceiveCancel(); + END + } +//EOF diff --git a/src/nfc/symbian/llcpsockettype2_symbian.h b/src/nfc/symbian/llcpsockettype2_symbian.h new file mode 100644 index 00000000..e67ea2b9 --- /dev/null +++ b/src/nfc/symbian/llcpsockettype2_symbian.h @@ -0,0 +1,266 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef LLCPSOCKETTYPE2_SYMBIAN_H_ +#define LLCPSOCKETTYPE2_SYMBIAN_H_ + +#include <e32base.h> +#include <nfcserver.h> // RNfcServer +#include <llcpprovider.h> // CLlcpProvider +#include <llcpconnorientedtransporter.h> // MLlcpConnOrientedTransporter +#include <llcpconnorientedlistener.h> // MLlcpConnOrientedListener +#include <llcplinklistener.h> // MLlcpLinkListener +#include <qconnectivityglobal.h> +#include "../qllcpsocket_symbian_p.h" +#include "../qllcpsocket.h" + +/* + * FORWARD DECLARATIONS + */ +class CLlcpConnecterAO; +class CLlcpSenderAO; +class CLlcpReceiverAO; +class CLlcpTimer; +/* + * CLASS DECLARATION for CLlcpSocketType2 (ConnectOriented Transportation). + */ +class CLlcpSocketType2 : public CBase +{ +public: + static CLlcpSocketType2* NewL(QLlcpSocketPrivate* aCallback = NULL); + + static CLlcpSocketType2* NewL(MLlcpConnOrientedTransporter* aTransporter, QLlcpSocketPrivate* aCallback = NULL); + ~CLlcpSocketType2(); + +public: + void ConnectToServiceL( const QString &serviceUri); + TInt DisconnectFromService(); + + TInt StartWriteDatagram(const TDesC8& aData); + TBool ReceiveData(TDes8& aData); + + TInt64 BytesAvailable(); + + //for qt signals + void Error(QLlcpSocket::SocketError aSocketError); + void StateChanged(QLlcpSocket::SocketState aSocketState); + void ReadyRead(); + void BytesWritten(qint64 aBytes); + + TBool WaitForReadyRead(TInt aMilliSeconds); + TBool WaitForBytesWritten(TInt aMilliSeconds); + TBool WaitForConnected(TInt aMilliSeconds); + + void AttachCallbackHandler(QLlcpSocketPrivate* aCallback); +private: + // Constructor + explicit CLlcpSocketType2(MLlcpConnOrientedTransporter* aTransporter = NULL,QLlcpSocketPrivate* aCallback = NULL); + // Second phase constructor + void ConstructL(); + void ConnectToServiceL( const TDesC8& aServiceName); + enum TWaitStatus + { + ENone, + EWaitForReadyRead, + EWaitForBytesWritten, + EWaitForConnected, + EWaitForDisconnected + }; + TBool WaitForOperationReady(TWaitStatus aWaitStatus,TInt aSeconds); + void StopWaitNow(TWaitStatus aWaitStatus); +private: + friend class CLlcpReceiverAO; + /* + * Handle to NFC-server. + * Own. + */ + RNfcServer iNfcServer; + + /* + * Pointer to CLlcpProvider object. + * Own. + */ + CLlcpProvider* iLlcp; + + MLlcpConnOrientedTransporter* iTransporter; + + CLlcpConnecterAO* iConnecter; + CLlcpSenderAO* iSender; + CLlcpReceiverAO* iReceiver; + + RPointerArray<HBufC8> iReceiveBufArray; + TInt iBufferOffset; + + CActiveSchedulerWait * iWait; + TWaitStatus iWaitStatus; + CLlcpTimer * iTimer; + + QLlcpSocketPrivate* iCallback; // not own + +}; + +class CLlcpConnecterAO : public CActive +{ +public: + static CLlcpConnecterAO* NewL( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ); + ~CLlcpConnecterAO(); + +public: + /* + * Disonnect with remote peer . + */ + void Disconnect(); + + /* + * Connect to remote peer as given service uri. + */ + void ConnectL(const TDesC8& aServiceName); + +private: // From CActive + void RunL(); + void DoCancel(); + +private: + // Constructor + CLlcpConnecterAO( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ); + // Second phase constructor + void ConstructL(); + +private: + enum TConnectionState + { + ENotConnected, + EConnecting, + EConnected + }; + /* + Pointer to MLlcpConnOrientedTransporter object. + */ + MLlcpConnOrientedTransporter& iConnection;//Not Own + CLlcpSocketType2& iSocket; + /* + State of LLCP connection object. + */ + TConnectionState iConnState; +}; +class CLlcpSenderAO : public CActive +{ +public: + static CLlcpSenderAO* NewL( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ); + ~CLlcpSenderAO(); + +public: + /* + Transfer given data to remote device. + */ + TInt Send( const TDesC8& aData ); + +private: // From CActive + void RunL(); + void DoCancel(); + +private: + // Constructor + CLlcpSenderAO( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ); + // Second phase constructor + void ConstructL(); +private: + void SendRestDataAndSwitchBuffer(RBuf8& aWorkingBuffer, RBuf8& aNextBuffer); + +private: + /* + Pointer to MLlcpConnOrientedTransporter object. + */ + MLlcpConnOrientedTransporter& iConnection; //Not Own + + CLlcpSocketType2& iSocket; + enum TSendBuffer + { + EBuffer0, + EBuffer1 + }; + /* + * Buffered data for sending data. + */ + RBuf8 iSendBuf0; + RBuf8 iSendBuf1; + TSendBuffer iCurrentBuffer; + TPtrC8 iCurrentSendPtr; + TInt iCurrentPos; + RBuf8 iCurrentSendBuf; +}; +class CLlcpReceiverAO : public CActive +{ +public: + static CLlcpReceiverAO* NewL( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ); + ~CLlcpReceiverAO(); + +public: + /* + Receive data from remote device. + */ + TInt StartReceiveDatagram(); + +private: // From CActive + void RunL(); + void DoCancel(); + +private: + // Constructor + CLlcpReceiverAO( MLlcpConnOrientedTransporter& aConnection, CLlcpSocketType2& aSocket ); + // Second phase constructor + void ConstructL(); +private: + + /* + * Pointer to MLlcpConnOrientedTransporter object. + */ + MLlcpConnOrientedTransporter& iConnection; //Not Own + + CLlcpSocketType2& iSocket; + /* + * Buffered data for receiving data. + */ + RBuf8 iReceiveBuf; +}; + +#endif /* LLCPSOCKETTYPE2_SYMBIAN_H_ */ diff --git a/src/nfc/symbian/nearfieldmanager_symbian.cpp b/src/nfc/symbian/nearfieldmanager_symbian.cpp new file mode 100644 index 00000000..c0d485b3 --- /dev/null +++ b/src/nfc/symbian/nearfieldmanager_symbian.cpp @@ -0,0 +1,388 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nearfieldmanager_symbian.h" +#include "nearfieldtargetfactory_symbian.h" +#include "../qnearfieldmanager_symbian_p.h" +#include "nearfieldutility_symbian.h" + +#include <ndefmessage.h> +#include "debug.h" + +/* + \class CNearFieldManager + \brief The CNearFieldManager class provides symbian backend implementation to access NFC service. + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 + \internal + + A Symbian implementation class to support symbian NFC backend. +*/ + +/* + Constructs a CNearFieldManager. +*/ +void CNearFieldManager::ConstructL() + { + BEGIN + User::LeaveIfError(iServer.Open()); + END + } + +/* + Start listening all type tags. +*/ +void CNearFieldManager::StartTargetDetectionL(const QList<QNearFieldTarget::Type> &aTargetTypes) + { + BEGIN + if (aTargetTypes.size() > 0) + { + if (!iNfcTagDiscovery) + { + iNfcTagDiscovery = CNfcTagDiscovery::NewL( iServer ); + User::LeaveIfError(iNfcTagDiscovery->AddTagConnectionListener( *this )); + } + else + { + iNfcTagDiscovery->RemoveTagSubscription(); + } + + if (!iTagSubscription) + { + iTagSubscription = CNfcTagSubscription::NewL(); + } + else + { + iTagSubscription->RemoveAllConnectionModes(); + } + for (int i = 0; i < aTargetTypes.size(); ++i) + { + switch(aTargetTypes[i]) + { + case QNearFieldTarget::NfcTagType1: + iTagSubscription->RemoveConnectionMode(TNfcConnectionInfo::ENfcType1); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfcType1 ); + break; + case QNearFieldTarget::NfcTagType2: + iTagSubscription->RemoveConnectionMode(TNfcConnectionInfo::ENfcType2); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfcType2 ); + break; + case QNearFieldTarget::NfcTagType3: + iTagSubscription->RemoveConnectionMode(TNfcConnectionInfo::ENfcType3); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfcType3 ); + break; + case QNearFieldTarget::NfcTagType4: + iTagSubscription->RemoveConnectionMode(TNfcConnectionInfo::ENfc14443P4); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfc14443P4 ); + break; + case QNearFieldTarget::MifareTag: + iTagSubscription->RemoveConnectionMode(TNfcConnectionInfo::ENfcMifareStd); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfcMifareStd ); + break; + case QNearFieldTarget::AnyTarget: + iTagSubscription->RemoveAllConnectionModes(); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfcType1 ); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfcType2 ); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfcType3 ); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfc14443P4 ); + iTagSubscription->AddConnectionModeL( TNfcConnectionInfo::ENfcMifareStd ); + if (!iLlcpProvider) + { + //create LLCP provider api + iLlcpProvider = CLlcpProvider::NewL( iServer ); + iLlcpProvider->AddLlcpLinkListenerL( *this ); + } + break; + case QNearFieldTarget::ProprietaryTag: + //No conterpart in symbian api + break; + case QNearFieldTarget::NfcForumDevice: + if (!iLlcpProvider) + { + //create LLCP provider api + iLlcpProvider = CLlcpProvider::NewL( iServer ); + iLlcpProvider->AddLlcpLinkListenerL( *this ); + } + break; + default: + break; + } + } + } + iNfcTagDiscovery->AddTagSubscriptionL( *iTagSubscription ); + END + } + +/* + Stop listening all type tags. +*/ +void CNearFieldManager::stopTargetDetection() + { + BEGIN + if (iNfcTagDiscovery) + { + iNfcTagDiscovery->RemoveTagConnectionListener(); + iNfcTagDiscovery->RemoveTagSubscription(); + + if (iTagSubscription) + { + delete iTagSubscription; + iTagSubscription = NULL; + } + delete iNfcTagDiscovery; + iNfcTagDiscovery = NULL; + } + if (iLlcpProvider) + { + iLlcpProvider->RemoveLlcpLinkListener(); + delete iLlcpProvider; + iLlcpProvider = NULL; + } + + END + } + +CNdefRecord::TNdefRecordTnf CNearFieldManager::QTnf2CTnf(const QNdefRecord::TypeNameFormat aQTnf) + { + CNdefRecord::TNdefRecordTnf ret = CNdefRecord::EEmpty; + switch(aQTnf) + { + case QNdefRecord::Empty: + break; + case QNdefRecord::NfcRtd: + ret = CNdefRecord::ENfcWellKnown; + break; + case QNdefRecord::Mime: + ret = CNdefRecord::EMime; + break; + case QNdefRecord::Uri: + ret = CNdefRecord::EUri; + break; + case QNdefRecord::ExternalRtd: + ret = CNdefRecord::ENfcExternal; + break; + case QNdefRecord::Unknown: + ret = CNdefRecord::EUnknown; + break; + default: + break; + } + return ret; + } + +/* + Register interested TNF NDEF message to NFC server. +*/ +TInt CNearFieldManager::AddNdefSubscription( const QNdefRecord::TypeNameFormat aTnf, + const QByteArray& aType ) + { + BEGIN + TInt err = KErrNone; + if ( !iNdefDiscovery ) + { + TRAP(err, iNdefDiscovery = CNdefDiscovery::NewL( iServer )); + if (err != KErrNone) + { + END + return err; + } + err = iNdefDiscovery->AddNdefMessageListener( *this ); + if (err != KErrNone) + { + END + return err; + } + + } + TPtrC8 type(QNFCNdefUtility::QByteArray2TPtrC8(aType)); + err = iNdefDiscovery->AddNdefSubscription( QTnf2CTnf(aTnf), type ); + END + return err; + } + +/* + Unregister interested TNF NDEF message to NFC server. +*/ +void CNearFieldManager::RemoveNdefSubscription( const QNdefRecord::TypeNameFormat aTnf, + const QByteArray& aType ) + { + BEGIN + if ( iNdefDiscovery ) + { + TPtrC8 type(QNFCNdefUtility::QByteArray2TPtrC8(aType)); + iNdefDiscovery->RemoveNdefSubscription( QTnf2CTnf(aTnf), type ); + } + END + } + +/* + Callback function when the tag found by NFC symbain services. +*/ +void CNearFieldManager::TagDetected( MNfcTag* aNfcTag ) + { + BEGIN + if (aNfcTag) + { + QNearFieldTarget* tag = TNearFieldTargetFactory::CreateTargetL(aNfcTag, iServer, &iCallback); + TInt error = KErrNone; + QT_TRYCATCH_ERROR(error, iCallback.targetFound(tag)); + Q_UNUSED(error);//just skip the error + } + END + } + +/* + Callback function when the tag lost event found by NFC symbain services. +*/ +void CNearFieldManager::TagLost() + { + BEGIN + TInt error = KErrNone; + QT_TRYCATCH_ERROR(error, iCallback.targetDisconnected());//just skip the error + Q_UNUSED(error);//just skip the error + END + } + +/* + Callback function when the LLCP peer found by NFC symbain services. +*/ +void CNearFieldManager::LlcpRemoteFound() + { + BEGIN + TInt error = KErrNone; + QNearFieldTarget* tag = NULL; + TRAP(error, tag = TNearFieldTargetFactory::CreateTargetL(NULL, iServer, &iCallback)); + if (error == KErrNone) + { + QT_TRYCATCH_ERROR(error, iCallback.targetFound(tag) ); + Q_UNUSED(error);//just skip the error + } + END + } + +/* + Callback function when the LLCP peer lost event found by NFC symbain services. +*/ +void CNearFieldManager::LlcpRemoteLost() + { + BEGIN + TInt error = KErrNone; + QT_TRYCATCH_ERROR(error, iCallback.targetDisconnected()); + Q_UNUSED(error);//just skip the error + END + } + +/* + Callback function when the registerd NDEF message found by NFC symbain services. +*/ +void CNearFieldManager::MessageDetected( CNdefMessage* aMessage ) + { + BEGIN + if ( aMessage ) + { + TInt error = KErrNone; + QNdefMessage msg; + TRAP(error, msg = QNFCNdefUtility::CNdefMsg2QNdefMsgL( *aMessage)); + if (error == KErrNone) + { + QT_TRYCATCH_ERROR(error, iCallback.invokeNdefMessageHandler(msg)); + Q_UNUSED(error);//just skip the error + } + delete aMessage; + } + END + } + +/* + New a CNearFieldManager instance. +*/ +CNearFieldManager::CNearFieldManager( QNearFieldManagerPrivateImpl& aCallback) + : iCallback(aCallback) + { + } + +/* + Create a new instance of this class. +*/ +CNearFieldManager* CNearFieldManager::NewL( QNearFieldManagerPrivateImpl& aCallback) + { + BEGIN + CNearFieldManager* self = new (ELeave) CNearFieldManager(aCallback); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + END + return self; + } + +/* + Destructor. +*/ +CNearFieldManager::~CNearFieldManager() + { + BEGIN + if ( iNfcTagDiscovery ) + { + iNfcTagDiscovery->RemoveTagConnectionListener(); + iNfcTagDiscovery->RemoveTagSubscription(); + } + + delete iTagSubscription; + delete iNfcTagDiscovery; + + if (iLlcpProvider) + { + iLlcpProvider->RemoveLlcpLinkListener(); + } + delete iLlcpProvider; + + if (iNdefDiscovery) + { + iNdefDiscovery->RemoveAllNdefSubscription(); + } + delete iNdefDiscovery; + + iServer.Close(); + END + } +//EOF diff --git a/src/nfc/symbian/nearfieldmanager_symbian.h b/src/nfc/symbian/nearfieldmanager_symbian.h new file mode 100644 index 00000000..82e05436 --- /dev/null +++ b/src/nfc/symbian/nearfieldmanager_symbian.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDMANAGER_SYMBIAN_H_ +#define QNEARFIELDMANAGER_SYMBIAN_H_ + +#include <nfcserver.h> +#include <nfctag.h> +#include <nfctagsubscription.h> +#include <nfcconnection.h> +#include <nfctype2connection.h> + +#include <nfctagdiscovery.h> +#include <nfctagconnectionlistener.h> +#include <nfcconnectioninfo.h> +#include <llcpprovider.h> // CLlcpProvider +#include <llcplinklistener.h> // MLlcpLinkListener + +#include <ndefmessagelistener.h> +#include <ndefdiscovery.h> + +#include "../qndefrecord.h" +#include <QList> +#include "../qnearfieldtarget.h" + +class QNearFieldManagerPrivateImpl; + +class CNearFieldManager : public CBase, + public MNfcTagConnectionListener, + public MLlcpLinkListener, + public MNdefMessageListener + { +public: + + static CNearFieldManager* NewL( QNearFieldManagerPrivateImpl& aCallback); + virtual ~CNearFieldManager(); + + void StartTargetDetectionL(const QList<QNearFieldTarget::Type> &aTargetTypes); + void stopTargetDetection(); + //for registerNdefMessageHandler ... api + TInt AddNdefSubscription( const QNdefRecord::TypeNameFormat aTnf, + const QByteArray& aType ); + void RemoveNdefSubscription( const QNdefRecord::TypeNameFormat aTnf, + const QByteArray& aType ); + +public: // From MNfcTagConnectionListener + + void TagDetected( MNfcTag* aNfcTag ); + void TagLost(); + +public: // From MLlcpLinkListener + + void LlcpRemoteFound(); + void LlcpRemoteLost(); + +public: // From MNdefMessageListener + + void MessageDetected( CNdefMessage* aMessage ); + +private: + + CNearFieldManager( QNearFieldManagerPrivateImpl& aCallback); + void ConstructL(); + CNdefRecord::TNdefRecordTnf QTnf2CTnf(const QNdefRecord::TypeNameFormat aQTnf); + //own + RNfcServer iServer; + //for Tag discovery + CNfcTagDiscovery* iNfcTagDiscovery; + CNfcTagSubscription* iTagSubscription; + //for LLCP discovery + CLlcpProvider* iLlcpProvider; + //for NDEF discovery + CNdefDiscovery* iNdefDiscovery; + //not own + QNearFieldManagerPrivateImpl& iCallback; + }; +#endif /* QNEARFIELDMANAGER_SYMBIAN_H_ */ diff --git a/src/nfc/symbian/nearfieldndeftarget_symbian.cpp b/src/nfc/symbian/nearfieldndeftarget_symbian.cpp new file mode 100644 index 00000000..0167462a --- /dev/null +++ b/src/nfc/symbian/nearfieldndeftarget_symbian.cpp @@ -0,0 +1,315 @@ +/**************************************************************************** + ** + ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the Qt Mobility Components. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ +#include <nfctype1connection.h> +#include <nfctype2connection.h> +#include <nfctype3connection.h> +#include <iso14443connection.h> +#include <ndefconnection.h> +#include <nfctag.h> +#include <qglobal.h> +#include "nearfieldtag_symbian.h" +#include "nearfieldndeftarget_symbian.h" +#include "nearfieldtagndefoperationcallback_symbian.h" +#include "debug.h" + +CNearFieldNdefTarget::CNearFieldNdefTarget(MNfcTag * aNfcTag, RNfcServer& aNfcServer) : iNfcTag(aNfcTag), + iNfcServer(aNfcServer), + iCurrentOperation(ENull) + { + } + +CNearFieldNdefTarget* CNearFieldNdefTarget::NewLC(MNfcTag * aNfcTag, RNfcServer& aNfcServer) + { + CNearFieldNdefTarget* self = new (ELeave) CNearFieldNdefTarget(aNfcTag, aNfcServer); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +void CNearFieldNdefTarget::ConstructL() + { + iNdefConnection = CNdefConnection::NewL(iNfcServer, *this); + } + +void CNearFieldNdefTarget::SetRealTarget(CNearFieldTag * aRealTarget) + { + iTagConnection = aRealTarget; + } + +CNearFieldNdefTarget::~CNearFieldNdefTarget() + { + BEGIN + // when connection is closed, cancel for each specific connection will be done. + if (iNdefConnection) + { + if (iNdefConnection->IsActivated()) + { + CloseConnection(); + } + delete iNdefConnection; + } + + // when Ndef target has a tag connection, iNfcTag ownership + // will transfer to tag connection. + if (iTagConnection) + { + delete iTagConnection; + } + else + { + delete iNfcTag; + } + END + } + +void CNearFieldNdefTarget::Cancel() + { + BEGIN + if (ERead == iCurrentOperation) + { + iNdefConnection->CancelRead(); + } + else if (EWrite == iCurrentOperation) + { + iNdefConnection->CancelWrite(); + } + + iCurrentOperation = ENull; + END + } + +CNearFieldTag * CNearFieldNdefTarget::CastToTag() + { + BEGIN + if (IsConnectionOpened()) + { + LOG("Ndef connection will be closed"); + CloseConnection(); + } + END + return iTagConnection ? iTagConnection->CastToTag() : reinterpret_cast<CNearFieldTag *>(0); + } + +CNearFieldNdefTarget * CNearFieldNdefTarget::CastToNdefTarget() + { + BEGIN + TInt error = KErrNone; + if (iTagConnection) + { + LOG("Check if Tag Connection is opened"); + if (iTagConnection->IsConnectionOpened()) + { + LOG("Close tag connection"); + iTagConnection->CloseConnection(); + } + } + + if (!IsConnectionOpened()) + { + LOG("Open ndef connection") + error = OpenConnection(); + LOG("error code is"<<error); + } + END + return (error == KErrNone) ? const_cast<CNearFieldNdefTarget *>(this) + : reinterpret_cast<CNearFieldNdefTarget *>(0); + } + +TInt CNearFieldNdefTarget::OpenConnection() + { + BEGIN + END + return iNfcTag->OpenConnection(*iNdefConnection); + } + +void CNearFieldNdefTarget::CloseConnection() + { + BEGIN + END + return iNfcTag->CloseConnection(*iNdefConnection); + } + +TBool CNearFieldNdefTarget::IsConnectionOpened() + { + BEGIN + TBool result = iNdefConnection->IsActivated(); + LOG(result); + END + return result; + } + +const TDesC8& CNearFieldNdefTarget::Uid() const + { + BEGIN + END + return iNfcTag->Uid(); + } + +void CNearFieldNdefTarget::ReadComplete( CNdefMessage* aMessage ) + { + BEGIN + if (iCallback) + { + TInt err = KErrNone; + if (iMessages) + { + err = iMessages->Append(aMessage); + LOG("append message, err = "<<err); + } + + TInt errIgnore = KErrNone; + QT_TRYCATCH_ERROR(errIgnore, iCallback->ReadComplete(err, iMessages)); + //TODO: consider it carefully + //iMessages = 0; + LOG("callback error is "<<errIgnore); + } + iCurrentOperation = ENull; + LOG(iCurrentOperation); + END + } + +void CNearFieldNdefTarget::WriteComplete() + { + BEGIN + if (iCallback) + { + TInt errIgnore = KErrNone; + QT_TRYCATCH_ERROR(errIgnore, iCallback->WriteComplete(KErrNone)); + LOG("callback error is "<<errIgnore); + } + iCurrentOperation = ENull; + LOG(iCurrentOperation); + END + } + +void CNearFieldNdefTarget::HandleError( TInt aError ) + { + BEGIN + if (iCallback) + { + LOG(iCurrentOperation); + + if (ERead == iCurrentOperation) + { + iCallback->ReadComplete(aError, iMessages); + } + else if (EWrite == iCurrentOperation) + { + iCallback->WriteComplete(aError); + } + //TODO: consider it carefully + //iMessages = 0; + } + iCurrentOperation = ENull; + END + } + +TInt CNearFieldNdefTarget::ndefMessages(RPointerArray<CNdefMessage>& aMessages) + { + BEGIN + TInt error = KErrNone; + LOG("iCurrentOperation = "<<iCurrentOperation); + if (iCurrentOperation != ENull) + { + error = KErrInUse; + } + else + { + if (!IsConnectionOpened()) + { + error = OpenConnection(); + LOG("Open connection, err = "<<error); + } + if (KErrNone == error) + { + LOG("begin to read message"); + iMessages = &aMessages; + error = iNdefConnection->ReadMessage(); + LOG("read message err = "<<error); + iCurrentOperation = (KErrNone == error) ? ERead : ENull; + } + } + END + return error; + } + +TInt CNearFieldNdefTarget::setNdefMessages(const RPointerArray<CNdefMessage>& aMessages) + { + BEGIN + TInt error = KErrNone; + CNdefMessage * message; + LOG("iCurrentOperation = "<<iCurrentOperation); + if (iCurrentOperation != ENull) + { + error = KErrInUse; + } + else + { + if (aMessages.Count() > 0) + { + LOG("message count > 0"); + // current only support single ndef message + message = aMessages[0]; + if (!IsConnectionOpened()) + { + error = OpenConnection(); + LOG("Open connection, err = "<<error); + } + if (KErrNone == error) + { + LOG("begin to write message"); + error = iNdefConnection->WriteMessage(*message); + LOG("write message err = "<<error); + iCurrentOperation = (KErrNone == error) ? EWrite : ENull; + } + } + } + END + return error; + } + +void CNearFieldNdefTarget::SetNdefOperationCallback(MNearFieldNdefOperationCallback * const aCallback) + { + BEGIN + iCallback = aCallback; + END + } + diff --git a/src/nfc/symbian/nearfieldndeftarget_symbian.h b/src/nfc/symbian/nearfieldndeftarget_symbian.h new file mode 100644 index 00000000..485e2516 --- /dev/null +++ b/src/nfc/symbian/nearfieldndeftarget_symbian.h @@ -0,0 +1,124 @@ +/**************************************************************************** + ** + ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the Qt Mobility Components. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#ifndef NEARFIELDNDEFTARGET_H +#define NEARFIELDNDEFTARGET_H + +#include <e32base.h> +#include <nfcserver.h> +#include <ndefconnection.h> +#include <e32cmn.h> +#include <ndefhandler.h> + +#include "debug.h" + +class CNearFieldTag; +class CNdefMessage; + +class CNdefConnection; +class MNfcTag; + +class MNearFieldNdefOperationCallback; + +class CNearFieldNdefTarget : public CBase, + public MNdefHandler + { + enum TOperation + { + ENull, + ERead, + EWrite + }; +public: + // Cancel and destroy + ~CNearFieldNdefTarget(); + + // Two-phased constructor. + static CNearFieldNdefTarget* NewLC(MNfcTag * aNfcTag, RNfcServer& aNfcServer); +public: // New functions + void SetRealTarget(CNearFieldTag * aRealTarget); + + // NdefAccess + TInt ndefMessages(RPointerArray<CNdefMessage>& aMessages); + TInt setNdefMessages(const RPointerArray<CNdefMessage>& aMessages); + void Cancel(); + +public: + CNearFieldTag * CastToTag(); + CNearFieldNdefTarget * CastToNdefTarget(); + + TInt OpenConnection(); + void CloseConnection(); + TBool IsConnectionOpened(); + const TDesC8& Uid() const; + void SetNdefOperationCallback(MNearFieldNdefOperationCallback * const aCallback); + +private: + // C++ constructor + CNearFieldNdefTarget(MNfcTag * aNfcTag, RNfcServer& aNfcServer); + + // Second-phase constructor + void ConstructL(); + +private: // From MNdefHandler + void ReadComplete( CNdefRecord* /*aRecord*/, CNdefRecord::TNdefMessagePart /*aPart*/ ){} + void ReadComplete( CNdefMessage* aMessage ); + void ReadComplete( const RPointerArray<CNdefMessage>& /*aMessages*/ ){} + void WriteComplete(); + void HandleError( TInt aError ); + +private: + // own + CNearFieldTag * iTagConnection; + CNdefConnection * iNdefConnection; + // own + MNfcTag * iNfcTag; + + RNfcServer& iNfcServer; + + TOperation iCurrentOperation; + + // Not own + MNearFieldNdefOperationCallback * iCallback; + RPointerArray<CNdefMessage> * iMessages; + }; + +#endif // NEARFIELDNDEFTARGET_H diff --git a/src/nfc/symbian/nearfieldtag_symbian.cpp b/src/nfc/symbian/nearfieldtag_symbian.cpp new file mode 100644 index 00000000..e6f9dbbe --- /dev/null +++ b/src/nfc/symbian/nearfieldtag_symbian.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <nfctag.h> +#include <qglobal.h> +#include <nfcconnection.h> +#include "nearfieldtag_symbian.h" +#include "nearfieldtagoperationcallback_symbian.h" +#include "debug.h" +/* + \class CNearFieldTag + \brief The CNearFieldTag class provides ways to access tag + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \internal + \since 5.0 +*/ + +CNearFieldTag::CNearFieldTag(MNfcTag * aNfcTag, RNfcServer& aNfcServer) : CActive(EPriorityStandard), + iNfcTag(aNfcTag), + iNfcServer(aNfcServer) + { + CActiveScheduler::Add(this); + } + +CNearFieldTag* CNearFieldTag::NewLC(MNfcTag * aNfcTag, RNfcServer& aNfcServer) + { + CNearFieldTag* self = new (ELeave) CNearFieldTag(aNfcTag, aNfcServer); + CleanupStack::PushL(self); + return self; + } + +CNearFieldTag::~CNearFieldTag() + { + Cancel(); + if (iTagConnection) + { + if(iTagConnection->IsActivated()) + { + CloseConnection(); + } + delete iTagConnection; + } + + delete iNfcTag; + } + +CNearFieldTag * CNearFieldTag::CastToTag() + { + BEGIN + TInt error = KErrNone; + + if (!IsConnectionOpened()) + { + error = OpenConnection(); + LOG("open connection, error is "<<error); + } + END + return (error == KErrNone) ? const_cast<CNearFieldTag *>(this) + : reinterpret_cast<CNearFieldTag *>(0); + } + +TInt CNearFieldTag::OpenConnection() + { + BEGIN + TInt error = iNfcTag->OpenConnection(*iTagConnection); + LOG(error); + END + return error; + } + +void CNearFieldTag::CloseConnection() + { + BEGIN + iNfcTag->CloseConnection(*iTagConnection); + END + } + +TBool CNearFieldTag::IsConnectionOpened() + { + BEGIN + LOG((int)iTagConnection); + LOG("check if connection is opened"); + TBool result = iTagConnection->IsActivated(); + LOG("result is "<<result); + END + return result; + } + +TInt CNearFieldTag::RawModeAccess(const TDesC8& aCommand, TDes8& aResponse, TTimeIntervalMicroSeconds32& aTimeout) + { + BEGIN + TInt error = KErrInUse; + if (!IsActive()) + { + LOG("AO is not active"); + // No ongoing request + if (IsConnectionOpened()) + { + LOG("Connection is open"); + error = KErrNone; + iTagConnection->RawModeAccess(iStatus, aCommand, aResponse, aTimeout); + SetActive(); + } + } + END + return error; + } + +void CNearFieldTag::DoCancel() + { + BEGIN + iTagConnection->CancelRawModeAccess(); + if (iCallback) + { + LOG("call back command complete with KErrCancel"); + TInt err; + QT_TRYCATCH_ERROR(err, iCallback->CommandComplete(KErrCancel)); + Q_UNUSED(err); + } + END + } + +void CNearFieldTag::RunL() + { + BEGIN + if (iCallback) + { + LOG("call back command complete with error"<<iStatus.Int()); + TInt err; + QT_TRYCATCH_ERROR(err, iCallback->CommandComplete(iStatus.Int())); + Q_UNUSED(err); + } + END + } + +void CNearFieldTag::SetTagOperationCallback(MNearFieldTagOperationCallback * const aCallback) + { + BEGIN + iCallback = aCallback; + END + } diff --git a/src/nfc/symbian/nearfieldtag_symbian.h b/src/nfc/symbian/nearfieldtag_symbian.h new file mode 100644 index 00000000..5b59f05a --- /dev/null +++ b/src/nfc/symbian/nearfieldtag_symbian.h @@ -0,0 +1,94 @@ +/**************************************************************************** + ** + ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the Qt Mobility Components. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#ifndef NEARFIELDTAG_SYMBIAN_H +#define NEARFIELDTAG_SYMBIAN_H +#include <nfcserver.h> +#include <e32base.h> +#include <iso14443connection.h> + +class MNfcTag; +class MNfcConnection; +class MNearFieldTagOperationCallback; + + +class CNearFieldTag : public CActive + { +public: + // Cancel and destroy + ~CNearFieldTag(); + + // Two-phased constructor. + static CNearFieldTag* NewLC(MNfcTag * aNfcTag, RNfcServer& aNfcServer); + +public: + CNearFieldTag * CastToTag(); + void SetConnection(MNfcConnection * aTagConnection) { iTagConnection = aTagConnection; } + + TInt OpenConnection(); + void CloseConnection(); + TBool IsConnectionOpened(); + + TInt RawModeAccess(const TDesC8& aCommand, TDes8& aResponse, TTimeIntervalMicroSeconds32& aTimeout); + + MNfcConnection * TagConnection() { return iTagConnection;} + + void SetTagOperationCallback(MNearFieldTagOperationCallback * const aCallback); + +private: + // C++ constructor + CNearFieldTag(MNfcTag * aNfcTag, RNfcServer& aNfcServer); + +private: + void RunL(); + void DoCancel(); + +private: + // own + MNfcConnection * iTagConnection; + MNfcTag * iNfcTag; + RNfcServer& iNfcServer; + // Not own + MNearFieldTagOperationCallback * iCallback; + TBool iIsTag4; + }; + +#endif // NEARFIELDTAG_SYMBIAN_H diff --git a/src/nfc/symbian/nearfieldtagasyncrequest_symbian.cpp b/src/nfc/symbian/nearfieldtagasyncrequest_symbian.cpp new file mode 100644 index 00000000..48dde301 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagasyncrequest_symbian.cpp @@ -0,0 +1,277 @@ +/**************************************************************************** + ** + ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the Qt Mobility Components. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ +#include "nearfieldtagasyncrequest_symbian.h" +#include "nearfieldutility_symbian.h" +#include "nearfieldtagimplcommon_symbian.h" +#include <e32std.h> +#include "debug.h" + +TInt MNearFieldTagAsyncRequest::TimeoutCallback(TAny * aObj) +{ + BEGIN + MNearFieldTagAsyncRequest * obj = static_cast<MNearFieldTagAsyncRequest *>(aObj); + obj->ProcessTimeout(); + END + return KErrNone; +} + +MNearFieldTagAsyncRequest::MNearFieldTagAsyncRequest(QNearFieldTagImplCommon& aOperator) : iOperator(aOperator) +{ + iWait = 0; + iTimer = 0; + iRequestIssued = EFalse; + iCurrentRequestResult = 0; + iSendSignal = true; + iRequestResult = 0; +} + +MNearFieldTagAsyncRequest::~MNearFieldTagAsyncRequest() +{ + BEGIN + if (iTimer) + { + LOG("delete timer"); + delete iTimer; + iTimer = 0; + } + + if (iWait) + { + if (iWait->IsStarted()) + { + iWait->AsyncStop(); + } + LOG("delete waiter"); + delete iWait; + } + END +} + +void MNearFieldTagAsyncRequest::SetRequestId(QNearFieldTarget::RequestId aId) +{ + BEGIN + iId = aId; + END +} + +QNearFieldTarget::RequestId MNearFieldTagAsyncRequest::RequestID() +{ + BEGIN + END + return iId; +} + +bool MNearFieldTagAsyncRequest::WaitRequestCompleted(int aMsecs) +{ + BEGIN + volatile bool result = false; + if (iWait) + { + if (iWait->IsStarted()) + { + LOG("waiter has already started"); + // the request is already waited, return false. + return false; + } + } + else + { + LOG("new a new waiter"); + iWait = new(ELeave) CActiveSchedulerWait(); + iCurrentRequestResult = &result; + } + + if (iTimer) + { + LOG("cancel previous timer"); + iTimer->Cancel(); + } + else + { + LOG("create a new timer"); + iTimer = CPeriodic::NewL(CActive::EPriorityStandard); + } + + iMsecs = aMsecs * 1000; + if (iRequestIssued) + { + // timer should be started when request is issued. + LOG("Start timer"); + TCallBack callback(MNearFieldTagAsyncRequest::TimeoutCallback, this); + iTimer->Start(iMsecs, iMsecs, callback); + } + LOG("Start waiter"); + iWait->Start(); + LOG("Waiting completed, "<<result); + END + return result; +} + +int MNearFieldTagAsyncRequest::WaitRequestCompletedNoSignal(int aMsecs) +{ + BEGIN + volatile int result = KErrNone; + iSendSignal = false; + iRequestResult = &result; + if (iWait) + { + if (iWait->IsStarted()) + { + LOG("waiter has already started"); + // the request is already waited, return false. + return KErrInUse; + } + } + else + { + LOG("new a new waiter"); + iWait = new(ELeave) CActiveSchedulerWait(); + iRequestResult = &result; + } + + if (iTimer) + { + LOG("cancel previous timer"); + iTimer->Cancel(); + } + else + { + LOG("create a new timer"); + iTimer = CPeriodic::NewL(CActive::EPriorityStandard); + } + + iMsecs = aMsecs * 1000; + if (iRequestIssued) + { + // timer should be started when request is issued. + LOG("Start timer"); + TCallBack callback(MNearFieldTagAsyncRequest::TimeoutCallback, this); + iTimer->Start(iMsecs, iMsecs, callback); + } + LOG("Start waiter"); + iWait->Start(); + LOG("Waiting completed, "<<result); + END + return result; +} + + +void MNearFieldTagAsyncRequest::ProcessResponse(TInt aError) +{ + BEGIN + LOG("Error is "<<aError); + + iOperator.IssueNextRequest(iId); + + HandleResponse(aError); + + if (iWait) + { + ProcessWaitRequestCompleted(aError); + } + else + { + ProcessEmitSignal(aError); + } + + LOG("remove the request from queue"); + iOperator.RemoveRequestFromQueue(iId); + LOG("delete the request"); + iRequestIssued = EFalse; + delete this; + END +} + +void MNearFieldTagAsyncRequest::ProcessWaitRequestCompleted(TInt aError) +{ + BEGIN + if (iSendSignal) + { + if (iCurrentRequestResult) + { + (*iCurrentRequestResult) = (KErrNone == aError); + } + + iCurrentRequestResult = 0; + if (iTimer) + { + LOG("cancel timer"); + delete iTimer; + iTimer = 0; + } + if (iWait) + { + if (iWait->IsStarted()) + { + LOG("async stop waiter"); + iWait->AsyncStop(); + } + } + ProcessEmitSignal(aError); + } + else + { + // just for internal waiting operation. + if (iRequestResult) + { + (*iRequestResult) = aError; + } + + iRequestResult = 0; + if (iTimer) + { + LOG("cancel timer"); + delete iTimer; + iTimer = 0; + } + if (iWait) + { + if (iWait->IsStarted()) + { + LOG("async stop waiter"); + iWait->AsyncStop(); + } + } + } + + END +} + diff --git a/src/nfc/symbian/nearfieldtagasyncrequest_symbian.h b/src/nfc/symbian/nearfieldtagasyncrequest_symbian.h new file mode 100644 index 00000000..cf5aa96b --- /dev/null +++ b/src/nfc/symbian/nearfieldtagasyncrequest_symbian.h @@ -0,0 +1,107 @@ +/**************************************************************************** + ** + ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the Qt Mobility Components. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#ifndef NEARFIELDTAGASYNCREQUEST_SYMBIAN_H +#define NEARFIELDTAGASYNCREQUEST_SYMBIAN_H + +#include <qnearfieldtarget.h> +#include <e32base.h> + +class QNearFieldTagImplCommon; + +class MNearFieldTagAsyncRequest + { +public: + enum TRequestType + { + ENdefRequest, + ETagCommandRequest, + ETagCommandsRequest, + ENull + }; + +public: + MNearFieldTagAsyncRequest(QNearFieldTagImplCommon& aOperator); + + virtual ~MNearFieldTagAsyncRequest(); + virtual void IssueRequest() = 0; + virtual void ProcessResponse(TInt aError); + + // inline to get fast speed since this function is used internally + // to convert async ndef request to sync. + virtual void ProcessTimeout() = 0; + + virtual void ProcessWaitRequestCompleted(TInt aError); + + // emit signal defined in QNearFieldTarget + virtual void ProcessEmitSignal(TInt aError) = 0; + + // should call iOperator->handleResponse(id, response) + virtual void HandleResponse(TInt aError) = 0; + + virtual TRequestType Type() = 0; + + virtual bool WaitRequestCompleted(int aMsec); + virtual int WaitRequestCompletedNoSignal(int aMsec); + + void SetRequestId(QNearFieldTarget::RequestId aId); + QNearFieldTarget::RequestId RequestID(); + static TInt TimeoutCallback(TAny * aObj); +protected: + // Current async request ID. + QNearFieldTarget::RequestId iId; + // Not own. + QNearFieldTagImplCommon& iOperator; + + // Own. + CActiveSchedulerWait * iWait; + // Own. + CPeriodic * iTimer; + TBool iRequestIssued; + + int iMsecs; + bool iSendSignal; + volatile int * iRequestResult; + + volatile bool * iCurrentRequestResult; + }; + +#endif // NEARFIELDTAGASYNCREQUEST_SYMBIAN_H diff --git a/src/nfc/symbian/nearfieldtagcommandrequest_symbian.cpp b/src/nfc/symbian/nearfieldtagcommandrequest_symbian.cpp new file mode 100644 index 00000000..79a9f0a8 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagcommandrequest_symbian.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "nearfieldtagcommandrequest_symbian.h" +#include "nearfieldutility_symbian.h" +#include "nearfieldtagimplcommon_symbian.h" +#include "debug.h" + +NearFieldTagCommandRequest::NearFieldTagCommandRequest(QNearFieldTagImplCommon& aOperator) : MNearFieldTagAsyncRequest(aOperator) +{ +} + +NearFieldTagCommandRequest::~NearFieldTagCommandRequest() +{ + BEGIN + if (iRequestIssued) + { + iOperator.DoCancelSendCommand(); + } + END +} + +void NearFieldTagCommandRequest::IssueRequest() +{ + BEGIN + + iOperator.DoSendCommand(iCommand, this); + iRequestIssued = ETrue; + if (iWait) + { + if (iWait->IsStarted()) + { + // start timer here + LOG("Start timer"); + TCallBack callback(MNearFieldTagAsyncRequest::TimeoutCallback, this); + iTimer->Start(iMsecs, iMsecs, callback); + } + } + + END +} + +bool NearFieldTagCommandRequest::IssueRequestNoDefer() +{ + BEGIN + iRequestIssued = iOperator.DoSendCommand(iCommand, this, false); + return iRequestIssued; +} + +void NearFieldTagCommandRequest::CommandComplete(TInt aError) +{ + BEGIN + iRequestIssued = EFalse; + ProcessResponse(HandlePassiveCommand(aError)); + END +} + + +void NearFieldTagCommandRequest::ProcessEmitSignal(TInt aError) +{ + BEGIN + LOG(aError); + if (aError != KErrNone) + { + iOperator.EmitError(aError, iId); + } + END +} + +void NearFieldTagCommandRequest::ProcessTimeout() +{ + if (iWait) + { + if (iWait->IsStarted()) + { + if (iRequestIssued) + { + iOperator.DoCancelSendCommand(); + iRequestIssued = EFalse; + } + ProcessResponse(HandlePassiveCommand(KErrTimedOut)); + } + } +} + +void NearFieldTagCommandRequest::HandleResponse(TInt aError) +{ + BEGIN + LOG(aError); + if (aError == KErrNone) + { + iOperator.HandleResponse(iId, iCommand, iRequestResponse, iSendSignal); + } + END +} + +TInt NearFieldTagCommandRequest::HandlePassiveCommand(TInt aError) +{ + BEGIN + TInt result = aError; + // check if the command is passive ack + if (iCommand.count() == 6) + { + // it may be the select sector packet 2 command for tag type 2 + if ((iCommand.at(1) == 0) && (iCommand.at(2) == 0) && (iCommand.at(3) == 0)) + { + result = KErrNone; + if (KErrTimedOut == aError) + { + iResponse->Append(0x0A); + } + else + { + iResponse->Append(0x05); + } + } + } + iRequestResponse = QNFCNdefUtility::TDesC2QByteArray(*iResponse); + END + return result; +} diff --git a/src/nfc/symbian/nearfieldtagcommandrequest_symbian.h b/src/nfc/symbian/nearfieldtagcommandrequest_symbian.h new file mode 100644 index 00000000..6ff06243 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagcommandrequest_symbian.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NEARFIELDTAGCOMMANDREQUEST_SYMBIAN_H +#define NEARFIELDTAGCOMMANDREQUEST_SYMBIAN_H + +#include "nearfieldtagasyncrequest_symbian.h" +#include "nearfieldtagoperationcallback_symbian.h" + +class NearFieldTagCommandRequest : public MNearFieldTagAsyncRequest, + public MNearFieldTagOperationCallback + { +public: + NearFieldTagCommandRequest(QNearFieldTagImplCommon& aOperator); + ~NearFieldTagCommandRequest(); + void IssueRequest(); + bool IssueRequestNoDefer(); + void ProcessTimeout(); + void ProcessEmitSignal(TInt aError); + void HandleResponse(TInt aError); + void SetInputCommand(QByteArray aCommand) { iCommand = aCommand; } + void SetResponseBuffer(RBuf8 * aResponse) { iResponse = aResponse; } + QString GetRequestCommand() { return iCommand; } + TRequestType Type() { return ETagCommandRequest; } +private: + void CommandComplete(TInt aError); + TInt HandlePassiveCommand(TInt aError); + QByteArray iCommand; + // Not own + RBuf8 * iResponse; + QByteArray iRequestResponse; + }; + +#endif diff --git a/src/nfc/symbian/nearfieldtagcommandsrequest_symbian.cpp b/src/nfc/symbian/nearfieldtagcommandsrequest_symbian.cpp new file mode 100644 index 00000000..5d3a3816 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagcommandsrequest_symbian.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "nearfieldtagcommandsrequest_symbian.h" +#include "nearfieldutility_symbian.h" +#include "nearfieldtagimplcommon_symbian.h" +#include "debug.h" + +NearFieldTagCommandsRequest::NearFieldTagCommandsRequest(QNearFieldTagImplCommon& aOperator) : MNearFieldTagAsyncRequest(aOperator) +{ + iCurrentCommand = 0; + iRequestCancelled = EFalse; +} + +NearFieldTagCommandsRequest::~NearFieldTagCommandsRequest() +{ + BEGIN + iRequestCancelled = ETrue; + if (iRequestIssued) + { + iOperator.DoCancelSendCommand(); + } + END +} + +void NearFieldTagCommandsRequest::IssueRequest() +{ + BEGIN + LOG("current command index = "<<iCurrentCommand); + LOG("commands count = "<<iCommands.count()); + iRequestIssued = ETrue; + if (iCurrentCommand < iCommands.count()) + { + if (iWait && (iCurrentCommand == 0)) + { + if (iWait->IsStarted() && !iTimer->IsActive()) + { + // start timer here + LOG("Start timer"); + TCallBack callback(MNearFieldTagAsyncRequest::TimeoutCallback, this); + iTimer->Start(iMsecs, iMsecs, callback); + } + } + iOperator.DoSendCommand(iCommands.at(iCurrentCommand), this); + ++iCurrentCommand; + } + END +} + +bool NearFieldTagCommandsRequest::IssueRequestNoDefer() +{ + BEGIN + if (iCommands.count() > 0) + { + iRequestIssued = iOperator.DoSendCommand(iCommands.at(0), this, false); + ++iCurrentCommand; + } + END + return iRequestIssued; +} + +void NearFieldTagCommandsRequest::ProcessResponse(TInt aError) +{ + BEGIN + LOG("error is "<<aError); + QByteArray result; + if (KErrNone == aError) + { + result = QNFCNdefUtility::TDesC2QByteArray(*iResponse); + LOG("result is "<<result); + LOG("clear the buffer"); + iResponse->Zero(); + iDecodedResponses.append(iOperator.decodeResponse(iCommands.at(iCurrentCommand - 1), result)); + } + else + { + // error occurs + LOG("error occurs, append QVariant() to rest list"); + for (--iCurrentCommand; iCurrentCommand < iCommands.count(); ++iCurrentCommand) + { + iDecodedResponses.append(QVariant()); + } + } + iRequestIssued = EFalse; + if (!iRequestCancelled && (iCurrentCommand < iCommands.count())) + { + LOG("issue another command in command list"); + IssueRequest(); + } + else + { + // all commands finished + LOG("all commands completed"); + MNearFieldTagAsyncRequest::ProcessResponse(aError); + } + END +} + +void NearFieldTagCommandsRequest::HandleResponse(TInt aError) +{ + BEGIN + iOperator.HandleResponse(iId, iDecodedResponses, aError); + END +} + +void NearFieldTagCommandsRequest::CommandComplete(TInt aError) +{ + BEGIN + ProcessResponse(HandlePassiveCommand(aError)); + END +} + +void NearFieldTagCommandsRequest::ProcessEmitSignal(TInt aError) +{ + BEGIN + LOG(aError); + if (aError != KErrNone) + { + iOperator.EmitError(aError, iId); + } + END +} + +void NearFieldTagCommandsRequest::ProcessTimeout() +{ + BEGIN + if (iWait) + { + if (iWait->IsStarted()) + { + if (iRequestIssued) + { + iOperator.DoCancelSendCommand(); + iRequestCancelled = ETrue; + iRequestIssued = EFalse; + } + LOG("wait timeout"); + ProcessResponse(HandlePassiveCommand(KErrTimedOut)); + } + } + END +} + +TInt NearFieldTagCommandsRequest::HandlePassiveCommand(TInt aError) +{ + BEGIN + TInt result = aError; + TInt index = (iCurrentCommand == 0) ? iCurrentCommand : (iCurrentCommand - 1); + QByteArray command = iCommands.at(index); + // check if the command is passive ack + if (command.count() == 6) + { + // it may be the select sector packet 2 command for tag type 2 + if ((command.at(1) == 0) && (command.at(2) == 0) && (command.at(3) == 0)) + { + iResponse->Zero(); + if (KErrTimedOut == aError) + { + result = KErrNone; + iResponse->Append(0x0A); + } + else + { + iResponse->Append(0x05); + } + } + } + END + return result; +} diff --git a/src/nfc/symbian/nearfieldtagcommandsrequest_symbian.h b/src/nfc/symbian/nearfieldtagcommandsrequest_symbian.h new file mode 100644 index 00000000..605d691f --- /dev/null +++ b/src/nfc/symbian/nearfieldtagcommandsrequest_symbian.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef NEARFIELDTAGCOMMANDSREQUEST_SYMBIAN_H +#define NEARFIELDTAGCOMMANDSREQUEST_SYMBIAN_H + +#include "nearfieldtagasyncrequest_symbian.h" +#include "nearfieldtagoperationcallback_symbian.h" +#include <QVariantList> + +class NearFieldTagCommandsRequest : public MNearFieldTagAsyncRequest, + public MNearFieldTagOperationCallback + { +public: + NearFieldTagCommandsRequest(QNearFieldTagImplCommon& aOperator); + ~NearFieldTagCommandsRequest(); + void IssueRequest(); + bool IssueRequestNoDefer(); + void ProcessResponse(TInt aError); + void ProcessEmitSignal(TInt aError); + void HandleResponse(TInt aError); + void ProcessTimeout(); + void SetInputCommands(QList<QByteArray> aCommands) { iCommands = aCommands; } + void SetResponseBuffer(RBuf8 * aResponse) { iResponse = aResponse; } + TRequestType Type() { return ETagCommandsRequest; } +private: + void CommandComplete(TInt aError); + TInt HandlePassiveCommand(TInt aError); + + QList<QByteArray> iCommands; + QVariantList iDecodedResponses; + // Not own + RBuf8 * iResponse; + int iCurrentCommand; + TBool iRequestCancelled; + }; +#endif diff --git a/src/nfc/symbian/nearfieldtagimpl_symbian.h b/src/nfc/symbian/nearfieldtagimpl_symbian.h new file mode 100644 index 00000000..00d2ec03 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagimpl_symbian.h @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNEARFIELDTAGIMPL_H +#define QNEARFIELDTAGIMPL_H + +#include "nearfieldtagimplcommon_symbian.h" +#include "debug.h" + +class QNearFieldTagType1Symbian; +class QNearFieldTagType2Symbian; +class QNearFieldTagType3Symbian; +class QNearFieldTagType4Symbian; + +template<typename TAGTYPE> +struct TagConstValue +{ + enum { MaxResponseSize = 4096, Timeout = 100 * 1000 }; +}; + +template<> +struct TagConstValue<QNearFieldTagType1Symbian> +{ + enum { MaxResponseSize = 131, Timeout = 5 * 1000 }; +}; + +template<> +struct TagConstValue<QNearFieldTagType2Symbian> +{ + enum { MaxResponseSize = 18, Timeout = 5 * 1000 }; +}; + +template<> +struct TagConstValue<QNearFieldTagType3Symbian> +{ + enum { MaxResponseSize = 256, Timeout = 500 * 1000 }; +}; + +template <typename TAGTYPE> +class QNearFieldTagImpl : public QNearFieldTagImplCommon +{ +public: // From MNearFieldTargetOperation + + void HandleResponse(const QNearFieldTarget::RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted); + void HandleResponse(const QNearFieldTarget::RequestId &id, const QVariantList& response, int error); + QVariant decodeResponse(const QByteArray& command, const QByteArray& response); + + void EmitNdefMessageRead(const QNdefMessage &message); + void EmitNdefMessagesWritten(); + void EmitRequestCompleted(const QNearFieldTarget::RequestId &id); + void EmitError(int error, const QNearFieldTarget::RequestId &id); + +public: + QNearFieldTagImpl(CNearFieldNdefTarget *tag); +}; + +template<typename TAGTYPE> +QNearFieldTagImpl<TAGTYPE>::QNearFieldTagImpl(CNearFieldNdefTarget *tag) : QNearFieldTagImplCommon(tag) +{ + TRAP_IGNORE(mResponse.CreateL(TagConstValue<TAGTYPE>::MaxResponseSize)); + mTimeout = TagConstValue<TAGTYPE>::Timeout; +} + +template<typename TAGTYPE> +void QNearFieldTagImpl<TAGTYPE>::HandleResponse(const QNearFieldTarget::RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted) +{ + BEGIN + TAGTYPE * tag = static_cast<TAGTYPE *>(this); + tag->handleTagOperationResponse(id, command, response, emitRequestCompleted); + END +} + +template<typename TAGTYPE> +void QNearFieldTagImpl<TAGTYPE>::HandleResponse(const QNearFieldTarget::RequestId &id, const QVariantList& response, int error) +{ + BEGIN + TAGTYPE * tag = static_cast<TAGTYPE *>(this); + tag->setResponseForRequest(id, response, (error == KErrNone)); + END +} + +template<typename TAGTYPE> +QVariant QNearFieldTagImpl<TAGTYPE>::decodeResponse(const QByteArray& command, const QByteArray& response) +{ + BEGIN + TAGTYPE * tag = static_cast<TAGTYPE *>(this); + END + return tag->decodeResponse(command, response); +} + +template<typename TAGTYPE> +void QNearFieldTagImpl<TAGTYPE>::EmitNdefMessageRead(const QNdefMessage &message) +{ + BEGIN + TAGTYPE * tag = static_cast<TAGTYPE *>(this); + int err; + QT_TRYCATCH_ERROR(err, emit tag->ndefMessageRead(message)); + Q_UNUSED(err); + END +} + +template<typename TAGTYPE> +void QNearFieldTagImpl<TAGTYPE>::EmitNdefMessagesWritten() +{ + BEGIN + TAGTYPE * tag = static_cast<TAGTYPE *>(this); + int err; + QT_TRYCATCH_ERROR(err, emit tag->ndefMessagesWritten()); + Q_UNUSED(err); + END +} + +template<typename TAGTYPE> +void QNearFieldTagImpl<TAGTYPE>::EmitRequestCompleted(const QNearFieldTarget::RequestId &id) +{ + BEGIN + TAGTYPE * tag = static_cast<TAGTYPE *>(this); + int err; + QT_TRYCATCH_ERROR(err, emit tag->requestCompleted(id)); + Q_UNUSED(err); + END +} + +template<typename TAGTYPE> +void QNearFieldTagImpl<TAGTYPE>::EmitError(int error, const QNearFieldTarget::RequestId &id) +{ + BEGIN + TAGTYPE * tag = static_cast<TAGTYPE *>(this); + + int err = KErrNone; + try { + QMetaObject::invokeMethod(tag, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, SymbianError2QtError(error)), + Q_ARG(QNearFieldTarget::RequestId, id)); + } catch (const std::exception &ex) { + err = qt_symbian_exception2Error(ex); + } + + Q_UNUSED(err); + END +} + +#endif // QNEARFIELDTAGIMPL_H diff --git a/src/nfc/symbian/nearfieldtagimplcommon_symbian.cpp b/src/nfc/symbian/nearfieldtagimplcommon_symbian.cpp new file mode 100644 index 00000000..bbfba7fc --- /dev/null +++ b/src/nfc/symbian/nearfieldtagimplcommon_symbian.cpp @@ -0,0 +1,596 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nearfieldtagimplcommon_symbian.h" + + +bool QNearFieldTagImplCommon::DoReadNdefMessages(MNearFieldNdefOperationCallback * const aCallback) +{ + BEGIN + int error = KErrGeneral; + CNearFieldNdefTarget * ndefTarget = mTag->CastToNdefTarget(); + if (ndefTarget) + { + LOG("switched to ndef connection"); + ndefTarget->SetNdefOperationCallback(aCallback); + mMessageList.Reset(); + error = ndefTarget->ndefMessages(mMessageList); + LOG("error code is"<<error); + } + + if (error != KErrNone) + { + aCallback->ReadComplete(error, 0); + } + END + return (error == KErrNone); +} + + +bool QNearFieldTagImplCommon::DoSetNdefMessages(const QList<QNdefMessage> &messages, MNearFieldNdefOperationCallback * const aCallback) +{ + BEGIN + int error = KErrGeneral; + CNearFieldNdefTarget * ndefTarget = mTag->CastToNdefTarget(); + + if (ndefTarget) + { + ndefTarget->SetNdefOperationCallback(aCallback); + if (ndefTarget) + { + mInputMessageList.ResetAndDestroy(); + TRAP( error, + for (int i = 0; i < messages.count(); ++i) + { + mInputMessageList.Append(QNFCNdefUtility::QNdefMsg2CNdefMsgL(messages.at(i))); + } + ) + + if (error == KErrNone) + { + ndefTarget->setNdefMessages(mInputMessageList); + } + } + } + if (error != KErrNone) + { + aCallback->WriteComplete(error); + } + END + return (error == KErrNone); +} + + +bool QNearFieldTagImplCommon::DoHasNdefMessages() +{ + BEGIN + + LOG("use async request to check ndef message"); + NearFieldTagNdefRequest * readNdefRequest = new NearFieldTagNdefRequest(*this); + + QNearFieldTarget::RequestId requestId; + + if (readNdefRequest) + { + readNdefRequest->SetRequestId(requestId); + readNdefRequest->SetNdefRequestType(NearFieldTagNdefRequest::EReadRequest); + + if (!_isProcessingRequest()) + { + // issue the request + LOG("the request will be issued at once"); + mCurrentRequest = readNdefRequest; + + mPendingRequestList.append(readNdefRequest); + readNdefRequest->IssueRequest(); + } + else + { + mPendingRequestList.append(readNdefRequest); + } + + readNdefRequest->WaitRequestCompletedNoSignal(5000); + if (mMessageList.Count() == 0) + { + END + return false; + } + else + { + mMessageList.Reset(); + END + return true; + } + } + else + { + LOG("unexpect error to create async request"); + END + return false; + } +} + + +bool QNearFieldTagImplCommon::DoSendCommand(const QByteArray& command, MNearFieldTagOperationCallback * const aCallback, bool deferred) +{ + BEGIN + int error = (mResponse.MaxLength() == 0) ? KErrGeneral : KErrNone; + + if ((KErrNone == error) && (command.count() > 0)) + { + CNearFieldTag * tag = mTag->CastToTag(); + + if (tag) + { + tag->SetTagOperationCallback(aCallback); + TPtrC8 cmd = QNFCNdefUtility::QByteArray2TPtrC8(command); + mResponse.Zero(); + error = tag->RawModeAccess(cmd, mResponse, mTimeout); + } + else + { + error = KErrGeneral; + } + } + else + { + if (deferred) + { + aCallback->CommandComplete(error); + } + } + END + return (error == KErrNone); +} + + +bool QNearFieldTagImplCommon::IssueNextRequest(QNearFieldTarget::RequestId aId) +{ + BEGIN + // find the request after current request + int index = mPendingRequestList.indexOf(mCurrentRequest); + LOG("index = "<<index); + if ((index < 0) || (index == mPendingRequestList.count() - 1)) + { + // no next request + mCurrentRequest = 0; + END + return false; + } + else + { + if (aId == mCurrentRequest->RequestID()) + { + mCurrentRequest = mPendingRequestList.at(index + 1); + mCurrentRequest->IssueRequest(); + } + else + { + LOG("re-entry happened"); + } + + END + return true; + } +} + + +void QNearFieldTagImplCommon::RemoveRequestFromQueue(QNearFieldTarget::RequestId aId) +{ + BEGIN + for(int i = 0; i < mPendingRequestList.count(); ++i) + { + MNearFieldTagAsyncRequest * request = mPendingRequestList.at(i); + if (request->RequestID() == aId) + { + LOG("remove request id"); + mPendingRequestList.removeAt(i); + break; + } + } + END +} + + +QNearFieldTarget::RequestId QNearFieldTagImplCommon::AllocateRequestId() +{ + BEGIN + QNearFieldTarget::RequestIdPrivate * p = new QNearFieldTarget::RequestIdPrivate; + QNearFieldTarget::RequestId id(p); + END + return id; +} + +QNearFieldTagImplCommon::QNearFieldTagImplCommon(CNearFieldNdefTarget *tag) : mTag(tag) +{ + mCurrentRequest = 0; +} + + +QNearFieldTagImplCommon::~QNearFieldTagImplCommon() +{ + BEGIN + LOG("pending request count is "<<mPendingRequestList.count()); + for (int i = 0; i < mPendingRequestList.count(); ++i) + { + delete mPendingRequestList[i]; + } + + mPendingRequestList.clear(); + mCurrentRequest = 0; + + delete mTag; + + mMessageList.Close(); + mInputMessageList.ResetAndDestroy(); + mInputMessageList.Close(); + + mResponse.Close(); + END +} + + +bool QNearFieldTagImplCommon::_hasNdefMessage() +{ + return DoHasNdefMessages(); +} + + +QNearFieldTarget::RequestId QNearFieldTagImplCommon::_ndefMessages() +{ + BEGIN + NearFieldTagNdefRequest * readNdefRequest = new NearFieldTagNdefRequest(*this); + QNearFieldTarget::RequestId requestId = AllocateRequestId(); + + if (readNdefRequest) + { + LOG("read ndef request created"); + readNdefRequest->SetRequestId(requestId); + readNdefRequest->SetNdefRequestType(NearFieldTagNdefRequest::EReadRequest); + + if (!_isProcessingRequest()) + { + LOG("the request will be issued at once"); + // issue the request + mCurrentRequest = readNdefRequest; + mPendingRequestList.append(readNdefRequest); + readNdefRequest->IssueRequest(); + } + else + { + mPendingRequestList.append(readNdefRequest); + } + } + else + { + EmitError(KErrNoMemory, requestId); + } + END + + return requestId; +} + + +QNearFieldTarget::RequestId QNearFieldTagImplCommon::_setNdefMessages(const QList<QNdefMessage> &messages) +{ + BEGIN + NearFieldTagNdefRequest * writeNdefRequest = new NearFieldTagNdefRequest(*this); + QNearFieldTarget::RequestId requestId = AllocateRequestId(); + + if (writeNdefRequest) + { + LOG("write ndef request created"); + writeNdefRequest->SetRequestId(requestId); + writeNdefRequest->SetNdefRequestType(NearFieldTagNdefRequest::EWriteRequest); + writeNdefRequest->SetInputNdefMessages(messages); + + if (!_isProcessingRequest()) + { + // issue the request + LOG("the request will be issued at once"); + mCurrentRequest = writeNdefRequest; + mPendingRequestList.append(writeNdefRequest); + writeNdefRequest->IssueRequest(); + } + else + { + mPendingRequestList.append(writeNdefRequest); + } + } + else + { + EmitError(KErrNoMemory, requestId); + } + END + + return requestId; +} + + +QNearFieldTarget::RequestId QNearFieldTagImplCommon::_sendCommand(const QByteArray &command) +{ + BEGIN + NearFieldTagCommandRequest * rawCommandRequest = new NearFieldTagCommandRequest(*this); + QNearFieldTarget::RequestId requestId = AllocateRequestId(); + + if (rawCommandRequest) + { + LOG("send command request created"); + rawCommandRequest->SetInputCommand(command); + rawCommandRequest->SetRequestId(requestId); + rawCommandRequest->SetResponseBuffer(&mResponse); + + if (!_isProcessingRequest()) + { + // issue the request + LOG("the request will be issued at once"); + mCurrentRequest = rawCommandRequest; + + if (rawCommandRequest->IssueRequestNoDefer()) + { + mPendingRequestList.append(rawCommandRequest); + } + else + { + END + return QNearFieldTarget::RequestId(); + } + } + else + { + mPendingRequestList.append(rawCommandRequest); + } + } + else + { + END + return QNearFieldTarget::RequestId(); + } + END + return requestId; +} + + +QNearFieldTarget::RequestId QNearFieldTagImplCommon::_sendCommands(const QList<QByteArray> &commands) +{ + BEGIN + NearFieldTagCommandsRequest * rawCommandsRequest = new NearFieldTagCommandsRequest(*this); + QNearFieldTarget::RequestId requestId = AllocateRequestId(); + + if (rawCommandsRequest) + { + LOG("send commands request created"); + rawCommandsRequest->SetInputCommands(commands); + rawCommandsRequest->SetRequestId(requestId); + rawCommandsRequest->SetResponseBuffer(&mResponse); + + if (!_isProcessingRequest()) + { + // issue the request + LOG("the request will be issued at once"); + mCurrentRequest = rawCommandsRequest; + + if (rawCommandsRequest->IssueRequestNoDefer()) + { + mPendingRequestList.append(rawCommandsRequest); + } + else + { + END + return QNearFieldTarget::RequestId(); + } + } + else + { + mPendingRequestList.append(rawCommandsRequest); + } + } + else + { + END + return QNearFieldTarget::RequestId(); + } + END + return requestId; +} + + +QByteArray QNearFieldTagImplCommon::_uid() const +{ + BEGIN + if (mUid.isEmpty()) + { + mUid = QNFCNdefUtility::TDesC2QByteArray(mTag->Uid()); + LOG(mUid); + } + END + return mUid; +} + + +bool QNearFieldTagImplCommon::_isProcessingRequest() const +{ + BEGIN + bool result = mPendingRequestList.count() > 0; + LOG(result); + END + return result; + +} + + +bool QNearFieldTagImplCommon::_waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs) +{ + BEGIN + int index = -1; + for (int i = 0; i < mPendingRequestList.count(); ++i) + { + if (id == mPendingRequestList.at(i)->RequestID()) + { + index = i; + break; + } + } + + if (index < 0) + { + // request ID is not in pending list. So maybe it is already completed. + END + return false; + } + + MNearFieldTagAsyncRequest * request = mPendingRequestList.at(index); + LOG("get the request from pending request list"); + END + return request->WaitRequestCompleted(msecs); +} + + +bool QNearFieldTagImplCommon::_waitForRequestCompletedNoSignal(const QNearFieldTarget::RequestId &id, int msecs) +{ + BEGIN + int index = -1; + for (int i = 0; i < mPendingRequestList.count(); ++i) + { + if (id == mPendingRequestList.at(i)->RequestID()) + { + index = i; + break; + } + } + + if (index < 0) + { + // request ID is not in pending list. So either it may not be issued, or has already completed + END + return false; + } + + MNearFieldTagAsyncRequest * request = mPendingRequestList.at(index); + LOG("get the request from pending request list"); + END + return (KErrNone == request->WaitRequestCompletedNoSignal(msecs)); +} + +void QNearFieldTagImplCommon::DoCancelSendCommand() +{ + BEGIN + CNearFieldTag * tag = mTag->CastToTag(); + if (tag) + { + LOG("Cancel raw command operation"); + tag->SetTagOperationCallback(0); + tag->Cancel(); + } + END +} + + +void QNearFieldTagImplCommon::DoCancelNdefAccess() +{ + BEGIN + CNearFieldNdefTarget * ndefTarget = mTag->CastToNdefTarget(); + if(ndefTarget) + { + LOG("Cancel ndef operation"); + ndefTarget->SetNdefOperationCallback(0); + ndefTarget->Cancel(); + } + END +} + + +QNearFieldTarget::Error QNearFieldTagImplCommon::SymbianError2QtError(int error) +{ + BEGIN + QNearFieldTarget::Error qtError = QNearFieldTarget::InvalidParametersError; + switch(error) + { + case KErrNone: + { + qtError = QNearFieldTarget::NoError; + break; + } + case KErrNotSupported: + { + qtError = QNearFieldTarget::UnsupportedError; + break; + } + case KErrTimedOut: + { + qtError = QNearFieldTarget::NoResponseError; + break; + } + case KErrAccessDenied: + case KErrEof: + case KErrServerTerminated: + { + if (mCurrentRequest) + { + if(mCurrentRequest->Type() == MNearFieldTagAsyncRequest::ENdefRequest) + { + NearFieldTagNdefRequest * req = static_cast<NearFieldTagNdefRequest *>(mCurrentRequest); + if (req->GetNdefRequestType() == NearFieldTagNdefRequest::EReadRequest) + { + qtError = QNearFieldTarget::NdefReadError; + } + else if (req->GetNdefRequestType() == NearFieldTagNdefRequest::EWriteRequest) + { + qtError = QNearFieldTarget::NdefWriteError; + } + } + } + break; + } + case KErrTooBig: + { + qtError = QNearFieldTarget::TargetOutOfRangeError; + break; + } + default: + { + break; + } + } + LOG(qtError); + END + return qtError; +} diff --git a/src/nfc/symbian/nearfieldtagimplcommon_symbian.h b/src/nfc/symbian/nearfieldtagimplcommon_symbian.h new file mode 100644 index 00000000..0d769863 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagimplcommon_symbian.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NEARFIELDTAGIMPLCOMMON_SYMBIAN_H +#define NEARFIELDTAGIMPLCOMMON_SYMBIAN_H + +#include <qnearfieldtarget.h> +#include <qnearfieldtarget_p.h> +#include "nearfieldtag_symbian.h" +#include "nearfieldndeftarget_symbian.h" +#include "nearfieldutility_symbian.h" +#include "nearfieldtagasyncrequest_symbian.h" + +#include "nearfieldtagoperationcallback_symbian.h" +#include "nearfieldtagndefoperationcallback_symbian.h" + +#include "nearfieldtagndefrequest_symbian.h" +#include "nearfieldtagcommandrequest_symbian.h" +#include "nearfieldtagcommandsrequest_symbian.h" + +class QNearFieldTagImplCommon +{ +public: + bool DoReadNdefMessages(MNearFieldNdefOperationCallback * const aCallback); + bool DoSetNdefMessages(const QList<QNdefMessage> &messages, MNearFieldNdefOperationCallback * const aCallback); + bool DoHasNdefMessages(); + bool DoSendCommand(const QByteArray& command, MNearFieldTagOperationCallback * const aCallback, bool deferred = true); + bool IssueNextRequest(QNearFieldTarget::RequestId aId); + void RemoveRequestFromQueue(QNearFieldTarget::RequestId aId); + QNearFieldTarget::RequestId AllocateRequestId(); + void DoCancelSendCommand(); + void DoCancelNdefAccess(); + QNearFieldTarget::Error SymbianError2QtError(int error); + + virtual void EmitNdefMessageRead(const QNdefMessage &message) = 0; + virtual void EmitNdefMessagesWritten() = 0; + virtual void EmitRequestCompleted(const QNearFieldTarget::RequestId &id) = 0; + virtual void EmitError(int error, const QNearFieldTarget::RequestId &id) = 0; + virtual void HandleResponse(const QNearFieldTarget::RequestId &id, const QByteArray &command, const QByteArray &response, bool emitRequestCompleted) = 0; + virtual void HandleResponse(const QNearFieldTarget::RequestId &id, const QVariantList& response, int error) = 0; + virtual QVariant decodeResponse(const QByteArray& command, const QByteArray& response) = 0; + +public: + QNearFieldTagImplCommon(CNearFieldNdefTarget *tag); + virtual ~QNearFieldTagImplCommon(); + +protected: + bool _hasNdefMessage(); + QNearFieldTarget::RequestId _ndefMessages(); + QNearFieldTarget::RequestId _setNdefMessages(const QList<QNdefMessage> &messages); + + void _setAccessMethods(const QNearFieldTarget::AccessMethods& accessMethods) + { + mAccessMethods = accessMethods; + } + + QNearFieldTarget::AccessMethods _accessMethods() const + { + return mAccessMethods; + } + + QNearFieldTarget::RequestId _sendCommand(const QByteArray &command); + QNearFieldTarget::RequestId _sendCommands(const QList<QByteArray> &command); + bool _waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs = 5000); + bool _waitForRequestCompletedNoSignal(const QNearFieldTarget::RequestId &id, int msecs = 5000); + + QByteArray _uid() const; + + bool _isProcessingRequest() const; + +protected: + CNearFieldNdefTarget * mTag; + QNearFieldTarget::AccessMethods mAccessMethods; + mutable QByteArray mUid; + RPointerArray<CNdefMessage> mMessageList; + RBuf8 mResponse; + + QList<MNearFieldTagAsyncRequest *> mPendingRequestList; + MNearFieldTagAsyncRequest * mCurrentRequest; + + TTimeIntervalMicroSeconds32 mTimeout; + RPointerArray<CNdefMessage> mInputMessageList; +}; + +#endif diff --git a/src/nfc/symbian/nearfieldtagndefoperationcallback_symbian.h b/src/nfc/symbian/nearfieldtagndefoperationcallback_symbian.h new file mode 100644 index 00000000..594d4396 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagndefoperationcallback_symbian.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NEARFIELDNDEFOPERATIONCALLBACK_H +#define NEARFIELDNDEFOPERATIONCALLBACK_H + +#include <e32cmn.h> +#include <ndefmessage.h> +class MNearFieldNdefOperationCallback + { +public: + virtual void ReadComplete(TInt aError, RPointerArray<CNdefMessage> * aMessages) = 0; + virtual void WriteComplete(TInt aError) = 0; + }; + +#endif diff --git a/src/nfc/symbian/nearfieldtagndefrequest_symbian.cpp b/src/nfc/symbian/nearfieldtagndefrequest_symbian.cpp new file mode 100644 index 00000000..5ac41b2c --- /dev/null +++ b/src/nfc/symbian/nearfieldtagndefrequest_symbian.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nearfieldtagndefrequest_symbian.h" +#include "nearfieldutility_symbian.h" +#include "nearfieldtagimplcommon_symbian.h" +#include "debug.h" + +NearFieldTagNdefRequest::NearFieldTagNdefRequest(QNearFieldTagImplCommon& aOperator) : MNearFieldTagAsyncRequest(aOperator) +{ +} + +NearFieldTagNdefRequest::~NearFieldTagNdefRequest() +{ + BEGIN + if (iRequestIssued) + { + iOperator.DoCancelNdefAccess(); + } + END +} + +void NearFieldTagNdefRequest::IssueRequest() +{ + BEGIN + + iRequestIssued = ETrue; + LOG(iType); + switch(iType) + { + case EReadRequest: + { + iOperator.DoReadNdefMessages(this); + break; + } + case EWriteRequest: + { + iOperator.DoSetNdefMessages(iMessages, this); + break; + } + default: + { + iRequestIssued = EFalse; + break; + } + } + + END +} + +void NearFieldTagNdefRequest::ReadComplete(TInt aError, RPointerArray<CNdefMessage> * aMessage) +{ + BEGIN + LOG(aError); + iRequestIssued = EFalse; + TRAP_IGNORE( + if (aMessage != 0) + { + for(int i = 0; i < aMessage->Count(); ++i) + { + QNdefMessage message = QNFCNdefUtility::CNdefMsg2QNdefMsgL(*(*aMessage)[i]); + iReadMessages.append(message); + } + } + else + { + iReadMessages.clear(); + } + ) // TRAP end + ProcessResponse(aError); + END +} + +void NearFieldTagNdefRequest::WriteComplete(TInt aError) +{ + BEGIN + iRequestIssued = EFalse; + ProcessResponse(aError); + END +} + +void NearFieldTagNdefRequest::ProcessEmitSignal(TInt aError) +{ + BEGIN + LOG("error code is "<<aError<<" request type is "<<iType); + if (aError != KErrNone) + { + iOperator.EmitError(aError, iId); + } + else + { + if (EReadRequest == iType) + { + // since there is no error, iReadMessages can't be NULL. + + LOG("message count is "<<iReadMessages.count()); + for(int i = 0; i < iReadMessages.count(); ++i) + { + LOG("emit signal ndef message read"); + iOperator.EmitNdefMessageRead(iReadMessages.at(i)); + } + iOperator.EmitRequestCompleted(iId); + } + else if (EWriteRequest == iType) + { + iOperator.EmitNdefMessagesWritten(); + //iOperator.EmitRequestCompleted(iId); + } + } + END +} + +void NearFieldTagNdefRequest::ProcessTimeout() +{ + if (iWait) + { + if (iWait->IsStarted()) + { + if (iRequestIssued) + { + iOperator.DoCancelNdefAccess(); + iRequestIssued = EFalse; + } + ProcessResponse(KErrTimedOut); + } + } +} + +void NearFieldTagNdefRequest::HandleResponse(TInt /*aError*/) +{ + BEGIN + END +} diff --git a/src/nfc/symbian/nearfieldtagndefrequest_symbian.h b/src/nfc/symbian/nearfieldtagndefrequest_symbian.h new file mode 100644 index 00000000..f55829e5 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagndefrequest_symbian.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef NEARFIELDTAGNDEFREQUEST_SYMBIAN_H +#define NEARFIELDTAGNDEFREQUEST_SYMBIAN_H + +#include "nearfieldtagasyncrequest_symbian.h" +#include "nearfieldtagndefoperationcallback_symbian.h" + +class NearFieldTagNdefRequest : public MNearFieldTagAsyncRequest, + public MNearFieldNdefOperationCallback + { +public: + enum TNdefRequestType + { + EReadRequest, + EWriteRequest, + ECheckRequest + }; +public: + NearFieldTagNdefRequest(QNearFieldTagImplCommon& aOperator); + ~NearFieldTagNdefRequest(); + void IssueRequest(); + void ProcessEmitSignal(TInt aError); + void ProcessTimeout(); + void HandleResponse(TInt aError); + void SetNdefRequestType(TNdefRequestType aType) { iType = aType; } + void SetInputNdefMessages(QList<QNdefMessage> aMessages) { iMessages = aMessages; } + TNdefRequestType GetNdefRequestType() { return iType; } + TRequestType Type() { return ENdefRequest; } + +private: + void ReadComplete(TInt aError, RPointerArray<CNdefMessage> * aMessages); + void WriteComplete(TInt aError); + +private: + TNdefRequestType iType; + QList<QNdefMessage> iMessages; + + QList<QNdefMessage> iReadMessages; + }; +#endif diff --git a/src/nfc/symbian/nearfieldtagoperationcallback_symbian.h b/src/nfc/symbian/nearfieldtagoperationcallback_symbian.h new file mode 100644 index 00000000..f80da9c5 --- /dev/null +++ b/src/nfc/symbian/nearfieldtagoperationcallback_symbian.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NEARFIELDTAGOPERATIONCALLBACK_H +#define NEARFIELDTAGOPERATIONCALLBACK_H + +class MNearFieldTagOperationCallback + { +public: + virtual void CommandComplete(TInt aError) = 0; + }; + +#endif diff --git a/src/nfc/symbian/nearfieldtargetfactory_symbian.cpp b/src/nfc/symbian/nearfieldtargetfactory_symbian.cpp new file mode 100644 index 00000000..03a032a9 --- /dev/null +++ b/src/nfc/symbian/nearfieldtargetfactory_symbian.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nearfieldtargetfactory_symbian.h" +#include <nfcserver.h> +#include <nfctag.h> +#include <nfctype1connection.h> +#include <nfctype2connection.h> +#include <nfctype3connection.h> +#include <iso14443connection.h> +#include <mifareclassicconnection.h> +#include "qnearfieldtagtype1_symbian_p.h" +#include "qnearfieldtagtype2_symbian_p.h" +#include "qnearfieldtagtype3_symbian_p.h" +#include "qnearfieldtagtype4_symbian_p.h" +#include "qnearfieldtagmifare_symbian_p.h" +#include "qnearfieldllcpdevice_symbian_p.h" +/* + \class TNearFieldTargetFactory + \brief The TNearFieldTargetFactory class creates detected target instance according + to the input tag information + + \ingroup connectivity-nfc + \inmodule QtConnectivity + \since 5.0 +*/ + +/* + Create tag type instance according to the tag information in \a aNfcTag and assign + the \a aParent as target's parent. +*/ +template <typename CTAGCONNECTION, typename QTAGTYPE> +QNearFieldTarget * TNearFieldTargetFactory::CreateTagTypeL(MNfcTag * aNfcTag, RNfcServer& aNfcServer, QObject * aParent) +{ + BEGIN + // ownership of aNfcTag transferred. + CTAGCONNECTION * connection = CTAGCONNECTION::NewLC(aNfcServer); + CNearFieldTag * tagType = CNearFieldTag::NewLC(aNfcTag, aNfcServer); + tagType->SetConnection(connection); + QTAGTYPE * tag= new(ELeave)QTAGTYPE(WrapNdefAccessL(aNfcTag, aNfcServer, tagType), aParent); + // walk around, symbian discovery API can't know if tag has Ndef Connection mode when detected + tag->setAccessMethods(ConnectionMode2AccessMethods(aNfcTag)|QNearFieldTarget::NdefAccess); + CleanupStack::Pop(tagType); + CleanupStack::Pop(connection); + END + return tag; +} + +/* + Create target instance according to the tag information in \a aNfcTag and assign + the \a aParent as target's parent. +*/ + +QNearFieldTarget * TNearFieldTargetFactory::CreateTargetL(MNfcTag * aNfcTag, RNfcServer& aNfcServer, QObject * aParent) + { + BEGIN + QNearFieldTarget * target = 0; + if (!aNfcTag) + { + LOG("llcp device created"); + target = new (ELeave)QNearFieldLlcpDeviceSymbian(aNfcServer, aParent); + } + else if(aNfcTag->HasConnectionMode(TNfcConnectionInfo::ENfcType1)) + { + LOG("tag type 1 created"); + target = CreateTagTypeL<CNfcType1Connection, QNearFieldTagType1Symbian>(aNfcTag, aNfcServer, aParent); + } + else if (aNfcTag->HasConnectionMode(TNfcConnectionInfo::ENfcType2)) + { + LOG("tag type 2 created"); + target = CreateTagTypeL<CNfcType2Connection, QNearFieldTagType2Symbian>(aNfcTag, aNfcServer, aParent); + } + else if (aNfcTag->HasConnectionMode(TNfcConnectionInfo::ENfcType3)) + { + LOG("tag type 3 created"); + target = CreateTagTypeL<CNfcType3Connection, QNearFieldTagType3Symbian>(aNfcTag, aNfcServer, aParent); + } + else if (aNfcTag->HasConnectionMode(TNfcConnectionInfo::ENfc14443P4)) + { + LOG("tag type 4 created"); + target = CreateTagTypeL<CIso14443Connection, QNearFieldTagType4Symbian>(aNfcTag, aNfcServer, aParent); + } + else if (aNfcTag->HasConnectionMode(TNfcConnectionInfo::ENfcMifareStd)) + { + LOG("tag type mifare created"); + target = CreateTagTypeL<CMifareClassicConnection, QNearFieldTagMifareSymbian>(aNfcTag, aNfcServer, aParent); + } + END + return target; + } + +CNearFieldNdefTarget * TNearFieldTargetFactory::WrapNdefAccessL(MNfcTag * aNfcTag, RNfcServer& aNfcServer, CNearFieldTag * aTarget) + { + BEGIN + // walk around, symbian discovery API can't know if tag has Ndef Connection mode when detected + + LOG("Wrap NDEF Access to the tag"); + + CNearFieldNdefTarget * ndefTarget = CNearFieldNdefTarget::NewLC(aNfcTag, aNfcServer); + ndefTarget->SetRealTarget(aTarget); + CleanupStack::Pop(ndefTarget); + END + return ndefTarget; + } + +QNearFieldTarget::AccessMethods TNearFieldTargetFactory::ConnectionMode2AccessMethods(MNfcTag * aNfcTag) + { + BEGIN + QNearFieldTarget::AccessMethods accessMethod; + if (aNfcTag->HasConnectionMode(TNfcConnectionInfo::ENdefConnection)) + { + LOG("the tag has NDefConnection"); + accessMethod |= QNearFieldTarget::NdefAccess; + } + if (!aNfcTag->HasConnectionMode(TNfcConnectionInfo::ENfcUnknownConnectionMode)) + { + LOG("the tag has tag specified access"); + accessMethod |= QNearFieldTarget::TagTypeSpecificAccess; + } + END + return accessMethod; + } diff --git a/src/nfc/symbian/nearfieldtargetfactory_symbian.h b/src/nfc/symbian/nearfieldtargetfactory_symbian.h new file mode 100644 index 00000000..2795d9c7 --- /dev/null +++ b/src/nfc/symbian/nearfieldtargetfactory_symbian.h @@ -0,0 +1,66 @@ +/**************************************************************************** + ** + ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the Qt Mobility Components. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** GNU Lesser General Public License Usage + ** This file may be used under the terms of the GNU Lesser General Public + ** License version 2.1 as published by the Free Software Foundation and + ** appearing in the file LICENSE.LGPL included in the packaging of this + ** file. Please review the following information to ensure the GNU Lesser + ** General Public License version 2.1 requirements will be met: + ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Nokia gives you certain additional + ** rights. These rights are described in the Nokia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU General + ** Public License version 3.0 as published by the Free Software Foundation + ** and appearing in the file LICENSE.GPL included in the packaging of this + ** file. Please review the following information to ensure the GNU General + ** Public License version 3.0 requirements will be met: + ** http://www.gnu.org/copyleft/gpl.html. + ** + ** Other Usage + ** Alternatively, this file may be used in accordance with the terms and + ** conditions contained in a signed written agreement between you and Nokia. + ** + ** + ** + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#ifndef NEARFIELDTARGETFACTORY_H_ +#define NEARFIELDTARGETFACTORY_H_ + +#include <qnearfieldtarget.h> +#include "nearfieldndeftarget_symbian.h" +#include "nearfieldtag_symbian.h" +#include "debug.h" + +class MNfcTag; +class RNfcServer; + +class TNearFieldTargetFactory + { +public: + static QNearFieldTarget * CreateTargetL(MNfcTag * aNfcTag, RNfcServer& aNfcServer, QObject * aParent); +private: + static CNearFieldNdefTarget * WrapNdefAccessL(MNfcTag * aNfcTag, RNfcServer& aNfcServer, CNearFieldTag * aTarget); + static QNearFieldTarget::AccessMethods ConnectionMode2AccessMethods(MNfcTag * aNfcTag); + + template <typename CTAGCONNECTION, typename QTAGTYPE> + static QNearFieldTarget * CreateTagTypeL(MNfcTag * aNfcTag, RNfcServer& aNfcServer, QObject * aParent); + }; + + +#endif /* NEARFIELDTARGETFACTORY_H */ diff --git a/src/nfc/symbian/nearfieldutility_symbian.cpp b/src/nfc/symbian/nearfieldutility_symbian.cpp new file mode 100644 index 00000000..44a0554d --- /dev/null +++ b/src/nfc/symbian/nearfieldutility_symbian.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <ndefmessage.h> +#include <QtCore/QList> +#include <e32base.h> +#include "../qndefmessage.h" +#include "nearfieldutility_symbian.h" +#include "debug.h" + +CNdefMessage* QNFCNdefUtility::QNdefMsg2CNdefMsgL( const QNdefMessage& msg ) + { + QByteArray payload = msg.toByteArray(); + CNdefMessage* cmsg = CNdefMessage::NewL(); + TPtrC8 rawData(reinterpret_cast<const TUint8*>(payload.constData()), payload.size()); + cmsg->ImportRawDataL(rawData, 0); + return cmsg; + } + + +QNdefMessage QNFCNdefUtility::CNdefMsg2QNdefMsgL( const CNdefMessage& msg ) + { + BEGIN + QNdefMessage result; + LOG("CNdefMessage size is "<<msg.SizeL()); + HBufC8* newBuf = HBufC8::NewL(msg.SizeL()); + RBuf8 buf; + buf.Assign(newBuf); + buf.CleanupClosePushL(); + LOG("export msg to raw data"); + msg.ExportRawDataL(buf,0); + LOG("import raw data to msg"); + QByteArray qtArray; + qtArray.append(reinterpret_cast<const char*>(newBuf->Ptr()),newBuf->Size()); + result = QNdefMessage::fromByteArray(qtArray); + CleanupStack::PopAndDestroy(&buf); + END + return result; + } + +TPtrC8 QNFCNdefUtility::QByteArray2TPtrC8(const QByteArray& qbytearray) + { + TPtrC8 ptr(reinterpret_cast<const TUint8*>(qbytearray.constData()), qbytearray.size()); + return ptr; + } + +QByteArray QNFCNdefUtility::TDesC2QByteArray( const TDesC8& des) + { + QByteArray result; + for(int i = 0; i < des.Length(); ++i) + { + result.append(des[i]); + } + return result; + } + + +HBufC8* QNFCNdefUtility::QString2HBufC8L(const QString& qstring) + { + TPtrC wide(static_cast<const TUint16*>(qstring.utf16()),qstring.length()); + HBufC8* newBuf = HBufC8::NewL(wide.Length()); + TPtr8 des = newBuf->Des(); + des.Copy(wide); + return newBuf; + } + +QString QNFCNdefUtility::TDesC82QStringL(const TDesC8& aDescriptor) + { + HBufC* newBuf = NULL; + QT_TRAP_THROWING(newBuf = HBufC::NewL(aDescriptor.Length())); + TPtr des = newBuf->Des(); + des.Copy(aDescriptor); + QString ret = QString::fromUtf16(newBuf->Ptr(),newBuf->Length()); + delete newBuf; + return ret; + } + +// timer implementation +CLlcpTimer* CLlcpTimer::NewL(CActiveSchedulerWait & aWait) + { + BEGIN + CLlcpTimer* self = new (ELeave) CLlcpTimer(aWait); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + END + return self; + } + +/** +Destructor. +*/ +CLlcpTimer::~CLlcpTimer() + { + BEGIN + Cancel(); + END + } + +/** +Starts the shutdown timer. +*/ +void CLlcpTimer::Start(TInt aMSecs) + { + BEGIN + const TUint KDelay = (1000 * aMSecs); + After(KDelay); + END + } + +void CLlcpTimer::RunL() + { + BEGIN + if (iWait.IsStarted()) + { + iWait.AsyncStop(); + } + END + } + +/** +Constructor +*/ +CLlcpTimer::CLlcpTimer(CActiveSchedulerWait & aWait) : + CTimer(EPriorityNormal), + iWait(aWait) + { + } + +/** +Second phase constructor. +*/ +void CLlcpTimer::ConstructL() + { + BEGIN + CTimer::ConstructL(); + CActiveScheduler::Add(this); + END + } + + diff --git a/src/nfc/symbian/nearfieldutility_symbian.h b/src/nfc/symbian/nearfieldutility_symbian.h new file mode 100644 index 00000000..de526f03 --- /dev/null +++ b/src/nfc/symbian/nearfieldutility_symbian.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNFCNDEFUTILITY_SYMBIAN_H_ +#define QNFCNDEFUTILITY_SYMBIAN_H_ +#include <qndefmessage.h> +#include <e32base.h> + +class CNdefMessage; + +class CLlcpTimer : public CTimer + { +public: + + static CLlcpTimer* NewL(CActiveSchedulerWait & aWait); + virtual ~CLlcpTimer(); + + void Start(TInt aMSecs); + +private: // From CTimer + + void RunL(); + +private: + + CLlcpTimer(CActiveSchedulerWait & aWait); + void ConstructL(); + +private: + + CActiveSchedulerWait& iWait; //not own + }; + +class QNdefMessage; +class QNFCNdefUtility +{ +public: + + /** + * Maps between CNdefMessage and QNdefMessage + * + */ + static CNdefMessage* QNdefMsg2CNdefMsgL( const QNdefMessage& msg ); + static QNdefMessage CNdefMsg2QNdefMsgL( const CNdefMessage& msg ); + + static TPtrC8 QByteArray2TPtrC8(const QByteArray& qbytearray); + static QByteArray TDesC2QByteArray( const TDesC8& des); + + static HBufC8* QString2HBufC8L(const QString& qstring); + static QString TDesC82QStringL(const TDesC8&); + +}; + +#endif /* QNFCNDEFUTILITY_SYMBIAN_H_ */ diff --git a/src/nfc/targetemulator.cpp b/src/nfc/targetemulator.cpp new file mode 100644 index 00000000..7d77aa17 --- /dev/null +++ b/src/nfc/targetemulator.cpp @@ -0,0 +1,382 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "targetemulator_p.h" + +#include <QtCore/QSettings> +#include <QtCore/QDateTime> + +#include <QtCore/QDebug> + +// Implementation of qNfcChecksum +#include "checksum_p.h" + +TagBase::TagBase() +: lastAccess(0) +{ +} + +TagBase::~TagBase() +{ +} + +static inline quint8 blockByteToAddress(quint8 block, quint8 byte) +{ + return ((block & 0x0f) << 3) | (byte & 0x07); +} + +NfcTagType1::NfcTagType1() +: hr0(0x11), hr1(0x00), memory(120, '\0') +{ + // Locked blocks + memory[(0x0e << 3) | 0x00] = 0x01; + memory[(0x0e << 3) | 0x01] = 0x60; +} + +void NfcTagType1::load(QSettings *settings) +{ + settings->beginGroup(QLatin1String("TagType1")); + + hr0 = settings->value(QLatin1String("HR0"), 0x11).toUInt(); + + if (!(hr0 & 0x10)) { + settings->endGroup(); + return; + } + + hr1 = settings->value(QLatin1String("HR1"), 0x00).toUInt(); + + memory = settings->value(QLatin1String("Data")).toByteArray(); + + //quint8 nmn = memory.at(8); + + quint8 vno = memory.at(9); + if (vno != 0x10) + qWarning("Only NFC TagType1 v1.0 behavior is supported."); + + quint8 tms = memory.at(10); + if (memory.length() != 8 * (tms + 1)) + qWarning("Static memory size does not match TMS value."); + + quint8 rwa = memory.at(11); + switch (rwa >> 4) { + case 0: + // Unrestricted read access tag + break; + default: + // tag with unknown read attributes + ; + } + + switch (rwa & 0x0f) { + case 0: + // Unrestricted write access tag + break; + case 0x0f: + // Read only tag + break; + default: + // tag with unknown write attributes + ; + } + + //quint16 lock = (quint8(memory[blockByteToAddress(0x0e, 1)]) << 8) | + // quint8(memory[blockByteToAddress(0x0e, 0)]); + + settings->endGroup(); +} + +QByteArray NfcTagType1::uid() const +{ + lastAccess = QDateTime::currentMSecsSinceEpoch(); + + return memory.left(7); +} + +quint8 NfcTagType1::readData(quint8 block, quint8 byte) +{ + return memory.at((block << 3) | byte); +} + +QByteArray NfcTagType1::processCommand(const QByteArray &command) +{ + lastAccess = QDateTime::currentMSecsSinceEpoch(); + + QByteArray response; + + bool tagType1 = (hr0 & 0xf0) == 0x10; + bool dynamic = (hr0 & 0x0f) != 0x01; + + if (command.length() == 9) { + // static memory model command + quint8 opcode = command.at(0); + quint8 address = command.at(1); + quint8 data = command.at(2); + QByteArray uid = command.mid(3, 4); + + // check checksum + if (qNfcChecksum(command.constData(), command.length()) != 0) + return QByteArray(); + + // check UID + if (uid != memory.left(4)) + return QByteArray(); + + switch (opcode) { + case 0x00: // RALL + response.append(hr0); + response.append(hr1); + response.append(memory.left(120)); + break; + case 0x01: // READ + response.append(address); + if (address & 0x80) + response.append(char(0x00)); + else + response.append(memory.at(address)); + break; + case 0x53: { // WRITE-E + quint8 block = address >> 3; + if (block == 0x00 || block == 0x0d || block == 0x0e) // locked blocks + break; + + quint16 lock = (readData(0x0e, 0x01) << 8) | readData(0x0e, 0x00); + if ((0x01 << block) & lock) // locked blocks + break; + + // FIXME: Test dynamic lock bytes + + memory[address] = data; + + response.append(address); + response.append(data); + break; + } + case 0x1a: { // WRITE-NE + quint8 block = address >> 3; + if (block == 0x00 || block == 0x0d) // locked blocks + break; + + quint16 lock = (readData(0x0e, 0x01) << 8) | readData(0x0e, 0x00); + if ((0x01 << block) & lock) // locked blocks + break; + + + // FIXME: Test dynamic lock bytes + + memory[address] = memory.at(address) | data; + + response.append(address); + response.append(memory.at(address)); + break; + } + case 0x78: // RID + response.append(hr0); + response.append(hr1); + response.append(memory.left(4)); + break; + } + } else if (tagType1 && dynamic && command.length() == 16) { + // dynamic memory model command + quint8 opcode = command.at(0); + quint8 address = command.at(1); + QByteArray data = command.mid(2, 8); + QByteArray uid = command.mid(10, 4); + + // check checksum + if (qNfcChecksum(command.constData(), command.length()) != 0) + return QByteArray(); + + // check UID + if (uid != memory.left(4)) + return QByteArray(); + + switch (opcode) { + case 0x10: // RSEG + response.append(address); + response.append(memory.mid(128 * (address >> 4), 128)); + break; + case 0x02: // READ8 + response.append(address); + response.append(memory.mid(8 * address, 8)); + break; + case 0x54: { // WRITE-E8 + // locked blocks + if (address == 0x00 || address == 0x0d || address == 0x0e || address == 0x0f) + break; + + quint16 lock = (readData(0x0e, 0x01) << 8) | readData(0x0e, 0x00); + if (address <= 0x0e && ((0x01 << address) & lock)) // locked blocks + break; + + // FIXME: Test dynamic lock bytes + + memory.replace(address * 8, 8, data); + + response.append(address); + response.append(memory.mid(address * 8, 8)); + break; + } + case 0x1b: // WRITE-NE8 + // locked blocks + if (address == 0x00 || address == 0x0d || address == 0x0e || address == 0x0f) + break; + + quint16 lock = (readData(0x0e, 0x01) << 8) | readData(0x0e, 0x00); + if (address <= 0x0e && ((0x01 << address) & lock)) // locked blocks + break; + + // FIXME: Test dynamic lock bytes + + for (int i = 0; i < 8; ++i) + memory[address * 8 + i] = memory.at(address * 8 + i) | data.at(i); + + response.append(address); + response.append(memory.mid(address * 8, 8)); + break; + } + } + + if (!response.isEmpty()) { + quint16 crc = qNfcChecksum(response.constData(), response.length()); + response.append(quint8(crc & 0xff)); + response.append(quint8(crc >> 8)); + } + + return response; +} + + +NfcTagType2::NfcTagType2() +: memory(64, 0x00), currentSector(0), expectPacket2(false) +{ +} + +void NfcTagType2::load(QSettings *settings) +{ + settings->beginGroup(QLatin1String("TagType2")); + + memory = settings->value(QLatin1String("Data")).toByteArray(); + + settings->endGroup(); +} + +QByteArray NfcTagType2::uid() const +{ + lastAccess = QDateTime::currentMSecsSinceEpoch(); + + return memory.left(3) + memory.mid(4, 4); +} + +#define NACK QByteArray("\x05") +#define ACK QByteArray("\x0a") + +QByteArray NfcTagType2::processCommand(const QByteArray &command) +{ + lastAccess = QDateTime::currentMSecsSinceEpoch(); + + QByteArray response; + + // check checksum + if (qNfcChecksum(command.constData(), command.length()) != 0) + return QByteArray(); + + if (expectPacket2) { + expectPacket2 = false; + quint8 sector = command.at(0); + if (sector * 1024 > memory.length()) + return NACK; + else { + currentSector = sector; + return QByteArray(); + } + } + + quint8 opcode = command.at(0); + + switch (opcode) { + case 0x30: { // READ BLOCK + quint8 block = command.at(1); + int absoluteBlock = currentSector * 256 + block; + + response.append(memory.mid(absoluteBlock * 4, 16)); + if (response.length() != 16) + response.append(QByteArray(16 - response.length(), '\0')); + + break; + } + case 0xa2: { // WRITE BLOCK + quint8 block = command.at(1); + int absoluteBlock = currentSector * 256 + block; + + // locked blocks + if (absoluteBlock == 0 || absoluteBlock == 1) + return NACK; + + const QByteArray data = command.mid(2, 4); + + memory.replace(absoluteBlock * 4, 4, data); + + return ACK; + } + case 0xc2: // SECTOR SELECT - Packet 1 + if (memory.length() > 1024) { + expectPacket2 = true; + return ACK; + } + + return NACK; + default: + qDebug() << "Unknown opcode for Tag Type 2" << hex << opcode; + qDebug() << "command:" << command.toHex(); + + return NACK; + ; + } + + if (!response.isEmpty()) { + quint16 crc = qNfcChecksum(response.constData(), response.length()); + response.append(quint8(crc & 0xff)); + response.append(quint8(crc >> 8)); + } + + return response; +} diff --git a/src/nfc/targetemulator_p.h b/src/nfc/targetemulator_p.h new file mode 100644 index 00000000..a19dd17d --- /dev/null +++ b/src/nfc/targetemulator_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TARGETEMULATOR_P_H +#define TARGETEMULATOR_P_H + +#include <QtCore/QtGlobal> +#include <QtCore/QByteArray> + +QT_FORWARD_DECLARE_CLASS(QSettings) + +class TagBase +{ +public: + TagBase(); + ~TagBase(); + + virtual void load(QSettings *settings) = 0; + + virtual QByteArray processCommand(const QByteArray &command) = 0; + + virtual QByteArray uid() const = 0; + + qint64 lastAccessTime() const { return lastAccess; } + +protected: + mutable qint64 lastAccess; +}; + +class NfcTagType1 : public TagBase +{ +public: + NfcTagType1(); + ~NfcTagType1(); + + void load(QSettings *settings); + + QByteArray processCommand(const QByteArray &command); + + QByteArray uid() const; + +private: + quint8 readData(quint8 block, quint8 byte); + + quint8 hr0; + quint8 hr1; + + QByteArray memory; +}; + +class NfcTagType2 : public TagBase +{ +public: + NfcTagType2(); + ~NfcTagType2(); + + void load(QSettings *settings); + + QByteArray processCommand(const QByteArray &command); + + QByteArray uid() const; + +private: + QByteArray memory; + quint8 currentSector; + bool expectPacket2; +}; + +#endif // TARGETEMULATOR_P_H diff --git a/src/qprivatelinearbuffer_p.h b/src/qprivatelinearbuffer_p.h new file mode 100644 index 00000000..34febb7d --- /dev/null +++ b/src/qprivatelinearbuffer_p.h @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPRIVATELINEARBUFFER_P_H +#define QPRIVATELINEARBUFFER_P_H + +// This is QIODevice's read buffer, optimised for read(), isEmpty() and getChar() +class QPrivateLinearBuffer +{ +public: + QPrivateLinearBuffer() : len(0), first(0), buf(0), capacity(0) { + } + ~QPrivateLinearBuffer() { + delete [] buf; + } + void clear() { + first = buf; + len = 0; + } + int size() const { + return len; + } + bool isEmpty() const { + return len == 0; + } + void skip(int n) { + if (n >= len) { + clear(); + } else { + len -= n; + first += n; + } + } + int getChar() { + if (len == 0) + return -1; + int ch = uchar(*first); + len--; + first++; + return ch; + } + int read(char* target, int size) { + int r = qMin(size, len); + memcpy(target, first, r); + len -= r; + first += r; + return r; + } + char* reserve(int size) { + makeSpace(size + len, freeSpaceAtEnd); + char* writePtr = first + len; + len += size; + return writePtr; + } + void chop(int size) { + if (size >= len) { + clear(); + } else { + len -= size; + } + } + QByteArray readAll() { + char* f = first; + int l = len; + clear(); + return QByteArray(f, l); + } + int readLine(char* target, int size) { + int r = qMin(size, len); + char* eol = static_cast<char*>(memchr(first, '\n', r)); + if (eol) + r = 1+(eol-first); + memcpy(target, first, r); + len -= r; + first += r; + return int(r); + } + bool canReadLine() const { + return memchr(first, '\n', len); + } + void ungetChar(char c) { + if (first == buf) { + // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer + makeSpace(len+1, freeSpaceAtStart); + } + first--; + len++; + *first = c; + } + void ungetBlock(const char* block, int size) { + if ((first - buf) < size) { + // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer + makeSpace(len + size, freeSpaceAtStart); + } + first -= size; + len += size; + memcpy(first, block, size); + } + +private: + enum FreeSpacePos {freeSpaceAtStart, freeSpaceAtEnd}; + void makeSpace(size_t required, FreeSpacePos where) { + size_t newCapacity = qMax(capacity, size_t(QPRIVATELINEARBUFFER_BUFFERSIZE)); + while (newCapacity < required) + newCapacity *= 2; + int moveOffset = (where == freeSpaceAtEnd) ? 0 : newCapacity - len; + if (newCapacity > capacity) { + // allocate more space + char* newBuf = new char[newCapacity]; + memmove(newBuf + moveOffset, first, len); + delete [] buf; + buf = newBuf; + capacity = newCapacity; + } else { + // shift any existing data to make space + memmove(buf + moveOffset, first, len); + } + first = buf + moveOffset; + } + +private: + // length of the unread data + int len; + // start of the unread data + char* first; + // the allocated buffer + char* buf; + // allocated buffer size + size_t capacity; +}; + +#endif // QPRIVATELINEARBUFFER_P_H diff --git a/src/qtconnectivityglobal.h b/src/qtconnectivityglobal.h new file mode 100644 index 00000000..e556334a --- /dev/null +++ b/src/qtconnectivityglobal.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtConnectivity module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QTCONNECTIVITY_H +#define QTCONNECTIVITY_H + +#include <QtCore/qglobal.h> + +#if defined(Q_OS_WIN) +# if defined(QT_NODLL) +# undef QT_MAKEDLL +# undef QT_DLL +# elif defined(QT_MAKEDLL) +# if defined(QT_DLL) +# undef QT_DLL +# endif +# if defined(QT_BUILD_BT_LIB) +# define Q_CONNECTIVITY_EXPORT Q_DECL_EXPORT +# else +# define Q_CONNECTIVITY_EXPORT Q_DECL_IMPORT +# endif +# elif defined(QT_DLL) +# define Q_CONNECTIVITY_EXPORT Q_DECL_EXPORT +# endif +#endif + +#if !defined(Q_CONNECTIVITY_EXPORT) +# if defined(QT_SHARED) +# define Q_CONNECTIVITY_EXPORT Q_DECL_EXPORT +# else +# define Q_CONNECTIVITY_EXPORT +# endif +#endif + +#include <QtCore/qglobal.h> +#if defined(QTM_BUILD_UNITTESTS) && (defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_MAKEDLL) +# define QM_AUTOTEST_EXPORT Q_DECL_EXPORT +#elif defined(QTM_BUILD_UNITTESTS) && (defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_DLL) +# define QM_AUTOTEST_EXPORT Q_DECL_IMPORT +#elif defined(QTM_BUILD_UNITTESTS) && !(defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_SHARED) +# define QM_AUTOTEST_EXPORT Q_DECL_EXPORT +#else +# define QM_AUTOTEST_EXPORT +#endif + +#endif // QTCONNECTIVITY_H diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 00000000..b39b5650 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +CONFIG += ordered +SUBDIRS = bluetooth nfc diff --git a/sync.profile b/sync.profile new file mode 100644 index 00000000..449c3943 --- /dev/null +++ b/sync.profile @@ -0,0 +1,33 @@ +%modules = ( # path to module name map + "QtBluetooth" => "$basedir/src/bluetooth", + "QtNfc" => "$basedir/src/nfc", +); +%moduleheaders = ( # restrict the module headers to those found in relative path +); +%classnames = ( + "qtbluetoothversion.h" => "QtBluetoothVersion", + "qtnfcversion.h" => "QtNfcVersion", +); +%mastercontent = ( + "bluetooth" => "#include <QtBluetooth/QtBluetooth>\n", + "nfc" => "#include <QtNfc/QtNfc>\n", +); +%modulepris = ( + "QtBluetooth" => "$basedir/modules/qt_bluetooth.pri", + "QtNfc" => "$basedir/modules/qt_nfc.pri", +); +# Module dependencies. +# Every module that is required to build this module should have one entry. +# Each of the module version specifiers can take one of the following values: +# - A specific Git revision. +# - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch) +# +%dependencies = ( + "qtbase" => "refs/heads/master", + "qtserviceframework" => "refs/heads/master", +); + +# Compile tests +%configtests = ( + "bluez" => {}, +); diff --git a/tests/btclient/btclient.c b/tests/btclient/btclient.c new file mode 100644 index 00000000..2d52718f --- /dev/null +++ b/tests/btclient/btclient.c @@ -0,0 +1,581 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/utsname.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/socket.h> +#include <stdlib.h> +#include <unistd.h> +#include <poll.h> +#include <assert.h> +#include <fcntl.h> +#include <limits.h> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/rfcomm.h> +#include <bluetooth/l2cap.h> + +#include <dbus/dbus.h> + +#include "btclient.h" + +#define UNUSED(x) do { (void)x; } while(0) + +const char *xmldefn = + "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + "\n" + "<record>\n" + " <attribute id=\"0x0000\">\n" + " <uint32 value=\"0x00010010\" />\n" + " </attribute>\n" + " <attribute id=\"0x0001\">\n" + " <sequence>\n" + " <uuid value=\"" ECHO_SERVICE_UUID "\" />\n" + " </sequence>\n" + " </attribute>\n" + " <attribute id=\"0x0003\">\n" + " <uuid value=\"" ECHO_SERVICE_UUID "\" />\n" + " </attribute>\n" + " <attribute id=\"0x0004\">\n" + " <sequence>\n" + " <sequence>\n" + " <uuid value=\"0x0100\" />\n" + " </sequence>\n" + " <sequence>\n" + " <uuid value=\"0x0003\" />\n" + " <uint8 value=\"0x0a\" />\n" + " </sequence>\n" + " </sequence>\n" + " </attribute>\n" + " <attribute id=\"0x0005\">\n" + " <sequence>\n" + " <uuid value=\"0x1002\" />\n" + " </sequence>\n" + " </attribute>\n" + " <attribute id=\"0x0100\">\n" + " <text value=\"QtConnectivity Test Echo Server\" />\n" + " </attribute>\n" + " <attribute id=\"0x0101\">\n" + " <text value=\"QtConnectivity test echo server\" />\n" + " </attribute>\n" + " <attribute id=\"0x0102\">\n" + " <text value=\"Nokia, QtDF\" />\n" + " </attribute>\n" + "</record>\n"; + +typedef void (*actionhandler_t)(int, short, void *); + +struct fdlist { + struct fdlist *next; + int fd; + short events; + actionhandler_t hanlder; + void *ptr; +}; + +struct fdlist *head = 0; + +void removefd(struct fdlist *fdl, int fd){ + struct fdlist *prev = fdl; + while(fdl && fdl->fd != fd) { + prev = fdl; + fdl = fdl->next; + } + assert(fdl); + + prev->next = fdl->next; + free(fdl); +} + +struct fdlist *addfd(struct fdlist *fdl, int fd, short events, actionhandler_t hanlder, void *data){ + struct fdlist *n = malloc(sizeof(struct fdlist)); + if(fdl){ + while(fdl->next) + fdl = fdl->next; + fdl->next = n; + } + + n->next = 0; + n->fd = fd; + n->events = events; + n->hanlder = hanlder; + n->ptr = data; + + return n; + +} + +int mkpoll(struct fdlist *fdl, struct pollfd *fds, int max){ + int num = 0; + while(fdl && num < max){ + fds[num].events = fdl->events; + fds[num].fd = fdl->fd; + fdl = fdl->next; + num++; + } + assert(num <= max); + return num; +} + +int createListening(int channel){ + struct sockaddr_rc addr; + int flags; + socklen_t addrLength = sizeof(addr); + int sk, opt = 1; + + /* Create echo socket on bt channel 10 */ + sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + + addr.rc_family = AF_BLUETOOTH; + addr.rc_channel = channel; + memset(&addr.rc_bdaddr, 0, sizeof(bdaddr_t)); + + if (bind(sk, (struct sockaddr *)&addr, addrLength) < 0) { + perror("Failed to bind to Bluetooth socket"); + return -1; + } + + if(setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0){ + perror("Warning: Failed to set SO_REUSEADDR options"); + } + + // ensure that O_NONBLOCK is set on new connections. + flags = fcntl(sk, F_GETFL, 0); + if (!(flags & O_NONBLOCK)) + fcntl(sk, F_SETFL, flags | O_NONBLOCK); + + if (listen(sk, 10) < 0){ + perror("Can't start listening on bluetooth socket"); + return -1; + } + printf("Got socket: %d\n", sk); + return sk; +} + +int createListeningL2cap(int psm){ + struct sockaddr_l2 addr; + int flags; + socklen_t addrLength = sizeof(struct sockaddr_l2); + int sk, opt = 1; + + sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + + memset(&addr,0, addrLength); + addr.l2_family = AF_BLUETOOTH; + addr.l2_psm = htobs(psm); + memset(&addr.l2_bdaddr, 0, sizeof(bdaddr_t)); + + if (bind(sk, (struct sockaddr *)&addr, addrLength) < 0) { + perror("Failed to bind to Bluetooth socket"); + return -1; + } + + if(setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0){ + perror("Warning: Failed to set SO_REUSEADDR options"); + } + + // ensure that O_NONBLOCK is set on new connections. + flags = fcntl(sk, F_GETFL, 0); + if (!(flags & O_NONBLOCK)) + fcntl(sk, F_SETFL, flags | O_NONBLOCK); + + if (listen(sk, 10) < 0){ + perror("Can't start listening on bluetooth socket"); + return -1; + } + printf("Got L2cap socket: %d\n", sk); + return sk; +} + +void echo_process(int fd, short revents, void *data){ + char buff[1024]; + + UNUSED(data); + + if(revents&POLLHUP || revents&POLLNVAL){ + close(fd); + removefd(head, fd); + return; + } + int size = read(fd, buff, 1024); + printf("%d: Read: %d bytes\n", fd, size); + size = write(fd, buff, size); + printf("%d: Wrote: %d bytes\n", fd, size); +} + +void echo_connect(int fd, short revents, void *data){ + + struct sockaddr_rc addr; + unsigned char *a; + socklen_t length = sizeof(struct sockaddr_rc); + + UNUSED(data); + UNUSED(revents); + + printf("Echo connect started\n"); + + int sk = accept(fd, (struct sockaddr *)&addr, &length); + + a = addr.rc_bdaddr.b; + printf("Connect from: %02x:%02x:%02x:%02x:%02x:%02x port %d\n", a[5], a[4], a[3], a[2], a[1], a[0], addr.rc_channel); + addfd(head, sk, POLLIN|POLLHUP|POLLNVAL, echo_process, 0); + +} + +struct connectioninfo { + int socket; + FILE *pipe; + struct sockaddr_rc addr_them; +}; + +void id_greeting(int fd, short revents, void *data){ + int err; + unsigned char *a, *b; + struct sockaddr_rc addr; + char buffer[1024]; + char name[100]; + socklen_t addrLength = sizeof(addr); + struct connectioninfo *ci; + + if(revents&POLLHUP || revents&POLLNVAL){ + close(fd); + removefd(head, fd); + return; + } + + ci = (struct connectioninfo *)data; + + err = getsockname(ci->socket, (struct sockaddr *)&addr, &addrLength); + if(err < 0){ + perror("failed to get socket name"); + exit(-1); + } + a = addr.rc_bdaddr.b; + + b = ci->addr_them.rc_bdaddr.b; + + err = fscanf(ci->pipe, "%s", name); + removefd(head, fd); + pclose(ci->pipe); + + sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x %d %s %02x:%02x:%02x:%02x:%02x:%02x %d\n", + a[5], a[4], a[3], a[2], a[1], a[0], addr.rc_channel, name, + b[5], b[4], b[3], b[2], b[1], b[0], ci->addr_them.rc_channel); + if(write(ci->socket, buffer, strlen(buffer)) < 0){ + perror("Failed to write greeting"); + } + printf("%s", buffer); + free(ci); + +} + +void id_process(int fd, short revents, void *data){ + int err; + unsigned char *b; + struct sockaddr_rc addr_them; + char cmd[100]; + socklen_t addrLength = sizeof(addr_them); + struct connectioninfo *ci; + + UNUSED(data); + + if(revents&POLLHUP || revents&POLLNVAL){ + close(fd); + removefd(head, fd); + return; + } + + err = getpeername(fd, (struct sockaddr *)&addr_them, &addrLength); + if(err < 0){ + perror("failed to get socket name"); + exit(-1); + } + b = addr_them.rc_bdaddr.b; + + sprintf(cmd, "hcitool name %02x:%02x:%02x:%02x:%02x:%02x", b[5], b[4], b[3], b[2], b[1], b[0]); + + FILE *f = popen(cmd, "r"); + ci = malloc(sizeof(struct connectioninfo)); + ci->socket = fd; + ci->pipe = f; + memcpy(&ci->addr_them, &addr_them, sizeof(struct sockaddr_rc)); + + addfd(head, fileno(f), POLLIN, id_greeting, ci); + +} + +void id_connect(int fd, short revents, void *data){ + + struct sockaddr_rc addr; + unsigned char *a; + socklen_t length = sizeof(struct sockaddr_rc); + + UNUSED(revents); + UNUSED(data); + + printf("ID connect started\n"); + + int sk = accept(fd, (struct sockaddr *)&addr, &length); + + a = addr.rc_bdaddr.b; + printf("Connect from: %02x:%02x:%02x:%02x:%02x:%02x port %d\n", a[5], a[4], a[3], a[2], a[1], a[0], addr.rc_channel); + addfd(head, sk, POLLIN|POLLHUP|POLLNVAL, id_process, 0); + id_process(sk, POLLIN, 0x0); +} + +void id_print(int socket){ + + int err; + unsigned char *a; + struct sockaddr_rc addr; + socklen_t addrLength = sizeof(addr); + + err = getsockname(socket, (struct sockaddr *)&addr, &addrLength); + if(err < 0){ + perror("failed to get socket name"); + exit(-1); + } + a = addr.rc_bdaddr.b; + printf("We are: %d:%d:%d:%d:%d:%d port %d\n", a[0], a[1], a[2], a[3], a[4], a[5], addr.rc_channel); +} + +void l2_process(int fd, short revents, void *data){ + char buff[1024]; + + UNUSED(data); + + if(revents&POLLHUP || revents&POLLNVAL){ + close(fd); + removefd(head, fd); + return; + } + int size = read(fd, buff, 1024); + printf("%d: Read: %d bytes\n", fd, size); + size = write(fd, buff, size); + printf("%d: Wrote: %d bytes\n", fd, size); +} + +void l2_connect(int fd, short revents, void *data){ + + struct sockaddr_l2 addr; + unsigned char *a; + socklen_t length = sizeof(struct sockaddr_l2); + + UNUSED(revents); + UNUSED(data); + + printf("L2 connect started\n"); + + int sk = accept(fd, (struct sockaddr *)&addr, &length); + + a = addr.l2_bdaddr.b; + printf("Connect from: %02x:%02x:%02x:%02x:%02x:%02x port %d\n", a[5], a[4], a[3], a[2], a[1], a[0], addr.l2_psm); + addfd(head, sk, POLLIN|POLLHUP|POLLNVAL, l2_process, 0); + l2_process(sk, POLLIN, 0x0); +} + +void dbus_error(int fd, short revents, void *data){ + UNUSED(fd); + UNUSED(data); + if(revents&POLLHUP || revents&POLLNVAL){ + printf("dBus connection failed, shutting down\n"); + exit(-1); + } +} + +void registerService() +{ + DBusMessage* msg; + DBusMessageIter args; + DBusConnection* conn; + DBusError err; + DBusPendingCall* pending; + dbus_uint32_t level; + int fd; + + char path[PATH_MAX]; + const char *ret_string = 0; + + // initialiset the errors + dbus_error_init(&err); + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + if (dbus_error_is_set(&err)) { + fprintf(stderr, "Connection Error (%s)\n", err.message); + dbus_error_free(&err); + return; + } + + // create a new method call and check for errors + msg = dbus_message_new_method_call("org.bluez", // target for the method call + "/", // object to call on + "org.bluez.Manager", // interface to call on + "DefaultAdapter"); // method name + + if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { + fprintf(stderr, "dbus-send failed: Out Of Memory!\n"); + return; + } + + dbus_connection_flush(conn); + + dbus_message_unref(msg); + dbus_pending_call_block(pending); + msg = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + + if (!dbus_message_iter_init(msg, &args)) + fprintf(stderr, "Message has no arguments!\n"); + else if (DBUS_TYPE_OBJECT_PATH != dbus_message_iter_get_arg_type(&args)) + fprintf(stderr, "Argument is not an object path!\n"); + else + dbus_message_iter_get_basic(&args, &ret_string); + + if(!ret_string){ + fprintf(stderr, "Failed to get bluez path\n"); + return; + } + + strcpy(path, ret_string); + // change path to use any + strcpy(rindex(path, '/'), "/any"); + + printf("Using path: %s\n", path); + + dbus_message_unref(msg); + + // create a new method call and check for errors + msg = dbus_message_new_method_call("org.bluez", // target for the method call + path, // object to call on + "org.bluez.Service", // interface to call on + "AddRecord"); // method name + + if(!dbus_message_append_args(msg, DBUS_TYPE_STRING, &xmldefn, DBUS_TYPE_INVALID)){ + fprintf(stderr, "Failed to append args\n"); + return; + } + + // send message and get a handle for a reply + if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { // -1 is default timeout + fprintf(stderr, "Out Of Memory!\n"); + exit(1); + } + dbus_connection_flush(conn); + + // free message + dbus_message_unref(msg); + + // block until we receive a reply + dbus_pending_call_block(pending); + + // get the reply message + msg = dbus_pending_call_steal_reply(pending); + if (NULL == msg) { + fprintf(stderr, "Reply Null\n"); + return; + } + // free the pending message handle + dbus_pending_call_unref(pending); + + // read the parameters + if (!dbus_message_iter_init(msg, &args)) + fprintf(stderr, "Message has no arguments!\n"); + else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args)) + fprintf(stderr, "Argument is not int!\n"); + else + dbus_message_iter_get_basic(&args, &level); + + printf("Got handle: 0x%x\n", level); + + // free reply + dbus_message_unref(msg); + + dbus_connection_get_socket(conn, &fd); + addfd(head, fd, POLLHUP|POLLNVAL, dbus_error, 0x0); +} + +int main(int argc, char **argv) +{ + int socket; +#define MAX_POLL 256 + struct pollfd fds[MAX_POLL]; + + UNUSED(argc); + UNUSED(argv); + + registerService(); + + socket = createListening(10); + head = addfd(head, socket, POLLIN, echo_connect, 0); // first creation + + socket = createListening(11); + addfd(head, socket, POLLIN, id_connect, 0); + + socket = createListeningL2cap(0x1011); // must be > 0x1001 and odd + addfd(head, socket, POLLIN, l2_connect, 0); + + while(1){ + int n = mkpoll(head, fds, MAX_POLL); + if(poll(fds, n, -1)){ + struct fdlist *fdl = head; + int i; + + for(i = 0; i < n; i++){ + if(fds[i].revents){ + while(fdl && fdl->fd != fds[i].fd) + fdl = fdl->next; + assert(fdl); + fdl->hanlder(fds[i].fd, fds[i].revents, fdl->ptr); + } + } + } + else { + perror("Poll failed"); + exit(-1); + } + } + + return 0; +} diff --git a/tests/btclient/btclient.h b/tests/btclient/btclient.h new file mode 100644 index 00000000..d6ab932c --- /dev/null +++ b/tests/btclient/btclient.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BTCLIENT_H +#define BTCLIENT_H + +#define ECHO_SERVICE_UUID "90aaac86-8fa8-489c-ba6c-d540392c2da5" + +#endif // BTCLIENT_H diff --git a/tests/btclient/btclient.pro b/tests/btclient/btclient.pro new file mode 100644 index 00000000..1a96b99b --- /dev/null +++ b/tests/btclient/btclient.pro @@ -0,0 +1,8 @@ +include(../../staticconfig.pri) +TARGET = btclient +CONFIG += link_pkgconfig +PKGCONFIG += dbus-1 +QT -= gui \ + core +SOURCES = btclient.c +HEADERS += btclient.h diff --git a/tests/nfcsymbianbackend/common/qautomsgbox.cpp b/tests/nfcsymbianbackend/common/qautomsgbox.cpp new file mode 100644 index 00000000..c6576ea4 --- /dev/null +++ b/tests/nfcsymbianbackend/common/qautomsgbox.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qautomsgbox.h" + +QAutoMsgBox::QAutoMsgBox(QWidget *parent) : + QMessageBox(parent),m_timer(0),m_spy(0),m_signalCount(0) +{ + +} + +QAutoMsgBox::~QAutoMsgBox() +{ + delete m_timer; +} +bool QAutoMsgBox::event(QEvent *e) +{ + if (e->type() == QEvent::Close) + { + this->close(); + return true; + } + return false; +} diff --git a/tests/nfcsymbianbackend/common/qautomsgbox.h b/tests/nfcsymbianbackend/common/qautomsgbox.h new file mode 100644 index 00000000..ec27e77b --- /dev/null +++ b/tests/nfcsymbianbackend/common/qautomsgbox.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QAUTOMSGBOX_H +#define QAUTOMSGBOX_H + +#include <QMessageBox> +#include <QTimer> +#include <QtTest/QtTest> +#include <QSignalSpy> +#include <QCloseEvent> + +class QAutoMsgBox : public QMessageBox +{ + Q_OBJECT + +public: + explicit QAutoMsgBox(QWidget *parent = 0); + ~QAutoMsgBox(); + /*! + * Call this method when you want to make the dialog dismissed + * when the signalspy's count is equal to the \a count + */ + void setSignalSpy(QSignalSpy* spy, int count) + { + if (spy == 0) + return; + m_spy = spy; + m_signalCount = count; + if (m_timer) + delete m_timer; + m_timer = new QTimer; + m_timer->setInterval(50); + connect(m_timer, SIGNAL(timeout()), this, SLOT(timeOutFired())); + m_timer->start(); + } + /*! + * Call this method when you want to make the dialog dismissed + * after /a timeout(ms) period + */ + void setDismissTimeOut(int timeout) + { + QTimer::singleShot(timeout, this, SLOT(singleShotSlot())); + } +private slots: + void timeOutFired() + { + if(m_spy->count() >= m_signalCount) + { + QApplication::postEvent(this, new QCloseEvent); + m_timer->stop(); + delete m_timer; + m_timer = 0; + } + } + void singleShotSlot() + { + QApplication::postEvent(this, new QCloseEvent); + } + +private: + bool event(QEvent *e); + QTimer *m_timer; + + QSignalSpy *m_spy;//not own + int m_signalCount; +}; + +#endif // QAUTOMSGBOX_H diff --git a/tests/nfcsymbianbackend/common/qdummyslot.cpp b/tests/nfcsymbianbackend/common/qdummyslot.cpp new file mode 100644 index 00000000..8503c244 --- /dev/null +++ b/tests/nfcsymbianbackend/common/qdummyslot.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qdummyslot.h" +#include "qnfctagtestcommon.h" + +QDummySlot::QDummySlot(QObject *parent) : + QObject(parent) +{ +} + +void QDummySlot::errorHandling(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId& id) +{ + if (id == iReqId) + { + qDebug()<<"get the error signal, wait for dummy request"<<endl; + iOp->run(); + // iOp must use wait + iOp->checkSignal(); + iOp->checkResponse(); + qDebug()<<"waited request completed"<<endl; + } +} + +void QDummySlot::requestCompletedHandling(const QNearFieldTarget::RequestId& id) +{ + if (id == iReqId) + { + qDebug()<<"get the requestCompleted signal, wait for dummy request"<<endl; + iOp->run(); + // iOp must use wait + iOp->checkSignal(); + iOp->checkResponse(); + qDebug()<<"waited request completed"<<endl; + } +} diff --git a/tests/nfcsymbianbackend/common/qdummyslot.h b/tests/nfcsymbianbackend/common/qdummyslot.h new file mode 100644 index 00000000..92f58008 --- /dev/null +++ b/tests/nfcsymbianbackend/common/qdummyslot.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef DUMMYSLOT_H +#define DUMMYSLOT_H + +#include <QObject> +#include <QtTest/QtTest> +#include "qnearfieldtarget.h" +#include "qnfctestcommon.h" +#include "qnfctestutil.h" + +class MNfcTagOperation; + +class QDummySlot : public QObject +{ + Q_OBJECT +public: + explicit QDummySlot(QObject *parent = 0); + +public slots: + void errorHandling(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId& id); + void requestCompletedHandling(const QNearFieldTarget::RequestId& id); +public: + QNearFieldTarget::RequestId iReqId; + MNfcTagOperation * iOp; +}; + +#endif // DUMMYSLOT_H + diff --git a/tests/nfcsymbianbackend/common/qnfctagtestcommon.h b/tests/nfcsymbianbackend/common/qnfctagtestcommon.h new file mode 100644 index 00000000..5dc389d8 --- /dev/null +++ b/tests/nfcsymbianbackend/common/qnfctagtestcommon.h @@ -0,0 +1,614 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNFCTAGTESTCOMMON_H +#define QNFCTAGTESTCOMMON_H + +#include <qnearfieldmanager.h> +#include <qnearfieldtarget.h> +#include <QtTest/QtTest> +#include <qndefmessage.h> +#include <qndefnfctextrecord.h> +#include <qndefnfcurirecord.h> +#include <qnearfieldtagtype1.h> +#include <qnearfieldtagtype2.h> +#include <qnearfieldtagtype3.h> +#include <qnearfieldtagtype4.h> +#include "qdummyslot.h" +#include "qnfctestcommon.h" +#include "qnfctestutil.h" + +template<typename TAG> +struct TagTrait +{ + static QNearFieldTarget::Type type() { return QNearFieldTarget::ProprietaryTag; } + static QString info(){ return QString("unknow tag"); } +}; + +template<> +struct TagTrait<QNearFieldTagType1> +{ + static QNearFieldTarget::Type type() { return QNearFieldTarget::NfcTagType1; } + static QString info(){ return QString("tag type 1"); } +}; + +template<> +struct TagTrait<QNearFieldTagType2> +{ + static QNearFieldTarget::Type type() { return QNearFieldTarget::NfcTagType2; } + static QString info(){ return QString("tag type 2"); } +}; + +template<> +struct TagTrait<QNearFieldTagType3> +{ + static QNearFieldTarget::Type type() { return QNearFieldTarget::NfcTagType3; } + static QString info(){ return QString("tag type 3"); } +}; + +template<> +struct TagTrait<QNearFieldTagType4> +{ + static QNearFieldTarget::Type type() { return QNearFieldTarget::NfcTagType4; } + static QString info(){ return QString("tag type 4"); } +}; + + + +class MNfcTagOperation +{ +public: + MNfcTagOperation(QNearFieldTarget * tag) + { + mTarget = tag; + } + virtual void run() = 0; + virtual void checkSignal() = 0; + virtual void checkResponse() = 0; + virtual ~MNfcTagOperation(){}; +protected: + // Not own + QNearFieldTarget * mTarget; +}; + +class NfcTagRawCommandOperationCommon : public MNfcTagOperation +{ +public: + enum Wait + { + ENoWait, + EWaitTrue, + EWaitFalse + }; + + enum Signal + { + ENoSignal, + EErrorSignal, + ECompleteSignal + }; +public: + inline NfcTagRawCommandOperationCommon(QNearFieldTarget * tag); + + ~NfcTagRawCommandOperationCommon() + { + delete okSpy; + delete errSpy; + } + + void checkSignal() + { + qDebug()<<"checkSignal begin"; + qDebug()<<"checking signal type "<<mSignalType; + // check signal + switch (mSignalType) + { + case EErrorSignal: + { + int findRequest = 0; + for (int i = 0; i < errSpy->count(); ++i) + { + if (mId == errSpy->at(i).at(1).value<QNearFieldTarget::RequestId>()) + { + qDebug()<<"real err code "<<(int)(errSpy->at(i).at(0).value<QNearFieldTarget::Error>()); + qDebug()<<"expect err code "<<(int)(mExpectedErrCode); + QCOMPARE(errSpy->at(i).at(0).value<QNearFieldTarget::Error>(), mExpectedErrCode); + ++findRequest; + } + } + qDebug()<<"find "<<findRequest<<" errSignal"; + QCOMPARE(findRequest, 1); + + findRequest = 0; + for (int i = 0; i < okSpy->count(); ++i) + { + if (mId == okSpy->at(i).at(0).value<QNearFieldTarget::RequestId>()) + { + ++findRequest; + } + } + qDebug()<<"find "<<findRequest<<" okSignal"; + QCOMPARE(findRequest, 0); + break; + } + + case ECompleteSignal: + { + int findResult = 0; + for (int i = 0; i < okSpy->count(); ++i) + { + if (mId == okSpy->at(i).at(0).value<QNearFieldTarget::RequestId>()) + { + ++findResult; + } + } + QCOMPARE(findResult, 1); + + findResult = 0; + for (int i = 0; i < errSpy->count(); ++i) + { + if (mId == errSpy->at(i).at(1).value<QNearFieldTarget::RequestId>()) + { + ++findResult; + } + } + QTRY_COMPARE(findResult, 0); + break; + } + + default: + { + int findRequest = 0; + for (int i = 0; i < errSpy->count(); ++i) + { + if (mId == errSpy->at(i).at(1).value<QNearFieldTarget::RequestId>()) + { + ++findRequest; + } + } + QTRY_COMPARE(findRequest, 0); + + findRequest = 0; + for (int i = 0; i < okSpy->count(); ++i) + { + if (mId == okSpy->at(i).at(0).value<QNearFieldTarget::RequestId>()) + { + ++findRequest; + } + } + QTRY_COMPARE(findRequest, 0); + } + } + qDebug()<<"checkSignal end"; + } + + void checkResponse() + { + qDebug()<<"checkResponse begin"; + QTRY_COMPARE(mTarget->requestResponse(mId), mExpectedResult); + qDebug()<<"checkResponse end"; + } + + void setWaitOperation(NfcTagRawCommandOperationCommon::Wait waitOp) { mWaitOp = waitOp; } + void setExpectedErrorSignal(QNearFieldTarget::Error error) { mExpectedErrCode = error; mSignalType = EErrorSignal; } + void setExpectedOkSignal() { mSignalType = ECompleteSignal; } + void setExpectedResponse(QVariant expected){ mExpectedResult = expected; } + void setIfExpectInvalidId() { mInvalidId = true; } + void checkInvalidId() { if (mInvalidId) QVERIFY(!mId.isValid()); } + void waitRequest() + { + if (mWaitOp == NfcTagRawCommandOperationCommon::EWaitFalse) + { + QVERIFY(!mTarget->waitForRequestCompleted(mId)); + } + else if (mWaitOp == NfcTagRawCommandOperationCommon::EWaitTrue) + { + QVERIFY(mTarget->waitForRequestCompleted(mId)); + } + } + + QNearFieldTarget::RequestId mId; +protected: + QSignalSpy * okSpy; + QSignalSpy * errSpy; + Wait mWaitOp; + Signal mSignalType; + QNearFieldTarget::Error mExpectedErrCode; + QVariant mExpectedResult; + bool mInvalidId; +}; + +NfcTagRawCommandOperationCommon::NfcTagRawCommandOperationCommon(QNearFieldTarget * tag) : MNfcTagOperation(tag) + { + mWaitOp = ENoWait; + mSignalType = ENoSignal; + mInvalidId = false; + okSpy = new QSignalSpy(mTarget, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId&))); + errSpy = new QSignalSpy(mTarget, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId&))); + } + +// Ndef signal count check has limit. Use Ndef operation only once so far. +class NfcTagNdefOperationCommon : public MNfcTagOperation +{ +public: + enum Signal + { + ENoSignal, + EErrorSignal, + EReadSignal, + EWriteSignal + }; +public: + inline NfcTagNdefOperationCommon(QNearFieldTarget * tag); + + ~NfcTagNdefOperationCommon() + { + delete errSpy; + delete ndefMessageReadSpy; + delete ndefMessagesWrittenSpy; + } + + void run() + { + if (readNdefMessages) + { + (mTarget->*readNdefMessages)(); + } + + if (writeNdefMessages) + { + (mTarget->*writeNdefMessages)(mInputMessages); + } + } + + void checkSignal() + { + // check signal + switch (mSignalType) + { + case NfcTagNdefOperationCommon::EErrorSignal: + { + for (int i = 0; i < errSpy->count(); ++i) + { + if (!(errSpy->at(i).at(0).value<QNearFieldTarget::RequestId>().isValid())) + { + QTRY_COMPARE(errSpy->at(i).at(1).value<QNearFieldTarget::Error>(), mExpectedErrCode); + break; + } + } + + break; + } + + case NfcTagNdefOperationCommon::EReadSignal: + { + QVERIFY(ndefMessageReadSpy->count()>0); + for (int i = 0; i < ndefMessageReadSpy->count(); ++i) + { + mReceivedMessages.push_back(ndefMessageReadSpy->at(i).at(0).value<QNdefMessage>()); + } + break; + } + + case NfcTagNdefOperationCommon::EWriteSignal: + { + QTRY_COMPARE(ndefMessagesWrittenSpy->count(), 1); + break; + } + + default: + { + QTRY_COMPARE(errSpy->count(), 0); + QTRY_COMPARE(ndefMessageReadSpy->count(), 0); + QTRY_COMPARE(ndefMessagesWrittenSpy->count(), 0); + } + } + } + void checkResponse() + { + if (!mExpectedMessages.isEmpty()) + { + QTRY_COMPARE(mReceivedMessages, mExpectedMessages); + } + } + + void setExpectedErrorSignal(QNearFieldTarget::Error error) { mExpectedErrCode = error; mSignalType = NfcTagNdefOperationCommon::EErrorSignal; } + void setExpectedNdefReadSignal() { mSignalType = NfcTagNdefOperationCommon::EReadSignal; } + void setExpectedNdefWriteSignal() { mSignalType = NfcTagNdefOperationCommon::EWriteSignal; } + + void setReadNdefOperation() { readNdefMessages = &QNearFieldTarget::readNdefMessages; } + void setWriteNdefOperation(const QList<QNdefMessage> &messages) { mInputMessages = messages; writeNdefMessages = &QNearFieldTarget::writeNdefMessages; } + +protected: + QSignalSpy * errSpy; + QSignalSpy * ndefMessageReadSpy; + QSignalSpy * ndefMessagesWrittenSpy; + NfcTagNdefOperationCommon::Signal mSignalType; + QNearFieldTarget::Error mExpectedErrCode; + QList<QNdefMessage> mInputMessages; + QList<QNdefMessage> mExpectedMessages; + QList<QNdefMessage> mReceivedMessages; + QNearFieldTarget::RequestId (QNearFieldTarget::*readNdefMessages)(); + QNearFieldTarget::RequestId (QNearFieldTarget::*writeNdefMessages)(const QList<QNdefMessage> &messages); +}; + +NfcTagNdefOperationCommon::NfcTagNdefOperationCommon(QNearFieldTarget * tag) : MNfcTagOperation(tag) +{ + QSignalSpy * errSpy = new QSignalSpy(mTarget, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId&))); + QSignalSpy * ndefMessageReadSpy = new QSignalSpy(mTarget, SIGNAL(ndefMessageRead(QNdefMessage))); + QSignalSpy * ndefMessagesWrittenSpy = new QSignalSpy(mTarget, SIGNAL(ndefMessagesWritten())); + mSignalType = ENoSignal; + readNdefMessages = 0; + writeNdefMessages = 0; +} + +class NfcTagSendCommandsCommon : public NfcTagRawCommandOperationCommon +{ +public: + inline NfcTagSendCommandsCommon(QNearFieldTarget * tag); +public: + void run() + { + mId = mTarget->sendCommands(mCommands); + checkInvalidId(); + waitRequest(); + } + void checkResponse() + { + QTRY_COMPARE(mTarget->requestResponse(mId).value<QVariantList>(), mExpectedResponse); + } +public: + void SetCommandLists(QList<QByteArray> commands) { mCommands = commands; } + void SetExpectedResponse(QVariantList response) { mExpectedResponse = response; } +protected: + QList<QByteArray> mCommands; + QVariantList mExpectedResponse; +}; + +NfcTagSendCommandsCommon::NfcTagSendCommandsCommon(QNearFieldTarget * tag) : NfcTagRawCommandOperationCommon(tag) +{ +} + +typedef QList<MNfcTagOperation *> OperationList; + +Q_DECLARE_METATYPE(QNearFieldTarget*) +Q_DECLARE_METATYPE(QNearFieldTarget::Type) +Q_DECLARE_METATYPE(QNearFieldTarget::AccessMethod) +Q_DECLARE_METATYPE(MNfcTagOperation *) +Q_DECLARE_METATYPE(OperationList) + +template <typename TAG> +class QNfcTagTestCommon +{ +public: + QNfcTagTestCommon(); + ~QNfcTagTestCommon(); + void touchTarget(QString info = QString("")); + void removeTarget(); + void testSequence(OperationList& operations); + void testWaitInSlot(MNfcTagOperation * op1, NfcTagRawCommandOperationCommon * op2WithWait, MNfcTagOperation * op3, MNfcTagOperation * waitOpInSlot); + void testDeleteOperationBeforeAsyncRequestComplete(OperationList& operations); + void testRemoveTagBeforeAsyncRequestComplete(OperationList& operations1, OperationList& operations2); + void testCancelNdefOperation(); +public: + QNearFieldManager manager; + TAG* target; +}; + +template<typename TAG> +QNfcTagTestCommon<TAG>::QNfcTagTestCommon() +{ + target = 0; + qRegisterMetaType<QNdefMessage>("QNdefMessage"); + qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*"); + qRegisterMetaType<QNearFieldTarget::Error>("QNearFieldTarget::Error"); + qRegisterMetaType<QNearFieldTarget::RequestId>("QNearFieldTarget::RequestId"); + qRegisterMetaType<MNfcTagOperation *>("MNfcTagOperation *"); + qRegisterMetaType<OperationList>("OperatoinList"); +} + + +template<typename TAG> +QNfcTagTestCommon<TAG>::~QNfcTagTestCommon() +{ + if (target) + { + delete target; + } +} + +template<typename TAG> +void QNfcTagTestCommon<TAG>::touchTarget(QString info) +{ + if (target) + { + delete target; + target = 0; + } + QSignalSpy targetDetectedSpy(&manager, SIGNAL(targetDetected(QNearFieldTarget*))); + QSignalSpy targetLostSpy(&manager, SIGNAL(targetLost(QNearFieldTarget*))); + + qDebug()<<"start detect tag type "<<TagTrait<TAG>::type()<<endl; + manager.startTargetDetection(TagTrait<TAG>::type()); + + QString hint("please touch "); + hint += TagTrait<TAG>::info(); + hint += info; + QNfcTestUtil::ShowAutoMsg(hint, &targetDetectedSpy); + + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + target = qobject_cast<TAG *>(targetDetectedSpy.at(targetDetectedSpy.count()-1).at(0).value<QNearFieldTarget *>()); + // make sure target can be detected + QVERIFY(target); + + // make sure target uid is not empty + QVERIFY(!target->uid().isEmpty()); + + QCOMPARE(target->type(), TagTrait<TAG>::type()); +} + +template<typename TAG> +void QNfcTagTestCommon<TAG>::removeTarget() +{ + QVERIFY(target); + + QSignalSpy targetLostSpy(&manager, SIGNAL(targetLost(QNearFieldTarget*))); + QSignalSpy disconnectedSpy(target, SIGNAL(disconnected())); + + QNfcTestUtil::ShowAutoMsg("please remove the tag", &targetLostSpy); + QTRY_VERIFY(!targetLostSpy.isEmpty()); + + TAG *lostTarget = qobject_cast<TAG*>(targetLostSpy.first().at(0).value<QNearFieldTarget *>()); + + QCOMPARE(target, lostTarget); + + QVERIFY(!disconnectedSpy.isEmpty()); + + manager.stopTargetDetection(); +} + +template<typename TAG> +void QNfcTagTestCommon<TAG>::testSequence(OperationList& operations) +{ + qDebug()<<"_testSequence begin"; + for (int i = 0; i < operations.count(); ++i) + { + operations.at(i)->run(); + } + + QTest::qWait(10000); + for (int i = 0; i < operations.count(); ++i) + { + operations.at(i)->checkSignal(); + operations.at(i)->checkResponse(); + } + + qDebug()<<"_testSequence end"; +} + +template <typename TAG> +void QNfcTagTestCommon<TAG>::testWaitInSlot(MNfcTagOperation * op1, NfcTagRawCommandOperationCommon * op2WithWait, MNfcTagOperation * op3, MNfcTagOperation * waitOpInSlot) +{ + QDummySlot waitSlot; + QObject::connect(target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId&)), + &waitSlot, SLOT(requestCompletedHandling(const QNearFieldTarget::RequestId&))); + QObject::connect(target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId&)), + &waitSlot, SLOT(errorHandling(QNearFieldTarget::Error, const QNearFieldTarget::RequestId&))); + + waitSlot.iOp = waitOpInSlot; + + op1->run(); + op2WithWait->run(); + QVERIFY(!target->waitForRequestCompleted(op2WithWait->mId)); + op3->run(); + + QTest::qWait(10000); + op1->checkSignal(); + op1->checkResponse(); + + op2WithWait->checkSignal(); + op2WithWait->checkResponse(); + + op3->checkSignal(); + op3->checkResponse(); +} + +template <typename TAG> +void QNfcTagTestCommon<TAG>::testDeleteOperationBeforeAsyncRequestComplete(OperationList& operations) +{ + for (int i = 0; i < operations.count(); ++i) + { + operations.at(i)->run(); + } + delete target; + target = 0; + + QNfcTestUtil::ShowMessage("Remove tag and press ok"); +} + +template <typename TAG> +void QNfcTagTestCommon<TAG>::testRemoveTagBeforeAsyncRequestComplete(OperationList& operations1, OperationList& operations2) +{ + for (int i = 0; i < operations1.count(); ++i) + { + operations1.at(i)->run(); + } + + QSignalSpy targetLostSpy(&manager, SIGNAL(targetLost(QNearFieldTarget*))); + + QNfcTestUtil::ShowAutoMsg("please remove the tag", &targetLostSpy); + QTRY_VERIFY(!targetLostSpy.isEmpty()); + + for (int i = 0; i < operations2.count(); ++i) + { + operations2.at(i)->run(); + } + delete target; + target = 0; +} + +template<typename TAG> +void QNfcTagTestCommon<TAG>::testCancelNdefOperation() +{ + target->readNdefMessages(); + delete target; + target = 0; + + QNfcTestUtil::ShowMessage("please remove tag and press ok"); + + touchTarget(); + + QNdefMessage message; + QNdefNfcTextRecord textRecord; + textRecord.setText(QLatin1String("nfc")); + + message.append(textRecord); + + QList<QNdefMessage> messages; + messages.append(message); + + target->writeNdefMessages(messages); + delete target; + target = 0; + + QNfcTestUtil::ShowMessage("please remove tag and press ok"); +} +#endif // QNFCTAGTESTCOMMON_H diff --git a/tests/nfcsymbianbackend/common/qnfctagutil.cpp b/tests/nfcsymbianbackend/common/qnfctagutil.cpp new file mode 100644 index 00000000..67d88339 --- /dev/null +++ b/tests/nfcsymbianbackend/common/qnfctagutil.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnfctagutil.h" + +bool QNfcTagUtil::WriteTextNdef2Tag(QNearFieldTarget& target, QString text) +{ + QSignalSpy ndefMessageWriteSpy(&target, SIGNAL(ndefMessagesWritten())); + QNdefMessage message; + QNdefNfcTextRecord textRecord; + textRecord.setText(text); + + message.append(textRecord); + + QList<QNdefMessage> messages; + messages.append(message); + target.writeNdefMessages(messages); + QTest::qWait(5000); + return (ndefMessageWriteSpy.count() > 0); +} + +bool QNfcTagUtil::WriteTextUriNdef2Tag(QNearFieldTarget& target, QUrl uri, QString text) +{ + QSignalSpy ndefMessageWriteSpy(&target, SIGNAL(ndefMessagesWritten())); + QNdefMessage message; + + QNdefNfcTextRecord textRecord; + textRecord.setText(text); + + message.append(textRecord); + + QNdefNfcUriRecord uriRecord; + uriRecord.setUri(uri); + message.append(uriRecord); + + QList<QNdefMessage> messages; + messages.append(message); + + target.writeNdefMessages(messages); + QTest::qWait(5000); + return (ndefMessageWriteSpy.count() > 0); +} + +bool QNfcTagUtil::WriteUriNdef2Tag(QNearFieldTarget& target, QUrl uri) +{ + QSignalSpy ndefMessageWriteSpy(&target, SIGNAL(ndefMessagesWritten())); + QNdefMessage message; + + QNdefNfcUriRecord uriRecord; + uriRecord.setUri(uri); + message.append(uriRecord); + + QList<QNdefMessage> messages; + messages.append(message); + + target.writeNdefMessages(messages); + QTest::qWait(5000); + return (ndefMessageWriteSpy.count() > 0); +} diff --git a/tests/nfcsymbianbackend/common/qnfctagutil.h b/tests/nfcsymbianbackend/common/qnfctagutil.h new file mode 100644 index 00000000..0a78c6ae --- /dev/null +++ b/tests/nfcsymbianbackend/common/qnfctagutil.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNFCTAGUTIL_H +#define QNFCTAGUTIL_H +#include <qnearfieldmanager.h> +#include <qnearfieldtarget.h> +#include <QtTest/QtTest> +#include "qnfctestcommon.h" +#include "qnfctestutil.h" +#include <qndefmessage.h> +#include <qndefnfctextrecord.h> +#include <qndefnfcurirecord.h> +#include <qnearfieldtagtype1.h> +#include <qnearfieldtagtype2.h> +#include <qnearfieldtagtype3.h> +#include <qnearfieldtagtype4.h> + +struct QNfcTagUtil +{ + static bool WriteTextNdef2Tag(QNearFieldTarget& target, QString text = QString("nfc tag test")); + static bool WriteUriNdef2Tag(QNearFieldTarget& target, QUrl uri = QUrl("http://qt.nokia.com")); + static bool WriteTextUriNdef2Tag(QNearFieldTarget& target, QUrl uri = QUrl("http://qt.nokia.com"), QString text = QString("nfc tag test")); +}; +#endif diff --git a/tests/nfcsymbianbackend/common/qnfctestcommon.h b/tests/nfcsymbianbackend/common/qnfctestcommon.h new file mode 100644 index 00000000..19c90333 --- /dev/null +++ b/tests/nfcsymbianbackend/common/qnfctestcommon.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNFCTESTCOMMON_H +#define QNFCTESTCOMMON_H + +// Wait for __expr to happen, while still allowing events to be processed. +#define QTRY_NOOP(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 15000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + } while(0) + +// Will try to wait for the condition while allowing event processing +#define QTRY_VERIFY(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 4000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QVERIFY(__expr); \ + } while(0) + +// Will try to wait for the condition while allowing event processing +#define QTRY_COMPARE(__expr, __expected) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if ((__expr) != (__expected)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QCOMPARE(__expr, __expected); \ + } while(0) + +#endif + diff --git a/tests/nfcsymbianbackend/common/qnfctestutil.h b/tests/nfcsymbianbackend/common/qnfctestutil.h new file mode 100644 index 00000000..cf22dfa8 --- /dev/null +++ b/tests/nfcsymbianbackend/common/qnfctestutil.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QNFCTESTUTIL_H +#define QNFCTESTUTIL_H +#include <QMessageBox> +#include "qautomsgbox.h" + +const int MsgBoxTimeOutTime = 3*1000; +class QNfcTestUtil : public QObject +{ + Q_OBJECT +public: + static void ShowMessage(const QString& message) + { + QMessageBox b(QMessageBox::Information, QObject::tr("NFC symbian backend test"), + message, QMessageBox::Ok); + b.exec(); + } + static void ShowAutoMsg(const QString& message, QSignalSpy* spy, int count = 1) + { + QAutoMsgBox w; + w.addButton(QMessageBox::Ok); + w.setIcon(QMessageBox::Information); + w.setText(message); + w.setWindowTitle(QObject::tr("NFC symbian backend test")); + w.setSignalSpy(spy, count); + + w.exec(); + } + static void ShowAutoMsg(const QString& message, int mseconds = MsgBoxTimeOutTime) + { + QAutoMsgBox w; + w.addButton(QMessageBox::Ok); + w.setIcon(QMessageBox::Information); + w.setText(message); + w.setWindowTitle(QObject::tr("NFC symbian backend test")); + w.setDismissTimeOut(mseconds); + + w.exec(); + } +}; +#endif diff --git a/tests/nfcsymbianbackend/nfcsymbianbackend.pro b/tests/nfcsymbianbackend/nfcsymbianbackend.pro new file mode 100644 index 00000000..f8d7d8c1 --- /dev/null +++ b/tests/nfcsymbianbackend/nfcsymbianbackend.pro @@ -0,0 +1,6 @@ +TEMPLATE = subdirs + +symbian { + + SUBDIRS += qnearfieldmanager qllcpserver qllcpsockettype2 qllcpsocketlocal qllcpsocketremote qnearfieldtagtype1 qnearfieldtagtype2 qnearfieldtagtype3 qnearfieldtagtype4 nfctestserviceprovider +} diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider/main.cpp b/tests/nfcsymbianbackend/nfctestserviceprovider/main.cpp new file mode 100644 index 00000000..b519b03e --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider/main.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nfctestserviceprovider.h" + +#include <QtGui> +#include <QApplication> +#include <qremoteserviceregister.h> +#include <qservicemanager.h> + +#include <QDebug> +#include <qnearfieldmanager.h> +#include <qndefmessage.h> +#include <qnearfieldtarget.h> + +#include <iostream> +#include <fstream> + +using namespace std; + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +void MyOutputHandler(QtMsgType type, const char *msg) { + static int fd = -1; + if (fd == -1) + fd = ::open("E:\\nfctestserviceprovider.log", O_WRONLY | O_CREAT); + + ::write(fd, msg, strlen(msg)); + ::write(fd, "\n", 1); + ::fsync(fd); + + switch (type) { + case QtFatalMsg: + abort(); + } +} + +nfctestserviceprovider* w; + +class MyContentHandler : public QObject +{ + Q_OBJECT + + +signals: + void userHandleMessage(const QNdefMessage& msg, QNearFieldTarget* target); + +public slots: + void handleMessage(const QNdefMessage& msg, QNearFieldTarget* target) + { + QFile m_file("E:\\testserviceprovider.dat"); + m_file.open(QIODevice::ReadWrite | QIODevice::Append); + QDataStream *m_dataStream = new QDataStream(&m_file); + QByteArray msgArray = msg.toByteArray(); + (*m_dataStream) << msgArray; + delete m_dataStream; + + w->close(); + } + +public: + MyContentHandler(QObject* parent = 0) + : QObject(parent) + { + qDebug() << " MyContentHandler constructed !!!!!" << endl; + connect(this, SIGNAL(userHandleMessage(const QNdefMessage& , QNearFieldTarget* )), + this, SLOT(handleMessage(const QNdefMessage& , QNearFieldTarget* ))); + } + +}; + +void unregisterExampleService() +{ + QServiceManager m; + m.removeService("nfctestserviceprovider"); +} + +void registerExampleService() +{ + unregisterExampleService(); + QServiceManager m; + const QString path = QCoreApplication::applicationDirPath() + "/xmldata/nfctestserviceprovider.xml"; + qWarning() << "xml path:" << path; + if (!m.addService(path)) + { + qWarning() << "Cannot register service provider" << path; + } + else + { + qDebug() << " Register ok" << endl; + } +} + +Q_DECLARE_METATYPE(QMetaType::Type); + + + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + w = new nfctestserviceprovider(); + w->setWindowTitle( "nfc test service provider" ); + w->showMaximized(); + + //qInstallMsgHandler(MyOutputHandler); + + qRegisterMetaType<QNearFieldTarget*>("QNearFieldTarget*"); + qRegisterMetaType<QNdefMessage>("QNdefMessage"); + + registerExampleService(); + + MyContentHandler handler; + QNearFieldManager manager; + + int handle = manager.registerNdefMessageHandler(&handler, SIGNAL(userHandleMessage(QNdefMessage, QNearFieldTarget*))); + int ret = app.exec(); + manager.unregisterNdefMessageHandler(handle); + delete w; + return ret; +} + +#include "main.moc" diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider/makesis.bat b/tests/nfcsymbianbackend/nfctestserviceprovider/makesis.bat new file mode 100644 index 00000000..d4b7ee28 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider/makesis.bat @@ -0,0 +1,49 @@ +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +:: All rights reserved. +:: Contact: Nokia Corporation (qt-info@nokia.com) +:: +:: This file is part of the Qt Mobility Components. +:: +:: $QT_BEGIN_LICENSE:LGPL$ +:: GNU Lesser General Public License Usage +:: This file may be used under the terms of the GNU Lesser General Public +:: License version 2.1 as published by the Free Software Foundation and +:: appearing in the file LICENSE.LGPL included in the packaging of this +:: file. Please review the following information to ensure the GNU Lesser +:: General Public License version 2.1 requirements will be met: +:: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +:: +:: In addition, as a special exception, Nokia gives you certain additional +:: rights. These rights are described in the Nokia Qt LGPL Exception +:: version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +:: +:: GNU General Public License Usage +:: Alternatively, this file may be used under the terms of the GNU General +:: Public License version 3.0 as published by the Free Software Foundation +:: and appearing in the file LICENSE.GPL included in the packaging of this +:: file. Please review the following information to ensure the GNU General +:: Public License version 3.0 requirements will be met: +:: http://www.gnu.org/copyleft/gpl.html. +:: +:: Other Usage +:: Alternatively, this file may be used in accordance with the terms and +:: conditions contained in a signed written agreement between you and Nokia. +:: +:: +:: +:: +:: +:: $QT_END_LICENSE$ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +set EPOC_TOOLS_ROOT=\epoc32\tools +set CERTIFICATE_PATH=\\begrp101\groups6\PCCONN\Tools\RnD_certs + +%EPOC_TOOLS_ROOT%\makesis nfctestserviceprovider_template.pkg nfctestserviceprovider_unsigned.sis + +%EPOC_TOOLS_ROOT%\signsis -s nfctestserviceprovider_unsigned.sis nfctestserviceprovider.sisx %CERTIFICATE_PATH%\Nokia_RnDCert_02.der %CERTIFICATE_PATH%\Nokia_RnDCert_02.key + +del nfctestserviceprovider_unsigned.sis diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.cpp b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.cpp new file mode 100644 index 00000000..b6477fc4 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nfctestserviceprovider.h" + +nfctestserviceprovider::nfctestserviceprovider(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} + +nfctestserviceprovider::~nfctestserviceprovider() +{ + +} diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.h b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.h new file mode 100644 index 00000000..31123adf --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef nfctestserviceprovider_H +#define nfctestserviceprovider_H + +#include <QtGui/QMainWindow> +#include "ui_nfctestserviceprovider.h" + +class nfctestserviceprovider : public QMainWindow +{ + Q_OBJECT + +public: + nfctestserviceprovider(QWidget *parent = 0); + ~nfctestserviceprovider(); + +private: + Ui::nfctestserviceprovider ui; +}; + +#endif // nfctestserviceprovider_H diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.pro b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.pro new file mode 100644 index 00000000..2d2a5ac1 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.pro @@ -0,0 +1,52 @@ +TEMPLATE = app +TARGET = nfctestserviceprovider + +QT += core gui serviceframework + +CONFIG += no_icon + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +HEADERS += nfctestserviceprovider.h +SOURCES += nfctestserviceprovider_reg.rss \ + main.cpp \ + nfctestserviceprovider.cpp +FORMS += nfctestserviceprovider.ui +RESOURCES += + +symbian: { + TARGET.UID3 = 0xe347d948 + MMP_RULES += DEBUGGABLE_UDEBONLY +} + + +wince*|symbian*: { + addFiles.sources = nfctestserviceprovider.xml + addFiles.path = xmldata + addFiles2.sources = nfctestserviceprovider.xml + addFiles2.path = /private/2002AC7F/import/ + DEPLOYMENT += addFiles addFiles2 +} + +symbian { + TARGET.UID3 = 0xe347d949 + TARGET.CAPABILITY = LocalServices + } + + +wince* { + DEFINES+= TESTDATA_DIR=\\\".\\\" +} else:!symbian { + DEFINES += TESTDATA_DIR=\\\"$$PWD/\\\" +} + +xml.path = $$QT_MOBILITY_EXAMPLES/xmldata +xml.files = nfctestserviceprovider.xml +INSTALLS += xml + diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.ui b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.ui new file mode 100644 index 00000000..33683597 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.ui @@ -0,0 +1,30 @@ +<ui version="4.0" > + <class>nfctestserviceprovider</class> + <widget class="QMainWindow" name="nfctestserviceprovider" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>600</height> + </rect> + </property> + <property name="windowTitle" > + <string>nfctestserviceprovider</string> + </property> + <widget class="QWidget" name="centralwidget" /> + <widget class="QMenuBar" name="menubar" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>21</height> + </rect> + </property> + </widget> + <widget class="QStatusBar" name="statusbar" /> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.xml b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.xml new file mode 100644 index 00000000..5b6d9f37 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider/nfctestserviceprovider.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<SFW version="1.1"> +<service> + <name>nfctestserviceprovider</name> + <ipcaddress>nfctestserviceprovider</ipcaddress> + <description>NFC serive provider</description> + <interface> + <name>com.nokia.qt.nfc.NdefMessageHandler</name> + <version>1.0</version> + <description>nfc service provider</description> + <capabilities></capabilities> + <customproperty key="datatype">urn:nfc:ext:R||abc</customproperty> + </interface> +</service> +</SFW> diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider2/main.cpp b/tests/nfcsymbianbackend/nfctestserviceprovider2/main.cpp new file mode 100644 index 00000000..9dc4e1b1 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider2/main.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nfctestserviceprovider2.h" + +#include <QtGui> +#include <QApplication> +#include <qremoteserviceregister.h> +#include <qservicemanager.h> + +#include <QDebug> +#include <qnearfieldmanager.h> +#include <qndefmessage.h> +#include <qnearfieldtarget.h> + +#include <iostream> +#include <fstream> + +using namespace std; + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +void MyOutputHandler(QtMsgType type, const char *msg) { + static int fd = -1; + if (fd == -1) + fd = ::open("E:\\nfctestserviceprovider2.log", O_WRONLY | O_CREAT); + + ::write(fd, msg, strlen(msg)); + ::write(fd, "\n", 1); + ::fsync(fd); + + switch (type) { + case QtFatalMsg: + abort(); + } +} + +nfctestserviceprovider2* w; + +class MyContentHandler : public QObject +{ + Q_OBJECT + + +signals: + void userHandleMessage(const QNdefMessage& msg, QNearFieldTarget* target); + +public slots: + void handleMessage(const QNdefMessage& msg, QNearFieldTarget* target) + { + QFile m_file("E:\\testserviceprovider2.dat"); + m_file.open(QIODevice::ReadWrite | QIODevice::Append); + QDataStream m_dataStream(&m_file); + QByteArray msgArray = msg.toByteArray(); + m_dataStream << msgArray; + + w->close(); + } + +public: + MyContentHandler(QObject* parent = 0) + : QObject(parent) + { + qDebug() << " MyContentHandler constructed !!!!!" << endl; + connect(this, SIGNAL(userHandleMessage(const QNdefMessage& , QNearFieldTarget* )), + this, SLOT(handleMessage(const QNdefMessage& , QNearFieldTarget* ))); + } + +}; + +void unregisterExampleService() +{ + QServiceManager m; + m.removeService("nfctestserviceprovider2"); +} + +void registerExampleService() +{ + unregisterExampleService(); + QServiceManager m; + const QString path = QCoreApplication::applicationDirPath() + "/xmldata/nfctestserviceprovider2.xml"; + qWarning() << "xml path:" << path; + if (!m.addService(path)) + { + qWarning() << "Cannot register service provider" << path; + } + else + { + qDebug() << " Register ok" << endl; + } +} + +Q_DECLARE_METATYPE(QMetaType::Type); + + + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + w = new nfctestserviceprovider2(); + w->setWindowTitle( "nfc test service provider 2" ); + w->showMaximized(); + + qInstallMsgHandler(MyOutputHandler); + + qRegisterMetaType<QNearFieldTarget*>("QNearFieldTarget*"); + qRegisterMetaType<QNdefMessage>("QNdefMessage"); + + registerExampleService(); + + MyContentHandler handler; + QNearFieldManager manager; + + int handle = manager.registerNdefMessageHandler(&handler, SIGNAL(userHandleMessage(QNdefMessage, QNearFieldTarget*))); + + QFile m_file("E:\\testserviceprovider2.dat"); + m_file.open(QIODevice::ReadWrite | QIODevice::Append); + QTextStream m_textStream(&m_file); + m_textStream << "register handle return " << QString::number(handle); + + int ret = app.exec(); + + manager.unregisterNdefMessageHandler(handle); + delete w; + return ret; +} + +#include "main.moc" diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider2/makesis.bat b/tests/nfcsymbianbackend/nfctestserviceprovider2/makesis.bat new file mode 100644 index 00000000..7e57ddc8 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider2/makesis.bat @@ -0,0 +1,48 @@ +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +:: All rights reserved. +:: Contact: Nokia Corporation (qt-info@nokia.com) +:: +:: This file is part of the Qt Mobility Components. +:: +:: $QT_BEGIN_LICENSE:LGPL$ +:: GNU Lesser General Public License Usage +:: This file may be used under the terms of the GNU Lesser General Public +:: License version 2.1 as published by the Free Software Foundation and +:: appearing in the file LICENSE.LGPL included in the packaging of this +:: file. Please review the following information to ensure the GNU Lesser +:: General Public License version 2.1 requirements will be met: +:: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +:: +:: In addition, as a special exception, Nokia gives you certain additional +:: rights. These rights are described in the Nokia Qt LGPL Exception +:: version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +:: +:: GNU General Public License Usage +:: Alternatively, this file may be used under the terms of the GNU General +:: Public License version 3.0 as published by the Free Software Foundation +:: and appearing in the file LICENSE.GPL included in the packaging of this +:: file. Please review the following information to ensure the GNU General +:: Public License version 3.0 requirements will be met: +:: http://www.gnu.org/copyleft/gpl.html. +:: +:: Other Usage +:: Alternatively, this file may be used in accordance with the terms and +:: conditions contained in a signed written agreement between you and Nokia. +:: +:: +:: +:: +:: +:: $QT_END_LICENSE$ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +set EPOC_TOOLS_ROOT=\epoc32\tools +set CERTIFICATE_PATH=\\begrp101\groups6\PCCONN\Tools\RnD_certs + +%EPOC_TOOLS_ROOT%\makesis nfctestserviceprovider2_template.pkg nfctestserviceprovider2_unsigned.sis + +%EPOC_TOOLS_ROOT%\signsis -s nfctestserviceprovider2_unsigned.sis nfctestserviceprovider2.sisx %CERTIFICATE_PATH%\Nokia_RnDCert_02.der %CERTIFICATE_PATH%\Nokia_RnDCert_02.key + +del nfctestserviceprovider2_unsigned.sis diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.cpp b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.cpp new file mode 100644 index 00000000..8b1d34ec --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nfctestserviceprovider2.h" + +nfctestserviceprovider2::nfctestserviceprovider2(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} + +nfctestserviceprovider2::~nfctestserviceprovider2() +{ + +} diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.h b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.h new file mode 100644 index 00000000..50c05f94 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef nfctestserviceprovider2_H +#define nfctestserviceprovider2_H + +#include <QtGui/QMainWindow> +#include "ui_nfctestserviceprovider2.h" + +class nfctestserviceprovider2 : public QMainWindow +{ + Q_OBJECT + +public: + nfctestserviceprovider2(QWidget *parent = 0); + ~nfctestserviceprovider2(); + +private: + Ui::nfctestserviceprovider2 ui; +}; + +#endif // nfctestserviceprovider2_H diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.pro b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.pro new file mode 100644 index 00000000..82161c33 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.pro @@ -0,0 +1,50 @@ +TEMPLATE = app +TARGET = nfctestserviceprovider2 + +QT += core gui serviceframework + +CONFIG += no_icon + +INCLUDEPATH += ../../../src/connectivity/nfc +DEPENDPATH += ../../../src/connectivity/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += nfctestserviceprovider2.h +SOURCES += nfctestserviceprovider2_reg.rss \ + main.cpp \ + nfctestserviceprovider2.cpp +FORMS += nfctestserviceprovider2.ui +RESOURCES += + + + +wince*|symbian*: { + addFiles.sources = nfctestserviceprovider2.xml + addFiles.path = xmldata + addFiles2.sources = nfctestserviceprovider2.xml + addFiles2.path = /private/2002AC7F/import/ + DEPLOYMENT += addFiles addFiles2 +} + +symbian { + TARGET.UID3 = 0xe347d950 + TARGET.CAPABILITY = LocalServices + } + + +wince* { + DEFINES+= TESTDATA_DIR=\\\".\\\" +} else:!symbian { + DEFINES += TESTDATA_DIR=\\\"$$PWD/\\\" +} + +xml.path = $$QT_MOBILITY_EXAMPLES/xmldata +xml.files = nfctestserviceprovider2.xml +INSTALLS += xml + diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.ui b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.ui new file mode 100644 index 00000000..516affe0 --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.ui @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>nfctestserviceprovider2</class> + <widget class="QMainWindow" name="nfctestserviceprovider2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>600</height> + </rect> + </property> + <property name="windowTitle"> + <string>nfctestserviceprovider</string> + </property> + <widget class="QWidget" name="centralwidget"/> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>26</height> + </rect> + </property> + </widget> + <widget class="QStatusBar" name="statusbar"/> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.xml b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.xml new file mode 100644 index 00000000..9d22644b --- /dev/null +++ b/tests/nfcsymbianbackend/nfctestserviceprovider2/nfctestserviceprovider2.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<SFW version="1.1"> +<service> + <name>nfctestserviceprovider3</name> + <ipcaddress>nfctestserviceprovider2</ipcaddress> + <description>NFC serive provider</description> + <interface> + <name>com.nokia.qt.nfc.NdefMessageHandler</name> + <version>1.0</version> + <description>nfc service provider</description> + <capabilities></capabilities> + <customproperty key="datatype">urn:nfc:ext:S||abc</customproperty> + </interface> +</service> +</SFW> diff --git a/tests/nfcsymbianbackend/qcontenthandler/makesis.bat b/tests/nfcsymbianbackend/qcontenthandler/makesis.bat new file mode 100644 index 00000000..82b29ae2 --- /dev/null +++ b/tests/nfcsymbianbackend/qcontenthandler/makesis.bat @@ -0,0 +1,48 @@ +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +:: All rights reserved. +:: Contact: Nokia Corporation (qt-info@nokia.com) +:: +:: This file is part of the Qt Mobility Components. +:: +:: $QT_BEGIN_LICENSE:LGPL$ +:: GNU Lesser General Public License Usage +:: This file may be used under the terms of the GNU Lesser General Public +:: License version 2.1 as published by the Free Software Foundation and +:: appearing in the file LICENSE.LGPL included in the packaging of this +:: file. Please review the following information to ensure the GNU Lesser +:: General Public License version 2.1 requirements will be met: +:: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +:: +:: In addition, as a special exception, Nokia gives you certain additional +:: rights. These rights are described in the Nokia Qt LGPL Exception +:: version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +:: +:: GNU General Public License Usage +:: Alternatively, this file may be used under the terms of the GNU General +:: Public License version 3.0 as published by the Free Software Foundation +:: and appearing in the file LICENSE.GPL included in the packaging of this +:: file. Please review the following information to ensure the GNU General +:: Public License version 3.0 requirements will be met: +:: http://www.gnu.org/copyleft/gpl.html. +:: +:: Other Usage +:: Alternatively, this file may be used in accordance with the terms and +:: conditions contained in a signed written agreement between you and Nokia. +:: +:: +:: +:: +:: +:: $QT_END_LICENSE$ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +set EPOC_TOOLS_ROOT=\epoc32\tools +set CERTIFICATE_PATH=\\begrp101\groups6\PCCONN\Tools\RnD_certs + +%EPOC_TOOLS_ROOT%\makesis tst_qcontenthandler_template.pkg tst_qcontenthandler_unsigned.sis + +%EPOC_TOOLS_ROOT%\signsis -s tst_qcontenthandler_unsigned.sis tst_qcontenthandler.sisx %CERTIFICATE_PATH%\Nokia_RnDCert_02.der %CERTIFICATE_PATH%\Nokia_RnDCert_02.key + +del tst_qcontenthandler_unsigned.sis diff --git a/tests/nfcsymbianbackend/qcontenthandler/qcontenthandler.pro b/tests/nfcsymbianbackend/qcontenthandler/qcontenthandler.pro new file mode 100644 index 00000000..58bf7d8f --- /dev/null +++ b/tests/nfcsymbianbackend/qcontenthandler/qcontenthandler.pro @@ -0,0 +1,23 @@ +QT += testlib + +TARGET = tst_qcontenthandler +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qautomsgbox.h +SOURCES += tst_qcontenthandler.cpp \ + ../common/qautomsgbox.cpp +symbian:TARGET.CAPABILITY = LocalServices ReadUserData WriteUserData NetworkServices UserEnvironment Location SwEvent ReadDeviceData WriteDeviceData diff --git a/tests/nfcsymbianbackend/qcontenthandler/tst_qcontenthandler.cpp b/tests/nfcsymbianbackend/qcontenthandler/tst_qcontenthandler.cpp new file mode 100644 index 00000000..04e76ca8 --- /dev/null +++ b/tests/nfcsymbianbackend/qcontenthandler/tst_qcontenthandler.cpp @@ -0,0 +1,333 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> + +#include "qnfctestcommon.h" +#include "qnfctestutil.h" + +#include <qnearfieldmanager.h> +#include <qnearfieldtarget.h> +#include <qnearfieldtagtype1.h> +#include <qndefnfctextrecord.h> +#include <qndefnfcurirecord.h> +#include <qndefmessage.h> +#include <qndefrecord.h> + +QTM_USE_NAMESPACE + +Q_DECLARE_METATYPE(QNearFieldTarget*) +Q_DECLARE_METATYPE(QNearFieldTarget::Type) +Q_DECLARE_METATYPE(QNdefFilter) + + +static const QString& logFileName = "E:\\testserviceprovider.dat"; +static const QString& logDirName = "E:\\"; + +static const QString& logFileName_negative = "E:\\testserviceprovider2.dat"; +static const QString& expectedLog = "register handle return -1"; + + +class MessageListener : public QObject +{ + Q_OBJECT + +signals: + void matchedNdefMessage(const QNdefMessage &message, QNearFieldTarget *target); +}; + +class tst_QContentHandler : public QObject +{ + Q_OBJECT + +public: + tst_QContentHandler(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void testcase_01(); + void testcase_02(); + void testcase_03_negative(); + + +private: + QNearFieldManager m_manager; + QNdefMessage m_message; +}; + +tst_QContentHandler::tst_QContentHandler() +{ + qRegisterMetaType<QNdefMessage>("QNdefMessage"); + qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*"); +} + +void tst_QContentHandler::initTestCase() +{ + +} + +void tst_QContentHandler::cleanupTestCase() +{ +} + +/*! + Description: Unit test for NFC content handler + + TestScenario: Write a Ndef Message into tag type 1, read the tag again to ensure corresponding service provider + being invoked + Note: This case need nfctestserviceprovider sis to be installed + +*/ +void tst_QContentHandler::testcase_01() +{ + //first step, delete the log file generated by nfctestserviceprovider if any + QFile m_file(logFileName); + if (m_file.exists()) + { + QDir(logDirName).remove(logFileName); + } + QVERIFY(m_file.exists() == false); + + //second step, write the ndef message into the tag + QNearFieldTagType1* target; + QSignalSpy targetDetectedSpy(&m_manager, SIGNAL(targetDetected(QNearFieldTarget*))); + + m_manager.startTargetDetection(QNearFieldTarget::NfcTagType1); + + QString hint("please touch a writable tag of type 1"); + QNfcTestUtil::ShowAutoMsg(hint, &targetDetectedSpy); + + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + target = qobject_cast<QNearFieldTagType1 *>(targetDetectedSpy.at(targetDetectedSpy.count()-1).at(0).value<QNearFieldTarget *>()); + // make sure target can be detected + QVERIFY(target); + + // make sure target uid is not empty + QVERIFY(!target->uid().isEmpty()); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::ExternalRtd); + record.setType("R"); + record.setPayload(QByteArray(2, quint8(0x55))); + m_message.append(record); + + QList<QNdefMessage> messages; + messages.append(m_message); + + QSignalSpy ndefMessageReadSpy(target, SIGNAL(ndefMessageRead(QNdefMessage))); + QSignalSpy ndefMessageWriteSpy(target, SIGNAL(ndefMessagesWritten())); + + target->writeNdefMessages(messages); + QTRY_VERIFY(!ndefMessageWriteSpy.isEmpty()); + + target->readNdefMessages(); + QTRY_VERIFY(!ndefMessageReadSpy.isEmpty()); + + const QNdefMessage& ndefMessage_new(ndefMessageReadSpy.first().at(0).value<QNdefMessage>()); + QVERIFY(messages.at(0) == ndefMessage_new); + + QSignalSpy targetLostSpy(&m_manager, SIGNAL(targetLost(QNearFieldTarget*))); + QNfcTestUtil::ShowAutoMsg("please remove the tag", &targetLostSpy); + QTRY_VERIFY(!targetLostSpy.isEmpty()); + + delete target; + + //third step: stop target detection(so that the ndef message can be routed to service provider) + // and touch the tag again to invoke service provider, if the service provider being + // invoked successfully, the log file contains the message content will be generated + // compare the message in the log file with the message writen to the tag + m_manager.stopTargetDetection(); + + hint = "please touch the tag just be writen successfully"; + QNfcTestUtil::ShowMessage(hint); + + QVERIFY(m_file.exists()); + m_file.open(QIODevice::ReadOnly); + QDataStream fileInData (&m_file); + QByteArray msgByteArray; + fileInData >> msgByteArray; + QNdefMessage msgFromLog = QNdefMessage::fromByteArray(msgByteArray); + + QVERIFY(m_message == msgFromLog); + + hint = "please remove tag"; + QNfcTestUtil::ShowMessage(hint); +} + +/*! + Description: Unit test for NFC content handler + + TestScenario: Read the tag again to ensure if an application registered for the ndef message, + the ndef message can't be routed to service provider + Note: This case need nfctestserviceprovider sis to be installed + +*/ +void tst_QContentHandler::testcase_02() +{ + //first step, delete the log file generated by nfctestserviceprovider if any + QFile m_file(logFileName); + if (m_file.exists()) + { + QDir(logDirName).remove(logFileName); + } + QVERIFY(m_file.exists() == false); + + //second step, register for the ndef message, so that the test case itself + // is the application registered for the ndef message + QNdefFilter filter; + filter.appendRecord(QNdefRecord::ExternalRtd, "R"); + MessageListener listener; + QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*))); + int id = m_manager.registerNdefMessageHandler(filter, &listener, + SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*))); + QVERIFY(id != -1); + + //third step, touch the tag with the ndef message, to verify the log file can't + // be generated because the service provider can't be invoked + QString hint("please touch again the tag just be writen successfully"); + QNfcTestUtil::ShowAutoMsg(hint, &messageSpy, 1); + + QVERIFY(m_file.exists() == false); + + m_manager.unregisterNdefMessageHandler(id); + + hint = "please remove tag"; + QNfcTestUtil::ShowMessage(hint); + +} + +/*! + Description: Unit test for NFC content handler + + TestScenario: Write a Ndef Message into tag type 1, read the tag again to ensure corresponding service provider + being invoked but the corresponding interface can't be invoked because user write xml file wrongly + Note: This case need nfctestserviceprovider2 sis to be installed + +*/ +void tst_QContentHandler::testcase_03_negative() +{ + //first step, delete the log file generated by nfctestserviceprovider2 if any + QFile m_file(logFileName_negative); + if (m_file.exists()) + { + QDir(logDirName).remove(logFileName_negative); + } + QVERIFY(!m_file.exists()); + + //second step, write the ndef message into the tag + QNearFieldTagType1* target; + QSignalSpy targetDetectedSpy(&m_manager, SIGNAL(targetDetected(QNearFieldTarget*))); + + m_manager.startTargetDetection(QNearFieldTarget::NfcTagType1); + + QString hint("please touch a writable tag of type 1"); + QNfcTestUtil::ShowAutoMsg(hint, &targetDetectedSpy); + + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + target = qobject_cast<QNearFieldTagType1 *>(targetDetectedSpy.at(targetDetectedSpy.count()-1).at(0).value<QNearFieldTarget *>()); + // make sure target can be detected + QVERIFY(target); + + // make sure target uid is not empty + QVERIFY(!target->uid().isEmpty()); + + QNdefRecord record; + record.setTypeNameFormat(QNdefRecord::ExternalRtd); + record.setType("S"); + record.setPayload(QByteArray(2, quint8(0x55))); + m_message.clear(); + m_message.append(record); + + QList<QNdefMessage> messages; + messages.append(m_message); + + QSignalSpy ndefMessageReadSpy(target, SIGNAL(ndefMessageRead(QNdefMessage))); + QSignalSpy ndefMessageWriteSpy(target, SIGNAL(ndefMessagesWritten())); + + target->writeNdefMessages(messages); + QTRY_VERIFY(!ndefMessageWriteSpy.isEmpty()); + + target->readNdefMessages(); + QTRY_VERIFY(!ndefMessageReadSpy.isEmpty()); + + const QNdefMessage& ndefMessage_new(ndefMessageReadSpy.first().at(0).value<QNdefMessage>()); + QVERIFY(messages.at(0) == ndefMessage_new); + + QSignalSpy targetLostSpy(&m_manager, SIGNAL(targetLost(QNearFieldTarget*))); + QNfcTestUtil::ShowAutoMsg("please remove the tag", &targetLostSpy); + QTRY_VERIFY(!targetLostSpy.isEmpty()); + + delete target; + m_manager.stopTargetDetection(); + + //third step: stop target detection(so that the ndef message can be routed to service provider) + // and touch the tag again to invoke service provider, if the service provider being + // invoked successfully, the log file contains the register fail info will be generated + // compare the message in the log file with the expected info + + hint = "please touch the tag just be writen successfully"; + QNfcTestUtil::ShowMessage(hint); + + QVERIFY(m_file.exists()); + + m_file.open(QIODevice::ReadOnly | QIODevice::Text); + QTextStream fileInData(&m_file); + QString logMsg = fileInData.readAll() ; + + qDebug() << "log message: " << logMsg; + + QVERIFY(expectedLog == logMsg); + + hint = "please remove tag"; + QNfcTestUtil::ShowMessage(hint); +} + + + + +QTEST_MAIN(tst_QContentHandler); + +#include "tst_qcontenthandler.moc" diff --git a/tests/nfcsymbianbackend/qllcpserver/qllcpserver.pro b/tests/nfcsymbianbackend/qllcpserver/qllcpserver.pro new file mode 100644 index 00000000..47e9e96d --- /dev/null +++ b/tests/nfcsymbianbackend/qllcpserver/qllcpserver.pro @@ -0,0 +1,25 @@ +QT += testlib + +TARGET = tst_qllcpserver +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qautomsgbox.h +SOURCES += tst_qllcpserver.cpp\ + ../common/qautomsgbox.cpp +symbian:TARGET.CAPABILITY = ALL -TCB + + diff --git a/tests/nfcsymbianbackend/qllcpserver/tst_qllcpserver.cpp b/tests/nfcsymbianbackend/qllcpserver/tst_qllcpserver.cpp new file mode 100644 index 00000000..4018a934 --- /dev/null +++ b/tests/nfcsymbianbackend/qllcpserver/tst_qllcpserver.cpp @@ -0,0 +1,464 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> +#include <qllcpserver.h> +#include <qllcpsocket.h> + +#include "qnfctestcommon.h" +#include "qnfctestutil.h" + +QString TestUri("urn:nfc:xsn:nokia:symbiantest"); + +static qint64 countBytesWritten(QSignalSpy& bytesWrittenSpy) + { + qint64 ret = 0; + for(int i = 0; i < bytesWrittenSpy.count(); i++) + { + ret+=bytesWrittenSpy[i].at(0).value<qint64>(); + } + return ret; + } + +Q_DECLARE_METATYPE(QLlcpSocket::SocketError) +class tst_QLlcpServer : public QObject +{ + Q_OBJECT + +public: + tst_QLlcpServer(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + + // basic acceptance test + void newConnection(); + void newConnection_data(); + void newConnection_wait(); + void newConnection_wait_data(); + void api_coverage(); + + //advance test case + void multiConnection(); + + // nagetive testcases + void negTestCase1(); +}; + +tst_QLlcpServer::tst_QLlcpServer() +{ +} + +void tst_QLlcpServer::initTestCase() +{ + qRegisterMetaType<QLlcpSocket::SocketError>("QLlcpSocket::SocketError"); +} + +void tst_QLlcpServer::cleanupTestCase() +{ +} +void tst_QLlcpServer::newConnection_data() +{ + QString hint = "handshake 1"; + QTest::addColumn<QString>("uri"); + QTest::addColumn<QString>("hint"); + QTest::newRow("0") << TestUri << hint; +} + +/*! + Description: Unit test for NFC LLCP server async functions + + TestScenario: 1. Server will listen to a pre-defined URI + 2. Wait client to connect. + 3. Read message from client. + 4. Echo the same message back to client + 5. Wait client disconnect event. + + TestExpectedResults: + 1. The listen successfully set up. + 2. The message has be received from client. + 3. The echoed message has been sent to client. + 4. Connection disconnected and NO error signals emitted. +*/ +void tst_QLlcpServer::newConnection() +{ + QFETCH(QString, uri); + QFETCH(QString, hint); + + QLlcpServer server; + qDebug() << "Create QLlcpServer completed"; + qDebug() << "Start listening..."; + QSignalSpy connectionSpy(&server, SIGNAL(newConnection())); + + bool ret = server.listen(uri); + QVERIFY(ret); + qDebug() << "Listen() return ok"; + + QNfcTestUtil::ShowAutoMsg(hint, &connectionSpy, 1); + + QTRY_VERIFY(!connectionSpy.isEmpty()); + qDebug() << "try to call nextPendingConnection()"; + QLlcpSocket *socket = server.nextPendingConnection(); + QVERIFY(socket != NULL); + QSignalSpy readyReadSpy(socket, SIGNAL(readyRead())); + QSignalSpy errorSpy(socket, SIGNAL(error(QLlcpSocket::SocketError))); + + //Get data from client + QTRY_VERIFY(!readyReadSpy.isEmpty()); + + qDebug() << "Bytes available = " << socket->bytesAvailable(); + quint16 blockSize = 0; + QDataStream in(socket); + in.setVersion(QDataStream::Qt_4_6); + while (socket->bytesAvailable() < (int)sizeof(quint16)){ + QSignalSpy readyRead(socket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + in >> blockSize; + qDebug()<<"Read blockSize from client: " << blockSize; + while (socket ->bytesAvailable() < blockSize){ + QSignalSpy readyRead(socket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + QString echo; + in >> echo; + qDebug() << "Read data from client:" << echo; + //Send data to client + QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64))); + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + qDebug()<<"Write echoed data back to client"; + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + qint64 val = socket->write(block); + qDebug("Write() return value = %d", val); + QVERIFY(val == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy); + qDebug()<<"Server::bytesWritten signal return value = " << written; + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + written += countBytesWritten(bytesWrittenSpy); + } + QVERIFY(written == block.size()); + //Now data has been sent,check the if existing error + QVERIFY(errorSpy.isEmpty()); + QTest::qWait(1500);//give some time to client to finish + server.close(); +} + +/*! + Description: Unit test for NFC LLCP server sync(waitXXX) functions + + TestScenario: 1. Server will listen to a pre-defined URI + 2. Wait client to connect. + 3. Read message from client. + 4. Echo the same message back to client + 5. Wait client disconnect event. + + TestExpectedResults: + 1. The listen successfully set up. + 2. The message has be received from client. + 3. The echoed message has been sent to client. + 4. Connection disconnected and NO error signals emitted. +*/ +void tst_QLlcpServer::newConnection_wait() + { + QFETCH(QString, uri); + QFETCH(QString, hint); + + QLlcpServer server; + qDebug() << "Create QLlcpServer completed"; + qDebug() << "Start listening..."; + bool ret = server.listen(uri); + QVERIFY(ret); + qDebug() << "Listen() return ok"; + QSignalSpy connectionSpy(&server, SIGNAL(newConnection())); + + QNfcTestUtil::ShowAutoMsg(hint, &connectionSpy, 1); + + QTRY_VERIFY(!connectionSpy.isEmpty()); + qDebug() << "try to call nextPendingConnection()"; + QLlcpSocket *socket = server.nextPendingConnection(); + QVERIFY(socket != NULL); + + QSignalSpy errorSpy(socket, SIGNAL(error(QLlcpSocket::SocketError))); + //Get data from client + const int Timeout = 10 * 1000; + + quint16 blockSize = 0; + QDataStream in(socket); + in.setVersion(QDataStream::Qt_4_6); + while (socket->bytesAvailable() < (int)sizeof(quint16)) { + bool ret = socket->waitForReadyRead(Timeout); + QVERIFY(ret); + } + + in >> blockSize; + qDebug()<<"Read blockSize from client: " << blockSize; + while (socket ->bytesAvailable() < blockSize){ + bool ret = socket->waitForReadyRead(Timeout); + QVERIFY(ret); + } + QString echo; + in >> echo; + qDebug() << "Read data from client:" << echo; + //Send data to client + QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64))); + + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + qDebug()<<"Write echoed data back to client"; + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + qint64 val = socket->write(block); + qDebug("Write() return value = %d", val); + QVERIFY(val == 0); + + ret = socket->waitForBytesWritten(Timeout); + QVERIFY(ret); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy); + + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64))); + bool ret = socket->waitForBytesWritten(Timeout); + QVERIFY(ret); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + written += countBytesWritten(bytesWrittenSpy); + } + QVERIFY(written == block.size()); + //Now data has been sent,check the if existing error + if (!errorSpy.isEmpty()) + { + QLlcpSocket::SocketError error = errorSpy.first().at(0).value<QLlcpSocket::SocketError>(); + qDebug("QLlcpSocket::SocketError =%d", error); + } + QVERIFY(errorSpy.isEmpty()); + QTest::qWait(1500);//give some time to client to finish + server.close(); + } + +void tst_QLlcpServer::newConnection_wait_data() + { + QTest::addColumn<QString>("uri"); + QTest::addColumn<QString>("hint"); + QTest::newRow("0") << TestUri + << "handshake 2"; + } + + + +/*! + Description: LLCP Server API test & Socket readDatagram API test + TestScenario: + 1) Read two datagrams from llcp client device + 2) Covered API: readDatagram(), serviceUri(), servicePort(), isListening(), serverError() + */ +void tst_QLlcpServer::api_coverage() +{ + QString uri = TestUri; + QLlcpServer server; + QSignalSpy connectionSpy(&server, SIGNAL(newConnection())); + bool ret = server.listen(uri); + QVERIFY(ret); + + QString message("api_coverage test"); + + QNfcTestUtil::ShowAutoMsg(message, &connectionSpy, 1); + QTRY_VERIFY(!connectionSpy.isEmpty()); + + bool hasPending = server.hasPendingConnections(); + QVERIFY(hasPending); + QLlcpSocket *socket = server.nextPendingConnection(); + QVERIFY(socket != NULL); + QSignalSpy readyReadSpy(socket, SIGNAL(readyRead())); + //Get data from client + QTRY_VERIFY(!readyReadSpy.isEmpty()); + + qint64 size = socket->bytesAvailable(); + QTRY_VERIFY(size > 0); + QByteArray datagram; + datagram.resize(size); + qint64 readSize = socket->readDatagram(datagram.data(), datagram.size()); + QVERIFY(readSize == size); + + qDebug()<<"Server Uri = " << server.serviceUri(); + QCOMPARE(uri,server.serviceUri()); + + quint8 unsupportedPort = 0; + QCOMPARE(unsupportedPort,server.serverPort()); + + QVERIFY(server.isListening() == true); + QVERIFY(server.serverError() == QLlcpSocket::UnknownSocketError); + server.close(); +} + + +/*! + Description: listen negative test - listen twice +*/ +void tst_QLlcpServer::negTestCase1() +{ + + QString uri = TestUri; + QLlcpServer server; + QSignalSpy connectionSpy(&server, SIGNAL(newConnection())); + bool ret = server.listen(uri); + QVERIFY(ret); + + QString message("negTestCase1 test"); + + QNfcTestUtil::ShowAutoMsg(message, &connectionSpy, 1); + + ret = server.listen(uri); + QVERIFY(ret == false); + QTest::qWait(1 * 1000);//give some time to wait new connection + server.close(); +} +/*! + Description: Add a llcp2 server which will always + run( actually run twice ), then a client in a device connect, + after the case finish, another device connect the + server again. + + CounterPart: tst_qllcpsockettype2 echo:"0" + run this case twice to test multiConnection() +*/ +void tst_QLlcpServer::multiConnection() + { + QString uri = TestUri; + QString hint ="multiConnection test"; + + QLlcpServer server; + qDebug() << "Create QLlcpServer completed"; + qDebug() << "Start listening..."; + QSignalSpy connectionSpy(&server, SIGNAL(newConnection())); + + bool ret = server.listen(uri); + QVERIFY(ret); + qDebug() << "Listen() return ok"; + const int KLoopCount = 2; + int loopCount = 0; + while(loopCount < KLoopCount) + { + qDebug() << "#########Loop count = " << loopCount <<" #########"; + QNfcTestUtil::ShowAutoMsg(hint, &connectionSpy, 1); + + QTRY_VERIFY(!connectionSpy.isEmpty()); + qDebug() << "try to call nextPendingConnection()"; + QLlcpSocket *socket = server.nextPendingConnection(); + QVERIFY(socket != NULL); + QSignalSpy readyReadSpy(socket, SIGNAL(readyRead())); + QSignalSpy errorSpy(socket, SIGNAL(error(QLlcpSocket::SocketError))); + + //Get data from client + QTRY_VERIFY(!readyReadSpy.isEmpty()); + + qDebug() << "Bytes available = " << socket->bytesAvailable(); + quint16 blockSize = 0; + QDataStream in(socket); + in.setVersion(QDataStream::Qt_4_6); + while (socket->bytesAvailable() < (int)sizeof(quint16)){ + QSignalSpy readyRead(socket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + in >> blockSize; + qDebug()<<"Read blockSize from client: " << blockSize; + while (socket ->bytesAvailable() < blockSize){ + QSignalSpy readyRead(socket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + QString echo; + in >> echo; + qDebug() << "Read data from client:" << echo; + //Send data to client + QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64))); + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + qDebug()<<"Write echoed data back to client"; + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + qint64 val = socket->write(block); + qDebug("Write() return value = %d", val); + QVERIFY(val == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy); + qDebug()<<"Server::bytesWritten signal return value = " << written; + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + written += countBytesWritten(bytesWrittenSpy); + } + QVERIFY(written == block.size()); + //Now data has been sent,check the if existing error + QVERIFY(errorSpy.isEmpty()); + + connectionSpy.removeFirst(); + loopCount++; + } + QTest::qWait(1500);//give some time to client to finish + server.close(); + } +QTEST_MAIN(tst_QLlcpServer); + +#include "tst_qllcpserver.moc" diff --git a/tests/nfcsymbianbackend/qllcpsocketlocal/qllcpsocketlocal.pro b/tests/nfcsymbianbackend/qllcpsocketlocal/qllcpsocketlocal.pro new file mode 100644 index 00000000..960388d9 --- /dev/null +++ b/tests/nfcsymbianbackend/qllcpsocketlocal/qllcpsocketlocal.pro @@ -0,0 +1,24 @@ + +QT += testlib + +TARGET = tst_qllcpsocketlocal +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qautomsgbox.h +SOURCES += tst_qllcpsocketlocal.cpp \ + ../common/qautomsgbox.cpp +symbian:TARGET.CAPABILITY = ALL -TCB diff --git a/tests/nfcsymbianbackend/qllcpsocketlocal/tst_qllcpsocketlocal.cpp b/tests/nfcsymbianbackend/qllcpsocketlocal/tst_qllcpsocketlocal.cpp new file mode 100644 index 00000000..657f22e8 --- /dev/null +++ b/tests/nfcsymbianbackend/qllcpsocketlocal/tst_qllcpsocketlocal.cpp @@ -0,0 +1,954 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> + +#include <qllcpsocket.h> +#include <qnearfieldmanager.h> +#include <qnearfieldtarget.h> +#include "qnfctestcommon.h" +#include "qnfctestutil.h" + +Q_DECLARE_METATYPE(QNearFieldTarget*) +Q_DECLARE_METATYPE(QLlcpSocket::SocketError ) +Q_DECLARE_METATYPE(QLlcpSocket::SocketState ) + +class tst_qllcpsocketlocal : public QObject +{ + Q_OBJECT + +public: + tst_qllcpsocketlocal(); +private Q_SLOTS: + + + void multipleClient(); + void echoClient(); + void echoClient_data(); + void testCase2(); //work with tst_qllcpsocketremote testCase2 + void testCase3(); + void coverageTest1(); + //advanced test + void deleteSocketWhenInUse(); + void waitBytesWrittenInSlot(); + void multiSocketToOneServer(); + //negtive test + void negTestCase1(); + void negTestCase2(); + //void negTestCase3(); + //void negTestCase4(); + + void initTestCase(); + void cleanupTest(); + +private: + void writeMessage(QLlcpSocket& localSocket,QString& payLoad); +private: + QNearFieldTarget *m_target; // not own + quint8 m_port; +}; + +tst_qllcpsocketlocal::tst_qllcpsocketlocal() +{ + qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*"); + qRegisterMetaType<QLlcpSocket::SocketError>("QLlcpSocket::SocketError"); + qRegisterMetaType<QLlcpSocket::SocketState>("QLlcpSocket::SocketState"); +} + +/*! + Description: Init test case for NFC LLCP connection-less mode socket - local peer + + TestScenario: + Touch a NFC device with LLCP connection-less service actived + + TestExpectedResults: + Signal of target detected has been found. +*/ +void tst_qllcpsocketlocal::initTestCase() +{ + qDebug()<<"tst_qllcpsocketlocal::initTestCase() Begin"; + QString message("Please touch a NFC device with llcp client enabled"); + QNearFieldManager nfcManager; + QSignalSpy targetDetectedSpy(&nfcManager, SIGNAL(targetDetected(QNearFieldTarget*))); + nfcManager.startTargetDetection(QNearFieldTarget::NfcForumDevice); + + QNfcTestUtil::ShowAutoMsg(message, &targetDetectedSpy, 1); + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + m_target = targetDetectedSpy.at(targetDetectedSpy.count() - 1).at(0).value<QNearFieldTarget*>(); + QVERIFY(m_target != NULL); + QVERIFY(m_target->accessMethods() & QNearFieldTarget::LlcpAccess); + QVERIFY(m_target->uid() == QByteArray()); + QVERIFY(m_target->type() == QNearFieldTarget::NfcForumDevice); + + m_port = 35; + qDebug()<<"tst_qllcpsocketlocal::initTestCase() End"; +} + +/*! + Description: Send the message and Receive the acknowledged identical message + + TestScenario: + 1. Local peer temps to read datagram without bind + 2. Local peer binds to the remote peer + 3. Local peer sends the "testcase1 string" message to the remote peer + 4. Local peer receives the above message sending from the remote peer + + TestExpectedResults: + 1. Local peer fails to read datagram without bind + 2. Local peer binds to local port successfully. + 3. The message has be sent to remote peer. + 4. The message has been received from remote peer. +*/ +void tst_qllcpsocketlocal::echoClient() +{ + QFETCH(QString, echoPayload); + QLlcpSocket localSocket; + + // STEP 1. readDatagram must be called before bind + QByteArray tmpForReadArray; + tmpForReadArray.resize(127); + qint64 ret = localSocket.readDatagram(tmpForReadArray.data(), tmpForReadArray.size()); + QVERIFY(ret == -1); + + QCOMPARE(localSocket.state(), QLlcpSocket::UnconnectedState); + QSignalSpy stateChangedSpy(&localSocket, SIGNAL(stateChanged(QLlcpSocket::SocketState))); + + // STEP 2: bind the local port for current socket + QSignalSpy readyReadSpy(&localSocket, SIGNAL(readyRead())); + bool retBool = localSocket.bind(m_port); + QVERIFY(retBool); + QVERIFY(!stateChangedSpy.isEmpty()); + QCOMPARE(localSocket.state(), QLlcpSocket::BoundState); + + // Wait remote part bind + QString messageBox("Wait remote bind"); + QNfcTestUtil::ShowAutoMsg(messageBox); + + // STEP 3: Local peer sends the message to the remote peer + writeMessage(localSocket,echoPayload); + QSignalSpy errorSpy(&localSocket, SIGNAL(error(QLlcpSocket::SocketState))); + + // STEP 4: Start read payload from server + QString messageBox2("Wait remote send buffer"); + QNfcTestUtil::ShowAutoMsg(messageBox2, &readyReadSpy); + + QByteArray inPayload; + while(localSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(localSocket.pendingDatagramSize()); + quint8 remotePort = 0; + QSignalSpy readyRead(&localSocket, SIGNAL(readyRead())); + qint64 readSize = localSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Client-- read inPayload size=" << inPayload.size(); + qDebug() << "Client-- read remotePort=" << remotePort; + if (inPayload.size() >= (int)sizeof(quint16)) { + break; + } + else + { + qDebug() << "Client-- not enough header"; + QTRY_VERIFY(!readyRead.isEmpty()); + } + } + + QDataStream in(inPayload); + in.setVersion(QDataStream::Qt_4_6); + quint16 headerSize = 0; // size of real echo payload + in >> headerSize; + qDebug() << "Client-- read headerSize=" << headerSize; + while (inPayload.size() < headerSize + (int)sizeof(quint16)){ + QSignalSpy readyRead(&localSocket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + if(localSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(localSocket.pendingDatagramSize()); + quint8 remotePort = 0; + qint64 readSize = localSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Client-- read long blocksize=" << inPayload.size(); + } + } + + QDataStream in2(inPayload); + in2.setVersion(QDataStream::Qt_4_6); + in2 >> headerSize; + QString inEchoPayload; + in2 >> inEchoPayload; + qDebug() << "Client-- in echo string len:" << inEchoPayload.length(); + qDebug("Client-- in echo string = %s", qPrintable(inEchoPayload)); + //test the echoed string is same as the original string + QVERIFY(echoPayload == inEchoPayload); + // make sure the no error signal emitted + QVERIFY(errorSpy.isEmpty()); +} + +void tst_qllcpsocketlocal::echoClient_data() +{ + QTest::addColumn<QString>("echoPayload"); + QTest::newRow("0") << "test payload"; + QString longStr4k; + for (int i = 0; i < 4000; i++) + longStr4k.append((char)(i%26 + 'a')); + QTest::newRow("1") << longStr4k; +} + +void tst_qllcpsocketlocal::writeMessage( + QLlcpSocket& localSocket, + QString& payLoad) +{ + // STEP 2: Local peer sends the message to the remote peer + QSignalSpy errorSpy(&localSocket, SIGNAL(error(QLlcpSocket::SocketState))); + QSignalSpy bytesWrittenSpy(&localSocket, SIGNAL(bytesWritten(qint64))); + + //Prepare data to send + QByteArray outPayload; + QDataStream out(&outPayload, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << payLoad; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(payLoad)); + qDebug("Client-- write echo string length= %d", payLoad.length()); + qDebug("Client-- write payload length = %d", outPayload.length()); + out.device()->seek(0); + out << (quint16)(outPayload.size() - sizeof(quint16)); + + qint64 ret = localSocket.writeDatagram(outPayload, m_target, m_port); + QVERIFY(ret == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + + qint64 written = 0; + qint32 lastSignalCount = 0; + while(true) + { + for(int i = lastSignalCount; i < bytesWrittenSpy.count(); i++) { + written += bytesWrittenSpy.at(i).at(0).value<qint64>(); + } + lastSignalCount = bytesWrittenSpy.count(); + qDebug() << "current signal count = " << lastSignalCount; + qDebug() << "written payload size = " << written; + if (written < outPayload.size()) { + QTRY_VERIFY(bytesWrittenSpy.count() > lastSignalCount); + } + else { + break; + } + } + qDebug() << "Overall bytesWritten = " << written; + qDebug() << "Overall block size = " << outPayload.size(); + QVERIFY(written == outPayload.size()); +} + + +/*! + Description: Send the message and Receive the acknowledged identical message + + TestScenario: + 1. Local peer sends the very long message to the remote peer + 2. Local peer sends the second very long message to the remote peer + + TestExpectedResults: + 1. The message has be sent to remote peer. + 2. The second message has been received from remote peer. +*/ +void tst_qllcpsocketlocal::multipleClient() +{ + QLlcpSocket localSocket; + QString longStr1k; + for (int i = 0; i < 1000; i++) + longStr1k.append((char)(i%26 + 'a')); + + QString longStr2k; + for (int i = 0; i < 2000; i++) + longStr2k.append((char)(i%26 + 'b')); + + QCOMPARE(localSocket.state(), QLlcpSocket::UnconnectedState); + QSignalSpy stateChangedSpy(&localSocket, SIGNAL(stateChanged(QLlcpSocket::SocketState))); + + // STEP 1: bind the local port for current socket + bool retBool = localSocket.bind(m_port); + QVERIFY(retBool); + QVERIFY(!stateChangedSpy.isEmpty()); + QCOMPARE(localSocket.state(), QLlcpSocket::BoundState); + + // Wait remote part bind + QString messageBox("Wait remote bind"); + QNfcTestUtil::ShowAutoMsg(messageBox); + + writeMessage(localSocket,longStr1k); + writeMessage(localSocket,longStr2k); +} + + +void tst_qllcpsocketlocal::testCase2() +{ + QLlcpSocket localSocket; + quint8 localPort = 38; + + // STEP 1: + //QSignalSpy bytesWrittenSpy(&localSocket, SIGNAL(bytesWritten(qint64))); + QString message("testcase2 string str1"); + QByteArray tmpArray(message.toAscii()); + const char* data = tmpArray.data(); + qint64 strSize = message.size(); + qint64 val = localSocket.writeDatagram(data, strSize, m_target, localPort); + QVERIFY(val != -1); + + // STEP 2: + QString message2("testcase2 string str2"); + QByteArray tmpArray2(message2.toAscii()); + const char* data2 = tmpArray2.data(); + qint64 strSize2 = message2.size(); + qint64 val2 = localSocket.writeDatagram(data2, strSize2, m_target, localPort); + QVERIFY(val2 != -1); + + // STEP 3: + const int Timeout = 2 * 1000; + bool ret = localSocket.waitForBytesWritten(Timeout); + QVERIFY(ret); + + // STEP 4: + ret = localSocket.waitForBytesWritten(Timeout); + QVERIFY(ret); + + QString messageBox("handshake 3"); + QNfcTestUtil::ShowAutoMsg(messageBox); + + // STEP 5: Try to cover waitForBytesWritten() in bound mode + const int Timeout1 = 1 * 1000; + localSocket.waitForBytesWritten(Timeout1); + QVERIFY(ret); +} + +/*! + Description: coverage testcase - targeted for sender doCancel +*/ +void tst_qllcpsocketlocal::testCase3() +{ + QLlcpSocket localSocket; + // STEP 1: + QString message("string1"); + QByteArray tmpArray(message.toAscii()); + const char* data = tmpArray.data(); + qint64 strSize = message.size(); + localSocket.writeDatagram(data,strSize,m_target, m_port); +} + +/*! + Description: coverage testcase - invalid usage of connection-oriented API +*/ +void tst_qllcpsocketlocal::coverageTest1() +{ + QLlcpSocket localSocket; + + QSignalSpy errorSpy(&localSocket, SIGNAL(error(QLlcpSocket::SocketError))); + localSocket.connectToService(m_target,"uri"); + QTRY_VERIFY(errorSpy.count() == 1); + QVERIFY(localSocket.error() == QLlcpSocket::UnknownSocketError); + + localSocket.disconnectFromService(); + QTRY_VERIFY(errorSpy.count() == 2); + + QVERIFY(localSocket.waitForConnected() == false); + QVERIFY(localSocket.waitForDisconnected() == false); + + QString message = "Oops, must follow a port parameter"; + QByteArray tmpArray(message.toAscii()); + const char* data = tmpArray.data(); + qint64 strSize = message.size(); + qint64 ret = localSocket.writeDatagram(data,strSize); + QVERIFY(ret == -1); +} + +class BytesWrittenSlot : public QObject +{ + Q_OBJECT +public: + BytesWrittenSlot(QLlcpSocket* s): m_socket(s) + { + connect(m_socket,SIGNAL(bytesWritten(qint64)),this,SLOT(gotBytesWritten(qint64))); + } +private slots: + void gotBytesWritten(qint64 w) + { + qDebug()<<"In BytesWrittenSlot: Delete the socket when still alive..."; + delete m_socket; + } +private: + QLlcpSocket* m_socket; +}; +/*! + Description: Add a case to test delete the socket in the slot when the transmission is still alive. + CounterPart test: tst_qllcpsocketremote::dumpServer() +*/ +void tst_qllcpsocketlocal::deleteSocketWhenInUse() + { + QString message("deleteSocketWhenInUse test"); + QNfcTestUtil::ShowAutoMsg(message); + + QLlcpSocket* socket = new QLlcpSocket; + + bool retBool = socket->bind(m_port); + QVERIFY(retBool); + + // STEP 3: Local peer sends the message to the remote peer + QSignalSpy errorSpy(socket, SIGNAL(error(QLlcpSocket::SocketState))); + + BytesWrittenSlot slot(socket); + + QString echo; + for (int i = 0; i < 2000; i++) + echo.append((char)(i%26 + 'a')); + //Prepare data to send + QByteArray outPayload; + QDataStream out(&outPayload, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + + out.device()->seek(0); + out << (quint16)(outPayload.size() - sizeof(quint16)); + + bool ret = socket->writeDatagram(outPayload, m_target, m_port); + QVERIFY(ret == 0); + + QTest::qWait(5 * 1000);//give some time to wait bytesWritten signal + QVERIFY(errorSpy.isEmpty()); + + } + +class WaitBytesWrittenSlot : public QObject +{ + Q_OBJECT +public: + WaitBytesWrittenSlot(QLlcpSocket& s): m_socket(s),m_signalCount(0) + { + connect(&m_socket,SIGNAL(bytesWritten(qint64)),this,SLOT(gotBytesWritten(qint64))); + } +private slots: +void gotBytesWritten(qint64 w) + { + m_signalCount++; + qDebug()<<"Got BytesWritten() signal number = "<<m_signalCount; + const int Timeout = 50;//3* 1000 seems too long, nfc server will panic spray signal + bool ret = m_socket.waitForBytesWritten(Timeout); + if (!ret) + { + qDebug()<<"WaitBytesWrittenSlot() in slot of ReadyRead signal return false"; + } + else + { + qDebug()<<"WaitBytesWrittenSlot() in slot of ReadyRead signal return true"; + } + } +private: + QLlcpSocket& m_socket; + int m_signalCount; +}; +/*! + Description: Test WaitForBytesWritten() in slot of + bytesWritten signal, make sure the signal will not + be emitted twice in the slot function. + CounterPart test: tst_qllcpsocketremote::echoServer() +*/ +void tst_qllcpsocketlocal::waitBytesWrittenInSlot() +{ + QLlcpSocket localSocket; + + QCOMPARE(localSocket.state(), QLlcpSocket::UnconnectedState); + QSignalSpy stateChangedSpy(&localSocket, SIGNAL(stateChanged(QLlcpSocket::SocketState))); + + QSignalSpy readyReadSpy(&localSocket, SIGNAL(readyRead())); + bool retBool = localSocket.bind(m_port); + QVERIFY(retBool); + QVERIFY(!stateChangedSpy.isEmpty()); + QCOMPARE(localSocket.state(), QLlcpSocket::BoundState); + + // Wait remote part bind + QString messageBox("Wait remote bind"); + QNfcTestUtil::ShowAutoMsg(messageBox); + + // STEP 3: Local peer sends the message to the remote peer + QSignalSpy errorSpy(&localSocket, SIGNAL(error(QLlcpSocket::SocketState))); + QSignalSpy bytesWrittenSpy(&localSocket, SIGNAL(bytesWritten(qint64))); + + WaitBytesWrittenSlot slot(localSocket); + + QString echoPayload; + for (int i = 0; i < 2000; i++) + echoPayload.append((char)(i%26 + 'a')); + //Prepare data to send + QByteArray outPayload; + QDataStream out(&outPayload, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echoPayload; + + out.device()->seek(0); + out << (quint16)(outPayload.size() - sizeof(quint16)); + + bool ret = localSocket.writeDatagram(outPayload, m_target, m_port); + QVERIFY(ret == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + + qint64 written = 0; + qint32 lastSignalCount = 0; + while(true) + { + for(int i = lastSignalCount; i < bytesWrittenSpy.count(); i++) { + written += bytesWrittenSpy.at(i).at(0).value<qint64>(); + } + lastSignalCount = bytesWrittenSpy.count(); + qDebug() << "current signal count = " << lastSignalCount; + qDebug() << "written payload size = " << written; + if (written < outPayload.size()) { + QTRY_VERIFY(bytesWrittenSpy.count() > lastSignalCount); + } + else { + break; + } + } + qDebug() << "Overall bytesWritten = " << written; + qDebug() << "Overall block size = " << outPayload.size(); + QVERIFY(written == outPayload.size()); + + // STEP 4: Start read payload from server + QString messageBox2("Wait remote send buffer"); + QNfcTestUtil::ShowAutoMsg(messageBox2, &readyReadSpy); + + QByteArray inPayload; + while(localSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(localSocket.pendingDatagramSize()); + quint8 remotePort = 0; + QSignalSpy readyRead(&localSocket, SIGNAL(readyRead())); + qint64 readSize = localSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Client-- read inPayload size=" << inPayload.size(); + qDebug() << "Client-- read remotePort=" << remotePort; + if (inPayload.size() >= (int)sizeof(quint16)) { + break; + } + else + { + qDebug() << "Client-- not enough header"; + QTRY_VERIFY(!readyRead.isEmpty()); + } + } + + QDataStream in(inPayload); + in.setVersion(QDataStream::Qt_4_6); + quint16 headerSize = 0; // size of real echo payload + in >> headerSize; + qDebug() << "Client-- read headerSize=" << headerSize; + while (inPayload.size() < headerSize + (int)sizeof(quint16)){ + QSignalSpy readyRead(&localSocket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + if(localSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(localSocket.pendingDatagramSize()); + quint8 remotePort = 0; + qint64 readSize = localSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Client-- read long blocksize=" << inPayload.size(); + } + } + + QDataStream in2(inPayload); + in2.setVersion(QDataStream::Qt_4_6); + in2 >> headerSize; + QString inEchoPayload; + in2 >> inEchoPayload; + qDebug() << "Client-- in echo string len:" << inEchoPayload.length(); + qDebug("Client-- in echo string = %s", qPrintable(inEchoPayload)); + //test the echoed string is same as the original string + QVERIFY(echoPayload == inEchoPayload); + // make sure the no error signal emitted + QVERIFY(errorSpy.isEmpty()); +} +/*! + Description: writeDatagram negative testcase I - invalid port num & wait* functions +*/ +void tst_qllcpsocketlocal::negTestCase1() +{ + QLlcpSocket localSocket; + QString message = "Oops, Invalid port num for writeDatagram"; + QByteArray tmpArray(message.toAscii()); + const char* data = tmpArray.data(); + qint64 strSize = message.size(); + qint8 invalidPort = -1; + qint64 ret = localSocket.writeDatagram(data,strSize,m_target, invalidPort); + QVERIFY(ret == -1); + + const int Timeout = 1 * 500; + bool retBool = localSocket.waitForBytesWritten(Timeout); + QVERIFY(!retBool); + + //Cover QLLCPUnConnected::WaitForReadyRead + retBool = localSocket.waitForReadyRead(Timeout); + QVERIFY(!retBool); + + //Cover QLLCPBind::WaitForReadyRead() + retBool = localSocket.waitForReadyRead(Timeout); + QVERIFY(!retBool); +} + +/*! + Description: bind negative test - double bind +*/ +void tst_qllcpsocketlocal::negTestCase2() +{ + QLlcpSocket localSocket1; + QLlcpSocket localSocket2; + // bind again will cause failure + bool ret2 = localSocket1.bind(m_port); + QVERIFY(ret2); + ret2 = localSocket2.bind(m_port); + QVERIFY(!ret2); +} + +/*! + Description: bind negative test - invalid port num +*/ +/* +void tst_qllcpsocketlocal::negTestCase3() +{ + QLlcpSocket localSocket; + bool ret = localSocket.bind(65); + QVERIFY(ret == false); +} +*/ + +/*! + Description: bind negative test - invalid port num II +*/ +/* +void tst_qllcpsocketlocal::negTestCase4() +{ + QLlcpSocket localSocket; + int reservedPort = 15; + bool ret = localSocket.bind(reservedPort); + QVERIFY(ret == false); +} +*/ +void tst_qllcpsocketlocal::multiSocketToOneServer() +{ + QString echoPayload = "multiSocketToOneServer"; + { + QLlcpSocket localSocket; + + + QCOMPARE(localSocket.state(), QLlcpSocket::UnconnectedState); + QSignalSpy stateChangedSpy(&localSocket, SIGNAL(stateChanged(QLlcpSocket::SocketState))); + + // STEP 2: bind the local port for current socket + QSignalSpy readyReadSpy(&localSocket, SIGNAL(readyRead())); + bool retBool = localSocket.bind(m_port); + QVERIFY(retBool); + QVERIFY(!stateChangedSpy.isEmpty()); + QCOMPARE(localSocket.state(), QLlcpSocket::BoundState); + + // Wait remote part bind + QString messageBox("Wait remote bind"); + QNfcTestUtil::ShowAutoMsg(messageBox); + + // STEP 3: Local peer sends the message to the remote peer + QSignalSpy errorSpy(&localSocket, SIGNAL(error(QLlcpSocket::SocketState))); + QSignalSpy bytesWrittenSpy(&localSocket, SIGNAL(bytesWritten(qint64))); + + //Prepare data to send + QByteArray outPayload; + QDataStream out(&outPayload, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echoPayload; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string length= %d", echoPayload.length()); + qDebug("Client-- write payload length = %d", outPayload.length()); + out.device()->seek(0); + out << (quint16)(outPayload.size() - sizeof(quint16)); + + bool ret = localSocket.writeDatagram(outPayload, m_target, m_port); + QVERIFY(ret == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + + qint64 written = 0; + qint32 lastSignalCount = 0; + while(true) + { + for(int i = lastSignalCount; i < bytesWrittenSpy.count(); i++) { + written += bytesWrittenSpy.at(i).at(0).value<qint64>(); + } + lastSignalCount = bytesWrittenSpy.count(); + qDebug() << "current signal count = " << lastSignalCount; + qDebug() << "written payload size = " << written; + if (written < outPayload.size()) { + QTRY_VERIFY(bytesWrittenSpy.count() > lastSignalCount); + } + else { + break; + } + } + qDebug() << "Overall bytesWritten = " << written; + qDebug() << "Overall block size = " << outPayload.size(); + QVERIFY(written == outPayload.size()); + + // STEP 4: Start read payload from server + QString messageBox2("Wait remote send buffer"); + QNfcTestUtil::ShowAutoMsg(messageBox2, &readyReadSpy); + + QByteArray inPayload; + while(localSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(localSocket.pendingDatagramSize()); + quint8 remotePort = 0; + QSignalSpy readyRead(&localSocket, SIGNAL(readyRead())); + qint64 readSize = localSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Client-- read inPayload size=" << inPayload.size(); + qDebug() << "Client-- read remotePort=" << remotePort; + if (inPayload.size() >= (int)sizeof(quint16)) { + break; + } + else + { + qDebug() << "Client-- not enough header"; + QTRY_VERIFY(!readyRead.isEmpty()); + } + } + + QDataStream in(inPayload); + in.setVersion(QDataStream::Qt_4_6); + quint16 headerSize = 0; // size of real echo payload + in >> headerSize; + qDebug() << "Client-- read headerSize=" << headerSize; + while (inPayload.size() < headerSize + (int)sizeof(quint16)){ + QSignalSpy readyRead(&localSocket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + if(localSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(localSocket.pendingDatagramSize()); + quint8 remotePort = 0; + qint64 readSize = localSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Client-- read long blocksize=" << inPayload.size(); + } + } + + QDataStream in2(inPayload); + in2.setVersion(QDataStream::Qt_4_6); + in2 >> headerSize; + QString inEchoPayload; + in2 >> inEchoPayload; + qDebug() << "Client-- in echo string len:" << inEchoPayload.length(); + qDebug("Client-- in echo string = %s", qPrintable(inEchoPayload)); + //test the echoed string is same as the original string + QVERIFY(echoPayload == inEchoPayload); + // make sure the no error signal emitted + QVERIFY(errorSpy.isEmpty()); + + } + { + QLlcpSocket localSocket; + + + QCOMPARE(localSocket.state(), QLlcpSocket::UnconnectedState); + QSignalSpy stateChangedSpy(&localSocket, SIGNAL(stateChanged(QLlcpSocket::SocketState))); + + // STEP 2: bind the local port for current socket + QSignalSpy readyReadSpy(&localSocket, SIGNAL(readyRead())); + bool retBool = localSocket.bind(m_port); + QVERIFY(retBool); + QVERIFY(!stateChangedSpy.isEmpty()); + QCOMPARE(localSocket.state(), QLlcpSocket::BoundState); + + // Wait remote part bind + QString messageBox("Wait remote bind"); + QNfcTestUtil::ShowAutoMsg(messageBox); + + // STEP 3: Local peer sends the message to the remote peer + QSignalSpy errorSpy(&localSocket, SIGNAL(error(QLlcpSocket::SocketState))); + QSignalSpy bytesWrittenSpy(&localSocket, SIGNAL(bytesWritten(qint64))); + + //Prepare data to send + QByteArray outPayload; + QDataStream out(&outPayload, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echoPayload; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string length= %d", echoPayload.length()); + qDebug("Client-- write payload length = %d", outPayload.length()); + out.device()->seek(0); + out << (quint16)(outPayload.size() - sizeof(quint16)); + + bool ret = localSocket.writeDatagram(outPayload, m_target, m_port); + QVERIFY(ret == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + + qint64 written = 0; + qint32 lastSignalCount = 0; + while(true) + { + for(int i = lastSignalCount; i < bytesWrittenSpy.count(); i++) { + written += bytesWrittenSpy.at(i).at(0).value<qint64>(); + } + lastSignalCount = bytesWrittenSpy.count(); + qDebug() << "current signal count = " << lastSignalCount; + qDebug() << "written payload size = " << written; + if (written < outPayload.size()) { + QTRY_VERIFY(bytesWrittenSpy.count() > lastSignalCount); + } + else { + break; + } + } + qDebug() << "Overall bytesWritten = " << written; + qDebug() << "Overall block size = " << outPayload.size(); + QVERIFY(written == outPayload.size()); + + // STEP 4: Start read payload from server + QString messageBox2("Wait remote send buffer"); + QNfcTestUtil::ShowAutoMsg(messageBox2, &readyReadSpy); + + QByteArray inPayload; + while(localSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(localSocket.pendingDatagramSize()); + quint8 remotePort = 0; + QSignalSpy readyRead(&localSocket, SIGNAL(readyRead())); + qint64 readSize = localSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Client-- read inPayload size=" << inPayload.size(); + qDebug() << "Client-- read remotePort=" << remotePort; + if (inPayload.size() >= (int)sizeof(quint16)) { + break; + } + else + { + qDebug() << "Client-- not enough header"; + QTRY_VERIFY(!readyRead.isEmpty()); + } + } + + QDataStream in(inPayload); + in.setVersion(QDataStream::Qt_4_6); + quint16 headerSize = 0; // size of real echo payload + in >> headerSize; + qDebug() << "Client-- read headerSize=" << headerSize; + while (inPayload.size() < headerSize + (int)sizeof(quint16)){ + QSignalSpy readyRead(&localSocket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + if(localSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(localSocket.pendingDatagramSize()); + quint8 remotePort = 0; + qint64 readSize = localSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Client-- read long blocksize=" << inPayload.size(); + } + } + + QDataStream in2(inPayload); + in2.setVersion(QDataStream::Qt_4_6); + in2 >> headerSize; + QString inEchoPayload; + in2 >> inEchoPayload; + qDebug() << "Client-- in echo string len:" << inEchoPayload.length(); + qDebug("Client-- in echo string = %s", qPrintable(inEchoPayload)); + //test the echoed string is same as the original string + QVERIFY(echoPayload == inEchoPayload); + // make sure the no error signal emitted + QVERIFY(errorSpy.isEmpty()); + + } + +} +void tst_qllcpsocketlocal::cleanupTest() +{ +} + +QTEST_MAIN(tst_qllcpsocketlocal); + +#include "tst_qllcpsocketlocal.moc" diff --git a/tests/nfcsymbianbackend/qllcpsocketremote/qllcpsocketremote.pro b/tests/nfcsymbianbackend/qllcpsocketremote/qllcpsocketremote.pro new file mode 100644 index 00000000..71175303 --- /dev/null +++ b/tests/nfcsymbianbackend/qllcpsocketremote/qllcpsocketremote.pro @@ -0,0 +1,24 @@ + +QT += testlib + +TARGET = tst_qllcpsocketremote +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qautomsgbox.h +SOURCES += tst_qllcpsocketremote.cpp \ + ../common/qautomsgbox.cpp +symbian:TARGET.CAPABILITY = ALL -TCB diff --git a/tests/nfcsymbianbackend/qllcpsocketremote/tst_qllcpsocketremote.cpp b/tests/nfcsymbianbackend/qllcpsocketremote/tst_qllcpsocketremote.cpp new file mode 100644 index 00000000..550c5458 --- /dev/null +++ b/tests/nfcsymbianbackend/qllcpsocketremote/tst_qllcpsocketremote.cpp @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> + +#include <qllcpsocket.h> +#include <qnearfieldmanager.h> +#include <qnearfieldtarget.h> +#include "qnfctestcommon.h" +#include "qnfctestutil.h" + +Q_DECLARE_METATYPE(QNearFieldTarget*) +Q_DECLARE_METATYPE(QLlcpSocket::SocketError); + +class tst_qllcpsocketremote : public QObject +{ + Q_OBJECT + +public: + tst_qllcpsocketremote(); + +private Q_SLOTS: + + void mulitpleServer(); + void echoServer(); + void testCase2(); + + void dumpServer(); + void multiConnection(); + + void initTestCase(); + void cleanupTest(); + + +private: + void readMessage(QLlcpSocket& remoteSocket,QByteArray& inPayload); + void verifyString(QString& longStr4k, QByteArray& inPayload); +private: + QNearFieldTarget *m_target; // Not own + quint8 m_port; +}; + +tst_qllcpsocketremote::tst_qllcpsocketremote() +{ + qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*"); + qRegisterMetaType<QLlcpSocket::SocketError>("QLlcpSocket::SocketError"); +} + +/*! + Description: Init test case for NFC LLCP connection-less mode socket - local peer + + TestScenario: + Touch a NFC device with LLCP connection-less service actived + + TestExpectedResults: + Signal of target detected has been found. +*/ +void tst_qllcpsocketremote::initTestCase() +{ + QNearFieldManager nfcManager; + QSignalSpy targetDetectedSpy(&nfcManager, SIGNAL(targetDetected(QNearFieldTarget*))); + nfcManager.startTargetDetection(QNearFieldTarget::NfcForumDevice); + + QString message("Please touch a NFC device with llcp client enabled"); + QNfcTestUtil::ShowAutoMsg(message, &targetDetectedSpy, 1); + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + m_target = targetDetectedSpy.at(targetDetectedSpy.count() - 1).at(0).value<QNearFieldTarget *>(); + QVERIFY(m_target!=NULL); + QVERIFY(m_target->accessMethods() & QNearFieldTarget::LlcpAccess); + QVERIFY(m_target->uid() == QByteArray()); + QVERIFY(m_target->type() == QNearFieldTarget::NfcForumDevice); + + m_port = 35; +} + + +void tst_qllcpsocketremote::readMessage( + QLlcpSocket& remoteSocket, + QByteArray& inPayload) +{ + // STEP 2: Receive data from the peer which send messages to + while(remoteSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(remoteSocket.pendingDatagramSize()); + quint8 remotePort = 0; + QSignalSpy readyRead(&remoteSocket, SIGNAL(readyRead())); + qint64 readSize = remoteSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Server-- read inPayload size=" << inPayload.size(); + qDebug() << "Server-- read remotePort=" << remotePort; + if (inPayload.size() >= (int)sizeof(quint16)) { + break; + } + else { + qDebug() << "Server-- not enough header"; + QTRY_VERIFY(!readyRead.isEmpty()); + } + } + + QDataStream in(inPayload); + quint16 headerSize = 0; // size of real echo payload + in >> headerSize; + qDebug() << "Server-- read headerSize=" << headerSize; + while (inPayload.size() < headerSize + (int)sizeof(quint16)){ + QSignalSpy readyRead(&remoteSocket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + if(remoteSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(remoteSocket.pendingDatagramSize()); + quint8 remotePort = 0; + qint64 readSize = remoteSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Server-- read long blocksize=" << inPayload.size(); + } + } +} + +void tst_qllcpsocketremote::verifyString( + QString& longStr, + QByteArray& inPayload) +{ + quint16 headerSize; + QDataStream in2(inPayload); + in2.setVersion(QDataStream::Qt_4_6); + in2 >> headerSize; + QString receivedLongStr; + in2 >> receivedLongStr; + qDebug() << "Client-- in received string len:" << receivedLongStr.length(); + qDebug("Client-- in received string = %s", qPrintable(receivedLongStr)); + //test the received string is same as the original string + QVERIFY(longStr == receivedLongStr); +} + + +/*! + Description: Description: Receive the message and send the acknowledged identical message + + TestScenario: 1. Remote peer binds to local port + 2. Remote peer receives the long message sending from the local peer + 3. Remote peer receives the other long message sending from the local peer + + TestExpectedResults: + 1. Remote peer binds to local port successfully. + 2. The 1st long message has been received from remote peer. + 3. The 2nd long message has been received from remote peer. +*/ +void tst_qllcpsocketremote::mulitpleServer() +{ + QLlcpSocket remoteSocket; + bool ret = remoteSocket.bind(m_port); + QVERIFY(ret); + + QString longStr1k; + for (int i = 0; i < 1000; i++) + longStr1k.append((char)(i%26 + 'a')); + + QString longStr2k; + for (int i = 0; i < 2000; i++) + longStr2k.append((char)(i%26 + 'b')); + + QSignalSpy readyReadSpy(&remoteSocket, SIGNAL(readyRead())); + QString message("mulitpleServer 1: Wait multiple msg coming"); + QNfcTestUtil::ShowAutoMsg(message, &readyReadSpy); + + QByteArray inPayload; + readMessage(remoteSocket,inPayload); + + QSignalSpy readyReadSpy2(&remoteSocket, SIGNAL(readyRead())); + QString message2("mulitpleServer 2: Wait multiple msg coming"); + QNfcTestUtil::ShowAutoMsg(message2, &readyReadSpy2); + + QByteArray inPayload2; + readMessage(remoteSocket,inPayload2); + + verifyString(longStr1k,inPayload); + verifyString(longStr2k,inPayload2); +} + +/*! + Description: Description: Receive the message and send the acknowledged identical message + + TestScenario: 1. Remote peer binds to local port + 2. Remote peer receives the message sending from the local peer + 3. Remote peer sends the echoed message to the local peer + + TestExpectedResults: + 1. Remote peer binds to local port successfully. + 2. The message has been received from remote peer. + 3. The message has be sent to local peer. +*/ +void tst_qllcpsocketremote::echoServer() +{ + QLlcpSocket remoteSocket; + // STEP 1: bind the local port for current socket + QSignalSpy readyReadSpy(&remoteSocket, SIGNAL(readyRead())); + bool ret = remoteSocket.bind(m_port); + QVERIFY(ret); + + QString message("Test 1: Wait client msg coming"); + QNfcTestUtil::ShowAutoMsg(message, &readyReadSpy); + + // STEP 2: Receive data from the peer which send messages to + QByteArray inPayload; + readMessage(remoteSocket,inPayload); + + // STEP 3: Send the received message back to the intiated device. + QSignalSpy errorSpy(&remoteSocket, SIGNAL(error(QLlcpSocket::SocketError))); + QSignalSpy bytesWrittenSpy(&remoteSocket, SIGNAL(bytesWritten(qint64))); + + qDebug("Server-- write payload length = %d", inPayload.length()); + qint64 val = remoteSocket.writeDatagram(inPayload, m_target, m_port); + QVERIFY(val != -1); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + + qint64 written = 0; + qint32 lastSignalCount = 0; + while(true) + { + for(int i = lastSignalCount; i < bytesWrittenSpy.count(); i++) { + written += bytesWrittenSpy.at(i).at(0).value<qint64>(); + } + lastSignalCount = bytesWrittenSpy.count(); + qDebug() << "current signal count = " << lastSignalCount; + qDebug() << "written payload size = " << written; + if (written < inPayload.size()) { + QTRY_VERIFY(bytesWrittenSpy.count() > lastSignalCount); + } + else { + break; + } + } + + qDebug() << "Overall bytesWritten = " << written; + qDebug() << "Overall block size = " << inPayload.size(); + QVERIFY(written == inPayload.size()); + // make sure the no error signal emitted + QCOMPARE(errorSpy.count(), 0); +} + +/*! + Description: This server will all dump data received from client + To test some negtive case +*/ +void tst_qllcpsocketremote::dumpServer() + { + QLlcpSocket remoteSocket; + QSignalSpy readyReadSpy(&remoteSocket, SIGNAL(readyRead())); + bool ret = remoteSocket.bind(m_port); + QVERIFY(ret); + QString message("dumpServer test"); + QNfcTestUtil::ShowAutoMsg(message, &readyReadSpy); + + QTest::qWait(2 * 1000); + } +/*! + Description: Unit test for NFC LLCP connection-less mode socket - remote peer (passive) + + TestScenario: 1. Remote peer binds to local port ( already done in testCase1) + 2. Remote peer receive datagram twice + 3. Remote peer waitForReadyRead + + TestExpectedResults: + 1. Remote peer binds to local port successfully. + 2. Remote peer receive datagram twice successfully + 3. waitForReadyRead return true as long as readyReadSpy not empty +*/ +void tst_qllcpsocketremote::testCase2() +{ + QLlcpSocket remoteSocket; + quint8 localPort = 38; + QSignalSpy readyReadSpy(&remoteSocket, SIGNAL(readyRead())); + bool ret = remoteSocket.bind(localPort); + QVERIFY(ret); + + // STEP 1: bind the local port for current socket + QString expectedMessage1("testcase2 string str1"); + QString expectedMessage2("testcase2 string str2"); + + QString boxMessage("handshake 3"); + QNfcTestUtil::ShowAutoMsg(boxMessage,&readyReadSpy); + + QTRY_VERIFY(readyReadSpy.count() == 1); + + QByteArray datagram; + if (remoteSocket.hasPendingDatagrams()) + { + datagram.resize(remoteSocket.pendingDatagramSize()); + qint64 readSize = remoteSocket.readDatagram(datagram.data(), datagram.size()); + QVERIFY(readSize != -1); + } + + QString receivedMessage1 = datagram.data(); + qDebug() << "receivedMessage1: " << receivedMessage1; + QVERIFY(expectedMessage1 == receivedMessage1); + + QTRY_VERIFY(readyReadSpy.count() == 2); + + QByteArray datagram2; + if (remoteSocket.hasPendingDatagrams()) + { + datagram2.resize(remoteSocket.pendingDatagramSize()); + qint64 readSize = remoteSocket.readDatagram(datagram2.data(), datagram2.size()); + QVERIFY(readSize != -1); + } + QString receivedMessage2 = datagram2.data(); + qDebug() << "receivedMessage2: " << receivedMessage2; + QVERIFY(expectedMessage2 == receivedMessage2); + + const int Timeout = 10 * 1000; + ret = remoteSocket.waitForReadyRead(Timeout); + + QVERIFY(ret == false); + } +void tst_qllcpsocketremote::multiConnection() + { + QLlcpSocket remoteSocket; + // STEP 1: bind the local port for current socket + QSignalSpy readyReadSpy(&remoteSocket, SIGNAL(readyRead())); + bool ret = remoteSocket.bind(m_port); + QVERIFY(ret); + + const int KLoopCount = 2; + int loopCount = 0; + + while(loopCount < KLoopCount) + { + QString message("Test 1: Wait client msg coming"); + QNfcTestUtil::ShowAutoMsg(message, &readyReadSpy); + + // STEP 2: Receive data from the peer which send messages to + QByteArray inPayload; + while(remoteSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(remoteSocket.pendingDatagramSize()); + quint8 remotePort = 0; + QSignalSpy readyRead(&remoteSocket, SIGNAL(readyRead())); + qint64 readSize = remoteSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Server-- read inPayload size=" << inPayload.size(); + qDebug() << "Server-- read remotePort=" << remotePort; + if (inPayload.size() >= (int)sizeof(quint16)) { + break; + } + else { + qDebug() << "Server-- not enough header"; + QTRY_VERIFY(!readyRead.isEmpty()); + } + } + + QDataStream in(inPayload); + quint16 headerSize = 0; // size of real echo payload + in >> headerSize; + qDebug() << "Server-- read headerSize=" << headerSize; + while (inPayload.size() < headerSize + (int)sizeof(quint16)){ + QSignalSpy readyRead(&remoteSocket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + if(remoteSocket.hasPendingDatagrams()) { + QByteArray tempBuffer; + tempBuffer.resize(remoteSocket.pendingDatagramSize()); + quint8 remotePort = 0; + qint64 readSize = remoteSocket.readDatagram(tempBuffer.data() + , tempBuffer.size() + , &m_target, &remotePort); + QVERIFY(readSize != -1); + QVERIFY(remotePort > 0); + inPayload.append(tempBuffer); + qDebug() << "Server-- read long blocksize=" << inPayload.size(); + } + } + + // STEP 3: Send the received message back to the intiated device. + QSignalSpy errorSpy(&remoteSocket, SIGNAL(error(QLlcpSocket::SocketError))); + QSignalSpy bytesWrittenSpy(&remoteSocket, SIGNAL(bytesWritten(qint64))); + + qDebug("Server-- write payload length = %d", inPayload.length()); + qint64 val = remoteSocket.writeDatagram(inPayload, m_target, m_port); + QVERIFY(val != -1); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + + qint64 written = 0; + qint32 lastSignalCount = 0; + while(true) + { + for(int i = lastSignalCount; i < bytesWrittenSpy.count(); i++) { + written += bytesWrittenSpy.at(i).at(0).value<qint64>(); + } + lastSignalCount = bytesWrittenSpy.count(); + qDebug() << "current signal count = " << lastSignalCount; + qDebug() << "written payload size = " << written; + if (written < inPayload.size()) { + QTRY_VERIFY(bytesWrittenSpy.count() > lastSignalCount); + } + else { + break; + } + } + + qDebug() << "Overall bytesWritten = " << written; + qDebug() << "Overall block size = " << inPayload.size(); + QVERIFY(written == inPayload.size()); + // make sure the no error signal emitted + QCOMPARE(errorSpy.count(), 0); + //wait another socket to send data + loopCount++; + readyReadSpy.removeFirst(); + } + QTest::qWait(1500);//give some time to client to finish + + } +void tst_qllcpsocketremote::cleanupTest() +{ +} + +QTEST_MAIN(tst_qllcpsocketremote); + +#include "tst_qllcpsocketremote.moc" diff --git a/tests/nfcsymbianbackend/qllcpsockettype2/qllcpsockettype2.pro b/tests/nfcsymbianbackend/qllcpsockettype2/qllcpsockettype2.pro new file mode 100644 index 00000000..0f0cc4fa --- /dev/null +++ b/tests/nfcsymbianbackend/qllcpsockettype2/qllcpsockettype2.pro @@ -0,0 +1,23 @@ +QT += testlib + +TARGET = tst_qllcpsockettype2 +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qautomsgbox.h +SOURCES += tst_qllcpsockettype2.cpp \ + ../common/qautomsgbox.cpp +symbian:TARGET.CAPABILITY = ALL -TCB diff --git a/tests/nfcsymbianbackend/qllcpsockettype2/tst_qllcpsockettype2.cpp b/tests/nfcsymbianbackend/qllcpsockettype2/tst_qllcpsockettype2.cpp new file mode 100644 index 00000000..cefdcd9f --- /dev/null +++ b/tests/nfcsymbianbackend/qllcpsockettype2/tst_qllcpsockettype2.cpp @@ -0,0 +1,1120 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> + +#include <qllcpsocket.h> +#include <qnearfieldmanager.h> +#include <qnearfieldtarget.h> +#include "qnfctestcommon.h" +#include "qnfctestutil.h" + +Q_DECLARE_METATYPE(QNearFieldTarget*) +Q_DECLARE_METATYPE(QLlcpSocket::SocketState) +Q_DECLARE_METATYPE(QLlcpSocket::SocketError) + +QString TestUri("urn:nfc:xsn:nokia:symbiantest"); +static qint64 countBytesWritten(QSignalSpy& bytesWrittenSpy) + { + qint64 ret = 0; + for(int i = 0; i < bytesWrittenSpy.count(); i++) + { + ret+=bytesWrittenSpy[i].at(0).value<qint64>(); + } + return ret; + } +class tst_qllcpsockettype2 : public QObject +{ + Q_OBJECT + +public: + tst_qllcpsockettype2(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + // basic acceptance testcases + void echo(); + void echo_data(); + void echo_wait(); + void echo_wait_data(); + void api_coverage(); + + void multipleWrite(); + void multipleWrite_data(); + // advanced testcases + void waitReadyReadInSlot(); + void deleteSocketWhenInUse(); + void multiSocketToOneServer(); + // nagetive testcases + void connectTest(); + void negTestCase1(); + void negTestCase2(); + void negTestCase3(); + + void sendEmptyData(); + + private: + QNearFieldTarget *m_target; // not own +}; + +tst_qllcpsockettype2::tst_qllcpsockettype2() +{ + qRegisterMetaType<QNearFieldTarget*>("QNearFieldTarget*"); + qRegisterMetaType<QLlcpSocket::SocketError>("QLlcpSocket::SocketError"); + qRegisterMetaType<QLlcpSocket::SocketState>("QLlcpSocket::SocketState"); +} + +void tst_qllcpsockettype2::initTestCase() +{ + qDebug()<<"tst_qllcpsockettype2::initTestCase() Begin"; + QString message("Please touch a NFC device with llcp client enabled"); + QNearFieldManager nfcManager; + QSignalSpy targetDetectedSpy(&nfcManager, SIGNAL(targetDetected(QNearFieldTarget*))); + nfcManager.startTargetDetection(QNearFieldTarget::NfcForumDevice); + + QNfcTestUtil::ShowAutoMsg(message, &targetDetectedSpy, 1); + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + m_target = targetDetectedSpy.at(targetDetectedSpy.count() - 1).at(0).value<QNearFieldTarget*>(); + QVERIFY(m_target != NULL); + QVERIFY(m_target->accessMethods() & QNearFieldTarget::LlcpAccess); + QVERIFY(m_target->uid() == QByteArray()); + QVERIFY(m_target->type() == QNearFieldTarget::NfcForumDevice); + qDebug()<<"tst_qllcpsockettype2::initTestCase() End"; +} + + +void tst_qllcpsockettype2::cleanupTestCase() +{ +} + + +/*! + Description: Unit test for NFC LLCP socket async functions + + TestScenario: + 1. Echo client will connect to the Echo server + 2. Echo client will send the "echo" message to the server + 3. Echo client will receive the same message echoed from the server + 4. Echo client will disconnect the connection. + + TestExpectedResults: + 2. The message has be sent to server. + 3. The echoed message has been received from server. + 4. Connection disconnected and NO error signals emitted. + + CounterPart test: tst_QLlcpServer::newConnection() or newConnection_wait() +*/ +void tst_qllcpsockettype2::echo() +{ + QFETCH(QString, uri); + QFETCH(QString, echo); + + QString message("echo test"); + + QNfcTestUtil::ShowAutoMsg(message); + QLlcpSocket socket(this); + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + QSignalSpy errorSpy(&socket, SIGNAL(error(QLlcpSocket::SocketError))); + QSignalSpy readyReadSpy(&socket, SIGNAL(readyRead())); + + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + + socket.connectToService(m_target, uri); + + // coverage add: WaitForBytesWritten will fail when connecting + const int secs = 1 * 1000; + bool waitRet = socket.waitForBytesWritten(secs); + QVERIFY( waitRet == false); + + QTRY_VERIFY(!connectedSpy.isEmpty()); + + // coverage add: connect to Service again when already connected will cause fail + socket.connectToService(m_target, uri); + QTRY_VERIFY(!errorSpy.isEmpty()); + errorSpy.clear(); + + //Send data to server + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(echo)); + qDebug("Client-- write echo string length= %d", echo.length()); + qDebug("Client-- write data length = %d", block.length()); + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + qint64 val = socket.write(block); + QVERIFY( val == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy); + + qDebug()<<"bytesWritten signal return value = "<<written; + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 w = countBytesWritten(bytesWrittenSpy); + qDebug()<<"got bytesWritten signal = "<<w; + written += w; + } + qDebug()<<"Overall bytesWritten = "<<written; + qDebug()<<"Overall block size = "<<block.size(); + QTRY_VERIFY(written == block.size()); + //Get the echoed data from server + QTRY_VERIFY(!readyReadSpy.isEmpty()); + quint16 blockSize = 0; + QDataStream in(&socket); + in.setVersion(QDataStream::Qt_4_6); + while (socket.bytesAvailable() < (int)sizeof(quint16)){ + QSignalSpy readyRead(&socket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + in >> blockSize; + qDebug() << "Client-- read blockSize=" << blockSize; + while (socket.bytesAvailable() < blockSize){ + QSignalSpy readyRead(&socket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + QString echoed; + in >> echoed; + + qDebug() << "Client-- read echoed string =" << echoed; + //test the echoed string is same as the original string + QVERIFY(echo == echoed); + + socket.disconnectFromService(); + + //Now data has been sent,check the if existing error + QVERIFY(errorSpy.isEmpty()); +} + +void tst_qllcpsockettype2::echo_data() +{ + QTest::addColumn<QString>("uri"); + QTest::addColumn<QString>("echo"); + QTest::newRow("0") << TestUri + << "echo"; + QString longStr4k; + for (int i = 0; i < 4000; i++) + longStr4k.append((char)(i%26 + 'a')); + QTest::newRow("1") << TestUri << longStr4k; +} + +/*! + Description: Unit test for NFC LLCP socket sync(waitXXX) functions + + TestScenario: 1. Touch a NFC device with LLCP Echo service actived + 2. Echo client will connect to the Echo server + 3. Echo client will send the "echo" message to the server + 4. Echo client will receive the same message echoed from the server + 5. Echo client will disconnect the connection. + + TestExpectedResults: + 1. The connection successfully set up. + 2. The message has be sent to server. + 3. The echoed message has been received from server. + 4. Connection disconnected and NO error signals emitted. + + CounterPart test: tst_QLlcpServer::newConnection() or newConnection_wait() +*/ +void tst_qllcpsockettype2::echo_wait() + { + QFETCH(QString, uri); + QFETCH(QString, echo); + + QString message("echo_wait test"); + + QNfcTestUtil::ShowAutoMsg(message); + QLlcpSocket socket(this); + const int Timeout = 10 * 1000; + + socket.connectToService(m_target, uri); + + bool ret = socket.waitForConnected(Timeout); + QVERIFY(ret); + + QSignalSpy errorSpy(&socket, SIGNAL(error(QLlcpSocket::SocketError))); + + //Send data to server + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + + //Send data to server + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(echo)); + qDebug("Client-- write echo string length= %d", echo.length()); + qDebug("Client-- write data length = %d", block.length()); + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + qint64 val = socket.write(block); + QVERIFY( val == 0); + + ret = socket.waitForBytesWritten(Timeout); + QVERIFY(ret); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy); + + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + ret = socket.waitForBytesWritten(Timeout); + QVERIFY(ret); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + written += countBytesWritten(bytesWrittenSpy); + } + QVERIFY(written == block.size()); + //Get the echoed data from server + quint16 blockSize = 0; + QDataStream in(&socket); + in.setVersion(QDataStream::Qt_4_6); + while (socket.bytesAvailable() < (int)sizeof(quint16)){ + ret = socket.waitForReadyRead(Timeout); + QVERIFY(ret); + } + in >> blockSize; + qDebug() << "Client-- read blockSize=" << blockSize; + while (socket.bytesAvailable() < blockSize){ + ret = socket.waitForReadyRead(Timeout); + QVERIFY(ret); + } + QString echoed; + in >> echoed; + qDebug() << "Client-- read echoed string =" << echoed; + //test the echoed string is same as the original string + QVERIFY(echo == echoed); + + socket.disconnectFromService(); + ret = socket.waitForDisconnected(Timeout); + QVERIFY(ret); + //Now data has been sent,check the if existing error + QVERIFY(errorSpy.isEmpty()); + } + +void tst_qllcpsockettype2::echo_wait_data() +{ + QTest::addColumn<QString>("uri"); + QTest::addColumn<QString>("echo"); + QTest::newRow("0") << TestUri + << "echo"; + QString longStr4k; + for (int i = 0; i < 4000; i++) + longStr4k.append((char)(i%26 + 'a')); + QTest::newRow("1") << TestUri << longStr4k; +} + + + +/*! + Description: LLCP Socket API & State Machine test (ReadDatagram tested in server side) + TestScenario: + Covered API: state(), error(), writeDatagram(const char *data, qint64 size); + writeDatagram(const QByteArray &datagram); + + CounterPart test: tst_QLlcpServer::api_coverage() + */ +void tst_qllcpsockettype2::api_coverage() +{ + + QString message("api_coverage test"); + + QNfcTestUtil::ShowAutoMsg(message); + + QLlcpSocket socket(this); + QCOMPARE(socket.state(), QLlcpSocket::UnconnectedState); + QSignalSpy stateChangedSpy(&socket, SIGNAL(stateChanged(QLlcpSocket::SocketState))); + + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + socket.connectToService(m_target, TestUri); + QTRY_VERIFY(!connectedSpy.isEmpty()); + + QVERIFY(stateChangedSpy.count() == 2); + QLlcpSocket::SocketState state1 = stateChangedSpy.at(0).at(0).value<QLlcpSocket::SocketState>(); + QLlcpSocket::SocketState state2 = stateChangedSpy.at(1).at(0).value<QLlcpSocket::SocketState>(); + QCOMPARE(state1, QLlcpSocket::ConnectingState); + QCOMPARE(state2, QLlcpSocket::ConnectedState); + + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + message = "Connection oriented write test string"; + QByteArray array; + array.append(message); + qint64 ret = socket.writeDatagram(array.constData(),array.size()); + QVERIFY( ret == 0); + + QTRY_VERIFY(bytesWrittenSpy.count() == 1); + qint64 w = bytesWrittenSpy.first().at(0).value<qint64>(); + QVERIFY(w == array.size()); + stateChangedSpy.clear(); + socket.disconnectFromService(); + QVERIFY(stateChangedSpy.count() == 1); + state1 = stateChangedSpy.at(0).at(0).value<QLlcpSocket::SocketState>(); + QCOMPARE(state1, QLlcpSocket::UnconnectedState); + + QCOMPARE(socket.error(),QLlcpSocket::UnknownSocketError); + +} + + +/*! + Description: connect to Service testcases + TestScenario: 1) double connect cause failure + 2) disconnect the connecting socket should not cause failure + 3) readDatagram after disconnection will cause failure. + + CounterPart test: tst_QLlcpServer::negTestCase1() + */ +void tst_qllcpsockettype2::connectTest() +{ + QString message("connectTest"); + + QNfcTestUtil::ShowAutoMsg(message); + + QLlcpSocket socket(this); + QCOMPARE(socket.state(), QLlcpSocket::UnconnectedState); + QSignalSpy errorSpy(&socket, SIGNAL(error(QLlcpSocket::SocketError))); + + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + socket.connectToService(m_target, TestUri); + + //connect to the service again when previous one is connecting + socket.connectToService(m_target, TestUri); + QTRY_VERIFY(!errorSpy.isEmpty()); + + errorSpy.clear(); + // make sure it is still connecting + if(connectedSpy.isEmpty()) + { + socket.disconnectFromService(); + } + QTRY_VERIFY(errorSpy.isEmpty()); + + //double disconnect should not cause error + socket.disconnectFromService(); + QTRY_VERIFY(errorSpy.isEmpty()); + + // readDatagram must be called before successul connection to server + QByteArray datagram; + datagram.resize(127); + qint64 ret = socket.readDatagram(datagram.data(), datagram.size()); + QVERIFY(ret == -1); +} + +/*! + Description: Unit test for NFC LLCP socket write several times + + TestScenario: + 1. Echo client will connect to the Echo server + 2. Echo client will send the "echo" message to the server + 3. Echo client will receive the same message echoed from the server + 4. Echo client will disconnect the connection. + + TestExpectedResults: + 2. The message has be sent to server. + 3. The echoed message has been received from server. + 4. Connection disconnected and NO error signals emitted. + + CounterPart test: tst_QLlcpServer::newConnection() or newConnection_wait() +*/ +void tst_qllcpsockettype2::multipleWrite() + { + QFETCH(QString, uri); + QFETCH(QString, echo); + QString message("multipleWrite test"); + QNfcTestUtil::ShowAutoMsg(message); + + QLlcpSocket socket(this); + + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + socket.connectToService(m_target, uri); + QTRY_VERIFY(!connectedSpy.isEmpty()); + + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + qint64 ret = socket.writeDatagram(block.constData(), block.size()/2); + QVERIFY( ret == 0); + ret = socket.writeDatagram(block.constData() + block.size()/2, block.size() - block.size()/2); + QVERIFY( ret == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy);; + + qDebug()<<"bytesWritten signal return value = "<<written; + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 w = countBytesWritten(bytesWrittenSpy); + qDebug()<<"got bytesWritten signal = "<<w; + written += w; + } + qDebug()<<"Overall bytesWritten = "<<written; + qDebug()<<"Overall block size = "<<block.size(); + QCOMPARE(written, (qint64)block.size()); + + //Get the echoed data from server + const int Timeout = 10 * 1000; + quint16 blockSize = 0; + QDataStream in(&socket); + in.setVersion(QDataStream::Qt_4_6); + while (socket.bytesAvailable() < (int)sizeof(quint16)){ + ret = socket.waitForReadyRead(Timeout); + QVERIFY(ret); + } + in >> blockSize; + qDebug() << "Client-- read blockSize=" << blockSize; + while (socket.bytesAvailable() < blockSize){ + ret = socket.waitForReadyRead(Timeout); + QVERIFY(ret); + } + QString echoed; + in >> echoed; + qDebug() << "Client-- read echoed string =" << echoed; + //test the echoed string is same as the original string + QCOMPARE(echoed, echo); + socket.disconnectFromService(); + ret = socket.waitForDisconnected(Timeout); + QVERIFY(ret); + } + +void tst_qllcpsockettype2::multipleWrite_data() +{ + QTest::addColumn<QString>("uri"); + QTest::addColumn<QString>("echo"); + QTest::newRow("0") << TestUri + << "1234567890"; + QString longStr4k; + for (int i = 0; i < 4000; i++) + longStr4k.append((char)(i%26 + 'a')); + QTest::newRow("1") << TestUri << longStr4k; +} +/*! + Description: coverage test - cover sender DoCancel() method + CounterPart test: tst_QLlcpServer::negTestCase1() +*/ +void tst_qllcpsockettype2::negTestCase1() +{ + QString message("negTestCase1 test"); + QNfcTestUtil::ShowAutoMsg(message); + + QLlcpSocket socket(this); + + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + socket.connectToService(m_target, TestUri); + QTRY_VERIFY(!connectedSpy.isEmpty()); + + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + message = "1234567890"; + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << message; + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + qint64 ret = socket.writeDatagram(block.constData(), block.size()); + QVERIFY( ret != -1); + //cover SenderAO DoCancel() method +} + +/*! + Description: readDatagram/writeDatagram negative test - read/write without connectToService + + CounterPart test: No need counterpart in server side +*/ +void tst_qllcpsockettype2::negTestCase2() +{ + QLlcpSocket socket(this); + QByteArray datagram("Connection oriented negTestCase2"); + qint64 ret = socket.writeDatagram(datagram); + QTRY_VERIFY(ret == -1); + ret = socket.readDatagram(datagram.data(),datagram.size()); + QTRY_VERIFY(ret == -1); +} + + +/*! + Description: negative testcase II - invalid usage of connection-less API + CounterPart test: tst_QLlcpServer::negTestCase1() +*/ +void tst_qllcpsockettype2::negTestCase3() +{ + QLlcpSocket socket(this); + + QString message("negTestCase3 test"); + QNfcTestUtil::ShowAutoMsg(message); + + QSignalSpy errorSpy(&socket, SIGNAL(error(QLlcpSocket::SocketError))); + socket.connectToService(m_target, TestUri); + + bool ret = socket.bind(35); + QVERIFY(ret == false); + + ret = socket.hasPendingDatagrams(); + QVERIFY(ret == false); + + qint64 size = socket.pendingDatagramSize(); + QVERIFY(size == -1); + + message = "Oops, Invalid usage for writeDatagram"; + const char* data = (const char *) message.data(); + qint64 strSize = message.size(); + size = socket.writeDatagram(data,strSize,m_target, 35); + QVERIFY(size == -1); + QByteArray datagram(data); + size = socket.writeDatagram(datagram,m_target, 35); + QVERIFY(size == -1); + + quint8 port = 35; + size = socket.readDatagram(datagram.data(),datagram.size(),&m_target, &port); + QVERIFY(size == -1); + +} +/*! + Description: Send empty data to server + CounterPart test: tst_QLlcpServer::negTestCase1() +*/ +void tst_qllcpsockettype2::sendEmptyData() + { + + QString message("sendEmptyData test"); + + QNfcTestUtil::ShowAutoMsg(message); + QLlcpSocket socket(this); + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + QSignalSpy errorSpy(&socket, SIGNAL(error(QLlcpSocket::SocketError))); + QSignalSpy readyReadSpy(&socket, SIGNAL(readyRead())); + + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + + socket.connectToService(m_target, TestUri); + + QTRY_VERIFY(!connectedSpy.isEmpty()); + + //Send data to server + QByteArray block; + + qDebug("Client-- write data length = %d", block.length()); + + qint64 val = socket.write(block); + QVERIFY(val == -1); + + socket.disconnectFromService(); + + //Now data has been sent,check the if existing error + QVERIFY(errorSpy.isEmpty()); + } +class ReadyReadSlot : public QObject +{ + Q_OBJECT +public: + ReadyReadSlot(QLlcpSocket& s): m_socket(s),m_signalCount(0) + { + connect(&m_socket,SIGNAL(readyRead()),this,SLOT(gotReadyRead())); + } +private slots: + void gotReadyRead() + { + m_signalCount++; + qDebug()<<"Got ReadyRead() signal number = "<<m_signalCount; + const int Timeout = 50;//3* 1000 seems too long, nfc server will panic spray signal + bool ret = m_socket.waitForReadyRead(Timeout); + if (!ret) + { + qDebug()<<"WaitForReadyRead() in slot of ReadyRead signal return false"; + } + else + { + qDebug()<<"WaitForReadyRead() in slot of ReadyRead signal return true"; + } + } +private: + QLlcpSocket& m_socket; + int m_signalCount; +}; +/*! + Description: Test WaitForReadyRead() in slot of + ReadyRead signal, make sure the signal will not + be emitted twice in the slot function. + CounterPart test: tst_QLlcpServer::newConnection() +*/ +void tst_qllcpsockettype2::waitReadyReadInSlot() +{ + QString message("waitReadyReadInSlot test"); + + QNfcTestUtil::ShowAutoMsg(message); + QLlcpSocket socket(this); + QSignalSpy connectedSpy(&socket, SIGNAL(connected())); + QSignalSpy errorSpy(&socket, SIGNAL(error(QLlcpSocket::SocketError))); + + QSignalSpy readyReadSpy(&socket, SIGNAL(readyRead())); + ReadyReadSlot slot(socket); + + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + + socket.connectToService(m_target, TestUri); + + QTRY_VERIFY(!connectedSpy.isEmpty()); + + QString echo; + for (int i = 0; i < 2000; i++) + echo.append((char)(i%26 + 'a')); + //Send data to server + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(echo)); + qDebug("Client-- write echo string length= %d", echo.length()); + qDebug("Client-- write data length = %d", block.length()); + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + qint64 val = socket.write(block); + QVERIFY( val == 0); + + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy); + + qDebug()<<"bytesWritten signal return value = "<<written; + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(&socket, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 w = countBytesWritten(bytesWrittenSpy); + qDebug()<<"got bytesWritten signal = "<<w; + written += w; + } + qDebug()<<"Overall bytesWritten = "<<written; + qDebug()<<"Overall block size = "<<block.size(); + QTRY_VERIFY(written == block.size()); + //Get the echoed data from server + QTRY_VERIFY(!readyReadSpy.isEmpty()); + quint16 blockSize = 0; + QDataStream in(&socket); + in.setVersion(QDataStream::Qt_4_6); + while (socket.bytesAvailable() < (int)sizeof(quint16)){ + QSignalSpy readyRead(&socket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + in >> blockSize; + qDebug() << "Client-- read blockSize=" << blockSize; + while (socket.bytesAvailable() < blockSize){ + QSignalSpy readyRead(&socket, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + QString echoed; + in >> echoed; + + qDebug() << "Client-- read echoed string =" << echoed; + //test the echoed string is same as the original string + QVERIFY(echo == echoed); + + socket.disconnectFromService(); + + //Now data has been sent,check the if existing error + QVERIFY(errorSpy.isEmpty()); +} + +class BytesWrittenSlot : public QObject +{ + Q_OBJECT +public: + BytesWrittenSlot(QLlcpSocket* s): m_socket(s) + { + connect(m_socket,SIGNAL(bytesWritten(qint64)),this,SLOT(gotBytesWritten(qint64))); + } +private slots: + void gotBytesWritten(qint64 w) + { + qDebug()<<"In BytesWrittenSlot: Delete the socket when still alive..."; + delete m_socket; + } +private: + QLlcpSocket* m_socket; +}; +/*! + Description: Add a case to test delete the socket in the slot when the transmission is still alive. + CounterPart test: tst_QLlcpServer::negTestCase1() +*/ +void tst_qllcpsockettype2::deleteSocketWhenInUse() + { + QString message("deleteSocketWhenInUse test"); + + QNfcTestUtil::ShowAutoMsg(message); + QLlcpSocket* socket = new QLlcpSocket; + QSignalSpy connectedSpy(socket, SIGNAL(connected())); + QSignalSpy errorSpy(socket, SIGNAL(error(QLlcpSocket::SocketError))); + + BytesWrittenSlot slot(socket); + QSignalSpy bytesWrittenSpy(socket, SIGNAL(bytesWritten(qint64))); + + socket->connectToService(m_target, TestUri); + + QTRY_VERIFY(!connectedSpy.isEmpty()); + + QString echo; + for (int i = 0; i < 2000; i++) + echo.append((char)(i%26 + 'a')); + //Send data to server + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(echo)); + qDebug("Client-- write echo string length= %d", echo.length()); + qDebug("Client-- write data length = %d", block.length()); + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + qint64 val = socket->write(block); + QVERIFY( val == 0); + QTest::qWait(5 * 1000);//give some time to wait bytesWritten signal + QVERIFY(errorSpy.isEmpty()); + } +/*! + Description: Add a server in one device, then two + client socket in another device to connect the server at same time + CounterPart test: tst_QLlcpServer::multiConnection() +*/ +void tst_qllcpsockettype2::multiSocketToOneServer() + { + QString message("multiSocketToOneServer test"); + + QNfcTestUtil::ShowAutoMsg(message); + QLlcpSocket* socket1 = new QLlcpSocket; + QLlcpSocket* socket2 = new QLlcpSocket; + QSignalSpy connectedSpy1(socket1, SIGNAL(connected())); + QSignalSpy errorSpy1(socket1, SIGNAL(error(QLlcpSocket::SocketError))); + QSignalSpy readyReadSpy1(socket1, SIGNAL(readyRead())); + QSignalSpy bytesWrittenSpy1(socket1, SIGNAL(bytesWritten(qint64))); + + QSignalSpy connectedSpy2(socket2, SIGNAL(connected())); + QSignalSpy errorSpy2(socket2, SIGNAL(error(QLlcpSocket::SocketError))); + QSignalSpy readyReadSpy2(socket2, SIGNAL(readyRead())); + QSignalSpy bytesWrittenSpy2(socket2, SIGNAL(bytesWritten(qint64))); + + socket1->connectToService(m_target, TestUri); + socket2->connectToService(m_target, TestUri); + + //test connect when some socket still processing data + QLlcpSocket* socket3 = new QLlcpSocket; + + QTRY_VERIFY(!connectedSpy1.isEmpty() || !connectedSpy2.isEmpty()); + if (!connectedSpy1.isEmpty()) + { + qDebug() << "socket 1 connected"; + QString echo1 = "aaaaaaa"; + //Send data to server + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo1; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(echo1)); + qDebug("Client-- write echo string length= %d", echo1.length()); + qDebug("Client-- write data length = %d", block.length()); + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + qint64 val = socket1->write(block); + QVERIFY( val == 0); + + QTRY_VERIFY(!bytesWrittenSpy1.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy1); + + socket3->connectToService(m_target, TestUri); + + qDebug()<<"bytesWritten signal return value = "<<written; + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(socket1, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 w = countBytesWritten(bytesWrittenSpy); + qDebug()<<"got bytesWritten signal = "<<w; + written += w; + } + qDebug()<<"Overall bytesWritten = "<<written; + qDebug()<<"Overall block size = "<<block.size(); + QTRY_VERIFY(written == block.size()); + //Get the echoed data from server + QTRY_VERIFY(!readyReadSpy1.isEmpty()); + quint16 blockSize = 0; + QDataStream in(socket1); + in.setVersion(QDataStream::Qt_4_6); + while (socket1->bytesAvailable() < (int)sizeof(quint16)){ + QSignalSpy readyRead(socket1, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + in >> blockSize; + qDebug() << "Client-- read blockSize=" << blockSize; + while (socket1->bytesAvailable() < blockSize){ + QSignalSpy readyRead(socket1, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + QString echoed; + in >> echoed; + + qDebug() << "Client-- read echoed string =" << echoed; + //test the echoed string is same as the original string + QCOMPARE(echo1, echoed); + + // + //try to handle the socket2 + // + QTRY_VERIFY(!connectedSpy2.isEmpty()); + qDebug() << "socket 2 connected"; + QString echo2 = "bbbbbbb"; + //Send data to server + QByteArray block2; + QDataStream out2(&block2, QIODevice::WriteOnly); + out2.setVersion(QDataStream::Qt_4_6); + out2 << (quint16)0; + out2 << echo2; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(echo2)); + qDebug("Client-- write echo string length= %d", echo2.length()); + qDebug("Client-- write data length = %d", block2.length()); + out2.device()->seek(0); + out2 << (quint16)(block2.size() - sizeof(quint16)); + + qint64 val2 = socket2->write(block2); + QVERIFY( val2 == 0); + + QTRY_VERIFY(!bytesWrittenSpy2.isEmpty()); + qint64 written2 = countBytesWritten(bytesWrittenSpy2); + + qDebug()<<"bytesWritten signal return value = "<<written2; + while (written2 < block2.size()) + { + QSignalSpy bytesWrittenSpy(socket2, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 w = countBytesWritten(bytesWrittenSpy); + qDebug()<<"got bytesWritten signal = "<<w; + written2 += w; + } + qDebug()<<"Overall bytesWritten = "<<written2; + qDebug()<<"Overall block size = "<<block2.size(); + QTRY_VERIFY(written2 == block2.size()); + //Get the echoed data from server + QTRY_VERIFY(!readyReadSpy2.isEmpty()); + quint16 blockSize2 = 0; + QDataStream in2(socket2); + in2.setVersion(QDataStream::Qt_4_6); + while (socket2->bytesAvailable() < (int)sizeof(quint16)){ + QSignalSpy readyRead(socket2, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + in2 >> blockSize2; + qDebug() << "Client-- read blockSize=" << blockSize2; + while (socket2->bytesAvailable() < blockSize2){ + QSignalSpy readyRead(socket2, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + QString echoed2; + in2 >> echoed2; + + qDebug() << "Client-- read echoed string =" << echoed; + //test the echoed string is same as the original string + QCOMPARE(echo2, echoed2); + } + else + { + + qDebug() << "socket 2 connected"; + QString echo2 = "bbbbbbb"; + //Send data to server + QByteArray block2; + QDataStream out2(&block2, QIODevice::WriteOnly); + out2.setVersion(QDataStream::Qt_4_6); + out2 << (quint16)0; + out2 << echo2; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(echo2)); + qDebug("Client-- write echo string length= %d", echo2.length()); + qDebug("Client-- write data length = %d", block2.length()); + out2.device()->seek(0); + out2 << (quint16)(block2.size() - sizeof(quint16)); + + qint64 val2 = socket2->write(block2); + QVERIFY( val2 == 0); + + QTRY_VERIFY(!bytesWrittenSpy2.isEmpty()); + qint64 written2 = countBytesWritten(bytesWrittenSpy2); + + socket3->connectToService(m_target, TestUri); + + qDebug()<<"bytesWritten signal return value = "<<written2; + while (written2 < block2.size()) + { + QSignalSpy bytesWrittenSpy(socket2, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 w = countBytesWritten(bytesWrittenSpy); + qDebug()<<"got bytesWritten signal = "<<w; + written2 += w; + } + qDebug()<<"Overall bytesWritten = "<<written2; + qDebug()<<"Overall block size = "<<block2.size(); + QTRY_VERIFY(written2 == block2.size()); + //Get the echoed data from server + QTRY_VERIFY(!readyReadSpy2.isEmpty()); + quint16 blockSize2 = 0; + QDataStream in2(socket2); + in2.setVersion(QDataStream::Qt_4_6); + while (socket2->bytesAvailable() < (int)sizeof(quint16)){ + QSignalSpy readyRead(socket2, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + in2 >> blockSize2; + qDebug() << "Client-- read blockSize=" << blockSize2; + while (socket2->bytesAvailable() < blockSize2){ + QSignalSpy readyRead(socket2, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + QString echoed2; + in2 >> echoed2; + + qDebug() << "Client-- read echoed string =" << echoed2; + //test the echoed string is same as the original string + QCOMPARE(echo2, echoed2); + + // + //try to handle the socket1 + // + QTRY_VERIFY(!connectedSpy1.isEmpty()); + qDebug() << "socket 1 connected"; + QString echo1 = "aaaaaaa"; + //Send data to server + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_6); + out << (quint16)0; + out << echo1; + + qDebug("Client-- write quint16 length = %d", sizeof(quint16)); + qDebug("Client-- write echo string = %s", qPrintable(echo1)); + qDebug("Client-- write echo string length= %d", echo1.length()); + qDebug("Client-- write data length = %d", block.length()); + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + qint64 val = socket1->write(block); + QVERIFY( val == 0); + + QTRY_VERIFY(!bytesWrittenSpy1.isEmpty()); + qint64 written = countBytesWritten(bytesWrittenSpy1); + + qDebug()<<"bytesWritten signal return value = "<<written; + while (written < block.size()) + { + QSignalSpy bytesWrittenSpy(socket1, SIGNAL(bytesWritten(qint64))); + QTRY_VERIFY(!bytesWrittenSpy.isEmpty()); + qint64 w = countBytesWritten(bytesWrittenSpy); + qDebug()<<"got bytesWritten signal = "<<w; + written += w; + } + qDebug()<<"Overall bytesWritten = "<<written; + qDebug()<<"Overall block size = "<<block.size(); + QTRY_VERIFY(written == block.size()); + //Get the echoed data from server + QTRY_VERIFY(!readyReadSpy1.isEmpty()); + quint16 blockSize = 0; + QDataStream in(socket1); + in.setVersion(QDataStream::Qt_4_6); + while (socket1->bytesAvailable() < (int)sizeof(quint16)){ + QSignalSpy readyRead(socket1, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + in >> blockSize; + qDebug() << "Client-- read blockSize=" << blockSize; + while (socket1->bytesAvailable() < blockSize){ + QSignalSpy readyRead(socket1, SIGNAL(readyRead())); + QTRY_VERIFY(!readyRead.isEmpty()); + } + QString echoed; + in >> echoed; + + qDebug() << "Client-- read echoed string =" << echoed; + //test the echoed string is same as the original string + QCOMPARE(echo1, echoed); + + } + QVERIFY(errorSpy1.isEmpty()); + QVERIFY(errorSpy2.isEmpty()); + delete socket1; + delete socket2; + delete socket3; + } +QTEST_MAIN(tst_qllcpsockettype2); + +#include "tst_qllcpsockettype2.moc" diff --git a/tests/nfcsymbianbackend/qnearfieldmanager/qnearfieldmanager.pro b/tests/nfcsymbianbackend/qnearfieldmanager/qnearfieldmanager.pro new file mode 100644 index 00000000..8efb8110 --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldmanager/qnearfieldmanager.pro @@ -0,0 +1,25 @@ +QT += testlib + +TARGET = tst_qnearfieldmanager +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc + +INCLUDEPATH += ../common +DEPENDPATH += ../common + +HEADERS += ../common/qautomsgbox.h +SOURCES += tst_qnearfieldmanager.cpp \ + ../common/qautomsgbox.cpp + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +symbian:TARGET.CAPABILITY = ALL -TCB diff --git a/tests/nfcsymbianbackend/qnearfieldmanager/tst_qnearfieldmanager.cpp b/tests/nfcsymbianbackend/qnearfieldmanager/tst_qnearfieldmanager.cpp new file mode 100644 index 00000000..6fae1f38 --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldmanager/tst_qnearfieldmanager.cpp @@ -0,0 +1,326 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> + +#include "qnfctestcommon.h" +#include "qnfctestutil.h" + +#include <qnearfieldmanager.h> +#include <qnearfieldtarget.h> +#include <qndefnfctextrecord.h> +#include <qndefnfcurirecord.h> +#include <qndefmessage.h> +#include <qndefrecord.h> + +Q_DECLARE_METATYPE(QNearFieldTarget*) +Q_DECLARE_METATYPE(QNearFieldTarget::Type) +Q_DECLARE_METATYPE(QNdefFilter) + +class tst_QNearFieldManager : public QObject +{ + Q_OBJECT + +public: + tst_QNearFieldManager(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void targetDetected(); + void targetDetected_data(); + void unregisterNdefMessageHandler(); + void registerNdefMessageHandler(); + void registerNdefMessageHandler_filter_data(); + void registerNdefMessageHandler_filter(); + void registerNdefMessageHandler_filter_negtive(); + void registerNdefMessageHandler_filter_negtive_data(); +}; + +tst_QNearFieldManager::tst_QNearFieldManager() +{ + qRegisterMetaType<QNdefMessage>("QNdefMessage"); + qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget*"); +} + +void tst_QNearFieldManager::initTestCase() +{ + qRegisterMetaType<QNearFieldTarget *>("QNearFieldTarget *"); +} + +void tst_QNearFieldManager::cleanupTestCase() +{ +} + +/*! + Description: Unit test for NFC target detected and lost + + TestScenario: 1. Touch and remove llcp device/Type1/Type2/Type3/Type4 tag one by one + + TestExpectedResults: 1. llcp device/Type1/Type2/Type3/Type4 tag detected/lost signal can be received +*/ + +void tst_QNearFieldManager::targetDetected() +{ + QFETCH(QNearFieldTarget::Type, type); + QFETCH(QString, hint); + + QNearFieldManager nfcManager; + + QSignalSpy targetDetectedSpy(&nfcManager, SIGNAL(targetDetected(QNearFieldTarget*))); + QSignalSpy targetLostSpy(&nfcManager, SIGNAL(targetLost(QNearFieldTarget*))); + + nfcManager.startTargetDetection(type); + + QNfcTestUtil::ShowAutoMsg(hint, &targetDetectedSpy, 1); + QTRY_VERIFY(!targetDetectedSpy.isEmpty()); + + QNearFieldTarget *target = targetDetectedSpy.at(targetDetectedSpy.count()-1).at(0).value<QNearFieldTarget *>(); + + QSignalSpy disconnectedSpy(target, SIGNAL(disconnected())); + QVERIFY(target); + + if (type != QNearFieldTarget::NfcForumDevice) + { + QVERIFY(!target->uid().isEmpty()); + QCOMPARE(target->type(), type); + } + + QNfcTestUtil::ShowAutoMsg("please remove the target", &disconnectedSpy, 1); + QTRY_VERIFY(!targetLostSpy.isEmpty()); + + QNearFieldTarget *lostTarget = targetLostSpy.first().at(0).value<QNearFieldTarget *>(); + + QCOMPARE(target, lostTarget); + + QVERIFY(!disconnectedSpy.isEmpty()); + + nfcManager.stopTargetDetection(); +} + +void tst_QNearFieldManager::targetDetected_data() +{ + QTest::addColumn<QNearFieldTarget::Type>("type"); + QTest::addColumn<QString>("hint"); + QTest::newRow("llcp device") << QNearFieldTarget::NfcForumDevice << "Please touch llcp device"; + QTest::newRow("NfcTagType1") << QNearFieldTarget::NfcTagType1 << "Please touch tag type1"; + QTest::newRow("NfcTagType2") << QNearFieldTarget::NfcTagType2 << "Please touch tag type2"; + QTest::newRow("NfcTagType3") << QNearFieldTarget::NfcTagType3 << "Please touch tag type3"; + QTest::newRow("NfcTagType4") << QNearFieldTarget::NfcTagType4 << "Please touch tag type4"; +} + +/*! + Description: Unit test for NFC unregisterNdefMessageHandler function + + TestScenario: 1. + + TestExpectedResults: 1. return false +*/ + +void tst_QNearFieldManager::unregisterNdefMessageHandler() +{ + QNearFieldManager manager; + + QVERIFY(!manager.unregisterNdefMessageHandler(-1)); + QVERIFY(!manager.unregisterNdefMessageHandler(0)); +} + +class MessageListener : public QObject +{ + Q_OBJECT + +signals: + void matchedNdefMessage(const QNdefMessage &message, QNearFieldTarget *target); +}; + +/*! + Description: Unit test for NFC registerNdefMessageHandler function + + TestScenario: 1. Symbian backend does not support registerNdefMessageHandler without a QNdefFilter + + TestExpectedResults: 1. return -1 +*/ +void tst_QNearFieldManager::registerNdefMessageHandler() +{ + QNearFieldManager manager; + + MessageListener listener; + QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*))); + + int id = manager.registerNdefMessageHandler(&listener, + SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*))); + + QVERIFY(id == -1);//symbian backend does not support registerNdefMessageHandler without QNdefFilter +} + +void tst_QNearFieldManager::registerNdefMessageHandler_filter_data() +{ + QTest::addColumn<QNdefFilter>("filter"); + QTest::addColumn<QString>("hint"); + + QNdefFilter filter; + + filter.appendRecord(QNdefRecord::NfcRtd, "Sp"); + QTest::newRow("SP") << filter << "Please touch a tag with 'SP' NDef message"; + + filter.clear(); + filter.setOrderMatch(true); + filter.appendRecord<QNdefNfcTextRecord>(1, 1); + filter.appendRecord<QNdefNfcUriRecord>(1, 1); + QTest::newRow("Text + URI") << filter << "Please touch a tag with 'Text + URI' NDef message"; + + filter.clear(); + filter.appendRecord<QNdefNfcUriRecord>(1, 1); + QTest::newRow("URI") << filter << "Please touch a tag with 'URI' NDef message"; + + filter.clear(); + filter.setOrderMatch(true); + filter.appendRecord<QNdefNfcUriRecord>(1, 1); + QTest::newRow("URI") << filter << "Please touch a tag with only one 'URI' NDef record"; + +} + +/*! + Description: Unit test for NFC registerNdefMessageHandler with a NDef filter + + TestScenario: 1. Touch a tag with random NDef message/with 'Image + Multiple Text + URI' NDef message/with 'Text + URI' NDef message + + TestExpectedResults: 1. matchedNdefMessage signal will be emitted +*/ +void tst_QNearFieldManager::registerNdefMessageHandler_filter() +{ + QFETCH(QNdefFilter, filter); + QFETCH(QString, hint); + + QNearFieldManager manager; + + MessageListener listener; + QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*))); + + int id = manager.registerNdefMessageHandler(filter, &listener, + SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*))); + + QVERIFY(id != -1); + + QNfcTestUtil::ShowAutoMsg(hint, &messageSpy, 1); + + QTRY_VERIFY(!messageSpy.isEmpty()); + + const QNdefMessage message = messageSpy.first().at(0).value<QNdefMessage>(); + + QNearFieldTarget *target = messageSpy.first().at(1).value<QNearFieldTarget *>(); + + QVERIFY(target == NULL);//symbain backend always return NULL target + QCOMPARE(filter.recordCount(), message.count()); + qDebug()<<"message.count()="<<message.count(); + for (int i = 0; i < filter.recordCount(); ++i) + { + if (filter.orderMatch()) + { + QCOMPARE(filter.recordAt(i).typeNameFormat, message.at(i).typeNameFormat()); + QCOMPARE(filter.recordAt(i).type, message.at(i).type()); + } + else + { + bool matched = false; + for (int j = 0; j < filter.recordCount(); ++j) + { + if (message.at(i).typeNameFormat() == filter.recordAt(i).typeNameFormat && message.at(i).type() == filter.recordAt(i).type) + { + matched = true; + break; + } + } + QVERIFY(matched); + } + } + + QVERIFY(manager.unregisterNdefMessageHandler(id)); +} + +void tst_QNearFieldManager::registerNdefMessageHandler_filter_negtive_data() +{ + QTest::addColumn<QNdefFilter>("filter"); + QTest::addColumn<QString>("hint"); + //negtive test + QNdefFilter filter; + + QTest::newRow("Empty") << filter << "Please touch a tag without NDef message"; + + filter.clear(); + filter.appendRecord<QNdefNfcUriRecord>(1, 1); + QTest::newRow("URI") << filter << "Please touch a tag without 'URI' NDef message"; + +} + +/*! + Description: Unit test for NFC registerNdefMessageHandler with a NDef filter + + TestScenario: 1. Touch a tag without filter expected NDef message + + TestExpectedResults: 1. matchedNdefMessage signal will NOT be emitted +*/ +void tst_QNearFieldManager::registerNdefMessageHandler_filter_negtive() +{ + QFETCH(QNdefFilter, filter); + QFETCH(QString, hint); + + QNearFieldManager manager; + + MessageListener listener; + QSignalSpy messageSpy(&listener, SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*))); + + int id = manager.registerNdefMessageHandler(filter, &listener, + SIGNAL(matchedNdefMessage(QNdefMessage,QNearFieldTarget*))); + + QVERIFY(id != -1); + + QNfcTestUtil::ShowAutoMsg(hint); + + QTRY_VERIFY(messageSpy.isEmpty()); + QVERIFY(manager.unregisterNdefMessageHandler(id)); +} + +QTEST_MAIN(tst_QNearFieldManager); + +#include "tst_qnearfieldmanager.moc" diff --git a/tests/nfcsymbianbackend/qnearfieldtagtype1/qnearfieldtagtype1.pro b/tests/nfcsymbianbackend/qnearfieldtagtype1/qnearfieldtagtype1.pro new file mode 100644 index 00000000..5f136db1 --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldtagtype1/qnearfieldtagtype1.pro @@ -0,0 +1,31 @@ +QT += testlib + +TARGET = tst_qnearfieldtagtype1 +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qnfctagtestcommon.h \ + ../common/qdummyslot.h \ + ../common/qautomsgbox.h \ + ../common/qnfctagutil.h + +SOURCES += tst_qnearfieldtagtype1.cpp \ + ../common/qdummyslot.cpp \ + ../common/qautomsgbox.cpp \ + ../common/qnfctagutil.cpp + + +symbian:TARGET.CAPABILITY = LocalServices diff --git a/tests/nfcsymbianbackend/qnearfieldtagtype1/tst_qnearfieldtagtype1.cpp b/tests/nfcsymbianbackend/qnearfieldtagtype1/tst_qnearfieldtagtype1.cpp new file mode 100644 index 00000000..962adf07 --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldtagtype1/tst_qnearfieldtagtype1.cpp @@ -0,0 +1,537 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> +#include <QVariant> +#include <QVariantList> +#include "qnfctagtestcommon.h" +#include <qnearfieldtagtype1.h> +#include "qnfctestcommon.h" + +class NfcTagRawCommandOperationType1 : public NfcTagRawCommandOperationCommon +{ +public: + NfcTagRawCommandOperationType1(QNearFieldTarget * tag); + + void setReadAllOp() { readAll = &QNearFieldTagType1::readAll; } + void setReadIdOp() { readIdentification = &QNearFieldTagType1::readIdentification; } + void setReadByteOp(quint8 addr) { mAddr = addr; readByte = &QNearFieldTagType1::readByte; } + void setWriteByteOp(quint8 addr, quint8 data, QNearFieldTagType1::WriteMode mode) + { + mAddr = addr; + mData = data; + mMode = mode; + writeByte = &QNearFieldTagType1::writeByte; + } + void setReadSegment(quint8 addr) { mAddr = addr; readSegment = &QNearFieldTagType1::readSegment; } + void setReadBlock(quint8 addr) { mAddr = addr; readBlock = &QNearFieldTagType1::readBlock; } + void setWriteBlock(quint8 addr, const QByteArray & data, QNearFieldTagType1::WriteMode mode) + { + mAddr = addr; + mDataArray = data; + mMode = mode; + writeBlock = &QNearFieldTagType1::writeBlock; + } + + void run() + { + if (readAll) + { + mId = (tagType1->*readAll)(); + } + + if (readIdentification) + { + mId = (tagType1->*readIdentification)(); + } + + if (readByte) + { + mId = (tagType1->*readByte)(mAddr); + } + + if (writeByte) + { + mId = (tagType1->*writeByte)(mAddr, mData, mMode); + } + + if (readBlock) + { + mId = (tagType1->*readBlock)(mAddr); + } + + if (writeBlock) + { + mId = (tagType1->*writeBlock)(mAddr, mDataArray, mMode); + } + + if (readSegment) + { + mId = (tagType1->*readSegment)(mAddr); + } + checkInvalidId(); + waitRequest(); + } + +protected: + QNearFieldTagType1 * tagType1; + QNearFieldTarget::RequestId (QNearFieldTagType1::*readAll)(); + QNearFieldTarget::RequestId (QNearFieldTagType1::*readIdentification)(); + + QNearFieldTarget::RequestId (QNearFieldTagType1::*readByte)(quint8 address); + QNearFieldTarget::RequestId (QNearFieldTagType1::*writeByte)(quint8 address, quint8 data, QNearFieldTagType1::WriteMode mode); + + // dynamic memory functions + QNearFieldTarget::RequestId (QNearFieldTagType1::*readSegment)(quint8 segmentAddress); + QNearFieldTarget::RequestId (QNearFieldTagType1::*readBlock)(quint8 blockAddress); + QNearFieldTarget::RequestId (QNearFieldTagType1::*writeBlock)(quint8 blockAddress, const QByteArray &data, + QNearFieldTagType1::WriteMode mode); + quint8 mAddr; + quint8 mData; + QByteArray mDataArray; + QNearFieldTagType1::WriteMode mMode; +}; + +NfcTagRawCommandOperationType1::NfcTagRawCommandOperationType1(QNearFieldTarget * tag):NfcTagRawCommandOperationCommon(tag) +{ + tagType1 = qobject_cast<QNearFieldTagType1 *>(mTarget); + QVERIFY(tagType1); + readAll = 0; + readIdentification = 0; + readByte = 0; + writeByte = 0; + readSegment = 0; + readBlock = 0; + writeBlock = 0; +} + +class tst_qnearfieldtagtype1 : public QObject +{ + Q_OBJECT + +public: + tst_qnearfieldtagtype1(); + void _testRawAccessAndNdefAccess(const QList<QNdefMessage> &messages); + +private Q_SLOTS: + void initTestCase(); + void testRawAndNdefAccess(); + void testSequence(); + void testWaitInSlot(); + void testDeleteOperationBeforeAsyncRequestComplete(); + void testRemoveTagBeforeAsyncRequestComplete(); + void testCancelNdefOperation(); + void cleanupTestCase(); +private: + QNfcTagTestCommon<QNearFieldTagType1> tester; +}; + + +tst_qnearfieldtagtype1::tst_qnearfieldtagtype1() +{ +} + +void tst_qnearfieldtagtype1::initTestCase() +{ +} + +void tst_qnearfieldtagtype1::cleanupTestCase() +{ +} + +void tst_qnearfieldtagtype1::testSequence() +{ + tester.touchTarget(" dynamic "); + QByteArray uid = tester.target->uid(); + QVERIFY(!uid.isEmpty()); + +//////////////////////////////////////////////////////////////////////////////////////////////// + qDebug()<<"========== Test readSeg, writeBlock, async and sync mix =========="; + OperationList rawCommandList; + const char data[] = {0,1,2,3,4,5,6,7}; + QByteArray blockData; + blockData.append(data, sizeof(data)); + QByteArray segmentData; + + for (int i = 0x10; i <= 0x1F; ++i) + { + NfcTagRawCommandOperationType1 * op1 = new NfcTagRawCommandOperationType1(tester.target); + op1->setWriteBlock(i, blockData, QNearFieldTagType1::EraseAndWrite); + op1->setExpectedOkSignal(); + op1->setExpectedResponse(QVariant(true)); + + if (i == 0x15) + { + op1->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitTrue); + } + rawCommandList.append(op1); + segmentData.append(blockData); + } + + NfcTagRawCommandOperationType1 * op2 = new NfcTagRawCommandOperationType1(tester.target); + op2->setReadSegment(1); + op2->setExpectedOkSignal(); + op2->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitTrue); + op2->setExpectedResponse(segmentData); + rawCommandList.append(op2); + + tester.testSequence(rawCommandList); + qDeleteAll(rawCommandList); + +////////////////////////////////////////////////////////////////////////////////////////////// + qDebug()<<"========== Test invalid readSeg, writeNE, writeBlockNE =========="; + rawCommandList.clear(); + NfcTagRawCommandOperationType1 * op6 = new NfcTagRawCommandOperationType1(tester.target); + op6->setReadSegment(0xf1); + op6->setIfExpectInvalidId(); + op6->setExpectedResponse(QVariant()); + rawCommandList.append(op6); + + NfcTagRawCommandOperationType1 * op3 = new NfcTagRawCommandOperationType1(tester.target); + op3->setWriteBlock(0x10, blockData, QNearFieldTagType1::WriteOnly); + op3->setExpectedOkSignal(); + op3->setExpectedResponse(QVariant(true)); + rawCommandList.append(op3); + + NfcTagRawCommandOperationType1 * op4 = new NfcTagRawCommandOperationType1(tester.target); + op4->setWriteByteOp(0x10, 0xff, QNearFieldTagType1::WriteOnly); + op4->setExpectedOkSignal(); + op4->setExpectedResponse(QVariant(true)); + rawCommandList.append(op4); + + QList<QByteArray> cmdList; + QByteArray command; + command.append(char(0x1a)); // WRITE-NE + command.append(char(0x10)); // Address + command.append(char(0x00)); // Data + command.append(uid.left(4)); // 4 bytes of UID + cmdList.append(command); + + command.clear(); + command.append(char(0xff)); // Invalid command + command.append(char(0xff)); + command.append(char(0xff)); + command.append(char(0xff)); + command.append(char(0xff)); + command.append(char(0xff)); + cmdList.append(command); + + QVariantList expectRsp; + expectRsp.push_back(QVariant(true)); + expectRsp.push_back(QVariant()); + + NfcTagSendCommandsCommon * op7 = new NfcTagSendCommandsCommon(tester.target); + op7->SetCommandLists(cmdList); + op7->setExpectedErrorSignal(QNearFieldTarget::InvalidParametersError); + op7->SetExpectedResponse(expectRsp); + op7->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitFalse); + rawCommandList.append(op7); + + cmdList.clear(); + QByteArray command1; + command1.append(char(0x1a)); // WRITE-NE + command1.append(char(0x10)); // Address + command1.append(char(0x00)); // Data + command1.append(uid.left(4)); // 4 bytes of UID + cmdList.append(command1); + cmdList.append(command1); + + expectRsp.clear(); + expectRsp.push_back(QVariant(true)); + expectRsp.push_back(QVariant(true)); + + NfcTagSendCommandsCommon * op8 = new NfcTagSendCommandsCommon(tester.target); + op8->SetCommandLists(cmdList); + op8->setExpectedOkSignal(); + op8->SetExpectedResponse(expectRsp); + rawCommandList.append(op8); + + tester.testSequence(rawCommandList); + qDeleteAll(rawCommandList); + + tester.removeTarget(); +} + +void tst_qnearfieldtagtype1::testWaitInSlot() +{ + tester.touchTarget(" dynamic "); + + const char data[] = {0,1,2,3,4,5,6,7}; + QByteArray blockData; + blockData.append(data, sizeof(data)); + + NfcTagRawCommandOperationType1 * op1 = new NfcTagRawCommandOperationType1(tester.target); + op1->setWriteBlock(0x10, blockData, QNearFieldTagType1::EraseAndWrite); + op1->setExpectedOkSignal(); + op1->setExpectedResponse(QVariant(true)); + + NfcTagRawCommandOperationType1 * op2Wait = new NfcTagRawCommandOperationType1(tester.target); + op2Wait->setWriteBlock(0x11, blockData, QNearFieldTagType1::EraseAndWrite); + op2Wait->setExpectedOkSignal(); + op2Wait->setExpectedResponse(QVariant(true)); + op2Wait->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitTrue); + + NfcTagRawCommandOperationType1 * op3 = new NfcTagRawCommandOperationType1(tester.target); + op3->setWriteBlock(0x12, blockData, QNearFieldTagType1::EraseAndWrite); + op3->setExpectedOkSignal(); + op3->setExpectedResponse(QVariant(true)); + + NfcTagRawCommandOperationType1 * op4WaitInSlot = new NfcTagRawCommandOperationType1(tester.target); + op4WaitInSlot->setWriteBlock(0x13, blockData, QNearFieldTagType1::EraseAndWrite); + op4WaitInSlot->setExpectedOkSignal(); + op4WaitInSlot->setExpectedResponse(QVariant(true)); + + tester.testWaitInSlot(op1, op2Wait, op3, op4WaitInSlot); + + delete op1; + delete op2Wait; + delete op3; + delete op4WaitInSlot; + + tester.removeTarget(); +} + +void tst_qnearfieldtagtype1::testDeleteOperationBeforeAsyncRequestComplete() +{ + tester.touchTarget(" dynamic "); + OperationList rawCommandList; + const char data[] = {0,1,2,3,4,5,6,7}; + QByteArray blockData; + blockData.append(data, sizeof(data)); + QByteArray segmentData; + + for (int i = 0x10; i <= 0x1F; ++i) + { + NfcTagRawCommandOperationType1 * op1 = new NfcTagRawCommandOperationType1(tester.target); + op1->setWriteBlock(i, blockData, QNearFieldTagType1::EraseAndWrite); + op1->setExpectedOkSignal(); + op1->setExpectedResponse(QVariant(true)); + + if (i == 0x15) + { + op1->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitTrue); + } + rawCommandList.append(op1); + segmentData.append(blockData); + } + + NfcTagRawCommandOperationType1 * op2 = new NfcTagRawCommandOperationType1(tester.target); + op2->setReadSegment(1); + op2->setExpectedOkSignal(); + op2->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitTrue); + op2->setExpectedResponse(segmentData); + rawCommandList.append(op2); + tester.testDeleteOperationBeforeAsyncRequestComplete(rawCommandList); + + qDeleteAll(rawCommandList); +} + +void tst_qnearfieldtagtype1::testRemoveTagBeforeAsyncRequestComplete() +{ + tester.touchTarget(" dynamic "); + OperationList rawCommandList; + const char data[] = {0,1,2,3,4,5,6,7}; + QByteArray blockData; + blockData.append(data, sizeof(data)); + QByteArray segmentData; + + for (int i = 0x10; i <= 0x1F; ++i) + { + NfcTagRawCommandOperationType1 * op1 = new NfcTagRawCommandOperationType1(tester.target); + op1->setWriteBlock(i, blockData, QNearFieldTagType1::EraseAndWrite); + op1->setExpectedOkSignal(); + op1->setExpectedResponse(QVariant(true)); + + rawCommandList.append(op1); + segmentData.append(blockData); + } + + NfcTagRawCommandOperationType1 * op2 = new NfcTagRawCommandOperationType1(tester.target); + op2->setReadSegment(1); + op2->setExpectedOkSignal(); + op2->setExpectedResponse(segmentData); + rawCommandList.append(op2); + + OperationList rawCommandList1; + + segmentData.clear(); + + for (int i = 0x10; i <= 0x1F; ++i) + { + NfcTagRawCommandOperationType1 * op1 = new NfcTagRawCommandOperationType1(tester.target); + op1->setWriteBlock(i, blockData, QNearFieldTagType1::EraseAndWrite); + op1->setExpectedOkSignal(); + op1->setExpectedResponse(QVariant(true)); + + rawCommandList1.append(op1); + segmentData.append(blockData); + } + + NfcTagRawCommandOperationType1 * op3 = new NfcTagRawCommandOperationType1(tester.target); + op3->setReadSegment(1); + op3->setExpectedOkSignal(); + op3->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitFalse); + op3->setExpectedResponse(segmentData); + rawCommandList1.append(op3); + + tester.testRemoveTagBeforeAsyncRequestComplete(rawCommandList, rawCommandList1); + qDeleteAll(rawCommandList); + qDeleteAll(rawCommandList1); +} + +void tst_qnearfieldtagtype1::testCancelNdefOperation() +{ + tester.touchTarget(" static "); + tester.testCancelNdefOperation(); +} + +void tst_qnearfieldtagtype1::_testRawAccessAndNdefAccess(const QList<QNdefMessage> &messages) +{ + QSignalSpy okSpy(tester.target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId&))); + QSignalSpy errSpy(tester.target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId&))); + QSignalSpy ndefMessageReadSpy(tester.target, SIGNAL(ndefMessageRead(QNdefMessage))); + QSignalSpy ndefMessageWriteSpy(tester.target, SIGNAL(ndefMessagesWritten())); + + int okCount = 0; + int errCount = 0; + int ndefReadCount = 0; + int ndefWriteCount = 0; + qDebug()<<"okSpy.count()"<<okSpy.count(); + + // write ndef first + tester.target->writeNdefMessages(messages); + ++ndefWriteCount; + QTRY_COMPARE(ndefMessageWriteSpy.count(), ndefWriteCount); + qDebug()<<"okSpy.count()"<<okSpy.count(); + + // has Ndef message check + QVERIFY(tester.target->hasNdefMessage()); + qDebug()<<"okSpy.count()"<<okSpy.count(); + + QNearFieldTarget::RequestId id = tester.target->readAll(); + QVERIFY(tester.target->waitForRequestCompleted(id)); + QByteArray allBlocks = tester.target->requestResponse(id).toByteArray(); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + + // Verify readByte + QNearFieldTarget::RequestId id1 = tester.target->readByte(0x08); + QVERIFY(tester.target->waitForRequestCompleted(id1)); + quint8 cc0 = tester.target->requestResponse(id1).value<quint8>(); + QCOMPARE(cc0, quint8(0xE1)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + + QNearFieldTarget::RequestId id2 = tester.target->readByte(0x0d); + QVERIFY(tester.target->waitForRequestCompleted(id2)); + quint8 len = tester.target->requestResponse(id2).value<quint8>(); + QCOMPARE(int(len), messages.at(0).toByteArray().count()); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + + QCOMPARE(allBlocks.mid(16, len), messages.at(0).toByteArray()); + + // Write NDEF with raw command + QNdefMessage message; + QNdefNfcTextRecord textRecord; + textRecord.setText("nfc"); + + message.append(textRecord); + + QByteArray newNdefMessageContent = message.toByteArray(); + quint8 ndefMessageContentLen = newNdefMessageContent.count(); + + QNearFieldTarget::RequestId id3 = tester.target->writeByte(0x0d, ndefMessageContentLen); + QVERIFY(tester.target->waitForRequestCompleted(id3)); + QVERIFY(tester.target->requestResponse(id3).toBool()); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + + quint8 block = 1; + quint8 byte = 6; + for (int i = 0; i < ndefMessageContentLen; ++i) + { + quint8 addr = (block & 0x0F); + addr <<= 3; + addr |= (byte & 0x07); + QNearFieldTarget::RequestId tempId = tester.target->writeByte(addr, newNdefMessageContent.at(i)); + QVERIFY(tester.target->waitForRequestCompleted(tempId)); + QVERIFY(tester.target->requestResponse(tempId).toBool()); + byte = (7 == byte) ? 0 : (byte+1); + block = (0 == byte) ? (block+1) : block; + ++okCount; + QCOMPARE(okSpy.count(), okCount); + } + + // read ndef with ndef access + tester.target->readNdefMessages(); + ++ndefReadCount; + QTRY_COMPARE(ndefMessageReadSpy.count(), ndefReadCount); + + const QNdefMessage& ndefMessage_new(ndefMessageReadSpy.first().at(0).value<QNdefMessage>()); + + QCOMPARE(newNdefMessageContent, ndefMessage_new.toByteArray()); + QCOMPARE(errSpy.count(), errCount); +} + +void tst_qnearfieldtagtype1::testRawAndNdefAccess() +{ + tester.touchTarget(" static "); + QByteArray uid = tester.target->uid(); + QVERIFY(!uid.isEmpty()); + + QNdefMessage message; + QNdefNfcUriRecord uriRecord; + uriRecord.setUri(QUrl("http://qt.nokia.com")); + message.append(uriRecord); + + QList<QNdefMessage> messages; + messages.append(message); + + _testRawAccessAndNdefAccess(messages); + tester.removeTarget(); +} + +QTEST_MAIN(tst_qnearfieldtagtype1); + +#include "tst_qnearfieldtagtype1.moc" diff --git a/tests/nfcsymbianbackend/qnearfieldtagtype2/qnearfieldtagtype2.pro b/tests/nfcsymbianbackend/qnearfieldtagtype2/qnearfieldtagtype2.pro new file mode 100644 index 00000000..2001993d --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldtagtype2/qnearfieldtagtype2.pro @@ -0,0 +1,31 @@ +QT += testlib + +TARGET = tst_qnearfieldtagtype2 +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qnfctagtestcommon.h \ + ../common/qdummyslot.h \ + ../common/qautomsgbox.h \ + ../common/qnfctagutil.h + +SOURCES += tst_qnearfieldtagtype2.cpp \ + ../common/qdummyslot.cpp \ + ../common/qautomsgbox.cpp \ + ../common/qnfctagutil.cpp + +symbian:TARGET.CAPABILITY = LocalServices + diff --git a/tests/nfcsymbianbackend/qnearfieldtagtype2/tst_qnearfieldtagtype2.cpp b/tests/nfcsymbianbackend/qnearfieldtagtype2/tst_qnearfieldtagtype2.cpp new file mode 100644 index 00000000..7f8ada31 --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldtagtype2/tst_qnearfieldtagtype2.cpp @@ -0,0 +1,303 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> +#include <QVariant> +#include <QVariantList> +#include "qnfctagtestcommon.h" +#include <qnearfieldtagtype2.h> +#include "qnfctestcommon.h" + +class NfcTagRawCommandOperationType2: public NfcTagRawCommandOperationCommon +{ +public: + NfcTagRawCommandOperationType2(QNearFieldTarget * tag); + + void run() + { + if (readBlock) + { + mId = (tagType2->*readBlock)(mAddr); + } + + if (writeBlock) + { + mId = (tagType2->*writeBlock)(mAddr, mDataArray); + } + + if (selectSector) + { + mId = (tagType2->*selectSector)(mSector); + } + checkInvalidId(); + waitRequest(); + } + + void setReadBlock(quint8 blockAddress) + { + mAddr = blockAddress; + readBlock = &QNearFieldTagType2::readBlock; + } + + void setWriteBlock(quint8 blockAddress, const QByteArray &data) + { + mAddr = blockAddress; + mDataArray = data; + writeBlock = &QNearFieldTagType2::writeBlock; + } + + void setSelectSector(quint8 sector) + { + mSector = sector; + selectSector = &QNearFieldTagType2::selectSector; + } + +protected: + QNearFieldTagType2 * tagType2; + QNearFieldTarget::RequestId (QNearFieldTagType2::*readBlock)(quint8 blockAddress); + QNearFieldTarget::RequestId (QNearFieldTagType2::*writeBlock)(quint8 blockAddress, const QByteArray &data); + QNearFieldTarget::RequestId (QNearFieldTagType2::*selectSector)(quint8 sector); + + quint8 mAddr; + quint8 mSector; + QByteArray mDataArray; +}; + +NfcTagRawCommandOperationType2::NfcTagRawCommandOperationType2(QNearFieldTarget * tag):NfcTagRawCommandOperationCommon(tag) +{ + tagType2 = qobject_cast<QNearFieldTagType2 *>(mTarget); + QVERIFY(tagType2); + readBlock = 0; + writeBlock = 0; + selectSector = 0; +} + +class tst_qnearfieldtagtype2: public QObject +{ + Q_OBJECT + +public: + tst_qnearfieldtagtype2(); + + void testRawAccessAndNdefAccess(const QList<QNdefMessage> &messages); + +private Q_SLOTS: + void initTestCase(); + void testRawAndNdefAccess(); + void testSequence(); + void cleanupTestCase(){} +private: + QNfcTagTestCommon<QNearFieldTagType2> tester; +}; + + +tst_qnearfieldtagtype2::tst_qnearfieldtagtype2() +{ +} + +void tst_qnearfieldtagtype2::initTestCase() +{ +} + +void tst_qnearfieldtagtype2::testSequence() +{ + tester.touchTarget(); + QByteArray uid = tester.target->uid(); + QVERIFY(!uid.isEmpty()); + + OperationList rawCommandList; + const char data[] = {0,1,2,3}; + QByteArray blockData; + blockData.append(data, sizeof(data)); + + for (int i = 4; i < 8; ++i) + { + NfcTagRawCommandOperationType2 * op1 = new NfcTagRawCommandOperationType2(tester.target); + op1->setWriteBlock(i, blockData); + op1->setExpectedOkSignal(); + op1->setExpectedResponse(QVariant(true)); + + if (i == 6) + { + op1->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitTrue); + } + rawCommandList.append(op1); + } + + QList<QByteArray> cmdList; + QByteArray command; + command.append(char(0xff)); // Invalid command + command.append(char(0xff)); + command.append(char(0xff)); + command.append(char(0xff)); + command.append(char(0xff)); + command.append(char(0xff)); + cmdList.append(command); + cmdList.append(command); + + QVariantList expectRsp; + expectRsp.push_back(QVariant()); + expectRsp.push_back(QVariant()); + + NfcTagSendCommandsCommon * op7 = new NfcTagSendCommandsCommon(tester.target); + op7->SetCommandLists(cmdList); + op7->setExpectedErrorSignal(QNearFieldTarget::InvalidParametersError); + op7->SetExpectedResponse(expectRsp); + op7->setWaitOperation(NfcTagRawCommandOperationCommon::EWaitFalse); + rawCommandList.append(op7); + + tester.testSequence(rawCommandList); + qDeleteAll(rawCommandList); + + tester.removeTarget(); +} + +void tst_qnearfieldtagtype2::testRawAccessAndNdefAccess(const QList<QNdefMessage> &messages) +{ + QSignalSpy okSpy(tester.target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId&))); + QSignalSpy errSpy(tester.target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId&))); + QSignalSpy ndefMessageReadSpy(tester.target, SIGNAL(ndefMessageRead(QNdefMessage))); + QSignalSpy ndefMessageWriteSpy(tester.target, SIGNAL(ndefMessagesWritten())); + + int okCount = 0; + int errCount = 0; + int ndefReadCount = 0; + int ndefWriteCount = 0; + + // write ndef first + tester.target->writeNdefMessages(messages); + ++ndefWriteCount; + QTRY_COMPARE(ndefMessageWriteSpy.count(), ndefWriteCount); + + QNearFieldTarget::RequestId id = tester.target->readBlock(3); + QVERIFY(tester.target->waitForRequestCompleted(id, 50000)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + // check if NDEF existed + QByteArray cc = tester.target->requestResponse(id).toByteArray(); + QCOMPARE((char)(cc.at(0)), (char)0xE1); + + // try to find NDEF tlv + QByteArray blocks; + int NdefLen = -1; + for(int i = 4; i < 15; i+=4) + { + QNearFieldTarget::RequestId id1 = tester.target->readBlock(i); + QVERIFY(tester.target->waitForRequestCompleted(id1, 50000)); + QByteArray tlv = tester.target->requestResponse(id1).toByteArray(); + blocks.append(tlv); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + } + + QByteArray ndefContent; + for (int i = 0; i < blocks.count(); ++i) + { + if ((blocks.at(i) == 0x03) && (i < blocks.count() - 1)) + { + // find ndef tlv + NdefLen = blocks.at(i+1); + qDebug()<<"NDefLen is "<<NdefLen; + ndefContent = blocks.mid(i+2, NdefLen); + break; + } + } + + QCOMPARE(ndefContent, messages.at(0).toByteArray()); + // update the ndef meesage with raw command + QNdefMessage message; + QNdefNfcTextRecord textRecord; + textRecord.setText("nfc"); + message.append(textRecord); + + QByteArray newNdefMessage = message.toByteArray(); + NdefLen = newNdefMessage.count(); + qDebug()<<"NDefLen is "<<NdefLen; + qDebug()<<"new Ndef len is "<<NdefLen; + newNdefMessage.push_front((char)NdefLen); + newNdefMessage.push_front((char)0x03); + + for(int i = 0; i < 16 - NdefLen; ++i) + { + // append padding + newNdefMessage.append((char)0); + } + + for(int i = 4; i < 8; ++i) + { + QNearFieldTarget::RequestId id2 = tester.target->writeBlock(i, newNdefMessage.left(4)); + QVERIFY(tester.target->waitForRequestCompleted(id2)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + newNdefMessage.remove(0,4); + } + + // read ndef with ndef access + tester.target->readNdefMessages(); + ++ndefReadCount; + QTRY_COMPARE(ndefMessageReadSpy.count(), ndefReadCount); + + const QNdefMessage& ndefMessage_new(ndefMessageReadSpy.first().at(0).value<QNdefMessage>()); + + QCOMPARE(message.toByteArray(), ndefMessage_new.toByteArray()); + QCOMPARE(errSpy.count(), errCount); +} + +void tst_qnearfieldtagtype2::testRawAndNdefAccess() +{ + tester.touchTarget(); + QNdefMessage message; + QNdefNfcUriRecord uriRecord; + uriRecord.setUri(QUrl("http://qt")); + message.append(uriRecord); + + QList<QNdefMessage> messages; + messages.append(message); + + testRawAccessAndNdefAccess(messages); + tester.removeTarget(); +} + +QTEST_MAIN(tst_qnearfieldtagtype2); + +#include "tst_qnearfieldtagtype2.moc" diff --git a/tests/nfcsymbianbackend/qnearfieldtagtype3/qnearfieldtagtype3.pro b/tests/nfcsymbianbackend/qnearfieldtagtype3/qnearfieldtagtype3.pro new file mode 100644 index 00000000..1a654dcc --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldtagtype3/qnearfieldtagtype3.pro @@ -0,0 +1,32 @@ +QT += testlib + +TARGET = tst_qnearfieldtagtype3 +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qnfctagtestcommon.h \ + ../common/qdummyslot.h \ + ../common/qautomsgbox.h \ + ../common/qnfctagutil.h + +SOURCES += tst_qnearfieldtagtype3.cpp \ + ../common/qdummyslot.cpp \ + ../common/qautomsgbox.cpp \ + ../common/qnfctagutil.cpp + + +symbian:TARGET.CAPABILITY = LocalServices + diff --git a/tests/nfcsymbianbackend/qnearfieldtagtype3/tst_qnearfieldtagtype3.cpp b/tests/nfcsymbianbackend/qnearfieldtagtype3/tst_qnearfieldtagtype3.cpp new file mode 100644 index 00000000..36417c8c --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldtagtype3/tst_qnearfieldtagtype3.cpp @@ -0,0 +1,295 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> +#include <QVariant> +#include <QVariantList> +#include "qnfctagtestcommon.h" +#include <qnearfieldtagtype3.h> +#include "qnfctestcommon.h" + +typedef QMap<quint16,QByteArray> checkResponseType; +Q_DECLARE_METATYPE(checkResponseType) + +class NfcTagRawCommandOperationType3: public NfcTagRawCommandOperationCommon +{ +public: + NfcTagRawCommandOperationType3(QNearFieldTarget * tag); + + void run() + { + if (check) + { + mId = (tagType3->*check)(mSerivceBlockList); + } + + if (update) + { + mId = (tagType3->*update)(mSerivceBlockList, mDataArray); + } + + checkInvalidId(); + waitRequest(); + } + + void setCheck(const QMap<quint16, QList<quint16> > &serviceBlockList) + { + check = &QNearFieldTagType3::check; + mSerivceBlockList = serviceBlockList; + } + + void setUpdate(const QMap<quint16, QList<quint16> > &serviceBlockList, + const QByteArray &data) + { + update = &QNearFieldTagType3::update; + mSerivceBlockList = serviceBlockList; + mDataArray = data; + } + + void checkResponse() + { + qDebug()<<"checkResponse begin"; + if (check) + { + // response is QMap<quint16, QByteArray> + checkResponseType e = mExpectedResult.value<checkResponseType>(); + checkResponseType r = mTarget->requestResponse(mId).value<checkResponseType>(); + QCOMPARE(e, r); + } + else + { + QTRY_COMPARE(mTarget->requestResponse(mId), mExpectedResult); + } + qDebug()<<"checkResponse end"; + } + +protected: + QNearFieldTagType3 * tagType3; + QNearFieldTarget::RequestId (QNearFieldTagType3::*check)(const QMap<quint16, QList<quint16> > &serviceBlockList); + QNearFieldTarget::RequestId (QNearFieldTagType3::*update)(const QMap<quint16, QList<quint16> > &serviceBlockList, + const QByteArray &data); + QMap<quint16, QList<quint16> > mSerivceBlockList; + QByteArray mDataArray; +}; + +NfcTagRawCommandOperationType3::NfcTagRawCommandOperationType3(QNearFieldTarget * tag):NfcTagRawCommandOperationCommon(tag) +{ + tagType3 = qobject_cast<QNearFieldTagType3 *>(mTarget); + QVERIFY(tagType3); + check = 0; + update = 0; +} + +class tst_qnearfieldtagtype3 : public QObject +{ + Q_OBJECT + +public: + tst_qnearfieldtagtype3(); + void testRawAccessAndNdefAccess(const QList<QNdefMessage> &messages); + +private Q_SLOTS: + void initTestCase(); + void testRawAndNdefAccess(); + void cleanupTestCase(){} +private: + QNfcTagTestCommon<QNearFieldTagType3> tester; +}; + + +tst_qnearfieldtagtype3::tst_qnearfieldtagtype3() +{ +} + +void tst_qnearfieldtagtype3::initTestCase() +{ + +} + +void tst_qnearfieldtagtype3::testRawAccessAndNdefAccess(const QList<QNdefMessage> &messages) +{ + QSignalSpy okSpy(tester.target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId&))); + QSignalSpy errSpy(tester.target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId&))); + QSignalSpy ndefMessageReadSpy(tester.target, SIGNAL(ndefMessageRead(QNdefMessage))); + QSignalSpy ndefMessageWriteSpy(tester.target, SIGNAL(ndefMessagesWritten())); + + int okCount = 0; + int errCount = 0; + int ndefReadCount = 0; + int ndefWriteCount = 0; + + // write ndef first + tester.target->writeNdefMessages(messages); + ++ndefWriteCount; + QTRY_COMPARE(ndefMessageWriteSpy.count(), ndefWriteCount); + + QList<quint16> blockList; + // first block + blockList.append(0); + // NDEF service + quint16 serviceCode = 0x0B; + + QMap<quint16, QList<quint16> > serviceBlockList; + serviceBlockList.insert(serviceCode, blockList); + + QNearFieldTarget::RequestId id = tester.target->check(serviceBlockList); + + QVERIFY(tester.target->waitForRequestCompleted(id)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + + QMap<quint16, QByteArray> result = tester.target->requestResponse(id).value<QMap<quint16, QByteArray> >(); + QVERIFY(result.contains(serviceCode)); + + const QByteArray& attribInfo = result.value(serviceCode); + QVERIFY(!attribInfo.isEmpty()); + + quint32 len = attribInfo.at(11); + len<<=8; + len |= attribInfo.at(12); + len<<=8; + len |= attribInfo.at(13); + + QCOMPARE(len, (quint32)(messages.at(0).toByteArray().count())); + + // read NDEF with RAW command + int Nbc = (0 == len%16)?(len/16):(len/16+1); + qDebug()<<"Nbc = "<<Nbc; + + serviceBlockList.clear(); + blockList.clear(); + for(int i = 1; i <= Nbc; ++i) + { + blockList.append(i); + } + serviceBlockList.insert(serviceCode, blockList); + + QNearFieldTarget::RequestId id1 = tester.target->check(serviceBlockList); + + QVERIFY(tester.target->waitForRequestCompleted(id1)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + + QMap<quint16, QByteArray> ndefContent = tester.target->requestResponse(id1).value<QMap<quint16, QByteArray> >(); + + QVERIFY(ndefContent.contains(serviceCode)); + QCOMPARE(ndefContent.value(serviceCode).left(len), messages.at(0).toByteArray()); + + // update the ndef meesage with raw command + QNdefMessage message; + QNdefNfcTextRecord textRecord; + textRecord.setText("nfc"); + message.append(textRecord); + + QByteArray expectedNdefContent = message.toByteArray(); + len = expectedNdefContent.count(); + serviceCode = 0x0009; + + // use previous attribute information block data, just update the len + QByteArray newAttribInfo = attribInfo; + newAttribInfo[13] = len&0xFF; + newAttribInfo[12] = (len>>8)&0xFF; + newAttribInfo[11] = (len>>16)&0xFF; + newAttribInfo[9] = 0x0F; + + QByteArray ndefData; + ndefData.append(newAttribInfo); + ndefData.append(expectedNdefContent); + + qDebug()<<"updated ndef len = "<<len; + + for (int i = 0; i < 16 - ndefData.count()%16; ++i) + { + // appending padding data + ndefData.append((char)0); + } + qDebug()<<"raw ndefData len = "<<ndefData.count(); + + QList<quint16> updatedBlockList; + + int blockNumber = (len%16 == 0)?len/16:(len/16+1); + qDebug()<<"updated block number = "<<blockNumber; + + for(int i = 0; i <= blockNumber; ++i) + { + updatedBlockList.append((char)i); + } + + qDebug()<<"updatedBlockList len = "<<updatedBlockList.count(); + serviceBlockList.clear(); + serviceBlockList.insert(serviceCode, updatedBlockList); + QNearFieldTarget::RequestId id2 = tester.target->update(serviceBlockList, ndefData); + QVERIFY(tester.target->waitForRequestCompleted(id2)); + QVERIFY(tester.target->requestResponse(id2).toBool()); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + + // read ndef with ndef access + tester.target->readNdefMessages(); + ++ndefReadCount; + QTRY_COMPARE(ndefMessageReadSpy.count(), ndefReadCount); + + const QNdefMessage& ndefMessage_new(ndefMessageReadSpy.first().at(0).value<QNdefMessage>()); + + QCOMPARE(expectedNdefContent, ndefMessage_new.toByteArray()); + QCOMPARE(errSpy.count(), errCount); +} + + +void tst_qnearfieldtagtype3::testRawAndNdefAccess() +{ + tester.touchTarget(); + QNdefMessage message; + QNdefNfcUriRecord uriRecord; + uriRecord.setUri(QUrl("http://qt.nokia.com")); + message.append(uriRecord); + + QList<QNdefMessage> messages; + messages.append(message); + + testRawAccessAndNdefAccess(messages); + tester.removeTarget(); +} +QTEST_MAIN(tst_qnearfieldtagtype3); + +#include "tst_qnearfieldtagtype3.moc" diff --git a/tests/nfcsymbianbackend/qnearfieldtagtype4/qnearfieldtagtype4.pro b/tests/nfcsymbianbackend/qnearfieldtagtype4/qnearfieldtagtype4.pro new file mode 100644 index 00000000..8dab49e6 --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldtagtype4/qnearfieldtagtype4.pro @@ -0,0 +1,32 @@ +QT += testlib + +TARGET = tst_qnearfieldtagtype4 +CONFIG += console +CONFIG -= app_bundle +CONFIG += testcase + +TEMPLATE = app + +INCLUDEPATH += ../../../src/nfc +DEPENDPATH += ../../../src/nfc +INCLUDEPATH += ../common +DEPENDPATH += ../common + +INCLUDEPATH += ../../../src/global +DEPENDPATH += ../../../src/global + +QMAKE_LIBDIR += $$QT_MOBILITY_BUILD_TREE/lib + +HEADERS += ../common/qnfctagtestcommon.h \ + ../common/qdummyslot.h \ + ../common/qautomsgbox.h \ + ../common/qnfctagutil.h + +SOURCES += tst_qnearfieldtagtype4.cpp \ + ../common/qdummyslot.cpp \ + ../common/qautomsgbox.cpp \ + ../common/qnfctagutil.cpp + + +symbian:TARGET.CAPABILITY = LocalServices + diff --git a/tests/nfcsymbianbackend/qnearfieldtagtype4/tst_qnearfieldtagtype4.cpp b/tests/nfcsymbianbackend/qnearfieldtagtype4/tst_qnearfieldtagtype4.cpp new file mode 100644 index 00000000..49f46adb --- /dev/null +++ b/tests/nfcsymbianbackend/qnearfieldtagtype4/tst_qnearfieldtagtype4.cpp @@ -0,0 +1,326 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> +#include <QVariant> +#include <QVariantList> +#include <QtEndian> +#include <qnearfieldtagtype4.h> +#include "qnfctagtestcommon.h" +#include "qnfctestcommon.h" + +class NfcTagRawCommandOperationType4: public NfcTagRawCommandOperationCommon +{ +public: + NfcTagRawCommandOperationType4(QNearFieldTarget * tag); + + void run() + { + if (selectByName) + { + mId = (mTagType4->*selectByName)(mName); + } + + if (selectById) + { + mId = (mTagType4->*selectById)(mFileId); + } + + if (read) + { + mId = (mTagType4->*read)(mLength, mStartOffset); + } + + if (write) + { + mId = (mTagType4->*write)(mDataArray, mStartOffset); + } + checkInvalidId(); + waitRequest(); + } + + void setRead(quint16 length, quint16 startOffset) + { + mLength = length; + mStartOffset = startOffset; + read = &QNearFieldTagType4::read; + } + + void setWrite(const QByteArray &data, quint16 startOffset) + { + mDataArray = data; + mStartOffset = startOffset; + write = &QNearFieldTagType4::write; + } + + void setSelectByName(const QByteArray &name) + { + mName = name; + selectByName = &QNearFieldTagType4::select; + } + + void setSelectById(quint16 fileId) + { + mFileId = fileId; + selectById = &QNearFieldTagType4::select; + } + +protected: + QNearFieldTagType4 * mTagType4; + QNearFieldTarget::RequestId (QNearFieldTagType4::*selectByName)(const QByteArray &name); + QNearFieldTarget::RequestId (QNearFieldTagType4::*selectById)(quint16 fileIdentifier); + QNearFieldTarget::RequestId (QNearFieldTagType4::*write)(const QByteArray &data, quint16 startOffset); + QNearFieldTarget::RequestId (QNearFieldTagType4::*read)(quint16 length, quint16 startOffset); + + QByteArray mDataArray; + QByteArray mName; + quint16 mLength; + quint16 mFileId; + quint16 mStartOffset; +}; + +NfcTagRawCommandOperationType4::NfcTagRawCommandOperationType4(QNearFieldTarget * tag):NfcTagRawCommandOperationCommon(tag) +{ + mTagType4 = qobject_cast<QNearFieldTagType4 *>(mTarget); + QVERIFY(mTagType4); + selectByName = 0; + selectById = 0; + write = 0; + read = 0; +} + + +class tst_qnearfieldtagtype4 : public QObject +{ + Q_OBJECT + +public: + tst_qnearfieldtagtype4(); + void testRawAccessAndNdefAccess(const QList<QNdefMessage> &messages); + +private Q_SLOTS: + void initTestCase(); + void testRawAndNdefAccess(); + void cleanupTestCase(){} +private: + QNfcTagTestCommon<QNearFieldTagType4> mTester; +}; + + +tst_qnearfieldtagtype4::tst_qnearfieldtagtype4() +{ +} + +void tst_qnearfieldtagtype4::initTestCase() +{ +} + +void tst_qnearfieldtagtype4::testRawAccessAndNdefAccess(const QList<QNdefMessage> &messages) +{ + QSignalSpy okSpy(mTester.target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId&))); + QSignalSpy errSpy(mTester.target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId&))); + QSignalSpy ndefMessageReadSpy(mTester.target, SIGNAL(ndefMessageRead(QNdefMessage))); + QSignalSpy ndefMessageWriteSpy(mTester.target, SIGNAL(ndefMessagesWritten())); + + int okCount = 0; + int errCount = 0; + int ndefReadCount = 0; + int ndefWriteCount = 0; + + // write ndef first + mTester.target->writeNdefMessages(messages); + ++ndefWriteCount; + QTRY_COMPARE(ndefMessageWriteSpy.count(), ndefWriteCount); + + // has Ndef message check + QVERIFY(mTester.target->hasNdefMessage()); + + // read NDEF with RAW command + QByteArray resp; // correct response + resp.append(char(0x90)); + resp.append(char(0x00)); + + qDebug()<<"select NDEF application"; + QByteArray command; + command.append(char(0xD2)); + command.append(char(0x76)); + command.append(char(0x00)); + command.append(char(0x00)); + command.append(char(0x85)); + command.append(char(0x01)); + command.append(char(0x00)); + QNearFieldTarget::RequestId id = mTester.target->select(command); + QVERIFY(mTester.target->waitForRequestCompleted(id)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + QVERIFY(mTester.target->requestResponse(id).toBool()); + + qDebug()<<"select CC"; + QNearFieldTarget::RequestId id1 = mTester.target->select(0xe103); + QVERIFY(mTester.target->waitForRequestCompleted(id1)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + QVERIFY(mTester.target->requestResponse(id1).toBool()); + + qDebug()<<"read CC"; + QNearFieldTarget::RequestId id2 = mTester.target->read(0x000F,0x0000); + QVERIFY(mTester.target->waitForRequestCompleted(id2)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + QByteArray ccContent = mTester.target->requestResponse(id2).toByteArray(); + QCOMPARE(ccContent.right(2), resp); + QCOMPARE(ccContent.count(), int(17)); + QCOMPARE(ccContent.at(1), char(0x0F)); + + quint16 ndefFileId = 0; + quint8 temp = ccContent.at(9); + ndefFileId |= temp; + ndefFileId <<= 8; + + temp = ccContent.at(10); + ndefFileId |= temp; + + quint16 maxNdefLen = 0; + temp = ccContent.at(11); + maxNdefLen |= temp; + maxNdefLen <<= 8; + + temp = ccContent.at(12); + maxNdefLen |= temp; + + qDebug()<<"ndefFileId is "<<ndefFileId; + qDebug()<<"maxNdefLen is "<<maxNdefLen; + + qDebug()<<"select NDEF"; + QNearFieldTarget::RequestId id3 = mTester.target->select(ndefFileId); + QVERIFY(mTester.target->waitForRequestCompleted(id3)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + QVERIFY(mTester.target->requestResponse(id3).toBool()); + + qDebug()<<"read NDEF message length"; + QNearFieldTarget::RequestId id4 = mTester.target->read(0x0002, 0x0000); + QVERIFY(mTester.target->waitForRequestCompleted(id4)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + QByteArray ndefLenResult = mTester.target->requestResponse(id4).toByteArray(); + QCOMPARE(ndefLenResult.right(2), resp); + + temp = ndefLenResult.at(0); + quint16 nLen = 0; + nLen |= temp; + nLen <<= 8; + + temp = ndefLenResult.at(1); + nLen |= temp; + + qDebug()<<"ndef length is "<<nLen; + QVERIFY( nLen > 0 ); + QVERIFY( nLen < maxNdefLen - 2 ); + + + qDebug()<<"read NDEF message"; + QNearFieldTarget::RequestId id5 = mTester.target->read(nLen + 2, 0x0000); + QVERIFY(mTester.target->waitForRequestCompleted(id5)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + QByteArray ndefContent = mTester.target->requestResponse(id5).toByteArray(); + QCOMPARE(ndefContent.right(2), resp); + + + QByteArray ndefMessageContent = ndefContent.mid(2, nLen); + QByteArray inputNdefMessageContent = messages.at(0).toByteArray(); + QCOMPARE(ndefMessageContent, inputNdefMessageContent); + + QCOMPARE(errSpy.count(), errCount); + + // Write NDEF with raw command + QNdefMessage message; + QNdefNfcTextRecord textRecord; + textRecord.setText("nfc"); + + message.append(textRecord); + + QByteArray newNdefMessageContent = message.toByteArray(); + quint16 ndefMessageContentLen = newNdefMessageContent.count(); + temp = ndefMessageContentLen & 0x00FF; + newNdefMessageContent.push_front((char)temp); + temp = (ndefMessageContentLen >> 8) & 0x00FF; + newNdefMessageContent.push_front((char)temp); + + // ndef file is selected + QNearFieldTarget::RequestId id6 = mTester.target->write(newNdefMessageContent, 0); + QVERIFY(mTester.target->waitForRequestCompleted(id6)); + ++okCount; + QCOMPARE(okSpy.count(), okCount); + QVERIFY(mTester.target->requestResponse(id6).toBool()); + + // read ndef with ndef access + mTester.target->readNdefMessages(); + ++ndefReadCount; + QTRY_COMPARE(ndefMessageReadSpy.count(), ndefReadCount); + + const QNdefMessage& ndefMessage_new(ndefMessageReadSpy.first().at(0).value<QNdefMessage>()); + + QCOMPARE(newNdefMessageContent.right(newNdefMessageContent.count() - 2), ndefMessage_new.toByteArray()); + QCOMPARE(errSpy.count(), errCount); +} + +void tst_qnearfieldtagtype4::testRawAndNdefAccess() +{ + mTester.touchTarget(); + QNdefMessage message; + QNdefNfcUriRecord uriRecord; + uriRecord.setUri(QUrl("http://qt.nokia.com")); + message.append(uriRecord); + + QList<QNdefMessage> messages; + messages.append(message); + + testRawAccessAndNdefAccess(messages); + mTester.removeTarget(); +} + +QTEST_MAIN(tst_qnearfieldtagtype4); + +#include "tst_qnearfieldtagtype4.moc" diff --git a/tests/nfctestserver/main.cpp b/tests/nfctestserver/main.cpp new file mode 100644 index 00000000..9e02f4f3 --- /dev/null +++ b/tests/nfctestserver/main.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QCoreApplication> + +#include "socketcontroller.h" +#include "servercontroller.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + // Connection oriented sockets + new ServerController(ServerController::StreamConnection, &app); + new ServerController(ServerController::DatagramConnection, &app); + new SocketController(SocketController::StreamConnection, &app); + new SocketController(SocketController::DatagramConnection, &app); + + // Connectionless sockets + new SocketController(SocketController::BoundSocket, &app); + new SocketController(SocketController::ConnectionlessSocket, &app); + + return app.exec(); +} diff --git a/tests/nfctestserver/nfctestserver.pro b/tests/nfctestserver/nfctestserver.pro new file mode 100644 index 00000000..c307c30b --- /dev/null +++ b/tests/nfctestserver/nfctestserver.pro @@ -0,0 +1,27 @@ + +INCLUDEPATH += $$PWD/../../src/nfc +DEPENDPATH += $$PWD/../../src/nfc + + +TARGET = nfctestserver + +CONFIG += qt debug warn_on console depend_includepath testcase +CONFIG += console strict_flags +CONFIG -= app_bundle + +QMAKE_LIBS += -Wl,-rpath,$${QT.nfc.libs} + +QT = core nfc connectivity +qtAddLibrary(QtTest) + + +TEMPLATE = app + +SOURCES += main.cpp \ + socketcontroller.cpp \ + servercontroller.cpp + +HEADERS += \ + socketcontroller.h \ + servercontroller.h \ + servicenames.h diff --git a/tests/nfctestserver/servercontroller.cpp b/tests/nfctestserver/servercontroller.cpp new file mode 100644 index 00000000..aafb82d4 --- /dev/null +++ b/tests/nfctestserver/servercontroller.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "servercontroller.h" +#include "servicenames.h" + +ServerController::ServerController(ConnectionType type, QObject *parent) +: QObject(parent), m_server(new QLlcpServer(this)), m_socket(0), m_connectionType(type) +{ + connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection())); + + switch (m_connectionType) { + case StreamConnection: + m_service = commandServer + streamSuffix; + break; + case DatagramConnection: + m_service = commandServer + datagramSuffix; + break; + } + + m_server->listen(m_service); + + if (m_server->isListening()) + qDebug() << "Server listening on" << m_service; +} + +ServerController::~ServerController() +{ + delete m_socket; + delete m_server; +} + +void ServerController::newConnection() +{ + m_socket = m_server->nextPendingConnection(); + + qDebug() << "Server got new connection"; + + connect(m_socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); + connect(m_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(socketBytesWritten(qint64))); + connect(m_socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); +} + +void ServerController::socketReadyRead() +{ + switch (m_connectionType) { + case StreamConnection: + while (m_socket->canReadLine()) { + const QByteArray line = m_socket->readLine().trimmed(); + + qDebug() << "Server read line:" << line; + + QByteArray command; + QByteArray parameter; + + int index = line.indexOf(' '); + if (index >= 0) { + command = line.left(index); + parameter = line.mid(index + 1); + } else { + command = line; + } + + if (command == "ECHO") { + m_socket->write(parameter + '\n'); + } else if (command == "DISCONNECT") { + m_socket->disconnectFromService(); + break; + } else if (command == "CLOSE") { + m_socket->close(); + break; + } else if (command == "URI") { + m_socket->write(m_service.toLatin1()); + m_socket->write("\n"); + } + } + break; + case DatagramConnection: + while (m_socket->hasPendingDatagrams()) { + qint64 size = m_socket->pendingDatagramSize(); + QByteArray data; + data.resize(size); + m_socket->readDatagram(data.data(), data.size()); + + QByteArray command; + QByteArray parameter; + + int index = data.indexOf(' '); + if (index >= 0) { + command = data.left(index); + parameter = data.mid(index + 1); + } else { + command = data; + } + + if (command == "ECHO") { + m_socket->writeDatagram(parameter); + } else if (command == "DISCONNECT") { + m_socket->disconnectFromService(); + break; + } else if (command == "CLOSE") { + m_socket->close(); + break; + } else if (command == "URI") { + m_socket->writeDatagram(m_service.toLatin1()); + } + } + break; + } +} + +void ServerController::socketBytesWritten(qint64 bytes) +{ + Q_UNUSED(bytes); +} + +void ServerController::socketDisconnected() +{ + m_socket->deleteLater(); + m_socket = 0; +} diff --git a/tests/nfctestserver/servercontroller.h b/tests/nfctestserver/servercontroller.h new file mode 100644 index 00000000..8cb6ca12 --- /dev/null +++ b/tests/nfctestserver/servercontroller.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SERVERCONTROLLER_H +#define SERVERCONTROLLER_H + +#include <QtCore/QObject> + +#include <qllcpserver.h> + +class ServerController : public QObject +{ + Q_OBJECT + +public: + enum ConnectionType { + StreamConnection, + DatagramConnection + }; + + ServerController(ConnectionType type, QObject *parent = 0); + ~ServerController(); + +private slots: + void newConnection(); + + void socketReadyRead(); + void socketBytesWritten(qint64 bytes); + void socketDisconnected(); + +private: + QLlcpServer *m_server; + QLlcpSocket *m_socket; + ConnectionType m_connectionType; + QString m_service; +}; + +#endif // SERVERCONTROLLER_H diff --git a/tests/nfctestserver/servicenames.h b/tests/nfctestserver/servicenames.h new file mode 100644 index 00000000..c90fa7b3 --- /dev/null +++ b/tests/nfctestserver/servicenames.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SERVICENAMES_H +#define SERVICENAMES_H + +static const QLatin1String commandServer("urn:nfc:sn:com.nokia.qt.commandserver"); +static const QLatin1String helloServer("urn:nfc:sn:com.nokia.qt.helloserver"); +static const QLatin1String streamSuffix(".stream"); +static const QLatin1String datagramSuffix(".datagram"); + +static const quint8 boundSocketPort = 63; + +#endif // SERVICENAMES_H diff --git a/tests/nfctestserver/socketcontroller.cpp b/tests/nfctestserver/socketcontroller.cpp new file mode 100644 index 00000000..e16f53eb --- /dev/null +++ b/tests/nfctestserver/socketcontroller.cpp @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "socketcontroller.h" +#include "servicenames.h" + +SocketController::SocketController(ConnectionType type, QObject *parent) +: QObject(parent), m_manager(0), m_socket(new QLlcpSocket(this)), m_connectionType(type), + m_timerId(-1) +{ + connect(m_socket, SIGNAL(connected()), this, SLOT(connected())); + connect(m_socket, SIGNAL(disconnected()), this, SLOT(disconnected())); + connect(m_socket, SIGNAL(error(QLlcpSocket::SocketError)), + this, SLOT(error(QLlcpSocket::SocketError))); + connect(m_socket, SIGNAL(stateChanged(QLlcpSocket::SocketState)), + this, SLOT(stateChanged(QLlcpSocket::SocketState))); + connect(m_socket, SIGNAL(readyRead()), this, SLOT(readyRead())); + + switch (m_connectionType) { + case StreamConnection: + m_service = helloServer + streamSuffix; + qDebug() << "Client connecting to" << m_service; + m_socket->connectToService(0, m_service); + break; + case DatagramConnection: + m_service = helloServer + datagramSuffix; + qDebug() << "Client connecting to" << m_service; + m_socket->connectToService(0, m_service); + break; + case BoundSocket: + m_port = boundSocketPort; + qDebug() << "Client binding to" << m_port; + if (!m_socket->bind(m_port)) + qDebug() << "Failed to bind to port" << m_port; + break; + case ConnectionlessSocket: + qDebug() << "Client binding to arbitrary port"; + if (!m_socket->bind(0)) { + qDebug() << "Failed to bind to arbitrary port"; + } else { + m_manager = new QNearFieldManager(this); + connect(m_manager, SIGNAL(targetDetected(QNearFieldTarget*)), + this, SLOT(targetDetected(QNearFieldTarget*))); + connect(m_manager, SIGNAL(targetLost(QNearFieldTarget*)), + this, SLOT(targetLost(QNearFieldTarget*))); + m_manager->startTargetDetection(QNearFieldTarget::NfcForumDevice); + } + break; + default: + qFatal("Unknown connection type"); + } +} + +SocketController::~SocketController() +{ + delete m_socket; +} + +void SocketController::connected() +{ + qDebug() << "Client connected"; + const QString data = QLatin1String("HELLO ") + m_service; + switch (m_connectionType) { + case StreamConnection: + m_socket->write(data.toUtf8() + '\n'); + break; + case DatagramConnection: + m_socket->writeDatagram(data.toUtf8()); + break; + default: + ; + } +} + +void SocketController::disconnected() +{ + qDebug() << "Client disconnected, reconnecting"; + + m_socket->connectToService(0, m_service); +} + +void SocketController::error(QLlcpSocket::SocketError socketError) +{ + qDebug() << "Client got error:" << socketError; +} + +void SocketController::stateChanged(QLlcpSocket::SocketState socketState) +{ + qDebug() << "Client state changed to" << socketState; +} + +void SocketController::readyRead() +{ + switch (m_connectionType) { + case StreamConnection: + while (m_socket->canReadLine()) { + const QByteArray line = m_socket->readLine().trimmed(); + + qDebug() << "Client read line:" << line; + + if (line == "DISCONNECT") { + m_socket->disconnectFromService(); + break; + } else if (line == "CLOSE") { + m_socket->close(); + break; + } + } + break; + case DatagramConnection: + while (m_socket->hasPendingDatagrams()) { + qint64 size = m_socket->pendingDatagramSize(); + QByteArray data; + data.resize(size); + m_socket->readDatagram(data.data(), data.size()); + + if (data == "DISCONNECT") { + m_socket->disconnectFromService(); + break; + } else if (data == "CLOSE") { + m_socket->close(); + break; + } + } + case BoundSocket: + case ConnectionlessSocket: + while (m_socket->hasPendingDatagrams()) { + qint64 size = m_socket->pendingDatagramSize(); + QByteArray data; + data.resize(size); + m_socket->readDatagram(data.data(), data.size()); + + qDebug() << data; + } + } +} + +void SocketController::targetDetected(QNearFieldTarget *target) +{ + Q_UNUSED(target); + + m_timerId = startTimer(500); +} + +void SocketController::targetLost(QNearFieldTarget *target) +{ + Q_UNUSED(target); + + killTimer(m_timerId); +} + +void SocketController::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + m_socket->writeDatagram("Test message", 12, 0, boundSocketPort); +} diff --git a/tests/nfctestserver/socketcontroller.h b/tests/nfctestserver/socketcontroller.h new file mode 100644 index 00000000..d6273233 --- /dev/null +++ b/tests/nfctestserver/socketcontroller.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SOCKETCONTROLLER_H +#define SOCKETCONTROLLER_H + +#include <QtCore/QObject> + +#include <qnearfieldmanager.h> +#include <qllcpsocket.h> + +class SocketController : public QObject +{ + Q_OBJECT + +public: + enum ConnectionType { + StreamConnection, + DatagramConnection, + BoundSocket, + ConnectionlessSocket + }; + + SocketController(ConnectionType type, QObject *parent = 0); + ~SocketController(); + +public slots: + void connected(); + void disconnected(); + void error(QLlcpSocket::SocketError socketError); + void stateChanged(QLlcpSocket::SocketState socketState); + void readyRead(); + void targetDetected(QNearFieldTarget *target); + void targetLost(QNearFieldTarget *target); + +protected: + void timerEvent(QTimerEvent *event); + +private: + QNearFieldManager *m_manager; + QLlcpSocket *m_socket; + ConnectionType m_connectionType; + QString m_service; + quint8 m_port; + int m_timerId; +}; + +#endif // SOCKETCONTROLLER_H diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 00000000..b2ca6bf9 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs +SUBDIRS += nfctestserver + +linux*:!linux-armcc:contains(bluez_enabled, yes):contains(QT_CONFIG, dbus) { + SUBDIRS += btclient +} + +symbian { + SUBDIRS += nfcsymbianbackend +} |