summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore11
-rw-r--r--AUTHORS2
-rw-r--r--LICENSE502
-rw-r--r--Makefile78
-rw-r--r--doc/MTS_IO_Documentation.doxyfile1679
-rwxr-xr-xdoc/resource/MTS_IO_DoxygenMain.h28
-rw-r--r--doc/resource/mts_logo.jpegbin0 -> 1622 bytes
-rw-r--r--include/mts/MTS_IO_CE910Radio.h56
-rw-r--r--include/mts/MTS_IO_CdmaRadio.h92
-rw-r--r--include/mts/MTS_IO_CellularRadio.h433
-rw-r--r--include/mts/MTS_IO_CellularRadioFactory.h76
-rw-r--r--include/mts/MTS_IO_Connection.h113
-rw-r--r--include/mts/MTS_IO_DE910Radio.h55
-rw-r--r--include/mts/MTS_IO_GE910Radio.h57
-rw-r--r--include/mts/MTS_IO_HE910DRadio.h56
-rw-r--r--include/mts/MTS_IO_HE910EUDRadio.h55
-rw-r--r--include/mts/MTS_IO_HE910Radio.h52
-rw-r--r--include/mts/MTS_IO_LE910EUGRadio.h53
-rw-r--r--include/mts/MTS_IO_LE910NAGRadio.h55
-rw-r--r--include/mts/MTS_IO_LE910Radio.h57
-rw-r--r--include/mts/MTS_IO_LE910SVGRadio.h55
-rw-r--r--include/mts/MTS_IO_LockFile.h59
-rw-r--r--include/mts/MTS_IO_MccMncTable.h62
-rw-r--r--include/mts/MTS_IO_SerialConnection.h181
-rw-r--r--scripts/create-mcc-mnc-table.py106
-rw-r--r--src/MTS_IO_CE910Radio.cpp42
-rw-r--r--src/MTS_IO_CdmaRadio.cpp1297
-rw-r--r--src/MTS_IO_CellularRadio.cpp1522
-rw-r--r--src/MTS_IO_CellularRadioFactory.cpp145
-rw-r--r--src/MTS_IO_Connection.cpp155
-rw-r--r--src/MTS_IO_DE910Radio.cpp41
-rw-r--r--src/MTS_IO_GE910Radio.cpp41
-rw-r--r--src/MTS_IO_HE910DRadio.cpp41
-rw-r--r--src/MTS_IO_HE910EUDRadio.cpp42
-rw-r--r--src/MTS_IO_HE910Radio.cpp40
-rw-r--r--src/MTS_IO_LE910EUGRadio.cpp41
-rw-r--r--src/MTS_IO_LE910NAGRadio.cpp45
-rw-r--r--src/MTS_IO_LE910Radio.cpp39
-rw-r--r--src/MTS_IO_LE910SVGRadio.cpp45
-rw-r--r--src/MTS_IO_LockFile.cpp109
-rw-r--r--src/MTS_IO_MccMncTable.cpp1723
-rw-r--r--src/MTS_IO_SerialConnection.cpp545
-rw-r--r--test/CMakeLists.txt9
-rw-r--r--test/TestRunnerClient.cpp566
-rw-r--r--test/TestRunnerClient.h147
-rw-r--r--version1
46 files changed, 10609 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1369c23
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+Debug/
+CppUnitTest/
+doc/html
+doc/latex
+doc/doxygen.log
+.settings
+*.xml
+*.o
+*.d
+libmts_io.a
+libmts_io.so*
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..7c6e7d1
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Sean Godinez <sgodinez@multitech.com>
+Jason Reiss <jreiss@multitech.com>
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a52c60b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,78 @@
+include version
+
+includedir ?= /usr/include
+libdir ?= /usr/lib
+
+OBJS += \
+MTS_IO_CdmaRadio.o \
+MTS_IO_CE910Radio.o \
+MTS_IO_CellularRadio.o \
+MTS_IO_CellularRadioFactory.o \
+MTS_IO_Connection.o \
+MTS_IO_DE910Radio.o \
+MTS_IO_GE910Radio.o \
+MTS_IO_HE910Radio.o \
+MTS_IO_HE910DRadio.o \
+MTS_IO_HE910EUDRadio.o \
+MTS_IO_LE910Radio.o \
+MTS_IO_LE910NAGRadio.o \
+MTS_IO_LE910SVGRadio.o \
+MTS_IO_LE910EUGRadio.o \
+MTS_IO_LockFile.o \
+MTS_IO_MccMncTable.o \
+MTS_IO_SerialConnection.o
+
+CPP_DEPS += \
+MTS_IO_CdmaRadio.d \
+MTS_IO_CE910Radio.d \
+MTS_IO_CellularRadio.d \
+MTS_IO_CellularRadioFactory.d \
+MTS_IO_Connection.d \
+MTS_IO_DE910Radio.d \
+MTS_IO_GE910Radio.d \
+MTS_IO_HE910Radio.d \
+MTS_IO_HE910DRadio.d \
+MTS_IO_HE910EUDRadio.d \
+MTS_IO_LE910Radio.d \
+MTS_IO_LE910NAGRadio.d \
+MTS_IO_LE910SVGRadio.d \
+MTS_IO_LE910EUGRadio.d \
+MTS_IO_LockFile.d \
+MTS_IO_MccMncTable.d \
+MTS_IO_SerialConnection.d
+
+all: libmts_io.a libmts_io.so.0
+
+libmts_io.a: $(OBJS)
+ @echo 'Building target: $@'
+ $(AR) -r libmts_io.a $(OBJS)
+ @echo 'Finished building target: $@'
+ @echo ' '
+
+libmts_io.so.0: $(OBJS)
+ @echo 'Building target: $@'
+ $(CXX) -shared -Wl,-soname,$@ -o libmts_io.so.$(VERSION) $(OBJS)
+ @echo 'Finished building target: $@'
+ @echo ' '
+
+%.o: src/%.cpp
+ @echo 'Building file: $<'
+ $(CXX) $(CFLAGS) -I=$(includedir)/jsoncpp -Iinclude -Wall -Werror -c -fPIC -fmessage-length=0 -std=c++0x -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
+ @echo 'Finished building: $<'
+ @echo ' '
+
+install:
+ mkdir -p $(DESTDIR)$(libdir)
+ mkdir -p $(DESTDIR)$(includedir)/mts
+ install -m 0644 libmts_io.a libmts_io.so.$(VERSION) $(DESTDIR)$(libdir)/
+ ln -sf libmts_io.so.$(VERSION) $(DESTDIR)$(libdir)/libmts_io.so.0
+ ln -sf libmts_io.so.0 $(DESTDIR)$(libdir)/libmts_io.so
+ install -m 0644 include/mts/* $(DESTDIR)$(includedir)/mts/
+
+clean:
+ -$(RM) $(OBJS) $(CPP_DEPS) libmts_io.a libmts_io.so*
+ -@echo ' '
+
+.PHONY: all clean dependents install
+.SECONDARY:
+
diff --git a/doc/MTS_IO_Documentation.doxyfile b/doc/MTS_IO_Documentation.doxyfile
new file mode 100644
index 0000000..59aca39
--- /dev/null
+++ b/doc/MTS_IO_Documentation.doxyfile
@@ -0,0 +1,1679 @@
+# Doxyfile 1.7.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "MTS IO C++ Library Documentation "
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 0.1
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "An IO Library"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO = mts_logo.jpeg
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even if there is only one candidate or it is obvious which candidate to choose by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST = YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE = doxygen.log
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = resource ../include ../../mts/include
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the stylesheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [0,1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+# Note that a value of 0 will completely suppress the enum values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = YES
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will write a font called Helvetica to the output
+# directory and reference it in all dot files that doxygen generates.
+# When you want a differently looking font you can specify the font name
+# using DOT_FONTNAME. You need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, svg, gif or svg.
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/doc/resource/MTS_IO_DoxygenMain.h b/doc/resource/MTS_IO_DoxygenMain.h
new file mode 100755
index 0000000..83f9c7f
--- /dev/null
+++ b/doc/resource/MTS_IO_DoxygenMain.h
@@ -0,0 +1,28 @@
+/*!
+ \file MTS_IO_DoxygenMain.h
+ \brief Header for MTS IO Library Code Documentation.
+ \date 2012-12-13
+ \author Sean Godinez
+
+ Details.
+ */
+
+#ifndef MTS_IO_DOXYGENMAIN_H_
+#define MTS_IO_DOXYGENMAIN_H_
+
+
+/** @mainpage Welcome to the Multi-Tech Systems MTS IO Library Documentation Site
+*
+* @authors MTS Software Developers
+*
+* @section intro Introduction
+* @todo Provide an introduction describing the MTS IO library,
+* build configuration, and unit testing.
+*
+* @todo Document MTS IO Libraries
+*
+* <hr>
+* Website: <A HREF="http://www.multitech.com"> Multi-Tech Systems </A>
+*/
+
+#endif /* MTR_DOXYGENMAIN_H_ */
diff --git a/doc/resource/mts_logo.jpeg b/doc/resource/mts_logo.jpeg
new file mode 100644
index 0000000..3bae16d
--- /dev/null
+++ b/doc/resource/mts_logo.jpeg
Binary files differ
diff --git a/include/mts/MTS_IO_CE910Radio.h b/include/mts/MTS_IO_CE910Radio.h
new file mode 100644
index 0000000..9719c7a
--- /dev/null
+++ b/include/mts/MTS_IO_CE910Radio.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_CE910Radio.h
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_CE910RADIO_H_
+#define MTS_IO_CE910RADIO_H_
+
+#include <mts/MTS_IO_CdmaRadio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class CE910Radio : public CdmaRadio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ CE910Radio(const std::string& sPort);
+ virtual ~CE910Radio(){};
+
+ protected:
+
+ private:
+
+ };
+ }
+}
+
+
+
+
+#endif /* MTS_IO_CE910RADIO_H_ */
diff --git a/include/mts/MTS_IO_CdmaRadio.h b/include/mts/MTS_IO_CdmaRadio.h
new file mode 100644
index 0000000..146034b
--- /dev/null
+++ b/include/mts/MTS_IO_CdmaRadio.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_CdmaRadio.h
+ \brief A brief description
+ \date Nov 19, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_CDMARADIO_H_
+#define MTS_IO_CDMARADIO_H_
+
+#include <mts/MTS_IO_CellularRadio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class CdmaRadio : public CellularRadio {
+
+ public:
+ virtual ~CdmaRadio();
+
+ virtual CODE getHardware(std::string& sHardware);
+ virtual CODE getMdn(std::string& sMdn);
+ virtual CODE getImei(std::string& sImei);
+ virtual CODE getMeid(std::string& sMeid);
+ virtual CODE getMsid(std::string& sMsid);
+ virtual CODE getCarrier(std::string& sCarrier);
+ virtual CODE getNetwork(std::string& sNetwork);
+ virtual CODE getSimStatus(std::string& sSimStatus);
+ virtual CODE getIccid(std::string& sIccid);
+ virtual CODE getLac(std::string& sLac);
+ virtual CODE getService(std::string& sService);
+
+ virtual CODE validateMsl(const Json::Value& jArgs);
+ virtual CODE setMdn(const Json::Value& jArgs);
+ virtual CODE setMsid(const Json::Value& jArgs);
+
+ virtual CODE getMipProfile(Json::Value& jMipProfile);
+ virtual CODE setMipActiveProfile(const Json::Value& jArgs);
+ virtual CODE setMipNai(const Json::Value& jArgs);
+ virtual CODE setMipHomeIp(const Json::Value& jArgs);
+ virtual CODE setMipPrimaryHa(const Json::Value& jArgs);
+ virtual CODE setMipSecondaryHa(const Json::Value& jArgs);
+ virtual CODE setMipMnAaaSpi(const Json::Value& jArgs);
+ virtual CODE setMipMnHaSpi(const Json::Value& jArgs);
+ virtual CODE setMipRevTun(const Json::Value& jArgs);
+ virtual CODE setMipMnAaaSs(const Json::Value& jArgs);
+ virtual CODE setMipMnHaSs(const Json::Value& jArgs);
+
+ virtual CODE updateDc(const Json::Value& jArgs, UpdateCb& stepCb);
+ virtual CODE updatePrl(const Json::Value& jArgs, UpdateCb& stepCb);
+ virtual CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb);
+ virtual CODE resetHfa(const Json::Value& jArgs, UpdateCb& stepCb);
+ virtual CODE activate(const Json::Value& jArgs, UpdateCb& stepCb);
+
+ virtual CODE getNetworkStatus(Json::Value& jData);
+
+ protected:
+ CdmaRadio(const std::string& sName, const std::string& sRadioPort);
+
+ std::string getMeidLastSix();
+
+ private:
+ std::string m_sCarrier;
+ };
+ }
+}
+
+
+
+
+#endif /* MTS_IO_CDMARADIO_H_ */
diff --git a/include/mts/MTS_IO_CellularRadio.h b/include/mts/MTS_IO_CellularRadio.h
new file mode 100644
index 0000000..b253c80
--- /dev/null
+++ b/include/mts/MTS_IO_CellularRadio.h
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_CellularRadio.h
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_CELLULARRADIO_H_
+#define MTS_IO_CELLULARRADIO_H_
+
+#include <mts/MTS_IO_SerialConnection.h>
+#include <mts/MTS_NonCopyable.h>
+#include <mts/MTS_AutoPtr.h>
+#include <mts/MTS_Lock.h>
+#include <mts/MTS_Stdint.h>
+#include <json/json.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+namespace MTS {
+ namespace IO {
+
+ class CellularRadio : NonCopyable {
+
+ public:
+ static const std::string DEFAULT_RADIO_PORT;
+ static const std::string DEFAULT_RADIO_DIR;
+
+ static const std::string VALUE_UNKNOWN;
+ static const std::string VALUE_UNAVAILABLE;
+ static const std::string VALUE_NOT_SUPPORTED;
+
+ //Special Payload Characters
+ static const char ETX; //Ends socket connection
+ static const char DLE; //Escapes ETX and DLE within Payload
+ static const char CR;
+ static const char NL;
+ static const char CTRL_Z;
+
+ static const std::string RSP_OK;
+ static const std::string RSP_ERROR;
+
+ //Registration Values
+ enum REGISTRATION : uint8_t {
+ NOT_REGISTERED = 0,
+ REGISTERED = 1,
+ SEARCHING=2,
+ DENIED=3,
+ UNKNOWN=4,
+ ROAMING=5
+ };
+
+ enum SERVICEDOMAIN : uint8_t {
+ NO_SERVICE = 0,
+ CS_ONLY = 1,
+ PS_ONLY = 2,
+ CSPS = 3
+ };
+
+ enum ACTIVEBAND : uint8_t {
+ GSM_850 = 0,
+ GSM_900 = 1,
+ DCS_1800 = 2,
+ PCS_1900 = 3
+ };
+
+ enum CODE : uint8_t {
+ SUCCESS = 0,
+ ERROR,
+ FAILURE,
+ NO_RESPONSE,
+ NOT_APPLICABLE,
+ INVALID_ARGS
+ };
+
+ enum SIMSTATUS : uint8_t {
+ READY = 0,
+ LOCKED,
+ BLOCKED,
+ NOT_INSERTED
+ };
+
+ static const std::string VALUE_NOT_REGISTERED;
+ static const std::string VALUE_REGISTERED;
+ static const std::string VALUE_SEARCHING;
+ static const std::string VALUE_DENIED;
+ static const std::string VALUE_ROAMING;
+
+ //Static Data
+ static const std::string KEY_TYPE; //!< GSM or CDMA
+ static const std::string KEY_CODE; //!< Product Code : H5, H6, C2, EV3, G3
+ static const std::string KEY_MODEL; //!< Model : HE910, CE910, DE910, GE910
+ static const std::string KEY_MANUFACTURER; //!< Manufacturer: Telit
+ static const std::string KEY_HARDWARE; //!< Radio Hardware Version
+ static const std::string KEY_FIRMWARE; //!< Radio Firmware Version
+ static const std::string KEY_IMEI; //!< International Mobile Station Equipment Identity
+ static const std::string KEY_MEID; //!< Mobile Equipment Identifier
+ static const std::string KEY_IMSI; //!< International Mobile Subscriber Identity
+ static const std::string KEY_MSID; //!< Mobil Station ID (MSID) aka MIN aka MSIN aka Last few digits of IMSI
+ static const std::string KEY_MDN; //!< Mobile Directory Number : Actual phone number dialed to reach radio
+ static const std::string KEY_CARRIER; //!< Cellular Service Provider (Home Network)
+ static const std::string KEY_ICCID; //!< Integrated Circuit Card Identifier
+ static const std::string KEY_MSL; //!< Master Subsidy Lock
+
+
+ //Network Status Data
+ static const std::string KEY_ROAMING; //!< Indicates whether or not using Home Network
+ static const std::string KEY_DATETIME; //!< Date and Time from tower
+ static const std::string KEY_SERVICE; //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO]
+ static const std::string KEY_NETWORK; //!< Cellular Service Provider
+ static const std::string KEY_CID; //!< Cellular ID (Tower) in HEX
+ static const std::string KEY_LAC; //!< Location Area Code in HEX
+ static const std::string KEY_RAC; //!< Routing Area Code in HEX
+ static const std::string KEY_RSSI; //!< Received Signal Strength Indication
+ static const std::string KEY_RSSIDBM; //!< Received Signal Strength Indication in dBm
+ static const std::string KEY_MCC; //!< Mobile Country Code
+ static const std::string KEY_MNC; //!< Mobile Network (Operator) Code
+ static const std::string KEY_CHANNEL; //!< ARFCN or UARFCN Assigned Radio Channel
+ static const std::string KEY_TXPWR; //!< Transmit Power
+ static const std::string KEY_PSC; //!< Active Primary Synchronization Code (PSC)
+ static const std::string KEY_ECIO; //!< Active Ec/Io (chip energy per total wideband power in dBm)
+ static const std::string KEY_RSCP; //!< Active RSCP (Received Signal Code Power in dBm)
+ static const std::string KEY_DRX; //!< Discontinuous reception cycle length (ms)
+ static const std::string KEY_MM; //!< Mobility Management State
+ static const std::string KEY_RR; //!< Radio Resource State
+ static const std::string KEY_NOM; //!< Network Operator Mode
+ static const std::string KEY_ABND; //!< Active Band
+ static const std::string KEY_BLER; //!< Block Error Rate (percentage)
+ static const std::string KEY_SD; //!< Service Domain
+ static const std::string KEY_DEBUG; //!< Debug Information
+
+ static const std::string KEY_MIP; //!< Mobile IP Information
+ static const std::string KEY_MIP_ID; //!< MIP Profile ID
+ static const std::string KEY_MIP_ENABLED; //!< MIP Profile Enabled/Disabled
+ static const std::string KEY_MIP_NAI; //!< Network Access Identifier
+ static const std::string KEY_MIP_HOMEADDRESS; //!< Home Address
+ static const std::string KEY_MIP_PRIMARYHA; //!< Primary Home Agent
+ static const std::string KEY_MIP_SECONDARYHA; //!< Secondary Home Agent
+ static const std::string KEY_MIP_MNAAASPI; //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index
+ static const std::string KEY_MIP_MNHASPI; //!< Mobile Node Home Agent Security Server Parameter Index
+ static const std::string KEY_MIP_REVTUN; //!< Reverse Tunneling Enabled
+ static const std::string KEY_MIP_MNAAASS; //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret
+ static const std::string KEY_MIP_MNHASS; //!< Mobile Node Home Agent Shared Secret
+
+
+ //Values - Type
+ static const std::string VALUE_TYPE_LTE;
+ static const std::string VALUE_TYPE_GSM;
+ static const std::string VALUE_TYPE_CDMA;
+
+ //Values - Carrier
+ static const std::string VALUE_CARRIER_VERIZON;
+ static const std::string VALUE_CARRIER_AERIS;
+ static const std::string VALUE_CARRIER_SPRINT;
+ static const std::string VALUE_CARRIER_ATT;
+ static const std::string VALUE_CARRIER_TMOBILE;
+
+ static const std::string VALUE_SD_NO_SERVICE;
+ static const std::string VALUE_SD_CS_ONLY;
+ static const std::string VALUE_SD_PS_ONLY;
+ static const std::string VALUE_SD_CSPS;
+
+ static const std::string VALUE_ABND_GSM_850;
+ static const std::string VALUE_ABND_GSM_900;
+ static const std::string VALUE_ABND_DCS_1800;
+ static const std::string VALUE_ABND_PCS_1900;
+
+ static const std::vector<std::string> DEFAULT_BAIL_STRINGS;
+
+ typedef std::function<bool(const std::string&/*iterationData*/, const std::string&/*allData*/)> IsNeedMoreData;
+ typedef std::function<void(const Json::Value&)> UpdateCb;
+
+ virtual ~CellularRadio();
+
+ virtual bool initialize(uint32_t iTimeoutMillis = 5000);
+ virtual bool resetRadio(uint32_t iTimeoutMillis = 5000);
+ virtual bool resetConnection(uint32_t iTimeoutMillis = 5000);
+ virtual void shutdown();
+
+ const std::string& getName() const;
+
+ virtual CODE getModel(std::string& sModel);
+ static CODE convertModelToType(const std::string& sModel, std::string& sType);
+ static CODE convertModelToMtsShortCode(const std::string& sModel, std::string& sCode);
+ static CODE convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd);
+ static CODE convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand);
+
+ virtual CODE getFirmware(std::string& sFirmware);
+ virtual CODE getHardware(std::string& sHardware);
+ virtual CODE getManufacturer(std::string& sManufacturer);
+ virtual CODE getImei(std::string& sImei);
+ virtual CODE getMeid(std::string& sMeid);
+ virtual CODE getImsi(std::string& sImsi);
+ virtual CODE getSimStatus(std::string& sSimStatus);
+ virtual CODE getIccid(std::string& sIccid);
+ virtual CODE getService(std::string& sService);
+ virtual CODE getLac(std::string& sLac);
+ virtual CODE getMdn(std::string& sMdn);
+ virtual CODE getMsid(std::string& sMsid);
+ virtual CODE getType(std::string& sType);
+ virtual CODE getCarrier(std::string& sCarrier);
+ virtual CODE getNetwork(std::string& sNetwork);
+ virtual CODE getTower(std::string& sTower);
+ virtual CODE getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone);
+ virtual CODE getRoaming(bool& bRoaming);
+
+ virtual CODE getSignalStrength(int32_t& iRssi);
+ virtual CODE convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& dBm);
+ virtual CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi);
+
+ virtual CODE getRegistration(REGISTRATION& eRegistration);
+ virtual CODE convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration);
+
+ //! Gather details of the radio's Mobile IP Profile
+ /*!
+ \param Json::Value object that will be populated with MIP data
+ \return Returns result code of gathering MIP
+ */
+ virtual CODE getMipProfile(Json::Value& jMipProfile);
+
+ /*
+ * jArgs = {
+ * "msl" : "Master Subsidy Lock (Aeris, Sprint): STRING"
+ * }
+ */
+ virtual CODE validateMsl(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "mdn" : "Mobile Directory Number : STRING",
+ * "msl" : "[OPTIONAL] Master Subsidy Lock (Aeris, Sprint): STRING"
+ * }
+ */
+ virtual CODE setMdn(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "msid" : "Mobil Station ID (MSID) aka MIN aka MSIN : STRING",
+ * "msl" : "[OPTIONAL] Master Subsidy Lock (Aeris, Sprint): STRING"
+ * }
+ */
+ virtual CODE setMsid(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "activeProfile" : "Set active profile: STRING"
+ * }
+ */
+ virtual CODE setMipActiveProfile(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "nai" : "Network Access Identifier : STRING"
+ * }
+ */
+ virtual CODE setMipNai(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "homeIp" : "Home Address : STRING"
+ * }
+ */
+ virtual CODE setMipHomeIp(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "primaryHa" : "Primary Home Agent : STRING"
+ * }
+ */
+ virtual CODE setMipPrimaryHa(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "secondaryHa" : "Secondary Home Agent : STRING"
+ * }
+ */
+ virtual CODE setMipSecondaryHa(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "mnAaaSpi" : "Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index : STRING"
+ * }
+ */
+ virtual CODE setMipMnAaaSpi(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "mnHaSpi" : "Mobile Node Home Agent Security Server Parameter Index : STRING"
+ * }
+ */
+ virtual CODE setMipMnHaSpi(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "revTun" : "[DESCRIPTION] : STRING"
+ * }
+ */
+ virtual CODE setMipRevTun(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "mnAaaSs" : "Mobile Node Authentication, Authorization, and Accounting Server Shared Secret : STRING"
+ * }
+ */
+ virtual CODE setMipMnAaaSs(const Json::Value& jArgs);
+
+ /*
+ * jArgs = {
+ * "mnHaSs" : "Mobile Node Home Agent Shared Secret : STRING"
+ * }
+ */
+ virtual CODE setMipMnHaSs(const Json::Value& jArgs);
+
+ /*
+ * jArgs = null
+ */
+ virtual CODE updateDc(const Json::Value& jArgs, UpdateCb& stepCb);
+
+ /*
+ * jArgs = null
+ */
+ virtual CODE updatePrl(const Json::Value& jArgs, UpdateCb& stepCb);
+
+ /*
+ * jArgs = null
+ */
+ virtual CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb);
+
+ /*
+ * jArgs = {
+ * "msl" : "Master Subsidy Lock (Sprint): STRING"
+ * }
+ */
+ virtual CODE resetHfa(const Json::Value& jArgs, UpdateCb& stepCb);
+
+ /*
+ * jArgs = {
+ * "mdn" : "Mobile Directory Number (Aeris): STRING"
+ * "msid" : "Mobile Station ID (Aeris): STRING"
+ * }
+ */
+ virtual CODE activate(const Json::Value& jArgs, UpdateCb& stepCb);
+
+ virtual CODE getEcho(bool& bEnabled);
+ virtual CODE setEcho(bool bEnabled = true);
+
+ virtual CODE getStaticInformation(Json::Value& jData);
+ virtual CODE getNetworkStatus(Json::Value& jData);
+
+ virtual CODE sendBasicCommand(const std::string& sCmd, int32_t timeoutMillis = 100, const char& ESC = CR);
+
+ virtual std::string sendCommand(const std::string& sCmd,
+ const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS,
+ int32_t timeoutMillis = 100,
+ const char& ESC = CR);
+
+
+ static std::string sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo,
+ const std::string& sCmd,
+ const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS,
+ int32_t timeoutMillis = 100,
+ const char& ESC = CR);
+
+ virtual std::string sendCommand(const std::string& sCmd,
+ IsNeedMoreData& isNeedMoreData,
+ int32_t timeoutMillis = 100,
+ const char& ESC = CR);
+
+ static std::string sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo,
+ const std::string& sCmd,
+ IsNeedMoreData& isNeedMoreData,
+ int32_t timeoutMillis = 100,
+ const char& ESC = CR);
+
+ static CODE test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds = 30);
+
+ static std::string extractModelFromResult(const std::string& sResult);
+ static std::string getCodeAsString(CODE code);
+
+ protected:
+
+ CellularRadio(const std::string& sName, const std::string& sRadioPort);
+
+ virtual bool getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier);
+ virtual bool getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware);
+
+ virtual void getCommonNetworkStats(Json::Value& jData);
+
+ void initMipProfile(Json::Value& jData);
+
+ bool splitAndAssign(const std::string& sLine, const std::string& sKey, Json::Value& jParent, const std::string& sJsonKey, Json::ValueType eType = Json::ValueType::stringValue);
+
+
+
+ private:
+ std::string m_sName;
+ std::string m_sRadioPort;
+ std::string m_sFirmware;
+ std::string m_sCarrier;
+ MTS::AutoPtr<MTS::IO::Connection> m_apIo;
+
+ bool m_bEchoEnabled;
+ bool m_bEnableEchoOnClose;
+
+ };
+ }
+}
+
+
+
+#endif /* MTS_IO_CELLULARRADIO_H_ */
diff --git a/include/mts/MTS_IO_CellularRadioFactory.h b/include/mts/MTS_IO_CellularRadioFactory.h
new file mode 100644
index 0000000..5fa44d7
--- /dev/null
+++ b/include/mts/MTS_IO_CellularRadioFactory.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_CellularRadioFactory.h
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_CELLULARRADIOFACTORY_H_
+#define MTS_IO_CELLULARRADIOFACTORY_H_
+
+#include <mts/MTS_IO_CellularRadio.h>
+#include <string>
+#include <map>
+
+namespace MTS {
+ namespace IO {
+
+ class HE910Radio;
+ class GE910Radio;
+ class DE910Radio;
+ class CE910Radio;
+ class CellularRadioFactory {
+
+ public:
+
+ CellularRadioFactory();
+ virtual ~CellularRadioFactory() {};
+
+ virtual CellularRadio* create(const std::string& sModel, const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+
+ virtual CellularRadio* createHE910D(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+ virtual CellularRadio* createHE910EUD(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+ virtual CellularRadio* createLE910NAG(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+ virtual CellularRadio* createLE910SVG(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+ virtual CellularRadio* createLE910EUG(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+ virtual CellularRadio* createGE910(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+ virtual CellularRadio* createDE910(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+ virtual CellularRadio* createCE910(const std::string& sPort = CellularRadio::DEFAULT_RADIO_PORT);
+
+ protected:
+ typedef MTS::IO::CellularRadio* (CellularRadioFactory::*CREATEFUNCPTR)(const std::string& sPort);
+ std::map< std::string, CREATEFUNCPTR > m_mCreationMap;
+
+ virtual std::string identifyRadio(const std::string& sPort);
+
+ private:
+
+
+ };
+ }
+}
+
+
+
+#endif /* MTS_IO_CELLULARRADIOFACTORY_H_ */
diff --git a/include/mts/MTS_IO_Connection.h b/include/mts/MTS_IO_Connection.h
new file mode 100644
index 0000000..bd4b32f
--- /dev/null
+++ b/include/mts/MTS_IO_Connection.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_Connection.h
+ \brief A brief description
+ \date Jan 15, 2013
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#ifndef MTS_IO_CONNECTION_H_
+#define MTS_IO_CONNECTION_H_
+
+#include <mts/MTS_AutoPtr.h>
+#include <mts/MTS_Lock.h>
+#include <mts/MTS_NonCopyable.h>
+#include <string>
+
+namespace MTS {
+
+ class Buffer;
+
+ namespace IO {
+ class Connection : public MTS::NonCopyable {
+
+ private:
+ static int32_t BLOCKING;
+
+ public:
+
+ virtual ~Connection();
+
+ const std::string& getName() const;
+
+ bool open(const int32_t& timeoutMillis = 1000);
+ void close();
+ bool isClosed() const;
+
+ void setCloseable(bool bCloseable);
+ bool isCloseable() const;
+
+ int read(char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis = BLOCKING);
+ int read(std::string& sBuffer, const uint32_t& iSize, int32_t& timeoutMillis = BLOCKING);
+ int read(Buffer& oBuffer, const uint32_t& iSize, int32_t& timeoutMillis = BLOCKING);
+
+ int write(const char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis = BLOCKING);
+ int write(const std::string& sBuffer, const uint32_t& iSize, int32_t& timeoutMillis = BLOCKING);
+ int write(const Buffer& oBuffer, const uint32_t& iSize, int32_t& timeoutMillis = BLOCKING);
+
+
+
+ protected:
+ explicit Connection(const std::string& sName);
+
+ private:
+ const std::string m_sName;
+ bool m_bClosed;
+ bool m_bCloseable;
+ AutoPtr<Lock> m_apLock;
+ AutoPtr<Lock> m_apReadLock;
+ AutoPtr<Lock> m_apWriteLock;
+
+ /*! Opens the connection
+ * \return true if the connection has been opened, false otherwise
+ */
+ virtual bool doOpen(const int32_t& timeoutMillis) = 0;
+
+ /*! Closes the connection
+ */
+ virtual void doClose() = 0;
+
+ /*! Perform read from connection
+ * \param pBuffer the buffer allocated for read bytes
+ * \param iSize the number of bytes to be read. the size allocated for pBuffer must be greater or equal to iSize
+ * \param timeoutMillis the amount of time to attempt to read iSize bytes. less than zero will block until iSize bytes has been read
+ * \return the number of bytes read. -1 for error
+ */
+ virtual int doRead(char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis) = 0;
+
+ /*! Perform write to connection
+ * \param pBuffer the buffer that contains the data to be written
+ * \param iSize the number of bytes to be written
+ * \param timeoutMillis the amount of time to attempt to write iSize bytes. less than zero will block until iSize bytes has been written
+ * \return the number of bytes written. -1 for error
+ */
+ virtual int doWrite(const char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis) = 0;
+
+ };
+ }
+}
+
+
+
+#endif /* MTS_IO_CONNECTION_H_ */
diff --git a/include/mts/MTS_IO_DE910Radio.h b/include/mts/MTS_IO_DE910Radio.h
new file mode 100644
index 0000000..40dc132
--- /dev/null
+++ b/include/mts/MTS_IO_DE910Radio.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_DE910Radio.h
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_DE910RADIO_H_
+#define MTS_IO_DE910RADIO_H_
+
+#include <mts/MTS_IO_CdmaRadio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class DE910Radio : public CdmaRadio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ DE910Radio(const std::string& sPort);
+ virtual ~DE910Radio(){};
+
+ protected:
+
+ private:
+
+ };
+ }
+}
+
+
+
+#endif /* MTS_IO_DE910RADIO_H_ */
diff --git a/include/mts/MTS_IO_GE910Radio.h b/include/mts/MTS_IO_GE910Radio.h
new file mode 100644
index 0000000..079765d
--- /dev/null
+++ b/include/mts/MTS_IO_GE910Radio.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_GE910Radio.h
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_GE910RADIO_H_
+#define MTS_IO_GE910RADIO_H_
+
+#include <mts/MTS_IO_CellularRadio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class GE910Radio : public CellularRadio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ GE910Radio(const std::string& sPort);
+ virtual ~GE910Radio(){};
+
+ protected:
+
+ private:
+
+
+ };
+ }
+}
+
+
+
+
+#endif /* MTS_IO_GE910RADIO_H_ */
diff --git a/include/mts/MTS_IO_HE910DRadio.h b/include/mts/MTS_IO_HE910DRadio.h
new file mode 100644
index 0000000..2fd648e
--- /dev/null
+++ b/include/mts/MTS_IO_HE910DRadio.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_HE910DRadio.h
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_HE910DRADIO_H_
+#define MTS_IO_HE910DRADIO_H_
+
+#include <mts/MTS_IO_HE910Radio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class HE910DRadio : public HE910Radio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ HE910DRadio(const std::string& sPort);
+ virtual ~HE910DRadio(){};
+
+ protected:
+
+ private:
+
+ };
+ }
+}
+
+
+
+
+#endif /* MTS_IO_HE910DRADIO_H_ */
diff --git a/include/mts/MTS_IO_HE910EUDRadio.h b/include/mts/MTS_IO_HE910EUDRadio.h
new file mode 100644
index 0000000..96353f2
--- /dev/null
+++ b/include/mts/MTS_IO_HE910EUDRadio.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_HE910EUDRadio.h
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_HE910EUDRADIO_H_
+#define MTS_IO_HE910EUDRADIO_H_
+
+
+#include <mts/MTS_IO_HE910Radio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class HE910EUDRadio : public HE910Radio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ HE910EUDRadio(const std::string& sPort);
+ virtual ~HE910EUDRadio(){};
+
+ protected:
+
+ private:
+
+ };
+ }
+}
+
+
+#endif /* MTS_IO_HE910EUDRADIO_H_ */
diff --git a/include/mts/MTS_IO_HE910Radio.h b/include/mts/MTS_IO_HE910Radio.h
new file mode 100644
index 0000000..ee8e1e7
--- /dev/null
+++ b/include/mts/MTS_IO_HE910Radio.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_HE910Radio.h
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_HE910RADIO_H_
+#define MTS_IO_HE910RADIO_H_
+
+#include <mts/MTS_IO_CellularRadio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class HE910Radio : public CellularRadio {
+
+ public:
+
+ virtual ~HE910Radio(){};
+
+ protected:
+ HE910Radio(const std::string& sHE910Model, const std::string& sPort);
+ private:
+
+ };
+ }
+}
+
+
+#endif /* MTS_IO_HE910RADIO_H_ */
diff --git a/include/mts/MTS_IO_LE910EUGRadio.h b/include/mts/MTS_IO_LE910EUGRadio.h
new file mode 100644
index 0000000..d0607e2
--- /dev/null
+++ b/include/mts/MTS_IO_LE910EUGRadio.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LE910EUGRadio.h
+ \brief A brief description
+ \date Jan 19, 2015
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_LE910EUGRADIO_H_
+#define MTS_IO_LE910EUGRADIO_H_
+
+#include <mts/MTS_IO_LE910Radio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class LE910EUGRadio : public LE910Radio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ LE910EUGRadio(const std::string& sPort);
+ virtual ~LE910EUGRadio(){};
+
+ protected:
+
+ private:
+
+ };
+ }
+}
+
+#endif /* MTS_IO_LE910EUGRADIO_H_ */
diff --git a/include/mts/MTS_IO_LE910NAGRadio.h b/include/mts/MTS_IO_LE910NAGRadio.h
new file mode 100644
index 0000000..a05a311
--- /dev/null
+++ b/include/mts/MTS_IO_LE910NAGRadio.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LE910NAGRadio.h
+ \brief A brief description
+ \date Jan 19, 2015
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_LE910NAGRADIO_H_
+#define MTS_IO_LE910NAGRADIO_H_
+
+#include <mts/MTS_IO_LE910Radio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class LE910NAGRadio : public LE910Radio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ LE910NAGRadio(const std::string& sPort);
+ virtual ~LE910NAGRadio(){};
+
+ virtual CODE getCarrier(std::string& sCarrier);
+
+ protected:
+
+ private:
+
+ };
+ }
+}
+
+#endif /* MTS_IO_LE910NAGRADIO_H_ */
diff --git a/include/mts/MTS_IO_LE910Radio.h b/include/mts/MTS_IO_LE910Radio.h
new file mode 100644
index 0000000..e2f4c12
--- /dev/null
+++ b/include/mts/MTS_IO_LE910Radio.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LE910Radio.h
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_LE910RADIO_H_
+#define MTS_IO_LE910RADIO_H_
+
+#include <mts/MTS_IO_CellularRadio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class LE910Radio : public CellularRadio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ LE910Radio(const std::string& sLE910Model, const std::string& sPort);
+ virtual ~LE910Radio(){};
+
+ protected:
+
+ private:
+
+
+ };
+ }
+}
+
+
+
+
+#endif /* MTS_IO_LE910RADIO_H_ */
diff --git a/include/mts/MTS_IO_LE910SVGRadio.h b/include/mts/MTS_IO_LE910SVGRadio.h
new file mode 100644
index 0000000..d92f877
--- /dev/null
+++ b/include/mts/MTS_IO_LE910SVGRadio.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LE910SVGRadio.h
+ \brief A brief description
+ \date Jan 19, 2015
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_LE910SVGRADIO_H_
+#define MTS_IO_LE910SVGRADIO_H_
+
+#include <mts/MTS_IO_LE910Radio.h>
+
+namespace MTS {
+ namespace IO {
+
+ class LE910SVGRadio : public LE910Radio {
+
+ public:
+ static const std::string MODEL_NAME;
+
+ LE910SVGRadio(const std::string& sPort);
+ virtual ~LE910SVGRadio(){};
+
+ virtual CODE getCarrier(std::string& sCarrier);
+
+ protected:
+
+ private:
+
+ };
+ }
+}
+
+#endif /* MTS_IO_LE910SVGRADIO_H_ */
diff --git a/include/mts/MTS_IO_LockFile.h b/include/mts/MTS_IO_LockFile.h
new file mode 100644
index 0000000..dcfb9ae
--- /dev/null
+++ b/include/mts/MTS_IO_LockFile.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LockFile.h
+ \brief A brief description
+ \date Oct 8, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_LOCKFILE_H_
+#define MTS_IO_LOCKFILE_H_
+
+#include <mts/MTS_NonCopyable.h>
+#include <string>
+
+namespace MTS {
+ namespace IO {
+
+ class LockFile : MTS::NonCopyable {
+
+ public:
+
+ LockFile(const std::string& sFilePath);
+ virtual ~LockFile();
+
+ bool lock(uint32_t tryMillis);
+ void unlock();
+ bool isLocked();
+
+ protected:
+
+ private:
+ std::string m_sFile;
+ int m_iLockFd;
+ };
+
+ }
+}
+
+#endif /* MTS_IO_LOCKFILE_H_ */
diff --git a/include/mts/MTS_IO_MccMncTable.h b/include/mts/MTS_IO_MccMncTable.h
new file mode 100644
index 0000000..7772258
--- /dev/null
+++ b/include/mts/MTS_IO_MccMncTable.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_MccMncTable.h
+ \brief A brief description
+ \date Dec 11, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+#ifndef MTS_IO_MCCMNCTABLE_H_
+#define MTS_IO_MCCMNCTABLE_H_
+
+#include <mts/MTS_AutoPtr.h>
+#include <mts/MTS_Lock.h>
+#include <json/json.h>
+#include <map>
+#include <string>
+
+namespace MTS {
+ namespace IO {
+
+ class MccMncTable {
+ public:
+ static MccMncTable* getInstance();
+
+ Json::Value lookup(const std::string& sMcc, const std::string& sMnc);
+
+ private:
+ static MccMncTable* m_pInstance;
+ static MTS::AutoPtr<MTS::Lock> m_apLock;
+
+ std::map<uint32_t, std::map<uint32_t, std::string> > m_mTable;
+
+ MccMncTable();
+ void createTable();
+ };
+
+ }
+}
+
+
+
+#endif /* MTS_IO_MCCMNCTABLE_H_ */
diff --git a/include/mts/MTS_IO_SerialConnection.h b/include/mts/MTS_IO_SerialConnection.h
new file mode 100644
index 0000000..b4bb61f
--- /dev/null
+++ b/include/mts/MTS_IO_SerialConnection.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_SerialConnection.h
+ \brief A brief description
+ \date Jan 15, 2013
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#ifndef MTS_IO_SERIALCONNECTION_H_
+#define MTS_IO_SERIALCONNECTION_H_
+
+#include <mts/MTS_IO_Connection.h>
+#include <mts/MTS_IO_LockFile.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+
+namespace MTS {
+ namespace IO {
+
+ class SerialConnection : public Connection {
+
+ public:
+
+ enum ETYPE {
+ RS232,
+ RS422,
+ RS485
+ };
+
+ enum EPARITY {
+ OFF,
+ ODD,
+ EVEN
+ };
+
+ enum EDATABITS {
+ B5,
+ B6,
+ B7,
+ B8
+ };
+
+ enum ESTOPBITS {
+ B1,
+ B2
+ };
+
+ enum IOCTL {
+ LE = TIOCM_LE,
+ DTR = TIOCM_DTR,
+ RTS = TIOCM_RTS,
+ ST = TIOCM_ST,
+ SR = TIOCM_SR,
+ CTS = TIOCM_CTS,
+ CAR = TIOCM_CAR,
+ CD = TIOCM_CD,
+ RNG = TIOCM_RNG,
+ RI = TIOCM_RI,
+ DSR = TIOCM_DSR
+ };
+
+ enum FLOW_CONTROL {
+ NONE,
+ RTS_CTS
+ };
+
+ class Builder {
+ public:
+ Builder(const std::string& sPortName);
+
+ Builder& type(const ETYPE& eType);
+ Builder& rs232();
+ Builder& rs422();
+ Builder& rs485();
+
+ Builder& parity(const EPARITY& eParity);
+ Builder& parityOff();
+ Builder& parityOdd();
+ Builder& parityEven();
+
+ Builder& dataBits(const EDATABITS& eDataLength);
+ Builder& fiveDataBits();
+ Builder& sixDataBits();
+ Builder& sevenDataBits();
+ Builder& eightDataBits();
+
+ Builder& stopBits(const ESTOPBITS& eStopBits);
+ Builder& oneStopBit();
+ Builder& twoStopBits();
+
+ Builder& useLockFile(bool enabled = true);
+ Builder& flowControl(const FLOW_CONTROL& eFlowControl);
+ Builder& baudRate(uint32_t iBaud);
+
+ Builder& build();
+
+ const std::string& getPortName() const;
+ const uint32_t& getBaudRate() const;
+ ETYPE getType() const;
+ EPARITY getParity() const;
+ EDATABITS getDataBits() const;
+ ESTOPBITS getStopBits() const;
+ FLOW_CONTROL getFlowControl() const;
+ std::string getTypeAsString() const;
+ bool isUsingLockFile() const;
+ bool isBuilt() const;
+
+ private:
+ std::string m_sPortName;
+ uint32_t m_iBaudRate;
+ ETYPE m_eType;
+ EPARITY m_eParity;
+ EDATABITS m_eDataBits;
+ ESTOPBITS m_eStopBits;
+ FLOW_CONTROL m_eFlowControl;
+ bool m_bLockFile;
+ bool m_bBuilt;
+ };
+
+ SerialConnection(const Builder& oBuilder);
+ virtual ~SerialConnection();
+
+ const std::string& getPortName() const;
+ uint32_t getBaudRate() const;
+
+ void flush();
+ void drain();
+ protected:
+ virtual int getFileDescriptor();
+
+ private:
+ const std::string m_sPortName;
+ uint32_t m_iBaudRate;
+ ETYPE m_eType;
+ EPARITY m_eParity;
+ EDATABITS m_eDataBits;
+ ESTOPBITS m_eStopBits;
+ FLOW_CONTROL m_eFlowControl;
+ AutoPtr<LockFile> m_apLockFile;
+
+ AutoPtr<Lock> m_apHandleLock;
+#ifdef WIN32
+ HANDLE m_iHandle;
+#else
+ int m_iHandle;
+ termios m_stPrevOptions;
+#endif
+
+ virtual bool doOpen(const int32_t& timeoutMillis);
+ virtual void doClose();
+ virtual int doRead(char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis);
+ virtual int doWrite(const char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis);
+
+ void cleanup();
+ };
+ }
+}
+
+
+#endif /* MTS_IO_SERIALCONNECTION_H_ */
diff --git a/scripts/create-mcc-mnc-table.py b/scripts/create-mcc-mnc-table.py
new file mode 100644
index 0000000..761454c
--- /dev/null
+++ b/scripts/create-mcc-mnc-table.py
@@ -0,0 +1,106 @@
+#Generates MTS_IO_MccMncTable.cpp file by pulling latest MCC/MNC values
+#from http://mcc-mnc.com
+
+#Original Source Idea: https://github.com/musalbas/mcc-mnc-table
+
+
+import re
+import urllib2
+import datetime
+
+print "/*!"
+print " \\file MTS_IO_MccMncTable.cpp"
+print " \\brief Auto-Generated MCC-MNC Lookup Table"
+print " \\date " + str(datetime.date.today())
+print " \\author sgodinez"
+print ""
+print " An Auto-Generated MCC-MNC Lookup Table"
+print "*/"
+print ""
+print "#include <mts/MTS_IO_MccMncTable.h>"
+print "#include <mts/MTS_Logger.h>"
+print "#include <mts/MTS_Text.h>"
+print ""
+print "using namespace MTS::IO;"
+print ""
+print "MTS::AutoPtr<MTS::Lock> MccMncTable::m_apLock(new MTS::Lock());"
+print "MccMncTable* MccMncTable::m_pInstance = NULL;"
+print ""
+print "MccMncTable* MccMncTable::getInstance() {"
+print " if(m_pInstance == NULL) {"
+print " m_apLock->lock();"
+print " if (m_pInstance == NULL) {"
+print " m_pInstance = new MccMncTable();"
+print " }"
+print " m_apLock->unlock();"
+print " }"
+print " return m_pInstance;"
+print "}"
+print ""
+print "MccMncTable::MccMncTable() {"
+print " createTable();"
+print "}"
+print ""
+print "Json::Value MccMncTable::lookup(const std::string& sMcc, const std::string& sMnc) {"
+print " uint32_t iMcc, iMnc;"
+print ' printTrace("[MCCMNC] MCCx[%s] MNCx[%s]", sMcc.c_str(), sMnc.c_str());'
+print " if(!MTS::Text::parseHex(iMcc, sMcc)) { return Json::Value::null; }"
+print " if(!MTS::Text::parseHex(iMnc, sMnc)) { return Json::Value::null; }"
+print ' printTrace("[MCCMNC] MCC0X[%d] MNC0X[%d]", iMcc, iMnc);'
+print " if (m_mTable.count(iMcc)) {"
+print " if(m_mTable[iMcc].count(iMnc)) {"
+print " std::vector<std::string> vJson = MTS::Text::split(m_mTable[iMcc][iMnc], ',');"
+print " Json::Value j;"
+print ' j["iso"] = vJson[0];'
+print ' j["country"] = vJson[1];'
+print ' j["code"] = vJson[2];'
+print ' j["carrier"] = vJson[3];'
+print " return j;"
+print " }"
+print " }"
+print ""
+print " return Json::Value::null;"
+print "}"
+print ""
+print "void MccMncTable::createTable() {"
+print " std::string sData;"
+
+td_re = re.compile('<td>([^<]*)</td>'*6)
+
+html = urllib2.urlopen('http://mcc-mnc.com/').read()
+
+tbody_start = False
+for line in html.split('\n'):
+ if '<tbody>' in line:
+ tbody_start = True
+ elif '</tbody>' in line:
+ break
+ elif tbody_start:
+ td_search = td_re.search(line)
+ mcc = td_search.group(1).strip().replace(',','')
+ mnc = td_search.group(2).strip().replace(',','')
+ iso = td_search.group(3).strip().replace(',','')
+ countryCode = td_search.group(4).strip().replace(',','')
+ country = td_search.group(5).strip().replace(',','')
+ carrier = td_search.group(6).strip().replace(',','')
+
+ if mnc != "n/a":
+ mcc_int = int(mcc, 16)
+ if len(mnc) == 2:
+ mnc_int = int(mnc + 'f', 16)
+ else:
+ mnc_int = int(mnc, 16)
+ print ' m_mTable[' + str(mcc_int) + '][' + str(mnc_int) + '] = "' + \
+ iso + ',' + countryCode + ',' + country + ',' + carrier + '";'
+ else:
+ print " //MCC(" + mcc + ') MNC(N/A) ISO(' + iso + ') Country Code(' + countryCode + ') Country(' + country + ') Carrier(' + carrier + ')'
+
+
+
+print "}"
+print ""
+
+
+
+
+
diff --git a/src/MTS_IO_CE910Radio.cpp b/src/MTS_IO_CE910Radio.cpp
new file mode 100644
index 0000000..b60c648
--- /dev/null
+++ b/src/MTS_IO_CE910Radio.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_CE910Radio.cpp
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_CE910Radio.h>
+
+using namespace MTS::IO;
+
+const std::string CE910Radio::MODEL_NAME("CE910");
+
+CE910Radio::CE910Radio(const std::string& sPort)
+: CdmaRadio(MODEL_NAME, sPort)
+{
+
+}
+
+
diff --git a/src/MTS_IO_CdmaRadio.cpp b/src/MTS_IO_CdmaRadio.cpp
new file mode 100644
index 0000000..66ce820
--- /dev/null
+++ b/src/MTS_IO_CdmaRadio.cpp
@@ -0,0 +1,1297 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_CdmaRadio.cpp
+ \brief A brief description
+ \date Nov 19, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_CdmaRadio.h>
+#include <mts/MTS_Text.h>
+#include <mts/MTS_Logger.h>
+#include <mts/MTS_Thread.h>
+
+using namespace MTS::IO;
+
+CdmaRadio::CdmaRadio(const std::string& sName, const std::string& sPort)
+: CellularRadio(sName, sPort)
+{
+
+}
+
+CdmaRadio::~CdmaRadio() {
+
+}
+
+CellularRadio::CODE CdmaRadio::getImei(std::string& sImei) {
+ printTrace("%s| Get IMEI", getName().c_str());
+ return getMeid(sImei);
+}
+
+CellularRadio::CODE CdmaRadio::getMeid(std::string& sMeid) {
+ printTrace("%s| Get MEID", getName().c_str());
+ sMeid = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT#MEIDESN?");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t pos = sResult.find(RSP_OK);
+ if (pos == std::string::npos) {
+ printWarning("%s| Unable to get MEID from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find("#MEIDESN:") + sizeof("#MEIDESN:");
+ size_t stop = sResult.find(",");
+
+ if(stop != std::string::npos && stop > start) {
+ sMeid = sResult.substr(start, stop - start);
+ } else {
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::getMsid(std::string& sMsid) {
+ printTrace("%s| Get MSID", getName().c_str());
+ sMsid = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT$MSID?");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to get MSID from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find("$MSID:") + sizeof("$MSID:");
+ sMsid = MTS::Text::trim(sResult.substr(start, end-start));
+ if(sMsid.size() == 0) {
+ printWarning("%s| MSID is empty", getName().c_str());
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::getCarrier(std::string& sCarrier) {
+ if(m_sCarrier != "") {
+ sCarrier = m_sCarrier;
+ return SUCCESS;
+ }
+
+ std::string sFirmware;
+ CODE code = getFirmware(sFirmware);
+ if(code != SUCCESS) {
+ return code;
+ }
+
+ if(!getCarrierFromFirmware(sFirmware, sCarrier)) {
+ return FAILURE;
+ }
+
+ m_sCarrier = sCarrier;
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::getNetwork(std::string& sNetwork) {
+ return getCarrier(sNetwork);
+}
+
+CellularRadio::CODE CdmaRadio::getSimStatus(std::string& sSimStatus) {
+ printTrace("%s| Get SIM Status", getName().c_str());
+ sSimStatus = VALUE_NOT_SUPPORTED;
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CdmaRadio::getIccid(std::string& sIccid) {
+ printTrace("%s| Get ICCID", getName().c_str());
+ sIccid = VALUE_NOT_SUPPORTED;
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CdmaRadio::getLac(std::string& sLac) {
+ printTrace("%s| Get LAC", getName().c_str());
+ sLac = VALUE_NOT_SUPPORTED;
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CdmaRadio::getService(std::string& sService) {
+ printTrace("%s| Get Service", getName().c_str());
+ sService = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+SERVICE?");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to get Service from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find("+SERVICE:");
+ if(start != std::string::npos) {
+ start += sizeof("+SERVICE:");
+ std::string sPsnt = MTS::Text::trim(sResult.substr(start, end-start));
+ int32_t iService;
+ sscanf(sPsnt.c_str(), "%d", &iService);
+
+ switch(iService) {
+ case 0: sService = "No Service"; break;
+ case 1: sService = "1xRTT"; break;
+ case 2: sService = "EVDO"; break; //Release 0
+ case 3: sService = "EVDO"; break; //Release A
+ case 4: sService = "GPRS"; break;
+ default: sService = VALUE_UNKNOWN; break;
+ }
+
+ printDebug("%s| Service ID: [%d][%s]", getName().c_str(), iService, sService.c_str());
+ }
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::getHardware(std::string& sHardware) {
+ printTrace("%s| Get Hardware", getName().c_str());
+ sHardware = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT#HWREV");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t pos = sResult.find(RSP_OK);
+ if (pos == std::string::npos) {
+ printWarning("%s| Unable to get hardware from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ sHardware = MTS::Text::trim(sResult.substr(0, pos));
+ if(sHardware.size() == 0) {
+ printWarning("%s| Unable to get hardware from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::getMdn(std::string& sMdn) {
+ printTrace("%s| Get MDN", getName().c_str());
+ sMdn = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+CNUM");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to get MDN from radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find("CNUM:");
+ std::vector<std::string> vParts = MTS::Text::split(sResult.substr(start + sizeof("CNUM:"), end), ",");
+ if(vParts.size() == 3) {
+ sMdn = vParts[1];
+ if(sMdn.size() == 0) {
+ printWarning("%s| MDN is empty. Device may need to be activated", getName().c_str(), sCmd.c_str());
+ }
+ } else {
+ printWarning("%s| Unable to parse MDN from radio using command [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::validateMsl(const Json::Value& jArgs) {
+ printTrace("%s| Validate MSL", getName().c_str());
+
+ if(!jArgs["msl"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ if(sCarrier != "Aeris" && sCarrier != "Sprint") {
+ return NOT_APPLICABLE;
+ }
+
+ std::string sMdn;
+ if(getMdn(sMdn) != SUCCESS) {
+ return FAILURE;
+ }
+
+ Json::Value jMdn(Json::objectValue);
+ jMdn["mdn"] = sMdn;
+ jMdn["msl"] = jArgs["msl"];
+
+ return setMdn(jMdn);
+}
+
+CellularRadio::CODE CdmaRadio::setMdn(const Json::Value& jArgs) {
+ printTrace("%s| Set MDN", getName().c_str());
+
+ if(!jArgs["mdn"].isString()) {
+ printError("%s| Arguments missing \"mdn\"", getName().c_str());
+ return INVALID_ARGS;
+ }
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ std::string sCmd("AT$MDN=");
+ if(sCarrier == "Sprint") {
+
+ if(!jArgs["msl"].isString()) {
+ printError("%s| Arguments missing \"msl\"", getName().c_str());
+ return INVALID_ARGS;
+ }
+ sCmd += jArgs["msl"].asString() + ",";
+ } else if(sCarrier == "Aeris") {
+ //AT$MDN=<Last Six Digits of HEX MEID>,<MDN>
+ sCmd += getMeidLastSix() + ",";
+ }
+
+ //Strip spaces and hyphens
+ std::string sMdn = jArgs["mdn"].asString();
+ sMdn = MTS::Text::strip(sMdn, '-');
+ sMdn = MTS::Text::strip(sMdn, '(');
+ sMdn = MTS::Text::strip(sMdn, ')');
+ sMdn = MTS::Text::strip(sMdn, ' ');
+
+
+ sCmd += sMdn;
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set MDN for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMsid(const Json::Value& jArgs) {
+ printTrace("%s| Set MSID", getName().c_str());
+ if(!jArgs["msid"].isString()) {
+ printError("%s| Arguments missing \"msid\"", getName().c_str());
+ return INVALID_ARGS;
+ }
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ std::string sCmd("AT$MSID=");
+ if(sCarrier == "Sprint") {
+ if(!jArgs["msl"].isString()) {
+ printError("%s| Arguments missing \"msl\"", getName().c_str());
+ return INVALID_ARGS;
+ }
+ sCmd += jArgs["msl"].asString() + ",";
+ } else if(sCarrier == "Aeris") {
+ //AT$MSID=<Last Six Digits of HEX MEID>,<MSID>
+ sCmd += getMeidLastSix() + ",";
+ }
+
+
+ sCmd += jArgs["msid"].asString();
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set MSID for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::getMipProfile(Json::Value& jMipProfile) {
+ printTrace("%s| Get MIP Active Profile", getName().c_str());
+
+ initMipProfile(jMipProfile);
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ if(sCarrier == "Aeris" || sCarrier == "Sprint") {
+ std::string sCmd("AT$QCMIPGETP");
+ std::string sResult = MTS::Text::trim(sendCommand(sCmd));
+ if (sResult.find(RSP_OK) == std::string::npos) {
+ printWarning("%s| Unable to get active MIP profile for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ std::vector<std::string> vLine = MTS::Text::split(sResult, "\r\n");
+
+ //ACTIVE MIP PROFILE
+ std::string sLine = vLine[0];
+ std::vector<std::string> vParts = MTS::Text::split(sLine, ':', 2);
+ if(vParts.size() == 2 && vParts[0] == "Profile") {
+ if(vParts[1].find("Enabled") != std::string::npos) {
+ jMipProfile[KEY_MIP_ENABLED] = true;
+ } else {
+ jMipProfile[KEY_MIP_ENABLED] = false;
+ }
+ int32_t id;
+ sscanf(vParts[1].c_str(), "%d", &id);
+ jMipProfile[KEY_MIP_ID] = id;
+
+ } else {
+ printWarning("%s| Unable to parse active MIP profile from line [%s]", getName().c_str(), sLine.c_str());
+ }
+
+
+ splitAndAssign(vLine[1], "NAI", jMipProfile, KEY_MIP_NAI);
+ splitAndAssign(vLine[2], "Home Addr", jMipProfile, KEY_MIP_HOMEADDRESS);
+ splitAndAssign(vLine[3], "Primary HA", jMipProfile, KEY_MIP_PRIMARYHA);
+ splitAndAssign(vLine[4], "Secondary HA", jMipProfile, KEY_MIP_SECONDARYHA);
+ splitAndAssign(vLine[5], "MN-AAA SPI", jMipProfile, KEY_MIP_MNAAASPI);
+ splitAndAssign(vLine[6], "MN-HA SPI", jMipProfile, KEY_MIP_MNHASPI);
+
+ //Reverse Tunneling
+ sLine = vLine[7];
+ vParts = MTS::Text::split(sLine, ':', 2);
+ if(vParts.size() == 2 && vParts[0] == "Rev Tun") {
+ if(vParts[1] == "1") {
+ jMipProfile[KEY_MIP_REVTUN] = true;
+ } else {
+ jMipProfile[KEY_MIP_REVTUN] = false;
+ }
+ } else {
+ printWarning("%s| Unable to parse Reverse Tunneling from line [%s]", getName().c_str(), sLine.c_str());
+ }
+
+ //MN-AAA SS
+ sLine = vLine[8];
+ vParts = MTS::Text::split(sLine, ':', 2);
+ if(vParts.size() == 2 && vParts[0] == "MN-AAA SS") {
+ if(vParts[1] == "Set") {
+ jMipProfile[KEY_MIP_MNAAASS] = true;
+ } else {
+ jMipProfile[KEY_MIP_MNAAASS] = false;
+ }
+ } else {
+ printWarning("%s| Unable to parse MN-AAA SS from line [%s]", getName().c_str(), sLine.c_str());
+ }
+
+ //MN-HA SS
+ sLine = vLine[9];
+ vParts = MTS::Text::split(sLine, ':', 2);
+ if(vParts.size() == 2 && vParts[0] == "MN-HA SS") {
+ if(vParts[1] == "Set") {
+ jMipProfile[KEY_MIP_MNHASS] = true;
+ } else {
+ jMipProfile[KEY_MIP_MNHASS] = false;
+ }
+ } else {
+ printWarning("%s| Unable to parse MN-HA SS from line [%s]", getName().c_str(), sLine.c_str());
+ }
+ }
+
+
+ return SUCCESS;
+}
+
+
+CellularRadio::CODE CdmaRadio::setMipActiveProfile(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Active Profile", getName().c_str());
+
+ if(!jArgs["activeProfile"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPP=");
+ sCmd += jArgs["activeProfile"].asString();
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set Active profile for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipNai(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP NAI", getName().c_str());
+
+ if(!jArgs["nai"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPNAI=");
+ sCmd += jArgs["nai"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set NAI for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipHomeIp(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Home IP", getName().c_str());
+
+ if(!jArgs["homeIp"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPHA=");
+ sCmd += jArgs["homeIp"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set Home IP profile for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipPrimaryHa(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Primary HA", getName().c_str());
+
+ if(!jArgs["primaryHa"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPPHA=");
+ sCmd += jArgs["primaryHa"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set Primary HA for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipSecondaryHa(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Secondary HA", getName().c_str());
+
+ if(!jArgs["secondaryHa"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPSHA=");
+ sCmd += jArgs["secondaryHa"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set Secondary HA for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipMnAaaSpi(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP MN-AAA SPI", getName().c_str());
+
+ if(!jArgs["mnAaaSpi"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPMASPI=");
+ sCmd += jArgs["mnAaaSpi"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set MN-AAA SPI for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipMnHaSpi(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP MN-HA SPI", getName().c_str());
+
+ if(!jArgs["mnHaSpi"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPMHSPI=");
+ sCmd += jArgs["mnHaSpi"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set MN-HA SPI for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipRevTun(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Rev Tun", getName().c_str());
+
+ if(!jArgs["revTun"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPRT=");
+ sCmd += jArgs["revTun"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set Rev Tun for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipMnAaaSs(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP MN-AAA SS", getName().c_str());
+
+ if(!jArgs["mnAaaSs"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPMASS=");
+ sCmd += jArgs["mnAaaSs"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set MN-AAA SS for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::setMipMnHaSs(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP MN-HA SS", getName().c_str());
+
+ if(!jArgs["mnHaSs"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT$QCMIPMHSS=");
+ sCmd += jArgs["mnHaSs"].asString() + ",1";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set MN-HA SS for radio using command [%s]", getName().c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CdmaRadio::updateDc(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| Update Device Configuration", getName().c_str());
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ if(sCarrier != "Sprint") {
+ return NOT_APPLICABLE;
+ }
+
+ CellularRadio::CODE result = FAILURE;
+ std::size_t pos = 0;
+ std::size_t end = 0;
+
+ IsNeedMoreData isNeedMoreData = [&stepCb, &result, &pos, &end, this](const std::string& iterationData, const std::string& allData)->bool {
+
+ if(iterationData.empty()) {
+ //No new data
+ return true;
+ }
+
+ end = allData.find(NL, pos);
+ printTrace("%s| Update DC Callback Started", this->getName().c_str());
+
+ while(end != std::string::npos) {
+ size_t next;
+ std::string sLine = MTS::Text::getLine(allData, pos, next);
+
+ printTrace("%s| Line: [%s]", this->getName().c_str(), sLine.c_str());
+
+ if(sLine == "#906") {
+ // DC DM session started
+ if(stepCb) {
+ stepCb(Json::Value("DC Info: DM session started"));
+ }
+ } else if(sLine == "#918") {
+ // DC Done, success
+ result = SUCCESS;
+ if(stepCb) {
+ stepCb(Json::Value("DC Done: success"));
+ }
+ return false;
+ } else if(sLine == "#924") {
+ // DC Done, no profile
+ result = SUCCESS;
+ if(stepCb) {
+ stepCb(Json::Value("DC Done: no profile"));
+ }
+ return false;
+ } else if(sLine == "#911") {
+ // DC Error: credential error
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("DC Error: credential error"));
+ }
+ return false;
+ } else if(sLine == "#912") {
+ // DC Error: unreachable server
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("DC Error: unreachable server"));
+ }
+ return false;
+ } else if(sLine == "#913") {
+ // DC Error: network error
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("DC Error: network error"));
+ }
+ return false;
+ } else if(sLine == "#915") {
+ // DC Error: update fails with other reasons
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("DC Error: update fails with other reasons"));
+ }
+ return false;
+ }else if(sLine == RSP_ERROR) {
+ result = ERROR;
+ return false;
+ }
+
+ //Set cursors for next iteration
+ if(next != std::string::npos) {
+ pos = next;
+ }
+ end = allData.find(NL, pos);
+ }
+
+ printTrace("%s| Update DC Callback Finished", this->getName().c_str());
+ return true;
+ };
+
+ sendCommand("AT+OMADM=2", isNeedMoreData, 5 * 60000);
+ return result;
+}
+
+CellularRadio::CODE CdmaRadio::updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| Update Preferred Roaming List", getName().c_str());
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ if(sCarrier != "Sprint") {
+ return NOT_APPLICABLE;
+ }
+
+ CellularRadio::CODE result = FAILURE;
+ std::size_t pos = 0;
+ std::size_t end = 0;
+
+ IsNeedMoreData isNeedMoreData = [&stepCb, &result, &pos, &end, this](const std::string& iterationData, const std::string& allData)->bool {
+
+ if(iterationData.empty()) {
+ //No new data
+ return true;
+ }
+
+ end = allData.find(NL, pos);
+ printTrace("%s| Update PRL Callback Started", this->getName().c_str());
+
+ while(end != std::string::npos) {
+ size_t next;
+ std::string sLine = MTS::Text::getLine(allData, pos, next);
+
+ printTrace("%s| Line: [%s]", this->getName().c_str(), sLine.c_str());
+
+ if(sLine == "#905") {
+ // PRL DM session started
+ if(stepCb) {
+ stepCb(Json::Value("PRL Info: DM session started"));
+ }
+ } else if(sLine == "#909") {
+ // PRL Done, success
+ result = SUCCESS;
+ if(stepCb) {
+ stepCb(Json::Value("PRL Done: success"));
+ }
+ return false;
+ } else if(sLine == "#910") {
+ // PRL Done, no PRL update
+ result = SUCCESS;
+ if(stepCb) {
+ stepCb(Json::Value("PRL Done: no PRL update"));
+ }
+ return false;
+ } else if(sLine == "#911") {
+ // PRL Error: credential error
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("PRL Error: credential error"));
+ }
+ return false;
+ } else if(sLine == "#912") {
+ // PRL Error: unreachable server
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("PRL Error: unreachable server"));
+ }
+ return false;
+ } else if(sLine == "#913") {
+ // PRL Error: network error
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("PRL Error: network error"));
+ }
+ return false;
+ } else if(sLine == "#915") {
+ // PRL Error: update fails with other reasons
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("PRL Error: update fails with other reasons"));
+ }
+ return false;
+ } else if(sLine == RSP_ERROR) {
+ result = ERROR;
+ return false;
+ }
+
+ //Set cursors for next iteration
+ if(next != std::string::npos) {
+ pos = next;
+ }
+ end = allData.find(NL, pos);
+ }
+
+ printTrace("%s| Update PRL Callback Finished", this->getName().c_str());
+ return true;
+ };
+
+ sendCommand("AT+PRL=2", isNeedMoreData, 5 * 60000);
+ return result;
+}
+
+CellularRadio::CODE CdmaRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| Update Firmware Update Management Object", getName().c_str());
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ if(sCarrier != "Sprint") {
+ return NOT_APPLICABLE;
+ }
+
+ CellularRadio::CODE result = FAILURE;
+ std::size_t pos = 0;
+ std::size_t end = 0;
+
+ IsNeedMoreData isNeedMoreData = [&stepCb, &result, &pos, &end, this](const std::string& iterationData, const std::string& allData)->bool {
+
+ if(iterationData.empty()) {
+ //No new data
+ return true;
+ }
+
+ end = allData.find(NL, pos);
+ printTrace("%s| Update FUMO Callback Started", this->getName().c_str());
+
+ while(end != std::string::npos) {
+ size_t next;
+ std::string sLine = MTS::Text::getLine(allData, pos, next);
+
+ printTrace("%s| Line: [%s]", this->getName().c_str(), sLine.c_str());
+
+ if(sLine == "#907") {
+ // FUMO DM session started
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Info: DM session started"));
+ }
+ } else if(sLine == "#916") {
+ // FUMO Done, no firmware update
+ result = SUCCESS;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Done: no firmware update"));
+ }
+ return false;
+ } else if(sLine == "#911") {
+ // FUMO Error: credential error
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: credential error"));
+ }
+ return false;
+ } else if(sLine == "#912") {
+ // FUMO Error: unreachable server
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: unreachable server"));
+ }
+ return false;
+ } else if(sLine == "#913") {
+ // FUMO Error: network error
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: network error"));
+ }
+ return false;
+ } else if(sLine == "#915") {
+ // FUMO Error: update fails with other reasons
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: update fails with other reasons"));
+ }
+ return false;
+ } else if(sLine == "#919") {
+ // FUMO Firmware downloaded successfully
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Info: firmware downloaded successfully"));
+ }
+ } else if(sLine == "#920:") {
+ // FUMO Firmware download progress (percent)
+ if(stepCb) {
+ stepCb(Json::Value(std::string("FUMO Info: firmware download progress ") + allData.substr(pos + 5, end + 5 - pos)));
+ }
+ } else if(sLine == "#921:") {
+ // FUMO Firmware size get from the OMA-DM server (byte)
+ if(stepCb) {
+ stepCb(Json::Value(std::string("FUMO Info: firmware size get from the OMA-DM server ") + allData.substr(pos + 5, end + 5 - pos) + " byte"));
+ }
+ } else if(sLine == "#921") { /// Info: check after check "#921:"
+ // FUMO Firmware download start
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Info: firmware downloaded successfully"));
+ }
+ } else if(sLine == "#929: 200") {
+ // FUMO Done, success
+ result = SUCCESS;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Done: update success"));
+ }
+ return false;
+ } else if(sLine == "#929: 402") {
+ // FUMO Error, firmware corrupted, CRC error
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: firmware corrupted, CRC error"));
+ }
+ return false;
+ } else if(sLine == "#929: 403") {
+ // FUMO Error, firmware package mismatch
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: firmware package mismatch"));
+ }
+ return false;
+ } else if(sLine == "#929: 404") {
+ // FUMO Error, firmware signature failed
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: firmware signature failed"));
+ }
+ return false;
+ } else if(sLine == "#929: 406") {
+ // FUMO Error, firmware update authentication failed
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: firmware update authentication failed"));
+ }
+ return false;
+ } else if(sLine == "#929: 410") {
+ // FUMO Error, firmware update general error
+ result = ERROR;
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Error: firmware update general error"));
+ }
+ return false;
+ } else if(sLine == "#930") {
+ // FUMO Reporting of Firmware Update result to server
+ if(stepCb) {
+ stepCb(Json::Value("FUMO Info: reporting of firmware update result to server"));
+ }
+ } else if(sLine == RSP_ERROR) {
+ result = ERROR;
+ return false;
+ }
+
+ //Set cursors for next iteration
+ if(next != std::string::npos) {
+ pos = next;
+ }
+ end = allData.find(NL, pos);
+ }
+
+ printTrace("%s| Update FUMO Callback Finished", this->getName().c_str());
+ return true;
+ };
+
+ sendCommand("AT+FUMO=2", isNeedMoreData, 30 * 60000);
+ return result;
+}
+
+CellularRadio::CODE CdmaRadio::resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| HFA Reset (after device reboot HFA will occur)", getName().c_str());
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ if(sCarrier != "Sprint") {
+ return NOT_APPLICABLE;
+ }
+
+ if(!jArgs["msl"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ CellularRadio::CODE result = FAILURE;
+ std::size_t pos = 0;
+ std::size_t end = 0;
+
+ IsNeedMoreData isNeedMoreData = [&stepCb, &result, &pos, &end, this](const std::string& iterationData, const std::string& allData)->bool {
+ /* Expected Events:
+ * #900 - DM Client ready
+ * #904 - HFA Started
+ * #914 - HFA Done - HFA Success
+ * #905 - PRL - Session started
+ * #909 - PRL - Done - PRL success
+ * #907 - FUMO - Firmware DM session started or started again until no more updates are available
+ * #916 - FUMO - Firmware Done, No firmware update
+ */
+
+
+ if(iterationData.empty()) {
+ //No new data
+ return true;
+ }
+
+ end = allData.find(NL, pos);
+ printTrace("%s| HFA Reset Callback Started", this->getName().c_str());
+
+ while(end != std::string::npos) {
+ size_t next;
+ std::string sLine = MTS::Text::getLine(allData, pos, next);
+
+ printTrace("%s| Line: [%s]", this->getName().c_str(), sLine.c_str());
+
+ if(sLine == "#900") {
+ if(stepCb) {
+ stepCb(Json::Value("RTN Info: DM Client Ready"));
+ }
+ } else if(sLine == "#904") {
+ if(stepCb) {
+ stepCb(Json::Value("RTN Info: HFA - Session Started"));
+ }
+ } else if(sLine == "#914") {
+ if(stepCb) {
+ stepCb(Json::Value("RTN Info: HFA - Session Completed Successfully"));
+ }
+ } else if(sLine == "#905") {
+ if(stepCb) {
+ stepCb(Json::Value("RTN Info: PRL - Session Started"));
+ }
+ } else if(sLine == "#909") {
+ if(stepCb) {
+ stepCb(Json::Value("RTN Info: PRL - Session Completed Successfully"));
+ }
+ } else if(sLine == "#907") {
+ if(stepCb) {
+ stepCb(Json::Value("RTN Info: Firmware DM - Session Started"));
+ }
+ } else if(sLine == "#916") {
+ // RTN Done, success
+ result = SUCCESS;
+ if(stepCb) {
+ stepCb(Json::Value("RTN Done: Firmware DM - Session Completed Successfully"));
+ }
+ return false;
+ } else if(sLine == RSP_ERROR) {
+ result = ERROR;
+ return false;
+ } else if(sLine == RSP_OK) {
+ //The Device will reboot now, so reset the connection
+ if(stepCb) {
+ stepCb(Json::Value("RTN Info: Resetting Radio"));
+ }
+
+ //TODO: Investigate a better way of to handle
+ // recapturing the radio port after reset
+
+ //Sleep for a few seconds while resetting
+ MTS::Thread::sleep(5000);
+
+ //Try to reconnect to radio
+ if(!this->resetConnection(10000)) {
+ printError("%s| Unable to obtain radio after reset", this->getName().c_str());
+ if(stepCb) {
+ stepCb(Json::Value("RTN Error: Unable to obtain radio after reset"));
+ }
+ result = ERROR;
+ return false;
+ }
+ }
+
+ //Set cursors for next iteration
+ if(next != std::string::npos) {
+ pos = next;
+ }
+ end = allData.find(NL, pos);
+ }
+
+ printTrace("%s| HFA Reset Callback Finished", this->getName().c_str());
+ return true;
+ };
+
+ std::string sCmd("AT#SPRTN=\"");
+ sCmd += jArgs["msl"].asString() + "\"";
+ sendCommand(sCmd, isNeedMoreData, 5 * 60000);
+ return result;
+}
+
+CellularRadio::CODE CdmaRadio::activate(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| Activation", getName().c_str());
+
+ std::string sActivationCmd;
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ if(sCarrier == "Aeris") {
+
+ if(!jArgs["msid"].isString()) {
+ printError("%s| Arguments missing \"msid\"", getName().c_str());
+ return INVALID_ARGS;
+ }
+
+ if(!jArgs["mdn"].isString()) {
+ printError("%s| Arguments missing \"mdn\"", getName().c_str());
+ return INVALID_ARGS;
+ }
+
+ std::string sMsid = jArgs["msid"].asString();
+ std::string sMdn = jArgs["mdn"].asString();
+ if(sMdn.size() != 10) {
+ printError("%s| MDN not valid. Expected length of 10: [%s][%d]", getName().c_str(), sMdn.c_str(), sMdn.size());
+ return INVALID_ARGS;
+ }
+
+ if(sMsid.size() != 10) {
+ printError("%s| MIN not valid. Expected length of 10: [%s][%d]", getName().c_str(), sMsid.c_str(), sMsid.size());
+ return INVALID_ARGS;
+ }
+
+ //Set MDN & MSID
+ CellularRadio::CODE code;
+ code = setMdn(jArgs);
+ if(code != SUCCESS) {
+ return code;
+ }
+
+ code = setMsid(jArgs);
+ if(code != SUCCESS) {
+ return code;
+ }
+
+ resetRadio(10000);
+
+ return SUCCESS;
+
+ } else if(sCarrier == "Verizon") {
+ sActivationCmd = "AT+CDV*22899\r";
+ } else {
+ return NOT_APPLICABLE;
+ }
+
+ CellularRadio::CODE result = FAILURE;
+ std::size_t pos = 0;
+ std::size_t end = 0;
+
+ IsNeedMoreData isNeedMoreData = [&stepCb, &result, &pos, &end, this](const std::string& iterationData, const std::string& allData)->bool {
+ //Verizon Activation
+ /* Expected Events:
+ * OK
+ * #OTASP: 0 //Start OTASP
+ * #OTASP: 1 //Start OTASP Commit
+ * #OTASP: 2 //End OTASP
+ *
+ * ERRORS:
+ * NO CARRIER //Account Plan Not Active
+ * #OTASP: 5 //Activation Failed
+ */
+
+
+ if(iterationData.empty()) {
+ //No new data
+ return true;
+ }
+
+ end = allData.find(NL, pos);
+ printTrace("%s| Activation Reset Callback Started", this->getName().c_str());
+
+ while(end != std::string::npos) {
+ size_t next;
+ std::string sLine = MTS::Text::getLine(allData, pos, next);
+
+ printTrace("%s| Line: [%s]", this->getName().c_str(), sLine.c_str());
+
+ if(sLine == RSP_OK) {
+ if(stepCb) {
+ stepCb(Json::Value("Activation Info: Over-the-Air Programming in Process"));
+ }
+ } else if(sLine == "#OTASP: 0") {
+ if(stepCb) {
+ stepCb(Json::Value("Activation Info: Saving Radio Configurations"));
+ }
+ } else if(sLine == "#OTASP: 1") {
+ if(stepCb) {
+ stepCb(Json::Value("Activation Info: Restarting Radio"));
+ }
+ } else if(sLine == "#OTASP: 2") {
+ if(stepCb) {
+ stepCb(Json::Value("Activation Info: Activation Completed Successfully"));
+ }
+ //Sleep for a few seconds while radio resets
+ MTS::Thread::sleep(5000);
+ this->resetConnection(10000);
+ result = SUCCESS;
+ return false;
+ } else if(sLine == "#OTASP: 5") {
+ if(stepCb) {
+ stepCb(Json::Value("Activation Error: Activation Failed"));
+ }
+ return false;
+ } else if(sLine == "NO CARRIER") {
+ if(stepCb) {
+ stepCb(Json::Value("Activation Error: Account Plan May Not Be Active"));
+ }
+ result = ERROR;
+ return false;
+ } else if(sLine == RSP_ERROR) {
+ result = ERROR;
+ return false;
+ }
+
+ //Set cursors for next iteration
+ if(next != std::string::npos) {
+ pos = next;
+ }
+ end = allData.find(NL, pos);
+ }
+
+ printTrace("%s| Activation Callback Finished", this->getName().c_str());
+ return true;
+ };
+
+ sendCommand(sActivationCmd, isNeedMoreData, 5 * 60000);
+ return result;
+}
+
+CellularRadio::CODE CdmaRadio::getNetworkStatus(Json::Value& jData) {
+ printTrace("%s| Get Network Status", getName().c_str());
+
+ getCommonNetworkStats(jData);
+
+ std::string sCarrier;
+ getCarrier(sCarrier);
+
+ if(sCarrier == VALUE_CARRIER_SPRINT) {
+ Json::Value& jDebug = jData["debug"];
+ std::string sCmd("AT$DEBUG?");
+ std::string sResult = MTS::Text::trim(sendCommand(sCmd));
+ if (sResult.find(RSP_OK) != std::string::npos) {
+ std::vector<std::string> vCategories = MTS::Text::split(sResult, "\r\n\r\n");
+ for(size_t i = 0 ; i < vCategories.size(); i++) {
+ std::vector<std::string> vLine = MTS::Text::split(vCategories[i], "\r\n");
+ if(vLine[0] == "1x Engineering") {
+ Json::Value& j1x = jDebug["1xrtt"];
+ splitAndAssign(vLine[1], "State", j1x, "state");
+ splitAndAssign(vLine[3], "Channel", j1x, "channel");
+ splitAndAssign(vLine[4], "Band Class", j1x, "bandClass");
+ splitAndAssign(vLine[5], "SID", j1x, "sid");
+ splitAndAssign(vLine[6], "NID", j1x, "nid");
+ splitAndAssign(vLine[7], "Base ID", j1x, "baseId");
+ splitAndAssign(vLine[8], "PN", j1x, "pn");
+ splitAndAssign(vLine[9], "P_rev", j1x, "pRev");
+ splitAndAssign(vLine[10], "Lat", j1x, "lat");
+ splitAndAssign(vLine[11], "Lon", j1x, "lon");
+ splitAndAssign(vLine[12], "Rx Pwr", j1x, "rxPwr");
+ splitAndAssign(vLine[13], "Rx Ec/Io", j1x, "rxEcIo");
+ splitAndAssign(vLine[14], "Rx FER", j1x, "rxFer");
+ splitAndAssign(vLine[15], "Tx Pwr", j1x, "txPwr");
+ splitAndAssign(vLine[16], "Active Set", j1x, "activeSet");
+ splitAndAssign(vLine[17], "Neighbor Set", j1x, "neighborSet");
+ } else if(vLine[0] == "EVDO Engineering") {
+ Json::Value& jEvdo = jDebug["evdo"];
+ splitAndAssign(vLine[1], "State", jEvdo, "state");
+ splitAndAssign(vLine[2], "Mac Index", jEvdo, "macIndex");
+ splitAndAssign(vLine[3], "Channel", jEvdo, "channel");
+ splitAndAssign(vLine[4], "Color Code", jEvdo, "colorCode");
+ splitAndAssign(vLine[5], "Sector ID", jEvdo, "sectorId");
+ splitAndAssign(vLine[6], "PN", jEvdo, "pn");
+ splitAndAssign(vLine[7], "Rx Pwr", jEvdo, "rxPwr");
+ splitAndAssign(vLine[8], "Rx PER", jEvdo, "rxPer");
+ splitAndAssign(vLine[9], "Pilot Energy", jEvdo, "pilotEnergy");
+ splitAndAssign(vLine[10], "DRC", jEvdo, "drc");
+ splitAndAssign(vLine[11], "SINR", jEvdo, "sinr");
+ splitAndAssign(vLine[12], "AN-AAA", jEvdo, "anAaa");
+ splitAndAssign(vLine[13], "IP Address", jEvdo, "ipAddress");
+ } else if(vLine[0] == "Configuration") {
+ Json::Value& jConf = jDebug["configuration"];
+ splitAndAssign(vLine[1], "Technology", jConf, "technology");
+ splitAndAssign(vLine[2], "1x Diversity", jConf, "1xDiversity");
+ splitAndAssign(vLine[3], "EVDO Diversity", jConf, "evdoDiversity");
+ splitAndAssign(vLine[4], "QLIC", jConf, "qlic");
+ splitAndAssign(vLine[5], "PRL", jConf, "prl");
+ splitAndAssign(vLine[6], "Chipset", jConf, "chipset");
+ splitAndAssign(vLine[7], "AMSS version", jConf, "amssVersion");
+ splitAndAssign(vLine[8], "Device version", jConf, "deviceVersion");
+ splitAndAssign(vLine[9], "Hardware version", jConf, "hardwareVersion");
+ splitAndAssign(vLine[10], "Browser", jConf, "browser");
+ splitAndAssign(vLine[11], "Multimedia Version", jConf, "multimediaVersion");
+ }
+ }
+
+ } else {
+ printDebug("%s| SPRINT Network Status command returned unexpected response: [%s][%s]", getName().c_str(), sCmd.c_str(), sResult.c_str());
+ }
+ }
+
+
+ printTrace("%s| Network Status:\n%s\n", getName().c_str(), jData.toStyledString().c_str());
+
+ return SUCCESS;
+}
+
+std::string CdmaRadio::getMeidLastSix() {
+ std::string sMeid;
+ if(getMeid(sMeid) != SUCCESS || sMeid.size() != 14) {
+ return "";
+ }
+ return sMeid.substr(8);
+}
diff --git a/src/MTS_IO_CellularRadio.cpp b/src/MTS_IO_CellularRadio.cpp
new file mode 100644
index 0000000..adea939
--- /dev/null
+++ b/src/MTS_IO_CellularRadio.cpp
@@ -0,0 +1,1522 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_CellularRadio.cpp
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+/*!
+ \file MTS_CELL_CellularRadio.cpp
+ \brief A brief description
+ \date Nov 4, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_CellularRadio.h>
+#include <mts/MTS_IO_MccMncTable.h>
+#include <mts/MTS_Thread.h>
+#include <mts/MTS_Timer.h>
+#include <mts/MTS_Logger.h>
+#include <mts/MTS_Text.h>
+#include <map>
+#include <cstring>
+#include <sstream>
+#include <sys/file.h>
+#include <errno.h>
+#include <unistd.h>
+
+
+using namespace MTS::IO;
+
+const char CellularRadio::ETX = 0x03; //Ends socket connection
+const char CellularRadio::DLE = 0x10; //Escapes ETX and DLE within Payload
+const char CellularRadio::CR = 0x0D;
+const char CellularRadio::NL = 0x0A;
+const char CellularRadio::CTRL_Z = 0x1A;
+
+const std::string CellularRadio::RSP_ERROR("ERROR");
+const std::string CellularRadio::RSP_OK("OK");
+
+
+const std::string CellularRadio::DEFAULT_RADIO_PORT("/dev/modem_at1");
+const std::string CellularRadio::DEFAULT_RADIO_DIR("/var/run/radio/");
+const std::string CellularRadio::VALUE_UNKNOWN("Unknown");
+const std::string CellularRadio::VALUE_UNAVAILABLE("Unavailable");
+const std::string CellularRadio::VALUE_NOT_SUPPORTED("Not Supported");
+
+const std::string CellularRadio::VALUE_NOT_REGISTERED("NOT REGISTERED");
+const std::string CellularRadio::VALUE_REGISTERED("REGISTERED");
+const std::string CellularRadio::VALUE_SEARCHING("SEARCHING");
+const std::string CellularRadio::VALUE_DENIED("DENIED");
+const std::string CellularRadio::VALUE_ROAMING("ROAMING");
+
+//Static Data
+const std::string CellularRadio::KEY_TYPE("type"); //!< GSM or CDMA
+const std::string CellularRadio::KEY_CODE("code"); //!< Product Code : H5, H6, C2, EV3, G3
+const std::string CellularRadio::KEY_MODEL("model"); //!< Model : HE910, LE910, CE910, DE910, GE910
+const std::string CellularRadio::KEY_MANUFACTURER("manufacturer"); //!< Manufacturer: Telit
+const std::string CellularRadio::KEY_HARDWARE("hardware"); //!< Radio Hardware Version
+const std::string CellularRadio::KEY_FIRMWARE("firmware"); //!< Radio Firmware Version
+
+const std::string CellularRadio::KEY_CARRIER("carrier"); //!< Cellular Service Provider (Home Network)
+const std::string CellularRadio::VALUE_CARRIER_VERIZON("Verizon");
+const std::string CellularRadio::VALUE_CARRIER_AERIS("Aeris");
+const std::string CellularRadio::VALUE_CARRIER_SPRINT("Sprint");
+const std::string CellularRadio::VALUE_CARRIER_ATT("AT&T");
+const std::string CellularRadio::VALUE_CARRIER_TMOBILE("T-Mobile");
+
+const std::string CellularRadio::KEY_IMEI("imei"); //!< International Mobile Station Equipment Identity
+const std::string CellularRadio::KEY_MEID("meid"); //!< Mobile Equipment Identifier
+const std::string CellularRadio::KEY_IMSI("imsi"); //!< International Mobile Subscriber Identity
+const std::string CellularRadio::KEY_MSID("msid"); //!< Mobil Station ID / Mobile Identification Number (MSID/MIN) (CDMA-Only)
+const std::string CellularRadio::KEY_MDN("mdn"); //!< Mobile Directory Number : Actual phone number dialed to reach radio
+const std::string CellularRadio::KEY_ICCID("iccid"); //!< Integrated Circuit Card Identifier
+const std::string CellularRadio::KEY_MSL("msl"); //!< Master Subsidy Lock
+
+//Dynamic Data
+const std::string CellularRadio::KEY_ROAMING("roaming"); //!< Indicates whether or not using Home Network
+const std::string CellularRadio::KEY_DATETIME("datetime"); //!< Date and Time from tower
+const std::string CellularRadio::KEY_SERVICE("service"); //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO]
+const std::string CellularRadio::KEY_NETWORK("network"); //!< Cellular Service Provider
+const std::string CellularRadio::KEY_CID("cid"); //!< Cellular ID (Tower) in HEX
+const std::string CellularRadio::KEY_LAC("lac"); //!< Location Area Code in HEX
+const std::string CellularRadio::KEY_RAC("rac"); //!< Routing Area Code in HEX
+const std::string CellularRadio::KEY_RSSI("rssi"); //!< Signal Strength
+const std::string CellularRadio::KEY_RSSIDBM("rssidBm"); //!< Signal Strength in dBm
+const std::string CellularRadio::KEY_MCC("mcc"); //!< Country Code
+const std::string CellularRadio::KEY_MNC("mnc"); //!< Operator Code
+const std::string CellularRadio::KEY_CHANNEL("channel"); //!< ARFCN or UARFCN Assigned Radio Channel
+const std::string CellularRadio::KEY_TXPWR("txpwr"); //!< Transmit Power
+const std::string CellularRadio::KEY_PSC("psc"); //!< Active Primary Synchronization Code (PSC)
+const std::string CellularRadio::KEY_ECIO("ecio"); //!< Active Ec/Io (chip energy per total wideband power in dBm)
+const std::string CellularRadio::KEY_RSCP("rscp"); //!< Active RSCP (Received Signal Code Power in dBm)
+const std::string CellularRadio::KEY_DRX("drx"); //!< Discontinuous reception cycle length (ms)
+const std::string CellularRadio::KEY_MM("mm"); //!< Mobility Management State
+const std::string CellularRadio::KEY_RR("rr"); //!< Radio Resource State
+const std::string CellularRadio::KEY_NOM("nom"); //!< Network Operator Mode
+const std::string CellularRadio::KEY_ABND("abnd"); //!< Active Band
+const std::string CellularRadio::KEY_BLER("bler"); //!< Block Error Rate (percentage)
+const std::string CellularRadio::KEY_SD("sd"); //!< Service Domain
+const std::string CellularRadio::KEY_DEBUG("debug"); //!< Debug Information
+
+const std::string CellularRadio::KEY_MIP("mipProfile"); //!< Mobile IP Information
+const std::string CellularRadio::KEY_MIP_ID("id"); //!< Mobile IP ID
+const std::string CellularRadio::KEY_MIP_ENABLED("enabled"); //!< Mobile IP Enabled/Disabled
+const std::string CellularRadio::KEY_MIP_NAI("nai"); //!< Network Access Identifier
+const std::string CellularRadio::KEY_MIP_HOMEADDRESS("homeAddress"); //!< Home Address
+const std::string CellularRadio::KEY_MIP_PRIMARYHA("primaryAddress"); //!< Primary Home Agent
+const std::string CellularRadio::KEY_MIP_SECONDARYHA("secondaryAddress"); //!< Secondary Home Agent
+const std::string CellularRadio::KEY_MIP_MNAAASPI("mnAaaSpi"); //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index
+const std::string CellularRadio::KEY_MIP_MNHASPI("mnHaSpi"); //!< Mobile Node Home Agent Security Server Parameter Index
+const std::string CellularRadio::KEY_MIP_REVTUN("revTun"); //!< Reverse Tunneling Enabled
+const std::string CellularRadio::KEY_MIP_MNAAASS("mnAaaSs"); //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret
+const std::string CellularRadio::KEY_MIP_MNHASS("mnHaSs"); //!< Mobile Node Home Agent Shared Secret
+
+const std::string CellularRadio::VALUE_TYPE_GSM("GSM");
+const std::string CellularRadio::VALUE_TYPE_LTE("LTE");
+const std::string CellularRadio::VALUE_TYPE_CDMA("CDMA");
+
+const std::string CellularRadio::VALUE_SD_NO_SERVICE("NO SERVICE");
+const std::string CellularRadio::VALUE_SD_CS_ONLY("CS ONLY");
+const std::string CellularRadio::VALUE_SD_PS_ONLY("PS ONLY");
+const std::string CellularRadio::VALUE_SD_CSPS("CS+PS");
+
+const std::string CellularRadio::VALUE_ABND_GSM_850("GSM 850");
+const std::string CellularRadio::VALUE_ABND_GSM_900("GSM 900");
+const std::string CellularRadio::VALUE_ABND_DCS_1800("DCS 1800");
+const std::string CellularRadio::VALUE_ABND_PCS_1900("PCS 1900");
+
+const std::vector<std::string> CellularRadio::DEFAULT_BAIL_STRINGS = { CellularRadio::RSP_OK, CellularRadio::RSP_ERROR };
+
+CellularRadio::CellularRadio(const std::string& sName, const std::string& sRadioPort)
+: m_sName(sName)
+, m_sRadioPort(sRadioPort)
+, m_bEchoEnabled(false)
+, m_bEnableEchoOnClose(false)
+{
+ m_apIo.reset(new MTS::IO::SerialConnection(
+ MTS::IO::SerialConnection::Builder(m_sRadioPort)
+ .baudRate(115200)
+ .useLockFile()
+ .build()));
+}
+
+
+CellularRadio::~CellularRadio() {
+ shutdown();
+ m_apIo.reset();
+}
+
+bool CellularRadio::initialize(uint32_t iTimeoutMillis) {
+ if(!m_apIo->open(iTimeoutMillis)) {
+ printError("%s| Failed to open radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str());
+ return false;
+ }
+
+ bool bEnabled;
+ CODE eCode = getEcho(bEnabled);
+ if(eCode == SUCCESS && bEnabled) {
+ printDebug("%s| Disabling 'echo'", m_sName.c_str());
+ setEcho(false);
+ m_bEnableEchoOnClose = true;
+ }
+
+ return true;
+}
+
+bool CellularRadio::resetRadio(uint32_t iTimeoutMillis) {
+
+ printInfo("%s| Rebooting radio", m_sName.c_str());
+ if(sendBasicCommand("AT#REBOOT") == SUCCESS) {
+ if(iTimeoutMillis > 5000) {
+ MTS::Thread::sleep(5000);
+ iTimeoutMillis -= 5000;
+ }
+ return resetConnection(iTimeoutMillis);
+ }
+
+ return false;
+}
+
+bool CellularRadio::resetConnection(uint32_t iTimeoutMillis) {
+ //Close Current Connection
+ if(!m_apIo.isNull()) {
+ m_apIo->close();
+ }
+
+ m_apIo.reset(new MTS::IO::SerialConnection(
+ MTS::IO::SerialConnection::Builder(m_sRadioPort)
+ .baudRate(115200)
+ .useLockFile()
+ .build()));
+
+ //Try to obtain the device port over the given period of time
+ MTS::Timer oTimer;
+ oTimer.start();
+ uint64_t iCurrentTime = 0;
+ while(iCurrentTime < iTimeoutMillis) {
+
+ if(!m_apIo->open(iTimeoutMillis - iCurrentTime)) {
+ printWarning("%s| Failed to re-open radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str());
+ } else {
+ printInfo("%s| Successfully re-opened radio port [%s]", m_sName.c_str(), m_sRadioPort.c_str());
+ break;
+ }
+
+ ::usleep(500000); //500 millis
+ iCurrentTime = oTimer.getMillis();
+ }
+ oTimer.stop();
+ return !m_apIo->isClosed();
+}
+
+void CellularRadio::shutdown() {
+
+ if(!m_apIo.isNull()) {
+ if(m_bEnableEchoOnClose) {
+ printDebug("%s| Enabling 'echo'", m_sName.c_str());
+ setEcho(true);
+ m_bEnableEchoOnClose = false;
+ }
+ m_apIo->close();
+ }
+}
+
+const std::string& CellularRadio::getName() const {
+ return m_sName;
+}
+
+
+CellularRadio::CODE CellularRadio::getModel(std::string& sModel) {
+ printTrace("%s| Get Model", m_sName.c_str());
+ //Always returns SUCCESS because the model should be m_sName
+ sModel = m_sName;
+ std::string sCmd("ATI4");
+ std::string sResult = CellularRadio::sendCommand(m_apIo, sCmd);
+ if (sResult.find("OK") == std::string::npos) {
+ printWarning("%s| Unable to get model from radio. Returning [%s]", m_sName.c_str(), m_sName.c_str());
+ return SUCCESS;
+ } else {
+ sModel = CellularRadio::extractModelFromResult(sResult);
+ if(sModel.size() == 0) {
+ printWarning("%s| Unable to get model from radio. Returning [%s]", m_sName.c_str(), m_sName.c_str());
+ return SUCCESS;
+ }
+ }
+
+ printDebug("%s| Extracted [%s] from [%s] query", m_sName.c_str(), sModel.c_str(), sCmd.c_str());
+ if(sModel != m_sName) {
+ printWarning("%s| Model identified [%s] does not match expected [%s]. Returning [%s]",
+ m_sName.c_str(), sModel.c_str(), m_sName.c_str(), sModel.c_str());
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::convertModelToMtsShortCode(const std::string& sModel, std::string& sCode) {
+ CODE eCode = FAILURE;
+
+ if(sModel.find("HE910-D") == 0) {
+ sCode = "H5";
+ eCode = SUCCESS;
+ } else if (sModel.find("HE910-EUD") == 0) {
+ sCode = "H6";
+ eCode = SUCCESS;
+ } else if (sModel.find("LE910-NAG") == 0) {
+ sCode = "LAT1";
+ eCode = SUCCESS;
+ } else if (sModel.find("LE910-SVG") == 0) {
+ sCode = "VW2";
+ eCode = SUCCESS;
+ } else if (sModel.find("LE910-EUG") == 0) {
+ sCode = "LEU1";
+ eCode = SUCCESS;
+ } else if (sModel.find("GE910") == 0) {
+ sCode = "G3";
+ eCode = SUCCESS;
+ } else if (sModel.find("CE910") == 0) {
+ sCode = "C2";
+ eCode = SUCCESS;
+ } else if (sModel.find("DE910") == 0) {
+ sCode = "EV3";
+ eCode = SUCCESS;
+ } else {
+ sCode = VALUE_NOT_SUPPORTED;
+ printError("RADIO| Could not identify MTS short code from model. [%s]", sModel.c_str());
+ eCode = ERROR;
+ }
+ return eCode;
+}
+
+CellularRadio::CODE CellularRadio::convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd) {
+ CODE eCode = FAILURE;
+ switch(eSd) {
+ case NO_SERVICE: sSd = VALUE_SD_NO_SERVICE; eCode = SUCCESS; break;
+ case CS_ONLY: sSd = VALUE_SD_CS_ONLY; eCode = SUCCESS; break;
+ case PS_ONLY: sSd = VALUE_SD_PS_ONLY; eCode = SUCCESS; break;
+ case CSPS: sSd = VALUE_SD_CSPS; eCode = SUCCESS; break;
+ default: sSd = VALUE_UNKNOWN; eCode = FAILURE; break;
+ }
+ return eCode;
+}
+
+CellularRadio::CODE CellularRadio::convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand) {
+ CODE eCode = FAILURE;
+ switch(eBand) {
+ case GSM_850: sBand = VALUE_ABND_GSM_850; eCode = SUCCESS; break;
+ case GSM_900: sBand = VALUE_ABND_GSM_900; eCode = SUCCESS; break;
+ case DCS_1800: sBand = VALUE_ABND_DCS_1800; eCode = SUCCESS; break;
+ case PCS_1900: sBand = VALUE_ABND_PCS_1900; eCode = SUCCESS; break;
+ default: sBand = VALUE_UNKNOWN; eCode = FAILURE; break;
+ }
+ return eCode;
+}
+
+CellularRadio::CODE CellularRadio::convertModelToType(const std::string& sModel, std::string& sType) {
+ CODE eCode = FAILURE;
+ sType = VALUE_NOT_SUPPORTED;
+
+ if(sModel.find("HE910-D") == 0) {
+ sType = VALUE_TYPE_GSM;
+ eCode = SUCCESS;
+ } else if (sModel.find("HE910-EUD") == 0) {
+ sType = VALUE_TYPE_GSM;
+ eCode = SUCCESS;
+ } else if (sModel.find("LE910-NAG") == 0) {
+ sType = VALUE_TYPE_LTE;
+ eCode = SUCCESS;
+ } else if (sModel.find("LE910-SVG") == 0) {
+ sType = VALUE_TYPE_LTE;
+ eCode = SUCCESS;
+ } else if (sModel.find("LE910-EUG") == 0) {
+ sType = VALUE_TYPE_LTE;
+ eCode = SUCCESS;
+ } else if (sModel.find("GE910") == 0) {
+ sType = VALUE_TYPE_GSM;
+ eCode = SUCCESS;
+ } else if (sModel.find("CE910") == 0) {
+ sType = VALUE_TYPE_CDMA;
+ eCode = SUCCESS;
+ } else if (sModel.find("DE910") == 0) {
+ sType = VALUE_TYPE_CDMA;
+ eCode = SUCCESS;
+ } else {
+ sType = VALUE_TYPE_GSM;
+ eCode = ERROR;
+ printError("RADIO| Could not identify type from model. [%s]. Assuming [%s]", sModel.c_str(), sType.c_str());
+ }
+ return eCode;
+}
+
+CellularRadio::CODE CellularRadio::getFirmware(std::string& sFirmware) {
+ printTrace("%s| Get Firmware", m_sName.c_str());
+ sFirmware = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+CGMR");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t pos = sResult.find(RSP_OK);
+ if (pos == std::string::npos) {
+ printWarning("%s| Unable to get firmware from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ sFirmware = MTS::Text::trim(sResult.substr(0, pos));
+ if(sFirmware.size() == 0) {
+ printWarning("%s| Unable to get firmware from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ m_sFirmware = sFirmware;
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getHardware(std::string& sHardware) {
+ printTrace("%s| Get Hardware", m_sName.c_str());
+ sHardware = VALUE_NOT_SUPPORTED;
+
+ if(m_sFirmware.size() == 0) {
+ getFirmware(m_sFirmware);
+ }
+
+ if(getHardwareVersionFromFirmware(m_sFirmware, sHardware)) {
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getManufacturer(std::string& sManufacturer) {
+ printTrace("%s| Get Manufacturer", m_sName.c_str());
+ sManufacturer = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+GMI");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t pos = sResult.find(RSP_OK);
+ if (pos == std::string::npos) {
+ printWarning("%s| Unable to get manufacturer from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ sManufacturer = MTS::Text::trim(sResult.substr(0, pos));
+ if(sManufacturer.size() == 0) {
+ printWarning("%s| Unable to get manufacturer from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getImei(std::string& sImei) {
+ printTrace("%s| Get IMEI", m_sName.c_str());
+ sImei = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+CGSN");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t pos = sResult.find(RSP_OK);
+ if (pos == std::string::npos) {
+ printWarning("%s| Unable to get IMEI from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ sImei = MTS::Text::trim(sResult.substr(0, pos));
+ if(sImei.size() == 0) {
+ printWarning("%s| Unable to get IMEI from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getMeid(std::string& sMeid) {
+ printTrace("%s| Get MEID", m_sName.c_str());
+ return getImei(sMeid);
+}
+
+CellularRadio::CODE CellularRadio::getImsi(std::string& sImsi) {
+ printTrace("%s| Get IMSI", m_sName.c_str());
+ sImsi = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+CIMI");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t pos = sResult.find(RSP_OK);
+ if (pos == std::string::npos) {
+ printWarning("%s| Unable to get IMSI from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ sImsi = MTS::Text::trim(sResult.substr(0, pos));
+ if(sImsi.size() == 0) {
+ printWarning("%s| Unable to get IMSI from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getSimStatus(std::string& sSimStatus) {
+ printTrace("%s| Get SIM Status", getName().c_str());
+ sSimStatus = VALUE_UNKNOWN;
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getIccid(std::string& sIccid) {
+ printTrace("%s| Get ICCID", m_sName.c_str());
+ sIccid = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT#CCID");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to get ICCID from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find("#CCID:");
+ if(start != std::string::npos) {
+ start += sizeof("#CCID:");
+ sIccid = MTS::Text::trim(sResult.substr(start, end-start));
+ if(sIccid.size() == 0) {
+ printWarning("%s| Unable to get ICCID from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+ }
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getService(std::string& sService) {
+ printTrace("%s| Get Service", m_sName.c_str());
+ sService = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT#PSNT?");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to get Service from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find(",");
+ if(start != std::string::npos) {
+ start += 1; //comma
+ std::string sPsnt = MTS::Text::trim(sResult.substr(start, end-start));
+ int32_t iService;
+ sscanf(sPsnt.c_str(), "%d", &iService);
+
+ switch(iService) {
+ case 0: sService = "GPRS"; break;
+ case 1: sService = "EGPRS"; break;
+ case 2: sService = "WCDMA"; break;
+ case 3: sService = "HSDPA"; break;
+ default: sService = VALUE_UNKNOWN; break;
+ }
+
+ printDebug("%s| Service ID: [%d][%s]", m_sName.c_str(), iService, sService.c_str());
+ }
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getLac(std::string& sLac) {
+ Json::Value jData;
+
+ printTrace("%s| Get LAC", m_sName.c_str());
+ sLac = VALUE_NOT_SUPPORTED;
+
+ if(getNetworkStatus(jData) == SUCCESS) {
+ if(jData.isMember(KEY_LAC)) {
+ sLac = jData[KEY_LAC].asString();
+ return SUCCESS;
+ }
+ }
+
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getMdn(std::string& sMdn) {
+ printTrace("%s| Get MDN", m_sName.c_str());
+ sMdn = VALUE_NOT_SUPPORTED;
+ std::string sCmd("AT+CNUM");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to get MDN from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find("CNUM:");
+ if(start != std::string::npos) {
+ start += sizeof("CNUM:");
+ std::vector<std::string> vParts = MTS::Text::split(sResult.substr(start, end - start), ',');
+ if(vParts.size() != 3) {
+ printWarning("%s| Unable to parse MDN from response [%s]", m_sName.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+ sMdn = MTS::Text::strip(vParts[1], '"');
+ if(sMdn.size() == 0) {
+ printWarning("%s| Unable to get MDN from radio using command [%s]. MDN may not be set.", m_sName.c_str(), sCmd.c_str());
+ }
+ } else {
+ sMdn = "";
+ printWarning("%s| Unable to get MDN from radio using command [%s]. MDN may not be set.", m_sName.c_str(), sCmd.c_str());
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getMsid(std::string& sMsid) {
+ printTrace("%s| Get MSID", m_sName.c_str());
+ sMsid = "";
+
+ std::string sImsi;
+ if(getImsi(sImsi) == SUCCESS) {
+ if(sImsi.size() >= 10) {
+ sMsid = sImsi.substr(sImsi.size() - 10);
+ printTrace("IMSI: [%s] MEID [%s]", sImsi.c_str(), sMsid.c_str());
+ return SUCCESS;
+ }
+ }
+ printWarning("%s| Unable to get MSID from radio", m_sName.c_str());
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getType(std::string& sType) {
+ printTrace("%s| Get Type", m_sName.c_str());
+ sType = VALUE_NOT_SUPPORTED;
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getCarrier(std::string& sCarrier) {
+ printTrace("%s| Get Carrier", m_sName.c_str());
+ if(m_sCarrier == "") {
+ Json::Value jData;
+ if(getNetworkStatus(jData) == SUCCESS) {
+ if(jData.isMember(KEY_MCC) && jData.isMember(KEY_MNC)) {
+ std::string sMcc = jData[KEY_MCC].asString();
+ std::string sMnc = jData[KEY_MNC].asString();
+ Json::Value jLookup = MccMncTable::getInstance()->lookup(sMcc, sMnc);
+ printTrace("%s| MCC-MNC Lookup: [%s][%s][%s]", m_sName.c_str(),
+ sMcc.c_str(), sMnc.c_str(), jLookup.toStyledString().c_str());
+ if(jLookup.isMember(KEY_CARRIER)) {
+ m_sCarrier = jLookup[KEY_CARRIER].asString();
+ } else {
+ printWarning("%s| MCC-MNC Lookup did not contain carrier", m_sName.c_str());
+ return FAILURE;
+ }
+ } else {
+ printWarning("%s| Network Status did no contain MCC or MNC", m_sName.c_str());
+ return FAILURE;
+ }
+ } else {
+ return FAILURE;
+ }
+ }
+
+ sCarrier = m_sCarrier;
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getTower(std::string& sTower) {
+ Json::Value jData;
+
+ printTrace("%s| Get Tower", m_sName.c_str());
+ sTower = VALUE_NOT_SUPPORTED;
+
+ if(getNetworkStatus(jData) == SUCCESS) {
+ if(jData.isMember(KEY_CID)) {
+ sTower = jData[KEY_CID].asString();
+ return SUCCESS;
+ }
+ }
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) {
+ Json::Value jData;
+
+ printTrace("%s| Get Time", m_sName.c_str());
+ sDate = "";
+ sTime = "";
+ sTimeZone = "";
+
+ std::string sCmd("AT+CCLK?");
+ std::string sResult = CellularRadio::sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to get Time from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find("CCLK: ");
+ if(start != std::string::npos) {
+ start += sizeof("CCLK: ");
+ std::string sValue = MTS::Text::trim(sResult.substr(start, end - start));
+ sValue = MTS::Text::strip(sValue, '"');
+
+ std::vector<std::string> vParts = MTS::Text::split(sValue, ',');
+ if(vParts.size() != 2) {
+ printWarning("%s| Unable to parse Date from response [%s]", m_sName.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+
+ std::vector<std::string> vDateParts = MTS::Text::split(vParts[0], '/');
+ if(vDateParts.size() != 3) {
+ printWarning("%s| Unable to parse Date from response [%s]", m_sName.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ //The Date format is YY/MM/DD -> Change to MM/DD/YY
+ sDate = vDateParts[1] + "/" + vDateParts[2] + "/" + vDateParts[0];
+
+ vParts = MTS::Text::split(vParts[1], '-');
+ if(vParts.size() != 2) {
+ printWarning("%s| Unable to parse Time from response [%s]", m_sName.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+ sTime = vParts[0];
+
+ int32_t iZoneUnits; //the difference, expressed in quarters of an hour, between the local time and GMT
+ if(!MTS::Text::parse(iZoneUnits, MTS::Text::strip(vParts[1], '+'))) {
+ printWarning("%s| Unable to parse Time Zone from response [%s]", m_sName.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ int32_t iZone = iZoneUnits/4; //Divide by 4 to get hours difference
+ int32_t iZonePartial = (iZoneUnits % 4) * 15; //Remainder in minutes
+ std::string sPlusSign = "+";
+ if(iZonePartial < 0) {
+ //Remove negative sign from partial and clear plus sign component
+ iZonePartial *= -1;
+ sPlusSign = "";
+ }
+ std::stringstream ss;
+ ss << sPlusSign << iZone;
+ if(iZonePartial != 0) {
+ ss << ":" << iZonePartial;
+ }
+
+ sTimeZone = ss.str();
+ return SUCCESS;
+
+ } else {
+ printWarning("%s| Unable to get Time from radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ }
+
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getRoaming(bool& bRoaming) {
+ Json::Value jData;
+
+ printTrace("%s| Get Roaming", m_sName.c_str());
+ bRoaming = false;
+
+ REGISTRATION eReg;
+ if(getRegistration(eReg) == SUCCESS) {
+ bRoaming = (eReg == ROAMING);
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getNetwork(std::string& sNetwork) {
+ Json::Value jData;
+
+ printTrace("%s| Get Network", m_sName.c_str());
+ sNetwork = VALUE_NOT_SUPPORTED;
+
+ if(getNetworkStatus(jData) == SUCCESS) {
+ if(jData.isMember(KEY_NETWORK)) {
+ sNetwork = jData[KEY_NETWORK].asString();
+ return SUCCESS;
+ }
+ }
+ return FAILURE;
+}
+
+CellularRadio::CODE CellularRadio::getSignalStrength(int32_t& rssi) {
+ printTrace("%s| Get Signal Strength", m_sName.c_str());
+ std::string sCmd("AT+CSQ");
+ std::string sResult = sendCommand(sCmd);
+ if (sResult.find("+CSQ: ") == std::string::npos) {
+ printDebug("%s| Signal Strength command returned unexpected response: [%s]", m_sName.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find(':');
+ size_t stop = sResult.find(',', start);
+ if(start == std::string::npos || stop == std::string::npos) {
+ printDebug("%s| Signal Strength command returned malformed response: [%s]", m_sName.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+ std::string signal = sResult.substr(start + 2, stop - start - 2);
+
+ sscanf(signal.c_str(), "%d", &rssi);
+ printDebug("%s| Signal Strength: [%d]", m_sName.c_str(), rssi);
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& iDbm) {
+
+ //Telit Conversion
+ if(iRssi < 0 || iRssi == 99) {
+ return FAILURE;
+ }
+
+ if(iRssi == 0) {
+ iDbm = -113;
+ } else if(iRssi == 1) {
+ iDbm = -111;
+ } else if(iRssi <= 30) {
+ //28 steps between 2 and 30
+ //54 dbm between 53 and 109
+ float stepSize = 54.0 / 28.0;
+ iDbm = -109 + (int)(stepSize * (iRssi-2));
+ } else {
+ iDbm = -51;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::convertdBmToSignalStrength(const int32_t& iDBm, int32_t& iRssi) {
+ //Telit Conversion
+ if(iDBm <= -113) {
+ iRssi = 0;
+ } else if(iDBm <= -111) {
+ iRssi = 1;
+ } else if(iDBm <= -53) {
+ //54 dbm between -109 and -53
+ //28 steps between 2 and 30
+ float stepSize = 28.0/54.0;
+ iRssi = ((iDBm + 109)*stepSize) + 2;
+ } else {
+ iRssi = 31;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::getEcho(bool& bEnabled) {
+ printTrace("%s| Echo Test", m_sName.c_str());
+ std::string sResult = sendCommand("AT");
+ if(sResult.size() == 0) {
+ return NO_RESPONSE;
+ }
+
+ if(sResult.find("AT") != std::string::npos) {
+ bEnabled = true;
+ } else {
+ bEnabled = false;
+ }
+ m_bEchoEnabled = bEnabled;
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::setEcho(bool bEnabled) {
+ CODE eCode = FAILURE;
+ if(bEnabled) {
+ eCode = sendBasicCommand("ATE1");
+ m_bEchoEnabled = (eCode == SUCCESS ) ? true : m_bEchoEnabled;
+ } else {
+ eCode = sendBasicCommand("ATE0");
+ m_bEchoEnabled = (eCode == SUCCESS ) ? false : m_bEchoEnabled;
+ }
+
+ return eCode;
+}
+
+CellularRadio::CODE CellularRadio::getStaticInformation(Json::Value& jData) {
+ printTrace("%s| Get Static Information", m_sName.c_str());
+
+ printTrace("%s| Static Information:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str());
+
+ return FAILURE;
+}
+
+/* AT#RFSTS - NETWORK STATUS
+
+ (GSM network)
+ #RFSTS:<PLMN>,<ARFCN>,<RSSI>,<LAC>,<RAC>,<TXPWR>,<MM>,<RR>,<NOM>,<CID>,<IMSI>,<NetNameAsc>,<SD>,<ABND>
+ Where:
+ <PLMN> - Country code and operator code(MCC, MNC)
+ <ARFCN> - GSM Assigned Radio Channel
+ <RSSI> - Received Signal Strength Indication
+ <LAC> - Localization Area Code
+ <RAC> - Routing Area Code
+ <TXPWR> - Tx Power
+ <MM> - Mobility Management state
+ <RR> - Radio Resource state
+ <NOM> - Network Operator Mode
+ <CID> - Cell ID
+ <IMSI> - International Mobile Subscriber Identity
+ <NetNameAsc> - Operator name
+ <SD> - Service Domain
+ 0 - No Service
+ 1 - CS only
+ 2 - PS only
+ 3 - CS+PS
+ <ABND> - Active Band
+ 1 - GSM 850
+ 2 - GSM 900
+ 3 - DCS 1800
+ 4 - PCS 1900
+
+
+ (WCDMA network)
+ #RFSTS:
+ <PLMN>,<UARFCN>,<PSC>,<Ec/Io>,<RSCP>, RSSI>,<LAC>,<RAC>,<TXPWR>,<DRX>,<MM>,<RRC>,<NOM>,<BLER>,<CID>,<IMSI>,
+ <NetNameAsc>,<SD>,<nAST>[,<nUARFCN><nPSC>,<nEc/Io>]
+ Where:
+ <PLMN> - Country code and operator code(MCC, MNC)
+ <UARFCN> - UMTS Assigned Radio Channel
+ <PSC> - Active PSC(Primary Synchronization Code)
+ <Ec/Io> - Active Ec/Io(chip energy per total wideband power in dBm)
+ <RSCP> - Active RSCP (Received Signal Code Power in dBm)
+ <RSSI> - Received Signal Strength Indication
+ <LAC> - Localization Area Code
+ <RAC> - Routing Area Code
+ <TXPWR> - Tx Power
+ <DRX> - Discontinuous reception cycle Length (cycle length in ms)
+ <MM> - Mobility Management state
+ <RR> - Radio Resource state
+ <NOM> - Network Operator Mode
+ <BLER> - Block Error Rate (e.g., 005 means 0.5 %)
+ <CID> - Cell ID
+ <IMSI> - International Mobile Station ID
+ <NetNameAsc> - Operator name
+ <SD> - Service Domain (see above)
+ <nAST> - Number of Active Set (Maximum 6)
+ <nUARFCN> UARFCN of n th active set
+ <nPSC> PSC of n th active set
+ <nEc/Io > Ec/Io of n th active Set
+
+ (LTE Network)
+ #RFSTS:
+ <PLMN> -
+ <EARFCN> -
+ <RSRP> -
+ <RSSI> -
+ <RSRQ> -
+ <TAC> -
+ [<TXPWR>] -
+ <DRX> -
+ <MM> -
+ <RRC> -
+ <CID> -
+ <IMSI> -
+ [<NetNameAsc>] -
+ <SD> -
+ <ABND> -
+*/
+CellularRadio::CODE CellularRadio::getNetworkStatus(Json::Value& jData) {
+ int32_t iValue;
+ std::string sValue;
+ const uint32_t GSM_NETWORK_FORMAT = 14;
+ const uint32_t WCDMA_NETWORK_FORMAT = 19;
+ const uint32_t LTE_NETWORK_FORMAT = 16;
+
+ printTrace("%s| Get Network Status", m_sName.c_str());
+ std::string sCmd("AT#RFSTS");
+ std::string sResult = sendCommand(sCmd);
+ if (sResult.find("#RFSTS:") == std::string::npos) {
+ printDebug("%s| Network Status command returned unexpected response: [%s][%s]", m_sName.c_str(), sCmd.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find(":") + 1; //Position right after "#RFSTS:"
+ std::vector<std::string> vParts = MTS::Text::split(MTS::Text::trim(sResult.substr(start)), ",");
+
+ if(vParts.size() >= 3) {
+ //Country Code and Operator Code
+ std::vector<std::string> vPLMN = MTS::Text::split(vParts[0], ' ');
+ if(vPLMN.size() == 2) {
+ jData[KEY_MCC] = MTS::Text::strip(vPLMN[0], '"');
+ jData[KEY_MNC] = MTS::Text::strip(vPLMN[1], '"');
+ }
+
+ jData[KEY_CHANNEL] = vParts[1];
+ } else {
+ //Unknown Format
+ return FAILURE;
+ }
+
+ if(vParts.size() == GSM_NETWORK_FORMAT ) {
+ //Parse as GSM Network Format
+ jData[KEY_RSSIDBM] = vParts[2];
+ jData[KEY_LAC] = vParts[3];
+ jData[KEY_RAC] = vParts[4];
+ jData[KEY_TXPWR] = vParts[5];
+ jData[KEY_MM] = vParts[6];
+ jData[KEY_RR] = vParts[7];
+ jData[KEY_NOM] = vParts[8];
+ jData[KEY_CID] = vParts[9];
+ jData[KEY_IMSI] = MTS::Text::strip(vParts[10], '"');
+ jData[KEY_NETWORK] = MTS::Text::strip(vParts[11], '"');
+ if(MTS::Text::parse(iValue, vParts[12]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) {
+ jData[KEY_SD] = sValue;
+ }
+ if(MTS::Text::parse(iValue, vParts[13]) && convertActiveBandToString((ACTIVEBAND)iValue, sValue) == SUCCESS) {
+ jData[KEY_ABND] = sValue;
+ }
+ } else if(vParts.size() >= WCDMA_NETWORK_FORMAT) {
+ Json::Value jDebug;
+
+ //Parse as WCDMA Network Format
+
+ jDebug[KEY_PSC] = vParts[2];
+ jDebug[KEY_ECIO] = vParts[3];
+ jDebug[KEY_RSCP] = vParts[4];
+
+ jData[KEY_RSSIDBM] = vParts[5];
+ jData[KEY_LAC] = vParts[6];
+ jData[KEY_RAC] = vParts[7];
+
+ jDebug[KEY_TXPWR] = vParts[8];
+ jDebug[KEY_DRX] = vParts[9];
+ jDebug[KEY_MM] = vParts[10];
+ jDebug[KEY_RR] = vParts[11];
+ jDebug[KEY_NOM] = vParts[12];
+
+ if(vParts[13].size() != 0) {
+ jDebug[KEY_BLER] = vParts[13];
+ } else {
+ jDebug[KEY_BLER] = "000";
+ }
+
+ jData[KEY_CID] = vParts[14];
+ jData[KEY_IMSI] = MTS::Text::strip(vParts[15], '"');
+ jData[KEY_NETWORK] = MTS::Text::strip(vParts[16], '"');
+
+ if(MTS::Text::parse(iValue, vParts[17]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) {
+ jDebug[KEY_SD] = sValue;
+ }
+ //Ignoring Active Set Values
+ // <nAST> - Number of Active Set (Maximum 6)
+ // <nUARFCN> - UARFCN of n th active set
+ // <nPSC> - PSC of n th active set
+ // <nEc/Io > - Ec/Io of n th active Set
+
+ jData[KEY_DEBUG] = jDebug;
+ } else if(vParts.size() >= LTE_NETWORK_FORMAT) {
+ Json::Value jDebug;
+
+ //Parse as WCDMA Network Format
+
+ jDebug["rsrp"] = vParts[2];
+ jDebug[KEY_RSSIDBM] = vParts[3];
+ jDebug["rsrq"] = vParts[4];
+
+ jData["tac"] = vParts[5];
+ jDebug[KEY_TXPWR] = vParts[6];
+ //Odd empty index at 7
+ jData[KEY_DRX] = vParts[8];
+
+ jDebug[KEY_MM] = vParts[9];
+ jDebug["rrc"] = vParts[10];
+ jDebug[KEY_CID] = vParts[11];
+ jData[KEY_IMSI] = MTS::Text::strip(vParts[12], '"');
+ jData[KEY_NETWORK] = MTS::Text::strip(vParts[13], '"');
+
+ if(MTS::Text::parse(iValue, vParts[13]) && convertServiceDomainToString((SERVICEDOMAIN)iValue, sValue) == SUCCESS) {
+ jDebug[KEY_SD] = sValue;
+ }
+ //Ignoring Active Set Values
+ // <nAST> - Number of Active Set (Maximum 6)
+ // <nUARFCN> - UARFCN of n th active set
+ // <nPSC> - PSC of n th active set
+ // <nEc/Io > - Ec/Io of n th active Set
+
+ jData[KEY_DEBUG] = jDebug;
+ }
+
+ getCommonNetworkStats(jData);
+
+ printTrace("%s| Network Status:\n%s\n", m_sName.c_str(), jData.toStyledString().c_str());
+
+ return SUCCESS;
+}
+
+void CellularRadio::getCommonNetworkStats(Json::Value& jData) {
+
+ bool bRoaming = false;
+ if(getRoaming(bRoaming) == SUCCESS) {
+ jData[KEY_ROAMING] = bRoaming;
+ }
+
+ int32_t iRssi;
+ if(getSignalStrength(iRssi) == SUCCESS) {
+ jData[KEY_RSSI] = iRssi;
+ int32_t dBm;
+ if(!jData.isMember(KEY_RSSIDBM) && convertSignalStrengthTodBm(iRssi, dBm) == SUCCESS) {
+ //Add RSSI in dBm format
+ jData[KEY_RSSIDBM] = MTS::Text::format(dBm);
+ }
+ }
+
+ std::string sService;
+ if(getService(sService) == SUCCESS) {
+ jData[KEY_SERVICE] = sService;
+ }
+ std::string sDate, sTime, sTimeZone;
+ if(getTime(sDate, sTime, sTimeZone) == SUCCESS) {
+
+ jData[KEY_DATETIME] = sDate + " " + sTime + " GMT" + sTimeZone;
+ }
+}
+
+void CellularRadio::initMipProfile(Json::Value& jData) {
+ jData[KEY_MIP_ID] = 0;
+ jData[KEY_MIP_ENABLED] = false;
+ jData[KEY_MIP_NAI] = VALUE_UNKNOWN;
+ jData[KEY_MIP_HOMEADDRESS] = VALUE_UNKNOWN;
+ jData[KEY_MIP_PRIMARYHA] = VALUE_UNKNOWN;
+ jData[KEY_MIP_SECONDARYHA] = VALUE_UNKNOWN;
+ jData[KEY_MIP_MNAAASPI] = VALUE_UNKNOWN;
+ jData[KEY_MIP_MNHASPI] = VALUE_UNKNOWN;
+ jData[KEY_MIP_MNAAASS] = false;
+ jData[KEY_MIP_MNHASS] = false;
+}
+
+CellularRadio::CODE CellularRadio::getRegistration(REGISTRATION& eRegistration) {
+ std::string sCmd("AT+CREG?");
+ std::string sResult = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, 5000);
+ if (sResult.find("+CREG: ") == std::string::npos) {
+ if(sResult.size() == 0) {
+ printDebug("%s| Registration command returned no response: [%s]", m_sName.c_str());
+ return NO_RESPONSE;
+ }
+ printDebug("%s| Registration command returned unexpected response: [%s]", m_sName.c_str(), sResult.c_str());
+ return FAILURE;
+ }
+
+ size_t start = sResult.find(',');
+ size_t stop = sResult.find(' ', start);
+ std::string sRegStat = sResult.substr(start + 1, stop - start - 1);
+ int32_t value;
+ sscanf(sRegStat.c_str(), "%d", &value);
+ eRegistration = (REGISTRATION)value;
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) {
+
+ CODE eCode = FAILURE;
+ switch (eRegistration) {
+ case NOT_REGISTERED: sRegistration = VALUE_NOT_REGISTERED; eCode = SUCCESS; break;
+ case REGISTERED: sRegistration = VALUE_REGISTERED; eCode = SUCCESS; break;
+ case SEARCHING: sRegistration = VALUE_SEARCHING; eCode = SUCCESS; break;
+ case DENIED: sRegistration = VALUE_DENIED; eCode = SUCCESS; break;
+ case UNKNOWN: sRegistration = VALUE_UNKNOWN; eCode = SUCCESS; break;
+ case ROAMING: sRegistration = VALUE_ROAMING; eCode = SUCCESS; break;
+ }
+ return eCode;
+}
+
+CellularRadio::CODE CellularRadio::validateMsl(const Json::Value& jArgs) {
+ printTrace("%s| Validate MSL", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMdn(const Json::Value& jArgs) {
+ printTrace("%s| Set MDN", m_sName.c_str());
+
+ if(!jArgs["mdn"].isString()) {
+ return INVALID_ARGS;
+ }
+
+ std::string sCmd("AT#SNUM=1,\"");
+ sCmd += jArgs["mdn"].asString() + "\"";
+
+ std::string sResult = sendCommand(sCmd);
+ size_t end = sResult.find(RSP_OK);
+ if (end == std::string::npos) {
+ printWarning("%s| Unable to set MDN for radio using command [%s]", m_sName.c_str(), sCmd.c_str());
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+CellularRadio::CODE CellularRadio::setMsid(const Json::Value& jArgs) {
+ printTrace("%s| Set MSID", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::getMipProfile(Json::Value& jMipProfile) {
+ printTrace("%s| Get MIP Active Profile", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipActiveProfile(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Active Profile", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipNai(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP NAI", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipHomeIp(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Home IP", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipPrimaryHa(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Primary HA", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipSecondaryHa(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Secondary HA", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipMnAaaSpi(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP MN-AAA SPI", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipMnHaSpi(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP MN-HA SPI", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipRevTun(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP Rev Tun", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipMnAaaSs(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP MN-AAA SS", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::setMipMnHaSs(const Json::Value& jArgs) {
+ printTrace("%s| Set MIP MN-HA SS", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::updateDc(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| Update Device Configuration", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| Update Preferred Roaming List", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| Update Firmware Update Management Object", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| HFA Reset", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::activate(const Json::Value& jArgs, UpdateCb& stepCb) {
+ printTrace("%s| Activation", m_sName.c_str());
+
+ return NOT_APPLICABLE;
+}
+
+CellularRadio::CODE CellularRadio::sendBasicCommand(const std::string& sCmd, int32_t iTimeoutMillis, const char& ESC) {
+ std::string response = sendCommand(sCmd, DEFAULT_BAIL_STRINGS, iTimeoutMillis, ESC);
+ if (response.size() == 0) {
+ return NO_RESPONSE;
+ } else if (response.find(RSP_OK) != std::string::npos) {
+ return SUCCESS;
+ } else if (response.find(RSP_ERROR) != std::string::npos) {
+ return ERROR;
+ } else {
+ return FAILURE;
+ }
+}
+
+std::string CellularRadio::sendCommand(const std::string& sCmd, const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) {
+ return sendCommand(m_apIo, sCmd, vBail, timeoutMillis, ESC);
+}
+
+std::string CellularRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd,
+ const std::vector<std::string>& vBail, int32_t timeoutMillis, const char& ESC) {
+ IsNeedMoreData isNeedMoreData = [&vBail](const std::string& iterationData, const std::string& allData)->bool {
+ for(size_t i = 0; i < vBail.size(); i++) {
+ const std::string& sBail = vBail[i];
+ if(sBail.size() > 0) {
+ if(allData.find(sBail) != std::string::npos) {
+ //Return when bail string is found
+ printTrace("RADIO| Found bail string [%s]", sBail.c_str());
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+ return sendCommand(apIo, sCmd, isNeedMoreData, timeoutMillis, ESC);
+}
+
+std::string CellularRadio::sendCommand(const std::string& sCmd, MTS::IO::CellularRadio::IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) {
+ return sendCommand(m_apIo, sCmd, isNeedMoreData, timeoutMillis, ESC);
+}
+
+std::string CellularRadio::sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo, const std::string& sCmd,
+ IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis, const char& ESC) {
+ if(MTS::Logger::getPrintLevel() >= MTS::Logger::PrintLevel::TRACE_LEVEL) {
+ printTrace("RADIO| Sending command [%s]", sCmd.c_str());
+ }
+ if(apIo.isNull()) {
+ printError("RADIO| IO is not set in sendCommand");
+ return "";
+ }
+
+ int32_t iResult;
+ if(ESC == 0x00) {
+ iResult = apIo->write(sCmd.data(), sCmd.size());
+ } else {
+ std::string sNewCmd(sCmd);
+ sNewCmd.push_back(ESC);
+ iResult = apIo->write(sNewCmd.data(), sNewCmd.size());
+ }
+
+ if(iResult == -1) {
+ printError("RADIO| Failed to send command to radio");
+ return "";
+ }
+
+ bool done = false;
+ const uint32_t capacity = 1024;
+ char buffer[capacity];
+ std::string sResult;
+ Timer timer;
+ timer.start();
+ do {
+ int32_t iterationTimeout = 100;
+ int bytesRead = apIo->read((char*)buffer, capacity, iterationTimeout);
+ if(bytesRead == -1) {
+ printError("RADIO| Failed to read from radio");
+ break;
+ }
+
+ std::string sIteration((char*)buffer, bytesRead);
+ sResult += sIteration;
+
+ if(isNeedMoreData && !isNeedMoreData(sIteration, sResult)) {
+ printTrace("RADIO| No more data needed");
+ return sResult;
+ }
+ if(timeoutMillis >= 0) {
+ done = (timer.getMillis() >= (uint64_t)timeoutMillis);
+ } else {
+ //Do not stop looping until bail string is found
+ }
+ } while(!done);
+
+ //Timed out
+ return sResult;
+}
+
+CellularRadio::CODE CellularRadio::test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds) {
+ printTrace("RADIO| Basic Test");
+ uint32_t count = 0;
+ std::string sCmd("AT");
+ do {
+ std::string sResult = sendCommand(apIo, sCmd);
+ if (sResult.find(RSP_OK) == std::string::npos) {
+ printTrace("RADIO| Waiting for basic radio communication [%s] ...", sResult.c_str());
+ } else {
+ break;
+ }
+ count++;
+ } while (count < timeoutSeconds);
+
+ if(count == timeoutSeconds) {
+ printWarning("RADIO| Basic radio communication FAILED");
+ return NO_RESPONSE;
+ }
+ return SUCCESS;
+}
+
+std::string CellularRadio::extractModelFromResult(const std::string& sResult) {
+ std::string sModel(CellularRadio::VALUE_NOT_SUPPORTED);
+ if(sResult.find("HE910-D") != std::string::npos) {
+ sModel = "HE910-D";
+ } else if(sResult.find("HE910-EUD") != std::string::npos) {
+ sModel = "HE910-EUD";
+ } else if(sResult.find("LE910-NAG") != std::string::npos) {
+ sModel = "LE910-NAG";
+ } else if(sResult.find("LE910-SVG") != std::string::npos) {
+ sModel = "LE910-SVG";
+ } else if(sResult.find("LE910-EUG") != std::string::npos) {
+ sModel = "LE910-EUG";
+ } else if(sResult.find("GE910") != std::string::npos) {
+ sModel = "GE910";
+ } else if(sResult.find("DE910-DUAL") != std::string::npos) {
+ sModel = "DE910-DUAL";
+ } else if(sResult.find("CE910") != std::string::npos) {
+ sModel = "CE910";
+ }
+ return sModel;
+}
+
+std::string CellularRadio::getCodeAsString(CODE eCode) {
+ switch(eCode) {
+ case SUCCESS:
+ return "SUCCESS";
+ case ERROR:
+ return "ERROR";
+ case FAILURE:
+ return "FAILURE";
+ case NO_RESPONSE:
+ return "NO RESPONSE";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool CellularRadio::splitAndAssign(const std::string& sLine, const std::string& sKey, Json::Value& jParent, const std::string& sJsonKey, Json::ValueType eType) {
+
+ std::vector<std::string> vParts = MTS::Text::split(sLine, ":", 2);
+
+ if(vParts.size() == 2 && vParts[0] == sKey) {
+ if(eType == Json::ValueType::stringValue) {
+ jParent[sJsonKey] = MTS::Text::trim(vParts[1]);
+ } else if (eType == Json::ValueType::intValue || eType == Json::ValueType::uintValue) {
+ //TODO:
+ printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str());
+ return false;
+ } else if(eType == Json::ValueType::realValue) {
+ //TODO:
+ printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str());
+ return false;
+ } else if(eType == Json::ValueType::booleanValue) {
+ //TODO:
+ printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str());
+ return false;
+ } else {
+ printWarning("%s| Unable to parse requested type from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str());
+ return false;
+ }
+ } else {
+ printWarning("%s| Unable to parse %s from line [%s]", getName().c_str(), sKey.c_str(), sLine.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+bool CellularRadio::getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier) {
+ // Telit Radios
+ // H.ab.zyx => 3 Main Components
+ // "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family
+ // "a" = Hardware version
+ // "b" = Software Major Version
+ // "z" = is the product type, i.e. DUAL or SC
+ // "y" = is the carrier variant
+ // "x" = is the firmware version
+ // Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, and "2" for Verizon.
+
+ const uint32_t CARRIER_INDEX = 1; //y in [zyx]
+
+ bool bResult = false;
+ std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.');
+
+ if(vParts.size() == 3) {
+ //CDMA firmware version notation
+ if(vParts[0] == "15" || vParts[0] == "18") {
+ //DE910 or CE910 -> Good good
+ std::string sID = vParts[2];
+ if(sID.size() == 3) {
+ char cId = sID[CARRIER_INDEX];
+
+ //Good good
+ if(cId == '0') {
+ sCarrier = VALUE_CARRIER_SPRINT;
+ bResult = true;
+ }
+ if(cId == '1') {
+ sCarrier = VALUE_CARRIER_AERIS;
+ bResult = true;
+ }
+ if(cId == '2') {
+ sCarrier = VALUE_CARRIER_VERIZON;
+ bResult = true;
+ }
+ }
+ }
+ }
+
+ return bResult;
+}
+
+bool CellularRadio::getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware) {
+ // Telit Radios
+ // H.ab.zyx => 3 Main Components
+ // "H" = Hardware -> 15 = DE910 family, 18 = CE910 family, 12 = HE910 family
+ // "a" = Hardware version
+ // "b" = Software Major Version
+ // "z" = is the product type, i.e. DUAL or SC
+ // "y" = is the carrier variant
+ // "x" = is the firmware version
+ // Telit will do their best to keep the carrier variant as "0" for Sprint, "1" for Aeris, and "2" for Verizon.
+
+ const uint32_t HARDWARE_INDEX = 0; //a in [ab]
+
+ bool bResult = false;
+ std::vector<std::string> vParts = MTS::Text::split(sFirmware, '.');
+
+ if(vParts.size() == 3) {
+ //GSM Hardware Version
+ if(!(vParts[0] == "15" || vParts[0] == "18")) {
+ //Not DE910 or CE910 -> Good good
+ std::string sVersion = vParts[1];
+ if(sVersion.size() == 2) {
+ sHardware = "1.";
+ sHardware += sVersion[HARDWARE_INDEX];
+ bResult = true;
+ }
+ }
+ }
+
+ return bResult;
+
+}
diff --git a/src/MTS_IO_CellularRadioFactory.cpp b/src/MTS_IO_CellularRadioFactory.cpp
new file mode 100644
index 0000000..3a5cb74
--- /dev/null
+++ b/src/MTS_IO_CellularRadioFactory.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_CellularRadioFactory.cpp
+ \brief A brief description
+ \date Nov 5, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_CellularRadioFactory.h>
+#include <mts/MTS_IO_HE910DRadio.h>
+#include <mts/MTS_IO_HE910EUDRadio.h>
+#include <mts/MTS_IO_LE910NAGRadio.h>
+#include <mts/MTS_IO_LE910SVGRadio.h>
+#include <mts/MTS_IO_LE910EUGRadio.h>
+#include <mts/MTS_IO_GE910Radio.h>
+#include <mts/MTS_IO_CE910Radio.h>
+#include <mts/MTS_IO_DE910Radio.h>
+#include <mts/MTS_Logger.h>
+
+using namespace MTS::IO;
+
+CellularRadioFactory::CellularRadioFactory() {
+ m_mCreationMap[HE910DRadio::MODEL_NAME] = &CellularRadioFactory::createHE910D;
+ m_mCreationMap[HE910EUDRadio::MODEL_NAME] = &CellularRadioFactory::createHE910EUD;
+ m_mCreationMap[LE910NAGRadio::MODEL_NAME] = &CellularRadioFactory::createLE910NAG;
+ m_mCreationMap[LE910SVGRadio::MODEL_NAME] = &CellularRadioFactory::createLE910SVG;
+ m_mCreationMap[LE910EUGRadio::MODEL_NAME] = &CellularRadioFactory::createLE910EUG;
+ m_mCreationMap[GE910Radio::MODEL_NAME] = &CellularRadioFactory::createGE910;
+ m_mCreationMap[DE910Radio::MODEL_NAME] = &CellularRadioFactory::createDE910;
+ m_mCreationMap[CE910Radio::MODEL_NAME] = &CellularRadioFactory::createCE910;
+}
+
+MTS::IO::CellularRadio* CellularRadioFactory::create(const std::string& sModel, const std::string& sPort) {
+
+ std::string model(sModel);
+
+ if(model.size() == 0) {
+ model = identifyRadio(sPort);
+ }
+
+ if(m_mCreationMap.count(model)) {
+ //Call this object's function via a function pointer
+ return (this->*m_mCreationMap[model])(sPort);
+ }
+
+ printWarning("[CELLULARRADIOFACTORY] Unknown radio [%s]. Attempting HE910 version.", model.c_str());
+
+ return new HE910DRadio(sPort);
+}
+
+std::string CellularRadioFactory::identifyRadio(const std::string& sPort) {
+ MTS::AutoPtr<Connection> apIo;
+
+ //Attempt to open port to radio
+ apIo.reset(new SerialConnection(SerialConnection::Builder(sPort).baudRate(115200).useLockFile().build()));
+ while(!apIo->open(30000)) {
+ printError("CellularRadioFactory| Failed to open radio port [%s]", sPort.c_str());
+ return CellularRadio::VALUE_UNKNOWN;
+ }
+
+ //Attempt basic radio communication
+ if(CellularRadio::test(apIo) != CellularRadio::SUCCESS) {
+ printError("CellularRadioFactory| Failed to communicate with radio on port [%s]", sPort.c_str());
+ apIo->close();
+ return CellularRadio::VALUE_UNKNOWN;
+ }
+
+ //Get model
+ int count = 0;
+ std::string sCmd("ATI4");
+ std::string sResult;
+ do {
+ sResult = CellularRadio::sendCommand(apIo, sCmd, CellularRadio::DEFAULT_BAIL_STRINGS, 1000, CellularRadio::CR);
+ if (sResult.find("OK") == std::string::npos) {
+ printDebug("RADIO| Attempting to get radio model [%s] ...", sResult.c_str());
+ } else {
+ break;
+ }
+ count++;
+ } while (count < 30);
+
+ if(count == 30) {
+ printDebug("RADIO| Unable to get radio model");
+ apIo->close();
+ return CellularRadio::VALUE_UNKNOWN;
+ }
+
+ std::string sModel = CellularRadio::extractModelFromResult(sResult);
+ printDebug("RADIO| Extracted [%s] from ATI4 query", sModel.c_str());
+ apIo->close();
+ return sModel;
+}
+
+CellularRadio* CellularRadioFactory::createHE910D(const std::string& sPort) {
+ return new HE910DRadio(sPort);
+}
+
+CellularRadio* CellularRadioFactory::createHE910EUD(const std::string& sPort) {
+ return new HE910EUDRadio(sPort);
+}
+
+CellularRadio* CellularRadioFactory::createLE910NAG(const std::string& sPort) {
+ return new LE910NAGRadio(sPort);
+}
+
+CellularRadio* CellularRadioFactory::createLE910SVG(const std::string& sPort) {
+ return new LE910SVGRadio(sPort);
+}
+
+CellularRadio* CellularRadioFactory::createLE910EUG(const std::string& sPort) {
+ return new LE910EUGRadio(sPort);
+}
+
+CellularRadio* CellularRadioFactory::createGE910(const std::string& sPort) {
+ return new GE910Radio(sPort);
+}
+
+CellularRadio* CellularRadioFactory::createDE910(const std::string& sPort) {
+ return new DE910Radio(sPort);
+}
+
+CellularRadio* CellularRadioFactory::createCE910(const std::string& sPort) {
+ return new CE910Radio(sPort);
+}
diff --git a/src/MTS_IO_Connection.cpp b/src/MTS_IO_Connection.cpp
new file mode 100644
index 0000000..36a91ed
--- /dev/null
+++ b/src/MTS_IO_Connection.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_Connection.cpp
+ \brief A brief description
+ \date Jan 15, 2013
+ \author sgodinez
+
+ A more elaborate description than necessary.
+*/
+
+
+#include <mts/MTS_IO_Connection.h>
+#include <mts/MTS_Buffer.h>
+#include <sys/select.h>
+
+using namespace MTS;
+using namespace MTS::IO;
+
+int32_t Connection::BLOCKING = -1;
+
+Connection::Connection(const std::string& name)
+: m_sName(name)
+, m_bClosed(true)
+, m_bCloseable(true) {
+ m_apLock.reset(new Lock());
+ m_apReadLock.reset(new Lock());
+ m_apWriteLock.reset(new Lock());
+}
+
+Connection::~Connection() {
+ m_apWriteLock.reset();
+ m_apReadLock.reset();
+ m_apLock.reset();
+}
+
+const std::string& Connection::getName() const {
+ return m_sName;
+}
+
+bool Connection::open(const int32_t& timeoutMillis) {
+ bool bOpened = true;
+ m_apLock->lock();
+ if (m_bClosed) {
+ bOpened = doOpen(timeoutMillis);
+ if (bOpened) {
+ m_bClosed = false;
+ }
+ }
+ m_apLock->unlock();
+ return bOpened;
+}
+
+void Connection::close() {
+ m_apLock->lock();
+ if (m_bCloseable) {
+ doClose();
+ m_bClosed = true;
+ }
+ m_apLock->unlock();
+}
+
+bool Connection::isClosed() const {
+ m_apLock->lock();
+ bool bResult = m_bClosed;
+ m_apLock->unlock();
+ return bResult;
+}
+
+void Connection::setCloseable(bool bCloseable) {
+ m_apLock->lock();
+ m_bCloseable = bCloseable;
+ m_apLock->unlock();
+}
+
+bool Connection::isCloseable() const {
+ m_apLock->lock();
+ bool bResult = m_bCloseable;
+ m_apLock->unlock();
+ return bResult;
+}
+
+int Connection::read(std::string& sBuffer, const uint32_t& iSize, int32_t& timeoutMillis) {
+ int result = -1;
+ if (isClosed()) {
+ return result;
+ } else {
+ char buffer[iSize];
+ m_apReadLock->lock();
+ result = doRead(buffer, iSize, timeoutMillis);
+ m_apReadLock->unlock();
+ if(result > 0) {
+ sBuffer = std::string(buffer, result);
+ }
+ }
+
+ return result;
+}
+
+int Connection::read(Buffer& oBuffer, const uint32_t& iSize, int32_t& timeoutMillis) {
+ int result = -1;
+ if (isClosed()) {
+ return result;
+ } else {
+ oBuffer.setCapacity(iSize);
+ m_apReadLock->lock();
+ result = doRead((char*)oBuffer.getBuffer(), iSize, timeoutMillis);
+ m_apReadLock->unlock();
+ }
+
+ return result;
+}
+
+int Connection::read(char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis) {
+ int result = -1;
+ if (isClosed()) {
+ return result;
+ } else {
+ m_apReadLock->lock();
+ result = doRead(pBuffer, iSize, timeoutMillis);
+ m_apReadLock->unlock();
+ }
+ return result;
+}
+
+int Connection::write(const char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis) {
+ int result = -1;
+ if (isClosed()) {
+ return result;
+ } else {
+ m_apWriteLock->lock();
+ result = doWrite(pBuffer, iSize, timeoutMillis);
+ m_apWriteLock->unlock();
+ }
+ return result;
+}
+
diff --git a/src/MTS_IO_DE910Radio.cpp b/src/MTS_IO_DE910Radio.cpp
new file mode 100644
index 0000000..766d7d1
--- /dev/null
+++ b/src/MTS_IO_DE910Radio.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_DE910Radio.cpp
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_DE910Radio.h>
+
+using namespace MTS::IO;
+
+const std::string DE910Radio::MODEL_NAME("DE910-DUAL");
+
+DE910Radio::DE910Radio(const std::string& sPort)
+: CdmaRadio(MODEL_NAME, sPort)
+{
+
+}
+
diff --git a/src/MTS_IO_GE910Radio.cpp b/src/MTS_IO_GE910Radio.cpp
new file mode 100644
index 0000000..013837b
--- /dev/null
+++ b/src/MTS_IO_GE910Radio.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_GE910Radio.cpp
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_GE910Radio.h>
+
+using namespace MTS::IO;
+
+const std::string GE910Radio::MODEL_NAME("GE910");
+
+GE910Radio::GE910Radio(const std::string& sPort)
+: CellularRadio(MODEL_NAME, sPort)
+{
+
+}
+
diff --git a/src/MTS_IO_HE910DRadio.cpp b/src/MTS_IO_HE910DRadio.cpp
new file mode 100644
index 0000000..b159a9c
--- /dev/null
+++ b/src/MTS_IO_HE910DRadio.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_HE910DRadio.cpp
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+
+#include <mts/MTS_IO_HE910DRadio.h>
+
+using namespace MTS::IO;
+
+const std::string HE910DRadio::MODEL_NAME("HE910-D");
+
+HE910DRadio::HE910DRadio(const std::string& sPort)
+: HE910Radio(MODEL_NAME, sPort)
+{
+
+}
diff --git a/src/MTS_IO_HE910EUDRadio.cpp b/src/MTS_IO_HE910EUDRadio.cpp
new file mode 100644
index 0000000..4ae7e19
--- /dev/null
+++ b/src/MTS_IO_HE910EUDRadio.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_HE910EUDRadio.cpp
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_HE910EUDRadio.h>
+
+using namespace MTS::IO;
+
+const std::string HE910EUDRadio::MODEL_NAME("HE910-EUD");
+
+HE910EUDRadio::HE910EUDRadio(const std::string& sPort)
+: HE910Radio(MODEL_NAME, sPort)
+{
+
+}
+
+
diff --git a/src/MTS_IO_HE910Radio.cpp b/src/MTS_IO_HE910Radio.cpp
new file mode 100644
index 0000000..3a7851a
--- /dev/null
+++ b/src/MTS_IO_HE910Radio.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_HE910Radio.cpp
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_HE910Radio.h>
+
+using namespace MTS::IO;
+
+HE910Radio::HE910Radio(const std::string& sHE910Model, const std::string& sPort)
+: CellularRadio(sHE910Model, sPort)
+{
+
+}
+
+
diff --git a/src/MTS_IO_LE910EUGRadio.cpp b/src/MTS_IO_LE910EUGRadio.cpp
new file mode 100644
index 0000000..c3e54c3
--- /dev/null
+++ b/src/MTS_IO_LE910EUGRadio.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LE910EUGRadio.cpp
+ \brief A brief description
+ \date Jan 19, 2015
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+
+#include <mts/MTS_IO_LE910EUGRadio.h>
+
+using namespace MTS::IO;
+
+const std::string LE910EUGRadio::MODEL_NAME("LE910-EUG");
+
+LE910EUGRadio::LE910EUGRadio(const std::string& sPort)
+: LE910Radio(MODEL_NAME, sPort)
+{
+
+}
diff --git a/src/MTS_IO_LE910NAGRadio.cpp b/src/MTS_IO_LE910NAGRadio.cpp
new file mode 100644
index 0000000..c2f8bf5
--- /dev/null
+++ b/src/MTS_IO_LE910NAGRadio.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LE910NAGRadio.cpp
+ \brief A brief description
+ \date Jan 19, 2015
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_LE910NAGRadio.h>
+
+using namespace MTS::IO;
+
+const std::string LE910NAGRadio::MODEL_NAME("LE910-NAG");
+
+LE910NAGRadio::LE910NAGRadio(const std::string& sPort)
+: LE910Radio(MODEL_NAME, sPort)
+{
+
+}
+
+CellularRadio::CODE LE910NAGRadio::getCarrier(std::string& sCarrier) {
+ sCarrier = "AT&T";
+ return SUCCESS;
+}
diff --git a/src/MTS_IO_LE910Radio.cpp b/src/MTS_IO_LE910Radio.cpp
new file mode 100644
index 0000000..cbff249
--- /dev/null
+++ b/src/MTS_IO_LE910Radio.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LE910Radio.cpp
+ \brief A brief description
+ \date Nov 6, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_LE910Radio.h>
+
+using namespace MTS::IO;
+
+LE910Radio::LE910Radio(const std::string& sLE910Model, const std::string& sPort)
+: CellularRadio(sLE910Model, sPort)
+{
+
+}
+
diff --git a/src/MTS_IO_LE910SVGRadio.cpp b/src/MTS_IO_LE910SVGRadio.cpp
new file mode 100644
index 0000000..ee9b3f8
--- /dev/null
+++ b/src/MTS_IO_LE910SVGRadio.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LE910SVGRadio.cpp
+ \brief A brief description
+ \date Jan 19, 2015
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_LE910SVGRadio.h>
+
+using namespace MTS::IO;
+
+const std::string LE910SVGRadio::MODEL_NAME("LE910-SVG");
+
+LE910SVGRadio::LE910SVGRadio(const std::string& sPort)
+: LE910Radio(MODEL_NAME, sPort)
+{
+
+}
+
+CellularRadio::CODE LE910SVGRadio::getCarrier(std::string& sCarrier) {
+ sCarrier = "Verizon";
+ return SUCCESS;
+}
diff --git a/src/MTS_IO_LockFile.cpp b/src/MTS_IO_LockFile.cpp
new file mode 100644
index 0000000..c013699
--- /dev/null
+++ b/src/MTS_IO_LockFile.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_LockFile.cpp
+ \brief A brief description
+ \date Oct 8, 2014
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_LockFile.h>
+#include <mts/MTS_Timer.h>
+#include <mts/MTS_Logger.h>
+#include <mts/MTS_System.h>
+#include <mts/MTS_Text.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+using namespace MTS::IO;
+
+LockFile::LockFile(const std::string& sFile)
+: m_sFile(sFile)
+, m_iLockFd(-1)
+{
+
+}
+
+LockFile::~LockFile() {
+ unlock();
+}
+
+bool LockFile::lock(uint32_t attemptMillis) {
+ if(isLocked()) {
+ return true;
+ }
+
+ MTS::Timer timer;
+
+ timer.start();
+ while(timer.getMillis() < attemptMillis) {
+ m_iLockFd =::open(m_sFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644);
+ if (m_iLockFd < 0) {
+ // device already locked -> bail out
+ printWarning("LockFile| Failed to Lock [%s] [%d][%s]", m_sFile.c_str(), errno, strerror(errno));
+
+ //Check if lock file's process still exists
+ std::string sResult;
+ if(MTS::System::readFile(m_sFile, sResult) == 0 && sResult.size() > 0) {
+ struct stat sts;
+ std::string sProc = "/proc/" + MTS::Text::trim(sResult);
+ if (stat(sProc.c_str(), &sts) == -1 && errno == ENOENT) {
+ printWarning("LockFile| Current Lock's Process [%s] does not exist. Removing lock.", sResult.c_str());
+ // process doesn't exist -> remove file
+ ::unlink(m_sFile.c_str());
+ }
+ }
+
+ } else {
+ //TODO: Investigate using flock in addition to minicom-style lock : flock(m_iLockFd, LOCK_EX | LOCK_NB);
+
+ // %4d to make concurrent mgetty (if any) happy.
+ // Mgetty treats 4-bytes lock files as binary,
+ // not text, PID. Making 5+ char file. Brrr...
+ char buf[256] = {0};
+ sprintf(buf, "%4d\n", getpid());
+ write(m_iLockFd, buf, strlen(buf));
+ close(m_iLockFd);
+ return true;
+ }
+ uint32_t randomSleepTime = ((rand() % 10) + 1) * 100000; //Sleep from 100ms to 1 Second
+ ::usleep(randomSleepTime);
+ }
+ return false;
+}
+
+void LockFile::unlock() {
+ if(isLocked()) {
+ ::unlink(m_sFile.c_str());
+ //TODO: flock cleanup : flock(m_iLockFd, LOCK_UN);
+ m_iLockFd = -1;
+ }
+}
+
+bool LockFile::isLocked() {
+ return m_iLockFd >= 0;
+}
+
diff --git a/src/MTS_IO_MccMncTable.cpp b/src/MTS_IO_MccMncTable.cpp
new file mode 100644
index 0000000..8ac3f62
--- /dev/null
+++ b/src/MTS_IO_MccMncTable.cpp
@@ -0,0 +1,1723 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_MccMncTable.cpp
+ \brief Auto-Generated MCC-MNC Lookup Table
+ \date 2014-12-11
+ \author sgodinez
+
+ An Auto-Generated MCC-MNC Lookup Table
+*/
+
+#include <mts/MTS_IO_MccMncTable.h>
+#include <mts/MTS_Logger.h>
+#include <mts/MTS_Text.h>
+
+using namespace MTS::IO;
+
+MTS::AutoPtr<MTS::Lock> MccMncTable::m_apLock(new MTS::Lock());
+MccMncTable* MccMncTable::m_pInstance = NULL;
+
+MccMncTable* MccMncTable::getInstance() {
+ if(m_pInstance == NULL) {
+ m_apLock->lock();
+ if (m_pInstance == NULL) {
+ m_pInstance = new MccMncTable();
+ }
+ m_apLock->unlock();
+ }
+ return m_pInstance;
+}
+
+MccMncTable::MccMncTable() {
+ createTable();
+}
+
+Json::Value MccMncTable::lookup(const std::string& sMcc, const std::string& sMnc) {
+ uint32_t iMcc, iMnc;
+ printTrace("[MCCMNC] MCCx[%s] MNCx[%s]", sMcc.c_str(), sMnc.c_str());
+ if(!MTS::Text::parseHex(iMcc, sMcc)) { return Json::Value::null; }
+ if(!MTS::Text::parseHex(iMnc, sMnc)) { return Json::Value::null; }
+ printTrace("[MCCMNC] MCC0X[%d] MNC0X[%d]", iMcc, iMnc);
+ if (m_mTable.count(iMcc)) {
+ if(m_mTable[iMcc].count(iMnc)) {
+ std::vector<std::string> vJson = MTS::Text::split(m_mTable[iMcc][iMnc], ',');
+ Json::Value j;
+ j["iso"] = vJson[0];
+ j["country"] = vJson[1];
+ j["code"] = vJson[2];
+ j["carrier"] = vJson[3];
+ return j;
+ }
+ }
+
+ return Json::Value::null;
+}
+
+void MccMncTable::createTable() {
+ std::string sData;
+ m_mTable[649][2191] = "ge,Abkhazia,7,A-Mobile";
+ m_mTable[649][1679] = "ge,Abkhazia,7,A-Mobile";
+ m_mTable[649][1663] = "ge,Abkhazia,7,Aquafon";
+ m_mTable[1042][2191] = "af,Afghanistan,93,Afghan Telecom Corp. (AT)";
+ m_mTable[1042][2063] = "af,Afghanistan,93,Afghan Telecom Corp. (AT)";
+ m_mTable[1042][31] = "af,Afghanistan,93,Afghan Wireless/AWCC";
+ m_mTable[1042][1039] = "af,Afghanistan,93,Areeba/MTN";
+ m_mTable[1042][1295] = "af,Afghanistan,93,Etisalat";
+ m_mTable[1042][527] = "af,Afghanistan,93,Roshan";
+ m_mTable[630][31] = "al,Albania,355,AMC Mobil";
+ m_mTable[630][63] = "al,Albania,355,Eagle Mobile";
+ m_mTable[630][79] = "al,Albania,355,PLUS Communication Sh.a";
+ m_mTable[630][47] = "al,Albania,355,Vodafone";
+ m_mTable[1539][31] = "dz,Algeria,213,ATM Mobils";
+ m_mTable[1539][47] = "dz,Algeria,213,Orascom / DJEZZY";
+ m_mTable[1539][63] = "dz,Algeria,213,Oreedo/Wataniya / Nedjma";
+ m_mTable[1348][287] = "as,American Samoa,684,Blue Sky Communications";
+ m_mTable[531][63] = "ad,Andorra,376,Mobiland";
+ m_mTable[1585][79] = "ao,Angola,244,MoviCel";
+ m_mTable[1585][47] = "ao,Angola,244,Unitel";
+ m_mTable[869][2112] = "ai,Anguilla,1264,Cable and Wireless";
+ m_mTable[869][16] = "ai,Anguilla,1264,Digicell / Wireless Vent. Ltd";
+ m_mTable[836][48] = "ag,Antigua and Barbuda,1268,APUA PCS";
+ m_mTable[836][2336] = "ag,Antigua and Barbuda,1268,C & W";
+ m_mTable[836][2352] = "ag,Antigua and Barbuda,1268,DigiCel/Cing. Wireless";
+ m_mTable[1826][784] = "ar,Argentina Republic,54,Claro/ CTI/AMX";
+ m_mTable[1826][816] = "ar,Argentina Republic,54,Claro/ CTI/AMX";
+ m_mTable[1826][800] = "ar,Argentina Republic,54,Claro/ CTI/AMX";
+ m_mTable[1826][16] = "ar,Argentina Republic,54,Compania De Radiocomunicaciones Moviles SA";
+ m_mTable[1826][112] = "ar,Argentina Republic,54,Movistar/Telefonica";
+ m_mTable[1826][32] = "ar,Argentina Republic,54,Nextel";
+ m_mTable[1826][833] = "ar,Argentina Republic,54,Telecom Personal S.A.";
+ m_mTable[643][31] = "am,Armenia,374,ArmenTel/Beeline";
+ m_mTable[643][79] = "am,Armenia,374,Karabakh Telecom";
+ m_mTable[643][271] = "am,Armenia,374,Orange";
+ m_mTable[643][95] = "am,Armenia,374,Vivacell";
+ m_mTable[867][527] = "aw,Aruba,297,Digicel";
+ m_mTable[867][31] = "aw,Aruba,297,Setar GSM";
+ m_mTable[1285][335] = "au,Australia,61,AAPT Ltd.";
+ m_mTable[1285][591] = "au,Australia,61,Advanced Comm Tech Pty.";
+ m_mTable[1285][159] = "au,Australia,61,Airnet Commercial Australia Ltd..";
+ m_mTable[1285][79] = "au,Australia,61,Department of Defense";
+ m_mTable[1285][623] = "au,Australia,61,Dialogue Communications Pty Ltd";
+ m_mTable[1285][303] = "au,Australia,61,H3G Ltd.";
+ m_mTable[1285][111] = "au,Australia,61,H3G Ltd.";
+ m_mTable[1285][2191] = "au,Australia,61,Localstar Holding Pty. Ltd";
+ m_mTable[1285][415] = "au,Australia,61,Lycamobile Pty Ltd";
+ m_mTable[1285][143] = "au,Australia,61,Railcorp/Vodafone";
+ m_mTable[1285][2463] = "au,Australia,61,Railcorp/Vodafone";
+ m_mTable[1285][319] = "au,Australia,61,Railcorp/Vodafone";
+ m_mTable[1285][2319] = "au,Australia,61,Singtel Optus";
+ m_mTable[1285][47] = "au,Australia,61,Singtel Optus";
+ m_mTable[1285][31] = "au,Australia,61,Telstra Corp. Ltd.";
+ m_mTable[1285][287] = "au,Australia,61,Telstra Corp. Ltd.";
+ m_mTable[1285][1823] = "au,Australia,61,Telstra Corp. Ltd.";
+ m_mTable[1285][1839] = "au,Australia,61,Telstra Corp. Ltd.";
+ m_mTable[1285][95] = "au,Australia,61,The Ozitel Network Pty.";
+ m_mTable[1285][367] = "au,Australia,61,Victorian Rail Track Corp. (VicTrack)";
+ m_mTable[1285][63] = "au,Australia,61,Vodafone";
+ m_mTable[1285][127] = "au,Australia,61,Vodafone";
+ m_mTable[562][31] = "at,Austria,43,A1 MobilKom";
+ m_mTable[562][287] = "at,Austria,43,A1 MobilKom";
+ m_mTable[562][159] = "at,Austria,43,A1 MobilKom";
+ m_mTable[562][47] = "at,Austria,43,A1 MobilKom";
+ m_mTable[562][351] = "at,Austria,43,T-Mobile/Telering";
+ m_mTable[562][15] = "at,Austria,43,Fix Line";
+ m_mTable[562][335] = "at,Austria,43,H3G";
+ m_mTable[562][271] = "at,Austria,43,H3G";
+ m_mTable[562][111] = "at,Austria,43,A1/Orange/One Connect";
+ m_mTable[562][303] = "at,Austria,43,A1/Orange/One Connect";
+ m_mTable[562][95] = "at,Austria,43,A1/Orange/One Connect";
+ m_mTable[562][127] = "at,Austria,43,T-Mobile/Telering";
+ m_mTable[562][79] = "at,Austria,43,T-Mobile/Telering";
+ m_mTable[562][63] = "at,Austria,43,T-Mobile/Telering";
+ m_mTable[562][143] = "at,Austria,43,Telefonica";
+ m_mTable[1024][31] = "az,Azerbaijan,994,Azercell Telekom B.M.";
+ m_mTable[1024][79] = "az,Azerbaijan,994,Azerfon.";
+ m_mTable[1024][63] = "az,Azerbaijan,994,Caspian American Telecommunications LLC (CATEL)";
+ m_mTable[1024][47] = "az,Azerbaijan,994,J.V. Bakcell GSM 2000";
+ m_mTable[868][783] = "bs,Bahamas,1242,Bahamas Telco. Comp.";
+ m_mTable[868][927] = "bs,Bahamas,1242,Bahamas Telco. Comp.";
+ m_mTable[868][912] = "bs,Bahamas,1242,Bahamas Telco. Comp.";
+ m_mTable[868][63] = "bs,Bahamas,1242,Smart Communications";
+ m_mTable[1062][31] = "bh,Bahrain,973,Batelco";
+ m_mTable[1062][47] = "bh,Bahrain,973,ZAIN/Vodafone";
+ m_mTable[1062][79] = "bh,Bahrain,973,VIVA";
+ m_mTable[1136][47] = "bd,Bangladesh,880,Robi/Aktel";
+ m_mTable[1136][95] = "bd,Bangladesh,880,Citycell";
+ m_mTable[1136][111] = "bd,Bangladesh,880,Citycell";
+ m_mTable[1136][31] = "bd,Bangladesh,880,GrameenPhone";
+ m_mTable[1136][63] = "bd,Bangladesh,880,Orascom";
+ m_mTable[1136][79] = "bd,Bangladesh,880,TeleTalk";
+ m_mTable[1136][127] = "bd,Bangladesh,880,Airtel/Warid";
+ m_mTable[834][1536] = "bb,Barbados,1246,C & W BET Ltd.";
+ m_mTable[834][2064] = "bb,Barbados,1246,Cingular Wireless";
+ m_mTable[834][1872] = "bb,Barbados,1246,Digicel";
+ m_mTable[834][80] = "bb,Barbados,1246,Digicel";
+ m_mTable[834][2080] = "bb,Barbados,1246,Sunbeach";
+ m_mTable[599][63] = "by,Belarus,375,BelCel JV";
+ m_mTable[599][79] = "by,Belarus,375,BeST";
+ m_mTable[599][31] = "by,Belarus,375,Mobile Digital Communications";
+ m_mTable[599][47] = "by,Belarus,375,MTS";
+ m_mTable[518][527] = "be,Belgium,32,Base/KPN";
+ m_mTable[518][31] = "be,Belgium,32,Belgacom/Proximus";
+ m_mTable[518][111] = "be,Belgium,32,Lycamobile Belgium";
+ m_mTable[518][271] = "be,Belgium,32,Mobistar/Orange";
+ m_mTable[518][47] = "be,Belgium,32,SNCT/NMBS";
+ m_mTable[518][95] = "be,Belgium,32,Telenet BidCo NV";
+ m_mTable[1794][1663] = "bz,Belize,501,DigiCell";
+ m_mTable[1794][1679] = "bz,Belize,501,International Telco (INTELCO)";
+ m_mTable[1558][79] = "bj,Benin,229,Bell Benin/BBCOM";
+ m_mTable[1558][47] = "bj,Benin,229,Etisalat/MOOV";
+ m_mTable[1558][95] = "bj,Benin,229,GloMobile";
+ m_mTable[1558][31] = "bj,Benin,229,Libercom";
+ m_mTable[1558][63] = "bj,Benin,229,MTN/Spacetel";
+ m_mTable[848][0] = "bm,Bermuda,1441,Bermuda Digital Communications Ltd (BDC)";
+ m_mTable[848][2463] = "bm,Bermuda,1441,CellOne Ltd";
+ m_mTable[848][271] = "bm,Bermuda,1441,DigiCel / Cingular";
+ m_mTable[848][47] = "bm,Bermuda,1441,M3 Wireless Ltd";
+ m_mTable[848][31] = "bm,Bermuda,1441,Telecommunications (Bermuda & West Indies) Ltd (Digicel Bermuda)";
+ m_mTable[1026][287] = "bt,Bhutan,975,B-Mobile";
+ m_mTable[1026][383] = "bt,Bhutan,975,Bhutan Telecom Ltd (BTL)";
+ m_mTable[1026][1919] = "bt,Bhutan,975,TashiCell";
+ m_mTable[1846][47] = "bo,Bolivia,591,Entel Pcs";
+ m_mTable[1846][31] = "bo,Bolivia,591,Nuevatel";
+ m_mTable[1846][63] = "bo,Bolivia,591,TELECEL BOLIVIA";
+ m_mTable[536][2319] = "ba,Bosnia & Herzegov.,387,BH Mobile";
+ m_mTable[536][63] = "ba,Bosnia & Herzegov.,387,Eronet Mobile";
+ m_mTable[536][95] = "ba,Bosnia & Herzegov.,387,M-Tel";
+ m_mTable[1618][79] = "bw,Botswana,267,beMOBILE";
+ m_mTable[1618][31] = "bw,Botswana,267,Mascom Wireless (Pty) Ltd.";
+ m_mTable[1618][47] = "bw,Botswana,267,Orange";
+ m_mTable[1828][303] = "br,Brazil,55,Claro/Albra/America Movil";
+ m_mTable[1828][911] = "br,Brazil,55,Claro/Albra/America Movil";
+ m_mTable[1828][95] = "br,Brazil,55,Claro/Albra/America Movil";
+ m_mTable[1828][31] = "br,Brazil,55,Vivo S.A./Telemig";
+ m_mTable[1828][847] = "br,Brazil,55,CTBC Celular SA (CTBC)";
+ m_mTable[1828][831] = "br,Brazil,55,CTBC Celular SA (CTBC)";
+ m_mTable[1828][815] = "br,Brazil,55,CTBC Celular SA (CTBC)";
+ m_mTable[1828][143] = "br,Brazil,55,TIM";
+ m_mTable[1828][927] = "br,Brazil,55,Nextel (Telet)";
+ m_mTable[1828][15] = "br,Brazil,55,Nextel (Telet)";
+ m_mTable[1828][591] = "br,Brazil,55,Amazonia Celular S/A";
+ m_mTable[1828][783] = "br,Brazil,55,Oi (TNL PCS / Oi)";
+ m_mTable[1828][799] = "br,Brazil,55,Oi (TNL PCS / Oi)";
+ m_mTable[1828][367] = "br,Brazil,55,Brazil Telcom";
+ m_mTable[1828][351] = "br,Brazil,55,Sercontel Cel";
+ m_mTable[1828][127] = "br,Brazil,55,CTBC/Triangulo";
+ m_mTable[1828][415] = "br,Brazil,55,Vivo S.A./Telemig";
+ m_mTable[1828][47] = "br,Brazil,55,TIM";
+ m_mTable[1828][79] = "br,Brazil,55,TIM";
+ m_mTable[1828][63] = "br,Brazil,55,TIM";
+ m_mTable[1828][895] = "br,Brazil,55,Unicel do Brasil Telecomunicacoes Ltda";
+ m_mTable[1828][271] = "br,Brazil,55,Vivo S.A./Telemig";
+ m_mTable[1828][111] = "br,Brazil,55,Vivo S.A./Telemig";
+ m_mTable[1828][575] = "br,Brazil,55,Vivo S.A./Telemig";
+ m_mTable[1828][287] = "br,Brazil,55,Vivo S.A./Telemig";
+ m_mTable[840][1392] = "vg,British Virgin Islands,284,Caribbean Cellular";
+ m_mTable[840][1904] = "vg,British Virgin Islands,284,Digicel";
+ m_mTable[840][368] = "vg,British Virgin Islands,284,LIME";
+ m_mTable[1320][47] = "bn,Brunei,673,b-mobile";
+ m_mTable[1320][287] = "bn,Brunei,673,Datastream (DTSCom)";
+ m_mTable[1320][31] = "bn,Brunei,673,Telekom Brunei Bhd (TelBru)";
+ m_mTable[644][111] = "bg,Bulgaria,359,BTC Mobile EOOD (vivatel)";
+ m_mTable[644][63] = "bg,Bulgaria,359,BTC Mobile EOOD (vivatel)";
+ m_mTable[644][95] = "bg,Bulgaria,359,Cosmo Mobile EAD/Globul";
+ m_mTable[644][31] = "bg,Bulgaria,359,MobilTel AD";
+ m_mTable[1555][63] = "bf,Burkina Faso,226,TeleCel";
+ m_mTable[1555][31] = "bf,Burkina Faso,226,TeleMob-OnaTel";
+ m_mTable[1555][47] = "bf,Burkina Faso,226,AirTel/ZAIN/CelTel";
+ m_mTable[1044][31] = "mm,Burma,95,Myanmar Post & Teleco.";
+ m_mTable[1602][47] = "bi,Burundi,257,Africel / Safaris";
+ m_mTable[1602][143] = "bi,Burundi,257,HiTs Telecom";
+ m_mTable[1602][63] = "bi,Burundi,257,Onatel / Telecel";
+ m_mTable[1602][127] = "bi,Burundi,257,Smart Mobile / LACELL";
+ m_mTable[1602][31] = "bi,Burundi,257,Spacetel / Econet";
+ m_mTable[1602][2095] = "bi,Burundi,257,U-COM";
+ m_mTable[1110][79] = "kh,Cambodia,855,Cambodia Advance Communications Co. Ltd (CADCOMMS)";
+ m_mTable[1110][47] = "kh,Cambodia,855,Hello/Malaysia Telcom";
+ m_mTable[1110][143] = "kh,Cambodia,855,Metfone";
+ m_mTable[1110][399] = "kh,Cambodia,855,MFone/Camshin";
+ m_mTable[1110][31] = "kh,Cambodia,855,Mobitel/Cam GSM";
+ m_mTable[1110][63] = "kh,Cambodia,855,QB/Cambodia Adv. Comms.";
+ m_mTable[1110][95] = "kh,Cambodia,855,Smart Mobile";
+ m_mTable[1110][111] = "kh,Cambodia,855,Smart Mobile";
+ m_mTable[1110][159] = "kh,Cambodia,855,Sotelco Ltd (Beeline Cambodia)";
+ m_mTable[1572][31] = "cm,Cameroon,237,MTN";
+ m_mTable[1572][79] = "cm,Cameroon,237,Nextel";
+ m_mTable[1572][47] = "cm,Cameroon,237,Orange";
+ m_mTable[770][1618] = "ca,Canada,1,BC Tel Mobility";
+ m_mTable[770][1584] = "ca,Canada,1,Bell Aliant";
+ m_mTable[770][1552] = "ca,Canada,1,Bell Mobility";
+ m_mTable[770][1617] = "ca,Canada,1,Bell Mobility";
+ m_mTable[770][1648] = "ca,Canada,1,CityWest Mobility";
+ m_mTable[770][865] = "ca,Canada,1,Clearnet";
+ m_mTable[770][864] = "ca,Canada,1,Clearnet";
+ m_mTable[770][896] = "ca,Canada,1,DMTS Mobility";
+ m_mTable[770][1808] = "ca,Canada,1,Globalstar Canada";
+ m_mTable[770][1600] = "ca,Canada,1,Latitude Wireless";
+ m_mTable[770][880] = "ca,Canada,1,FIDO (Rogers AT&T/ Microcell)";
+ m_mTable[770][800] = "ca,Canada,1,mobilicity";
+ m_mTable[770][1794] = "ca,Canada,1,MT&T Mobility";
+ m_mTable[770][1621] = "ca,Canada,1,MTS Mobility";
+ m_mTable[770][1632] = "ca,Canada,1,MTS Mobility";
+ m_mTable[770][1793] = "ca,Canada,1,NB Tel Mobility";
+ m_mTable[770][1795] = "ca,Canada,1,New Tel Mobility";
+ m_mTable[770][1888] = "ca,Canada,1,Public Mobile";
+ m_mTable[770][1623] = "ca,Canada,1,Quebectel Mobility";
+ m_mTable[770][1824] = "ca,Canada,1,Rogers AT&T Wireless";
+ m_mTable[770][1664] = "ca,Canada,1,Sask Tel Mobility";
+ m_mTable[770][1620] = "ca,Canada,1,Sask Tel Mobility";
+ m_mTable[770][1622] = "ca,Canada,1,Tbay Mobility";
+ m_mTable[770][544] = "ca,Canada,1,Telus Mobility";
+ m_mTable[770][1619] = "ca,Canada,1,Telus Mobility";
+ m_mTable[770][1280] = "ca,Canada,1,Videotron";
+ m_mTable[770][1168] = "ca,Canada,1,WIND";
+ m_mTable[1573][31] = "cv,Cape Verde,238,CV Movel";
+ m_mTable[1573][47] = "cv,Cape Verde,238,T+ Telecom";
+ m_mTable[838][80] = "ky,Cayman Islands,1345,Digicel Cayman Ltd";
+ m_mTable[838][6] = "ky,Cayman Islands,1345,Digicel Ltd.";
+ m_mTable[838][320] = "ky,Cayman Islands,1345,LIME / Cable & Wirel.";
+ m_mTable[1571][31] = "cf,Central African Rep.,236,Centrafr. Telecom+";
+ m_mTable[1571][79] = "cf,Central African Rep.,236,Nationlink";
+ m_mTable[1571][63] = "cf,Central African Rep.,236,Orange/Celca";
+ m_mTable[1571][47] = "cf,Central African Rep.,236,Telecel Centraf.";
+ m_mTable[1570][79] = "td,Chad,235,Salam/Sotel";
+ m_mTable[1570][47] = "td,Chad,235,Tchad Mobile";
+ m_mTable[1570][63] = "td,Chad,235,Tigo/Milicom/Tchad Mobile";
+ m_mTable[1570][31] = "td,Chad,235,Zain/Airtel/Celtel";
+ m_mTable[1840][111] = "cl,Chile,56,Blue Two Chile SA";
+ m_mTable[1840][287] = "cl,Chile,56,Celupago SA";
+ m_mTable[1840][351] = "cl,Chile,56,Cibeles Telecom SA";
+ m_mTable[1840][63] = "cl,Chile,56,Claro";
+ m_mTable[1840][271] = "cl,Chile,56,Entel PCS";
+ m_mTable[1840][31] = "cl,Chile,56,Entel Telefonia Mov";
+ m_mTable[1840][335] = "cl,Chile,56,Netline Telefonica Movil Ltda";
+ m_mTable[1840][159] = "cl,Chile,56,Nextel SA";
+ m_mTable[1840][95] = "cl,Chile,56,Nextel SA";
+ m_mTable[1840][79] = "cl,Chile,56,Nextel SA";
+ m_mTable[1840][127] = "cl,Chile,56,TELEFONICA";
+ m_mTable[1840][47] = "cl,Chile,56,TELEFONICA";
+ m_mTable[1840][303] = "cl,Chile,56,Telestar Movil SA";
+ m_mTable[1840][15] = "cl,Chile,56,TESAM SA";
+ m_mTable[1840][319] = "cl,Chile,56,Tribe Mobile SPA";
+ m_mTable[1840][143] = "cl,Chile,56,VTR Banda Ancha SA";
+ m_mTable[1120][127] = "cn,China,86,China Mobile GSM";
+ m_mTable[1120][15] = "cn,China,86,China Mobile GSM";
+ m_mTable[1120][47] = "cn,China,86,China Mobile GSM";
+ m_mTable[1120][79] = "cn,China,86,China Space Mobile Satellite Telecommunications Co. Ltd (China Spacecom)";
+ m_mTable[1120][63] = "cn,China,86,China Telecom";
+ m_mTable[1120][95] = "cn,China,86,China Telecom";
+ m_mTable[1120][111] = "cn,China,86,China Unicom";
+ m_mTable[1120][31] = "cn,China,86,China Unicom";
+ m_mTable[1842][304] = "co,Colombia,57,Avantel SAS";
+ m_mTable[1842][258] = "co,Colombia,57,Movistar";
+ m_mTable[1842][259] = "co,Colombia,57,TIGO/Colombia Movil";
+ m_mTable[1842][1] = "co,Colombia,57,TIGO/Colombia Movil";
+ m_mTable[1842][257] = "co,Colombia,57,Comcel S.A. Occel S.A./Celcaribe";
+ m_mTable[1842][2] = "co,Colombia,57,Edatel S.A.";
+ m_mTable[1842][291] = "co,Colombia,57,Movistar";
+ m_mTable[1842][273] = "co,Colombia,57,TIGO/Colombia Movil";
+ m_mTable[1842][322] = "co,Colombia,57,UNE EPM Telecomunicaciones SA ESP";
+ m_mTable[1842][32] = "co,Colombia,57,UNE EPM Telecomunicaciones SA ESP";
+ m_mTable[1842][340] = "co,Colombia,57,Virgin Mobile Colombia SAS";
+ m_mTable[1620][31] = "km,Comoros,269,HURI - SNPT";
+ m_mTable[1584][2159] = "cd,Congo Dem. Rep.,243,Orange RDC sarl";
+ m_mTable[1584][95] = "cd,Congo Dem. Rep.,243,SuperCell";
+ m_mTable[1584][2207] = "cd,Congo Dem. Rep.,243,TIGO/Oasis";
+ m_mTable[1584][31] = "cd,Congo Dem. Rep.,243,Vodacom";
+ m_mTable[1584][2191] = "cd,Congo Dem. Rep.,243,Yozma Timeturns sprl (YTT)";
+ m_mTable[1584][47] = "cd,Congo Dem. Rep.,243,ZAIN CelTel";
+ m_mTable[1577][31] = "cg,Congo Republic,242,Airtel Congo SA";
+ m_mTable[1577][47] = "cg,Congo Republic,242,Zain/Celtel";
+ m_mTable[1577][271] = "cg,Congo Republic,242,MTN/Libertis";
+ m_mTable[1577][127] = "cg,Congo Republic,242,Warid";
+ m_mTable[1352][31] = "ck,Cook Islands,682,Telecom Cook Islands";
+ m_mTable[1810][63] = "cr,Costa Rica,506,Claro";
+ m_mTable[1810][47] = "cr,Costa Rica,506,ICE";
+ m_mTable[1810][31] = "cr,Costa Rica,506,ICE";
+ m_mTable[1810][79] = "cr,Costa Rica,506,Movistar";
+ m_mTable[1810][527] = "cr,Costa Rica,506,Virtualis";
+ m_mTable[537][31] = "hr,Croatia,385,T-Mobile/Cronet";
+ m_mTable[537][47] = "hr,Croatia,385,Tele2";
+ m_mTable[537][271] = "hr,Croatia,385,VIPnet d.o.o.";
+ m_mTable[872][31] = "cu,Cuba,53,C-COM";
+ m_mTable[866][2399] = "cw,Curacao,599,EOCG Wireless NV";
+ m_mTable[866][1695] = "cw,Curacao,599,Polycom N.V./ Digicel";
+ m_mTable[640][271] = "cy,Cyprus,357,MTN/Areeba";
+ m_mTable[640][527] = "cy,Cyprus,357,PrimeTel PLC";
+ m_mTable[640][31] = "cy,Cyprus,357,Vodafone/CyTa";
+ m_mTable[560][143] = "cz,Czech Rep.,420,Compatel s.r.o.";
+ m_mTable[560][47] = "cz,Czech Rep.,420,O2";
+ m_mTable[560][31] = "cz,Czech Rep.,420,T-Mobile / RadioMobil";
+ m_mTable[560][95] = "cz,Czech Rep.,420,Travel Telekommunikation s.r.o.";
+ m_mTable[560][79] = "cz,Czech Rep.,420,Ufone";
+ m_mTable[560][2463] = "cz,Czech Rep.,420,Vodafone";
+ m_mTable[560][63] = "cz,Czech Rep.,420,Vodafone";
+ m_mTable[568][95] = "dk,Denmark,45,ApS KBUS";
+ m_mTable[568][575] = "dk,Denmark,45,Banedanmark";
+ m_mTable[568][655] = "dk,Denmark,45,CoolTEL ApS";
+ m_mTable[568][111] = "dk,Denmark,45,Hi3G";
+ m_mTable[568][303] = "dk,Denmark,45,Lycamobile Ltd";
+ m_mTable[568][63] = "dk,Denmark,45,Mach Connectivity ApS";
+ m_mTable[568][127] = "dk,Denmark,45,";
+ m_mTable[568][79] = "dk,Denmark,45,NextGen Mobile Ltd (CardBoardFish)";
+ m_mTable[568][271] = "dk,Denmark,45,TDC Denmark";
+ m_mTable[568][31] = "dk,Denmark,45,TDC Denmark";
+ m_mTable[568][1919] = "dk,Denmark,45,Telenor/Sonofon";
+ m_mTable[568][47] = "dk,Denmark,45,Telenor/Sonofon";
+ m_mTable[568][527] = "dk,Denmark,45,Telia";
+ m_mTable[568][783] = "dk,Denmark,45,Telia";
+ m_mTable[1592][31] = "dj,Djibouti,253,Djibouti Telecom SA (Evatis)";
+ m_mTable[870][272] = "dm,Dominica,1767,C & W";
+ m_mTable[870][32] = "dm,Dominica,1767,Cingular Wireless/Digicel";
+ m_mTable[870][80] = "dm,Dominica,1767,Wireless Ventures (Dominica) Ltd (Digicel Dominica)";
+ m_mTable[880][47] = "do,Dominican Republic,1809,Claro";
+ m_mTable[880][31] = "do,Dominican Republic,1809,Orange";
+ m_mTable[880][63] = "do,Dominican Republic,1809,TRIcom";
+ m_mTable[880][79] = "do,Dominican Republic,1809,Trilogy Dominicana S. A.";
+ m_mTable[1856][47] = "ec,Ecuador,593,Alegro/Telcsa";
+ m_mTable[1856][15] = "ec,Ecuador,593,MOVISTAR/OteCel";
+ m_mTable[1856][31] = "ec,Ecuador,593,Porta/Conecel";
+ m_mTable[1538][31] = "eg,Egypt,20,EMS - Mobinil";
+ m_mTable[1538][63] = "eg,Egypt,20,ETISALAT";
+ m_mTable[1538][47] = "eg,Egypt,20,Vodafone/Mirsfone";
+ m_mTable[1798][31] = "sv,El Salvador,503,CLARO/CTE";
+ m_mTable[1798][47] = "sv,El Salvador,503,Digicel";
+ m_mTable[1798][95] = "sv,El Salvador,503,INTELFON SA de CV";
+ m_mTable[1798][79] = "sv,El Salvador,503,Telefonica";
+ m_mTable[1798][63] = "sv,El Salvador,503,Telemovil";
+ m_mTable[1575][63] = "gq,Equatorial Guinea,240,HiTs-GE";
+ m_mTable[1575][31] = "gq,Equatorial Guinea,240,ORANGE/GETESA";
+ m_mTable[1623][31] = "er,Eritrea,291,Eritel";
+ m_mTable[584][31] = "ee,Estonia,372,EMT GSM";
+ m_mTable[584][47] = "ee,Estonia,372,Radiolinja Eesti";
+ m_mTable[584][63] = "ee,Estonia,372,Tele2 Eesti AS";
+ m_mTable[584][79] = "ee,Estonia,372,Top Connect OU";
+ m_mTable[1590][31] = "et,Ethiopia,251,ETH/MTN";
+ m_mTable[1872][1] = "fk,Falkland Islands (Malvinas),500,Cable and Wireless South Atlantic Ltd (Falkland Islands";
+ m_mTable[648][63] = "fo,Faroe Islands,298,Edge Mobile Sp/F";
+ m_mTable[648][31] = "fo,Faroe Islands,298,Faroese Telecom";
+ m_mTable[648][47] = "fo,Faroe Islands,298,Kall GSM";
+ m_mTable[1346][47] = "fj,Fiji,679,DigiCell";
+ m_mTable[1346][31] = "fj,Fiji,679,Vodafone";
+ m_mTable[580][335] = "fi,Finland,358,Alands";
+ m_mTable[580][623] = "fi,Finland,358,Compatel Ltd";
+ m_mTable[580][319] = "fi,Finland,358,DNA/Finnet";
+ m_mTable[580][63] = "fi,Finland,358,DNA/Finnet";
+ m_mTable[580][303] = "fi,Finland,358,DNA/Finnet";
+ m_mTable[580][79] = "fi,Finland,358,DNA/Finnet";
+ m_mTable[580][543] = "fi,Finland,358,Elisa/Saunalahti";
+ m_mTable[580][95] = "fi,Finland,358,Elisa/Saunalahti";
+ m_mTable[580][2095] = "fi,Finland,358,ID-Mobile";
+ m_mTable[580][287] = "fi,Finland,358,Mundio Mobile (Finland) Ltd";
+ m_mTable[580][159] = "fi,Finland,358,Nokia Oyj";
+ m_mTable[580][271] = "fi,Finland,358,TDC Oy Finland";
+ m_mTable[580][2335] = "fi,Finland,358,TeliaSonera";
+ m_mTable[520][639] = "fr,France,33,AFONE SA";
+ m_mTable[520][2351] = "fr,France,33,Association Plate-forme Telecom";
+ m_mTable[520][655] = "fr,France,33,Astrium";
+ m_mTable[520][543] = "fr,France,33,Bouygues Telecom";
+ m_mTable[520][527] = "fr,France,33,Bouygues Telecom";
+ m_mTable[520][2191] = "fr,France,33,Bouygues Telecom";
+ m_mTable[520][335] = "fr,France,33,Lliad/FREE Mobile";
+ m_mTable[520][127] = "fr,France,33,GlobalStar";
+ m_mTable[520][111] = "fr,France,33,GlobalStar";
+ m_mTable[520][95] = "fr,France,33,GlobalStar";
+ m_mTable[520][671] = "fr,France,33,Orange";
+ m_mTable[520][367] = "fr,France,33,Lliad/FREE Mobile";
+ m_mTable[520][351] = "fr,France,33,Lliad/FREE Mobile";
+ m_mTable[520][607] = "fr,France,33,Lycamobile SARL";
+ m_mTable[520][63] = "fr,France,33,MobiquiThings";
+ m_mTable[520][591] = "fr,France,33,MobiquiThings";
+ m_mTable[520][799] = "fr,France,33,Mundio Mobile (France) Ltd";
+ m_mTable[520][623] = "fr,France,33,NRJ";
+ m_mTable[520][2207] = "fr,France,33,Virgin Mobile/Omer";
+ m_mTable[520][575] = "fr,France,33,Virgin Mobile/Omer";
+ m_mTable[520][47] = "fr,France,33,Orange";
+ m_mTable[520][31] = "fr,France,33,Orange";
+ m_mTable[520][2335] = "fr,France,33,Orange";
+ m_mTable[520][287] = "fr,France,33,S.F.R.";
+ m_mTable[520][271] = "fr,France,33,S.F.R.";
+ m_mTable[520][159] = "fr,France,33,S.F.R.";
+ m_mTable[520][319] = "fr,France,33,S.F.R.";
+ m_mTable[520][79] = "fr,France,33,SISTEER";
+ m_mTable[520][15] = "fr,France,33,Tel/Tel";
+ m_mTable[520][559] = "fr,France,33,Transatel SA";
+ m_mTable[832][527] = "fg,French Guiana,594,Bouygues/DigiCel";
+ m_mTable[832][31] = "fg,French Guiana,594,Orange Caribe";
+ m_mTable[832][47] = "fg,French Guiana,594,Outremer Telecom";
+ m_mTable[832][63] = "fg,French Guiana,594,TelCell GSM";
+ m_mTable[832][287] = "fg,French Guiana,594,TelCell GSM";
+ m_mTable[1351][351] = "pf,French Polynesia,689,Pacific Mobile Telecom (PMT)";
+ m_mTable[1351][527] = "pf,French Polynesia,689,Tikiphone";
+ m_mTable[1576][79] = "ga,Gabon,241,Azur/Usan S.A.";
+ m_mTable[1576][31] = "ga,Gabon,241,Libertis S.A.";
+ m_mTable[1576][47] = "ga,Gabon,241,MOOV/Telecel";
+ m_mTable[1576][63] = "ga,Gabon,241,ZAIN/Celtel Gabon S.A.";
+ m_mTable[1543][47] = "gm,Gambia,220,Africel";
+ m_mTable[1543][63] = "gm,Gambia,220,Comium";
+ m_mTable[1543][31] = "gm,Gambia,220,Gamcel";
+ m_mTable[1543][79] = "gm,Gambia,220,Q-Cell";
+ m_mTable[642][31] = "ge,Georgia,995,Geocell Ltd.";
+ m_mTable[642][63] = "ge,Georgia,995,Iberiatel Ltd.";
+ m_mTable[642][47] = "ge,Georgia,995,Magti GSM Ltd.";
+ m_mTable[642][79] = "ge,Georgia,995,MobiTel/Beeline";
+ m_mTable[642][95] = "ge,Georgia,995,Silknet";
+ m_mTable[610][383] = "de,Germany,49,E-Plus";
+ m_mTable[610][271] = "de,Germany,49,DB Netz AG";
+ //MCC(262) MNC(N/A) ISO(de) Country Code(Germany) Country(49) Carrier(Debitel)
+ m_mTable[610][63] = "de,Germany,49,E-Plus";
+ m_mTable[610][95] = "de,Germany,49,E-Plus";
+ m_mTable[610][1919] = "de,Germany,49,E-Plus";
+ m_mTable[610][303] = "de,Germany,49,E-Plus";
+ m_mTable[610][335] = "de,Germany,49,Group 3G UMTS";
+ m_mTable[610][1087] = "de,Germany,49,Lycamobile";
+ m_mTable[610][319] = "de,Germany,49,Mobilcom";
+ m_mTable[610][287] = "de,Germany,49,O2";
+ m_mTable[610][127] = "de,Germany,49,O2";
+ m_mTable[610][143] = "de,Germany,49,O2";
+ //MCC(262) MNC(N/A) ISO(de) Country Code(Germany) Country(49) Carrier(Talkline)
+ m_mTable[610][111] = "de,Germany,49,T-mobile/Telekom";
+ m_mTable[610][31] = "de,Germany,49,T-mobile/Telekom";
+ m_mTable[610][367] = "de,Germany,49,Telogic/ViStream";
+ m_mTable[610][159] = "de,Germany,49,Vodafone D2";
+ m_mTable[610][79] = "de,Germany,49,Vodafone D2";
+ m_mTable[610][47] = "de,Germany,49,Vodafone D2";
+ m_mTable[1568][79] = "gh,Ghana,233,Expresso Ghana Ltd";
+ m_mTable[1568][127] = "gh,Ghana,233,GloMobile";
+ m_mTable[1568][63] = "gh,Ghana,233,Milicom/Tigo";
+ m_mTable[1568][31] = "gh,Ghana,233,MTN";
+ m_mTable[1568][47] = "gh,Ghana,233,Vodafone";
+ m_mTable[1568][111] = "gh,Ghana,233,Airtel/ZAIN";
+ m_mTable[614][111] = "gi,Gibraltar,350,CTS Mobile";
+ m_mTable[614][159] = "gi,Gibraltar,350,eazi telecom";
+ m_mTable[614][31] = "gi,Gibraltar,350,Gibtel GSM";
+ m_mTable[514][127] = "gr,Greece,30,AMD Telecom SA";
+ m_mTable[514][47] = "gr,Greece,30,Cosmote";
+ m_mTable[514][31] = "gr,Greece,30,Cosmote";
+ m_mTable[514][79] = "gr,Greece,30,Organismos Sidirodromon Ellados (OSE)";
+ m_mTable[514][63] = "gr,Greece,30,OTE Hellenic Telecommunications Organization SA";
+ m_mTable[514][271] = "gr,Greece,30,Tim/Wind";
+ m_mTable[514][159] = "gr,Greece,30,Tim/Wind";
+ m_mTable[514][95] = "gr,Greece,30,Vodafone";
+ m_mTable[656][31] = "gl,Greenland,299,Tele Greenland";
+ m_mTable[850][272] = "gd,Grenada,1473,Cable & Wireless";
+ m_mTable[850][48] = "gd,Grenada,1473,Digicel";
+ m_mTable[850][80] = "gd,Grenada,1473,Digicel";
+ m_mTable[832][143] = "gp,Guadeloupe,590,Dauphin Telecom SU (Guadeloupe Telecom) (Guadeloupe";
+ m_mTable[832][271] = "gp,Guadeloupe,590,";
+ m_mTable[784][880] = "gu,Guam,1671,Docomo";
+ m_mTable[784][1136] = "gu,Guam,1671,Docomo";
+ m_mTable[784][320] = "gu,Guam,1671,GTA Wireless";
+ m_mTable[784][51] = "gu,Guam,1671,Guam Teleph. Auth.";
+ m_mTable[784][50] = "gu,Guam,1671,IT&E OverSeas";
+ m_mTable[785][592] = "gu,Guam,1671,Wave Runner LLC";
+ m_mTable[1796][31] = "gt,Guatemala,502,SERCOM";
+ m_mTable[1796][63] = "gt,Guatemala,502,Telefonica";
+ m_mTable[1796][47] = "gt,Guatemala,502,TIGO/COMCEL";
+ m_mTable[1553][79] = "gn,Guinea,224,Areeba - MTN";
+ m_mTable[1553][95] = "gn,Guinea,224,Celcom";
+ m_mTable[1553][63] = "gn,Guinea,224,Intercel";
+ m_mTable[1553][31] = "gn,Guinea,224,Orange/Spacetel";
+ m_mTable[1553][47] = "gn,Guinea,224,SotelGui";
+ m_mTable[1586][31] = "gw,Guinea-Bissau,245,GuineTel";
+ m_mTable[1586][63] = "gw,Guinea-Bissau,245,Orange";
+ m_mTable[1586][47] = "gw,Guinea-Bissau,245,SpaceTel";
+ m_mTable[1848][47] = "gy,Guyana,592,Cellink Plus";
+ m_mTable[1848][31] = "gy,Guyana,592,DigiCel";
+ m_mTable[882][31] = "ht,Haiti,509,Comcel";
+ m_mTable[882][47] = "ht,Haiti,509,Digicel";
+ m_mTable[882][63] = "ht,Haiti,509,National Telecom SA (NatCom)";
+ m_mTable[1800][1039] = "hn,Honduras,504,Digicel";
+ m_mTable[1800][783] = "hn,Honduras,504,HonduTel";
+ m_mTable[1800][31] = "hn,Honduras,504,SERCOM/CLARO";
+ m_mTable[1800][47] = "hn,Honduras,504,Telefonica/CELTEL";
+ m_mTable[1108][319] = "hk,Hongkong China,852,China Mobile/Peoples";
+ m_mTable[1108][303] = "hk,Hongkong China,852,China Mobile/Peoples";
+ m_mTable[1108][159] = "hk,Hongkong China,852,China Motion";
+ m_mTable[1108][127] = "hk,Hongkong China,852,China Unicom Ltd";
+ m_mTable[1108][287] = "hk,Hongkong China,852,China-HongKong Telecom Ltd (CHKTL)";
+ m_mTable[1108][31] = "hk,Hongkong China,852,Citic Telecom Ltd.";
+ m_mTable[1108][47] = "hk,Hongkong China,852,CSL Ltd.";
+ m_mTable[1108][15] = "hk,Hongkong China,852,CSL Ltd.";
+ m_mTable[1108][399] = "hk,Hongkong China,852,CSL Ltd.";
+ m_mTable[1108][271] = "hk,Hongkong China,852,CSL/New World PCS Ltd.";
+ m_mTable[1108][335] = "hk,Hongkong China,852,H3G/Hutchinson";
+ m_mTable[1108][95] = "hk,Hongkong China,852,H3G/Hutchinson";
+ m_mTable[1108][79] = "hk,Hongkong China,852,H3G/Hutchinson";
+ m_mTable[1108][63] = "hk,Hongkong China,852,H3G/Hutchinson";
+ m_mTable[1108][415] = "hk,Hongkong China,852,HKT/PCCW";
+ m_mTable[1108][527] = "hk,Hongkong China,852,HKT/PCCW";
+ m_mTable[1108][671] = "hk,Hongkong China,852,HKT/PCCW";
+ m_mTable[1108][367] = "hk,Hongkong China,852,HKT/PCCW";
+ m_mTable[1108][1151] = "hk,Hongkong China,852,shared by private TETRA systems";
+ m_mTable[1108][1039] = "hk,Hongkong China,852,shared by private TETRA systems";
+ m_mTable[1108][143] = "hk,Hongkong China,852,Trident Telecom Ventures Ltd.";
+ m_mTable[1108][383] = "hk,Hongkong China,852,Vodafone/SmarTone";
+ m_mTable[1108][351] = "hk,Hongkong China,852,Vodafone/SmarTone";
+ m_mTable[1108][111] = "hk,Hongkong China,852,Vodafone/SmarTone";
+ m_mTable[534][31] = "hu,Hungary,36,Pannon/Telenor";
+ m_mTable[534][783] = "hu,Hungary,36,T-mobile/Magyar";
+ m_mTable[534][1823] = "hu,Hungary,36,UPC Magyarorszag Kft.";
+ m_mTable[534][1807] = "hu,Hungary,36,Vodafone";
+ m_mTable[628][159] = "is,Iceland,354,Amitelo";
+ m_mTable[628][127] = "is,Iceland,354,IceCell";
+ m_mTable[628][143] = "is,Iceland,354,Landssiminn";
+ m_mTable[628][31] = "is,Iceland,354,Landssiminn";
+ m_mTable[628][287] = "is,Iceland,354,NOVA";
+ m_mTable[628][79] = "is,Iceland,354,VIKING/IMC";
+ m_mTable[628][63] = "is,Iceland,354,Vodafone/Tal hf";
+ m_mTable[628][47] = "is,Iceland,354,Vodafone/Tal hf";
+ m_mTable[628][95] = "is,Iceland,354,Vodafone/Tal hf";
+ m_mTable[1028][655] = "in,India,91,Aircel";
+ m_mTable[1028][607] = "in,India,91,Aircel";
+ m_mTable[1028][383] = "in,India,91,Aircel";
+ m_mTable[1028][1071] = "in,India,91,Aircel";
+ m_mTable[1028][831] = "in,India,91,Aircel";
+ m_mTable[1028][671] = "in,India,91,Aircel";
+ m_mTable[1028][31] = "in,India,91,Aircel Digilink India";
+ m_mTable[1028][351] = "in,India,91,Aircel Digilink India";
+ m_mTable[1028][1551] = "in,India,91,Aircel Digilink India";
+ m_mTable[1029][1343] = "in,India,91,AirTel";
+ m_mTable[1028][2159] = "in,India,91,Barakhamba Sales & Serv.";
+ m_mTable[1028][319] = "in,India,91,Barakhamba Sales & Serv.";
+ m_mTable[1028][1919] = "in,India,91,BSNL";
+ m_mTable[1028][1615] = "in,India,91,BSNL";
+ m_mTable[1028][1359] = "in,India,91,BSNL";
+ m_mTable[1028][1823] = "in,India,91,BSNL";
+ m_mTable[1028][1903] = "in,India,91,BSNL";
+ m_mTable[1028][1583] = "in,India,91,BSNL";
+ m_mTable[1028][1343] = "in,India,91,BSNL";
+ m_mTable[1028][1439] = "in,India,91,BSNL";
+ m_mTable[1028][1887] = "in,India,91,BSNL";
+ m_mTable[1028][1311] = "in,India,91,BSNL";
+ m_mTable[1028][1423] = "in,India,91,BSNL";
+ m_mTable[1028][2079] = "in,India,91,BSNL";
+ m_mTable[1028][1871] = "in,India,91,BSNL";
+ m_mTable[1028][911] = "in,India,91,BSNL";
+ m_mTable[1028][1407] = "in,India,91,BSNL";
+ m_mTable[1028][2063] = "in,India,91,BSNL";
+ m_mTable[1028][1855] = "in,India,91,BSNL";
+ m_mTable[1028][847] = "in,India,91,BSNL";
+ m_mTable[1028][1647] = "in,India,91,BSNL";
+ m_mTable[1028][1375] = "in,India,91,BSNL";
+ m_mTable[1028][1839] = "in,India,91,BSNL";
+ m_mTable[1029][271] = "in,India,91,Bharti Airtel Limited (Delhi)";
+ m_mTable[1028][1951] = "in,India,91,CellOne A&N";
+ m_mTable[1028][2095] = "in,India,91,Escorts Telecom Ltd.";
+ m_mTable[1028][2207] = "in,India,91,Escorts Telecom Ltd.";
+ m_mTable[1028][2191] = "in,India,91,Escorts Telecom Ltd.";
+ m_mTable[1028][2175] = "in,India,91,Escorts Telecom Ltd.";
+ m_mTable[1028][415] = "in,India,91,Escotel Mobile Communications";
+ m_mTable[1028][1391] = "in,India,91,Escotel Mobile Communications";
+ m_mTable[1028][303] = "in,India,91,Escotel Mobile Communications";
+ m_mTable[1029][95] = "in,India,91,Fascel Limited";
+ m_mTable[1028][95] = "in,India,91,Fascel";
+ m_mTable[1028][1807] = "in,India,91,Hexacom India";
+ m_mTable[1028][367] = "in,India,91,Hexcom India";
+ m_mTable[1028][1935] = "in,India,91,Idea Cellular Ltd.";
+ m_mTable[1028][127] = "in,India,91,Idea Cellular Ltd.";
+ m_mTable[1028][79] = "in,India,91,Idea Cellular Ltd.";
+ m_mTable[1028][591] = "in,India,91,Idea Cellular Ltd.";
+ m_mTable[1028][559] = "in,India,91,Idea Cellular Ltd.";
+ m_mTable[1028][1679] = "in,India,91,Mahanagar Telephone Nigam";
+ m_mTable[1028][1695] = "in,India,91,Mahanagar Telephone Nigam";
+ m_mTable[1028][2111] = "in,India,91,Reliable Internet Services";
+ m_mTable[1028][1295] = "in,India,91,Reliance Telecom Private";
+ m_mTable[1028][1663] = "in,India,91,Reliance Telecom Private";
+ m_mTable[1028][399] = "in,India,91,Reliance Telecom Private";
+ m_mTable[1028][2143] = "in,India,91,Reliance Telecom Private";
+ m_mTable[1028][159] = "in,India,91,Reliance Telecom Private";
+ m_mTable[1028][879] = "in,India,91,Reliance Telecom Private";
+ m_mTable[1028][1327] = "in,India,91,Reliance Telecom Private";
+ m_mTable[1028][1055] = "in,India,91,RPG Cellular";
+ m_mTable[1028][335] = "in,India,91,Spice";
+ m_mTable[1028][1103] = "in,India,91,Spice";
+ m_mTable[1028][287] = "in,India,91,Sterling Cellular Ltd.";
+ m_mTable[1028][783] = "in,India,91,Usha Martin Telecom";
+ m_mTable[1296][143] = "id,Indonesia,62,Axis/Natrindo";
+ m_mTable[1296][2207] = "id,Indonesia,62,H3G CP";
+ m_mTable[1296][31] = "id,Indonesia,62,Indosat/Satelindo/M3";
+ m_mTable[1296][543] = "id,Indonesia,62,Indosat/Satelindo/M3";
+ m_mTable[1296][15] = "id,Indonesia,62,PT Pasifik Satelit Nusantara (PSN)";
+ m_mTable[1296][639] = "id,Indonesia,62,PT Sampoerna Telekomunikasi Indonesia (STI)";
+ m_mTable[1296][655] = "id,Indonesia,62,PT Smartfren Telecom Tbk";
+ m_mTable[1296][159] = "id,Indonesia,62,PT Smartfren Telecom Tbk";
+ m_mTable[1296][287] = "id,Indonesia,62,PT. Excelcom";
+ m_mTable[1296][271] = "id,Indonesia,62,Telkomsel";
+ m_mTable[2305][319] = "n/a,International Networks,882,Antarctica";
+ m_mTable[1074][415] = "ir,Iran,98,Mobile Telecommunications Company of Esfahan JV-PJS (MTCE)";
+ m_mTable[1074][1807] = "ir,Iran,98,MTCE";
+ m_mTable[1074][863] = "ir,Iran,98,MTN/IranCell";
+ m_mTable[1074][815] = "ir,Iran,98,Taliya";
+ m_mTable[1074][287] = "ir,Iran,98,TCI / MCI";
+ m_mTable[1074][335] = "ir,Iran,98,TKC/KFZO";
+ m_mTable[1048][95] = "iq,Iraq,964,Asia Cell";
+ m_mTable[1048][2351] = "iq,Iraq,964,Itisaluna and Kalemat";
+ m_mTable[1048][1039] = "iq,Iraq,964,Korek";
+ m_mTable[1048][2095] = "iq,Iraq,964,Korek";
+ m_mTable[1048][1119] = "iq,Iraq,964,Mobitel (Iraq-Kurdistan) and Moutiny";
+ m_mTable[1048][527] = "iq,Iraq,964,ZAIN/Atheer";
+ m_mTable[1048][783] = "iq,Iraq,964,Orascom Telecom";
+ m_mTable[1048][143] = "iq,Iraq,964,Sanatel";
+ m_mTable[626][79] = "ie,Ireland,353,Access Telecom Ltd.";
+ m_mTable[626][159] = "ie,Ireland,353,Clever Communications Ltd";
+ m_mTable[626][127] = "ie,Ireland,353,eircom Ltd";
+ m_mTable[626][95] = "ie,Ireland,353,H3G";
+ m_mTable[626][287] = "ie,Ireland,353,Liffey Telecom";
+ m_mTable[626][319] = "ie,Ireland,353,Lycamobile";
+ m_mTable[626][63] = "ie,Ireland,353,Meteor Mobile Ltd.";
+ m_mTable[626][47] = "ie,Ireland,353,O2/Digifone";
+ m_mTable[626][31] = "ie,Ireland,353,Vodafone Eircell";
+ m_mTable[1061][335] = "il,Israel,972,Alon Cellular Ltd";
+ m_mTable[1061][47] = "il,Israel,972,Cellcom ltd.";
+ m_mTable[1061][143] = "il,Israel,972,Golan Telekom";
+ m_mTable[1061][351] = "il,Israel,972,Home Cellular Ltd";
+ m_mTable[1061][127] = "il,Israel,972,Hot Mobile/Mirs";
+ m_mTable[1061][1919] = "il,Israel,972,Hot Mobile/Mirs";
+ m_mTable[1061][31] = "il,Israel,972,Orange/Partner Co. Ltd.";
+ m_mTable[1061][63] = "il,Israel,972,Pelephone";
+ m_mTable[1061][367] = "il,Israel,972,Rami Levy Hashikma Marketing Communications Ltd";
+ m_mTable[546][847] = "it,Italy,39,BT Italia SpA";
+ m_mTable[546][47] = "it,Italy,39,Elsacom";
+ m_mTable[546][2463] = "it,Italy,39,Hi3G";
+ m_mTable[546][831] = "it,Italy,39,Hi3G";
+ m_mTable[546][1919] = "it,Italy,39,IPSE 2000";
+ m_mTable[546][863] = "it,Italy,39,Lycamobile Srl";
+ m_mTable[546][127] = "it,Italy,39,Noverca Italia Srl";
+ m_mTable[546][783] = "it,Italy,39,RFI Rete Ferroviaria Italiana SpA";
+ m_mTable[546][1167] = "it,Italy,39,Telecom Italia Mobile SpA";
+ m_mTable[546][1087] = "it,Italy,39,Telecom Italia Mobile SpA";
+ m_mTable[546][31] = "it,Italy,39,TIM";
+ m_mTable[546][271] = "it,Italy,39,Vodafone";
+ m_mTable[546][111] = "it,Italy,39,Vodafone";
+ m_mTable[546][2191] = "it,Italy,39,WIND (Blu) -";
+ m_mTable[546][1103] = "it,Italy,39,WIND (Blu) -";
+ m_mTable[1554][127] = "ci,Ivory Coast,225,Aircomm SA";
+ m_mTable[1554][47] = "ci,Ivory Coast,225,Atlantik Tel./Moov";
+ m_mTable[1554][79] = "ci,Ivory Coast,225,Comium";
+ m_mTable[1554][31] = "ci,Ivory Coast,225,Comstar";
+ m_mTable[1554][95] = "ci,Ivory Coast,225,MTN";
+ m_mTable[1554][63] = "ci,Ivory Coast,225,Orange";
+ m_mTable[1554][111] = "ci,Ivory Coast,225,OriCell";
+ m_mTable[824][272] = "jm,Jamaica,1876,Cable & Wireless";
+ m_mTable[824][32] = "jm,Jamaica,1876,Cable & Wireless";
+ m_mTable[824][384] = "jm,Jamaica,1876,Cable & Wireless";
+ m_mTable[824][80] = "jm,Jamaica,1876,DIGICEL/Mossel";
+ m_mTable[1088][15] = "jp,Japan,81,eMobile";
+ m_mTable[1088][1343] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1919] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][143] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1839] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1359] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1951] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][127] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1855] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1375] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][2191] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1295] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1871] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1807] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][2207] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1311] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1887] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1391] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1089][1807] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1327] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1903] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][1823] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][607] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1615] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][895] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][639] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][47] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][559] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][1087] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][799] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][2175] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][383] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][2351] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1631] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][879] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][655] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][63] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][303] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1423] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][2335] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][815] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1567] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][399] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][2367] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][1039] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1647] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][863] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][671] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][159] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1183] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][831] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1551] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][415] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][2319] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][2383] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][1055] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1663] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][335] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][783] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][271] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1583] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][927] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][591] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][31] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][527] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][1119] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][2447] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][1071] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1679] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][351] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][623] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][287] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1599] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][911] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][319] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][575] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][543] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][1103] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1089][2463] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][847] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1695] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][367] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][2463] = "jp,Japan,81,NTT Docomo";
+ m_mTable[1088][1935] = "jp,Japan,81,Okinawa Cellular Telephone";
+ m_mTable[1089][1615] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1135] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2431] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1071] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2319] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1089][1631] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2351] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2447] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1087] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2367] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1167] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][111] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1089][1567] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1103] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2383] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][79] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1089][1583] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1119] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2415] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1039] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1089][1599] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1151] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2399] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][1055] = "jp,Japan,81,SoftBank Mobile Corp";
+ m_mTable[1088][2111] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][2143] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][2079] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][2063] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][2159] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][2127] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1088][2095] = "jp,Japan,81,KDDI Corporation";
+ m_mTable[1046][1919] = "jo,Jordan,962,Orange/Petra";
+ m_mTable[1046][63] = "jo,Jordan,962,Umniah Mobile Co.";
+ m_mTable[1046][47] = "jo,Jordan,962,Xpress";
+ m_mTable[1046][31] = "jo,Jordan,962,ZAIN /J.M.T.S";
+ m_mTable[1025][31] = "kz,Kazakhstan,7,Beeline/KaR-Tel LLP";
+ m_mTable[1025][127] = "kz,Kazakhstan,7,Dalacom/Altel";
+ m_mTable[1025][47] = "kz,Kazakhstan,7,K-Cell";
+ m_mTable[1025][1919] = "kz,Kazakhstan,7,Tele2/NEO/MTS";
+ m_mTable[1593][95] = "ke,Kenya,254,Econet Wireless";
+ m_mTable[1593][127] = "ke,Kenya,254,Orange";
+ m_mTable[1593][47] = "ke,Kenya,254,Safaricom Ltd.";
+ m_mTable[1593][63] = "ke,Kenya,254,Zain/Celtel Ltd.";
+ m_mTable[1349][159] = "ki,Kiribati,686,Kiribati Frigate";
+ m_mTable[1127][403] = "kp,Korea N. Dem. People's Rep.,850,Sun Net";
+ m_mTable[1104][47] = "kr,Korea S Republic of,82,KT Freetel Co. Ltd.";
+ m_mTable[1104][79] = "kr,Korea S Republic of,82,KT Freetel Co. Ltd.";
+ m_mTable[1104][143] = "kr,Korea S Republic of,82,KT Freetel Co. Ltd.";
+ m_mTable[1104][111] = "kr,Korea S Republic of,82,LG Telecom";
+ m_mTable[1104][63] = "kr,Korea S Republic of,82,SK Telecom";
+ m_mTable[1104][95] = "kr,Korea S Republic of,82,SK Telecom Co. Ltd";
+ m_mTable[1049][79] = "kw,Kuwait,965,Viva";
+ m_mTable[1049][63] = "kw,Kuwait,965,Wantaniya";
+ m_mTable[1049][47] = "kw,Kuwait,965,Zain";
+ m_mTable[1079][63] = "kg,Kyrgyzstan,996,AkTel LLC";
+ m_mTable[1079][31] = "kg,Kyrgyzstan,996,Beeline/Bitel";
+ m_mTable[1079][95] = "kg,Kyrgyzstan,996,MEGACOM";
+ m_mTable[1079][159] = "kg,Kyrgyzstan,996,O!/NUR Telecom";
+ m_mTable[1111][47] = "la,Laos P.D.R.,856,ETL Mobile";
+ m_mTable[1111][31] = "la,Laos P.D.R.,856,Lao Tel";
+ m_mTable[1111][143] = "la,Laos P.D.R.,856,Tigo/Millicom";
+ m_mTable[1111][63] = "la,Laos P.D.R.,856,UNITEL/LAT";
+ m_mTable[583][95] = "lv,Latvia,371,Bite";
+ m_mTable[583][31] = "lv,Latvia,371,Latvian Mobile Phone";
+ m_mTable[583][159] = "lv,Latvia,371,SIA Camel Mobile";
+ m_mTable[583][143] = "lv,Latvia,371,SIA IZZI";
+ m_mTable[583][127] = "lv,Latvia,371,SIA Master Telecom";
+ m_mTable[583][111] = "lv,Latvia,371,SIA Rigatta";
+ m_mTable[583][47] = "lv,Latvia,371,Tele2";
+ m_mTable[583][63] = "lv,Latvia,371,TRIATEL/Telekom Baltija";
+ m_mTable[1045][815] = "lb,Lebanon,961,Cellis";
+ m_mTable[1045][863] = "lb,Lebanon,961,Cellis";
+ m_mTable[1045][831] = "lb,Lebanon,961,Cellis";
+ m_mTable[1045][847] = "lb,Lebanon,961,FTML Cellis";
+ m_mTable[1045][927] = "lb,Lebanon,961,MIC2/LibanCell";
+ m_mTable[1045][911] = "lb,Lebanon,961,MIC2/LibanCell";
+ m_mTable[1045][895] = "lb,Lebanon,961,MIC2/LibanCell";
+ m_mTable[1045][31] = "lb,Lebanon,961,MIC1 (Alfa)";
+ m_mTable[1045][63] = "lb,Lebanon,961,MIC2/LibanCell";
+ m_mTable[1045][879] = "lb,Lebanon,961,MIC2/LibanCell";
+ m_mTable[1617][47] = "ls,Lesotho,266,Econet/Ezi-cel";
+ m_mTable[1617][31] = "ls,Lesotho,266,Vodacom Lesotho";
+ m_mTable[1560][127] = "lr,Liberia,231,Celcom";
+ m_mTable[1560][63] = "lr,Liberia,231,Celcom";
+ m_mTable[1560][79] = "lr,Liberia,231,Comium BVI";
+ m_mTable[1560][47] = "lr,Liberia,231,Libercell";
+ m_mTable[1560][527] = "lr,Liberia,231,LibTelco";
+ m_mTable[1560][31] = "lr,Liberia,231,Lonestar";
+ m_mTable[1542][47] = "ly,Libya,218,Al-Madar";
+ m_mTable[1542][31] = "ly,Libya,218,Al-Madar";
+ m_mTable[1542][111] = "ly,Libya,218,Hatef";
+ m_mTable[1542][15] = "ly,Libya,218,Libyana";
+ m_mTable[1542][63] = "ly,Libya,218,Libyana";
+ m_mTable[661][111] = "li,Liechtenstein,423,CUBIC (Liechtenstein";
+ m_mTable[661][127] = "li,Liechtenstein,423,First Mobile AG";
+ m_mTable[661][95] = "li,Liechtenstein,423,Mobilkom AG";
+ m_mTable[661][47] = "li,Liechtenstein,423,Orange";
+ m_mTable[661][31] = "li,Liechtenstein,423,Swisscom FL AG";
+ m_mTable[661][1919] = "li,Liechtenstein,423,Alpmobile/Tele2";
+ m_mTable[582][47] = "lt,Lithuania,370,Bite";
+ m_mTable[582][31] = "lt,Lithuania,370,Omnitel";
+ m_mTable[582][63] = "lt,Lithuania,370,Tele2";
+ m_mTable[624][1919] = "lu,Luxembourg,352,Millicom Tango GSM";
+ m_mTable[624][31] = "lu,Luxembourg,352,P+T LUXGSM";
+ m_mTable[624][2463] = "lu,Luxembourg,352,VOXmobile S.A.";
+ m_mTable[1109][79] = "mo,Macao China,853,C.T.M. TELEMOVEL+";
+ m_mTable[1109][31] = "mo,Macao China,853,C.T.M. TELEMOVEL+";
+ m_mTable[1109][47] = "mo,Macao China,853,China Telecom";
+ m_mTable[1109][95] = "mo,Macao China,853,Hutchison Telephone (Macau) Company Ltd";
+ m_mTable[1109][63] = "mo,Macao China,853,Hutchison Telephone (Macau) Company Ltd";
+ m_mTable[1109][111] = "mo,Macao China,853,Smartone Mobile";
+ m_mTable[1109][15] = "mo,Macao China,853,Smartone Mobile";
+ m_mTable[660][1887] = "mk,Macedonia,389,MTS/Cosmofone";
+ m_mTable[660][47] = "mk,Macedonia,389,MTS/Cosmofone";
+ m_mTable[660][31] = "mk,Macedonia,389,T-Mobile/Mobimak";
+ m_mTable[660][63] = "mk,Macedonia,389,VIP Mobile";
+ m_mTable[1606][31] = "mg,Madagascar,261,MADACOM";
+ m_mTable[1606][47] = "mg,Madagascar,261,Orange/Soci";
+ m_mTable[1606][63] = "mg,Madagascar,261,Sacel";
+ m_mTable[1606][79] = "mg,Madagascar,261,Telma";
+ m_mTable[1616][31] = "mw,Malawi,265,TNM/Telekom Network Ltd.";
+ m_mTable[1616][271] = "mw,Malawi,265,Zain/Celtel ltd.";
+ m_mTable[1282][31] = "my,Malaysia,60,Art900";
+ m_mTable[1282][337] = "my,Malaysia,60,Baraka Telecom Sdn Bhd";
+ m_mTable[1282][415] = "my,Malaysia,60,CelCom";
+ m_mTable[1282][319] = "my,Malaysia,60,CelCom";
+ m_mTable[1282][367] = "my,Malaysia,60,Digi Telecommunications";
+ m_mTable[1282][271] = "my,Malaysia,60,Digi Telecommunications";
+ m_mTable[1282][527] = "my,Malaysia,60,Electcoms Wireless Sdn Bhd";
+ m_mTable[1282][383] = "my,Malaysia,60,Maxis";
+ m_mTable[1282][303] = "my,Malaysia,60,Maxis";
+ m_mTable[1282][287] = "my,Malaysia,60,MTX Utara";
+ m_mTable[1282][339] = "my,Malaysia,60,Packet One Networks (Malaysia) Sdn Bhd";
+ m_mTable[1282][341] = "my,Malaysia,60,Samata Communications Sdn Bhd";
+ m_mTable[1282][340] = "my,Malaysia,60,Talk Focus Sdn Bhd";
+ m_mTable[1282][399] = "my,Malaysia,60,U Mobile";
+ m_mTable[1282][338] = "my,Malaysia,60,YES";
+ m_mTable[1138][31] = "mv,Maldives,960,Dhiraagu/C&W";
+ m_mTable[1138][47] = "mv,Maldives,960,Wataniya/WMOBILE";
+ m_mTable[1552][31] = "ml,Mali,223,Malitel";
+ m_mTable[1552][47] = "ml,Mali,223,Orange/IKATEL";
+ m_mTable[632][543] = "mt,Malta,356,GO/Mobisle";
+ m_mTable[632][1919] = "mt,Malta,356,Melita";
+ m_mTable[632][31] = "mt,Malta,356,Vodafone";
+ m_mTable[832][303] = "mq,Martinique (French Department of),596,UTS Caraibe";
+ m_mTable[1545][47] = "mr,Mauritania,222,Chinguitel SA";
+ m_mTable[1545][31] = "mr,Mauritania,222,Mattel";
+ m_mTable[1545][271] = "mr,Mauritania,222,Mauritel";
+ m_mTable[1559][271] = "mu,Mauritius,230,Emtel Ltd";
+ m_mTable[1559][47] = "mu,Mauritius,230,Mahanagar Telephone";
+ m_mTable[1559][63] = "mu,Mauritius,230,Mahanagar Telephone";
+ m_mTable[1559][31] = "mu,Mauritius,230,Orange/Cellplus";
+ m_mTable[820][15] = "mx,Mexico,52,Axtel";
+ m_mTable[820][1295] = "mx,Mexico,52,IUSACell/UneFon";
+ m_mTable[820][80] = "mx,Mexico,52,IUSACell/UneFon";
+ m_mTable[820][64] = "mx,Mexico,52,IUSACell/UneFon";
+ m_mTable[820][79] = "mx,Mexico,52,IUSACell/UneFon";
+ m_mTable[820][63] = "mx,Mexico,52,Movistar/Pegaso";
+ m_mTable[820][48] = "mx,Mexico,52,Movistar/Pegaso";
+ m_mTable[820][16] = "mx,Mexico,52,NEXTEL";
+ m_mTable[820][31] = "mx,Mexico,52,NEXTEL";
+ m_mTable[820][144] = "mx,Mexico,52,NEXTEL";
+ m_mTable[820][128] = "mx,Mexico,52,Operadora Unefon SA de CV";
+ m_mTable[820][112] = "mx,Mexico,52,Operadora Unefon SA de CV";
+ m_mTable[820][96] = "mx,Mexico,52,SAI PCS";
+ m_mTable[820][32] = "mx,Mexico,52,TelCel/America Movil";
+ m_mTable[820][47] = "mx,Mexico,52,TelCel/America Movil";
+ m_mTable[1360][31] = "fm,Micronesia,691,FSM Telecom";
+ m_mTable[601][79] = "md,Moldova,373,Eventis Mobile";
+ m_mTable[601][95] = "md,Moldova,373,IDC/Unite";
+ m_mTable[601][63] = "md,Moldova,373,IDC/Unite";
+ m_mTable[601][2463] = "md,Moldova,373,IDC/Unite";
+ m_mTable[601][47] = "md,Moldova,373,Moldcell";
+ m_mTable[601][31] = "md,Moldova,373,Orange/Voxtel";
+ m_mTable[530][271] = "mc,Monaco,377,Monaco Telecom";
+ m_mTable[530][31] = "mc,Monaco,377,Monaco Telecom";
+ m_mTable[1064][2447] = "mn,Mongolia,976,G-Mobile Corporation Ltd";
+ m_mTable[1064][2463] = "mn,Mongolia,976,Mobicom";
+ m_mTable[1064][15] = "mn,Mongolia,976,Skytel Co. Ltd";
+ m_mTable[1064][2191] = "mn,Mongolia,976,Unitel";
+ m_mTable[663][47] = "me,Montenegro,382,Monet/T-mobile";
+ m_mTable[663][63] = "me,Montenegro,382,Mtel";
+ m_mTable[663][31] = "me,Montenegro,382,Promonte GSM";
+ m_mTable[852][2144] = "ms,Montserrat,1664,Cable & Wireless";
+ m_mTable[1540][31] = "ma,Morocco,212,IAM/Itissallat";
+ m_mTable[1540][47] = "ma,Morocco,212,INWI/WANA";
+ m_mTable[1540][15] = "ma,Morocco,212,Medi Telecom";
+ m_mTable[1603][31] = "mz,Mozambique,258,mCel";
+ m_mTable[1603][63] = "mz,Mozambique,258,Movitel";
+ m_mTable[1603][79] = "mz,Mozambique,258,Vodacom";
+ m_mTable[1609][63] = "na,Namibia,264,Leo / Orascom";
+ m_mTable[1609][31] = "na,Namibia,264,MTC";
+ m_mTable[1609][47] = "na,Namibia,264,Switch/Nam. Telec.";
+ m_mTable[1065][47] = "np,Nepal,977,Ncell";
+ m_mTable[1065][31] = "np,Nepal,977,NT Mobile / Namaste";
+ m_mTable[1065][79] = "np,Nepal,977,Smart Cell";
+ m_mTable[516][335] = "nl,Netherlands,31,6GMOBILE BV";
+ m_mTable[516][575] = "nl,Netherlands,31,Aspider Solutions";
+ m_mTable[516][95] = "nl,Netherlands,31,Elephant Talk Communications Premium Rate Services Netherlands BV";
+ m_mTable[516][383] = "nl,Netherlands,31,Intercity Mobile Communications BV";
+ m_mTable[516][271] = "nl,Netherlands,31,KPN Telecom B.V.";
+ m_mTable[516][143] = "nl,Netherlands,31,KPN Telecom B.V.";
+ m_mTable[516][1695] = "nl,Netherlands,31,KPN Telecom B.V.";
+ m_mTable[516][303] = "nl,Netherlands,31,KPN/Telfort";
+ m_mTable[516][655] = "nl,Netherlands,31,Lancelot BV";
+ m_mTable[516][159] = "nl,Netherlands,31,Lycamobile Ltd";
+ m_mTable[516][111] = "nl,Netherlands,31,Mundio/Vectone Mobile";
+ m_mTable[516][543] = "nl,Netherlands,31,NS Railinfrabeheer B.V.";
+ m_mTable[516][591] = "nl,Netherlands,31,Private Mobility Nederland BV";
+ m_mTable[516][2447] = "nl,Netherlands,31,T-Mobile B.V.";
+ m_mTable[516][367] = "nl,Netherlands,31,T-Mobile B.V.";
+ m_mTable[516][527] = "nl,Netherlands,31,T-mobile/former Orange";
+ m_mTable[516][47] = "nl,Netherlands,31,Tele2";
+ m_mTable[516][127] = "nl,Netherlands,31,Teleena Holding BV";
+ m_mTable[516][1679] = "nl,Netherlands,31,Unify Mobile";
+ m_mTable[516][399] = "nl,Netherlands,31,UPC Nederland BV";
+ m_mTable[516][79] = "nl,Netherlands,31,Vodafone Libertel";
+ m_mTable[516][63] = "nl,Netherlands,31,Voiceworks Mobile BV";
+ m_mTable[516][351] = "nl,Netherlands,31,Ziggo BV";
+ m_mTable[866][1584] = "an,Netherlands Antilles,599,Cingular Wireless";
+ m_mTable[866][1311] = "an,Netherlands Antilles,599,TELCELL GSM";
+ m_mTable[866][2335] = "an,Netherlands Antilles,599,SETEL GSM";
+ m_mTable[866][2385] = "an,Netherlands Antilles,599,UTS Wireless";
+ m_mTable[1350][31] = "nc,New Caledonia,687,OPT Mobilis";
+ m_mTable[1328][655] = "nz,New Zealand,64,2degrees";
+ m_mTable[1328][95] = "nz,New Zealand,64,NZ Telecom CDMA";
+ m_mTable[1328][47] = "nz,New Zealand,64,NZ Telecom CDMA";
+ m_mTable[1328][79] = "nz,New Zealand,64,Telstra";
+ m_mTable[1328][591] = "nz,New Zealand,64,Two Degrees Mobile Ltd";
+ m_mTable[1328][31] = "nz,New Zealand,64,Vodafone";
+ m_mTable[1328][63] = "nz,New Zealand,64,Walker Wireless Ltd.";
+ m_mTable[1808][543] = "ni,Nicaragua,505,Empresa Nicaraguense de Telecomunicaciones SA (ENITEL)";
+ m_mTable[1808][783] = "ni,Nicaragua,505,Movistar";
+ m_mTable[1808][1855] = "ni,Nicaragua,505,Claro";
+ m_mTable[1556][63] = "ne,Niger,227,Etisalat/TeleCel";
+ m_mTable[1556][79] = "ne,Niger,227,Orange/Sahelc.";
+ m_mTable[1556][31] = "ne,Niger,227,Orange/Sahelc.";
+ m_mTable[1556][47] = "ne,Niger,227,Zain/CelTel";
+ m_mTable[1569][527] = "ng,Nigeria,234,Airtel/ZAIN/Econet";
+ m_mTable[1569][1551] = "ng,Nigeria,234,ETISALAT";
+ m_mTable[1569][1295] = "ng,Nigeria,234,Glo Mobile";
+ m_mTable[1569][1039] = "ng,Nigeria,234,M-Tel/Nigeria Telecom. Ltd.";
+ m_mTable[1569][783] = "ng,Nigeria,234,MTN";
+ m_mTable[1569][2463] = "ng,Nigeria,234,Starcomms";
+ m_mTable[1569][31] = "ng,Nigeria,234,Visafone";
+ m_mTable[1569][607] = "ng,Nigeria,234,Visafone";
+ m_mTable[1365][31] = "nu,Niue,683,Niue Telecom";
+ m_mTable[578][159] = "no,Norway,47,Com4 AS";
+ m_mTable[578][543] = "no,Norway,47,Jernbaneverket (GSM-R)";
+ m_mTable[578][527] = "no,Norway,47,Jernbaneverket (GSM-R)";
+ m_mTable[578][575] = "no,Norway,47,Lycamobile Ltd";
+ m_mTable[578][47] = "no,Norway,47,Netcom";
+ m_mTable[578][559] = "no,Norway,47,Network Norway AS";
+ m_mTable[578][95] = "no,Norway,47,Network Norway AS";
+ m_mTable[578][111] = "no,Norway,47,ICE Nordisk Mobiltelefon AS";
+ m_mTable[578][143] = "no,Norway,47,TDC Mobil A/S";
+ m_mTable[578][79] = "no,Norway,47,Tele2";
+ m_mTable[578][31] = "no,Norway,47,Telenor";
+ m_mTable[578][303] = "no,Norway,47,Telenor";
+ m_mTable[578][63] = "no,Norway,47,Teletopia";
+ m_mTable[578][127] = "no,Norway,47,Ventelo AS";
+ m_mTable[1058][63] = "om,Oman,968,Nawras";
+ m_mTable[1058][47] = "om,Oman,968,Oman Mobile/GTO";
+ m_mTable[1040][143] = "pk,Pakistan,92,Instaphone";
+ m_mTable[1040][31] = "pk,Pakistan,92,Mobilink";
+ m_mTable[1040][111] = "pk,Pakistan,92,Telenor";
+ m_mTable[1040][63] = "pk,Pakistan,92,UFONE/PAKTel";
+ m_mTable[1040][127] = "pk,Pakistan,92,Warid Telecom";
+ m_mTable[1040][79] = "pk,Pakistan,92,ZONG/CMPak";
+ m_mTable[1362][2063] = "pw,Palau (Republic of),680,Palau Mobile Corp. (PMC) (Palau";
+ m_mTable[1362][31] = "pw,Palau (Republic of),680,Palau National Communications Corp. (PNCC) (Palau";
+ m_mTable[1061][95] = "ps,Palestinian Territory,970,Jawwal";
+ m_mTable[1061][111] = "ps,Palestinian Territory,970,Wataniya Mobile";
+ m_mTable[1812][31] = "pa,Panama,507,Cable & Wireless S.A.";
+ m_mTable[1812][63] = "pa,Panama,507,Claro";
+ m_mTable[1812][79] = "pa,Panama,507,Digicel";
+ m_mTable[1812][32] = "pa,Panama,507,Movistar";
+ m_mTable[1812][47] = "pa,Panama,507,Movistar";
+ m_mTable[1335][63] = "pg,Papua New Guinea,675,Digicel";
+ m_mTable[1335][47] = "pg,Papua New Guinea,675,GreenCom PNG Ltd";
+ m_mTable[1335][31] = "pg,Papua New Guinea,675,Pacific Mobile";
+ m_mTable[1860][47] = "py,Paraguay,595,Claro/Hutchison";
+ m_mTable[1860][63] = "py,Paraguay,595,Compa";
+ m_mTable[1860][31] = "py,Paraguay,595,Hola/VOX";
+ m_mTable[1860][95] = "py,Paraguay,595,TIM/Nucleo/Personal";
+ m_mTable[1860][79] = "py,Paraguay,595,Tigo/Telecel";
+ m_mTable[1814][271] = "pe,Peru,51,Claro /Amer.Mov./TIM";
+ m_mTable[1814][527] = "pe,Peru,51,Claro /Amer.Mov./TIM";
+ m_mTable[1814][31] = "pe,Peru,51,GlobalStar";
+ m_mTable[1814][47] = "pe,Peru,51,GlobalStar";
+ m_mTable[1814][111] = "pe,Peru,51,Movistar";
+ m_mTable[1814][127] = "pe,Peru,51,Nextel";
+ m_mTable[1301][15] = "ph,Philippines,63,Fix Line";
+ m_mTable[1301][47] = "ph,Philippines,63,Globe Telecom";
+ m_mTable[1301][31] = "ph,Philippines,63,Globe Telecom";
+ m_mTable[1301][2191] = "ph,Philippines,63,Next Mobile";
+ m_mTable[1301][399] = "ph,Philippines,63,RED Mobile/Cure";
+ m_mTable[1301][63] = "ph,Philippines,63,Smart";
+ m_mTable[1301][95] = "ph,Philippines,63,SUN/Digitel";
+ m_mTable[608][383] = "pl,Poland,48,Aero2 SP.";
+ m_mTable[608][399] = "pl,Poland,48,AMD Telecom.";
+ m_mTable[608][911] = "pl,Poland,48,CallFreedom Sp. z o.o.";
+ m_mTable[608][303] = "pl,Poland,48,Cyfrowy POLSAT S.A.";
+ m_mTable[608][143] = "pl,Poland,48,e-Telko";
+ m_mTable[608][159] = "pl,Poland,48,Lycamobile";
+ m_mTable[608][367] = "pl,Poland,48,Mobyland";
+ m_mTable[608][879] = "pl,Poland,48,Mundio Mobile Sp. z o.o.";
+ m_mTable[608][127] = "pl,Poland,48,Play/P4";
+ m_mTable[608][287] = "pl,Poland,48,NORDISK Polska";
+ m_mTable[608][95] = "pl,Poland,48,Orange/IDEA/Centertel";
+ m_mTable[608][63] = "pl,Poland,48,Orange/IDEA/Centertel";
+ m_mTable[608][863] = "pl,Poland,48,PKP Polskie Linie Kolejowe S.A.";
+ m_mTable[608][111] = "pl,Poland,48,Play/P4";
+ m_mTable[608][2447] = "pl,Poland,48,Play/P4";
+ m_mTable[608][31] = "pl,Poland,48,Polkomtel/Plus";
+ m_mTable[608][319] = "pl,Poland,48,Sferia";
+ m_mTable[608][335] = "pl,Poland,48,Sferia";
+ m_mTable[608][271] = "pl,Poland,48,Sferia";
+ m_mTable[608][847] = "pl,Poland,48,T-Mobile/ERA";
+ m_mTable[608][47] = "pl,Poland,48,T-Mobile/ERA";
+ m_mTable[608][351] = "pl,Poland,48,Tele2";
+ m_mTable[608][79] = "pl,Poland,48,Tele2";
+ m_mTable[616][79] = "pt,Portugal,351,CTT - Correios de Portugal SA";
+ m_mTable[616][127] = "pt,Portugal,351,Optimus";
+ m_mTable[616][63] = "pt,Portugal,351,Optimus";
+ m_mTable[616][111] = "pt,Portugal,351,TMN";
+ m_mTable[616][31] = "pt,Portugal,351,Vodafone";
+ m_mTable[816][287] = "pr,Puerto Rico,1787,Puerto Rico Telephone Company Inc. (PRTC)";
+ m_mTable[816][272] = "pr,Puerto Rico,1787,Puerto Rico Telephone Company Inc. (PRTC)";
+ m_mTable[1063][31] = "qa,Qatar,974,Qtel";
+ m_mTable[1063][47] = "qa,Qatar,974,Vodafone";
+ m_mTable[1607][15] = "re,Reunion,262,Orange";
+ m_mTable[1607][47] = "re,Reunion,262,Outremer Telecom";
+ m_mTable[1607][271] = "re,Reunion,262,SFR";
+ m_mTable[550][63] = "ro,Romania,40,Cosmote";
+ m_mTable[550][287] = "ro,Romania,40,Enigma Systems";
+ m_mTable[550][271] = "ro,Romania,40,Orange";
+ m_mTable[550][95] = "ro,Romania,40,RCS&RDS Digi Mobile";
+ m_mTable[550][47] = "ro,Romania,40,Romtelecom SA";
+ m_mTable[550][111] = "ro,Romania,40,Telemobil/Zapp";
+ m_mTable[550][31] = "ro,Romania,40,Vodafone";
+ m_mTable[550][79] = "ro,Romania,40,Telemobil/Zapp";
+ m_mTable[592][303] = "ru,Russian Federation,79,Baykal Westcom";
+ m_mTable[592][655] = "ru,Russian Federation,79,BeeLine/VimpelCom";
+ m_mTable[592][271] = "ru,Russian Federation,79,DTC/Don Telecom";
+ m_mTable[592][319] = "ru,Russian Federation,79,Kuban GSM";
+ m_mTable[592][863] = "ru,Russian Federation,79,LLC Ekaterinburg-2000";
+ m_mTable[592][47] = "ru,Russian Federation,79,Megafon";
+ m_mTable[592][31] = "ru,Russian Federation,79,MTS";
+ m_mTable[592][63] = "ru,Russian Federation,79,NCC";
+ m_mTable[592][367] = "ru,Russian Federation,79,NTC";
+ m_mTable[592][415] = "ru,Russian Federation,79,OJSC Altaysvyaz";
+ m_mTable[592][287] = "ru,Russian Federation,79,Orensot";
+ m_mTable[592][2351] = "ru,Russian Federation,79,Printelefone";
+ m_mTable[592][79] = "ru,Russian Federation,79,Sibchallenge";
+ m_mTable[592][1103] = "ru,Russian Federation,79,StavTelesot";
+ m_mTable[592][527] = "ru,Russian Federation,79,Tele2/ECC/Volgogr.";
+ m_mTable[592][2367] = "ru,Russian Federation,79,Telecom XXL";
+ m_mTable[592][927] = "ru,Russian Federation,79,UralTel";
+ m_mTable[592][383] = "ru,Russian Federation,79,UralTel";
+ m_mTable[592][2463] = "ru,Russian Federation,79,VimpelCom";
+ m_mTable[592][95] = "ru,Russian Federation,79,Yenisey Telecom";
+ m_mTable[592][351] = "ru,Russian Federation,79,ZAO SMARTS";
+ m_mTable[592][127] = "ru,Russian Federation,79,ZAO SMARTS";
+ m_mTable[1589][335] = "rw,Rwanda,250,Airtel Rwanda Ltd";
+ m_mTable[1589][271] = "rw,Rwanda,250,MTN/Rwandacell";
+ m_mTable[1589][319] = "rw,Rwanda,250,TIGO";
+ m_mTable[854][272] = "kn,Saint Kitts and Nevis,1869,Cable & Wireless";
+ m_mTable[854][1295] = "kn,Saint Kitts and Nevis,1869,Digicel";
+ m_mTable[854][1807] = "kn,Saint Kitts and Nevis,1869,UTS Cariglobe";
+ m_mTable[856][272] = "lc,Saint Lucia,1758,Cable & Wireless";
+ m_mTable[856][783] = "lc,Saint Lucia,1758,Cingular Wireless";
+ m_mTable[856][1295] = "lc,Saint Lucia,1758,Digicel (St Lucia) Limited";
+ m_mTable[1353][639] = "ws,Samoa,685,Samoatel Mobile";
+ m_mTable[1353][31] = "ws,Samoa,685,Telecom Samoa Cellular Ltd.";
+ m_mTable[658][31] = "sm,San Marino,378,Prima Telecom";
+ m_mTable[1574][31] = "st,Sao Tome & Principe,239,CSTmovel";
+ m_mTable[2305][335] = "n/a,Satellite Networks,870,AeroMobile";
+ m_mTable[2305][287] = "n/a,Satellite Networks,870,InMarSAT";
+ m_mTable[2305][303] = "n/a,Satellite Networks,870,Maritime Communications Partner AS";
+ m_mTable[2305][95] = "n/a,Satellite Networks,870,Thuraya Satellite";
+ m_mTable[1056][127] = "sa,Saudi Arabia,966,Zain";
+ m_mTable[1056][63] = "sa,Saudi Arabia,966,Etihad/Etisalat/Mobily";
+ m_mTable[1056][31] = "sa,Saudi Arabia,966,STC/Al Jawal";
+ m_mTable[1056][79] = "sa,Saudi Arabia,966,Zain";
+ m_mTable[1544][63] = "sn,Senegal,221,Expresso/Sudatel";
+ m_mTable[1544][31] = "sn,Senegal,221,Orange/Sonatel";
+ m_mTable[1544][47] = "sn,Senegal,221,Sentel GSM";
+ m_mTable[544][63] = "rs,Serbia,381,MTS/Telekom Srbija";
+ m_mTable[544][47] = "rs,Serbia,381,Telenor/Mobtel";
+ m_mTable[544][31] = "rs,Serbia,381,Telenor/Mobtel";
+ m_mTable[544][95] = "rs,Serbia,381,VIP Mobile";
+ m_mTable[1587][271] = "sc,Seychelles,248,Airtel";
+ m_mTable[1587][31] = "sc,Seychelles,248,C&W";
+ m_mTable[1587][47] = "sc,Seychelles,248,Smartcom";
+ m_mTable[1561][63] = "sl,Sierra Leone,232,Africel";
+ m_mTable[1561][31] = "sl,Sierra Leone,232,Zain/Celtel";
+ m_mTable[1561][79] = "sl,Sierra Leone,232,Comium";
+ m_mTable[1561][95] = "sl,Sierra Leone,232,Africel";
+ m_mTable[1561][47] = "sl,Sierra Leone,232,Tigo/Millicom";
+ m_mTable[1561][607] = "sl,Sierra Leone,232,Mobitel";
+ m_mTable[1317][303] = "sg,Singapore,65,GRID Communications Pte Ltd";
+ m_mTable[1317][63] = "sg,Singapore,65,MobileOne Ltd";
+ m_mTable[1317][47] = "sg,Singapore,65,Singtel";
+ m_mTable[1317][31] = "sg,Singapore,65,Singtel";
+ m_mTable[1317][127] = "sg,Singapore,65,Singtel";
+ m_mTable[1317][111] = "sg,Singapore,65,Starhub";
+ m_mTable[1317][95] = "sg,Singapore,65,Starhub";
+ m_mTable[561][111] = "sk,Slovakia,421,O2";
+ m_mTable[561][95] = "sk,Slovakia,421,Orange";
+ m_mTable[561][31] = "sk,Slovakia,421,Orange";
+ m_mTable[561][351] = "sk,Slovakia,421,Orange";
+ m_mTable[561][47] = "sk,Slovakia,421,T-Mobile";
+ m_mTable[561][79] = "sk,Slovakia,421,T-Mobile";
+ m_mTable[561][2463] = "sk,Slovakia,421,Zeleznice Slovenskej republiky (ZSR)";
+ m_mTable[659][1055] = "si,Slovenia,386,Mobitel";
+ m_mTable[659][1039] = "si,Slovenia,386,SI.Mobil";
+ m_mTable[659][271] = "si,Slovenia,386,Slovenske zeleznice d.o.o.";
+ m_mTable[659][1615] = "si,Slovenia,386,T-2 d.o.o.";
+ m_mTable[659][1807] = "si,Slovenia,386,TusMobil/VEGA";
+ m_mTable[1344][47] = "sb,Solomon Islands,677,bemobile";
+ m_mTable[1344][271] = "sb,Solomon Islands,677,BREEZE";
+ m_mTable[1344][31] = "sb,Solomon Islands,677,BREEZE";
+ m_mTable[1591][783] = "so,Somalia,252,Golis";
+ m_mTable[1591][415] = "so,Somalia,252,HorTel";
+ m_mTable[1591][271] = "so,Somalia,252,Nationlink";
+ m_mTable[1591][1551] = "so,Somalia,252,Nationlink";
+ m_mTable[1591][79] = "so,Somalia,252,Somafone";
+ m_mTable[1591][2095] = "so,Somalia,252,Telcom Mobile Somalia";
+ m_mTable[1591][31] = "so,Somalia,252,Telesom";
+ m_mTable[1621][47] = "za,South Africa,27,8.ta";
+ m_mTable[1621][543] = "za,South Africa,27,Cape Town Metropolitan";
+ m_mTable[1621][127] = "za,South Africa,27,Cell C";
+ m_mTable[1621][271] = "za,South Africa,27,MTN";
+ m_mTable[1621][303] = "za,South Africa,27,MTN";
+ m_mTable[1621][111] = "za,South Africa,27,Sentech";
+ m_mTable[1621][31] = "za,South Africa,27,Vodacom";
+ m_mTable[1621][415] = "za,South Africa,27,Wireless Business Solutions (Pty) Ltd";
+ m_mTable[1625][63] = "ss,South Sudan (Republic of),211,Gemtel Ltd (South Sudan";
+ m_mTable[1625][47] = "ss,South Sudan (Republic of),211,MTN South Sudan (South Sudan";
+ m_mTable[1625][79] = "ss,South Sudan (Republic of),211,Network of The World Ltd (NOW) (South Sudan";
+ m_mTable[1625][111] = "ss,South Sudan (Republic of),211,Zain South Sudan (South Sudan";
+ m_mTable[532][575] = "es,Spain,34,Lycamobile SL";
+ m_mTable[532][559] = "es,Spain,34,Movistar";
+ m_mTable[532][351] = "es,Spain,34,BT Espana SAU";
+ m_mTable[532][399] = "es,Spain,34,Cableuropa SAU (ONO)";
+ m_mTable[532][143] = "es,Spain,34,Euskaltel SA";
+ m_mTable[532][527] = "es,Spain,34,fonYou Wireless SL";
+ m_mTable[532][543] = "es,Spain,34,Jazz Telecom SAU";
+ m_mTable[532][623] = "es,Spain,34,Lleida";
+ m_mTable[532][607] = "es,Spain,34,Lycamobile SL";
+ m_mTable[532][127] = "es,Spain,34,Movistar";
+ m_mTable[532][95] = "es,Spain,34,Movistar";
+ m_mTable[532][287] = "es,Spain,34,Orange";
+ m_mTable[532][159] = "es,Spain,34,Orange";
+ m_mTable[532][63] = "es,Spain,34,Orange";
+ m_mTable[532][383] = "es,Spain,34,R Cable y Telec. Galicia SA";
+ m_mTable[532][415] = "es,Spain,34,Simyo/KPN";
+ m_mTable[532][367] = "es,Spain,34,Telecable de Asturias SA";
+ m_mTable[532][639] = "es,Spain,34,Truphone";
+ m_mTable[532][31] = "es,Spain,34,Vodafone";
+ m_mTable[532][111] = "es,Spain,34,Vodafone Enabler Espana SL";
+ m_mTable[532][79] = "es,Spain,34,Yoigo";
+ m_mTable[1043][95] = "lk,Sri Lanka,94,Bharti Airtel";
+ m_mTable[1043][63] = "lk,Sri Lanka,94,Etisalat/Tigo";
+ m_mTable[1043][143] = "lk,Sri Lanka,94,H3G Hutchison";
+ m_mTable[1043][31] = "lk,Sri Lanka,94,Mobitel Ltd.";
+ m_mTable[1043][47] = "lk,Sri Lanka,94,MTN/Dialog";
+ m_mTable[776][31] = "pm,St. Pierre & Miquelon,508,Ameris";
+ m_mTable[864][272] = "vc,St. Vincent & Gren.,1784,C & W";
+ m_mTable[864][271] = "vc,St. Vincent & Gren.,1784,Cingular";
+ m_mTable[864][256] = "vc,St. Vincent & Gren.,1784,Cingular";
+ m_mTable[864][80] = "vc,St. Vincent & Gren.,1784,Digicel";
+ m_mTable[864][1807] = "vc,St. Vincent & Gren.,1784,Digicel";
+ m_mTable[1588][15] = "sd,Sudan,249,Canar Telecom";
+ m_mTable[1588][47] = "sd,Sudan,249,MTN";
+ m_mTable[1588][559] = "sd,Sudan,249,MTN";
+ m_mTable[1588][351] = "sd,Sudan,249,Sudani One";
+ m_mTable[1588][127] = "sd,Sudan,249,Sudani One";
+ m_mTable[1588][95] = "sd,Sudan,249,Vivacell";
+ m_mTable[1588][143] = "sd,Sudan,249,Vivacell";
+ m_mTable[1588][111] = "sd,Sudan,249,ZAIN/Mobitel";
+ m_mTable[1588][31] = "sd,Sudan,249,ZAIN/Mobitel";
+ m_mTable[1862][63] = "sr,Suriname,597,Digicel";
+ m_mTable[1862][31] = "sr,Suriname,597,Telesur";
+ m_mTable[1862][47] = "sr,Suriname,597,Telecommunicatiebedrijf Suriname (TELESUR)";
+ m_mTable[1862][79] = "sr,Suriname,597,UNIQA";
+ m_mTable[1619][271] = "sz,Swaziland,268,Swazi MTN";
+ m_mTable[1619][31] = "sz,Swaziland,268,SwaziTelecom";
+ m_mTable[576][863] = "se,Sweden,46,42 Telecom AB";
+ m_mTable[576][367] = "se,Sweden,46,42 Telecom AB";
+ m_mTable[576][623] = "se,Sweden,46,Beepsend";
+ m_mTable[576][783] = "se,Sweden,46,NextGen Mobile Ltd (CardBoardFish)";
+ m_mTable[576][655] = "se,Sweden,46,CoolTEL Aps";
+ m_mTable[576][607] = "se,Sweden,46,Digitel Mobile Srl";
+ m_mTable[576][559] = "se,Sweden,46,Eu Tel AB";
+ m_mTable[576][639] = "se,Sweden,46,Fogg Mobile AB";
+ m_mTable[576][399] = "se,Sweden,46,Generic Mobile Systems Sweden AB";
+ m_mTable[576][383] = "se,Sweden,46,Gotalandsnatet AB";
+ m_mTable[576][47] = "se,Sweden,46,H3G Access AB";
+ m_mTable[576][79] = "se,Sweden,46,H3G Access AB";
+ m_mTable[576][879] = "se,Sweden,46,ID Mobile";
+ m_mTable[576][575] = "se,Sweden,46,Infobip Ltd.";
+ m_mTable[576][287] = "se,Sweden,46,Lindholmen Science Park AB";
+ m_mTable[576][303] = "se,Sweden,46,Lycamobile Ltd";
+ m_mTable[576][671] = "se,Sweden,46,Mercury International Carrier Services";
+ m_mTable[576][415] = "se,Sweden,46,Mundio Mobile (Sweden) Ltd";
+ m_mTable[576][271] = "se,Sweden,46,Spring Mobil AB";
+ m_mTable[576][95] = "se,Sweden,46,Svenska UMTS-N";
+ m_mTable[576][335] = "se,Sweden,46,TDC Sverige AB";
+ m_mTable[576][127] = "se,Sweden,46,Tele2 Sverige AB";
+ m_mTable[576][111] = "se,Sweden,46,Telenor (Vodafone)";
+ m_mTable[576][591] = "se,Sweden,46,Telenor (Vodafone)";
+ m_mTable[576][143] = "se,Sweden,46,Telenor (Vodafone)";
+ m_mTable[576][31] = "se,Sweden,46,Telia Mobile";
+ m_mTable[576][319] = "se,Sweden,46,Ventelo Sverige AB";
+ m_mTable[576][527] = "se,Sweden,46,Wireless Maingate AB";
+ m_mTable[576][351] = "se,Sweden,46,Wireless Maingate Nordic AB";
+ m_mTable[552][1311] = "ch,Switzerland,41,BebbiCell AG";
+ m_mTable[552][159] = "ch,Switzerland,41,Comfone AG";
+ m_mTable[552][95] = "ch,Switzerland,41,Comfone AG";
+ m_mTable[552][127] = "ch,Switzerland,41,TDC Sunrise";
+ m_mTable[552][1359] = "ch,Switzerland,41,Lycamobile AG";
+ m_mTable[552][1327] = "ch,Switzerland,41,Mundio Mobile AG";
+ m_mTable[552][63] = "ch,Switzerland,41,Orange";
+ m_mTable[552][31] = "ch,Switzerland,41,Swisscom";
+ m_mTable[552][303] = "ch,Switzerland,41,TDC Sunrise";
+ m_mTable[552][47] = "ch,Switzerland,41,TDC Sunrise";
+ m_mTable[552][143] = "ch,Switzerland,41,TDC Sunrise";
+ m_mTable[552][1343] = "ch,Switzerland,41,upc cablecom GmbH";
+ m_mTable[1047][47] = "sy,Syrian Arab Republic,963,MTN/Spacetel";
+ m_mTable[1047][159] = "sy,Syrian Arab Republic,963,Syriatel Holdings";
+ m_mTable[1047][31] = "sy,Syrian Arab Republic,963,Syriatel Holdings";
+ m_mTable[1126][1679] = "tw,Taiwan,886,ACeS Taiwan - ACeS Taiwan Telecommunications Co Ltd";
+ m_mTable[1126][95] = "tw,Taiwan,886,Asia Pacific Telecom Co. Ltd (APT)";
+ m_mTable[1126][287] = "tw,Taiwan,886,Chunghwa Telecom LDM";
+ m_mTable[1126][2351] = "tw,Taiwan,886,Chunghwa Telecom LDM";
+ m_mTable[1126][127] = "tw,Taiwan,886,Far EasTone";
+ m_mTable[1126][47] = "tw,Taiwan,886,Far EasTone";
+ m_mTable[1126][111] = "tw,Taiwan,886,Far EasTone";
+ m_mTable[1126][63] = "tw,Taiwan,886,Far EasTone";
+ m_mTable[1126][31] = "tw,Taiwan,886,Far EasTone";
+ m_mTable[1126][271] = "tw,Taiwan,886,Global Mobile Corp.";
+ m_mTable[1126][1391] = "tw,Taiwan,886,International Telecom Co. Ltd (FITEL)";
+ m_mTable[1126][2191] = "tw,Taiwan,886,KG Telecom";
+ m_mTable[1126][2431] = "tw,Taiwan,886,Taiwan Cellular";
+ m_mTable[1126][2367] = "tw,Taiwan,886,Mobitai";
+ m_mTable[1126][2463] = "tw,Taiwan,886,TransAsia";
+ m_mTable[1126][2207] = "tw,Taiwan,886,VIBO";
+ m_mTable[1126][159] = "tw,Taiwan,886,VMAX Telecom Co. Ltd";
+ m_mTable[1078][79] = "tk,Tajikistan,992,Babilon-M";
+ m_mTable[1078][95] = "tk,Tajikistan,992,Bee Line";
+ m_mTable[1078][47] = "tk,Tajikistan,992,CJSC Indigo Tajikistan";
+ m_mTable[1078][303] = "tk,Tajikistan,992,Tcell/JC Somoncom";
+ m_mTable[1078][63] = "tk,Tajikistan,992,MLT/TT mobile";
+ m_mTable[1078][31] = "tk,Tajikistan,992,Tcell/JC Somoncom";
+ m_mTable[1600][143] = "tz,Tanzania,255,Benson Informatics Ltd";
+ m_mTable[1600][111] = "tz,Tanzania,255,Dovetel (T) Ltd";
+ m_mTable[1600][159] = "tz,Tanzania,255,ExcellentCom (T) Ltd";
+ m_mTable[1600][287] = "tz,Tanzania,255,Smile Communications Tanzania Ltd";
+ m_mTable[1600][127] = "tz,Tanzania,255,Tanzania Telecommunications Company Ltd (TTCL)";
+ m_mTable[1600][47] = "tz,Tanzania,255,TIGO/MIC";
+ m_mTable[1600][31] = "tz,Tanzania,255,Tri Telecomm. Ltd.";
+ m_mTable[1600][79] = "tz,Tanzania,255,Vodacom Ltd";
+ m_mTable[1600][95] = "tz,Tanzania,255,ZAIN/Celtel";
+ m_mTable[1600][63] = "tz,Tanzania,255,Zantel/Zanzibar Telecom";
+ m_mTable[1312][527] = "th,Thailand,66,ACeS Thailand - ACeS Regional Services Co Ltd";
+ m_mTable[1312][351] = "th,Thailand,66,ACT Mobile";
+ m_mTable[1312][63] = "th,Thailand,66,Advanced Wireless Networks/AWN";
+ m_mTable[1312][31] = "th,Thailand,66,AIS/Advanced Info Service";
+ m_mTable[1312][575] = "th,Thailand,66,Digital Phone Co.";
+ m_mTable[1312][15] = "th,Thailand,66,Hutch/CAT CDMA";
+ m_mTable[1312][399] = "th,Thailand,66,Total Access (DTAC)";
+ m_mTable[1312][95] = "th,Thailand,66,Total Access (DTAC)";
+ m_mTable[1312][79] = "th,Thailand,66,True Move/Orange";
+ m_mTable[1312][2463] = "th,Thailand,66,True Move/Orange";
+ m_mTable[1300][31] = "tp,Timor-Leste,670,Telin/ Telkomcel";
+ m_mTable[1300][47] = "tp,Timor-Leste,670,Timor Telecom";
+ m_mTable[1557][47] = "tg,Togo,228,Telecel/MOOV";
+ m_mTable[1557][63] = "tg,Togo,228,Telecel/MOOV";
+ m_mTable[1557][31] = "tg,Togo,228,Togo Telecom/TogoCELL";
+ m_mTable[1337][1087] = "to,Tonga,676,Shoreline Communication";
+ m_mTable[1337][31] = "to,Tonga,676,Tonga Communications";
+ m_mTable[884][297] = "tt,Trinidad and Tobago,1868,Bmobile/TSTT";
+ m_mTable[884][304] = "tt,Trinidad and Tobago,1868,Digicel";
+ m_mTable[884][320] = "tt,Trinidad and Tobago,1868,LaqTel Ltd.";
+ m_mTable[1541][31] = "tn,Tunisia,216,Orange";
+ m_mTable[1541][63] = "tn,Tunisia,216,Oreedo/Orascom";
+ m_mTable[1541][47] = "tn,Tunisia,216,TuniCell/Tunisia Telecom";
+ m_mTable[646][79] = "tr,Turkey,90,AVEA/Aria";
+ m_mTable[646][63] = "tr,Turkey,90,AVEA/Aria";
+ m_mTable[646][31] = "tr,Turkey,90,Turkcell";
+ m_mTable[646][47] = "tr,Turkey,90,Vodafone-Telsim";
+ m_mTable[1080][31] = "tm,Turkmenistan,993,Barash Communication";
+ m_mTable[1080][47] = "tm,Turkmenistan,993,TM-Cell";
+ m_mTable[886][848] = "tc,Turks and Caicos Islands,1649,Cable & Wireless (TCI) Ltd";
+ m_mTable[886][80] = "tc,Turks and Caicos Islands,1649,Digicel TCI Ltd";
+ m_mTable[886][850] = "tc,Turks and Caicos Islands,1649,IslandCom Communications Ltd.";
+ m_mTable[1363][31] = "tv,Tuvalu,688,Tuvalu Telecommunication Corporation (TTC)";
+ m_mTable[1601][31] = "ug,Uganda,256,Celtel";
+ m_mTable[1601][1647] = "ug,Uganda,256,i-Tel Ltd";
+ m_mTable[1601][783] = "ug,Uganda,256,K2 Telecom Ltd";
+ m_mTable[1601][271] = "ug,Uganda,256,MTN Ltd.";
+ m_mTable[1601][335] = "ug,Uganda,256,Orange";
+ m_mTable[1601][831] = "ug,Uganda,256,Smile Communications Uganda Ltd";
+ m_mTable[1601][399] = "ug,Uganda,256,Suretelecom Uganda Ltd";
+ m_mTable[1601][287] = "ug,Uganda,256,Uganda Telecom Ltd.";
+ m_mTable[1601][559] = "ug,Uganda,256,Airtel/Warid";
+ m_mTable[597][111] = "ua,Ukraine,380,Astelit/LIFE";
+ m_mTable[597][95] = "ua,Ukraine,380,Golden Telecom";
+ m_mTable[597][927] = "ua,Ukraine,380,Golden Telecom";
+ m_mTable[597][79] = "ua,Ukraine,380,Intertelecom Ltd (IT)";
+ m_mTable[597][1663] = "ua,Ukraine,380,KyivStar";
+ m_mTable[597][63] = "ua,Ukraine,380,KyivStar";
+ m_mTable[597][543] = "ua,Ukraine,380,Telesystems Of Ukraine CJSC (TSU)";
+ m_mTable[597][127] = "ua,Ukraine,380,TriMob LLC";
+ m_mTable[597][1295] = "ua,Ukraine,380,UMC/MTS";
+ m_mTable[597][47] = "ua,Ukraine,380,Beeline";
+ m_mTable[597][31] = "ua,Ukraine,380,UMC/MTS";
+ m_mTable[597][1679] = "ua,Ukraine,380,Beeline";
+ m_mTable[1060][63] = "ae,United Arab Emirates,971,DU";
+ m_mTable[1073][47] = "ae,United Arab Emirates,971,Etisalat";
+ m_mTable[1060][47] = "ae,United Arab Emirates,971,Etisalat";
+ m_mTable[1072][47] = "ae,United Arab Emirates,971,Etisalat";
+ m_mTable[564][63] = "gb,United Kingdom,44,Airtel/Vodafone";
+ m_mTable[564][1903] = "gb,United Kingdom,44,BT Group";
+ m_mTable[564][1919] = "gb,United Kingdom,44,BT Group";
+ m_mTable[564][127] = "gb,United Kingdom,44,Cable and Wireless";
+ m_mTable[564][2351] = "gb,United Kingdom,44,Cable and Wireless";
+ m_mTable[564][879] = "gb,United Kingdom,44,Cable and Wireless Isle of Man";
+ m_mTable[564][399] = "gb,United Kingdom,44,Cloud9/wire9 Tel.";
+ m_mTable[565][47] = "gb,United Kingdom,44,Everyth. Ev.wh.";
+ m_mTable[564][383] = "gb,United Kingdom,44,FlexTel";
+ m_mTable[564][1375] = "gb,United Kingdom,44,Guernsey Telecoms";
+ m_mTable[564][335] = "gb,United Kingdom,44,HaySystems";
+ m_mTable[564][527] = "gb,United Kingdom,44,Hutchinson 3G";
+ m_mTable[564][2383] = "gb,United Kingdom,44,Hutchinson 3G";
+ m_mTable[564][1887] = "gb,United Kingdom,44,Inquam Telecom Ltd";
+ m_mTable[564][1295] = "gb,United Kingdom,44,Jersey Telecom";
+ m_mTable[564][863] = "gb,United Kingdom,44,JSC Ingenicum";
+ m_mTable[564][623] = "gb,United Kingdom,44,Lycamobile";
+ m_mTable[564][1423] = "gb,United Kingdom,44,Manx Telecom";
+ m_mTable[564][31] = "gb,United Kingdom,44,Mapesbury C. Ltd";
+ m_mTable[564][655] = "gb,United Kingdom,44,Marthon Telecom";
+ m_mTable[564][271] = "gb,United Kingdom,44,O2 Ltd.";
+ m_mTable[564][47] = "gb,United Kingdom,44,O2 Ltd.";
+ m_mTable[564][287] = "gb,United Kingdom,44,O2 Ltd.";
+ m_mTable[564][143] = "gb,United Kingdom,44,OnePhone";
+ m_mTable[564][367] = "gb,United Kingdom,44,Opal Telecom";
+ m_mTable[564][847] = "gb,United Kingdom,44,Everyth. Ev.wh./Orange";
+ m_mTable[564][831] = "gb,United Kingdom,44,Everyth. Ev.wh./Orange";
+ m_mTable[564][415] = "gb,United Kingdom,44,PMN/Teleware";
+ m_mTable[564][303] = "gb,United Kingdom,44,Railtrack Plc";
+ m_mTable[564][559] = "gb,United Kingdom,44,Routotelecom";
+ m_mTable[564][591] = "gb,United Kingdom,44,Stour Marine";
+ m_mTable[564][895] = "gb,United Kingdom,44,Synectiv Ltd.";
+ m_mTable[564][799] = "gb,United Kingdom,44,Everyth. Ev.wh./T-Mobile";
+ m_mTable[564][783] = "gb,United Kingdom,44,Everyth. Ev.wh./T-Mobile";
+ m_mTable[564][815] = "gb,United Kingdom,44,Everyth. Ev.wh./T-Mobile";
+ m_mTable[564][639] = "gb,United Kingdom,44,Vodafone";
+ m_mTable[564][159] = "gb,United Kingdom,44,Tismi";
+ m_mTable[564][607] = "gb,United Kingdom,44,Truphone";
+ m_mTable[564][1311] = "gb,United Kingdom,44,Jersey Telecom";
+ m_mTable[564][575] = "gb,United Kingdom,44,Vectofone Mobile Wifi";
+ m_mTable[564][351] = "gb,United Kingdom,44,Vodafone";
+ m_mTable[564][2335] = "gb,United Kingdom,44,Vodafone";
+ m_mTable[564][1935] = "gb,United Kingdom,44,Wave Telecom Ltd";
+ m_mTable[784][80] = "us,United States,1,";
+ m_mTable[784][2176] = "us,United States,1,";
+ m_mTable[784][2128] = "us,United States,1,Aeris Comm. Inc.";
+ m_mTable[784][1600] = "us,United States,1,";
+ m_mTable[784][1296] = "us,United States,1,Airtel Wireless LLC";
+ m_mTable[784][400] = "us,United States,1,Unknown";
+ m_mTable[786][144] = "us,United States,1,Allied Wireless Communications Corporation";
+ m_mTable[785][304] = "us,United States,1,";
+ m_mTable[784][1808] = "us,United States,1,Arctic Slope Telephone Association Cooperative Inc.";
+ m_mTable[784][336] = "us,United States,1,AT&T Wireless Inc.";
+ m_mTable[784][1664] = "us,United States,1,AT&T Wireless Inc.";
+ m_mTable[784][112] = "us,United States,1,AT&T Wireless Inc.";
+ m_mTable[784][1376] = "us,United States,1,AT&T Wireless Inc.";
+ m_mTable[784][1040] = "us,United States,1,AT&T Wireless Inc.";
+ m_mTable[784][896] = "us,United States,1,AT&T Wireless Inc.";
+ m_mTable[784][368] = "us,United States,1,AT&T Wireless Inc.";
+ m_mTable[784][2432] = "us,United States,1,AT&T Wireless Inc.";
+ m_mTable[785][2064] = "us,United States,1,Bluegrass Wireless LLC";
+ m_mTable[785][2048] = "us,United States,1,Bluegrass Wireless LLC";
+ m_mTable[785][1088] = "us,United States,1,Bluegrass Wireless LLC";
+ m_mTable[784][2304] = "us,United States,1,Cable & Communications Corp.";
+ m_mTable[785][1424] = "us,United States,1,California RSA No. 3 Limited Partnership";
+ m_mTable[785][1280] = "us,United States,1,Cambridge Telephone Company Inc.";
+ m_mTable[784][2096] = "us,United States,1,Caprock Cellular Ltd.";
+ m_mTable[785][630] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1153] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1158] = "us,United States,1,Verizon Wireless";
+ m_mTable[784][19] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][641] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][624] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][646] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][629] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1152] = "us,United States,1,Verizon Wireless";
+ m_mTable[784][18] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][640] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1157] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][272] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][645] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][628] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][912] = "us,United States,1,Verizon Wireless";
+ m_mTable[784][16] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][633] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1156] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1161] = "us,United States,1,Verizon Wireless";
+ m_mTable[784][2320] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][644] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][627] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][649] = "us,United States,1,Verizon Wireless";
+ m_mTable[784][4] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][632] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1155] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1160] = "us,United States,1,Verizon Wireless";
+ m_mTable[784][2192] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][643] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][626] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][648] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][631] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1154] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][1159] = "us,United States,1,Verizon Wireless";
+ m_mTable[784][1424] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][642] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][625] = "us,United States,1,Verizon Wireless";
+ m_mTable[785][647] = "us,United States,1,Verizon Wireless";
+ m_mTable[786][624] = "us,United States,1,Cellular Network Partnership LLC";
+ m_mTable[784][864] = "us,United States,1,Cellular Network Partnership LLC";
+ m_mTable[786][640] = "us,United States,1,Cellular Network Partnership LLC";
+ m_mTable[785][400] = "us,United States,1,";
+ m_mTable[784][48] = "us,United States,1,";
+ m_mTable[785][288] = "us,United States,1,Choice Phone LLC";
+ m_mTable[784][1152] = "us,United States,1,Choice Phone LLC";
+ m_mTable[784][1584] = "us,United States,1,";
+ m_mTable[784][1056] = "us,United States,1,Cincinnati Bell Wireless LLC";
+ m_mTable[784][384] = "us,United States,1,Cingular Wireless";
+ m_mTable[784][1568] = "us,United States,1,Coleman County Telco /Trans TX";
+ m_mTable[785][64] = "us,United States,1,";
+ m_mTable[784][1551] = "us,United States,1,Consolidated Telcom";
+ m_mTable[784][111] = "us,United States,1,Consolidated Telcom";
+ m_mTable[786][896] = "us,United States,1,";
+ m_mTable[784][2352] = "us,United States,1,";
+ m_mTable[785][576] = "us,United States,1,";
+ m_mTable[784][128] = "us,United States,1,";
+ m_mTable[784][1792] = "us,United States,1,Cross Valliant Cellular Partnership";
+ m_mTable[786][48] = "us,United States,1,Cross Wireless Telephone Co.";
+ m_mTable[785][320] = "us,United States,1,Cross Wireless Telephone Co.";
+ m_mTable[785][1312] = "us,United States,1,";
+ m_mTable[786][64] = "us,United States,1,Custer Telephone Cooperative Inc.";
+ m_mTable[784][1088] = "us,United States,1,Dobson Cellular Systems";
+ m_mTable[784][2448] = "us,United States,1,E.N.M.R. Telephone Coop.";
+ m_mTable[784][1872] = "us,United States,1,East Kentucky Network LLC";
+ m_mTable[786][304] = "us,United States,1,East Kentucky Network LLC";
+ m_mTable[786][288] = "us,United States,1,East Kentucky Network LLC";
+ m_mTable[784][144] = "us,United States,1,Edge Wireless LLC";
+ m_mTable[784][1552] = "us,United States,1,Elkhart TelCo. / Epic Touch Co.";
+ m_mTable[785][528] = "us,United States,1,";
+ m_mTable[785][785] = "us,United States,1,Farmers";
+ m_mTable[785][1120] = "us,United States,1,Fisher Wireless Services Inc.";
+ m_mTable[785][880] = "us,United States,1,GCI Communication Corp.";
+ m_mTable[784][1072] = "us,United States,1,GCI Communication Corp.";
+ m_mTable[784][2336] = "us,United States,1,Get Mobile Inc.";
+ m_mTable[784][2416] = "us,United States,1,";
+ m_mTable[785][832] = "us,United States,1,Illinois Valley Cellular RSA 2 Partnership";
+ m_mTable[785][48] = "us,United States,1,";
+ m_mTable[785][1040] = "us,United States,1,Iowa RSA No. 2 Limited Partnership";
+ m_mTable[786][368] = "us,United States,1,Iowa RSA No. 2 Limited Partnership";
+ m_mTable[784][1904] = "us,United States,1,Iowa Wireless Services LLC";
+ m_mTable[784][1616] = "us,United States,1,Jasper";
+ m_mTable[784][2160] = "us,United States,1,Kaplan Telephone Company Inc.";
+ m_mTable[786][384] = "us,United States,1,Keystone Wireless LLC";
+ m_mTable[784][1680] = "us,United States,1,Keystone Wireless LLC";
+ m_mTable[785][784] = "us,United States,1,Lamar County Cellular";
+ m_mTable[784][22] = "us,United States,1,Leap Wireless International Inc.";
+ m_mTable[785][144] = "us,United States,1,";
+ m_mTable[784][64] = "us,United States,1,Matanuska Tel. Assn. Inc.";
+ m_mTable[784][1920] = "us,United States,1,Message Express Co. / Airlink PCS";
+ m_mTable[785][1632] = "us,United States,1,";
+ m_mTable[785][816] = "us,United States,1,Michigan Wireless LLC";
+ m_mTable[785][0] = "us,United States,1,";
+ m_mTable[784][1024] = "us,United States,1,Minnesota South. Wirel. Co. / Hickory";
+ m_mTable[786][544] = "us,United States,1,Missouri RSA No 5 Partnership";
+ m_mTable[786][16] = "us,United States,1,Missouri RSA No 5 Partnership";
+ m_mTable[785][2336] = "us,United States,1,Missouri RSA No 5 Partnership";
+ m_mTable[785][32] = "us,United States,1,Missouri RSA No 5 Partnership";
+ m_mTable[785][16] = "us,United States,1,Missouri RSA No 5 Partnership";
+ m_mTable[784][848] = "us,United States,1,Mohave Cellular LP";
+ m_mTable[784][1392] = "us,United States,1,MTPCS LLC";
+ m_mTable[784][656] = "us,United States,1,NEP Cellcorp Inc.";
+ m_mTable[784][847] = "us,United States,1,Nevada Wireless LLC";
+ m_mTable[785][896] = "us,United States,1,";
+ m_mTable[784][1536] = "us,United States,1,New-Cell Inc.";
+ m_mTable[785][256] = "us,United States,1,";
+ m_mTable[785][768] = "us,United States,1,Nexus Communications Inc.";
+ m_mTable[784][304] = "us,United States,1,North Carolina RSA 3 Cellular Tel. Co.";
+ m_mTable[786][560] = "us,United States,1,North Dakota Network Company";
+ m_mTable[785][1552] = "us,United States,1,North Dakota Network Company";
+ m_mTable[784][1104] = "us,United States,1,Northeast Colorado Cellular Inc.";
+ m_mTable[785][1808] = "us,United States,1,Northeast Wireless Networks LLC";
+ m_mTable[784][1648] = "us,United States,1,Northstar";
+ m_mTable[784][17] = "us,United States,1,Northstar";
+ m_mTable[785][1056] = "us,United States,1,Northwest Missouri Cellular Limited Partnership";
+ m_mTable[784][1344] = "us,United States,1,";
+ m_mTable[784][1888] = "us,United States,1,Panhandle Telephone Cooperative Inc.";
+ m_mTable[784][1408] = "us,United States,1,PCS ONE";
+ m_mTable[785][368] = "us,United States,1,PetroCom";
+ m_mTable[785][1648] = "us,United States,1,Pine Belt Cellular Inc.";
+ m_mTable[785][128] = "us,United States,1,";
+ m_mTable[784][1936] = "us,United States,1,";
+ m_mTable[784][256] = "us,United States,1,Plateau Telecommunications Inc.";
+ m_mTable[784][2368] = "us,United States,1,Poka Lambro Telco Ltd.";
+ m_mTable[785][1840] = "us,United States,1,";
+ m_mTable[785][1344] = "us,United States,1,";
+ m_mTable[784][1280] = "us,United States,1,Public Service Cellular Inc.";
+ m_mTable[785][1072] = "us,United States,1,RSA 1 Limited Partnership";
+ m_mTable[786][352] = "us,United States,1,RSA 1 Limited Partnership";
+ m_mTable[785][848] = "us,United States,1,Sagebrush Cellular Inc.";
+ m_mTable[785][2320] = "us,United States,1,";
+ m_mTable[784][1135] = "us,United States,1,SIMMETRY";
+ m_mTable[785][608] = "us,United States,1,SLO Cellular Inc / Cellular One of San Luis";
+ m_mTable[784][800] = "us,United States,1,Smith Bagley Inc.";
+ m_mTable[784][351] = "us,United States,1,Unknown";
+ m_mTable[790][17] = "us,United States,1,Southern Communications Services Inc.";
+ m_mTable[786][1328] = "us,United States,1,Sprint Spectrum";
+ m_mTable[785][2160] = "us,United States,1,Sprint Spectrum";
+ m_mTable[785][1168] = "us,United States,1,Sprint Spectrum";
+ m_mTable[784][288] = "us,United States,1,Sprint Spectrum";
+ m_mTable[790][16] = "us,United States,1,Sprint Spectrum";
+ m_mTable[786][400] = "us,United States,1,Sprint Spectrum";
+ m_mTable[785][2176] = "us,United States,1,Sprint Spectrum";
+ m_mTable[784][512] = "us,United States,1,T-Mobile";
+ m_mTable[784][592] = "us,United States,1,T-Mobile";
+ m_mTable[784][352] = "us,United States,1,T-Mobile";
+ m_mTable[784][576] = "us,United States,1,T-Mobile";
+ m_mTable[784][1632] = "us,United States,1,T-Mobile";
+ m_mTable[784][560] = "us,United States,1,T-Mobile";
+ m_mTable[784][799] = "us,United States,1,T-Mobile";
+ m_mTable[784][544] = "us,United States,1,T-Mobile";
+ m_mTable[784][624] = "us,United States,1,T-Mobile";
+ m_mTable[784][528] = "us,United States,1,T-Mobile";
+ m_mTable[784][608] = "us,United States,1,T-Mobile";
+ m_mTable[784][2048] = "us,United States,1,T-Mobile";
+ m_mTable[784][768] = "us,United States,1,T-Mobile";
+ m_mTable[784][640] = "us,United States,1,T-Mobile";
+ m_mTable[784][816] = "us,United States,1,T-Mobile";
+ m_mTable[784][784] = "us,United States,1,T-Mobile";
+ m_mTable[785][1856] = "us,United States,1,";
+ m_mTable[784][1856] = "us,United States,1,Telemetrix Inc.";
+ m_mTable[784][335] = "us,United States,1,Testing";
+ m_mTable[784][2384] = "us,United States,1,Unknown";
+ m_mTable[784][2144] = "us,United States,1,Texas RSA 15B2 Limited Partnership";
+ m_mTable[785][2096] = "us,United States,1,Thumb Cellular Limited Partnership";
+ m_mTable[785][80] = "us,United States,1,Thumb Cellular Limited Partnership";
+ m_mTable[784][1120] = "us,United States,1,TMP Corporation";
+ m_mTable[784][1168] = "us,United States,1,Triton PCS";
+ m_mTable[786][656] = "us,United States,1,Uintah Basin Electronics Telecommunications Inc.";
+ m_mTable[785][2144] = "us,United States,1,Uintah Basin Electronics Telecommunications Inc.";
+ m_mTable[784][2400] = "us,United States,1,Uintah Basin Electronics Telecommunications Inc.";
+ m_mTable[784][32] = "us,United States,1,Union Telephone Co.";
+ m_mTable[785][544] = "us,United States,1,United States Cellular Corp.";
+ m_mTable[784][1840] = "us,United States,1,United States Cellular Corp.";
+ m_mTable[785][1616] = "us,United States,1,United Wireless Communications Inc.";
+ m_mTable[784][911] = "us,United States,1,USA 3650 AT&T";
+ m_mTable[784][1312] = "us,United States,1,VeriSign";
+ m_mTable[784][3] = "us,United States,1,Unknown";
+ m_mTable[784][575] = "us,United States,1,Unknown";
+ m_mTable[784][591] = "us,United States,1,Unknown";
+ m_mTable[784][607] = "us,United States,1,Unknown";
+ m_mTable[784][1328] = "us,United States,1,West Virginia Wireless";
+ m_mTable[784][623] = "us,United States,1,Unknown";
+ m_mTable[784][832] = "us,United States,1,Westlink Communications LLC";
+ m_mTable[785][336] = "us,United States,1,";
+ m_mTable[785][112] = "us,United States,1,Wisconsin RSA #7 Limited Partnership";
+ m_mTable[784][912] = "us,United States,1,Yorkville Telephone Cooperative";
+ m_mTable[1864][63] = "uy,Uruguay,598,Ancel/Antel";
+ m_mTable[1864][31] = "uy,Uruguay,598,Ancel/Antel";
+ m_mTable[1864][271] = "uy,Uruguay,598,Claro/AM Wireless";
+ m_mTable[1864][127] = "uy,Uruguay,598,MOVISTAR";
+ m_mTable[1076][79] = "uz,Uzbekistan,998,Bee Line/Unitel";
+ m_mTable[1076][31] = "uz,Uzbekistan,998,Buztel";
+ m_mTable[1076][127] = "uz,Uzbekistan,998,MTS/Uzdunrobita";
+ m_mTable[1076][95] = "uz,Uzbekistan,998,Ucell/Coscom";
+ m_mTable[1076][47] = "uz,Uzbekistan,998,Uzmacom";
+ m_mTable[1345][95] = "vu,Vanuatu,678,DigiCel";
+ m_mTable[1345][31] = "vu,Vanuatu,678,SMILE";
+ m_mTable[1844][63] = "ve,Venezuela,58,DigiTel C.A.";
+ m_mTable[1844][47] = "ve,Venezuela,58,DigiTel C.A.";
+ m_mTable[1844][31] = "ve,Venezuela,58,DigiTel C.A.";
+ m_mTable[1844][111] = "ve,Venezuela,58,Movilnet C.A.";
+ m_mTable[1844][79] = "ve,Venezuela,58,Movistar/TelCel";
+ m_mTable[1106][127] = "vn,Viet Nam,84,Beeline";
+ m_mTable[1106][31] = "vn,Viet Nam,84,Mobifone";
+ m_mTable[1106][63] = "vn,Viet Nam,84,S-Fone/Telecom";
+ m_mTable[1106][95] = "vn,Viet Nam,84,VietnaMobile";
+ m_mTable[1106][111] = "vn,Viet Nam,84,Viettel Mobile";
+ m_mTable[1106][79] = "vn,Viet Nam,84,Viettel Mobile";
+ m_mTable[1106][143] = "vn,Viet Nam,84,Viettel Mobile";
+ m_mTable[1106][47] = "vn,Viet Nam,84,Vinaphone";
+ m_mTable[886][1295] = "vi,Virgin Islands U.S.,1340,Digicel";
+ m_mTable[1057][79] = "ye,Yemen,967,HITS/Y Unitel";
+ m_mTable[1057][47] = "ye,Yemen,967,MTN/Spacetel";
+ m_mTable[1057][31] = "ye,Yemen,967,Sabaphone";
+ m_mTable[1057][63] = "ye,Yemen,967,Yemen Mob. CDMA";
+ m_mTable[1605][63] = "zm,Zambia,260,Cell Z/MTS";
+ m_mTable[1605][47] = "zm,Zambia,260,MTN/Telecel";
+ m_mTable[1605][31] = "zm,Zambia,260,Airtel/Zain/Celtel";
+ m_mTable[1608][79] = "zw,Zimbabwe,263,Econet";
+ m_mTable[1608][31] = "zw,Zimbabwe,263,Net One";
+ m_mTable[1608][63] = "zw,Zimbabwe,263,Telecel";
+}
+
diff --git a/src/MTS_IO_SerialConnection.cpp b/src/MTS_IO_SerialConnection.cpp
new file mode 100644
index 0000000..8f0b8e3
--- /dev/null
+++ b/src/MTS_IO_SerialConnection.cpp
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts_io.
+ *
+ * libmts_io 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 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts_io 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 libmts_io. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*!
+ \file MTS_IO_SerialConnection.cpp
+ \brief A brief description
+ \date Jan 15, 2013
+ \author sgodinez
+
+ A more elaborate description
+*/
+
+#include <mts/MTS_IO_SerialConnection.h>
+#include <mts/MTS_Text.h>
+#include <mts/MTS_Logger.h>
+#include <unistd.h>
+
+#ifdef WIN32
+
+#else
+#include <fcntl.h> /* File control definitions */
+#include <errno.h> /* Error number definitions */
+#include <termios.h> /* POSIX terminal control definitions */
+#include <string.h> /* String function definitions */
+#endif
+
+using namespace MTS::IO;
+
+SerialConnection::Builder::Builder(const std::string& sPortName)
+: m_sPortName(sPortName)
+, m_iBaudRate(9600)
+, m_eType(RS232)
+, m_eParity(OFF)
+, m_eDataBits(B8)
+, m_eStopBits(B1)
+, m_bBuilt(false)
+{
+
+}
+
+SerialConnection::Builder& SerialConnection::Builder::type(const ETYPE& eType) {
+ m_eType = eType;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::rs232() {
+ m_eType = RS232;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::rs422() {
+ m_eType = RS422;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::rs485() {
+ m_eType = RS485;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::parity(const EPARITY& eParity) {
+ m_eParity = eParity;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::parityOff() {
+ m_eParity = OFF;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::parityOdd() {
+ m_eParity = ODD;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::parityEven() {
+ m_eParity = EVEN;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::dataBits(const EDATABITS& eDataBits) {
+ m_eDataBits = eDataBits;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::fiveDataBits() {
+ m_eDataBits = B5;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::sixDataBits() {
+ m_eDataBits = B6;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::sevenDataBits() {
+ m_eDataBits = B7;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::eightDataBits() {
+ m_eDataBits = B8;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::stopBits(const ESTOPBITS& eStopBits) {
+ m_eStopBits = eStopBits;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::oneStopBit() {
+ m_eStopBits = B1;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::twoStopBits() {
+ m_eStopBits = B2;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::baudRate(uint32_t iBaud) {
+ m_iBaudRate = iBaud;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::useLockFile(bool bEnabled) {
+ m_bLockFile = bEnabled;
+ return *this;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::build() {
+ m_bBuilt = true;
+ return *this;
+}
+
+const std::string& SerialConnection::Builder::getPortName() const {
+ return m_sPortName;
+}
+
+const uint32_t& SerialConnection::Builder::getBaudRate() const {
+ return m_iBaudRate;
+}
+
+SerialConnection::ETYPE SerialConnection::Builder::getType() const {
+ return m_eType;
+}
+
+SerialConnection::EPARITY SerialConnection::Builder::getParity() const {
+ return m_eParity;
+}
+
+SerialConnection::EDATABITS SerialConnection::Builder::getDataBits() const {
+ return m_eDataBits;
+}
+
+SerialConnection::ESTOPBITS SerialConnection::Builder::getStopBits() const {
+ return m_eStopBits;
+}
+
+bool SerialConnection::Builder::isUsingLockFile() const {
+ return m_bLockFile;
+}
+
+std::string SerialConnection::Builder::getTypeAsString() const {
+ std::string sType;
+ switch(m_eType) {
+ case RS232:
+ sType = "RS232";
+ break;
+ case RS422:
+ sType = "RS422";
+ break;
+ case RS485:
+ sType = "RS485";
+ break;
+ default:
+ break;
+ }
+ return sType;
+}
+
+SerialConnection::Builder& SerialConnection::Builder::flowControl(const SerialConnection::FLOW_CONTROL& eFlowControl) {
+ m_eFlowControl = eFlowControl;
+ return *this;
+}
+
+SerialConnection::FLOW_CONTROL SerialConnection::Builder::getFlowControl() const {
+ return m_eFlowControl;
+}
+
+bool SerialConnection::Builder::isBuilt() const {
+ return m_bBuilt;
+}
+
+SerialConnection::SerialConnection(const Builder& oBuilder)
+: Connection(oBuilder.getTypeAsString())
+, m_sPortName(oBuilder.getPortName())
+, m_iBaudRate(oBuilder.getBaudRate())
+, m_eType(oBuilder.getType())
+, m_eParity(oBuilder.getParity())
+, m_eDataBits(oBuilder.getDataBits())
+, m_eStopBits(oBuilder.getStopBits())
+, m_eFlowControl(oBuilder.getFlowControl())
+{
+ if(!oBuilder.isBuilt()) {
+ //Throw Exception?
+ }
+#ifdef WIN32
+ m_iHandle = INVALID_HANDLE_VALUE;
+#else
+ m_iHandle = -1;
+#endif
+ m_apHandleLock.reset(new Lock());
+ if(oBuilder.isUsingLockFile()) {
+ std::vector<std::string> vParts = MTS::Text::split(m_sPortName, "/");
+ m_apLockFile.reset(new LockFile("/var/lock/LCK.." + vParts[vParts.size()-1]));
+ }
+}
+
+SerialConnection::~SerialConnection() {
+ doClose();
+ m_apHandleLock.reset();
+}
+
+const std::string& SerialConnection::getPortName() const {
+ return m_sPortName;
+}
+
+uint32_t SerialConnection::getBaudRate() const {
+ return m_iBaudRate;
+}
+
+int SerialConnection::getFileDescriptor() {
+ m_apHandleLock->lock();
+ int h = m_iHandle;
+ m_apHandleLock->unlock();
+ return h;
+}
+
+bool SerialConnection::doOpen(const int32_t& timeoutMillis) {
+ m_apHandleLock->lock();
+
+ if (m_iHandle != -1) {
+ m_apHandleLock->unlock();
+ return true;
+ }
+ if(!m_apLockFile.isNull() && !m_apLockFile->lock(timeoutMillis)) {
+ printError("SERIAL| Failed to obtain file lock");
+ m_apHandleLock->unlock();
+ return false;
+ }
+
+#ifdef WIN32
+
+#else
+ m_iHandle = ::open(m_sPortName.c_str(), O_RDWR | O_NOCTTY );
+ if (m_iHandle == -1) {
+ printWarning("SERIAL| Failed to open port [%s] [%d]", m_sPortName.c_str(), errno);
+ if(!m_apLockFile.isNull()) {
+ m_apLockFile->unlock();
+ }
+ m_apHandleLock->unlock();
+ return false;
+ }
+
+ int result = tcgetattr(m_iHandle, &m_stPrevOptions);
+ if (result == -1) {
+ printWarning("SERIAL| Failed to get attributes on port [%s] [%d]", m_sPortName.c_str(), errno);
+ }
+
+ termios options = m_stPrevOptions;
+
+ //Set to Raw Mode
+ cfmakeraw(&options);
+
+ //Set the Baud Rate
+ speed_t speed = B9600;
+ switch (m_iBaudRate) {
+ case 300:
+ speed = B300;
+ break;
+ case 600:
+ speed = B600;
+ break;
+ case 1200:
+ speed = B1200;
+ break;
+ case 2400:
+ speed = B2400;
+ break;
+ case 4800:
+ speed = B4800;
+ break;
+ case 9600:
+ speed = B9600;
+ break;
+ case 19200:
+ speed = B19200;
+ break;
+ case 38400:
+ speed = B38400;
+ break;
+ case 57600:
+ speed = B57600;
+ break;
+ case 115200:
+ speed = B115200;
+ break;
+ case 230400:
+ speed = B230400;
+ break;
+ case 460800:
+ speed = B460800;
+ break;
+ case 921600:
+ speed = B921600;
+ break;
+ default:
+ printWarning("SERIAL| Baud Rate [%d] not supported. Defaulting to 9600.", m_iBaudRate);
+ m_iBaudRate = 9600;
+ speed = B9600;
+ break;
+ }
+
+ result = cfsetispeed(&options, speed);
+ if (result == -1) {
+ printWarning("SERIAL| Failed to set input speed of [%d] on port [%s] [%d]", m_iBaudRate, m_sPortName.c_str(), errno);
+ goto CLEANUP;
+ }
+ result = cfsetospeed(&options, speed);
+ if (result == -1) {
+ printWarning("SERIAL| Failed to set output speed of [%d] on port [%s] [%d]", m_iBaudRate, m_sPortName.c_str(), errno);
+ goto CLEANUP;
+ }
+
+ //Set Parity, Stop Bits, and Data Length
+ switch(m_eParity) {
+ case ODD:
+ options.c_cflag |= ( PARODD | PARENB );
+ break;
+
+ case EVEN:
+ options.c_cflag |= PARENB;
+ break;
+
+ case OFF:
+ default:
+ options.c_cflag &= ~PARENB;
+ break;
+ }
+
+ options.c_cflag &= ~CSIZE;
+ switch(m_eDataBits) {
+ case B5:
+ options.c_cflag |= CS5;
+ break;
+
+ case B6:
+ options.c_cflag |= CS6;
+ break;
+
+ case B7:
+ options.c_cflag |= CS7;
+ break;
+
+ case B8:
+ default:
+ options.c_cflag |= CS8;
+ break;
+ }
+
+ switch(m_eStopBits) {
+ case B2:
+ options.c_cflag &= CSTOPB;
+ break;
+
+ case B1:
+ default:
+ options.c_cflag &= ~CSTOPB;
+ break;
+ }
+
+ switch (m_eFlowControl) {
+ case RTS_CTS:
+ options.c_cflag &= CRTSCTS;
+ break;
+ case NONE:
+ default:
+ options.c_cflag &= ~(IXON | IXOFF | IXANY);
+ break;
+ }
+
+ //Set Control Modes
+ options.c_cc[VMIN] = 0;
+ options.c_cc[VTIME] = 2; // tenths of seconds
+
+ result = tcsetattr(m_iHandle, TCSANOW, &options);
+ if (result == -1) {
+ printWarning("SERIAL| Failed to set configurations on port [%s] [%d]", m_sPortName.c_str(), errno);
+ goto CLEANUP;
+ }
+ result = tcflush(m_iHandle, TCIOFLUSH);
+ if (result == -1) {
+ printWarning("SERIAL| Failed to flush port [%s] [%d]", m_sPortName.c_str(), errno);
+ goto CLEANUP;
+ }
+#endif
+ m_apHandleLock->unlock();
+ printInfo("SERIAL| %s connection opened on %s @ %d", getName().c_str(), m_sPortName.c_str(), m_iBaudRate);
+ return true;
+CLEANUP:
+ cleanup();
+ m_apHandleLock->unlock();
+ return false;
+}
+
+void SerialConnection::doClose() {
+ m_apHandleLock->lock();
+ cleanup();
+ m_apHandleLock->unlock();
+}
+
+int SerialConnection::doRead(char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis) {
+ int32_t result = -1;
+#ifdef WIN32
+
+#else
+
+ int h = getFileDescriptor();
+
+ if (h == -1) {
+ printError("SERIAL| bad handle on port %s", m_sPortName.c_str());
+ return result;
+ }
+
+ if(timeoutMillis < 0) {
+ result = ::read(h, pBuffer, iSize);
+ } else {
+ fd_set readfs;
+ struct timeval stTimeout;
+ stTimeout.tv_usec = ((timeoutMillis%1000) * 1000);
+ stTimeout.tv_sec = timeoutMillis/1000;
+
+ FD_ZERO(&readfs);
+ FD_SET(h, &readfs);
+ int res = select(h + 1, &readfs, NULL, NULL, &stTimeout);
+ if(res == -1) {
+ result = -1;
+ } else if (res == 0) {
+ //Timeout Occured
+ //printTrace("SERIAL| read timed out on port [%s]", m_sPortName.c_str());
+ result = 0;
+ } else {
+ if (FD_ISSET(h, &readfs)) {
+ result = ::read(h, pBuffer, iSize);
+ } else {
+ //socket closed?
+ result = -1;
+ }
+ }
+ timeoutMillis = (stTimeout.tv_usec / 1000) + (stTimeout.tv_sec * 1000);
+ }
+#endif
+ if (result < 0) {
+ printWarning("SERIAL| failed to read from %s [%d]", m_sPortName.c_str(), errno);
+ }
+ return result;
+}
+
+int SerialConnection::doWrite(const char* pBuffer, const uint32_t& iSize, int32_t& timeoutMillis) {
+ int32_t result = -1;
+#ifdef WIN32
+
+#else
+
+ int h = getFileDescriptor();
+
+ if (h == -1) {
+ printError("SERIAL| bad handle on port %s", m_sPortName.c_str());
+ return result;
+ }
+
+ if(timeoutMillis < 0) {
+ result = ::write(h, pBuffer, iSize);
+ } else {
+ //No difference between timeout and no timeout
+ result = ::write(h, pBuffer, iSize);
+ }
+
+#endif
+ if (result < 0) {
+ printWarning("SERIAL| failed to write to %s [%d]", m_sPortName.c_str(), errno);
+ }
+ return result;
+}
+
+void SerialConnection::cleanup() {
+#ifdef WIN32
+ CloseHandle(m_iHandle);
+ m_iHandle = INVALID_HANDLE_VALUE;
+#else
+ if(m_iHandle >= 0) {
+ int result = tcsetattr(m_iHandle, TCSANOW, &m_stPrevOptions);
+ if (result == -1) {
+ printWarning("SERIAL| Failed to revert configurations on port [%s] [%d]", m_sPortName.c_str(), errno);
+ }
+ ::close(m_iHandle);
+ m_iHandle = -1;
+ }
+#endif
+ if(!m_apLockFile.isNull()) {
+ m_apLockFile->unlock();
+ }
+}
+
+void SerialConnection::drain() {
+ int result = tcdrain(m_iHandle);
+ if (result == -1) {
+ printWarning("SERIAL| Failed to drain port [%s] [%d]", m_sPortName.c_str(), errno);
+ }
+}
+
+void SerialConnection::flush() {
+ int result = tcflush(m_iHandle, TCIOFLUSH);
+ if (result == -1) {
+ printWarning("SERIAL| Failed to flush port [%s] [%d]", m_sPortName.c_str(), errno);
+ }
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 0000000..64428e9
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,9 @@
+project (TestRunnerClient)
+
+include_directories (../include)
+link_directories (..)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -DCPPUNIT_MAIN=main")
+
+add_executable (TestRunnerClient TestRunnerClient.cpp )
+target_link_libraries (TestRunnerClient cppunit mts mts_io ssl rt pthread)
diff --git a/test/TestRunnerClient.cpp b/test/TestRunnerClient.cpp
new file mode 100644
index 0000000..fcb9c75
--- /dev/null
+++ b/test/TestRunnerClient.cpp
@@ -0,0 +1,566 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Gerhard Leonhartsberger.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+#include "TestRunnerClient.h"
+
+#ifdef CPPUNIT_MAIN
+
+#include "cppunit/XmlOutputter.h"
+#include "cppunit/TextOutputter.h"
+#include "cppunit/TestSuite.h"
+#include "cppunit/TestResult.h"
+#include "cppunit/TestFailure.h"
+#include "cppunit/SourceLine.h"
+#include "cppunit/Exception.h"
+#include "cppunit/extensions/TestFactoryRegistry.h"
+#include "cppunit/extensions/TestDecorator.h"
+#include "cppunit/ui/text/TestRunner.h"
+
+#include <iostream>
+#include <sstream>
+#include <typeinfo>
+#include <vector>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#ifdef _WIN32 // Bugzilla 40710
+#include <windows.h>
+#include <winbase.h>
+#include <winsock.h>
+#else
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#endif
+
+#define MAX_HOSTNAME_SIZE 255
+
+/*
+ * CppUnitServer protocol constants
+ */
+static const std::string TRACE_START = "%TRACES ";
+static const std::string TRACE_END = "%TRACEE ";
+static const std::string TEST_RUN_START = "%TESTC ";
+static const std::string TEST_START = "%TESTS ";
+static const std::string TEST_END = "%TESTE ";
+static const std::string TEST_ERROR = "%ERROR ";
+static const std::string TEST_FAILED = "%FAILED ";
+static const std::string TEST_RUN_END = "%RUNTIME";
+static const std::string TEST_STOPPED = "%TSTSTP ";
+static const std::string TEST_TREE = "%TSTTREE";
+
+TestRunnerClient::TestRunnerClient()
+{
+ fTestResult = 0;
+ fClientSocket = -1;
+ fPort = 0;
+ fKeepAlive = 0;
+ fDebugMode = 0;
+
+ fHost = (char *) malloc(MAX_HOSTNAME_SIZE);
+ strcpy(fHost, "");
+}
+
+TestRunnerClient::~TestRunnerClient() {
+
+ if (fHost != NULL) {
+ free(fHost);
+ }
+}
+
+int TestRunnerClient::Run()
+{
+ if (fDebugMode)
+ {
+ std::cerr << "TestRunnerClient: Starting client." << std::endl;
+ }
+
+ if (Connect() == -1) {
+ return -1;
+ }
+
+ InstallListeners();
+
+ RunTests();
+
+ UninstallListeners();
+
+ if(fTestResult != NULL)
+ {
+ fTestResult->stop();
+ fTestResult= NULL;
+ }
+
+ ShutDown();
+
+ return 0;
+}
+
+void TestRunnerClient::Init(int n, char *args[])
+{
+ ParseCommandLine(n, args);
+ DefineHostName();
+}
+
+void TestRunnerClient::ParseCommandLine(int n, char *args[])
+{
+ // parse all arguments passed by args
+ for(int i = 0; i < n; i++)
+ {
+ std::string arg(args[i]);
+
+ // port option
+ std::string portOption("-port=");
+ int pos = arg.find(portOption);
+ if(pos> -1)
+ {
+ std::string v = arg.substr(pos + portOption.length(), arg.length());
+ fPort = atoi(v.c_str());
+ }
+
+ // debug option
+ std::string debugOption("-debug");
+ pos = arg.find(debugOption);
+ if(pos> - 1)
+ {
+ fDebugMode = 1;
+ }
+ }
+}
+
+void TestRunnerClient::DefineHostName()
+{
+ // set fHost to hostname or localhost
+ int ret = gethostname(fHost, MAX_HOSTNAME_SIZE);
+ if (ret == -1)
+ {
+ strcpy(fHost, "localhost");
+ }
+}
+
+int TestRunnerClient::Connect()
+{
+
+#ifdef _WIN32 // Bugzilla 40710
+ if (fDebugMode)
+ {
+ std::cerr << "TestRunnerClient: Starting Windows Sockets WSAStartup()." << std:endl;
+ }
+
+ // start up Windows Sockets
+ WSADATA WSAData;
+ int result = WSAStartup (MAKEWORD(1, 1), &WSAData);
+ if (result != NO_ERROR)
+ {
+ std::cerr << "TestRunnerClient: WSAStartup() failed! Error code: " << result << std::endl;
+ return -1;
+ }
+#endif
+
+ if (fDebugMode)
+ {
+ std::cerr << "TestRunnerClient: Trying to connect to " << fHost << ":" << fPort << std::endl;
+ }
+
+ fClientSocket = socket(AF_INET, SOCK_STREAM, 0);
+ if (fClientSocket == -1)
+ {
+ std::cerr << "TestRunnerClient: Socket creation failed! error code: " << fClientSocket << std::endl;
+ return -1;
+ }
+
+ struct hostent *host = gethostbyname(fHost);
+ if (host == NULL)
+ {
+ std::cerr << "TestRunnerClient: Cannot find host address for " << fHost << "." << std::endl;
+ fClientSocket = -1;
+ return -1;
+ }
+
+ struct sockaddr_in name;
+ memset((void *)&name, 0, sizeof(struct sockaddr_in));
+ name.sin_family = AF_INET;
+ name.sin_port = htons(fPort);
+
+ memcpy(&name.sin_addr, host->h_addr, host->h_length);
+
+ if (fDebugMode) {
+ std::cerr << "TestRunnerClient: Waiting for the JVM to listen ... (trying 3 times)" << std::endl;
+ }
+
+ int ret = -1;
+ int j = 0;
+ while ((j < 3) && (ret == -1))
+ {
+ ret = ::connect(fClientSocket, (struct sockaddr *) &name, sizeof(struct sockaddr_in));
+ if (ret == -1)
+ {
+ if (fDebugMode) {
+ std::cerr << "TestRunnerClient: Connection request, waiting 1 second. "
+ << ((j-3)*-1) << " times left." << std::endl;
+ }
+ PrivateSleep(1000);
+ j++;
+ }
+ }
+ if (ret == -1)
+ {
+ std::cerr << "TestRunnerClient: No connection established. Error code: " << errno << std::endl;
+ fClientSocket = -1;
+ return -1;
+ }
+
+ if (fDebugMode) {
+ std::cerr << "TestRunnerClient: Connection established." << std::endl;
+ }
+ return 0;
+}
+
+void TestRunnerClient::InstallListeners()
+{
+ fTestResult = new CppUnit::TestResult();
+ fTestResult->addListener(this);
+ fTestResult->addListener(&resultCollector);
+}
+
+void TestRunnerClient::UninstallListeners()
+{
+ fTestResult->removeListener(this);
+}
+
+void TestRunnerClient::RunTests()
+{
+
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+ CppUnit::Test *suite = registry.makeTest();
+ int count = suite->countTestCases();
+ NotifyTestRunStarted(count);
+
+ if (count == 0)
+ {
+ NotifyTestRunEnded(0);
+ }
+
+ long startTime = CurrentTimeMillis();
+ if (fDebugMode)
+ {
+ std::cerr <<"TestRunnerClient: Start sending test case tree ..." << std::endl;
+ }
+
+ SendTestTree(suite);
+
+ int elapsedTime = CurrentTimeMillis() - startTime;
+ if (fDebugMode) {
+ std::cerr << "TestRunnerClient: Done sending test case tree. Elapsed time is "
+ << elapsedTime << "ms." << std::endl;
+ }
+
+ long testStartTime = CurrentTimeMillis();
+ if (fDebugMode) {
+ std::cerr << "TestRunnerClient: Test start time is " << testStartTime
+ << "ms." << std::endl;
+ }
+
+ suite->run(fTestResult);
+
+ if (fTestResult == NULL || fTestResult->shouldStop())
+ {
+ NotifyTestRunStopped(CurrentTimeMillis() - testStartTime);
+ }
+ else
+ {
+ NotifyTestRunEnded(CurrentTimeMillis() - testStartTime);
+ }
+}
+
+void TestRunnerClient::ShutDown()
+{
+ if (fClientSocket != -1)
+ {
+ if (fDebugMode) {
+ std::cerr << "TestRunnerClient: Closing connection to CppUnit sever at "
+ << fHost << ":" << fPort << std::endl;
+ }
+
+#ifdef _WIN32 // Bugzilla 40710
+ // TODO: std:err output for error return codes
+ closesocket(fClientSocket);
+ WSACleanup();
+#else
+ int result = close(fClientSocket);
+ if (result != 0)
+ {
+ std::cerr << "TestRunnerClient: Close connection error: " << errno << std::endl;
+ }
+#endif
+
+ fClientSocket = -1;
+ }
+}
+
+void TestRunnerClient::Stop()
+{
+ if (fTestResult != NULL)
+ {
+ fTestResult->stop();
+ }
+}
+
+void TestRunnerClient::SendTestTree(CppUnit::Test *test)
+{
+ if (typeid(*test) == typeid(CppUnit::TestDecorator))
+ {
+ class TmpClass : public CppUnit::TestDecorator {
+
+ public:
+ TmpClass(Test *t):CppUnit::TestDecorator(t)
+ {
+ // nothing to do
+ }
+
+ ~TmpClass() // Bugzilla 39894
+ {
+ // nothing to do
+ }
+
+ CppUnit::Test *getTest()
+ {
+ return m_test;
+ }
+ };
+
+ TmpClass *t = (TmpClass *)test;
+ SendTestTree(t->getTest());
+ }
+ else if (typeid(*test) == typeid(CppUnit::TestSuite))
+ {
+ CppUnit::TestSuite *suite = (CppUnit::TestSuite *)test;
+ const std::vector<CppUnit::Test *> &x = suite->getTests();
+
+ std::ostringstream os;
+ os << suite->getName() << ",true," << x.size();
+ NotifyTestTreeEntry(os.str());
+
+ for(unsigned int i=0; i < x.size(); i++)
+ {
+ SendTestTree(x[i]);
+ }
+ }
+ else
+ {
+ std::ostringstream os;
+ os << test->getName() << ",false," << test->countTestCases();
+ NotifyTestTreeEntry(os.str());
+ }
+}
+
+void TestRunnerClient::SendMessage(std::string msg)
+{
+ if (fClientSocket == -1)
+ {
+ return;
+ }
+
+#ifdef _WIN32 // Bugzilla 40710
+ send (fClientSocket, msg.c_str(), msg.length(), 0);
+ send (fClientSocket, "\n", 1, 0);
+#else
+ write(fClientSocket, msg.c_str(), msg.length());
+ write(fClientSocket, "\n", 1);
+#endif
+
+ if (fDebugMode)
+ {
+ std::cerr << "TestRunnerClient: Sent message \"" << msg << "\""
+ << std::endl;
+ }
+}
+
+void TestRunnerClient::NotifyTestRunStarted(int testCount)
+{
+ std::ostringstream os;
+ os << TEST_RUN_START << testCount;
+ SendMessage(os.str());
+}
+
+void TestRunnerClient::NotifyTestRunEnded(long elapsedTime)
+{
+ std::ostringstream os;
+ os << TEST_RUN_END << elapsedTime;
+ SendMessage(os.str());
+}
+
+void TestRunnerClient::NotifyTestRunStopped(long elapsedTime)
+{
+ std::ostringstream os;
+ os << TEST_STOPPED << elapsedTime;
+ SendMessage(os.str());
+}
+
+void TestRunnerClient::NotifyTestTreeEntry(std::string treeEntry)
+{
+ SendMessage(TEST_TREE + treeEntry);
+}
+
+void TestRunnerClient::NotifyTestStarted(std::string testName)
+{
+ SendMessage(TEST_START + testName);
+}
+
+void TestRunnerClient::NotifyTestEnded(std::string testName)
+{
+ SendMessage(TEST_END + testName);
+}
+
+void TestRunnerClient::NotifyTestFailed(std::string status, std::string testName, std::string trace)
+{
+ SendMessage(status + testName);
+ SendMessage(TRACE_START);
+ SendMessage(trace);
+ SendMessage(TRACE_END);
+}
+
+// From TestListener
+void TestRunnerClient::startTest(CppUnit::Test *test)
+{
+ NotifyTestStarted(test->getName());
+}
+
+// From TestListener
+void TestRunnerClient::addFailure(const CppUnit::TestFailure &failure)
+{
+ if(failure.isError())
+ {
+ NotifyTestFailed(TEST_ERROR,failure.failedTestName(),GetTrace(failure));
+ }
+ else
+ {
+ NotifyTestFailed(TEST_FAILED,failure.failedTestName(),GetTrace(failure));
+ }
+}
+
+// From TestListener
+void TestRunnerClient::endTest(CppUnit::Test *test)
+{
+ NotifyTestEnded(test->getName());
+}
+
+std::string TestRunnerClient::GetTrace(const CppUnit::TestFailure &failure)
+{
+ std::ostringstream os;
+
+ CppUnit::Exception *e=failure.thrownException();
+ if(e->sourceLine().lineNumber()!=-1)
+ {
+ os << "File " << e->sourceLine().fileName() << ":" << e->sourceLine().lineNumber() << "\n";
+ }
+ else
+ {
+ os << "File Unknown:1\n";
+ }
+ /* TODO: expected, actual value implementation
+ if(typeid(*e)==typeid(CppUnit::NotEqualException))
+ {
+ CppUnit::NotEqualException *ne=(CppUnit::NotEqualException *)e;
+
+ os << "Expected Value: " << ne->expectedValue() << "\n";
+ os << "Actual Value: " << ne->expectedValue() << "\n";
+ os << "Additional Message: " << ne->additionalMessage() << "\n";
+ }
+ else
+ {
+ End */
+ os << "Message: " << std::string(e->what()) << "\n";
+ /* } */
+
+ return(os.str());
+}
+
+long TestRunnerClient::CurrentTimeMillis()
+{
+#ifdef _WIN32 // Bugzilla 40710
+ unsigned long long p;
+ __asm__ __volatile__ ("rdtsc" : "=A" (p));
+ return (unsigned long)p;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return((long)(tv.tv_sec*1000) + (tv.tv_usec/1000));
+#endif
+}
+
+void TestRunnerClient::PrivateSleep(int millisecs)
+{
+ struct timeval delta;
+ delta.tv_sec = (millisecs * 1000L) / 1000000L;
+ delta.tv_usec = (millisecs * 1000L) % 1000000L;
+ select (0, NULL, NULL, NULL, &delta);
+}
+
+CppUnit::TestResultCollector& TestRunnerClient::getResultCollector() {
+ return resultCollector;
+}
+
+/*!
+ * This is the main routine. The TestRunnerClient is initialized and run. The
+ * CppUnit tests are created, executed, and sent to the CppUnitServer.
+ * If no connection to the CppUnitServer was established the CppUnit tests are
+ * displayed on the console.
+ *
+ * @return <code>0</code> if the results of the CppUnit tests were sent to the
+ * CppUnitServer successfully.
+ * <code>-1</code> if a connection could not be established to the
+ * CppUnitServer.
+ */
+int CPPUNIT_MAIN(int n, char *arg[])
+{
+ std::ofstream xmlFileOut("cppunit_results.xml");
+
+ TestRunnerClient client;
+ client.Init(n, arg);
+ int ret = client.Run();
+ if (ret == -1)
+ {
+ //The Test Runner Client has failed
+ //Create the event manager and test controller
+
+ CppUnit::TestResult controller;
+
+ // Add a listener that collects test result
+ CppUnit::TestResultCollector result;
+ controller.addListener ( &result );
+
+ CppUnit::XmlOutputter xmlOutputter ( &result, xmlFileOut );
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+ CppUnit::Test *suite = registry.makeTest();
+
+ CppUnit::TextUi::TestRunner *runner = new CppUnit::TextUi::TestRunner();
+ runner->addTest(suite);
+ runner->run(controller);
+
+ // Output to XML
+ xmlOutputter.write();
+ } else {
+
+ CppUnit::TextOutputter textOutputter (&client.getResultCollector(), std::cout);
+ textOutputter.write();
+
+ // Output to XML
+ CppUnit::XmlOutputter xmlOutputter ( &client.getResultCollector(), xmlFileOut );
+ xmlOutputter.write();
+ }
+
+
+ xmlFileOut.close();
+}
+
+#endif /*CPPUNIT_MAIN*/
diff --git a/test/TestRunnerClient.h b/test/TestRunnerClient.h
new file mode 100644
index 0000000..4dc4460
--- /dev/null
+++ b/test/TestRunnerClient.h
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Gerhard Leonhartsberger.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+#ifndef TESTRUNNERSERVER_H_
+#define TESTRUNNERSERVER_H_
+
+#ifdef CPPUNIT_MAIN
+
+#include "cppunit/TestResultCollector.h"
+#include "cppunit/TestListener.h"
+
+#include <vector>
+#include <string>
+#include <string.h>
+#include <stdlib.h>
+
+
+/*!
+ * Class <code>TestRunnerClient</code> handles the network connection to the
+ * <code>CppUnitServer</code> and executes all registered CppUnit tests.
+ * <p>
+ * The meta data of the CppUnit tests and the test results are sent to the
+ * <code>CppUnitServer</code> for displaying.
+ * </p>
+ * <p>
+ * For debugging purposes class <code>TestRunnerClient</code> displays debug
+ * messages on <code>std.cerr</code>. The debug modus is activated by specifying
+ * <code>debug</code> command line option. The command line is parsed by method
+ * <code>Init()</code>.
+ * </p>
+ * <p>
+ * Note: This class is not intended to be subclassed by clients. This class is
+ * based on the original <code>RemoteTestRunner</code> class provided by
+ * <code>org.eclipse.cdt.cppunit</code>.
+ * </p>
+ *
+ * @author Gerhard Leonhartsberger
+ */
+class TestRunnerClient: public CppUnit::TestListener
+{
+private:
+ CppUnit::TestResult *fTestResult;
+ CppUnit::TestResultCollector resultCollector;
+ int fClientSocket;
+ char *fHost;
+ int fPort;
+ int fDebugMode;
+ int fKeepAlive;
+
+public:
+ TestRunnerClient();
+ virtual ~TestRunnerClient();
+
+ CppUnit::TestResultCollector& getResultCollector();
+
+ /*!
+ * Initializes the <code>TestRunnerClient</code>.
+ * <p>
+ * The given <code>args</code> are parsed. The syntax for the arguments is
+ * defined in EBNF as follows: <code>{-option=value}</code>
+ * </p>
+ *
+ * @param n The number of arguments.
+ * @param args The argument values. Valid options are:
+ * <li><code>-debug</code> When present the TestRunnerClient
+ * is run in debug modus and displays debug messages.</li>
+ * <li><code>-port=number</code> Defines the port where
+ * CppUnitServer is listening for client connections.</li>
+ */
+ void Init(int n,char *args[]);
+
+ /*!
+ * Runs the TestRunnerClient. A trial to connect to the CppUnitServer is done.
+ * The test results are sent to the CppUnitServer.
+ *
+ * @return The return value is <code>0</code> when the CppUnitServer was connected successfully
+ * otherwise the return value is <code>-1</code>.
+ */
+ int Run();
+
+ /*!
+ * Stops processing <code>CppUnit</code> from executing tests.
+ */
+ void Stop();
+
+ /*!
+ * Method defined in <code>CppUnit::TestListener</code>.
+ */
+ void startTest(CppUnit::Test *test);
+
+ /*!
+ * Method defined in <code>CppUnit::TestListener</code>.
+ */
+ void addFailure(const CppUnit::TestFailure &failure);
+
+ /*!
+ * Method defined in <code>CppUnit::TestListener</code>.
+ */
+ void endTest(CppUnit::Test *test);
+
+private:
+ int Connect();
+ void RunTests();
+ void ShutDown();
+
+ // utility methods
+ void ParseCommandLine(int n, char *args[]);
+ void DefineHostName();
+ void InstallListeners();
+ void UninstallListeners();
+
+ /*!
+ * Sends the given test to the CppUnitView.
+ * <p>
+ * In case of test is of type CppUnit::Test the following protocol is sent:
+ * <code>TSTTREE name, false, testCaseCount</code>
+ * </p>
+ * <p>
+ * In case of test is of type CppUnit::TestSuite the following protocol is sent:
+ * TSTTREE name, true, testCount
+ * </p>
+ * @param test the CppUnit test
+ */
+ void SendTestTree(CppUnit::Test *test);
+ void SendMessage(std::string msg);
+
+ // Notification methods
+ void NotifyTestRunStarted(int testCount);
+ void NotifyTestRunEnded(long elapsedTime);
+ void NotifyTestRunStopped(long elapsedTime);
+ void NotifyTestTreeEntry(std::string treeEntry);
+ void NotifyTestStarted(std::string testName);
+ void NotifyTestEnded(std::string testName);
+ void NotifyTestFailed(std::string status, std::string testName, std::string trace);
+
+ std::string GetTrace(const CppUnit::TestFailure &failure);
+ long CurrentTimeMillis();
+ void PrivateSleep(int millisecs);
+};
+
+#endif /*CPPUNIT_MAIN*/
+#endif /*TESTRUNNERSERVER_H_*/
diff --git a/version b/version
new file mode 100644
index 0000000..2e94ead
--- /dev/null
+++ b/version
@@ -0,0 +1 @@
+VERSION=0.1