Commit f5bf9ebe authored by matthew coleman's avatar matthew coleman

Merge remote-tracking branch 'upstream/master'

parents 7624ae36 3101261e

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

This diff is collapsed.
# -------------------------------------------------
# QGroundControl - Micro Air Vehicle Groundstation
# Please see our website at <http://qgroundcontrol.org>
# Maintainer:
# Lorenz Meier <lm@inf.ethz.ch>
# (c) 2009-2014 QGroundControl Developers
# This file is part of the open groundstation project
# QGroundControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# QGroundControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with QGroundControl. If not, see <http://www.gnu.org/licenses/>.
# -------------------------------------------------
#
# This file contains configuration settings which are common to both the QGC Application and
# the Location Plugin. It should mainly contains intial CONFIG tag setup and compiler settings.
#
# Setup our supported build types. We do this once here and then use the defined config scopes
# to allow us to easily modify suported build types in one place instead of duplicated throughout
# the project file.
linux {
linux-g++ | linux-g++-64 {
message("Linux build")
CONFIG += LinuxBuild
} else : android-g++ {
message("Android build")
CONFIG += AndroidBuild
DEFINES += __mobile__
DEFINES += __android__
warning("Android build is experimental and not fully functional")
} else {
error("Unsuported Linux toolchain, only GCC 32- or 64-bit is supported")
}
} else : win32 {
win32-msvc2010 | win32-msvc2012 | win32-msvc2013 {
message("Windows build")
CONFIG += WindowsBuild
} else {
error("Unsupported Windows toolchain, only Visual Studio 2010, 2012, and 2013 are supported")
}
} else : macx {
macx-clang | macx-llvm {
message("Mac build")
CONFIG += MacBuild
QMAKE_CXXFLAGS += -fvisibility=hidden
} else {
error("Unsupported Mac toolchain, only 64-bit LLVM+clang is supported")
}
} else {
error("Unsupported build platform, only Linux, Windows, and Mac are supported")
}
# Installer configuration
installer {
CONFIG -= debug
CONFIG -= debug_and_release
CONFIG += release
message(Build Installer)
}
# Setup our supported build flavors
CONFIG(debug, debug|release) {
message(Debug flavor)
CONFIG += DebugBuild
} else:CONFIG(release, debug|release) {
message(Release flavor)
CONFIG += ReleaseBuild
} else {
error(Unsupported build flavor)
}
# Need to special case Windows debug_and_release since VS Project creation in this case does strange things [QTBUG-40351]
win32:debug_and_release {
CONFIG += WindowsDebugAndRelease
}
# Setup our build directories
BASEDIR = $${IN_PWD}
DebugBuild {
DESTDIR = $${OUT_PWD}/debug
BUILDDIR = $${OUT_PWD}/build-debug
}
ReleaseBuild {
DESTDIR = $${OUT_PWD}/release
BUILDDIR = $${OUT_PWD}/build-release
}
OBJECTS_DIR = $${BUILDDIR}/obj
MOC_DIR = $${BUILDDIR}/moc
UI_DIR = $${BUILDDIR}/ui
RCC_DIR = $${BUILDDIR}/rcc
LANGUAGE = C++
# We place the created plugin lib into the objects dir so that make clean will clean it as well
LOCATION_PLUGIN_DESTDIR = $${OBJECTS_DIR}
LOCATION_PLUGIN_NAME = QGeoServiceProviderFactoryQGC
message(BASEDIR $$BASEDIR DESTDIR $$DESTDIR TARGET $$TARGET)
# Turn off serial port warnings
DEFINES += _TTY_NOWARN_
#
# OS Specific settings
#
AndroidBuild {
DEFINES += __STDC_LIMIT_MACROS
}
MacBuild {
CONFIG += x86_64
CONFIG -= x86
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
QMAKE_MAC_SDK = macosx10.9
}
LinuxBuild {
DEFINES += __STDC_LIMIT_MACROS
}
WindowsBuild {
DEFINES += __STDC_LIMIT_MACROS
# Specify multi-process compilation within Visual Studio.
# (drastically improves compilation times for multi-core computers)
QMAKE_CXXFLAGS_DEBUG += -MP
QMAKE_CXXFLAGS_RELEASE += -MP
}
#
# By default warnings as errors are turned off. Even so, in order for a pull request
# to be accepted you must compile cleanly with warnings as errors turned on the default
# set of OS builds. See http://www.qgroundcontrol.org/dev/contribute for more details.
# You can use the WarningsAsErrorsOn CONFIG switch to turn warnings as errors on for your
# own builds.
#
MacBuild | LinuxBuild {
QMAKE_CXXFLAGS_WARN_ON += -Wall
WarningsAsErrorsOn {
QMAKE_CXXFLAGS_WARN_ON += -Werror
}
}
WindowsBuild {
QMAKE_CXXFLAGS_WARN_ON += /W3 \
/wd4996 \ # silence warnings about deprecated strcpy and whatnot
/wd4005 \ # silence warnings about macro redefinition
/wd4290 \ # ignore exception specifications
/Zc:strictStrings- # work around win 8.1 sdk sapi.h problem
WarningsAsErrorsOn {
QMAKE_CXXFLAGS_WARN_ON += /WX
}
}
#
# Build-specific settings
#
ReleaseBuild {
DEFINES += QT_NO_DEBUG
WindowsBuild {
# Use link time code generation for better optimization (I believe this is supported in MSVC Express, but not 100% sure)
QMAKE_LFLAGS_LTCG = /LTCG
QMAKE_CFLAGS_LTCG = -GL
}
}
#
# Unit Test specific configuration goes here
#
# We have to special case Windows debug_and_release builds because you can't have files
# which are only in the debug variant [QTBUG-40351]. So in this case we include unit tests
# even in the release variant. If you want a Windows release build with no unit tests run
# qmake with CONFIG-=debug_and_release CONFIG+=release.
#
DebugBuild|WindowsDebugAndRelease {
DEFINES += UNITTEST_BUILD
}
......@@ -55,153 +55,6 @@ exists($$MAVLINKPATH/common) {
error($$sprintf("MAVLink folder does not exist at '%1'! Run 'git submodule init && git submodule update' on the command line.",$$MAVLINKPATH_REL))
}
#
# [OPTIONAL] OpenSceneGraph
# Allow the user to override OpenSceneGraph compilation through a DISABLE_OPEN_SCENE_GRAPH
# define like: `qmake DEFINES=DISABLE_OPEN_SCENE_GRAPH`
contains(DEFINES, DISABLE_OPEN_SCENE_GRAPH) {
message("Skipping support for OpenSceneGraph (manual override from command line)")
DEFINES -= DISABLE_OPEN_SCENE_GRAPH
}
# Otherwise the user can still disable this feature in the user_config.pri file.
else:exists(user_config.pri):infile(user_config.pri, DEFINES, DISABLE_OPEN_SCENE_GRAPH) {
message("Skipping support for OpenSceneGraph (manual override from user_config.pri)")
}
else:MacBuild {
# GLUT and OpenSceneGraph are part of standard install on Mac
message("Including support for OpenSceneGraph")
CONFIG += OSGDependency
INCLUDEPATH += \
$$BASEDIR/libs/lib/mac64/include
LIBS += \
-L$$BASEDIR/libs/lib/mac64/lib \
-losgWidget
} else:LinuxBuild {
exists(/usr/include/osg) | exists(/usr/local/include/osg) {
message("Including support for OpenSceneGraph")
CONFIG += OSGDependency
} else {
warning("Skipping support for OpenSceneGraph (missing libraries, see README)")
}
} else:WindowsBuild {
exists($$BASEDIR/libs/lib/osg123) {
message("Including support for OpenSceneGraph")
CONFIG += OSGDependency
INCLUDEPATH += \
$$BASEDIR/libs/lib/osgEarth/win32/include \
$$BASEDIR/libs/lib/osgEarth_3rdparty/win32/OpenSceneGraph-2.8.2/include
LIBS += -L$$BASEDIR/libs/lib/osgEarth_3rdparty/win32/OpenSceneGraph-2.8.2/lib
} else {
warning("Skipping support for OpenSceneGraph (missing libraries, see README)")
}
} else {
message("Skipping support for OpenSceneGraph (unsupported platform)")
}
OSGDependency {
DEFINES += QGC_OSG_ENABLED
LIBS += \
-losg \
-losgViewer \
-losgGA \
-losgDB \
-losgText \
-lOpenThreads
HEADERS += \
src/ui/map3D/gpl.h \
src/ui/map3D/CameraParams.h \
src/ui/map3D/ViewParamWidget.h \
src/ui/map3D/SystemContainer.h \
src/ui/map3D/SystemViewParams.h \
src/ui/map3D/GlobalViewParams.h \
src/ui/map3D/SystemGroupNode.h \
src/ui/map3D/Q3DWidget.h \
src/ui/map3D/GCManipulator.h \
src/ui/map3D/ImageWindowGeode.h \
src/ui/map3D/PixhawkCheetahNode.h \
src/ui/map3D/Pixhawk3DWidget.h \
src/ui/map3D/Q3DWidgetFactory.h \
src/ui/map3D/WebImageCache.h \
src/ui/map3D/WebImage.h \
src/ui/map3D/TextureCache.h \
src/ui/map3D/Texture.h \
src/ui/map3D/Imagery.h \
src/ui/map3D/HUDScaleGeode.h \
src/ui/map3D/WaypointGroupNode.h \
src/ui/map3D/TerrainParamDialog.h \
src/ui/map3D/ImageryParamDialog.h
SOURCES += \
src/ui/map3D/gpl.cc \
src/ui/map3D/CameraParams.cc \
src/ui/map3D/ViewParamWidget.cc \
src/ui/map3D/SystemContainer.cc \
src/ui/map3D/SystemViewParams.cc \
src/ui/map3D/GlobalViewParams.cc \
src/ui/map3D/SystemGroupNode.cc \
src/ui/map3D/Q3DWidget.cc \
src/ui/map3D/ImageWindowGeode.cc \
src/ui/map3D/GCManipulator.cc \
src/ui/map3D/PixhawkCheetahNode.cc \
src/ui/map3D/Pixhawk3DWidget.cc \
src/ui/map3D/Q3DWidgetFactory.cc \
src/ui/map3D/WebImageCache.cc \
src/ui/map3D/WebImage.cc \
src/ui/map3D/TextureCache.cc \
src/ui/map3D/Texture.cc \
src/ui/map3D/Imagery.cc \
src/ui/map3D/HUDScaleGeode.cc \
src/ui/map3D/WaypointGroupNode.cc \
src/ui/map3D/TerrainParamDialog.cc \
src/ui/map3D/ImageryParamDialog.cc
}
#
# [OPTIONAL] Google Earth dependency. Provides Google Earth view to supplement 2D map view.
# Only supported on Mac and Windows where Google Earth can be installed.
#
GoogleEarthDisableOverride {
contains(DEFINES, DISABLE_GOOGLE_EARTH) {
message("Skipping support for Google Earth view (manual override from command line)")
DEFINES -= DISABLE_GOOGLE_EARTH
}
# Otherwise the user can still disable this feature in the user_config.pri file.
else:exists(user_config.pri):infile(user_config.pri, DEFINES, DISABLE_GOOGLE_EARTH) {
message("Skipping support for Google Earth view (manual override from user_config.pri)")
} else:MacBuild {
message("Including support for Google Earth view")
DEFINES += QGC_GOOGLE_EARTH_ENABLED
HEADERS += src/ui/map3D/QGCGoogleEarthView.h \
src/ui/map3D/QGCWebPage.h \
src/ui/QGCWebView.h
SOURCES += src/ui/map3D/QGCGoogleEarthView.cc \
src/ui/map3D/QGCWebPage.cc \
src/ui/QGCWebView.cc
FORMS += src/ui/QGCWebView.ui
} else:WindowsBuild {
message("Including support for Google Earth view")
DEFINES += QGC_GOOGLE_EARTH_ENABLED
HEADERS += src/ui/map3D/QGCGoogleEarthView.h \
src/ui/map3D/QGCWebPage.h \
src/ui/QGCWebView.h
SOURCES += src/ui/map3D/QGCGoogleEarthView.cc \
src/ui/map3D/QGCWebPage.cc \
src/ui/QGCWebView.cc
FORMS += src/ui/QGCWebView.ui
QT += axcontainer
} else {
message("Skipping support for Google Earth view (unsupported platform)")
}
} else {
message("Skipping support for Google Earth due to Issue 1157")
}
#
# [REQUIRED] EIGEN matrix library
# NOMINMAX constant required to make internal min/max work.
......@@ -416,11 +269,12 @@ contains (DEFINES, DISABLE_SPEECH) {
}
# Mac support is built into OS 10.6+.
else:MacBuild {
message("Including support for speech output")
DEFINES += QGC_SPEECH_ENABLED
message("Including support for speech output")
DEFINES += QGC_SPEECH_ENABLED
}
# Windows supports speech through native API.
else:WindowsBuild {
message("Including support for speech output")
DEFINES += QGC_SPEECH_ENABLED
message("Including support for speech output")
DEFINES += QGC_SPEECH_ENABLED
LIBS += -lOle32
}
include(QGCCommon.pri)
TEMPLATE = lib
TARGET = QGeoServiceProviderFactoryQGC
CONFIG += plugin static
QT += location-private positioning-private network
PLUGIN_TYPE = geoservices
DESTDIR = $${LOCATION_PLUGIN_DESTDIR}
INCLUDEPATH += $$QT.location.includes
HEADERS += \
src/QtLocationPlugin/qgeoserviceproviderpluginqgc.h \
src/QtLocationPlugin/qgeotiledmappingmanagerengineqgc.h \
src/QtLocationPlugin/qgeotilefetcherqgc.h \
src/QtLocationPlugin/qgeomapreplyqgc.h \
src/QtLocationPlugin/qgeocodingmanagerengineqgc.h \
src/QtLocationPlugin/qgeocodereplyqgc.h \
src/QtLocationPlugin/OpenPilotMaps.h
SOURCES += \
src/QtLocationPlugin/qgeoserviceproviderpluginqgc.cpp \
src/QtLocationPlugin/qgeotiledmappingmanagerengineqgc.cpp \
src/QtLocationPlugin/qgeotilefetcherqgc.cpp \
src/QtLocationPlugin/qgeomapreplyqgc.cpp \
src/QtLocationPlugin/qgeocodingmanagerengineqgc.cpp \
src/QtLocationPlugin/qgeocodereplyqgc.cpp \
src/QtLocationPlugin/OpenPilotMaps.cc
OTHER_FILES += \
src/QtLocationPlugin/qgc_maps_plugin.json
......@@ -19,6 +19,10 @@
QMAKE_POST_LINK += echo "Copying files"
AndroidBuild {
INSTALLS += $$DESTDIR
}
#
# Copy the application resources to the associated place alongside the application
#
......@@ -36,14 +40,14 @@ MacBuild {
# in the target.
WindowsBuild {
# Make sure to keep both side of this if using the same set of directories
DESTDIR_COPY_RESOURCE_LIST = $$replace(DESTDIR,"/","\\")
BASEDIR_COPY_RESOURCE_LIST = $$replace(BASEDIR,"/","\\")
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$BASEDIR_COPY_RESOURCE_LIST\\files\" \"$$DESTDIR_COPY_RESOURCE_LIST\\files\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$BASEDIR_COPY_RESOURCE_LIST\\data\" \"$$DESTDIR_COPY_RESOURCE_LIST\\data\"
DESTDIR_COPY_RESOURCE_LIST = $$replace(DESTDIR,"/","\\")
BASEDIR_COPY_RESOURCE_LIST = $$replace(BASEDIR,"/","\\")
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$BASEDIR_COPY_RESOURCE_LIST\\flightgear\" \"$$DESTDIR_COPY_RESOURCE_LIST\\flightgear\"
} else {
# Make sure to keep both side of this if using the same set of directories
QMAKE_POST_LINK += && $$QMAKE_COPY_DIR $$BASEDIR/files $$DESTDIR_COPY_RESOURCE_LIST
QMAKE_POST_LINK += && $$QMAKE_COPY_DIR $$BASEDIR/data $$DESTDIR_COPY_RESOURCE_LIST
!AndroidBuild {
# Make sure to keep both sides of this if using the same set of directories
QMAKE_POST_LINK += && $$QMAKE_COPY_DIR $$BASEDIR/flightgear $$DESTDIR_COPY_RESOURCE_LIST
}
}
#
......@@ -153,13 +157,13 @@ MacBuild {
}
WindowsBuild {
BASEDIR_WIN = $$replace(BASEDIR, "/", "\\")
DESTDIR_WIN = $$replace(DESTDIR, "/", "\\")
D_DIR = $$[QT_INSTALL_LIBEXECS]
DLL_DIR = $$replace(D_DIR, "/", "\\")
BASEDIR_WIN = $$replace(BASEDIR, "/", "\\")
DESTDIR_WIN = $$replace(DESTDIR, "/", "\\")
D_DIR = $$[QT_INSTALL_LIBEXECS]
DLL_DIR = $$replace(D_DIR, "/", "\\")
# Copy dependencies
DebugBuild: DLL_QT_DEBUGCHAR = "d"
# Copy dependencies
DebugBuild: DLL_QT_DEBUGCHAR = "d"
ReleaseBuild: DLL_QT_DEBUGCHAR = ""
COPY_FILE_LIST = \
$$BASEDIR\\libs\\lib\\sdl\\win32\\SDL.dll \
......@@ -167,6 +171,7 @@ WindowsBuild {
$$DLL_DIR\\icu*.dll \
$$DLL_DIR\\Qt5Core$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5Gui$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5Location$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5Multimedia$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5MultimediaWidgets$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5Network$${DLL_QT_DEBUGCHAR}.dll \
......@@ -178,7 +183,6 @@ WindowsBuild {
$$DLL_DIR\\Qt5QuickWidgets$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5Sensors$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5SerialPort$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5OpenGL$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5Sql$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5Svg$${DLL_QT_DEBUGCHAR}.dll \
$$DLL_DIR\\Qt5Test$${DLL_QT_DEBUGCHAR}.dll \
......@@ -190,17 +194,18 @@ WindowsBuild {
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"$$COPY_FILE\" \"$$DESTDIR_WIN\"
}
# Copy platform plugins
P_DIR = $$[QT_INSTALL_PLUGINS]
PLUGINS_DIR_WIN = $$replace(P_DIR, "/", "\\")
QMAKE_POST_LINK += $$escape_expand(\\n) mkdir release\\platforms
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"$$PLUGINS_DIR_WIN\\platforms\\qwindows$${DLL_QT_DEBUGCHAR}.dll\" \"$$DESTDIR_WIN\\platforms\\qwindows$${DLL_QT_DEBUGCHAR}.dll\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$PLUGINS_DIR_WIN\\imageformats\" \"$$DESTDIR_WIN\\imageformats\"
# Copy platform plugins
P_DIR = $$[QT_INSTALL_PLUGINS]
PLUGINS_DIR_WIN = $$replace(P_DIR, "/", "\\")
QMAKE_POST_LINK += $$escape_expand(\\n) mkdir "$$DESTDIR_WIN\\platforms"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"$$PLUGINS_DIR_WIN\\platforms\\qwindows$${DLL_QT_DEBUGCHAR}.dll\" \"$$DESTDIR_WIN\\platforms\\qwindows$${DLL_QT_DEBUGCHAR}.dll\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$PLUGINS_DIR_WIN\\imageformats\" \"$$DESTDIR_WIN\\imageformats\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$PLUGINS_DIR_WIN\\sqldrivers\" \"$$DESTDIR_WIN\\sqldrivers\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$PLUGINS_DIR_WIN\\bearer\" \"$$DESTDIR_WIN\\bearer\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$PLUGINS_DIR_WIN\\iconengines\" \"$$DESTDIR_WIN\\iconengines\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$PLUGINS_DIR_WIN\\printsupport\" \"$$DESTDIR_WIN\\printsupport\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$PLUGINS_DIR_WIN\\qmltooling\" \"$$DESTDIR_WIN\\qmltooling\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$PLUGINS_DIR_WIN\\geoservices\" \"$$DESTDIR_WIN\\geoservices\"
# Copy Qml libraries
Q_DIR = $$[QT_INSTALL_QML]
......@@ -208,6 +213,8 @@ WindowsBuild {
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$QML_DIR_WIN\\QtGraphicalEffects\" \"$$DESTDIR_WIN\\QtGraphicalEffects\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$QML_DIR_WIN\\QtQuick\" \"$$DESTDIR_WIN\\QtQuick\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$QML_DIR_WIN\\QtQuick.2\" \"$$DESTDIR_WIN\\QtQuick.2\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$QML_DIR_WIN\\QtLocation\" \"$$DESTDIR_WIN\\QtLocation\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY_DIR \"$$QML_DIR_WIN\\QtPositioning\" \"$$DESTDIR_WIN\\QtPositioning\"
ReleaseBuild {
# Copy Visual Studio DLLs
......
......@@ -50,7 +50,7 @@ QGroundControl builds are supported for OSX, Linux and Windows. See the individu
Supported builds are 64 bit, built using the clang compiler.
#### Install QT
- - -
1. Download Qt 5.4 from: <http://download.qt-project.org/official_releases/qt/5.4/5.4.0/qt-opensource-mac-x64-clang-5.4.0.dmg>
2. Double click the package installer and follow instructions.
......@@ -66,12 +66,14 @@ Supported builds for Linux are 32 or 64-bit, built using gcc.
* For Fedora: `sudo yum install qt-creator qt5-qtbase-devel qt5-qtdeclarative-devel qt5-qtserialport-devel qt5-qtsvg-devel qt5-qtwebkit-devel SDL-devel SDL-static systemd-devel qt5-qtgraphicaleffects qt5-qtquickcontrols`
* For Arch Linux: `pacman -Sy qtcreator qt5-base qt5-declarative qt5-serialport qt5-svg qt5-webkit`
* For Ubuntu: Please be aware that the time of writing, Qt5.4 is unavailable in the official repositories Ubuntu 14.04/Mint 17
* Add this PPA to your sources.list: `ppa:beineri/opt-qt541-trusty`
* Add this PPA for Qt5.4: `sudo add-apt-repository ppa:beineri/opt-qt541-trusty`
* If you get a 404 error from "apt-get update" below, open System Settings:Software & Updates:Other Software and edit the entry for opt-qt541-trusty to reference Distribution: trusty.
* Run the following in your terminal: `sudo apt-get update && sudo apt-get install qt54tools qt54base qt54declarative qt54serialport qt54svg qt54webkit qt54quickcontrols qt54xmlpatterns qt54x11extras qt54websockets qt54sensors qt54script qt54quick1 qt54qbs qt54multimedia qt54location qt54imageformats qt54graphicaleffects qt54creator qt54connectivity`
* Run the following in your terminal: `sudo apt-get update && sudo apt-get install qt54tools qt54base qt54declarative qt54serialport qt54svg qt54webkit qt54quickcontrols qt54xmlpatterns qt54x11extras qt54websockets qt54sensors qt54script qt54quick1 qt54qbs qt54multimedia qt54location qt54imageformats qt54graphicaleffects qt54creator qt54connectivity libsdl1.2-dev libudev-dev`
* Next, set the environment variables by executing in the terminal: `source /opt/qt54/bin/qt54-env.sh` or copy and paste the contents to your `~/.profile` file to set them on login.
* Verify that the variables have been set: `echo $PATH && echo $QTDIR`. The output should read `/opt/qt54/bin:...` and `/opt/qt54`.
If you get this error when running qgroundcontrol: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version 'GLIBCXX_3.4.20' not found. You need to either update to the latest gcc, or install the latest libstdc++.6 using: sudo apt-get install libstdc++6.
#### [Optional] Install additional libraries
* For text-to-speech (espeak)
* For Ubuntu: `sudo apt-get install espeak libespeak-dev`
......@@ -84,12 +86,15 @@ Supported builds for Linux are 32 or 64-bit, built using gcc.
#### Build QGroundControl
1. Change directory to you `qgroundcontrol` source directory.
2. Run `qmake`
2. Run `qmake -r qgroundcontrol.pro`
3. Run `make`
### Build on Windows
Supported builds for Windows are 32 bit only built using Visual Studio 2013 or higher.
#### Install Windows USB driver to connect to Pixhawk/PX4Flow/3DR Radio
Install from here: http://www.pixhawk.org/firmware/downloads
#### Install Visual Studio Express 2013
Only compilation using Visual Studio 2013 is supported. Download and install Visual Studio Express Edition (free) from here: <http://www.visualstudio.com/downloads/download-visual-studio-vs#d-express-windows-desktop>. Make sure you install the Windows Desktop version.
......@@ -100,9 +105,30 @@ Download Qt 5.4 from here: <http://download.qt-project.org/official_releases/qt/
#### Build QGroundControl
1. Open the Qt Command Prompt program from the Start Menu
2. Change directory to your 'qgroundcontrol' source folder.
3. Run `qmake -tp vc qgroundcontrol.pro`. This will create a 'qgroundcontrol.vcxproj' project file which is capable of building both debug and release configurations.
4. Now open the generated 'qgroundcontrol.vcxproj' file in Visual Studio.
5. Compile and edit in Visual Studio. If you need to add new files, add them to qgroundcontrol.pro and re-run qmake from step 3.
3. Run `qmake -r -tp vc qgroundcontrol.pro`. This will create a 'qgroundcontrol.sln' *Solution* file which is capable of building both debug and release configurations.
4. Now open the generated 'qgroundcontrol.sln' file in Visual Studio.
5. Compile and edit in Visual Studio. If you need to add new files to the qgroundcontrol project, add them to QGCApplication.pro and re-run qmake from step 3.
Note that the *Solution* contains two projets. The main QGroundControl project and the QGC Geoservice Provider Factory plugin. From within Visual Studio, before running or debugging, make sure you have *qgroundcontrol* as the current project (right-click and select *Set as Current Project*)
#### Alternate (Qt Creator IDE) Build Type (Any OS)
All steps below assume you already have a running software development enviroment (i.e. gcc/g++ on Ubuntu, Xcode on Mac OSX along with the command line tools, Visual Studio on Windows, etc.) along with the various external dependencies described elsewhere in this document.
* Download the Qt Online Installer executable from <http://www.qt.io/download-open-source/>
* On Ubuntu, you have to set the file to executable:`chmod +x ~/Downloads/qt-opensource-linux-x64-1.6.0-8-online.run\`
* Run the installer and follow the installation steps.
* Select the directory you want to install Qt, which is handy if you don't want to install system wide or don't have root access.
* Select the components you want to install. *Tools* will be selected by default. You also want to install the Qt 5.4 module along with the targets you are interested in (i.e. 32-Bit OpenGL for Windows, etc.). On Ubuntu, *Android armv7* will be selected by default as well. You may or may not want to install that, depending on your desire to target that platform. Same idea for OS X. It will have *iOS* Kits selected as well.
* Accept the license and the installer will download all the necessary modules and install where you told it to install.
* Go to the Qt Creator directory:
* `~/local/Qt/Tools/QtCreator/bin` for Ubuntu (if that's where you installed it)
* `~/local/Qt/Qt Creator.app` for OS X (if that's where you installed it)
* `C:/local/Qt/Tools/QtCreator/bin` for Windows (if that's where you installed it)
* Launch Qt Creator and open the `qgroundcontrol.pro` project.
When you open a project in Qt Creator for the first time, it will ask what targets (*Kits*) you want to target. The options will depend on what modules you downloaded above. For instance, on Mac OS X you would select *Desktop Qt 5.4.1 clang 64bit*.
It's also a good idea to go into *Projects/Build Steps* (side tool bar) and select Make's *Details*. For *Make Arguments*, add `-jx` (`/J x` on Windows) where `x` is at least the numbers of cores you have. That is, if you are running on a Mac Pro with 24 cores, you would use `-j24`. That will run 24 concurrent compiler instances at a time and run the build a whole lot faster. Your mileage may vary depending on your disk IO throughput. Note that for Windows, this method will build QGC x many times faster than when using Visual Studio as described above. Visual Studio allocates one process per *Project*. As QGroundControl is one very large project, it will still compile one file at a time within that one process. When you build from within Qt Creator (and give the ```/J x``` option to make), it will use x number of concurrent compiler processes.
Qt Creator is a full-blown development IDE. You can even debug right from within it and it provides the full Qt API documentation. Just place the mouse cursor over a Qt class/element and hit the F1 key.
### Additional build notes for all supported OS
......@@ -114,7 +140,6 @@ Download Qt 5.4 from here: <http://download.qt-project.org/official_releases/qt/
* Single release congfiguration on Windows: If you want to build a vs project that does not create both debug and release builds. Include `CONFIG-=debug_and_release` on the qmake command line plus either `CONFIG+=debug` or
`CONFIG+=release` depending on the build type you want.
* Build using QtCreator: It is possible to build and debug using QtCreator as well. The above instructions should provide you with enough information to setup QtCreator on OSX and Linux. QtCreator on Windows is supposedly possible but we don't have any instructions available for that.
* Google Earth is only supported on 32 bit builds, which by default means only Windows builds.
* QGroundControl is using the Qt QLoggingCategory class for logging (<http://qt-project.org/doc/qt-5/qloggingcategory.html>). Since logging is on by default, an example qtlogging.ini file is included at the root of the repository which disables logging. Follow the instructions from Qt as to why and where to put this file. You can then edit the file to get a logging level that suits your needs.
## Additional functionality
......
<?xml version="1.0"?>
<manifest package="org.qgroundcontrol" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.3.0" android:versionCode="2" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:icon="@drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qgroundcontrol.qgchelper.UsbDeviceJNI" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="reverseLandscape" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
</intent-filter>
<!-- Needed to keep working while 'asleep' -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Support devices without USB host mode since there are other connection types -->
<uses-feature android:name="android.hardware.usb.host" android:required="false"/>
<meta-data android:resource="@xml/device_filter" android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
<meta-data android:resource="@xml/device_filter" android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
<!-- Rest of Standard Manifest -->
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<!-- Splash screen -->
<!--
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
-->
<!-- Splash screen -->
<!-- Background running -->
<!-- Warning: changing this value to true may cause unexpected crashes if the
application still try to draw after
"applicationStateChanged(Qt::ApplicationSuspended)"
signal is sent! -->
<meta-data android:name="android.app.background_running" android:value="false"/>
<!-- Background running -->
</activity>
</application>
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Everything -->
<usb-device />
<!-- 0x26AC / 0x11: PX4 FMU Pixhawk -->
<!--
<usb-device vendor-id="9900" product-id="17" />
-->
<!-- 0x0403 / 0x6001: FTDI FT232R UART -->
<!--
<usb-device vendor-id="1027" product-id="24577" />
-->
<!-- 0x0403 / 0x6015: FTDI FT231X -->
<!--
<usb-device vendor-id="1027" product-id="24597" />
-->
<!-- 0x2341 / Arduino -->
<!--
<usb-device vendor-id="9025" />
-->
<!-- 0x16C0 / 0x0483: Teensyduino -->
<!--
<usb-device vendor-id="5824" product-id="1155" />
-->
<!-- 0x10C4 / 0xEA60: CP210x UART Bridge -->
<!--
<usb-device vendor-id="4292" product-id="60000" />
-->
<!-- 0x067B / 0x2303: Prolific PL2303 -->
<!--
<usb-device vendor-id="1659" product-id="8963" />
-->
</resources>
package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.util.Log;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* USB CDC/ACM serial driver implementation.
*
* @author mike wakerly (opensource@hoho.com)
* @see <a
* href="http://www.usb.org/developers/devclass_docs/usbcdc11.pdf">Universal
* Serial Bus Class Definitions for Communication Devices, v1.1</a>
*/
public class CdcAcmSerialDriver extends CommonUsbSerialDriver {
private final String TAG = CdcAcmSerialDriver.class.getSimpleName();
private UsbInterface mControlInterface;
private UsbInterface mDataInterface;
private UsbEndpoint mControlEndpoint;
private UsbEndpoint mReadEndpoint;
private UsbEndpoint mWriteEndpoint;
private boolean mRts = false;
private boolean mDtr = false;
private static final int USB_RECIP_INTERFACE = 0x01;
private static final int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE;
private static final int SET_LINE_CODING = 0x20; // USB CDC 1.1 section 6.2
private static final int GET_LINE_CODING = 0x21;
private static final int SET_CONTROL_LINE_STATE = 0x22;
private static final int SEND_BREAK = 0x23;
public CdcAcmSerialDriver(UsbDevice device, UsbDeviceConnection connection) {
super(device, connection);
}
@Override
public void open() throws IOException {
Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount());
Log.d(TAG, "Claiming control interface.");
mControlInterface = mDevice.getInterface(0);
Log.d(TAG, "Control iface=" + mControlInterface);
// class should be USB_CLASS_COMM
if (!mConnection.claimInterface(mControlInterface, true)) {
throw new IOException("Could not claim control interface.");
}
mControlEndpoint = mControlInterface.getEndpoint(0);
Log.d(TAG, "Control endpoint direction: " + mControlEndpoint.getDirection());
Log.d(TAG, "Claiming data interface.");
mDataInterface = mDevice.getInterface(1);
Log.d(TAG, "data iface=" + mDataInterface);
// class should be USB_CLASS_CDC_DATA
if (!mConnection.claimInterface(mDataInterface, true)) {
throw new IOException("Could not claim data interface.");
}
mReadEndpoint = mDataInterface.getEndpoint(1);
Log.d(TAG, "Read endpoint direction: " + mReadEndpoint.getDirection());
mWriteEndpoint = mDataInterface.getEndpoint(0);
Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection());
}
private int sendAcmControlMessage(int request, int value, byte[] buf) {
return mConnection.controlTransfer(
USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000);
}
@Override
public void close() throws IOException {
mConnection.close();
}
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int write(byte[] src, int timeoutMillis) throws IOException {
// TODO(mikey): Nearly identical to FtdiSerial write. Refactor.
int offset = 0;
while (offset < src.length) {
final int writeLength;
final int amtWritten;
synchronized (mWriteBufferLock) {
final byte[] writeBuffer;
writeLength = Math.min(src.length - offset, mWriteBuffer.length);
if (offset == 0) {
writeBuffer = src;
} else {
// bulkTransfer does not support offsets, make a copy.
System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
writeBuffer = mWriteBuffer;
}
amtWritten = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
timeoutMillis);
}
if (amtWritten <= 0) {
throw new IOException("Error writing " + writeLength
+ " bytes at offset " + offset + " length=" + src.length);
}
//Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
offset += amtWritten;
}
return offset;
}
@Override
public void setParameters(int baudRate, int dataBits, int stopBits, int parity) {
byte stopBitsByte;
switch (stopBits) {
case STOPBITS_1: stopBitsByte = 0; break;
case STOPBITS_1_5: stopBitsByte = 1; break;
case STOPBITS_2: stopBitsByte = 2; break;
default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits);
}
byte parityBitesByte;
switch (parity) {
case PARITY_NONE: parityBitesByte = 0; break;
case PARITY_ODD: parityBitesByte = 1; break;
case PARITY_EVEN: parityBitesByte = 2; break;
case PARITY_MARK: parityBitesByte = 3; break;
case PARITY_SPACE: parityBitesByte = 4; break;
default: throw new IllegalArgumentException("Bad value for parity: " + parity);
}
byte[] msg = {
(byte) ( baudRate & 0xff),
(byte) ((baudRate >> 8 ) & 0xff),
(byte) ((baudRate >> 16) & 0xff),
(byte) ((baudRate >> 24) & 0xff),
stopBitsByte,
parityBitesByte,
(byte) dataBits};
sendAcmControlMessage(SET_LINE_CODING, 0, msg);
}
@Override
public boolean getCD() throws IOException {
return false; // TODO
}
@Override
public boolean getCTS() throws IOException {
return false; // TODO
}
@Override
public boolean getDSR() throws IOException {
return false; // TODO
}
@Override
public boolean getDTR() throws IOException {
return mDtr;
}
@Override
public void setDTR(boolean value) throws IOException {
mDtr = value;
setDtrRts();
}
@Override
public boolean getRI() throws IOException {
return false; // TODO
}
@Override
public boolean getRTS() throws IOException {
return mRts;
}
@Override
public void setRTS(boolean value) throws IOException {
mRts = value;
setDtrRts();
}
private void setDtrRts() {
int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0);
sendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null);
}
public static Map<Integer, int[]> getSupportedDevices() {
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>();
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ARDUINO),
new int[] {
UsbId.ARDUINO_UNO,
UsbId.ARDUINO_UNO_R3,
UsbId.ARDUINO_MEGA_2560,
UsbId.ARDUINO_MEGA_2560_R3,
UsbId.ARDUINO_SERIAL_ADAPTER,
UsbId.ARDUINO_SERIAL_ADAPTER_R3,
UsbId.ARDUINO_MEGA_ADK,
UsbId.ARDUINO_MEGA_ADK_R3,
UsbId.ARDUINO_LEONARDO,
});
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_VAN_OOIJEN_TECH),
new int[] {
UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL,
});
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ATMEL),
new int[] {
UsbId.ATMEL_LUFA_CDC_DEMO_APP,
});
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_LEAFLABS),
new int[] {
UsbId.LEAFLABS_MAPLE,
});
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_PX4),
new int[] {
UsbId.DEVICE_PX4FMU,
});
return supportedDevices;
}
}
/* Copyright 2013 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Project home page: http://code.google.com/p/usb-serial-for-android/
*/
package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import java.io.IOException;
/**
* A base class shared by several driver implementations.
*
* @author mike wakerly (opensource@hoho.com)
*/
abstract class CommonUsbSerialDriver implements UsbSerialDriver {
public static final int DEFAULT_READ_BUFFER_SIZE = 16 * 1024;
public static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024;
protected final UsbDevice mDevice;
protected final UsbDeviceConnection mConnection;
protected final Object mReadBufferLock = new Object();
protected final Object mWriteBufferLock = new Object();
/** Internal read buffer. Guarded by {@link #mReadBufferLock}. */
protected byte[] mReadBuffer;
/** Internal write buffer. Guarded by {@link #mWriteBufferLock}. */
protected byte[] mWriteBuffer;
public CommonUsbSerialDriver(UsbDevice device, UsbDeviceConnection connection) {
mDevice = device;
mConnection = connection;
mReadBuffer = new byte[DEFAULT_READ_BUFFER_SIZE];
mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE];
}
/**
* Returns the currently-bound USB device.
*
* @return the device
*/
@Override
public final UsbDevice getDevice() {
return mDevice;
}
/**
* Returns the currently-bound USB device connection.
*
* @return the device connection
*/
@Override
public final UsbDeviceConnection getDeviceConnection() {
return mConnection;
}
/**
* Sets the size of the internal buffer used to exchange data with the USB
* stack for read operations. Most users should not need to change this.
*
* @param bufferSize the size in bytes
*/
public final void setReadBufferSize(int bufferSize) {
synchronized (mReadBufferLock) {
if (bufferSize == mReadBuffer.length) {
return;
}
mReadBuffer = new byte[bufferSize];
}
}
/**
* Sets the size of the internal buffer used to exchange data with the USB
* stack for write operations. Most users should not need to change this.
*
* @param bufferSize the size in bytes
*/
public final void setWriteBufferSize(int bufferSize) {
synchronized (mWriteBufferLock) {
if (bufferSize == mWriteBuffer.length) {
return;
}
mWriteBuffer = new byte[bufferSize];
}
}
@Override
public abstract void open() throws IOException;
@Override
public abstract void close() throws IOException;
@Override
public abstract int read(final byte[] dest, final int timeoutMillis) throws IOException;
@Override
public abstract int write(final byte[] src, final int timeoutMillis) throws IOException;
@Override
public abstract void setParameters(
int baudRate, int dataBits, int stopBits, int parity) throws IOException;
@Override
public abstract boolean getCD() throws IOException;
@Override
public abstract boolean getCTS() throws IOException;
@Override
public abstract boolean getDSR() throws IOException;
@Override
public abstract boolean getDTR() throws IOException;
@Override
public abstract void setDTR(boolean value) throws IOException;
@Override
public abstract boolean getRI() throws IOException;
@Override
public abstract boolean getRTS() throws IOException;
@Override
public abstract void setRTS(boolean value) throws IOException;
@Override
public boolean purgeHwBuffers(boolean flushReadBuffers, boolean flushWriteBuffers) throws IOException {
return !flushReadBuffers && !flushWriteBuffers;
}
}
package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.util.Log;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
public class Cp2102SerialDriver extends CommonUsbSerialDriver {
private static final String TAG = Cp2102SerialDriver.class.getSimpleName();
private static final int DEFAULT_BAUD_RATE = 9600;
private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
/*
* Configuration Request Types
*/
private static final int REQTYPE_HOST_TO_DEVICE = 0x41;
/*
* Configuration Request Codes
*/
private static final int SILABSER_IFC_ENABLE_REQUEST_CODE = 0x00;
private static final int SILABSER_SET_BAUDDIV_REQUEST_CODE = 0x01;
private static final int SILABSER_SET_LINE_CTL_REQUEST_CODE = 0x03;
private static final int SILABSER_SET_MHS_REQUEST_CODE = 0x07;
private static final int SILABSER_SET_BAUDRATE = 0x1E;
private static final int SILABSER_FLUSH_REQUEST_CODE = 0x12;
private static final int FLUSH_READ_CODE = 0x0a;
private static final int FLUSH_WRITE_CODE = 0x05;
/*
* SILABSER_IFC_ENABLE_REQUEST_CODE
*/
private static final int UART_ENABLE = 0x0001;
private static final int UART_DISABLE = 0x0000;
/*
* SILABSER_SET_BAUDDIV_REQUEST_CODE
*/
private static final int BAUD_RATE_GEN_FREQ = 0x384000;
/*
* SILABSER_SET_MHS_REQUEST_CODE
*/
private static final int MCR_DTR = 0x0001;
private static final int MCR_RTS = 0x0002;
private static final int MCR_ALL = 0x0003;
private static final int CONTROL_WRITE_DTR = 0x0100;
private static final int CONTROL_WRITE_RTS = 0x0200;
private UsbEndpoint mReadEndpoint;
private UsbEndpoint mWriteEndpoint;
public Cp2102SerialDriver(UsbDevice device, UsbDeviceConnection connection) {
super(device, connection);
}
private int setConfigSingle(int request, int value) {
return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
0, null, 0, USB_WRITE_TIMEOUT_MILLIS);
}
@Override
public void open() throws IOException {
boolean opened = false;
try {
for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
UsbInterface usbIface = mDevice.getInterface(i);
if (mConnection.claimInterface(usbIface, true)) {
Log.d(TAG, "claimInterface " + i + " SUCCESS");
} else {
Log.d(TAG, "claimInterface " + i + " FAIL");
}
}
UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1);
for (int i = 0; i < dataIface.getEndpointCount(); i++) {
UsbEndpoint ep = dataIface.getEndpoint(i);
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
mReadEndpoint = ep;
} else {
mWriteEndpoint = ep;
}
}
}
setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_ENABLE);
setConfigSingle(SILABSER_SET_MHS_REQUEST_CODE, MCR_ALL | CONTROL_WRITE_DTR | CONTROL_WRITE_RTS);
setConfigSingle(SILABSER_SET_BAUDDIV_REQUEST_CODE, BAUD_RATE_GEN_FREQ / DEFAULT_BAUD_RATE);
// setParameters(DEFAULT_BAUD_RATE, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY);
opened = true;
} finally {
if (!opened) {
close();
}
}
}
@Override
public void close() throws IOException {
setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
mConnection.close();
}
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int write(byte[] src, int timeoutMillis) throws IOException {
int offset = 0;
while (offset < src.length) {
final int writeLength;
final int amtWritten;
synchronized (mWriteBufferLock) {
final byte[] writeBuffer;
writeLength = Math.min(src.length - offset, mWriteBuffer.length);
if (offset == 0) {
writeBuffer = src;
} else {
// bulkTransfer does not support offsets, make a copy.
System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
writeBuffer = mWriteBuffer;
}
amtWritten = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
timeoutMillis);
}
if (amtWritten <= 0) {
throw new IOException("Error writing " + writeLength
+ " bytes at offset " + offset + " length=" + src.length);
}
//Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
offset += amtWritten;
}
return offset;
}
private void setBaudRate(int baudRate) throws IOException {
byte[] data = new byte[] {
(byte) ( baudRate & 0xff),
(byte) ((baudRate >> 8 ) & 0xff),
(byte) ((baudRate >> 16) & 0xff),
(byte) ((baudRate >> 24) & 0xff)
};
int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,
0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS);
if (ret < 0) {
throw new IOException("Error setting baud rate.");
}
}
@Override
public void setParameters(int baudRate, int dataBits, int stopBits, int parity)
throws IOException {
setBaudRate(baudRate);
int configDataBits = 0;
switch (dataBits) {
case DATABITS_5:
configDataBits |= 0x0500;
break;
case DATABITS_6:
configDataBits |= 0x0600;
break;
case DATABITS_7:
configDataBits |= 0x0700;
break;
case DATABITS_8:
configDataBits |= 0x0800;
break;
default:
configDataBits |= 0x0800;
break;
}
setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configDataBits);
int configParityBits = 0; // PARITY_NONE
switch (parity) {
case PARITY_ODD:
configParityBits |= 0x0010;
break;
case PARITY_EVEN:
configParityBits |= 0x0020;
break;
}
setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configParityBits);
int configStopBits = 0;
switch (stopBits) {
case STOPBITS_1:
configStopBits |= 0;
break;
case STOPBITS_2:
configStopBits |= 2;
break;
}
setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configStopBits);
}
@Override
public boolean getCD() throws IOException {
return false;
}
@Override
public boolean getCTS() throws IOException {
return false;
}
@Override
public boolean getDSR() throws IOException {
return false;
}
@Override
public boolean getDTR() throws IOException {
return true;
}
@Override
public void setDTR(boolean value) throws IOException {
}
@Override
public boolean getRI() throws IOException {
return false;
}
@Override
public boolean getRTS() throws IOException {
return true;
}
@Override
public boolean purgeHwBuffers(boolean purgeReadBuffers,
boolean purgeWriteBuffers) throws IOException {
int value = (purgeReadBuffers ? FLUSH_READ_CODE : 0)
| (purgeWriteBuffers ? FLUSH_WRITE_CODE : 0);
if (value != 0) {
setConfigSingle(SILABSER_FLUSH_REQUEST_CODE, value);
}
return true;
}
@Override
public void setRTS(boolean value) throws IOException {
}
public static Map<Integer, int[]> getSupportedDevices() {
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>();
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SILAB),
new int[] {
UsbId.SILAB_CP2102
});
return supportedDevices;
}
}
/* Copyright 2012 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Project home page: http://code.google.com/p/usb-serial-for-android/
*/
package com.hoho.android.usbserial.driver;
/**
* Registry of USB vendor/product ID constants.
*
* Culled from various sources; see
* <a href="http://www.linux-usb.org/usb.ids">usb.ids</a> for one listing.
*
* @author mike wakerly (opensource@hoho.com)
*/
public final class UsbId {
public static final int VENDOR_FTDI = 0x0403;
public static final int FTDI_FT232R = 0x6001;
public static final int FTDI_FT231X = 0x6015;
public static final int VENDOR_PX4 = 0x26AC;
public static final int DEVICE_PX4FMU = 0x11;
public static final int VENDOR_ATMEL = 0x03EB;
public static final int ATMEL_LUFA_CDC_DEMO_APP = 0x2044;
public static final int VENDOR_ARDUINO = 0x2341;
public static final int ARDUINO_UNO = 0x0001;
public static final int ARDUINO_MEGA_2560 = 0x0010;
public static final int ARDUINO_SERIAL_ADAPTER = 0x003b;
public static final int ARDUINO_MEGA_ADK = 0x003f;
public static final int ARDUINO_MEGA_2560_R3 = 0x0042;
public static final int ARDUINO_UNO_R3 = 0x0043;
public static final int ARDUINO_MEGA_ADK_R3 = 0x0044;
public static final int ARDUINO_SERIAL_ADAPTER_R3 = 0x0044;
public static final int ARDUINO_LEONARDO = 0x8036;
public static final int VENDOR_VAN_OOIJEN_TECH = 0x16c0;
public static final int VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL = 0x0483;
public static final int VENDOR_LEAFLABS = 0x1eaf;
public static final int LEAFLABS_MAPLE = 0x0004;
public static final int VENDOR_SILAB = 0x10c4;
public static final int SILAB_CP2102 = 0xea60;
public static final int VENDOR_PROLIFIC = 0x067b;
public static final int PROLIFIC_PL2303 = 0x2303;
private UsbId() {
throw new IllegalAccessError("Non-instantiable class.");
}
}
/* Copyright 2011 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Project home page: http://code.google.com/p/usb-serial-for-android/
*/
package com.hoho.android.usbserial.driver;
import java.io.IOException;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
/**
* Driver interface for a USB serial device.
*
* @author mike wakerly (opensource@hoho.com)
*/
public interface UsbSerialDriver {
/** 5 data bits. */
public static final int DATABITS_5 = 5;
/** 6 data bits. */
public static final int DATABITS_6 = 6;
/** 7 data bits. */
public static final int DATABITS_7 = 7;
/** 8 data bits. */
public static final int DATABITS_8 = 8;
/** No flow control. */
public static final int FLOWCONTROL_NONE = 0;
/** RTS/CTS input flow control. */
public static final int FLOWCONTROL_RTSCTS_IN = 1;
/** RTS/CTS output flow control. */
public static final int FLOWCONTROL_RTSCTS_OUT = 2;
/** XON/XOFF input flow control. */
public static final int FLOWCONTROL_XONXOFF_IN = 4;
/** XON/XOFF output flow control. */
public static final int FLOWCONTROL_XONXOFF_OUT = 8;
/** No parity. */
public static final int PARITY_NONE = 0;
/** Odd parity. */
public static final int PARITY_ODD = 1;
/** Even parity. */
public static final int PARITY_EVEN = 2;
/** Mark parity. */
public static final int PARITY_MARK = 3;
/** Space parity. */
public static final int PARITY_SPACE = 4;
/** 1 stop bit. */
public static final int STOPBITS_1 = 1;
/** 1.5 stop bits. */
public static final int STOPBITS_1_5 = 3;
/** 2 stop bits. */
public static final int STOPBITS_2 = 2;
/**
* Returns the currently-bound USB device.
*
* @return the device
*/
public UsbDevice getDevice();
/**
* Returns the currently-bound USB device.
*
* @return the device
*/
public UsbDeviceConnection getDeviceConnection();
/**
* Opens and initializes the device as a USB serial device. Upon success,
* caller must ensure that {@link #close()} is eventually called.
*
* @throws IOException on error opening or initializing the device.
*/
public void open() throws IOException;
/**
* Closes the serial device.
*
* @throws IOException on error closing the device.
*/
public void close() throws IOException;
/**
* Reads as many bytes as possible into the destination buffer.
*
* @param dest the destination byte buffer
* @param timeoutMillis the timeout for reading
* @return the actual number of bytes read
* @throws IOException if an error occurred during reading
*/
public int read(final byte[] dest, final int timeoutMillis) throws IOException;
/**
* Writes as many bytes as possible from the source buffer.
*
* @param src the source byte buffer
* @param timeoutMillis the timeout for writing
* @return the actual number of bytes written
* @throws IOException if an error occurred during writing
*/
public int write(final byte[] src, final int timeoutMillis) throws IOException;
/**
* Sets various serial port parameters.
*
* @param baudRate baud rate as an integer, for example {@code 115200}.
* @param dataBits one of {@link #DATABITS_5}, {@link #DATABITS_6},
* {@link #DATABITS_7}, or {@link #DATABITS_8}.
* @param stopBits one of {@link #STOPBITS_1}, {@link #STOPBITS_1_5}, or
* {@link #STOPBITS_2}.
* @param parity one of {@link #PARITY_NONE}, {@link #PARITY_ODD},
* {@link #PARITY_EVEN}, {@link #PARITY_MARK}, or
* {@link #PARITY_SPACE}.
* @throws IOException on error setting the port parameters
*/
public void setParameters(
int baudRate, int dataBits, int stopBits, int parity) throws IOException;
/**
* Gets the CD (Carrier Detect) bit from the underlying UART.
*
* @return the current state, or {@code false} if not supported.
* @throws IOException if an error occurred during reading
*/
public boolean getCD() throws IOException;
/**
* Gets the CTS (Clear To Send) bit from the underlying UART.
*
* @return the current state, or {@code false} if not supported.
* @throws IOException if an error occurred during reading
*/
public boolean getCTS() throws IOException;
/**
* Gets the DSR (Data Set Ready) bit from the underlying UART.
*
* @return the current state, or {@code false} if not supported.
* @throws IOException if an error occurred during reading
*/
public boolean getDSR() throws IOException;
/**
* Gets the DTR (Data Terminal Ready) bit from the underlying UART.
*
* @return the current state, or {@code false} if not supported.
* @throws IOException if an error occurred during reading
*/
public boolean getDTR() throws IOException;
/**
* Sets the DTR (Data Terminal Ready) bit on the underlying UART, if
* supported.
*
* @param value the value to set
* @throws IOException if an error occurred during writing
*/
public void setDTR(boolean value) throws IOException;
/**
* Gets the RI (Ring Indicator) bit from the underlying UART.
*
* @return the current state, or {@code false} if not supported.
* @throws IOException if an error occurred during reading
*/
public boolean getRI() throws IOException;
/**
* Gets the RTS (Request To Send) bit from the underlying UART.
*
* @return the current state, or {@code false} if not supported.
* @throws IOException if an error occurred during reading
*/
public boolean getRTS() throws IOException;
/**
* Sets the RTS (Request To Send) bit on the underlying UART, if
* supported.
*
* @param value the value to set
* @throws IOException if an error occurred during writing
*/
public void setRTS(boolean value) throws IOException;
/**
* Flush non-transmitted output data and / or non-read input data
* @param flushRX {@code true} to flush non-transmitted output data
* @param flushTX {@code true} to flush non-read input data
* @return {@code true} if the operation was successful, or
* {@code false} if the operation is not supported by the driver or device
* @throws IOException if an error occurred during flush
*/
public boolean purgeHwBuffers(boolean flushRX, boolean flushTX) throws IOException;
}
/* Copyright 2011 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Project home page: http://code.google.com/p/usb-serial-for-android/
*/
package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Helper class which finds compatible {@link UsbDevice}s and creates
* {@link UsbSerialDriver} instances.
*
* <p/>
* You don't need a Prober to use the rest of the library: it is perfectly
* acceptable to instantiate driver instances manually. The Prober simply
* provides convenience functions.
*
* <p/>
* For most drivers, the corresponding {@link #probe(UsbManager, UsbDevice)}
* method will either return an empty list (device unknown / unsupported) or a
* singleton list. However, multi-port drivers may return multiple instances.
*
* @author mike wakerly (opensource@hoho.com)
*/
public enum UsbSerialProber {
// TODO(mikey): Too much boilerplate.
/**
* Prober for {@link FtdiSerialDriver}.
*
* @see FtdiSerialDriver
*/
FTDI_SERIAL {
@Override
public List<UsbSerialDriver> probe(final UsbManager manager, final UsbDevice usbDevice) {
if (!testIfSupported(usbDevice, FtdiSerialDriver.getSupportedDevices())) {
return Collections.emptyList();
}
final UsbDeviceConnection connection = manager.openDevice(usbDevice);
if (connection == null) {
return Collections.emptyList();
}
final UsbSerialDriver driver = new FtdiSerialDriver(usbDevice, connection);
return Collections.singletonList(driver);
}
},
CDC_ACM_SERIAL {
@Override
public List<UsbSerialDriver> probe(UsbManager manager, UsbDevice usbDevice) {
if (!testIfSupported(usbDevice, CdcAcmSerialDriver.getSupportedDevices())) {
return Collections.emptyList();
}
final UsbDeviceConnection connection = manager.openDevice(usbDevice);
if (connection == null) {
return Collections.emptyList();
}
final UsbSerialDriver driver = new CdcAcmSerialDriver(usbDevice, connection);
return Collections.singletonList(driver);
}
},
SILAB_SERIAL {
@Override
public List<UsbSerialDriver> probe(final UsbManager manager, final UsbDevice usbDevice) {
if (!testIfSupported(usbDevice, Cp2102SerialDriver.getSupportedDevices())) {
return Collections.emptyList();
}
final UsbDeviceConnection connection = manager.openDevice(usbDevice);
if (connection == null) {
return Collections.emptyList();
}
final UsbSerialDriver driver = new Cp2102SerialDriver(usbDevice, connection);
return Collections.singletonList(driver);
}
},
PROLIFIC_SERIAL {
@Override
public List<UsbSerialDriver> probe(final UsbManager manager, final UsbDevice usbDevice) {
if (!testIfSupported(usbDevice, ProlificSerialDriver.getSupportedDevices())) {
return Collections.emptyList();
}
final UsbDeviceConnection connection = manager.openDevice(usbDevice);
if (connection == null) {
return Collections.emptyList();
}
final UsbSerialDriver driver = new ProlificSerialDriver(usbDevice, connection);
return Collections.singletonList(driver);
}
};
/**
* Tests the supplied {@link UsbDevice} for compatibility with this enum
* member, returning one or more driver instances if compatible.
*
* @param manager the {@link UsbManager} to use
* @param usbDevice the raw {@link UsbDevice} to use
* @return zero or more {@link UsbSerialDriver}, depending on compatibility
* (never {@code null}).
*/
protected abstract List<UsbSerialDriver> probe(final UsbManager manager, final UsbDevice usbDevice);
/**
* Creates and returns a new {@link UsbSerialDriver} instance for the first
* compatible {@link UsbDevice} found on the bus. If none are found,
* returns {@code null}.
*
* <p/>
* The order of devices is undefined, therefore if there are multiple
* devices on the bus, the chosen device may not be predictable (clients
* should use {@link #findAllDevices(UsbManager)} instead).
*
* @param usbManager the {@link UsbManager} to use.
* @return the first available {@link UsbSerialDriver}, or {@code null} if
* none are available.
*/
public static UsbSerialDriver findFirstDevice(final UsbManager usbManager) {
for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) {
for (final UsbSerialProber prober : values()) {
final List<UsbSerialDriver> probedDevices = prober.probe(usbManager, usbDevice);
if (!probedDevices.isEmpty()) {
return probedDevices.get(0);
}
}
}
return null;
}
/**
* Creates a new {@link UsbSerialDriver} instance for all compatible
* {@link UsbDevice}s found on the bus. If no compatible devices are found,
* the list will be empty.
*
* @param usbManager
* @return
*/
public static List<UsbSerialDriver> findAllDevices(final UsbManager usbManager) {
final List<UsbSerialDriver> result = new ArrayList<UsbSerialDriver>();
//Log.i("QGC_UsbSerialProber", "Looking for USB devices");
// For each UsbDevice, call probe() for each prober.
for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) {
//Log.i("QGC_UsbSerialProber", "Probing device: " + usbDevice.getDeviceName() + " mid: " + usbDevice.getVendorId() + " pid: " + usbDevice.getDeviceId());
result.addAll(probeSingleDevice(usbManager, usbDevice));
}
return result;
}
/**
* Special method for testing a specific device for driver support,
* returning any compatible driver(s).
*
* <p/>
* Clients should ordinarily use {@link #findAllDevices(UsbManager)}, which
* operates against the entire bus of devices. This method is useful when
* testing against only a single target is desired.
*
* @param usbManager the {@link UsbManager} to use.
* @param usbDevice the device to test against.
* @return a list containing zero or more {@link UsbSerialDriver} instances.
*/
public static List<UsbSerialDriver> probeSingleDevice(final UsbManager usbManager,
UsbDevice usbDevice)
{
final List<UsbSerialDriver> result = new ArrayList<UsbSerialDriver>();
for (final UsbSerialProber prober : values()) {
final List<UsbSerialDriver> probedDevices = prober.probe(usbManager, usbDevice);
result.addAll(probedDevices);
}
return result;
}
/**
* Deprecated; Use {@link #findFirstDevice(UsbManager)}.
*
* @param usbManager
* @return
*/
@Deprecated
public static UsbSerialDriver acquire(final UsbManager usbManager) {
return findFirstDevice(usbManager);
}
/**
* Deprecated; use {@link #probeSingleDevice(UsbManager, UsbDevice)}.
*
* @param usbManager
* @param usbDevice
* @return
*/
@Deprecated
public static UsbSerialDriver acquire(final UsbManager usbManager, final UsbDevice usbDevice) {
final List<UsbSerialDriver> probedDevices = probeSingleDevice(usbManager, usbDevice);
if (!probedDevices.isEmpty()) {
return probedDevices.get(0);
}
return null;
}
/**
* Returns {@code true} if the given device is found in the driver's
* vendor/product map.
*
* @param usbDevice the device to test
* @param supportedDevices map of vendor IDs to product ID(s)
* @return {@code true} if supported
*/
private static boolean testIfSupported(final UsbDevice usbDevice,
final Map<Integer, int[]> supportedDevices) {
final int[] supportedProducts = supportedDevices.get(
Integer.valueOf(usbDevice.getVendorId()));
if (supportedProducts == null) {
return false;
}
final int productId = usbDevice.getProductId();
for (int supportedProductId : supportedProducts) {
if (productId == supportedProductId) {
return true;
}
}
return false;
}
}
/*
* Copyright 2011 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package com.hoho.android.usbserial.driver;
/**
* Generic unchecked exception for the usbserial package.
*
* @author mike wakerly (opensource@hoho.com)
*/
@SuppressWarnings("serial")
public class UsbSerialRuntimeException extends RuntimeException {
public UsbSerialRuntimeException() {
super();
}
public UsbSerialRuntimeException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
public UsbSerialRuntimeException(String detailMessage) {
super(detailMessage);
}
public UsbSerialRuntimeException(Throwable throwable) {
super(throwable);
}
}
This diff is collapsed.
package org.qgroundcontrol.qgchelper;
/* Copyright 2011 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Project home page: http://code.google.com/p/usb-serial-for-android/
*/
import com.hoho.android.usbserial.driver.*;
import java.io.IOException;
import java.nio.ByteBuffer;
import android.util.Log;
/**
* Utility class which services a {@link UsbSerialDriver} in its {@link #run()}
* method.
*
* Original author mike wakerly (opensource@hoho.com)
* Modified by Mike Goza
*/
public class UsbIoManager implements Runnable {
private static final int READ_WAIT_MILLIS = 100;
private static final int BUFSIZ = 4096;
private static final String TAG = "QGC_UsbIoManager";
private final UsbSerialDriver mDriver;
private int mUserData;
private final ByteBuffer mReadBuffer = ByteBuffer.allocate(BUFSIZ);
private final ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ);
private enum State
{
STOPPED,
RUNNING,
STOPPING
}
// Synchronized by 'this'
private State mState = State.STOPPED;
// Synchronized by 'this'
private Listener mListener;
public interface Listener
{
/**
* Called when new incoming data is available.
*/
public void onNewData(byte[] data, int userData);
/**
* Called when {@link SerialInputOutputManager#run()} aborts due to an
* error.
*/
public void onRunError(Exception e, int userData);
}
/**
* Creates a new instance with no listener.
*/
public UsbIoManager(UsbSerialDriver driver)
{
this(driver, null, 0);
Log.i(TAG, "Instance created");
}
/**
* Creates a new instance with the provided listener.
*/
public UsbIoManager(UsbSerialDriver driver, Listener listener, int userData)
{
mDriver = driver;
mListener = listener;
mUserData = userData;
}
public synchronized void setListener(Listener listener)
{
mListener = listener;
}
public synchronized Listener getListener()
{
return mListener;
}
public void writeAsync(byte[] data)
{
synchronized (mWriteBuffer)
{
mWriteBuffer.put(data);
}
}
public synchronized void stop()
{
if (getState() == State.RUNNING)
{
mState = State.STOPPING;
mUserData = 0;
}
}
private synchronized State getState()
{
return mState;
}
/**
* Continuously services the read and write buffers until {@link #stop()} is
* called, or until a driver exception is raised.
*/
@Override
public void run()
{
synchronized (this)
{
if (mState != State.STOPPED)
throw new IllegalStateException("Already running.");
mState = State.RUNNING;
}
try
{
while (true)
{
if (mState != State.RUNNING)
break;
step();
}
}
catch (Exception e)
{
final Listener listener = getListener();
if (listener != null)
listener.onRunError(e, mUserData);
}
finally
{
synchronized (this)
{
mState = State.STOPPED;
}
}
}
private void step() throws IOException
{
// Handle incoming data.
int len = mDriver.read(mReadBuffer.array(), READ_WAIT_MILLIS);
if (len > 0)
{
final Listener listener = getListener();
if (listener != null)
{
final byte[] data = new byte[len];
mReadBuffer.get(data, 0, len);
listener.onNewData(data, mUserData);
}
mReadBuffer.clear();
}
/*
// Handle outgoing data.
byte[] outBuff = null;
synchronized (mWriteBuffer)
{
if (mWriteBuffer.position() > 0)
{
len = mWriteBuffer.position();
outBuff = new byte[len];
mWriteBuffer.rewind();
mWriteBuffer.get(outBuff, 0, len);
mWriteBuffer.clear();
}
}
if (outBuff != null)
mDriver.write(outBuff, READ_WAIT_MILLIS);
*/
}
}
#!/bin/bash
#----------------------------------------------------------
# You will need:
# - Qt 5.4 android_armv7 kit
# - Android SDK
# - Androig NDK
# - Current Java
# - ant
#----------------------------------------------------------
# Update with correct location for these
export ANDROID_HOME=~/Library/Android/sdk
export ANDROID_SDK_ROOT=~/Library/Android/sdk
export ANDROID_NDK_ROOT=~/Library/Android/ndk
export ANDROID_NDK_HOST=darwin-x86_64
export ANDROID_NDK_PLATFORM=/android-9
export ANDROID_NDK_TOOLCHAIN_PREFIX=arm-linux-androideabi
export ANDROID_NDK_TOOLCHAIN_VERSION=4.9
export ANDROID_NDK_TOOLS_PREFIX=arm-linux-androideabi
#----------------------------------------------------------
# To build it, run (replacing the path with where you have Qt installed)
#
# For a shadow build: (strongly recomended)
#
# >source android_environment.sh
# cd ../
# mkdir android_build
# cd android_build
# >~/local/Qt/5.4/android_armv7/bin/qmake -r -spec android-g++ CONFIG+=debug ../qgroundcontrol/qgroundcontrol.pro
# >make -j24
# >~/local/Qt/5.4/android_armv7/bin/androiddeployqt --input ./android-libqgroundcontrol.so-deployment-settings.json --output ./android-build --deployment bundled --android-platform android-22 --jdk /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home --verbose --ant /opt/local/bin/ant
#
# For an in place build (not recomended)
#
# >source android_environment.sh
# >~/local/Qt/5.4/android_armv7/bin/qmake -r -spec android-g++ CONFIG+=debug qgroundcontrol.pro
# >make -j24
# >~/local/Qt/5.4/android_armv7/bin/androiddeployqt --input ./android-libqgroundcontrol.so-deployment-settings.json --output ./android-build --deployment bundled --android-platform android-22 --jdk /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home --verbose --ant /opt/local/bin/ant
<ParameterList version="0.1">
<!-- Parameters in the top level block -->
<Block name="TopLevel">
</Block>
<!--Parameters related to the navigation block -->
<Block name="Navigation">
<Parameter
SimulinkPath="avionics_src/sm_avionics/Navigation_Filter/NAV_FILT_INIT/"
SimulinkParameterName="Value"
QGCParamID="NAV_FILT_INIT"
/>
</Block>
<!--Parameters related to the controller block -->
<Block name="Controller">
<!-- Aileron Control Parameters -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Attitude_Controller/PID_AIL/kp/"
SimulinkParameterName="Gain"
QGCParamID="AIL_KP"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Attitude_Controller/PID_AIL/ki/"
SimulinkParameterName="Gain"
QGCParamID="AIL_KI"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Attitude_Controller/PID_AIL/kd/"
SimulinkParameterName="Gain"
QGCParamID="AIL_KD"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Attitude_Controller/PID_AIL/Angle_Norm/Max_Min_Angle/"
SimulinkParameterName="Value"
QGCParamID="ANG_AIL_MAX"
/>
<!-- Elevator Control Parameters -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Attitude_Controller/PID_ELE/kp/"
SimulinkParameterName="Gain"
QGCParamID="ELE_KP"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Attitude_Controller/PID_ELE/ki/"
SimulinkParameterName="Gain"
QGCParamID="ELE_KI"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Attitude_Controller/PID_ELE/kd/"
SimulinkParameterName="Gain"
QGCParamID="ELE_KD"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Attitude_Controller/PID_ELE/Angle_Norm/Max_Min_Angle/"
SimulinkParameterName="Value"
QGCParamID="ANG_ELE_MAX"
/>
</Block>
<!-- Paremters for the Pilot Input/Raw RC block -->
<Block name="ServoInputs">
<!-- Settings for Aileron Servo -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/AileronInput/"
SimulinkParameterName="Setpoint0"
QGCParamID="AIL_LEFT_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/AileronInput/"
SimulinkParameterName="Setpoint1"
QGCParamID="AIL_CENTER_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/AileronInput/"
SimulinkParameterName="Setpoint2"
QGCParamID="AIL_RIGHT_IN"
/>
<!-- Settings for Elevator Servo -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/ElevatorInput/"
SimulinkParameterName="Setpoint0"
QGCParamID="ELE_DOWN_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/ElevatorInput/"
SimulinkParameterName="Setpoint1"
QGCParamID="ELE_CENTER_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/ElevatorInput/"
SimulinkParameterName="Setpoint2"
QGCParamID="ELE_UP_IN"
/>
<!-- Settings for Throttle Servo -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/ThrottleInput/"
SimulinkParameterName="Setpoint0"
QGCParamID="THR_SET0_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/ThrottleInput/"
SimulinkParameterName="Setpoint1"
QGCParamID="THR_SET1_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/ThrottleInput/"
SimulinkParameterName="Setpoint2"
QGCParamID="THR_SET2_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/ThrottleInput/"
SimulinkParameterName="Setpoint3"
QGCParamID="THR_SET3_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/ThrottleInput/"
SimulinkParameterName="Setpoint4"
QGCParamID="THR_SET4_IN"
/>
<!-- Settings for Rudder Servo -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/RudderInput/"
SimulinkParameterName="Setpoint0"
QGCParamID="RUD_LEFT_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/RudderInput/"
SimulinkParameterName="Setpoint1"
QGCParamID="RUD_CENTER_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/RudderInput/"
SimulinkParameterName="Setpoint2"
QGCParamID="RUD_RIGHT_IN"
/>
<!-- Settings for Gyro Mode/Gain Switch -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/GyroInput/"
SimulinkParameterName="Setpoint0"
QGCParamID="GYRO_DEF_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/GyroInput/"
SimulinkParameterName="Setpoint1"
QGCParamID="GYRO_TOG_IN"
/>
<!-- Settings for Pitch Servo -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/PitchInput/"
SimulinkParameterName="Setpoint0"
QGCParamID="PIT_SET0_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/PitchInput/"
SimulinkParameterName="Setpoint1"
QGCParamID="PIT_SET1_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/PitchInput/"
SimulinkParameterName="Setpoint2"
QGCParamID="PIT_SET2_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/PitchInput/"
SimulinkParameterName="Setpoint3"
QGCParamID="PIT_SET3_IN"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Pilot_Inputs/PitchInput/"
SimulinkParameterName="Setpoint4"
QGCParamID="PIT_SET4_IN"
/>
</Block>
<!-- Parameters for the servo output block -->
<Block name="ServoOutputs">
<!-- Settings for Aileron Servo -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Servo_Outputs/AileronOutput/"
SimulinkParameterName="Setpoint0"
QGCParamID="AIL_LEFT_OUT"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Servo_Outputs/AileronOutput/"
SimulinkParameterName="Setpoint1"
QGCParamID="AIL_CENTER_OUT"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Servo_Outputs/AileronOutput/"
SimulinkParameterName="Setpoint2"
QGCParamID="AIL_RIGHT_OUT"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Servo_Outputs/AileronMix/Controller_Mix/"
SimulinkParameterName="Value"
QGCParamID="MIX_AIL"
/>
<!-- Settings for Elevator Servo -->
<Parameter
SimulinkPath="avionics_src/sm_avionics/Servo_Outputs/ElevatorOutput/"
SimulinkParameterName="Setpoint0"
QGCParamID="ELE_DOWN_OUT"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Servo_Outputs/ElevatorOutput/"
SimulinkParameterName="Setpoint1"
QGCParamID="ELE_CENTER_OUT"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Servo_Outputs/ElevatorOutput/"
SimulinkParameterName="Setpoint2"
QGCParamID="ELE_UP_OUT"
/>
<Parameter
SimulinkPath="avionics_src/sm_avionics/Servo_Outputs/ElevatorMix/Controller_Mix/"
SimulinkParameterName="Value"
QGCParamID="MIX_ELE"
/>
</Block>
</ParameterList>
[rgb]
principal_point\x=314.70228964
principal_point\y=264.30478827
focal_length\x=527.91246131
focal_length\y=527.91246131
distortion\k1=0.20496745
distortion\k2=-0.36341243
distortion\k3=0.00000000
distortion\k4=0.00000000
distortion\k5=0.00000000
[depth]
principal_point\x=311.88621344
principal_point\y=247.63447078
focal_length\x=593.89813561
focal_length\y=593.89813561
distortion\k1=0.00000000
distortion\k2=0.00000000
distortion\k3=0.00000000
distortion\k4=0.00000000
distortion\k5=0.00000000
[transform]
R11=0.999982
R12=0.000556
R13=0.005927
R21=-0.000563
R22=0.999999
R23=0.001235
R31=-0.005926
R32=-0.001239
R33=0.999982
Tx=-0.024287
Ty=0.001018
Tz=-0.015195
baseline=0.06061
disparity_offset=1092.3403
qgroundcontrol (2.4-0ubuntu1) trusty; urgency=low
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
-- Daniel Agar <daniel@agar.ca> Sat, 04 Apr 2015 17:14:10 -0400
Source: qgroundcontrol
Section: electronics
Priority: optional
Maintainer: Daniel Agar <daniel@agar.ca>
Build-Depends: debhelper (>= 9), qt54tools, qt54base, qt54declarative, qt54serialport, qt54svg, qt54webkit, qt54quickcontrols, qt54xmlpatterns, qt54x11extras, qt54websockets, qt54sensors, qt54script, qt54quick1, qt54qbs, qt54multimedia, qt54location, qt54imageformats, qt54graphicaleffects, qt54creator, qt54connectivity, libsdl1.2-dev, libudev-dev
Standards-Version: 3.9.5
Homepage: https://github.com/mavlink/qgroundcontrol
Vcs-Git: git://github.com/mavlink/qgroundcontrol.git
#Vcs-Browser: http://git.debian.org/?p=collab-maint/qgroundcontrol.git;a=summary
Package: qgroundcontrol
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, qt54tools, qt54base, qt54declarative, qt54serialport, qt54svg, qt54webkit, qt54quickcontrols, qt54xmlpatterns, qt54x11extras, qt54websockets, qt54sensors, qt54script, qt54quick1, qt54multimedia, qt54location, qt54imageformats, qt54graphicaleffects, qt54connectivity
Description: Open Source Micro Air Vehicle Ground Control Station
<insert long description, indented with spaces>
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: qgroundcontrol
Source: https://github.com/mavlink/qgroundcontrol
Files: *
Copyright: QGroundControl Developers https://github.com/mavlink/qgroundcontrol/graphs/contributors
License: GPL-3+
?package(qgroundcontrol):needs="x11" \
section="Applications/Electronics" \
title="QGroundControl" \
command="/usr/bin/qgroundcontrol"
qgroundcontrol.desktop usr/share/applications
release/qgroundcontrol usr/bin
resources/ usr/share/qgroundcontrol
resources/icons/qgroundcontrol.png usr/share/pixmaps
#!/usr/bin/make -f
# -*- makefile -*-
export QT_SELECT := qt5
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
%:
dh $@
override_dh_auto_configure:
/opt/qt54/bin/qmake qgroundcontrol.pro
tar-ignore = ".git/*"
version=3
https://github.com/mavlink/qgroundcontrol/tags .*/archive/[a-z](\d\S*)\.tar\.gz
......@@ -14,9 +14,11 @@ LicenseData license.txt
Section
SetOutPath $INSTDIR
File /r release\*.*
File deploy\px4driver.msi
WriteUninstaller $INSTDIR\QGroundControl_uninstall.exe
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\QGroundControl" "DisplayName" "QGroundControl"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\QGroundControl" "UninstallString" "$\"$INSTDIR\QGroundControl_uninstall.exe$\""
ExecWait '"msiexec" /i "px4driver.msi"'
SectionEnd
Section "Uninstall"
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.