diff options
author | Michael 'Mickey' Lauer <mickey@vanille-media.de> | 2010-03-09 20:33:47 +0100 |
---|---|---|
committer | Michael 'Mickey' Lauer <mickey@vanille-media.de> | 2010-03-09 20:33:47 +0100 |
commit | 01c994311391e6593d46a09f1d02018b50a68019 (patch) | |
tree | 2f3862e38c744ff858d54432b4d46427ce932ef7 /libgsm0710mux | |
parent | e443dccbf0654dd550bb0bc78eb47a0e86ef1eb4 (diff) | |
download | cornucopia-01c994311391e6593d46a09f1d02018b50a68019.tar.gz cornucopia-01c994311391e6593d46a09f1d02018b50a68019.tar.bz2 cornucopia-01c994311391e6593d46a09f1d02018b50a68019.zip |
add libgsm0710mux and fso-abyss to the cornucopia directory
they are cornucopia subprojects and should have been here since
long
Diffstat (limited to 'libgsm0710mux')
-rw-r--r-- | libgsm0710mux/.gitignore | 31 | ||||
-rw-r--r-- | libgsm0710mux/AUTHORS | 2 | ||||
-rw-r--r-- | libgsm0710mux/COPYING | 340 | ||||
-rw-r--r-- | libgsm0710mux/ChangeLog | 1 | ||||
-rw-r--r-- | libgsm0710mux/INSTALL | 237 | ||||
-rw-r--r-- | libgsm0710mux/MAINTAINERS | 4 | ||||
-rw-r--r-- | libgsm0710mux/Makefile.am | 100 | ||||
-rw-r--r-- | libgsm0710mux/NEWS | 0 | ||||
-rw-r--r-- | libgsm0710mux/README | 23 | ||||
-rw-r--r-- | libgsm0710mux/TODO | 7 | ||||
-rwxr-xr-x | libgsm0710mux/autogen.sh | 12 | ||||
-rw-r--r-- | libgsm0710mux/configure.ac | 72 | ||||
-rw-r--r-- | libgsm0710mux/gsm0710mux-1.0.deps | 2 | ||||
-rw-r--r-- | libgsm0710mux/gsm0710mux-1.0.pc.in | 13 | ||||
-rw-r--r-- | libgsm0710mux/gsm0710mux/channel.vala | 216 | ||||
-rw-r--r-- | libgsm0710mux/gsm0710mux/consts.vala | 85 | ||||
-rw-r--r-- | libgsm0710mux/gsm0710mux/manager.vala | 264 | ||||
-rw-r--r-- | libgsm0710mux/gsm0710mux/multiplexer.vala | 560 |
18 files changed, 1969 insertions, 0 deletions
diff --git a/libgsm0710mux/.gitignore b/libgsm0710mux/.gitignore new file mode 100644 index 00000000..f6c27502 --- /dev/null +++ b/libgsm0710mux/.gitignore @@ -0,0 +1,31 @@ +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +compile +config.guess +config.h +config.h.in +config.h.in~ +config.log +config.status +config.sub +configure +depcomp +install-sh +libtool +ltmain.sh +missing +.deps +.libs +*.c +*.h +*.pc +*.o +*.lo +*.la +*.gir +*.vapi +stamp-h1 +.*stamp + diff --git a/libgsm0710mux/AUTHORS b/libgsm0710mux/AUTHORS new file mode 100644 index 00000000..ee719a67 --- /dev/null +++ b/libgsm0710mux/AUTHORS @@ -0,0 +1,2 @@ +Michael 'Mickey' Lauer <mickey@vanille-media.de> + diff --git a/libgsm0710mux/COPYING b/libgsm0710mux/COPYING new file mode 100644 index 00000000..623b6258 --- /dev/null +++ b/libgsm0710mux/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libgsm0710mux/ChangeLog b/libgsm0710mux/ChangeLog new file mode 100644 index 00000000..f8175ebf --- /dev/null +++ b/libgsm0710mux/ChangeLog @@ -0,0 +1 @@ +Please see git changelog. diff --git a/libgsm0710mux/INSTALL b/libgsm0710mux/INSTALL new file mode 100644 index 00000000..d3c5b40a --- /dev/null +++ b/libgsm0710mux/INSTALL @@ -0,0 +1,237 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007 Free Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 6. Often, you can also type `make uninstall' to remove the installed + files again. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/libgsm0710mux/MAINTAINERS b/libgsm0710mux/MAINTAINERS new file mode 100644 index 00000000..b605ccb1 --- /dev/null +++ b/libgsm0710mux/MAINTAINERS @@ -0,0 +1,4 @@ +Michael 'Mickey' Lauer +E-Mail: mlauer@vanille-media.de +Userid: mickeyl + diff --git a/libgsm0710mux/Makefile.am b/libgsm0710mux/Makefile.am new file mode 100644 index 00000000..8d5eb07f --- /dev/null +++ b/libgsm0710mux/Makefile.am @@ -0,0 +1,100 @@ +NULL = + +AUTOMAKE_OPTIONS = subdir-objects + +VALAC_ARGS = \ + --vapidir $(top_srcdir)/vapi \ + --header gsm0710mux.h \ + --pkg config \ + --pkg gsm0710-1.0 \ + --pkg fsotransport-2.0 \ + --pkg fsobasics-2.0 \ + --library=gsm0710mux-1.0 \ + --save-temps --basedir $(top_srcdir) + +if WANT_DEBUG +VALAC_ARGS += -g -D DEBUG +AM_CFLAGS = -ggdb -O0 +endif + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = gsm0710mux-1.0.pc + +vapidir = $(datadir)/vala/vapi + +dist_vapi_DATA = \ + gsm0710mux-1.0.vapi \ + gsm0710mux-1.0.deps \ + $(NULL) + +SUBDIRS = \ + $(NULL) + +INCLUDES = \ + $(DEPS_CFLAGS) \ + -include $(CONFIG_HEADER) \ + $(NULL) + +gsm0710muxincludedir = $(includedir)/gsm0710mux-1.0 +gsm0710muxinclude_HEADERS = gsm0710mux.h + +BUILT_SOURCES = gsm0710mux/.vala.stamp + +lib_LTLIBRARIES = \ + libgsm0710mux.la \ + $(NULL) + +libgsm0710mux_la_VALASOURCES = \ + gsm0710mux/consts.vala \ + gsm0710mux/channel.vala \ + gsm0710mux/multiplexer.vala \ + gsm0710mux/manager.vala \ + $(NULL) + +libgsm0710mux_la_SOURCES = \ + $(libgsm0710mux_la_VALASOURCES:.vala=.c) \ + $(NULL) + +gsm0710mux-1.0.vapi gsm0710mux/.vala.stamp: $(libgsm0710mux_la_VALASOURCES) + $(VALAC) -C $(VALAC_ARGS) $^ + touch $@ + +libgsm0710mux_la_LIBADD = \ + $(DEPS_LIBS) \ + $(NULL) + +EXTRA_DIST = \ + MAINTAINERS \ + gsm0710mux-1.0.pc.in \ + gsm0710mux-1.0.vapi \ + gsm0710mux-1.0.deps \ + $(libgsm0710mux_la_VALASOURCES) \ + gsm0710mux/.vala.stamp \ + $(NULL) + +CLEANFILES = \ + gsm0710mux/channel.? \ + gsm0710mux/serial.? \ + gsm0710mux/multiplexer.? \ + gsm0710mux/server.? \ + gsm0710mux/consts.? \ + gsm0710mux/main.? \ + gsm0710mux/.vala.stamp \ + $(NULL) + +DISTCLEANFILES = \ + $(NULL) + +MAINTAINERCLEANFILES = aclocal.m4 compile config.guess config.sub \ + configure depcomp install-sh ltmain.sh \ + Makefile.in missing config.h.in \ + intltool-extract \ + intltool-merge \ + intltool-update \ + mkinstalldirs \ + gsm0710mux/*.c gsm0710mux/*.h \ + *~ \ + gsm0710mux-1.0.gir \ + gsm0710mux-1.0.vapi \ + gsm0710mux-1.0.pc \ + $(NULL) diff --git a/libgsm0710mux/NEWS b/libgsm0710mux/NEWS new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/libgsm0710mux/NEWS diff --git a/libgsm0710mux/README b/libgsm0710mux/README new file mode 100644 index 00000000..5a55f541 --- /dev/null +++ b/libgsm0710mux/README @@ -0,0 +1,23 @@ +libgsm0710mux +============= + +This library supports implementing a GSM 07.10 Multiplexing Server. +It requires libgsm0710 for the protocol engine and glib. + +You may either write standalone programs (e.g. communicating over dbus +and using ptys) or embed the library in your GSM server to improve +performance. + +Here's why using ptys is bad: +============================= +Hardware -> Kernel -> Userland (07.10) -> Kernel (pty) -> Userland (GSM Server)-> UI + +Every '->' involves context switches and copying data around. + +The recommended way of using this library is to embed it in your GSM server: + +Hardware -> Kernel -> Userland (07.10 + GSM Server) -> UI + +(Yes, eventually it would be useful to have 07.10 multiplexing directly in the +kernel. But until this happens, the aforementioned sequence is the best +we have). diff --git a/libgsm0710mux/TODO b/libgsm0710mux/TODO new file mode 100644 index 00000000..a09a695f --- /dev/null +++ b/libgsm0710mux/TODO @@ -0,0 +1,7 @@ +Before 1.0: + +(Deep Sleep) + * Configure option for 'reset_timer_on' = 'read', 'write', 'readwrite' + +(Flow control) + * Configure option for 'on_flow_control' = 'drop', 'stall' diff --git a/libgsm0710mux/autogen.sh b/libgsm0710mux/autogen.sh new file mode 100755 index 00000000..61289aa0 --- /dev/null +++ b/libgsm0710mux/autogen.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure "$@" diff --git a/libgsm0710mux/configure.ac b/libgsm0710mux/configure.ac new file mode 100644 index 00000000..bfc49f69 --- /dev/null +++ b/libgsm0710mux/configure.ac @@ -0,0 +1,72 @@ +AC_INIT([libgsm0710mux], [0.9.2], [mlauer@vanille-media.de], [libgsm0710mux]) +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_HEADERS(config.h) +AM_INIT_AUTOMAKE([dist-bzip2]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_GNU_SOURCE +AC_PROG_CC +AM_PROG_CC_C_O +AC_DISABLE_STATIC +AC_PROG_LIBTOOL + +AC_SUBST(CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(LDFLAGS) + +# pkg-config requirements +PKG_PROG_PKG_CONFIG + +VALA_REQUIRED=0.7.6 +GLIB_REQUIRED=2.12.0 +FSO_BASICS_REQUIRED=0.8.3 +FSO_TRANSPORT_REQUIRED=0.9.5 +GSM_REQUIRED=1.2.0 + +# vala +AC_PATH_PROG(VALAC, valac, valac) +AC_SUBST(VALAC) + +# dependencies +PKG_CHECK_MODULES(DEPS, + glib-2.0 >= $GLIB_REQUIRED + gobject-2.0 >= $GLIB_REQUIRED + gsm0710-1.0 >= $GSM_REQUIRED + fsotransport-2.0 >= $FSO_TRANSPORT_REQUIRED + fsobasics-2.0 >= $FSO_BASICS_REQUIRED) +AC_SUBST(DEPS_CFLAGS) +AC_SUBST(DEPS_LIBS) + +# check for debugging +AC_ARG_ENABLE(debug, + [ --enable-debug Enable debug build (default=disabled)], + debug="yes", debug="no") +AM_CONDITIONAL( [WANT_DEBUG], [test x"$debug" = x"yes"]) + +# git version +GITV=`cat .git/refs/heads/master || echo "unknown"` +AC_DEFINE_UNQUOTED([PACKAGE_GITV], ["${GITV}"], [git version]) + +# output +AC_CONFIG_FILES([Makefile +gsm0710mux-1.0.pc]) + +AC_OUTPUT + +# info +echo +echo +echo +echo "------------------------------------------------------------------------" +echo "$PACKAGE_NAME $PACKAGE_VERSION-$GITV" +echo "------------------------------------------------------------------------" +echo +echo "Configuration Options:" +echo +echo " debug build.............: $debug" +echo +echo " prefix..................: $prefix" +echo +echo "------------------------------------------------------------------------" +echo +echo "Now type 'make' to compile and 'make install' to install this package." diff --git a/libgsm0710mux/gsm0710mux-1.0.deps b/libgsm0710mux/gsm0710mux-1.0.deps new file mode 100644 index 00000000..fe6ec949 --- /dev/null +++ b/libgsm0710mux/gsm0710mux-1.0.deps @@ -0,0 +1,2 @@ +posix +fsotransport-2.0 diff --git a/libgsm0710mux/gsm0710mux-1.0.pc.in b/libgsm0710mux/gsm0710mux-1.0.pc.in new file mode 100644 index 00000000..11b58cd7 --- /dev/null +++ b/libgsm0710mux/gsm0710mux-1.0.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +datarootdir=@datarootdir@ +datadir=@datadir@ + +Name: libgsm0710mux +Description: GSM 07.10 Multiplexing Engine +Version: @VERSION@ +Requires: fsotransport-2.0 +Libs: -L${libdir} -lgsm0710mux +Cflags: -I${includedir}/gsm0710mux-1.0 diff --git a/libgsm0710mux/gsm0710mux/channel.vala b/libgsm0710mux/gsm0710mux/channel.vala new file mode 100644 index 00000000..5c55cdf0 --- /dev/null +++ b/libgsm0710mux/gsm0710mux/channel.vala @@ -0,0 +1,216 @@ +/* + * This file is part of libgsm0710mux + * + * (C) 2009-2010 Michael 'Mickey' Lauer <mlauer@vanille-media.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +//=========================================================================== +using GLib; +using CONST; +using Gsm0710; + +//=========================================================================== +// The Channel class +// +internal class Channel +{ + public enum Status + { + Requested, /* requested on 07.10 layer, but not acknowledged by modem */ + Acked, /* acknowledged by modem, but not opened by any client */ + Open, /* acknowledged and opened by a client */ + Denied, /* denied by the modem. this status is persistent */ + Shutdown, /* shutting down, will no longer be openable */ + } + + // FIXME: Do we really want to expose the whole multiplexer object to the channel? Consider only using the relevant delegates. + Multiplexer _multiplexer; + Status _status; + FsoFramework.Transport transport; + FsoFramework.Logger logger; + + string _name; + int _number; + int _serial_status; + + SourceFunc ackCallback; + uint ackTimeoutWatch; + + public Channel( Multiplexer? multiplexer, + Gsm0710mux.ChannelInfo info, + SourceFunc? ackCallback = null, + uint ackTimeout = 0 ) + { + logger = FsoFramework.Logger.createFromKeyFile( FsoFramework.theConfig, LIBGSM0710MUX_CONFIG_SECTION, LIBGSM0710MUX_LOGGING_DOMAIN ); + logger.setReprDelegate( repr ); + + _multiplexer = multiplexer; + _status = Status.Requested; + _name = info.consumer; + _number = info.number; + + info.tspec.create(); + transport = info.tspec.transport; + transport.setPriorities( TRANSPORT_READ_PRIORITY, TRANSPORT_WRITE_PRIORITY ); + transport.setDelegates( onRead, onHup ); + info.tspec.transport = transport; + assert( logger.debug( "Constructed" ) ); + + if ( ackTimeout > 0 ) + { + ackTimeoutWatch = Timeout.add_seconds( ackTimeout, ackCallback ); + } + this.ackCallback = ackCallback; + } + + ~Channel() + { + assert( logger.debug( "Destructed" ) ); + } + + public string repr() + { + return "<%d (%s) connected via %s>".printf( _number, _name, transport != null? transport.getName() : "(none)" ); + } + + public string acked() + { + if ( ackTimeoutWatch > 0 ) + { + Source.remove( ackTimeoutWatch ); + } + + assert( logger.debug( "Acked" ) ); + + if ( !transport.open() ) + { + logger.error( "Could not open transport: %s".printf( Posix.strerror( Posix.errno ) ) ); + return ""; + } + + _status = Status.Acked; + + if ( ackCallback != null ) + { + assert( logger.debug( "AckCallback is set, calling" ) ); + ackCallback(); + } + else + { + assert( logger.debug( "AckCallback NOT set" ) ); + } + + return transport.getName(); + } + + public void close() + { + assert( logger.debug( "Closing" ) ); + var oldstatus = _status; + _status = Status.Shutdown; + + if ( oldstatus != Status.Requested ) + { + if (_multiplexer != null ) + _multiplexer.channel_closed( _number ); + } + + if ( transport != null ) + { + transport.close(); + transport = null; + } + } + + public string name() + { + return _name; + } + + public string path() + { + return transport.getName(); + } + + public bool isAcked() + { + return _status != Status.Requested; + } + + public void setSerialStatus( int newstatus ) + { + assert( logger.debug( "setSerialStatus()" ) ); + + var oldstatus = _serial_status; + _serial_status = newstatus; + + if ( Gsm0710mux.Manager.leave_fc_alone ) + { + return; + } + + // check whether the FC bit has been set + if ( ( ( oldstatus & SerialStatus.FC ) == 0 ) && + ( ( newstatus & SerialStatus.FC ) == SerialStatus.FC ) ) + { + logger.warning( "FC has been set. Disabling read from PTY" ); + transport.freeze(); + } + + // check whether the FC bit has been cleared + if ( ( ( oldstatus & SerialStatus.FC ) == SerialStatus.FC ) && + ( ( newstatus & SerialStatus.FC ) == 0 ) ) + { + logger.warning( "FC has been cleared. Reenabling read from PTY" ); + transport.thaw(); + } + } + + public void deliverData( void* data, int len ) + { + transport.write( data, len ); + MainContext.default().iteration( false ); // give other channels a chance (round-robin) + } + + // + // delegates from Pty object + // + public void onRead( FsoFramework.Transport transport ) + { + assert( logger.debug( "onRead() from Transport; reading." ) ); + assert( _multiplexer != null ); + + if ( ( _serial_status & SerialStatus.FC ) == SerialStatus.FC ) + { + logger.warning( "FC active... reading anyways..." ); + } + + var buffer = new char[8192]; + int bytesread = transport.read( buffer, 8192 ); + assert( logger.debug( @"Read $bytesread bytes" ) ); + + _multiplexer.submit_data( _number, buffer, (int)bytesread ); + } + + public void onHup( FsoFramework.Transport transport ) + { + assert( logger.debug( "onHup() from Transport; closing." ) ); + close(); + } + +} diff --git a/libgsm0710mux/gsm0710mux/consts.vala b/libgsm0710mux/gsm0710mux/consts.vala new file mode 100644 index 00000000..9cbc97ad --- /dev/null +++ b/libgsm0710mux/gsm0710mux/consts.vala @@ -0,0 +1,85 @@ +/* + * const.vala: constants and helper functions + * + * (C) 2009-2010 Michael 'Mickey' Lauer <mlauer@vanille-media.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +public errordomain Gsm0710mux.MuxerError +{ + CHANNEL_TAKEN, + INVALID_CHANNEL, + INVALID_TRANSPORT, + NO_SESSION, + NO_CHANNEL, + SESSION_ALREADY_OPEN, + SESSION_OPEN_ERROR, +} + +namespace CONST +{ + //=========================================================================== + internal const string LIBGSM0710MUX_CONFIG_SECTION = "libgsm0710mux"; + internal const string LIBGSM0710MUX_LOGGING_DOMAIN = "libgsm0710mux"; + + internal const uint GSM_PING_SEND_TIMEOUT = 5; + internal const uint GSM_PING_RESPONSE_TIMEOUT = 3; + + internal const int TRANSPORT_READ_PRIORITY = -20; + internal const int TRANSPORT_WRITE_PRIORITY = 0; + + //=========================================================================== + internal void hexdump( bool write, void* data, int len, FsoFramework.Logger logger ) + { + if ( len < 1 ) + return; + + int BYTES_PER_LINE = 16; + + uchar* pointer = (uchar*) data; + var hexline = new StringBuilder( write? ">>> " : "<<< " ); + var ascline = new StringBuilder(); + uchar b; + int i; + + for ( i = 0; i < len; ++i ) + { + b = pointer[i]; + hexline.append_printf( "%02X ", b ); + if ( 31 < b && b < 128 ) + ascline.append_printf( "%c", b ); + else + ascline.append_printf( "." ); + + if ( i % BYTES_PER_LINE+1 == BYTES_PER_LINE ) + { + hexline.append( ascline.str ); + logger.debug( hexline.str ); + hexline = new StringBuilder( write? ">>> " : "<<< " ); + ascline = new StringBuilder(); + } + } + if ( i % BYTES_PER_LINE+1 != BYTES_PER_LINE ) + { + while ( hexline.len < 52 ) + hexline.append_c( ' ' ); + + hexline.append( ascline.str ); + logger.debug( hexline.str ); + } + } +} diff --git a/libgsm0710mux/gsm0710mux/manager.vala b/libgsm0710mux/gsm0710mux/manager.vala new file mode 100644 index 00000000..aedcb7ab --- /dev/null +++ b/libgsm0710mux/gsm0710mux/manager.vala @@ -0,0 +1,264 @@ +/* + * This file is part of libgsm0710mux + * + * (C) 2009-2010 Michael 'Mickey' Lauer <mlauer@vanille-media.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +//=========================================================================== +using GLib; +using CONST; + +extern MainLoop loop; + +namespace Gsm0710mux { + +//=========================================================================== +public class ChannelInfo +{ + /** + * Consumer Identification + **/ + public string consumer; + /** + * Requested multiplexing channel number + **/ + public int number; + /** + * Transport specification for the transport the + * channel should be exposed over + **/ + public FsoFramework.TransportSpec tspec; +} + +//=========================================================================== +public class Manager : Object +{ + private Multiplexer muxer; + private FsoFramework.SmartKeyFile config; + private FsoFramework.Logger logger; + + private bool autoopen = false; + private bool autoclose = false; + private bool autoexit = true; + private string session_type = "serial"; + private string session_path = "/dev/ttySAC0"; + private uint session_speed = 115200; + private bool session_mode = true; + private uint session_framesize = 64; + public uint channel_ack_timeout = 10; + private uint wakeup_threshold = 0; + private uint wakeup_waitms = 0; + + public static bool leave_mux_alone = false; + public static bool leave_fc_alone = false; + + private uint channelsOpen; + + public Manager() + { + config = FsoFramework.theConfig; // use standard config for this binary + logger = FsoFramework.Logger.createFromKeyFile( config, LIBGSM0710MUX_CONFIG_SECTION, LIBGSM0710MUX_LOGGING_DOMAIN ); + logger.setReprDelegate( repr ); + assert( logger.debug( "Constructed" ) ); + + try + { + autoopen = config.boolValue( LIBGSM0710MUX_CONFIG_SECTION, "muxer_autoopen", autoopen ); + autoclose = config.boolValue( LIBGSM0710MUX_CONFIG_SECTION, "muxer_autoclose", autoclose ); + autoexit = config.boolValue( LIBGSM0710MUX_CONFIG_SECTION, "muxer_autoexit", autoexit ); + + session_type = config.stringValue( LIBGSM0710MUX_CONFIG_SECTION, "device_type", session_type ); + session_path = config.stringValue( LIBGSM0710MUX_CONFIG_SECTION, "device_port", session_path ); + session_speed = config.intValue( LIBGSM0710MUX_CONFIG_SECTION, "device_speed", (int)session_speed ); + + session_mode = config.boolValue( LIBGSM0710MUX_CONFIG_SECTION, "device_mux_mode", session_mode ); + session_framesize = config.intValue( LIBGSM0710MUX_CONFIG_SECTION, "device_mux_framesize", (int)session_framesize ); + channel_ack_timeout = config.intValue( LIBGSM0710MUX_CONFIG_SECTION, "device_ack_timeout", (int)channel_ack_timeout ); + + wakeup_threshold = config.intValue( LIBGSM0710MUX_CONFIG_SECTION, "device_wakeup_threshold", (int)wakeup_threshold ); + wakeup_waitms = config.intValue( LIBGSM0710MUX_CONFIG_SECTION, "device_wakeup_waitms", (int)wakeup_waitms ); + + leave_mux_alone = config.boolValue( LIBGSM0710MUX_CONFIG_SECTION, "session_debug_leave_mux_alone", false ); + leave_fc_alone = config.boolValue( LIBGSM0710MUX_CONFIG_SECTION, "session_debug_leave_fc_alone", false ); + } + catch ( GLib.Error e ) + { + warning( "Manager: config error: %s", e.message ); + } + } + + public string repr() + { + return "<Manager>"; + } + + ~Manager() + { + assert( logger.debug( "Destructed" ) ); + } + + internal void _shutdown() + { + assert( logger.debug( "_shutdown" ) ); + if ( muxer != null ) + { + muxer.closeSession(); + muxer = null; + } + if ( ( Environment.get_prgname() == "fso-abyss" ) && autoexit ) + loop.quit(); + } + + internal void channelsHaveBeenClosed( int num ) + { + channelsOpen -= num; + if ( channelsOpen == 0 && autoclose ) + { + _shutdown(); + } + } + + // + // Public API + // + public string getVersion() + { + return Config.PACKAGE_VERSION; + } + + public bool hasAutoSession() + { + return autoopen; + } + + public void openSession( bool advanced, int framesize, string porttype, string portname, int portspeed ) throws MuxerError + { + logger.debug( "InitSession requested for mode %s, framesize %d, type %s, name %s @ %d".printf( advanced? "advanced":"basic", framesize, porttype, portname, portspeed ) ); + if ( muxer != null ) + { + throw new MuxerError.SESSION_ALREADY_OPEN( "Close session before opening another one." ); + } + else + { + muxer = new Multiplexer( advanced, framesize, porttype, portname, portspeed, this ); + if ( !muxer.initSession() ) + { + muxer = null; + throw new MuxerError.SESSION_OPEN_ERROR( "Can't initialize the session" ); + } + } + } + + public void closeSession() throws MuxerError + { + logger.debug( "CloseSession requested" ); + if ( muxer == null ) + { + throw new MuxerError.NO_SESSION( "Session has to be initialized first." ); + } + else + { + muxer.closeSession(); + //FIXME: This forcefully destroys the muxer and the transport and gives + //them no chance to wait for the modem's reply + muxer = null; + } + } + + public async int allocChannel( ChannelInfo channel ) throws MuxerError + { + assert( logger.debug( @"Consumer $(channel.consumer) requested channel $(channel.number) via $(channel.tspec.type)" ) ); + + if ( autoopen && muxer == null ) + { + logger.debug( "auto configuring..." ); + openSession( session_mode, (int)session_framesize, session_type, session_path, (int)session_speed ); + + if ( wakeup_threshold > 0 && wakeup_waitms > 0 ) + { + setWakeupThreshold( wakeup_threshold, wakeup_waitms ); + } + } + + if ( channel.number < 0 ) + { + throw new MuxerError.INVALID_CHANNEL( "Channel has to be >= 0" ); + } + + if ( muxer == null ) + { + throw new MuxerError.NO_SESSION( "Session has to be initialized first." ); + } + else + { + var number = yield muxer.allocChannel( channel ); + channelsOpen++; + return number; + } + } + + public void releaseChannel( string name ) throws MuxerError + { + logger.debug( "ReleaseChannel requested for name %s".printf( name ) ); + if ( muxer == null ) + { + throw new MuxerError.NO_SESSION( "Session has to be initialized first." ); + } + else + { + muxer.releaseChannel( name ); + } + } + + public void setWakeupThreshold( uint seconds, uint waitms ) throws MuxerError + { + logger.debug( "SetWakeupThreshold to wakeup before transmitting after %u sec. of idleness, wait period = %u msec.".printf( seconds, waitms ) ); + if ( muxer == null ) + { + throw new MuxerError.NO_SESSION( "Session has to be initialized first." ); + } + else + { + muxer.setWakeupThreshold( seconds, waitms ); + } + } + + public void setStatus( int channel, string status ) throws MuxerError + { + logger.debug( "SetStatus requested for channel %d, status = %s".printf( channel, status ) ); + if ( muxer == null ) + { + throw new MuxerError.NO_SESSION( "Session has to be initialized first." ); + } + else + { + muxer.setStatus( channel, status ); + } + } + + //public signal void Status( int channel, string status ); + + public void testCommand( uint8[] data ) throws MuxerError + { + logger.debug( "Sending %d test command bytes".printf( data.length ) ); + muxer.testCommand( data ); + } + +} + +} /* namespace Gsm0710mux */ diff --git a/libgsm0710mux/gsm0710mux/multiplexer.vala b/libgsm0710mux/gsm0710mux/multiplexer.vala new file mode 100644 index 00000000..557b69ec --- /dev/null +++ b/libgsm0710mux/gsm0710mux/multiplexer.vala @@ -0,0 +1,560 @@ +/* + * This file is part of libgsm0710mux + * + * (C) 2009-2010 Michael 'Mickey' Lauer <mlauer@vanille-media.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +//=========================================================================== +using GLib; +using CONST; +using Gsm0710; +using Gsm0710mux; + +//=========================================================================== +// callback forwarders +// + +internal static bool at_command_fwd( Context ctx, string command ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + return m.at_command( command ); +} + +internal static int read_fwd( Context ctx, void* data, int len ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + return m.read( data, len ); +} + +internal static bool write_fwd( Context ctx, void* data, int len ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + return m.write( data, len ); +} + +internal static void deliver_data_fwd( Context ctx, int channel, void* data, int len ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + m.deliver_data( channel, data, len ); +} + +internal static void deliver_status_fwd( Context ctx, int channel, int status ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + m.deliver_status( channel, status ); +} + +internal static void debug_message_fwd( Context ctx, string msg ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + m.debug_message( msg ); +} + +internal static void open_channel_fwd( Context ctx, int channel ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + m.open_channel( channel ); +} + +internal static void close_channel_fwd( Context ctx, int channel ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + m.close_channel( channel ); +} + +internal static void terminate_fwd( Context ctx ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + m.terminate(); +} + +internal static void response_to_test_fwd( Context ctx, char[] data ) +{ + Multiplexer m = (Multiplexer) ctx.user_data; + m.response_to_test( data ); +} + +//=========================================================================== +// The Multiplexer class +// +internal class Multiplexer +{ + Manager manager; + + string portname; + string porttype; + int portspeed; + + FsoFramework.Logger logger; + + Context ctx; + + uint pingwatch; + + Timer idle_wakeup_timer; + uint idle_wakeup_threshold; + uint idle_wakeup_waitms; + + Channel[] vc = new Channel[MAX_CHANNELS]; + + FsoFramework.Transport transport; + + public Multiplexer( bool advanced, int framesize, string porttype, string portname, int portspeed, Manager manager ) + { + assert( porttype != null ); + assert( portname != null ); + this.porttype = porttype; + this.portname = portname; + this.portspeed = portspeed; + this.manager = manager; + + ctx = new Context(); + + ctx.mode = advanced? 1 : 0; + ctx.frame_size = framesize; + ctx.port_speed = portspeed; + + ctx.user_data = this; + + ctx.at_command = at_command_fwd; + ctx.read = read_fwd; + ctx.write = write_fwd; + ctx.deliver_data = deliver_data_fwd; + ctx.deliver_status = deliver_status_fwd; + ctx.debug_message = debug_message_fwd; + ctx.open_channel = open_channel_fwd; + ctx.close_channel = close_channel_fwd; + ctx.terminate = terminate_fwd; + ctx.response_to_test = response_to_test_fwd; + + logger = FsoFramework.Logger.createFromKeyFile( FsoFramework.theConfig, LIBGSM0710MUX_CONFIG_SECTION, LIBGSM0710MUX_LOGGING_DOMAIN ); + logger.setReprDelegate( repr ); + assert( logger.debug( "Created" ) ); + } + + ~Multiplexer() + { + if ( transport != null ) + { + transport.close(); + } + assert( logger.debug( "Destructed" ) ); + } + + public string repr() + { + return "<%c%d %s@%d>".printf( ( ctx.mode == 1 ? 'A':'B' ), ctx.frame_size, portname, ctx.port_speed ); + } + + public bool initSession() + { + assert( logger.debug( "InitSession()" ) ); + + if ( !openTransport() ) + { + logger.error( "Can't open the transport" ); + return false; + } + + if ( manager.leave_mux_alone ) + { + logger.warning( "Assuming device is already in MUX mode..." ); + transport.flush(); + var ok = ctx.startup( false ); + transport.drain(); + return ok; + } + + transport.flush(); + ctx.shutdown(); + ctx.shutdown(); + transport.drain(); + transport.flush(); + + bool ok; + + if ( ctx.mode == 0 ) + { + if (!at_command( "AT+CMUX=0\r\n" ) ) + return false; + ok = ctx.startup( false ); + } + else + { + ok = ctx.startup( true ); + } + + /* + if (ok) + Timeout.add_seconds( GSM_PING_SEND_TIMEOUT, protocol_ping_send_timeout ); + */ + + return ok; + } + + public void closeSession() + { + logger.debug( "closeSession()" ); + for ( int i = 1; i < MAX_CHANNELS; ++i ) + { + if ( vc != null && vc[i] != null ) + { + vc[i].close(); + } + } + + if ( ctx != null && !Manager.leave_mux_alone ) + { + ctx.shutdown(); + } + } + + public async int allocChannel( ChannelInfo info ) throws MuxerError + { + assert( logger.debug( @"allocChannel() requested for channel $(info.number)" ) ); + + if ( info.number == 0 ) + { + // find the first free one + for ( int i = 1; i < MAX_CHANNELS; ++i ) + { + if ( vc[i] == null ) + { + info.number = i; + break; + } + } + } + else + { + // lets check whether we already have this channel + if ( vc[info.number] != null ) + { + throw new MuxerError.CHANNEL_TAKEN( @"Channel $(info.number) is already taken." ); + } + } + + wakeupIfNecessary(); + + var ok = ctx.openChannel( info.number ); + assert( logger.debug( @"0710 open channel returned $ok" ) ); + if ( !ok ) + { + throw new MuxerError.NO_CHANNEL( @"Modem does not provide channel $(info.number)." ); + } + vc[info.number] = new Channel( this, info, allocChannel.callback, manager.channel_ack_timeout ); + + yield; + + if ( vc[info.number].isAcked() ) + { + var path = vc[info.number].path(); + assert( logger.debug( @"0710 channel $(info.number) opened and connected to $path" ) ); + return info.number; + } + + assert( logger.debug( @"0710 timeout while waiting for channel $(info.number) status signal" ) ); + vc[info.number] = null; + throw new MuxerError.NO_CHANNEL( "Modem does not provide this channel." ); + } + + public void releaseChannel( string name ) throws MuxerError + { + assert( logger.debug( @"releaseChannel() requested for $name" ) ); + if ( vc == null ) + { + logger.warning( "Channel array has already been destroyed" ); + return; + } + var closed = 0; + for ( int i = 1; i < MAX_CHANNELS; ++i ) + { + if ( vc[i] != null && vc[i].name() == name ) + { + vc[i].close(); + closed++; + } + } + if ( closed > 0 ) + { + manager.channelsHaveBeenClosed( closed ); + } + else + { + throw new MuxerError.NO_CHANNEL( "Could not find any channel with that name." ); + } + } + + public void setStatus( int channel, string status ) throws MuxerError + { + assert( logger.debug( @"setStatus() requested for channel $channel" ) ); + if ( vc[channel] == null ) + throw new MuxerError.NO_CHANNEL( "Could not find channel with that index." ); + + var v24 = stringToSerialStatus( status ); + wakeupIfNecessary(); + ctx.setStatus( channel, v24 ); + } + + public void setWakeupThreshold( uint seconds, uint waitms ) throws MuxerError + { + if ( seconds == 0 ) /* disable */ + { + idle_wakeup_timer = null; + } + else /* enable */ + { + if ( idle_wakeup_timer == null ) + { + idle_wakeup_timer = new Timer(); + idle_wakeup_timer.start(); + } + } + idle_wakeup_threshold = seconds; + idle_wakeup_waitms = waitms; + } + + public void testCommand( uint8[] data ) + { + debug( "muxer: testCommand" ); + wakeupIfNecessary(); + ctx.sendTest( data, data.length ); + } + + // + // internal helpers + // + internal bool openTransport() + { + assert( transport == null ); + transport = FsoFramework.Transport.create( porttype, portname, portspeed ); + if ( transport == null ) + { + return false; + } + transport.setDelegates( onReadFromTransport, onHupFromTransport ); + transport.setBuffered( false ); + transport.open(); + return transport.isOpen(); + } + + public int channelByName( string name ) + { + for ( int i = 1; i < MAX_CHANNELS; ++i ) + { + if ( vc[i] != null && vc[i].name() == name ) + return i; + } + return 0; + } + + public string serialStatusToString( int status ) // module -> application + { + var sb = new StringBuilder(); + if ( ( status & SerialStatus.FC ) == SerialStatus.FC ) + sb.append( "FC "); + if ( ( status & SerialStatus.RTC ) == SerialStatus.RTC ) + sb.append( "DSR "); + if ( ( status & SerialStatus.RTR ) == SerialStatus.RTR ) + sb.append( "CTS "); + if ( ( status & SerialStatus.RING ) == SerialStatus.RING ) + sb.append( "RING "); + if ( ( status & SerialStatus.DCD ) == SerialStatus.DCD ) + sb.append( "DCD "); + return sb.str; + } + + public int stringToSerialStatus( string status ) // application -> module + { + int v24 = 0; + var bits = status.split( " " ); + foreach( var bit in bits ) + { + if ( bit == "DTR" ) + v24 |= SerialStatus.RTC; + else if ( bit == "RTS" ) + v24 |= SerialStatus.RTR; + } + return v24; + } + + public void clearPingResponseTimeout() + { + if ( pingwatch != 0 ) + Source.remove( pingwatch ); + } + + public void wakeupIfNecessary() + { + if ( idle_wakeup_timer != null ) + { + var elapsed = idle_wakeup_timer.elapsed(); + if ( elapsed > idle_wakeup_threshold ) + { + assert( logger.debug( "Channel has been idle for %.2f seconds, waking up".printf( elapsed ) ) ); + var wakeup = new char[] { 'W', 'A', 'K', 'E', 'U', 'P', '!' }; + ctx.sendTest( wakeup, wakeup.length ); + Thread.usleep( 1000 * idle_wakeup_waitms ); + } + } + } + + // callbacks from modem transport + public void onReadFromTransport( FsoFramework.Transport transport ) + { + ctx.readyRead(); + } + + public void onHupFromTransport( FsoFramework.Transport transport ) + { + critical( "FOO" ); + } + + // + // callbacks from channel + // + public void submit_data( int channel, void* data, int len ) + { + wakeupIfNecessary(); + ctx.writeDataForChannel( channel, data, len ); + } + + public void channel_closed( int channel ) + { + wakeupIfNecessary(); + ctx.closeChannel( channel ); + vc[channel] = null; + } + + // + // callbacks from 0710 core + // + public int read( void* data, int len ) + { + assert( logger.debug( "0710 -> should read max %d bytes to %p".printf( len, data ) ) ); + var numread = transport.read( data, len ); + hexdump( false, data, numread, logger ); + return numread; + } + + public bool write( void* data, int len ) + { + assert( logger.debug( "0710 -> should write %d bytes".printf( len ) ) ); + if ( idle_wakeup_timer != null ) + { + idle_wakeup_timer.reset(); + } + hexdump( true, data, len, logger ); + var numsent = transport.write( data, len ); + return ( numsent > 0 ); + } + + public bool at_command( string command ) + { + logger.debug( "0710 -> should send at_command '%s'".printf( command ) ); + + var response = new char[1024]; + var numread = transport.writeAndRead( command, (int)command.length, response, response.length ); + assert( logger.debug( "Got %u bytes back w/ content = %s".printf( (uint)numread, ((string)response).escape( "" ) ) ) ); + return "OK" in (string)response; + } + + public void deliver_data( int channel, void* data, int len ) + { + logger.debug( "0710 -> deliver %d bytes for channel %d".printf( len, channel ) ); + if ( vc[channel] == null ) + { + logger.debug( "Should deliver bytes for unknown channel: ignoring" ); + } + else + { + vc[channel].deliverData( data, len ); + } + clearPingResponseTimeout(); + } + + public void deliver_status( int channel, int serial_status ) + { + string status = serialStatusToString( serial_status ); + logger.debug( "0710 -> deliver status %d = '%s' for channel %d".printf( serial_status, status, channel ) ); + if ( vc[channel] == null ) + { + logger.debug( ":::should deliver status for unknown channel: ignoring" ); + } + else + { + if ( !vc[channel].isAcked() ) + { + vc[channel].acked(); + } + vc[channel].setSerialStatus( serial_status ); + } + clearPingResponseTimeout(); + } + + public void debug_message( string msg ) + { + logger.debug( "0710 -> say '%s".printf( msg ) ); + } + + public void open_channel( int channel ) + { + logger.debug( "0710 -> open channel %d".printf( channel ) ); + logger.error( "Unhandled modem side open channel command" ); + } + + public void close_channel( int channel ) + { + logger.debug( "0710 -> close channel %d".printf( channel ) ); + var message = new char[] { '\r', '\n', '!', 'S', 'H', 'U', 'T', 'D', 'O', 'W', 'N', '\r', '\n' }; + deliver_data( channel, message, message.length ); + vc[channel] = null; + } + + public void terminate() + { + logger.debug( "0710 -> terminate" ); + // FIXME send close session signal, remove muxer object + } + + public void response_to_test( char[] data ) + { + var b = new StringBuilder(); + foreach( var c in data ) + b.append_printf( "%c", c ); + logger.debug( "0710 -> response to test (%d bytes): %s".printf( data.length, b.str ) ); + clearPingResponseTimeout(); + } + + public bool protocol_ping_response_timeout() + { + logger.warning( "\n*\n*\n* PING TIMEOUT !!!\n*\n*\n*" ); + return true; + } + + public bool protocol_ping_send_timeout() + { + var data = new char[] { 'P', 'I', 'N', 'G' }; + ctx.sendTest( data, data.length ); + + if ( pingwatch != 0 ) + Source.remove( pingwatch ); + pingwatch = Timeout.add_seconds( GSM_PING_RESPONSE_TIMEOUT, protocol_ping_response_timeout ); + return true; + } +} |