r1426 - in developers/seanchiang: . gsm gsm/doc gsm/include gsm/include/common gsm/include/gsmd gsm/include/libgsmd gsm/logs gsm/src gsm/src/gsmd gsm/src/libgsmd gsm/src/util
sean_chiang at sita.openmoko.org
sean_chiang at sita.openmoko.org
Tue Mar 20 08:30:35 CET 2007
Author: sean_chiang
Date: 2007-03-20 08:29:51 +0100 (Tue, 20 Mar 2007)
New Revision: 1426
Added:
developers/seanchiang/gsm/
developers/seanchiang/gsm/COPYING
developers/seanchiang/gsm/COPYING.library
developers/seanchiang/gsm/Makefile.am
developers/seanchiang/gsm/README.txt
developers/seanchiang/gsm/autogen.sh
developers/seanchiang/gsm/configure.ac
developers/seanchiang/gsm/doc/
developers/seanchiang/gsm/doc/functions.txt
developers/seanchiang/gsm/include/
developers/seanchiang/gsm/include/Makefile.am
developers/seanchiang/gsm/include/common/
developers/seanchiang/gsm/include/common/Makefile.am
developers/seanchiang/gsm/include/common/linux_list.h
developers/seanchiang/gsm/include/gsmd/
developers/seanchiang/gsm/include/gsmd/Makefile.am
developers/seanchiang/gsm/include/gsmd/atcmd.h
developers/seanchiang/gsm/include/gsmd/event.h
developers/seanchiang/gsm/include/gsmd/extrsp.h
developers/seanchiang/gsm/include/gsmd/gsmd.h
developers/seanchiang/gsm/include/gsmd/select.h
developers/seanchiang/gsm/include/gsmd/state.h
developers/seanchiang/gsm/include/gsmd/talloc.h
developers/seanchiang/gsm/include/gsmd/ts0707.h
developers/seanchiang/gsm/include/gsmd/unsolicited.h
developers/seanchiang/gsm/include/gsmd/usock.h
developers/seanchiang/gsm/include/gsmd/vendorplugin.h
developers/seanchiang/gsm/include/libgsmd/
developers/seanchiang/gsm/include/libgsmd/Makefile.am
developers/seanchiang/gsm/include/libgsmd/event.h
developers/seanchiang/gsm/include/libgsmd/handset.h
developers/seanchiang/gsm/include/libgsmd/libgsmd.h
developers/seanchiang/gsm/include/libgsmd/misc.h
developers/seanchiang/gsm/include/libgsmd/phonebook.h
developers/seanchiang/gsm/include/libgsmd/pin.h
developers/seanchiang/gsm/include/libgsmd/voicecall.h
developers/seanchiang/gsm/libgsmd.pc.in
developers/seanchiang/gsm/logs/
developers/seanchiang/gsm/logs/screenlog.0
developers/seanchiang/gsm/src/
developers/seanchiang/gsm/src/Makefile.am
developers/seanchiang/gsm/src/gsmd/
developers/seanchiang/gsm/src/gsmd/Makefile.am
developers/seanchiang/gsm/src/gsmd/atcmd.c
developers/seanchiang/gsm/src/gsmd/ext_response.c
developers/seanchiang/gsm/src/gsmd/gsmd.c
developers/seanchiang/gsm/src/gsmd/gsmd.h
developers/seanchiang/gsm/src/gsmd/gsmd_event.h
developers/seanchiang/gsm/src/gsmd/log.c
developers/seanchiang/gsm/src/gsmd/operator_cache.c
developers/seanchiang/gsm/src/gsmd/select.c
developers/seanchiang/gsm/src/gsmd/sms_cb.c
developers/seanchiang/gsm/src/gsmd/talloc.c
developers/seanchiang/gsm/src/gsmd/unsolicited.c
developers/seanchiang/gsm/src/gsmd/usock.c
developers/seanchiang/gsm/src/gsmd/vendor.c
developers/seanchiang/gsm/src/gsmd/vendor_ti.c
developers/seanchiang/gsm/src/gsmd/vendorplugin.h
developers/seanchiang/gsm/src/libgsmd/
developers/seanchiang/gsm/src/libgsmd/Makefile.am
developers/seanchiang/gsm/src/libgsmd/lgsm_internals.h
developers/seanchiang/gsm/src/libgsmd/libgsmd.c
developers/seanchiang/gsm/src/libgsmd/libgsmd_event.c
developers/seanchiang/gsm/src/libgsmd/libgsmd_input.c
developers/seanchiang/gsm/src/libgsmd/libgsmd_network.c
developers/seanchiang/gsm/src/libgsmd/libgsmd_passthrough.c
developers/seanchiang/gsm/src/libgsmd/libgsmd_phone.c
developers/seanchiang/gsm/src/libgsmd/libgsmd_pin.c
developers/seanchiang/gsm/src/libgsmd/libgsmd_voicecall.c
developers/seanchiang/gsm/src/util/
developers/seanchiang/gsm/src/util/Makefile.am
developers/seanchiang/gsm/src/util/atcmd.c
developers/seanchiang/gsm/src/util/atcmd.h
developers/seanchiang/gsm/src/util/event.c
developers/seanchiang/gsm/src/util/event.h
developers/seanchiang/gsm/src/util/libgsmd-tool.c
developers/seanchiang/gsm/src/util/pin.c
developers/seanchiang/gsm/src/util/pin.h
developers/seanchiang/gsm/src/util/shell.c
developers/seanchiang/gsm/src/util/shell.h
Log:
support phonebook, sms(not fully support yet)
Added: developers/seanchiang/gsm/COPYING
===================================================================
--- developers/seanchiang/gsm/COPYING 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/COPYING 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,339 @@
+ 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 Lesser 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 Lesser General
+Public License instead of this License.
Added: developers/seanchiang/gsm/COPYING.library
===================================================================
--- developers/seanchiang/gsm/COPYING.library 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/COPYING.library 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, 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 St, 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!
+
+
Added: developers/seanchiang/gsm/Makefile.am
===================================================================
--- developers/seanchiang/gsm/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,15 @@
+AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
+
+SUBDIRS = include src
+#LINKOPTS = -lusb
+
+AM_CFLAGS = -std=gnu99
+
+$(OBJECTS): libtool
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
+
+pcdata_DATA= libgsmd.pc
+pcdatadir= $(libdir)/pkgconfig
+
+EXTRA_DIST= $(pcdata_DATA)
Added: developers/seanchiang/gsm/README.txt
===================================================================
--- developers/seanchiang/gsm/README.txt 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/README.txt 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,76 @@
+
+
+1. GSMD api towards libgsmd
+ - provides api for other processes to interact with GSM subsystem
+ - is not documented and subject to change
+
+2. GSMD api towards vendor-specific plugins
+ - implement vendor-specific AT commands
+ - is not documented and will initially only support TI
+ - later, a Motorola plugin is planned.
+
+3. libgsmd api towards applications
+ - wraps GSMD-libgsmd api into C functions that can be used by applications
+ - will be documented and is supposed to be stable.
+
+3.1. Events
+
+The application registers callback handlers for events. libgsmd can call these callback
+handlers at any given time. Events include "incoming call", "remote end hangup", ...
+
+3.2. Commands
+
+Commands have the form of command-reply. Usually they will be performed
+synchronously, i.e. the the caller will be blocked until a response to the command has been
+received.
+
+If this behaviour is not desired, a completion handler callback function can be
+registered. In this case, the function call will return immediately after the
+command has been sent to gsmd. Further incoming packets on the gsmd socket
+will be handled to libgsmd by calling lgsm_handle_packet(). If one such packet is the
+response to a currently-executing command, the completion handler will be
+called from within lgsm_handle_packet(). Matching of responses to requests is done by
+assigning a unique id to each request. gsmd responses will have a matching id.
+
+
+code flow in gsmd:
+
+- select loop detects data has arrived on user socket
+ - gsmd_usock_user_cb()
+ - if this is atcmd passthrough,
+ - alloc + fill in gsmd_atcmd
+ - atcmd_submit()
+ - append it to pending_atcmds
+ - mark interest of writing to UART
+ - if this is not passthrough
+ - do whatever handling, including enqueueing of atcmds
+- select loop detects UART is marked writable
+ - atcmd_select_cb()
+ - iterate over list of pending_atcmds()
+ - write a particular atcmd to UART
+ - move atcmd to busy_atcmds
+- select loop detects UART is marked readable
+ - atcmd_select_cb()
+ - read up to 1024 bytes into buffer
+ - llparse_string()
+ - llparse_byte()
+ - llparse_append()
+ - llp->cb == ml_parse()
+ - if this is not unsolicited
+ - call cmd->cb()
+ - alloc + fill ucmd reply
+ - add to finished_ucmds
+ - mark user sock writable
+ - unlink + free atcmd
+ - if this is unsolicited
+ - unsolicited_parse()
+ - usock_evt_send()
+ - alloc + fill ucmd reply
+ - add to finished_ucmds
+ - mark user sock writable
+- select loop detects user sock writeability
+ - gsmd_usock_user_cb()
+ - iterate over finished_ucmds
+ - write ucmd
+ - unlink + free ucmd
+
Added: developers/seanchiang/gsm/autogen.sh
===================================================================
--- developers/seanchiang/gsm/autogen.sh 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/autogen.sh 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,5 @@
+#! /bin/sh
+autoreconf -v --install || exit 1
+glib-gettextize --force --copy || exit 1
+./configure --enable-maintainer-mode "$@"
+
Added: developers/seanchiang/gsm/configure.ac
===================================================================
--- developers/seanchiang/gsm/configure.ac 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/configure.ac 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,28 @@
+AC_PREREQ(2.53)
+AC_INIT(gsmd, 0.0.1, http://www.openmoko.org/)
+AM_INIT_AUTOMAKE()
+AC_CONFIG_SRCDIR(src/gsmd/gsmd.c)
+AM_CONFIG_HEADER(config.h)
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AC_STDC_HEADERS
+AC_PROG_LIBTOOL
+
+# base deps
+
+# output stuff
+AC_OUTPUT([
+Makefile
+libgsmd.pc
+src/Makefile
+src/gsmd/Makefile
+src/libgsmd/Makefile
+src/util/Makefile
+include/Makefile
+include/gsmd/Makefile
+include/libgsmd/Makefile
+include/common/Makefile
+])
+
Added: developers/seanchiang/gsm/doc/functions.txt
===================================================================
--- developers/seanchiang/gsm/doc/functions.txt 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/doc/functions.txt 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,51 @@
+0. general
+
+commands
+- power up/down phone
+- operator selection
+- get list of operators
+- get operator name / id list
+- get (and edit) preferred operator list
+- get manufacturer/device/serial info
+- get IMSI
+- obtain network registration status
+
+
+events
+- some pin required
+- network registration status
+- time zone update
+
+
+1. voice calls
+
+commands (request/response)
+- dial outgoing call
+- send dtmf digit (during call)
+- hang up (incoming/outgoing)
+- accept currently pending incoming call
+- enable/disable clip
+- enable/disable colp
+- enable/disable clir
+- call forwarding
+- call deflection
+
+events
+- incoming call
+- clip
+- colp
+- call waiting
+-
+
+2. SMS
+
+commands
+- send outgoing message
+
+3. data calls
+
+TBD
+
+4. GPRS
+
+TBD
Added: developers/seanchiang/gsm/include/Makefile.am
===================================================================
--- developers/seanchiang/gsm/include/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1 @@
+SUBDIRS = libgsmd gsmd common
Added: developers/seanchiang/gsm/include/common/Makefile.am
===================================================================
--- developers/seanchiang/gsm/include/common/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/common/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,3 @@
+
+noinst_HEADERS = linux_list.h
+
Added: developers/seanchiang/gsm/include/common/linux_list.h
===================================================================
--- developers/seanchiang/gsm/include/common/linux_list.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/common/linux_list.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,364 @@
+#ifndef _LINUX_LLIST_H
+#define _LINUX_LLIST_H
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#include <stddef.h>
+
+#ifndef inline
+#define inline __inline__
+#endif
+
+static inline void prefetch(const void *x) {;}
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized llist entries.
+ */
+#define LLIST_POISON1 ((void *) 0x00100100)
+#define LLIST_POISON2 ((void *) 0x00200200)
+
+/*
+ * Simple doubly linked llist implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole llists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct llist_head {
+ struct llist_head *next, *prev;
+};
+
+#define LLIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LLIST_HEAD(name) \
+ struct llist_head name = LLIST_HEAD_INIT(name)
+
+#define INIT_LLIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal llist manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __llist_add(struct llist_head *new,
+ struct llist_head *prev,
+ struct llist_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * llist_add - add a new entry
+ * @new: new entry to be added
+ * @head: llist head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void llist_add(struct llist_head *new, struct llist_head *head)
+{
+ __llist_add(new, head, head->next);
+}
+
+/**
+ * llist_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: llist head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void llist_add_tail(struct llist_head *new, struct llist_head *head)
+{
+ __llist_add(new, head->prev, head);
+}
+
+/*
+ * Delete a llist entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal llist manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __llist_del(struct llist_head * prev, struct llist_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * llist_del - deletes entry from llist.
+ * @entry: the element to delete from the llist.
+ * Note: llist_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void llist_del(struct llist_head *entry)
+{
+ __llist_del(entry->prev, entry->next);
+ entry->next = LLIST_POISON1;
+ entry->prev = LLIST_POISON2;
+}
+
+/**
+ * llist_del_init - deletes entry from llist and reinitialize it.
+ * @entry: the element to delete from the llist.
+ */
+static inline void llist_del_init(struct llist_head *entry)
+{
+ __llist_del(entry->prev, entry->next);
+ INIT_LLIST_HEAD(entry);
+}
+
+/**
+ * llist_move - delete from one llist and add as another's head
+ * @llist: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void llist_move(struct llist_head *llist, struct llist_head *head)
+{
+ __llist_del(llist->prev, llist->next);
+ llist_add(llist, head);
+}
+
+/**
+ * llist_move_tail - delete from one llist and add as another's tail
+ * @llist: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void llist_move_tail(struct llist_head *llist,
+ struct llist_head *head)
+{
+ __llist_del(llist->prev, llist->next);
+ llist_add_tail(llist, head);
+}
+
+/**
+ * llist_empty - tests whether a llist is empty
+ * @head: the llist to test.
+ */
+static inline int llist_empty(const struct llist_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __llist_splice(struct llist_head *llist,
+ struct llist_head *head)
+{
+ struct llist_head *first = llist->next;
+ struct llist_head *last = llist->prev;
+ struct llist_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * llist_splice - join two llists
+ * @llist: the new llist to add.
+ * @head: the place to add it in the first llist.
+ */
+static inline void llist_splice(struct llist_head *llist, struct llist_head *head)
+{
+ if (!llist_empty(llist))
+ __llist_splice(llist, head);
+}
+
+/**
+ * llist_splice_init - join two llists and reinitialise the emptied llist.
+ * @llist: the new llist to add.
+ * @head: the place to add it in the first llist.
+ *
+ * The llist at @llist is reinitialised
+ */
+static inline void llist_splice_init(struct llist_head *llist,
+ struct llist_head *head)
+{
+ if (!llist_empty(llist)) {
+ __llist_splice(llist, head);
+ INIT_LLIST_HEAD(llist);
+ }
+}
+
+/**
+ * llist_entry - get the struct for this entry
+ * @ptr: the &struct llist_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * llist_for_each - iterate over a llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, prefetch(pos->next))
+
+/**
+ * __llist_for_each - iterate over a llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ *
+ * This variant differs from llist_for_each() in that it's the
+ * simplest possible llist iteration code, no prefetching is done.
+ * Use this for code that knows the llist to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __llist_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * llist_for_each_prev - iterate over a llist backwards
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_prev(pos, head) \
+ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+ pos = pos->prev, prefetch(pos->prev))
+
+/**
+ * llist_for_each_safe - iterate over a llist safe against removal of llist entry
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @n: another &struct llist_head to use as temporary storage
+ * @head: the head for your llist.
+ */
+#define llist_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * llist_for_each_entry - iterate over llist of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry(pos, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * llist_for_each_entry_reverse - iterate backwards over llist of given type.
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_reverse(pos, head, member) \
+ for (pos = llist_entry((head)->prev, typeof(*pos), member), \
+ prefetch(pos->member.prev); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.prev, typeof(*pos), member), \
+ prefetch(pos->member.prev))
+
+/**
+ * llist_for_each_entry_continue - iterate over llist of given type
+ * continuing after existing point
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_continue(pos, head, member) \
+ for (pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ n = llist_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = llist_entry(n->member.next, typeof(*n), member))
+
+/**
+ * llist_for_each_rcu - iterate over an rcu-protected llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_rcu(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
+
+#define __llist_for_each_rcu(pos, head) \
+ for (pos = (head)->next; pos != (head); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
+
+/**
+ * llist_for_each_safe_rcu - iterate over an rcu-protected llist safe
+ * against removal of llist entry
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @n: another &struct llist_head to use as temporary storage
+ * @head: the head for your llist.
+ */
+#define llist_for_each_safe_rcu(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
+
+/**
+ * llist_for_each_entry_rcu - iterate over rcu llist of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_rcu(pos, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ ({ smp_read_barrier_depends(); 0;}), \
+ prefetch(pos->member.next))
+
+
+/**
+ * llist_for_each_continue_rcu - iterate over an rcu-protected llist
+ * continuing after existing point.
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_continue_rcu(pos, head) \
+ for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
+ (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
+
+
+#endif
Added: developers/seanchiang/gsm/include/gsmd/Makefile.am
===================================================================
--- developers/seanchiang/gsm/include/gsmd/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,4 @@
+
+pkginclude_HEADERS = event.h usock.h
+
+noinst_HEADERS = atcmd.h gsmd.h select.h ts0707.h unsolicited.h usock.h vendorplugin.h
Added: developers/seanchiang/gsm/include/gsmd/atcmd.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/atcmd.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/atcmd.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,17 @@
+#ifndef __GSMD_ATCMD_H
+#define __GSMD_ATCMD_H
+
+#ifdef __GSMD__
+
+#include <gsmd/gsmd.h>
+
+typedef int atcmd_cb_t(struct gsmd_atcmd *cmd, void *ctx, char *resp);
+
+extern struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen, atcmd_cb_t *cb, void *ctx, u_int16_t id);
+extern int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd);
+extern int atcmd_init(struct gsmd *g, int sockfd);
+extern void atcmd_drain(int fd);
+
+#endif /* __GSMD__ */
+
+#endif
Added: developers/seanchiang/gsm/include/gsmd/event.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/event.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/event.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,80 @@
+#ifndef _GSMD_EVENT_H
+#define _GSMD_EVENT_H
+
+enum gsmd_events {
+ GSMD_EVT_NONE = 0,
+ GSMD_EVT_IN_CALL = 1, /* Incoming call */
+ GSMD_EVT_IN_SMS = 2, /* Incoming SMS */
+ GSMD_EVT_IN_GPRS = 3, /* Network initiated GPRS */
+ GSMD_EVT_IN_CLIP = 4, /* Incoming CLIP */
+ GSMD_EVT_NETREG = 5, /* Network (un)registration event */
+ GSMD_EVT_SIGNAL = 6, /* Signal quality event */
+ GSMD_EVT_PIN = 7, /* Modem is waiting for some PIN/PUK */
+ GSMD_EVT_OUT_STATUS = 8, /* Outgoing call status */
+ GSMD_EVT_OUT_COLP = 9, /* Outgoing COLP */
+ GSMD_EVT_CALL_WAIT = 10, /* Call Waiting */
+ GSMD_EVT_TIMEZONE = 11, /* Timezone change */
+ GSMD_EVT_SUBSCRIPTIONS = 12, /* To which events are we subscribed to */
+ GSMD_EVT_CIPHER = 13, /* Chiphering Information */
+ __NUM_GSMD_EVT
+};
+
+/* Chapter 8.3 */
+enum gsmd_pin_type { /* waiting for ... */
+ GSMD_PIN_NONE = 0, /* not for any PIN */
+ GSMD_PIN_SIM_PIN = 1, /* SIM PIN */
+ GSMD_PIN_SIM_PUK = 2, /* SIM PUK */
+ GSMD_PIN_PH_SIM_PIN = 3, /* phone-to-SIM passowrd */
+ GSMD_PIN_PH_FSIM_PIN = 4, /* phone-to-very-first SIM password */
+ GSMD_PIN_PH_FSIM_PUK = 5, /* phone-to-very-first SIM PUK password */
+ GSMD_PIN_SIM_PIN2 = 6, /* SIM PIN2 */
+ GSMD_PIN_SIM_PUK2 = 7, /* SIM PUK2 */
+ GSMD_PIN_PH_NET_PIN = 8, /* netwokr personalisation password */
+ GSMD_PIN_PH_NET_PUK = 9, /* network personalisation PUK */
+ GSMD_PIN_PH_NETSUB_PIN = 10, /* network subset personalisation PIN */
+ GSMD_PIN_PH_NETSUB_PUK = 11, /* network subset personalisation PUK */
+ GSMD_PIN_PH_SP_PIN = 12, /* service provider personalisation PIN */
+ GSMD_PIN_PH_SP_PUK = 13, /* service provider personalisation PUK */
+ GSMD_PIN_PH_CORP_PIN = 14, /* corporate personalisation PIN */
+ GSMD_PIN_PH_CORP_PUK = 15, /* corporate personalisation PUK */
+ __NUM_GSMD_PIN
+};
+
+enum gsmd_call_type {
+ GSMD_CALL_NONE = 0,
+ GSMD_CALL_UNSPEC = 1,
+ GSMD_CALL_VOICE = 2,
+ GSMD_CALL_FAX = 4,
+ GSMD_CALL_DATA_SYNC = 5,
+ GSMD_CALL_DATA_REL_ASYNC= 6,
+ GSMD_CALL_DATA_REL_SYNC = 7,
+ __NUM_GSMD_CALL
+};
+
+enum gsmd_netreg_state {
+ GSMD_NETREG_NONE = 0,
+ __NUM_GSMD_NETREG
+};
+
+enum gsmd_call_progress {
+ GSMD_CALLPROG_SETUP = 0,
+ GSMD_CALLPROG_DISCONNECT = 1,
+ GSMD_CALLPROG_ALERT = 2,
+ GSMD_CALLPROG_CALL_PROCEED = 3,
+ GSMD_CALLPROG_SYNC = 4,
+ GSMD_CALLPROG_PROGRESS = 5,
+ GSMD_CALLPROG_CONNECTED = 6,
+ GSMD_CALLPROG_RELEASE = 7,
+ GSMD_CALLPROG_REJECT = 8,
+ GSMD_CALLPROG_UNKNOWN = 9,
+ __NUM_GSMD_CALLPROG
+};
+
+enum gsmd_call_direction {
+ GSMD_CALL_DIR_MO = 0, /* Mobile Originated (Outgoing) */
+ GSMD_CALL_DIR_MT = 1, /* Mobile Terminated (Incoming) */
+ GSMD_CALL_DIR_CCBS = 2, /* network initiated MO */
+ GSMD_CALL_DIR_MO_REDIAL = 3, /* Mobile Originated Redial */
+};
+
+#endif
Added: developers/seanchiang/gsm/include/gsmd/extrsp.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/extrsp.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/extrsp.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,45 @@
+#ifndef _GSMD_EXTRSP_H
+#define _GSMD_EXTRSP_H
+
+/* how many tokens (CSV items) can an extended response have, max */
+#define GSM_EXTRSP_MAX_TOKENS 16
+
+/* how many individual sub-ranges can one range contain */
+#define GSM_EXTRSP_MAX_RANGES 16
+
+
+struct gsm_extrsp_range_item {
+ int min;
+ int max;
+};
+
+enum gsm_extrsp_tok_type {
+ GSMD_ECMD_RTT_NONE,
+ GSMD_ECMD_RTT_EMPTY,
+ GSMD_ECMD_RTT_NUMERIC,
+ GSMD_ECMD_RTT_STRING,
+ GSMD_ECMD_RTT_RANGE,
+};
+
+struct gsm_extrsp_tok {
+ enum gsm_extrsp_tok_type type;
+ union {
+ struct {
+ struct gsm_extrsp_range_item item[GSM_EXTRSP_MAX_RANGES];
+ int num_items;
+ } range;
+ char string[64];
+ int numeric;
+ } u;
+};
+
+struct gsm_extrsp {
+ unsigned int num_tokens;
+ struct gsm_extrsp_tok tokens[GSM_EXTRSP_MAX_TOKENS];
+};
+
+extern int extrsp_supports(const struct gsm_extrsp *er, int index, int value);
+extern struct gsm_extrsp *extrsp_parse(const void *ctx, const char *input);
+extern void extrsp_dump(const struct gsm_extrsp *er);
+
+#endif
Added: developers/seanchiang/gsm/include/gsmd/gsmd.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/gsmd.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/gsmd.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,100 @@
+#ifndef _GSMD_H
+#define _GSMD_H
+
+#ifdef __GSMD__
+
+#include <sys/types.h>
+
+#include <common/linux_list.h>
+
+#include <gsmd/vendorplugin.h>
+#include <gsmd/select.h>
+#include <gsmd/state.h>
+
+void *gsmd_tallocs;
+
+/* Refer to 3GPP TS 07.07 v 7.8.0, Chapter 4.1 */
+#define LGSM_ATCMD_F_EXTENDED 0x01 /* as opposed to basic */
+#define LGSM_ATCMD_F_PARAM 0x02 /* as opposed to action */
+
+struct gsmd_atcmd {
+ struct llist_head list;
+ void *ctx;
+ int (*cb)(struct gsmd_atcmd *cmd, void *ctx, char *resp);
+ char *resp;
+ int32_t ret;
+ u_int32_t buflen;
+ u_int16_t id;
+ u_int8_t flags;
+ char buf[];
+};
+
+enum llparse_state {
+ LLPARSE_STATE_IDLE, /* idle, not parsing a response */
+ LLPARSE_STATE_IDLE_CR, /* CR before response (V1) */
+ LLPARSE_STATE_IDLE_LF, /* LF before response (V1) */
+ LLPARSE_STATE_RESULT, /* within result payload */
+ LLPARSE_STATE_RESULT_CR, /* CR after result */
+ LLPARSE_STATE_ERROR, /* something went wrong */
+ /* ... idle again */
+};
+
+/* we can't take any _single_ response bigger than this: */
+#define LLPARSE_BUF_SIZE 256
+
+struct llparser {
+ enum llparse_state state;
+ unsigned int len;
+ unsigned int flags;
+ void *ctx;
+ int (*cb)(const char *buf, int len, void *ctx);
+ char *cur;
+ char buf[LLPARSE_BUF_SIZE];
+};
+
+struct gsmd;
+
+#define GSMD_FLAG_V0 0x0001 /* V0 responses to be expected from TA */
+
+struct gsmd {
+ unsigned int flags;
+ struct gsmd_fd gfd_uart;
+ struct gsmd_fd gfd_sock;
+ struct llparser llp;
+ struct llist_head users;
+ struct llist_head pending_atcmds; /* our busy gsmd_atcmds */
+ struct llist_head busy_atcmds; /* our busy gsmd_atcmds */
+ struct gsmd_vendor_plugin *vendorpl;
+ struct gsmd_device_state dev_state;
+
+ struct llist_head operators; /* cached list of operator names */
+};
+
+struct gsmd_user {
+ struct llist_head list; /* our entry in the global list */
+ struct llist_head finished_ucmds; /* our busy gsmd_ucmds */
+ struct gsmd *gsmd;
+ struct gsmd_fd gfd; /* the socket */
+ u_int32_t subscriptions; /* bitmaks of subscribed event groups */
+};
+
+#define GSMD_DEBUG 1 /* debugging information */
+#define GSMD_INFO 3
+#define GSMD_NOTICE 5 /* abnormal/unexpected condition */
+#define GSMD_ERROR 7 /* error condition, requires user action */
+#define GSMD_FATAL 8 /* fatal, program aborted */
+
+extern int gsmdlog_init(const char *path);
+/* write a message to the daemons' logfile */
+void __gsmd_log(int level, const char *file, int line, const char *function, const char *message, ...);
+/* macro for logging including filename and line number */
+#define gsmd_log(level, format, args ...) \
+ __gsmd_log(level, __FILE__, __LINE__, __FUNCTION__, format, ## args)
+
+#define DEBUGP(x, args ...) gsmd_log(GSMD_DEBUG, x, ## args)
+
+extern int gsmd_simplecmd(struct gsmd *gsmd, char *cmdtxt);
+
+#endif /* __GSMD__ */
+
+#endif /* _GSMD_H */
Added: developers/seanchiang/gsm/include/gsmd/select.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/select.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/select.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,26 @@
+#ifndef __GSMD_SELECT_H
+#define __GSMD_SELECT_H
+
+#ifdef __GSMD__
+
+#include <common/linux_list.h>
+
+#define GSMD_FD_READ 0x0001
+#define GSMD_FD_WRITE 0x0002
+#define GSMD_FD_EXCEPT 0x0004
+
+struct gsmd_fd {
+ struct llist_head list;
+ int fd; /* file descriptor */
+ unsigned int when;
+ int (*cb)(int fd, unsigned int what, void *data);
+ void *data; /* void * to pass to callback */
+};
+
+extern int gsmd_register_fd(struct gsmd_fd *ufd);
+extern void gsmd_unregister_fd(struct gsmd_fd *ufd);
+extern int gsmd_select_main(void);
+
+#endif /* __GSMD__ */
+
+#endif
Added: developers/seanchiang/gsm/include/gsmd/state.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/state.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/state.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,23 @@
+#ifndef _GSMD_STATE_H
+#define _GSMD_STATE_H
+
+#ifdef __GSMD__
+
+#define GSMD_CIPHIND_CAPABLE 0x01
+#define GSMD_CIPHIND_DISABLED_SIM 0x02
+#define GSMD_CIPHIND_ACTIVE 0x04
+
+struct gsmd_device_state {
+ struct {
+ unsigned int flags;
+ unsigned int network_state_gsm;
+ unsigned int network_state_gprs;
+ } ciph_ind;
+
+ unsigned int on;
+ unsigned int registered;
+};
+
+#endif /* __GSMD__ */
+
+#endif /* _GSMD_STATE_H */
Added: developers/seanchiang/gsm/include/gsmd/talloc.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/talloc.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/talloc.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,140 @@
+#ifndef _TALLOC_H_
+#define _TALLOC_H_
+
+
+#ifdef __GSMD__
+/*
+ Unix SMB/CIFS implementation.
+ Samba temporary memory allocation functions
+
+ Copyright (C) Andrew Tridgell 2004-2005
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* nfsim additions */
+#include <stdarg.h>
+#include <stdio.h>
+
+/* this is only needed for compatibility with the old talloc */
+typedef void TALLOC_CTX;
+
+/*
+ this uses a little trick to allow __LINE__ to be stringified
+*/
+#define _STRING_LINE_(s) #s
+#define _STRING_LINE2_(s) _STRING_LINE_(s)
+#define __LINESTR__ _STRING_LINE2_(__LINE__)
+#define __location__ __FILE__ ":" __LINESTR__
+
+#ifndef TALLOC_DEPRECATED
+#define TALLOC_DEPRECATED 0
+#endif
+
+/* useful macros for creating type checked pointers */
+#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
+#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
+
+#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
+
+#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
+#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
+
+#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
+#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
+#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
+
+#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
+#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
+
+#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
+
+#define malloc_p(type) (type *)malloc(sizeof(type))
+#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count)
+#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count)
+
+#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__)
+#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__)
+#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__)
+
+#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
+#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
+
+
+#if TALLOC_DEPRECATED
+#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
+#define talloc_p(ctx, type) talloc(ctx, type)
+#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
+#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
+#define talloc_destroy(ctx) talloc_free(ctx)
+#endif
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+
+/* The following definitions come from talloc.c */
+void *_talloc(const void *context, size_t size);
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
+void talloc_increase_ref_count(const void *ptr);
+void *talloc_reference(const void *context, const void *ptr);
+int talloc_unlink(const void *context, void *ptr);
+void talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+void talloc_set_name_const(const void *ptr, const char *name);
+void *talloc_named(const void *context, size_t size,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+void *talloc_named_const(const void *context, size_t size, const char *name);
+const char *talloc_get_name(const void *ptr);
+void *talloc_check_name(const void *ptr, const char *name);
+void talloc_report_depth(const void *ptr, FILE *f, int depth);
+void *talloc_parent(const void *ptr);
+void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+int talloc_free(void *ptr);
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
+void *talloc_steal(const void *new_ctx, const void *ptr);
+off_t talloc_total_size(const void *ptr);
+off_t talloc_total_blocks(const void *ptr);
+void talloc_report_full(const void *ptr, FILE *f);
+void talloc_report(const void *ptr, FILE *f);
+void talloc_enable_null_tracking(void);
+void talloc_enable_leak_report(void);
+void talloc_enable_leak_report_full(void);
+void *_talloc_zero(const void *ctx, size_t size, const char *name);
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
+char *talloc_strdup(const void *t, const char *p);
+char *talloc_strndup(const void *t, const char *p, size_t n);
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append(char *s,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
+void *talloc_autofree_context(void);
+size_t talloc_get_size(const void *ctx);
+
+#endif
+
+#endif
Added: developers/seanchiang/gsm/include/gsmd/ts0707.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/ts0707.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/ts0707.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,45 @@
+#ifndef _GSM_0707_H
+#define _GSM_0707_H
+
+/* Section 9.2.1 */
+enum gsm0707_cme_error {
+ GSM0707_CME_PHONE_FAILURE = 0,
+ GSM0707_CME_PHONE_NOCONNECT = 1,
+ GSM0707_CME_PHONE_ADAPT_RESERVED = 2,
+ GSM0707_CME_OPERATION_NOT_ALLOWED = 3,
+ GSM0707_CME_OPERATUON_NOT_SUPPORTED = 4,
+ GSM0707_CME_PH_SIM_PIN_REQUIRED = 5,
+ GSM0707_CME_PH_FSIM_PIN_REQUIRED = 6,
+ GSM0707_CME_PH_FSIM_PUK_REQUIRED = 7,
+ GSM0707_CME_SIM_NOT_INSERTED = 10,
+ GSM0707_CME_SIM_PIN_REQUIRED = 11,
+ GSM0707_CME_SIM_PUK_REQUIRED = 12,
+ GSM0707_CME_SIM_FAILURE = 13,
+ GSM0707_CME_SIM_BUSY = 14,
+ GSM0707_CME_SIM_WRONG = 15,
+ GSM0707_CME_INCORRECT_PASSWORD = 16,
+ GSM0707_CME_SIM_PIN2_REQUIRED = 17,
+ GSM0707_CME_SIM_PUK2_REQUIRED = 18,
+ GSM0707_CME_MEMORY_FULL = 20,
+ GSM0707_CME_INVALID_INDEX = 21,
+ GSM0707_CME_NOT_FOUND = 22,
+ GSM0707_CME_MEMORY_FAILURE = 23,
+ GSM0707_CME_TEXT_STRING_TOO_LONG = 24,
+ GSM0707_CME_TEXT_STRING_INVAL_CHARS = 25,
+ GSM0707_CME_DIAL_STRING_TOO_LONG = 26,
+ GSM0707_CME_DIAL_STRING_INVAL_CHARS = 27,
+ GSM0707_CME_NO_NETWORK_SERVICE = 30,
+ GSM0707_CME_NETWORK_TIMEOUT = 31,
+ GSM0707_CME_NETWORK_NOT_ALLOWED = 32,
+ GSM0707_CME_NETPERS_PIN_REQUIRED = 40,
+ GSM0707_CME_NETPERS_PUK_REQUIRED = 41,
+ GSM0707_CME_NETSUBSET_PIN_REQUIRED = 42,
+ GSM0707_CME_NETSUBSET_PUK_REQUIRED = 43,
+ GSM0707_CME_PROVIDER_PIN_REQUIRED = 44,
+ GSM0707_CME_PROVIDER_PUK_REQUIRED = 45,
+ GSM0707_CME_CORPORATE_PIN_REQUIRED = 46,
+ GSM0707_CME_CORPORATE_PUK_REQUIRED = 47,
+ GSM0707_CME_UNKNOWN = 100,
+};
+
+#endif /* _GSM_0707_H */
Added: developers/seanchiang/gsm/include/gsmd/unsolicited.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/unsolicited.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/unsolicited.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,18 @@
+#ifndef __GSMD_UNSOLICITED_H
+#define __GSMD_UNSOLICITED_H
+
+#ifdef __GSMD__
+
+#include <gsmd/gsmd.h>
+
+struct gsmd_unsolicit {
+ const char *prefix;
+ int (*parse)(char *unsol, int len, const char *param, struct gsmd *gsmd);
+};
+
+extern int unsolicited_parse(struct gsmd *g, char *buf, int len, const char *param);
+extern int generate_event_from_cme(struct gsmd *g, unsigned int cme_error);
+
+#endif /* __GSMD__ */
+
+#endif
Added: developers/seanchiang/gsm/include/gsmd/usock.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/usock.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/usock.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,266 @@
+#ifndef _GSMD_USOCK_H
+#define _GSMD_USOCK_H
+
+#include <gsmd/event.h>
+
+#define GSMD_UNIX_SOCKET "\0gsmd"
+//#define GSMD_UNIX_SOCKET_TYPE SOCK_SEQPACKET
+#define GSMD_UNIX_SOCKET_TYPE SOCK_STREAM
+
+#define GSMD_PROTO_VERSION 1
+
+#define GSMD_MSGSIZE_MAX 4096
+
+enum gsmd_msg_type {
+ GSMD_MSG_NONE = 0,
+ GSMD_MSG_EVENT = 1,
+ GSMD_MSG_PASSTHROUGH = 2,
+ GSMD_MSG_VOICECALL = 3,
+ GSMD_MSG_DATACALL = 4,
+ GSMD_MSG_PHONEBOOK = 5,
+ GSMD_MSG_NETWORK = 6,
+ GSMD_MSG_PHONE = 7,
+ GSMD_MSG_PIN = 8,
+ GSMD_MSG_SMS = 9,
+ __NUM_GSMD_MSGS
+};
+
+enum gsmd_passthrough_type {
+ GSMD_PASSTHROUGH_NONE = 0,
+ GSMD_PASSTHROUGH_REQ = 1,
+ GSMD_PASSTHROUGH_RESP = 2,
+};
+
+enum gsmd_msg_voicecall_type {
+ GSMD_VOICECALL_DIAL = 1,
+ GSMD_VOICECALL_HANGUP = 2,
+ GSMD_VOICECALL_ANSWER = 3,
+ GSMD_VOICECALL_DTMF = 4,
+ GSMD_VOICECALL_VOL_SET = 5,
+ GSMD_VOICECALL_VOL_GET = 6,
+};
+
+/* Handset / MT related commands */
+enum gsmd_msg_phone_type {
+ GSMD_PHONE_VOLUME = 1,
+ GSMD_PHONE_VIBRATOR = 2,
+};
+
+enum gsmd_msg_pin_type {
+ GSMD_PIN_INPUT = 1,
+};
+
+enum gsmd_msg_phone {
+ GSMD_PHONE_POWERUP = 1,
+ GSMD_PHONE_POWERDOWN = 2,
+};
+
+enum gsmd_msg_network {
+ GSMD_NETWORK_REGISTER = 1,
+ GSMD_NETWORK_SIGQ_GET = 2,
+ GSMD_NETWORK_VMAIL_GET = 3,
+ GSMD_NETWORK_VMAIL_SET = 4,
+ GSMD_NETWORK_OPER_GET = 5,
+ GSMD_NETWORK_CIND_GET = 6,
+};
+
+enum gsmd_msg_sms {
+ GSMD_SMS_LIST = 1,
+ GSMD_SMS_READ = 2,
+ GSMD_SMS_SEND = 3,
+ GSMD_SMS_WRITE = 4,
+ GSMD_SMS_DELETE = 5,
+};
+
+/* SMS stat from 3GPP TS 07.05, Clause 3.1 */
+enum gsmd_msg_sms_type {
+ GSMD_SMS_REC_UNREAD = 0,
+ GSMD_SMS_REC_READ = 1,
+ GSMD_SMS_STO_UNSENT = 2,
+ GSMD_SMS_STO_SENT = 3,
+ GSMD_SMS_ALL = 4,
+};
+
+/* SMS format from 3GPP TS 07.05, Clause 3.2.3 */
+enum gsmd_msg_sms_fmt {
+ GSMD_SMS_FMT_PDU = 0,
+ GSMD_SMS_FMT_TEXT = 1,
+};
+
+/* SMS delflg from 3GPP TS 07.05, Clause 3.5.4 */
+enum gsmd_msg_sms_delflg {
+ GSMD_SMS_DELFLG_INDEX = 0,
+ GSMD_SMS_DELFLG_READ = 1,
+ GSMD_SMS_DELFLG_READ_SENT = 2,
+ GSMD_SMS_DELFLG_LEAVING_UNREAD = 3,
+ GSMD_SMS_DELFLG_ALL = 4,
+};
+
+enum gsmd_msg_phonebook {
+ GSMD_PHONEBOOK_FIND = 1,
+ GSMD_PHONEBOOK_READ = 2,
+ GSMD_PHONEBOOK_READRG = 3,
+ GSMD_PHONEBOOK_WRITE = 4,
+ GSMD_PHONEBOOK_DELETE = 5,
+ GSMD_PHONEBOOK_GET_SUPPORT = 6,
+};
+
+/* Length from 3GPP TS 04.08, Clause 10.5.4.7 */
+
+#define GSMD_ADDR_MAXLEN 32
+struct gsmd_addr {
+ u_int8_t type;
+ char number[GSMD_ADDR_MAXLEN+1];
+} __attribute__ ((packed));
+
+struct gsmd_dtmf {
+ u_int8_t len;
+ char dtmf[0];
+} __attribute__ ((packed));
+
+struct gsmd_signal_quality {
+ u_int8_t rssi;
+ u_int8_t ber;
+} __attribute__ ((packed));
+
+struct gsmd_voicemail {
+ u_int8_t enable;
+ struct gsmd_addr addr;
+} __attribute__ ((packed));
+
+#define GSMD_PIN_MAXLEN 8
+struct gsmd_pin {
+ enum gsmd_pin_type type;
+ char pin[GSMD_PIN_MAXLEN+1];
+ char newpin[GSMD_PIN_MAXLEN+1];
+} __attribute__ ((packed));
+
+struct gsmd_evt_auxdata {
+ union {
+ struct {
+ enum gsmd_call_type type;
+ } call;
+ struct {
+ struct gsmd_addr addr;
+ } clip;
+ struct {
+ struct gsmd_addr addr;
+ } colp;
+ struct {
+ /* TBD */
+ struct gsmd_addr addr;
+ } sms;
+ struct {
+ enum gsmd_pin_type type;
+ } pin;
+ struct {
+ enum gsmd_netreg_state state;
+ u_int16_t lac;
+ u_int16_t ci;
+ } netreg;
+ struct {
+ u_int8_t tz;
+ } timezone;
+ struct {
+ struct gsmd_signal_quality sigq;
+ } signal;
+ struct {
+ enum gsmd_call_progress prog;
+ struct gsmd_addr addr;
+ u_int8_t ibt:1,
+ tch:1,
+ dir:2;
+ } call_status;
+ struct {
+ u_int16_t flags;
+ u_int16_t net_state_gsm;
+ u_int16_t net_state_gprs;
+ } cipher;
+ } u;
+} __attribute__((packed));
+
+/* Refer to GSM 07.05 subclause 3.5.4 */
+struct gsmd_sms_delete {
+ u_int8_t index;
+ u_int8_t delflg;
+} __attribute__ ((packed));
+
+/* Refer to GSM 03.40 subclause 9.2.2.2 and GSM 07.05 subclause 4.3 */
+#define GSMD_SMS_DATA_MAXLEN 164
+struct gsmd_sms {
+ u_int8_t length;
+ char data[GSMD_SMS_DATA_MAXLEN+1];
+} __attribute__ ((packed));
+
+/* Refer to GSM 07.05 subclause 4.4 */
+struct gsmd_sms_write {
+ u_int8_t stat;
+ struct gsmd_sms sms;
+} __attribute__ ((packed));
+
+/* Refer to GSM 07.07 subclause 8.12 */
+struct gsmd_phonebook_readrg {
+ u_int8_t index1;
+ u_int8_t index2;
+} __attribute__ ((packed));
+
+/* Refer to GSM 07.07 subclause 8.14 */
+/* FIXME: the nlength and tlength depend on SIM, use +CPBR=? to get */
+#define GSMD_PB_NUMB_MAXLEN 44
+#define GSMD_PB_TEXT_MAXLEN 14
+struct gsmd_phonebook {
+ u_int8_t index;
+ char numb[GSMD_PB_NUMB_MAXLEN+1];
+ u_int8_t type;
+ char text[GSMD_PB_TEXT_MAXLEN+1];
+} __attribute__ ((packed));
+
+
+/* Refer to GSM 07.07 subclause 8.13 */
+/* FIXME: the tlength depends on SIM, use +CPBR=? to get */
+struct gsmd_phonebook_find {
+ char findtext[GSMD_PB_TEXT_MAXLEN+1];
+} __attribute__ ((packed));
+
+/* Refer to GSM 07.07 subclause 8.12 */
+struct gsmd_phonebook_support {
+ u_int8_t index;
+ u_int8_t nlength;
+ u_int8_t tlength;
+} __attribute__ ((packed));
+
+struct gsmd_msg_hdr {
+ u_int8_t version;
+ u_int8_t msg_type;
+ u_int8_t msg_subtype;
+ u_int8_t _pad;
+ u_int16_t id;
+ u_int16_t len;
+ u_int8_t data[];
+} __attribute__((packed));
+
+#ifdef __GSMD__
+
+#include <common/linux_list.h>
+
+#include <gsmd/usock.h>
+#include <gsmd/gsmd.h>
+
+struct gsmd_user;
+
+struct gsmd_ucmd {
+ struct llist_head list;
+ struct gsmd_msg_hdr hdr;
+ char buf[];
+} __attribute__ ((packed));
+
+extern struct gsmd_ucmd *ucmd_alloc(int extra_size);
+extern int usock_init(struct gsmd *g);
+extern void usock_cmd_enqueue(struct gsmd_ucmd *ucmd, struct gsmd_user *gu);
+extern struct gsmd_ucmd *usock_build_event(u_int8_t type, u_int8_t subtype, u_int8_t len);
+extern int usock_evt_send(struct gsmd *gsmd, struct gsmd_ucmd *ucmd, u_int32_t evt);
+
+#endif /* __GSMD__ */
+
+#endif
+
Added: developers/seanchiang/gsm/include/gsmd/vendorplugin.h
===================================================================
--- developers/seanchiang/gsm/include/gsmd/vendorplugin.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/gsmd/vendorplugin.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,27 @@
+#ifndef _GSMD_VENDORPLUGIN_H
+#define _GSMD_VENDORPLUGIN_H
+
+#ifdef __GSMD__
+
+#include <common/linux_list.h>
+#include <gsmd/gsmd.h>
+
+struct gsmd;
+struct gsmd_unsolicit;
+
+struct gsmd_vendor_plugin {
+ struct llist_head list;
+ unsigned char *name;
+ unsigned int num_unsolicit;
+ const struct gsmd_unsolicit *unsolicit;
+ int (*detect)(struct gsmd *g);
+ int (*initsettings)(struct gsmd *g);
+};
+
+extern int gsmd_vendor_plugin_register(struct gsmd_vendor_plugin *pl);
+extern void gsmd_vendor_plugin_unregister(struct gsmd_vendor_plugin *pl);
+extern int gsmd_vendor_plugin_find(struct gsmd *g);
+
+#endif /* __GSMD__ */
+
+#endif
Added: developers/seanchiang/gsm/include/libgsmd/Makefile.am
===================================================================
--- developers/seanchiang/gsm/include/libgsmd/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/libgsmd/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,2 @@
+pkgincludedir = $(includedir)/libgsmd
+pkginclude_HEADERS = event.h handset.h libgsmd.h misc.h phonebook.h voicecall.h
Added: developers/seanchiang/gsm/include/libgsmd/event.h
===================================================================
--- developers/seanchiang/gsm/include/libgsmd/event.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/libgsmd/event.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,18 @@
+#ifndef _LIBGSMD_EVENT_H
+#define _LIBGSMD_EVENT_H
+
+#include <gsmd/event.h>
+
+/* Prototype of libgsmd callback handler function */
+typedef int lgsm_evt_handler(struct lgsm_handle *lh, int evt_type, struct gsmd_evt_auxdata *aux);
+
+/* Register an event callback handler with libgsmd */
+extern int lgsm_evt_handler_register(struct lgsm_handle *lh, int evt_type,
+ lgsm_evt_handler *handler);
+extern void lgsm_evt_handler_unregister(struct lgsm_handle *lh, int evt_type);
+
+extern int lgsm_evt_init(struct lgsm_handle *lh);
+extern void lgsm_evt_exit(struct lgsm_handle *lh);
+
+
+#endif
Added: developers/seanchiang/gsm/include/libgsmd/handset.h
===================================================================
--- developers/seanchiang/gsm/include/libgsmd/handset.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/libgsmd/handset.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,15 @@
+#ifndef _LIBGSMD_HANDSET_H
+#define _LIBGSMD_HANDSET_H
+
+#include <libgsmd/libgsmd.h>
+/* Set speaker level (Chapter 8.23) */
+extern int lgsm_set_spkr_level(struct lgsm_handle *lh,
+ u_int32_t level);
+
+/* Mute call during voice call */
+extern int lgsm_mute_set(struct lgsm_handle *lh, u_int8_t on);
+
+/* Get information on whether voice call is muted or not */
+extern int lgsm_mute_get(struct lgsm_handle *lh, u_int8_t *on);
+
+#endif
Added: developers/seanchiang/gsm/include/libgsmd/libgsmd.h
===================================================================
--- developers/seanchiang/gsm/include/libgsmd/libgsmd.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/libgsmd/libgsmd.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,69 @@
+#ifndef _LIBGSMD_H
+#define _LIBGSMD_H
+
+/* libgsmd.h - Library API for gsmd, the GSM Daemon
+ * (C) 2006 by Harald Welte <hwelte at hmw-consulting.de>
+ * Development funded by First International Computers, Inc.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+
+#include <gsmd/usock.h>
+
+/* Generic Information
+ *
+ * Return value:
+ * < 0 Error, see libgsmd/errno.h and errno.h
+ * = 0 Success
+ * > 0 Success, number of information elements returned
+ *
+ * Allocation:
+ * All data structures are caller-allocated. The only exception
+ * is struct lgsm_handle which is allocatedi in lgsm_init() and
+ * free'd in lgsm_exit()
+ *
+ * References:
+ * Recefences to "Chapter X" are referring to 3GPP TS 07.07 version 7.8.0
+ */
+
+/* Opaque data structure, content only known to libgsm implementation */
+struct lgsm_handle;
+
+/* Refer to GSM 04.08 [8] subclause 10.5.4.7 */
+enum lgsm_addr_type {
+ LGSM_ATYPE_ISDN_UNKN = 161,
+ //LGSM_ATYPE_ISDN_INTL = ,
+ //LGSM_ATYPE_ISDN_NATIONAL = ,
+};
+
+#define LGSM_ADDR_MAXLEN 31
+struct lgsm_addr {
+ enum lgsm_addr_type type;
+ char addr[LGSM_ADDR_MAXLEN+1];
+};
+
+typedef int lgsm_msg_handler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh);
+
+#define LGSMD_DEVICE_GSMD "gsmd"
+
+/* initialize usage of libgsmd, obtain handle for othe API calls */
+extern struct lgsm_handle *lgsm_init(const char *device);
+
+/* Terminate usage of libgsmd */
+extern int lgsm_exit(struct lgsm_handle *lh);
+
+/* Obtain file descriptor (e.g. for select-loop under app control) */
+extern int lgsm_fd(struct lgsm_handle *lh);
+
+extern int lgsm_register_handler(struct lgsm_handle *lh, int type, lgsm_msg_handler *handler);
+extern void lgsm_unregister_handler(struct lgsm_handle *lh, int type);
+
+extern int lgsm_passthrough_send(struct lgsm_handle *lh, const char *tx);
+extern int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned int *rx_len);
+extern int lgsm_subscriptions(struct lgsm_handle *lh, u_int32_t subscriptions);
+
+extern struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len);
+extern int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh);
+
+#endif
Added: developers/seanchiang/gsm/include/libgsmd/misc.h
===================================================================
--- developers/seanchiang/gsm/include/libgsmd/misc.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/libgsmd/misc.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,76 @@
+#ifndef _LIBGSMD_H
+#define _LIBGSMD_H
+
+/* libgsmd.h - Library API for gsmd, the GSM Daemon
+ * (C) 2006 by Harald Welte <hwelte at hmw-consulting.de>
+ * Development funded by First International Computers, Inc.
+ */
+
+#include <libgsmd/libgsmd.h>
+
+extern int lgsm_phone_power(struct lgsm_handle *lh, int power);
+
+enum lgsm_netreg_state {
+ LGSM_NETREG_ST_NOTREG = 0,
+ LGSM_NETREG_ST_REG_HOME = 1,
+ LGSM_NETREG_ST_NOTREG_SEARCH = 2,
+ LGSM_NETREG_ST_DENIED = 3,
+ LGSM_NETREG_ST_UNKNOWN = 4,
+ LGSM_NETREG_ST_REG_ROAMING = 5,
+};
+
+/* Get the current network registration status */
+extern int lgsm_get_netreg_state(struct lgsm_handle *lh,
+ enum lgsm_netreg_state *state);
+
+extern int lgsm_netreg_register(struct lgsm_handle *lh, int oper);
+
+enum lgsm_info_type {
+ LGSM_INFO_TYPE_NONE = 0,
+ LGSM_INFO_TYPE_MANUF = 1,
+ LGSM_INFO_TYPE_MODEL = 2,
+ LGSM_INFO_TYPE_REVISION = 3,
+ LGSM_INFO_TYPE_SERIAL = 4,
+ LGSM_INFO_TYPE_IMSI = 5,
+};
+
+/* Get some information about the handset */
+extern int lgsm_get_info(struct lgsm_handle *lh,
+ enum lgsm_info_type type,
+ char *ret_string, u_int16_t len);
+
+/* Authenticate to SIM Card using specified null-terminated pin */
+extern int lgsm_pin_auth(struct lgsm_handle *lh, const char *pin);
+
+
+/* General Commands */
+
+/* Get Signal Strehngth (Chapter 8.5) */
+extern int lgsm_get_signal_quality(struct lgsm_handle *h,
+ unsigned int *rssi);
+
+/* Set voice mail number */
+extern int lgsm_voicemail_set(struct lgsm_handle *lh,
+ struct lgsm_addr *addr);
+
+/* Get currently configured voice mail number */
+extern int lgsm_voicemail_get(struct lgsm_handle *lh,
+ struct lgsm_addr *addr);
+
+/* Operator Selection, Network Registration */
+/* TBD */
+
+
+/* CLIP, CLIR, COLP, Call Forwarding, Call Waiting, Call Deflecting */
+/* TBD */
+
+
+/* SMS related functions */
+/* TBD */
+
+
+/* GPRS related functions */
+/* TBD */
+
+
+#endif
Added: developers/seanchiang/gsm/include/libgsmd/phonebook.h
===================================================================
--- developers/seanchiang/gsm/include/libgsmd/phonebook.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/libgsmd/phonebook.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,103 @@
+#ifndef _LIBGSMD_PBOOK_H
+#define _LIBGSMD_PBOOK_H
+
+#include <libgsmd/libgsmd.h>
+
+/* Phonebook */
+
+/* Chapter 8.11 */
+enum lgsm_pbook_type {
+ LGSM_PB_ME_DIALLED = 1,
+ LGSM_PB_SIM_EMERGENCY = 2,
+ LGSM_PB_SIM_FIXDIAL = 3,
+ LGSM_PB_SIM_DIALLED = 4,
+ LGSM_PB_ME_MISSED = 5,
+ LGSM_PB_ME_PHONEBOOK = 6,
+ LGSM_PB_COMB_PHONEBOOK = 7,
+ LGSM_PB_SIM_OWN_NUMBERS = 8,
+ LGSM_PB_ME_RECEIVED = 9,
+ LGSM_PB_SIM_PHONEBOOK = 10,
+ LGSM_PB_TA_PHONEBOOK = 11,
+};
+
+/* Refer to GSM 07.07 subclause 8.14 */
+enum lgsm_pb_addr_type {
+ LGSM_PB_ATYPE_INTL = 145,
+ LGSM_PB_ATYPE_OTHE = 129,
+};
+
+/* Refer to GSM 07.07 subclause 8.12 */
+struct lgsm_phonebook_readrg {
+ int index1;
+ int index2;
+};
+
+/* Refer to GSM 07.07 subclause 8.14 */
+/* FIXME: the nlength and tlength depend on SIM, use +CPBR=? to get */
+#define LGSM_PB_NUMB_MAXLEN 44
+#define LGSM_PB_TEXT_MAXLEN 14
+struct lgsm_phonebook {
+ int index;
+ char numb[LGSM_PB_NUMB_MAXLEN+1];
+ enum lgsm_pb_addr_type type;
+ char text[LGSM_PB_TEXT_MAXLEN+1];
+};
+
+/* Refer to GSM 07.07 subclause 8.13 */
+/* FIXME: the tlength depends on SIM, use +CPBR=? to get */
+struct lgsm_phonebook_find {
+ char findtext[LGSM_PB_TEXT_MAXLEN+1];
+};
+
+#if 0
+/* Get a bitmask of supported phonebook types */
+extern int lgsm_pb_get_types(struct lgsm_handle *lh, u_int32 *typemask);
+
+/* Get a range of supported indexes in given phonebook type, Chapter 8.12 */
+extern int lgsm_pb_get_range(struct lgsm_handle *lh,
+ enum lgsm_pbook_type type,
+ u_int32_t *from, u_int32_t *to,
+ u_int32_t *nlength, *u_int32_t tlength);
+
+#define LGSM_PB_TEXT_MAXLEN 31
+
+struct lgsm_pb_entry {
+ struct lgsm_pb_entry *next;
+ enum lgsm_pbook_type type;
+ u_int32_t index;
+ char text[LGSM_PB_TEXT_MAXLEN+1];
+};
+#endif
+
+/* Get a specific phonebook entry and store it to 'pb'
+ * pb' is caller-allocated */
+extern int lgsm_pb_get_entry(struct lgsm_handle *lh,
+ struct lgsm_pb_entry *pb);
+
+/* Store a specific phonebook entry 'pb' into phone */
+extern int lgsm_pb_set_entry(struct lgsm_handle *lh,
+ struct lgsm_pb_entry *pb);
+
+/* Find phonebook entires which alphanumeric filed start
+ * with string <findtext> */
+extern int lgsm_pb_find_entry(struct lgsm_handle *lh,
+ const struct lgsm_phonebook_find *pb_find);
+
+/* Read phonebook entry in location number index */
+extern int lgsm_pb_read_entry(struct lgsm_handle *lh, int index);
+
+/* Read phonebook entries in location number range */
+extern int lgsm_pb_read_entryies(struct lgsm_handle *lh,
+ const struct lgsm_phonebook_readrg *pb_readrg);
+
+/* Delete phonebook entry in location index */
+extern int lgsmd_pb_del_entry(struct lgsm_handle *lh, int index);
+
+/* Write phonebook entry in location */
+extern int lgsmd_pb_write_entry(struct lgsm_handle *lh,
+ const struct lgsm_phonebook *pb);
+
+/* Get the location range/nlength/tlength supported */
+extern int lgsm_pb_get_support(struct lgsm_handle *lh);
+
+#endif
Added: developers/seanchiang/gsm/include/libgsmd/pin.h
===================================================================
--- developers/seanchiang/gsm/include/libgsmd/pin.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/libgsmd/pin.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,8 @@
+#ifndef _LGSM_PIN_H
+#define _LGSM_PIN_H
+
+extern const char *lgsm_pin_name(enum gsmd_pin_type ptype);
+
+extern int lgsm_pin(struct lgsm_handle *lh, unsigned int type, char *pin, char *newpin);
+
+#endif
Added: developers/seanchiang/gsm/include/libgsmd/voicecall.h
===================================================================
--- developers/seanchiang/gsm/include/libgsmd/voicecall.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/include/libgsmd/voicecall.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,21 @@
+#ifndef _LIBGSMD_VCALL_H
+#define _LIBGSMD_VCALL_H
+
+#include <libgsmd/libgsmd.h>
+
+/* Voice Calls */
+
+/* Initiate an outgoing voice call */
+extern int lgsm_voice_out_init(struct lgsm_handle *lh,
+ const struct lgsm_addr *number);
+
+/* Accept incoming voice call */
+extern int lgsm_voice_in_accept(struct lgsm_handle *lh);
+
+/* Terminate outgoing (or incoming) voice call */
+extern int lgsm_voice_hangup(struct lgsm_handle *lh);
+
+/* Send DTMF character during voice call */
+extern int lgsm_voice_dtmf(struct lgsm_handle *lh, char dtmf_char);
+
+#endif
Added: developers/seanchiang/gsm/libgsmd.pc.in
===================================================================
--- developers/seanchiang/gsm/libgsmd.pc.in 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/libgsmd.pc.in 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libgsmd
+Description: GSM 07.10 Multiplexer Library
+Version: @VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lgsmd
+Requires:
+
Added: developers/seanchiang/gsm/logs/screenlog.0
===================================================================
--- developers/seanchiang/gsm/logs/screenlog.0 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/logs/screenlog.0 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,500 @@
+ccu -l /dev/ttU yUSB0 -s 15200
+cu: Unsupported baud rate 15200
+[1m[3m%[23m[1m[m
[m[23m[24m[J[3mlaforge at rama%pts/11 (20:27)[23m phone/src/libgsmd/atcmd > [K[46C [1m2/1[m[50Dcu -l /dev/ttyUSB0 -s 1520015200
+Connected.
+
+OK
+ATV1
+OK
+AT+COPS=?
+ERROR
+AT+COPS=?
+ERROR
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS=?
+ERROR
+
+OK
+
+OK
+AT+CRC=1
+OK
+AT+CRC=?
++CRC: (0,1)
+
+OK
+AT+CGMI
+<manufacturer>
+
+OK
+AT+GMM
+<model>
+
+OK
+AT+CGSI
+EXT: I
+
+ERROR
+AT+CGSS
+EXT: I
+
+ERROR
+AT+CGSS=?
+EXT: I
+
+ERROR
+AT+CGSS?
+EXT: I
+
+ERROR
+AT+CGSN
+<serial number>
+
+OK
+AT+CSCS?
++CSCS: "IRA"
+
+OK
+AT+CSCS=?
++CSCS: "GSM","IRA","PCCP437","PCDN","8859-1","HEX","UCS2"
+
+OK
+AT+CIMI?
+ERROR
+AT+CIMI
+262074992516579
+
+OK
+AT+M
+EXT: I
+
+ERROR
+AT+CMUX?
+OK
+AT-Command Interpreter ready
+
+OK
+AT+CMUX=?
++CMUX: (1),(0),(1-5),(10-100),(1-255),(0-100),(2-255),(1-255),(1-7)
+
+OK
+AT-Command Interpreter ready
+AT+CSTA
+ERROR
+AT+CSTA?
++CSTA: 129
+
+OK
+AT+CSTA=?
++CSTA: (129,145)
+
+OK
+AT+CPIN?
++CPIN: SIM PIN
+
+OK
+ATP
+ERROR
+AT+CPIN=9450
+ERROR
+AT+CMOD?
++CMOD: 0
+
+OK
+AT+CMOD=?
++CMOD: (0-3)
+
+OK
+
+OK
+AT+CHUP
+OK
+AT+CBST=?
++CBST: (0-7,12,14,65,66,68,70,71,75),(0),(0-3)
+
+OK
+AT
+ERROR
+AT+CRLP=?
++CRLP: (0-61),(0-61),(39-255),(1-255)
+
+OK
+
+OK
+AT+CR?
++CR: 0
+
+OK
+AT+CR=?
++CR: (0,1)
+
+OK
+AT+CR=1
+OK
+
+OK
+
+OK
+
+OK
+AT+CEER=1
++CEER: 0,1,1,255,no error
+
+OK
+AT+CEER?
+ERROR
+AT+CEER=?
+OK
+
+OK
+AT+CRC=1
+OK
+AT+CRC=?
++CRC: (0,1)
+
+OK
+AT+CSNS=?
+ERROR
+AT+CSNS?
++CSNS: 0
+
+OK
+AT+CSNS=?
++CSNS: (0-7)
+
+OK
+
+OK
+AT+CHVU?
+EXT: I
+
+ERROR
+AT+CVUHU?
+EXT: I
+
+ERROR
+AT+CVHU?
+EXT: I
+
+ERROR
+AT+CVHU=?
+EXT: I
+
+ERROR
+
+OK
+AT+CV120?
+EXT: I
+
+ERROR
+AT+CV120=?
+EXT: I
+
+ERROR
+
+OK
+AT+CNUM?
+ERROR
+AT+CNUM=?
+OK
+AT+CNUM?
+ERROR
+AT+CNUM=?
+OK
+AT+CREG?
++CREG: 0,2
+
+OK
+AT+CREG=?
++CREG: (0-2)
+
+OK
+AT
+ERROR
+ATC
+EXT: I
+
+ERROR
+AT+CREG=2
+OK
+
+OK
+AT+COPS=?
+ERROR
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS=?
+ERROR
+
+OK
+AT+CLKS=?
+EXT: I
+
+ERROR
+AT+CLCK=?
++CLCK: ("SC","AO","OI","OX","AI","IR","AB","AG","AC","FD","PS","PN","PU","PP","PC","PF","AL")
+
+OK
+
+OK
+AT+CLIP=?
++CLIP: (0,1)
+
+OK
+ATP
+ERROR
+AT+CLIP?
++CLIP: 0,2
+
+OK
+AT+CLIR=?
++CLIR: (0,1,2)
+
+OK
+AT+CLIR?
++CLIR: 0,2
+
+OK
+AT+COPLP+
+EXT: I
+
+ERROR
+AT+COLP?
++COLP: 0,2
+
+OK
+AT+COLP=?
++COLP: (0,1)
+
+OK
+AT+CCFG
+EXT: I
+
+ERROR
+a
+ERROR
+AT+CCFC?
+ERROR
+AT+CCFC=?
++CCFC: (0-5)
+
+OK
+AT+CCWA
+OK
+AT+CCWA?
++CCWA: 0
+
+OK
+AT+CCWA=?
++CCWA: (0,1)
+
+OK
+
+OK
+AT+CCWA=1
+OK
+
+OK
+AT+CTFR=?
+OK
+AT+CTFR?
+ERROR
+
+OK
+AT+CUSD=?
++CUSD: (0,1,2)
+
+OK
+AT+CUSD?
++CUSD: 0
+
+OK
+AT+CUSD=1
+OK
+AT+CCSN?
+EXT: I
+
+ERROR
+AT+CCSN=?
+EXT: I
+
+ERROR
+
+OK
+AT+CCSI?
+EXT: I
+
+ERROR
+AT
+ERROR
+AT+CLCC?
+ERROR
+AT+CLCC=?
+OK
+
+OK
+AT+CPOL?
+ERROR
+AT+CPOL=?
+ERROR
+AT+
+ERROR
+AT+COPN?
+ERROR
+AT+COPN=?
+OK
+
+OK
+AT+CPAS?
+ERROR
+AT+CPAS=?
++CPAS: (0-5)
+
+OK
+AT+CPAS
++CPAS: 0
+
+OK
+
+OK
+AT+CMEC?
+EXT: I
+
+ERROR
+AT+CMEC=?
+EXT: I
+
+ERROR
+AT+CFUN?
++CFUN: 1
+
+OK
+AT+CFUN=?
++CFUN: (0,1,4),(0)
+
+OK
+
+OK
+AT+PIN
+EXT: I
+
+ERROR
+AT+CPIN?
++CPIN: SIM PIN
+
+OK
+AT+CPIN?
++CPIN: SIM PIN
+
+OK
+AT+CPIN=9450
+ERROR
+
++CREG: 2
+
+OK
+AT+CPIN?
++CPIN: READY
+
+OK
+AT+CBC?
+ERROR
+AT+CBC=?
++CBC: (0-3),(0-100)
+
+OK
+AT+CBC
++CBC: 0,0
+
+OK
+AT+CBC
++CBC: 0,0
+
+OK
+AT+CBC
++CBC: 0,0
+
+OK
+AT+CSQ?
+ERROR
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS=?
AT-Command Interpreter ready
+
+OK
+
+OK
+AT+CPIN
+ERROR
+AT+CPIN?
++CPIN: SIM PIN
+
+OK
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS?
++COPS: 0
+
+OK
+AT+CPAS?
+ERROR
+AT+CAP
+EXT: I
+
+ERROR
+AT+CPAS
++CPAS: 0
+
+OK
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS=?
AT-Command Interpreter ready
+AT+CPIN?
++CPIN: READY
+
+OK
+AT+CMEC
+EXT: I
+
+ERROR
+AT+CMEC?
+EXT: I
+
+ERROR
+AT+CDIS?
+EXT: I
+
+ERROR
+AT+CIND?
++CIND: 0,0
+
+OK
+AT+CIND=/?
+OK
+AT+CIND=?
++CIND: ("signal", (0-5)), ("smsfull", (0-1))
+
+OK
+AT+CMER?
++CMER: 0,0,0,0,0
+
+OK
+AT+CMER=?
++CMER: (0-2), (0), (0), (0-2), (0,1)
+
+OK
+cu: Got hangup signal
+
+Disconnected.
+[1m[3m%[23m[1m[m
[m[23m[24m[J[3mlaforge at rama%pts/11 (22:31)[23m phone/src/libgsmd/atcmd > [K[46C [1m3/0[m[50D
\ No newline at end of file
Added: developers/seanchiang/gsm/src/Makefile.am
===================================================================
--- developers/seanchiang/gsm/src/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1 @@
+SUBDIRS = gsmd libgsmd util
Added: developers/seanchiang/gsm/src/gsmd/Makefile.am
===================================================================
--- developers/seanchiang/gsm/src/gsmd/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,11 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS = -std=gnu99
+
+sbin_PROGRAMS = gsmd
+
+gsmd_SOURCES = gsmd.c atcmd.c select.c vendor.c usock.c unsolicited.c log.c \
+ vendor_ti.c talloc.c operator_cache.c ext_response.c
+#gsmd_LDADD = ../libgsmd/libgsmd.la
+#gsmd_LDFLAGS = -dynamic
+
+noinst_HEADERS = gsmd.h
Added: developers/seanchiang/gsm/src/gsmd/atcmd.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/atcmd.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/atcmd.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,475 @@
+/* gsmd AT command interpreter / parser / constructor
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <termios.h>
+
+#include <sys/types.h>
+
+#include <common/linux_list.h>
+
+#include "gsmd.h"
+
+#include <gsmd/ts0707.h>
+#include <gsmd/gsmd.h>
+#include <gsmd/atcmd.h>
+#include <gsmd/talloc.h>
+#include <gsmd/unsolicited.h>
+
+static void *__atcmd_ctx;
+
+enum final_result_codes {
+ GSMD_RESULT_OK = 0,
+ GSMD_RESULT_ERR = 1,
+ NUM_FINAL_RESULTS,
+};
+
+static const char *final_results[] = {
+ "OK",
+ "ERROR",
+ "+CME ERROR:"
+};
+
+/* we basically implement a parse that can deal with
+ * - receiving and queueing commands from higher level of libgmsd
+ * - optionally combining them into one larger command (; appending)
+ * - sending those commands to the TA, receiving and parsing responses
+ * - calling back application on completion, or waiting synchronously
+ * for a response
+ * - dealing with intermediate and unsolicited resultcodes by calling
+ * back into the application / higher levels
+ */
+
+static inline int llparse_append(struct llparser *llp, char byte)
+{
+ if (llp->cur < llp->buf + llp->len) {
+ *(llp->cur++) = byte;
+ return 0;
+ } else {
+ DEBUGP("llp->cur too big!!!\n");
+ return -EFBIG;
+ }
+}
+
+static int llparse_byte(struct llparser *llp, char byte)
+{
+ int ret = 0;
+
+ switch (llp->state) {
+ case LLPARSE_STATE_IDLE:
+ if (llp->flags & LGSM_ATCMD_F_EXTENDED) {
+ if (byte == '\r')
+ llp->state = LLPARSE_STATE_IDLE_CR;
+ else {
+#ifdef STRICT
+ llp->state = LLPARSE_STATE_ERROR;
+#else
+ llp->state = LLPARSE_STATE_RESULT;
+ ret = llparse_append(llp, byte);
+#endif
+ }
+ } else {
+ llp->state = LLPARSE_STATE_RESULT;
+ ret = llparse_append(llp, byte);
+ }
+ break;
+ case LLPARSE_STATE_IDLE_CR:
+ if (byte == '\n')
+ llp->state = LLPARSE_STATE_IDLE_LF;
+ else
+ llp->state = LLPARSE_STATE_ERROR;
+ break;
+ case LLPARSE_STATE_IDLE_LF:
+ /* can we really go directly into result_cr ? */
+ if (byte == '\r')
+ llp->state = LLPARSE_STATE_RESULT_CR;
+ else {
+ llp->state = LLPARSE_STATE_RESULT;
+ ret = llparse_append(llp, byte);
+ }
+ break;
+ case LLPARSE_STATE_RESULT:
+ if (byte == '\r')
+ llp->state = LLPARSE_STATE_RESULT_CR;
+ else
+ ret = llparse_append(llp, byte);
+ break;
+ case LLPARSE_STATE_RESULT_CR:
+ if (byte == '\n') {
+ /* re-set cursor to start of buffer */
+ llp->cur = llp->buf;
+ llp->state = LLPARSE_STATE_IDLE;
+ memset(llp->buf, 0, LLPARSE_BUF_SIZE);
+ }
+ break;
+ case LLPARSE_STATE_ERROR:
+ break;
+ }
+
+ return ret;
+}
+
+static int llparse_string(struct llparser *llp, char *buf, unsigned int len)
+{
+ while (len--) {
+ int rc = llparse_byte(llp, *(buf++));
+ if (rc < 0)
+ return rc;
+
+ /* if _after_ parsing the current byte we have finished,
+ * let the caller know that there is something to handle */
+ if (llp->state == LLPARSE_STATE_RESULT_CR) {
+ /* FIXME: what to do with return value ? */
+ llp->cb(llp->buf, llp->cur - llp->buf, llp->ctx);
+ }
+ }
+
+ return 0;
+}
+
+static int llparse_init(struct llparser *llp)
+{
+ llp->state = LLPARSE_STATE_IDLE;
+ return 0;
+}
+
+/* mid-level parser */
+
+static int parse_final_result(const char *res)
+{
+ int i;
+ for (i = 0; i < NUM_FINAL_RESULTS; i++) {
+ if (!strcmp(res, final_results[i]))
+ return i;
+ }
+
+ return -1;
+}
+
+static int ml_parse(const char *buf, int len, void *ctx)
+{
+ struct gsmd *g = ctx;
+ struct gsmd_atcmd *cmd = NULL;
+ int rc = 0, final = 0;
+
+ DEBUGP("buf=`%s'(%d)\n", buf, len);
+
+ /* FIXME: This needs to be part of the vendor plugin. If we receive
+ * an empty string or that 'ready' string, we need to init the modem */
+ if (strlen(buf) == 0 ||
+ !strcmp(buf, "AT-Command Interpreter ready")) {
+ gsmd_initsettings(g);
+ return 0;
+ }
+
+ /* responses come in order, so first response has to be for first
+ * command we sent, i.e. first entry in list */
+ if (!llist_empty(&g->busy_atcmds))
+ cmd = llist_entry(g->busy_atcmds.next,
+ struct gsmd_atcmd, list);
+
+ /* we have to differentiate between the following cases:
+ *
+ * A) an information response ("+whatever: ...")
+ * we just pass it up the callback
+ * B) an unsolicited message ("+whateverelse: ... ")
+ * we call the unsolicited.c handlers
+ * C) a final response ("OK", "+CME ERROR", ...)
+ * in this case, we need to check whether we already sent some
+ * previous data to the callback (information response). If yes,
+ * we do nothing. If no, we need to call the callback.
+ * D) an intermediate response ("CONNECTED", "BUSY", "NO DIALTONE")
+ * TBD
+ */
+
+ if (buf[0] == '+' || buf[0] == '%') {
+ /* an extended response */
+ const char *colon = strchr(buf, ':');
+ if (!colon) {
+ gsmd_log(GSMD_ERROR, "no colon in extd response `%s'\n",
+ buf);
+ return -EINVAL;
+ }
+ if (!strncmp(buf+1, "CME ERROR", 9)) {
+ /* Part of Case 'C' */
+ unsigned long err_nr;
+ err_nr = strtoul(colon+1, NULL, 10);
+ DEBUGP("error number %lu\n", err_nr);
+ if (cmd)
+ cmd->ret = err_nr;
+ final = 1;
+ goto final_cb;
+ }
+
+ if (!cmd || strncmp(buf, &cmd->buf[2], colon-buf)) {
+ /* Assuming Case 'B' */
+ DEBUGP("extd reply `%s' to cmd `%s', must be "
+ "unsolicited\n", buf, cmd ? &cmd->buf[2] : "NONE");
+ colon++;
+ if (colon > buf+len)
+ colon = NULL;
+ rc = unsolicited_parse(g, buf, len, colon);
+ /* if unsolicited parser didn't handle this 'reply', then we
+ * need to continue and try harder and see what it is */
+ if (rc != -ENOENT) {
+ /* Case 'B' finished */
+ return rc;
+ }
+ /* contine, not 'B' */
+ }
+
+ if (cmd) {
+ if (cmd->buf[2] != '+' && cmd->buf[2] != '%') {
+ gsmd_log(GSMD_ERROR, "extd reply to non-extd command?\n");
+ return -EINVAL;
+ }
+
+ /* if we survive till here, it's a valid extd response
+ * to an extended command and thus Case 'A' */
+
+ /* FIXME: solve multi-line responses ! */
+ if (cmd->buflen < len)
+ len = cmd->buflen;
+
+ memcpy(cmd->buf, buf, len);
+ }
+ } else {
+ if (!strcmp(buf, "RING")) {
+ /* this is the only non-extended unsolicited return
+ * code, part of Case 'B' */
+ return unsolicited_parse(g, buf, len, NULL);
+ }
+
+ if (!strcmp(buf, "ERROR") ||
+ ((g->flags & GSMD_FLAG_V0) && buf[0] == '4')) {
+ /* Part of Case 'C' */
+ DEBUGP("unspecified error\n");
+ if (cmd)
+ cmd->ret = 4;
+ final = 1;
+ goto final_cb;
+ }
+
+ if (!strncmp(buf, "OK", 2)
+ || ((g->flags & GSMD_FLAG_V0) && buf[0] == '0')) {
+ /* Part of Case 'C' */
+ if (cmd)
+ cmd->ret = 0;
+ final = 1;
+ goto final_cb;
+ }
+
+ /* FIXME: handling of those special commands in response to
+ * ATD / ATA */
+ if (!strncmp(buf, "NO CARRIER", 11)) {
+ /* Part of Case 'D' */
+ final = 1;
+ goto final_cb;
+ }
+
+ if (!strncmp(buf, "BUSY", 4)) {
+ /* Part of Case 'D' */
+ final = 1;
+ goto final_cb;
+ }
+ }
+
+ /* we reach here, if we are at an information response that needs to be
+ * passed on */
+
+final_cb:
+ /* if we reach here, the final result code of a command has been reached */
+
+ if (!cmd)
+ return rc;
+
+ if (cmd && cmd->ret != 0)
+ generate_event_from_cme(g, cmd->ret);
+
+ if (!cmd->cb) {
+ gsmd_log(GSMD_NOTICE, "command without cb!!!\n");
+ } else {
+ if (!final || !cmd->resp) {
+ /* if we reach here, we didn't send any information responses yet */
+ DEBUGP("Calling cmd->cb()\n");
+ cmd->resp = buf;
+ rc = cmd->cb(cmd, cmd->ctx, buf);
+ }
+ }
+
+ if (final) {
+ /* remove from list of currently executing cmds */
+ llist_del(&cmd->list);
+ talloc_free(cmd);
+
+ /* if we're finished with current commands, but still have pending
+ * commands: we want to WRITE again */
+ if (llist_empty(&g->busy_atcmds) && !llist_empty(&g->pending_atcmds))
+ g->gfd_uart.when |= GSMD_FD_WRITE;
+ }
+
+ return rc;
+}
+
+/* callback to be called if [virtual] UART has some data for us */
+static int atcmd_select_cb(int fd, unsigned int what, void *data)
+{
+ int len, rc;
+ static char rxbuf[1024];
+ struct gsmd *g = data;
+
+ if (what & GSMD_FD_READ) {
+ memset(rxbuf, 0, sizeof(rxbuf));
+ while ((len = read(fd, rxbuf, sizeof(rxbuf)))) {
+ if (len < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ gsmd_log(GSMD_NOTICE, "ERROR reading from fd %u: %d (%s)\n", fd, len,
+ strerror(errno));
+ return len;
+ }
+ rc = llparse_string(&g->llp, rxbuf, len);
+ if (rc < 0) {
+ gsmd_log(GSMD_ERROR, "ERROR during llparse_string: %d\n", rc);
+ return rc;
+ }
+ }
+ }
+
+ /* write pending commands to UART */
+ if (what & GSMD_FD_WRITE) {
+ struct gsmd_atcmd *pos, *pos2;
+ llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) {
+ len = strlen(pos->buf);
+ rc = write(fd, pos->buf, strlen(pos->buf));
+ if (rc == 0) {
+ gsmd_log(GSMD_ERROR, "write returns 0, aborting\n");
+ break;
+ } else if (rc < 0) {
+ gsmd_log(GSMD_ERROR, "error during write to fd %d: %d\n",
+ fd, rc);
+ return rc;
+ }
+ if (rc < len) {
+ gsmd_log(GSMD_FATAL, "short write!!! FIXME!\n");
+ exit(3);
+ }
+ write(fd, "\r", 1);
+ /* success: remove from global list of to-be-sent atcmds */
+ llist_del(&pos->list);
+ /* append to global list of executing atcmds */
+ llist_add_tail(&pos->list, &g->busy_atcmds);
+
+ /* we only send one cmd at the moment */
+ g->gfd_uart.when &= ~GSMD_FD_WRITE;
+ break;
+ }
+ }
+
+#if 0
+ if (llist_empty(&g->pending_atcmds))
+ g->gfd_uart.when &= ~GSMD_FD_WRITE;
+#endif
+
+
+ return 0;
+}
+
+
+struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen,
+ atcmd_cb_t cb, void *ctx, u_int16_t id)
+{
+ int buflen = strlen(cmd);
+ struct gsmd_atcmd *atcmd;
+
+ if (rlen > buflen)
+ buflen = rlen;
+
+ atcmd = talloc_size(__atcmd_ctx, sizeof(*atcmd)+ buflen);
+ if (!atcmd)
+ return NULL;
+
+ atcmd->ctx = ctx;
+ atcmd->id = id;
+ atcmd->flags = 0;
+ atcmd->ret = -255;
+ atcmd->buflen = buflen;
+ atcmd->buf[buflen-1] = '\0';
+ atcmd->cb = cb;
+ atcmd->resp = NULL;
+ strncpy(atcmd->buf, cmd, buflen-1);
+
+ return atcmd;
+}
+
+/* submit an atcmd in the global queue of pending atcmds */
+int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd)
+{
+ DEBUGP("submitting command `%s'\n", cmd->buf);
+
+ llist_add_tail(&cmd->list, &g->pending_atcmds);
+ g->gfd_uart.when |= GSMD_FD_WRITE;
+
+ return 0;
+}
+
+void atcmd_drain(int fd)
+{
+ int rc;
+ struct termios t;
+ rc = tcflush(fd, TCIOFLUSH);
+ rc = tcgetattr(fd, &t);
+ DEBUGP("c_iflag = 0x%08x, c_oflag = 0x%08x, c_cflag = 0x%08x, c_lflag = 0x%08x\n",
+ t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag);
+ t.c_iflag = t.c_oflag = 0;
+ cfmakeraw(&t);
+ rc = tcsetattr(fd, TCSANOW, &t);
+}
+
+/* init atcmd parser */
+int atcmd_init(struct gsmd *g, int sockfd)
+{
+ __atcmd_ctx = talloc_named_const(gsmd_tallocs, 1, "atcmds");
+
+ g->gfd_uart.fd = sockfd;
+ g->gfd_uart.when = GSMD_FD_READ;
+ g->gfd_uart.data = g;
+ g->gfd_uart.cb = &atcmd_select_cb;
+
+ INIT_LLIST_HEAD(&g->pending_atcmds);
+ INIT_LLIST_HEAD(&g->busy_atcmds);
+
+ llparse_init (&g->llp);
+
+ g->llp.cur = g->llp.buf;
+ g->llp.len = sizeof(g->llp.buf);
+ g->llp.cb = &ml_parse;
+ g->llp.ctx = g;
+ g->llp.flags = LGSM_ATCMD_F_EXTENDED;
+
+ return gsmd_register_fd(&g->gfd_uart);
+}
+
Added: developers/seanchiang/gsm/src/gsmd/ext_response.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/ext_response.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/ext_response.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,213 @@
+/* gsmd extended response parser
+ *
+ * (C) 2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#include "gsmd.h"
+
+#include <gsmd/gsmd.h>
+#include <gsmd/atcmd.h>
+#include <gsmd/extrsp.h>
+#include <gsmd/talloc.h>
+
+int extrsp_supports(const struct gsm_extrsp *er, int index, int value)
+{
+ int i;
+
+ if (index >= er->num_tokens)
+ return -EINVAL;
+ if (er->tokens[index].type != GSMD_ECMD_RTT_RANGE)
+ return -EINVAL;
+
+ for (i = 0; i < er->tokens[index].u.range.num_items; i++) {
+ struct gsm_extrsp_range_item *ri =
+ &er->tokens[index].u.range.item[i];
+ if (value >= ri->min && value <= ri->max)
+ return 1;
+ }
+
+ return 0;
+}
+
+enum parser_state {
+ IDLE,
+ TOKEN_STRING,
+ TOKEN_STRING_LASTQUOTE,
+ TOKEN_NUMERIC,
+ TOKEN_RANGE,
+};
+
+/* parse a comma-separated list, possibly containing quote values */
+struct gsm_extrsp *extrsp_parse(const void *ctx, const char *input)
+{
+ const char *cur = input;
+ struct gsm_extrsp *er;
+ int cur_tok = 0;
+ enum parser_state state = IDLE;
+ char buf[512];
+ char *cur_buf = buf;
+ struct gsm_extrsp_tok *cur_token;
+
+ if (!input || strlen(input) == 0)
+ return NULL;
+
+ er = talloc(ctx, struct gsm_extrsp);
+ if (!er)
+ return NULL;
+ memset(er, 0, sizeof(*er));
+
+ while (*cur) {
+ cur_token = &er->tokens[er->num_tokens];
+
+ switch (state) {
+ case IDLE:
+ memset(buf, 0, sizeof(buf));
+ cur_buf = buf;
+
+ if (isblank(*cur))
+ break;
+ else if (*cur == '"') {
+ cur_token->type = GSMD_ECMD_RTT_STRING;
+ state = TOKEN_STRING;
+ } else if (*cur == '(') {
+ cur_token->type = GSMD_ECMD_RTT_RANGE;
+ state = TOKEN_RANGE;
+ } else if (isdigit(*cur)) {
+ cur_token->type = GSMD_ECMD_RTT_NUMERIC;
+ *cur_buf = *cur;
+ cur_buf++;
+ state = TOKEN_NUMERIC;
+ } else if (*cur == ',') {
+ cur_token->type = GSMD_ECMD_RTT_EMPTY;
+ er->num_tokens++;
+ state = IDLE;
+ }
+ break;
+ case TOKEN_NUMERIC:
+ if (*cur == ',') {
+ /* end of number */
+ cur_token->u.numeric = atoi(buf);
+ er->num_tokens++;
+ state = IDLE;
+ } else if (isdigit(*cur)) {
+ *cur_buf = *cur;
+ cur_buf++;
+ } else {
+ /* ERORR */
+ }
+ break;
+ case TOKEN_STRING:
+ if (*cur == '"') {
+ int len = strlen(buf);
+ if (len > sizeof(cur_token->u.string)-1)
+ len = sizeof(cur_token->u.string)-1;
+
+ /* end of string token */
+ strncpy(cur_token->u.string, buf, len);
+ er->num_tokens++;
+ state = TOKEN_STRING_LASTQUOTE;
+ } else {
+ *cur_buf = *cur;
+ cur_buf++;
+ }
+ break;
+ case TOKEN_STRING_LASTQUOTE:
+ if (*cur == ',')
+ state = IDLE;
+ else {
+ /* ERROR */
+ }
+ break;
+ case TOKEN_RANGE:
+ if (isdigit(*cur)) {
+ *cur_buf = *cur;
+ cur_buf++;
+ } else if (*cur == '-') {
+ /* previous number has completed */
+ cur_token->u.range.item[cur_token->u.range.num_items].min = atoi(buf);
+ memset(buf, 0, sizeof(buf));
+ cur_buf = buf;
+ } else if (*cur == ',') {
+ /* previous number has completed */
+ cur_token->u.range.item[cur_token->u.range.num_items].max = atoi(buf);
+ cur_token->u.range.num_items++;
+ } else if (*cur == ')') {
+ /* previous number has completed */
+ cur_token->u.range.item[cur_token->u.range.num_items].max = atoi(buf);
+ cur_token->u.range.num_items++;
+ state = TOKEN_STRING_LASTQUOTE;
+ er->num_tokens++;
+ } else {
+ /* ERROR */
+ }
+ break;
+ }
+ cur++;
+ }
+
+ //extrsp_dump(er);
+ return er;
+}
+
+static const char *er_tok_names[] = {
+ [GSMD_ECMD_RTT_EMPTY] = "EMPTY",
+ [GSMD_ECMD_RTT_NUMERIC] = "NUMERIC",
+ [GSMD_ECMD_RTT_STRING] = "STRING",
+ [GSMD_ECMD_RTT_RANGE] = "RANGE",
+};
+
+void extrsp_dump(const struct gsm_extrsp *er)
+{
+ int i;
+
+ DEBUGP("entering(er=%p, num_tokens=%u)\n", er, er->num_tokens);
+ for (i = 0; i < er->num_tokens; i++) {
+ const struct gsm_extrsp_tok *tok = &er->tokens[i];
+ DEBUGP("Token %u: %s: ", i, er_tok_names[tok->type]);
+ switch (tok->type) {
+ case GSMD_ECMD_RTT_EMPTY:
+ DEBUGP("\n");
+ break;
+ case GSMD_ECMD_RTT_NUMERIC:
+ DEBUGP("%d\n", tok->u.numeric);
+ break;
+ case GSMD_ECMD_RTT_STRING:
+ DEBUGP("%s\n", tok->u.string);
+ break;
+ case GSMD_ECMD_RTT_RANGE: {
+ int j;
+ for (j = 0; j < tok->u.range.num_items; j++)
+ DEBUGP("%d-%d, ", tok->u.range.item[j].min,
+ tok->u.range.item[j].max);
+ }
+
+ break;
+ }
+ }
+
+}
Added: developers/seanchiang/gsm/src/gsmd/gsmd.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/gsmd.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/gsmd.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,307 @@
+/* gsmd core
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <signal.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "gsmd.h"
+
+#include <gsmd/gsmd.h>
+#include <gsmd/atcmd.h>
+#include <gsmd/select.h>
+#include <gsmd/usock.h>
+#include <gsmd/vendorplugin.h>
+#include <gsmd/talloc.h>
+
+static int gsmd_test_atcb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ printf("`%s' returned `%s'\n", cmd->buf, resp);
+ return 0;
+}
+
+int gsmd_simplecmd(struct gsmd *gsmd, char *cmdtxt)
+{
+ struct gsmd_atcmd *cmd;
+ cmd = atcmd_fill(cmdtxt, strlen(cmdtxt)+1, &gsmd_test_atcb, NULL, 0);
+ if (!cmd)
+ return -ENOMEM;
+
+ return atcmd_submit(gsmd, cmd);
+}
+
+int gsmd_initsettings(struct gsmd *gsmd)
+{
+ int rc;
+
+ /* echo on, verbose */
+ rc |= gsmd_simplecmd(gsmd, "ATE0V1");
+ /* use +CRING instead of RING */
+ rc |= gsmd_simplecmd(gsmd, "AT+CRC=1");
+ /* enable +CREG: unsolicited response if registration status changes */
+ rc |= gsmd_simplecmd(gsmd, "AT+CREG=2");
+ /* use +CME ERROR: instead of ERROR */
+ rc |= gsmd_simplecmd(gsmd, "AT+CMEE=1");
+ /* use +CLIP: to indicate CLIP */
+ rc |= gsmd_simplecmd(gsmd, "AT+CLIP=1");
+ /* use +COLP: to indicate COLP */
+ rc |= gsmd_simplecmd(gsmd, "AT+COLP=1");
+ /* power on the phone */
+ rc |= gsmd_simplecmd(gsmd, "AT+CFUN=1");
+ /* configure message format as PDU mode*/
+ /* FIXME: TEXT mode support!! */
+ rc |= gsmd_simplecmd(gsmd, "AT+CMGF=0");
+
+ if (gsmd->vendorpl && gsmd->vendorpl->initsettings)
+ return gsmd->vendorpl->initsettings(gsmd);
+ else
+ return rc;
+}
+
+struct bdrt {
+ int bps;
+ u_int32_t b;
+};
+
+static struct bdrt bdrts[] = {
+ { 0, B0 },
+ { 9600, B9600 },
+ { 19200, B19200 },
+ { 38400, B38400 },
+ { 57600, B57600 },
+ { 115200, B115200 },
+};
+
+static int set_baudrate(int fd, int baudrate, int hwflow)
+{
+ int i;
+ u_int32_t bd = 0;
+ struct termios ti;
+
+ for (i = 0; i < ARRAY_SIZE(bdrts); i++) {
+ if (bdrts[i].bps == baudrate)
+ bd = bdrts[i].b;
+ }
+ if (bd == 0)
+ return -EINVAL;
+
+ i = tcgetattr(fd, &ti);
+ if (i < 0)
+ return i;
+
+ i = cfsetispeed(&ti, B0);
+ if (i < 0)
+ return i;
+
+ i = cfsetospeed(&ti, bd);
+ if (i < 0)
+ return i;
+
+ if (hwflow)
+ ti.c_cflag |= CRTSCTS;
+ else
+ ti.c_cflag &= ~CRTSCTS;
+
+ return tcsetattr(fd, 0, &ti);
+}
+
+
+static struct gsmd g;
+
+static int gsmd_initialize(struct gsmd *g)
+{
+ INIT_LLIST_HEAD(&g->users);
+
+ return 0;
+}
+
+static struct option opts[] = {
+ { "version", 0, NULL, 'V' },
+ { "daemon", 0, NULL, 'd' },
+ { "help", 0, NULL, 'h' },
+ { "device", 1, NULL, 'p' },
+ { "speed", 1, NULL, 's' },
+ { "logfile", 1, NULL, 'l' },
+ { "hwflow", 0, NULL, 'F' },
+ { "leak-report", 0, NULL, 'L' },
+ { 0, 0, 0, 0 }
+};
+
+static void print_help(void)
+{
+ printf("gsmd - (C) 2006 by Harald Welte <laforge at gnumonks.org>\n"
+ "This program is FREE SOFTWARE under the terms of GNU GPL\n\n"
+ "Usage:\n"
+ "\t-v\t--version\tDisplay program version\n"
+ "\t-d\t--daemon\tDeamonize\n"
+ "\t-h\t--help\t\tDisplay this help message\n"
+ "\t-p dev\t--device dev\tSpecify serial device to be used\n"
+ "\t-s spd\t--speed spd\tSpecify speed in bps (9600,38400,115200,...)\n"
+ "\t-F\t--hwflow\tHardware Flow Control (RTS/CTS)\n"
+ "\t-L\t--leak-report\tLeak Report of talloc memory allocator\n"
+ "\t-l file\t--logfile file\tSpecify a logfile to log to\n"
+ );
+}
+
+static void sig_handler(int signr)
+{
+ switch (signr) {
+ case SIGTERM:
+ case SIGINT:
+ talloc_report_full(gsmd_tallocs, stderr);
+ exit(0);
+ break;
+ case SIGUSR1:
+ talloc_report_full(gsmd_tallocs, stderr);
+ break;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int fd, argch;
+
+ int daemonize = 0;
+ int bps = 115200;
+ int hwflow = 0;
+ char *device = "/dev/ttyUSB0";
+ char *logfile = "syslog";
+
+ signal(SIGTERM, sig_handler);
+ signal(SIGINT, sig_handler);
+ signal(SIGSEGV, sig_handler);
+ signal(SIGUSR1, sig_handler);
+
+ gsmd_tallocs = talloc_named_const(NULL, 1, "GSMD");
+
+ /*FIXME: parse commandline, set daemonize, device, ... */
+ while ((argch = getopt_long(argc, argv, "FVLdhp:s:l:", opts, NULL)) != -1) {
+ switch (argch) {
+ case 'V':
+ /* FIXME */
+ break;
+ case 'L':
+ talloc_enable_leak_report_full();
+ break;
+ case 'F':
+ hwflow = 1;
+ break;
+ case 'd':
+ daemonize = 1;
+ break;
+ case 'h':
+ /* FIXME */
+ print_help();
+ exit(0);
+ break;
+ case 'p':
+ device = optarg;
+ break;
+ case 's':
+ bps = atoi(optarg);
+ break;
+ case 'l':
+ if (gsmdlog_init(optarg)) {
+ fprintf(stderr, "can't open logfile `%s'\n", optarg);
+ exit(2);
+ }
+ break;
+ }
+ }
+
+ /* use direct access to device node ([virtual] tty device) */
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "can't open device `%s': %s\n",
+ device, strerror(errno));
+ exit(1);
+ }
+
+ if (set_baudrate(fd, bps, hwflow) < 0) {
+ fprintf(stderr, "can't set baudrate\n");
+ exit(1);
+ }
+
+ if (gsmd_initialize(&g) < 0) {
+ fprintf(stderr, "internal error\n");
+ exit(1);
+ }
+
+ if (atcmd_init(&g, fd) < 0) {
+ fprintf(stderr, "can't initialize UART device\n");
+ exit(1);
+ }
+ atcmd_drain(fd);
+
+ if (usock_init(&g) < 0) {
+ fprintf(stderr, "can't open unix socket\n");
+ exit(1);
+ }
+
+ if (daemonize) {
+ if (fork()) {
+ exit(0);
+ }
+ fclose(stdout);
+ fclose(stderr);
+ fclose(stdin);
+ setsid();
+ }
+
+ /* FIXME: do this dynamically */
+ ticalypso_init();
+
+ gsmd_vendor_plugin_find(&g);
+
+ gsmd_initsettings(&g);
+
+ gsmd_opname_init(&g);
+
+ while (1) {
+ int ret = gsmd_select_main();
+ if (ret == 0)
+ continue;
+
+ if (ret < 0) {
+ if (errno == -EINTR)
+ continue;
+ else {
+ DEBUGP("select returned error (%s)\n",
+ strerror(errno));
+ break;
+ }
+ }
+ }
+
+ exit(0);
+}
Added: developers/seanchiang/gsm/src/gsmd/gsmd.h
===================================================================
--- developers/seanchiang/gsm/src/gsmd/gsmd.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/gsmd.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,3 @@
+#ifndef __GSMD__
+#define __GSMD__
+#endif
Added: developers/seanchiang/gsm/src/gsmd/gsmd_event.h
===================================================================
--- developers/seanchiang/gsm/src/gsmd/gsmd_event.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/gsmd_event.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,53 @@
+#ifndef __GSMD_EVENT_H
+#define __GSMD_EVENT_H
+
+/* event handling */
+
+enum gsmd_event_type {
+ GSMD_EVTTYPE_NONE,
+ GSMD_EVTTYPE_VOICECALL,
+ GSMD_EVTTYPE_DATACALL,
+ GSMD_EVTTYPE_SMS,
+ GSMD_EVTTYPE_GPRS,
+ GSMD_EVTTYPE_CIPHER_IND,
+};
+
+enum gsmd_event_call {
+ GSMD_EVT_CALL_NONE,
+ GSMD_EVT_CALL_HANGUP, /* any call: hanged up */
+ GSMD_EVT_CALL_RING, /* incoming call: we're ringing */
+ GSMD_EVT_CALL_BUSY, /* outgoing call: busy */
+ GSMD_EVT_CALL_RINGING, /* outgoing call: other end ringing */
+ GSMD_EVT_CALL_ESTABLISHED, /* any call: now established */
+};
+
+enum gsmd_event_voice {
+ /* all of event_call */
+};
+
+enum gsmd_event_data {
+ /* all of event_call */
+};
+
+enum gsmd_event_sms {
+ GSMD_EVT_SMS_NONE,
+ GSMD_EVT_SMS_RCVD, /* incoming SMS received */
+ GSMD_EVT_SMS_OVERFLOW, /* sms memory full, can't receive */
+};
+
+enum gsmd_event_gprs {
+};
+
+enum gsmd_event_cipher {
+ GSMD_EVT_CI_NONE,
+ GSMD_EVT_CI_ENABLED, /* cipher enabled */
+ GSMD_EVT_CI_DISABLED, /* cipher disabled */
+};
+
+enum gsmd_event_network {
+ GSMD_EVT_NW_NONE,
+ GSMD_EVT_NW_SIGNAL, /* signal strength */
+ GSMD_EVT_NW_REG, /* network registration */
+};
+
+#endif
Added: developers/seanchiang/gsm/src/gsmd/log.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/log.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/log.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,109 @@
+/* gsmd logging functions
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <time.h>
+
+#include <sys/types.h>
+
+#include "gsmd.h"
+
+#include <gsmd/gsmd.h>
+
+static FILE *logfile;
+static FILE syslog_dummy;
+static int loglevel;
+
+static int gsmd2syslog[] = {
+ [GSMD_DEBUG] = LOG_DEBUG,
+ [GSMD_INFO] = LOG_INFO,
+ [GSMD_NOTICE] = LOG_NOTICE,
+ [GSMD_ERROR] = LOG_ERR,
+ [GSMD_FATAL] = LOG_CRIT,
+};
+
+static inline int gsmd2syslog_level(int level)
+{
+ if (level >= ARRAY_SIZE(gsmd2syslog))
+ return LOG_ERR;
+
+ return gsmd2syslog[level];
+}
+
+void __gsmd_log(int level, const char *file, int line, const char *function,
+ const char *format, ...)
+{
+ char *timestr;
+ va_list ap;
+ time_t tm;
+ FILE *outfd;
+
+ if (level < loglevel)
+ return;
+
+ if (logfile == &syslog_dummy) {
+ va_start(ap, format);
+ vsyslog(gsmd2syslog_level(level), format, ap);
+ va_end(ap);
+ } else {
+ if (logfile)
+ outfd = logfile;
+ else
+ outfd = stderr;
+
+ tm = time(NULL);
+ timestr = ctime(&tm);
+ timestr[strlen(timestr)-1] = '\0';
+ fprintf(outfd, "%s <%1.1d> %s:%d:%s() ", timestr, level, file,
+ line, function);
+
+ va_start(ap, format);
+ vfprintf(outfd, format, ap);
+ va_end(ap);
+
+ fflush(outfd);
+ }
+}
+
+int gsmdlog_init(const char *path)
+{
+
+ if (!strcmp(path, "syslog")) {
+ logfile = &syslog_dummy;
+ openlog("gsmd", 0, LOG_DAEMON);
+ } else {
+ logfile = fopen(path, "a+");
+ }
+
+ if (logfile == NULL)
+ return -1;
+
+ gsmd_log(LOG_INFO, "logfile successfully opened\n");
+
+ return 0;
+}
Added: developers/seanchiang/gsm/src/gsmd/operator_cache.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/operator_cache.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/operator_cache.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,99 @@
+/* gsmd cache of operator names
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "gsmd.h"
+
+#include <common/linux_list.h>
+#include <gsmd/gsmd.h>
+#include <gsmd/talloc.h>
+
+static void *__opc_ctx;
+
+struct opname {
+ struct llist_head list;
+ struct {
+ u_int16_t mcc; /* mobile country code */
+ u_int8_t mnc; /* mobile network code */
+ } numeric;
+ char alnum_long[16+1];
+ //char alnum_short[8+1];
+};
+
+/* add an entry to the operator name list, overwrite existing entries for
+ * same mcc/mnc */
+static int _opname_add(struct gsmd *g, struct opname *op)
+{
+ struct opname *cur, *cur2;
+
+ llist_for_each_entry_safe(cur, cur2, &g->operators, list) {
+ if (op->numeric.mcc == cur->numeric.mcc &&
+ op->numeric.mnc == cur->numeric.mnc) {
+ llist_del(&cur->list);
+ talloc_free(cur);
+ }
+ }
+ llist_add_tail(&op->list, &g->operators);
+
+ return 0;
+}
+
+int gsmd_opname_add(struct gsmd *g, const char *numeric_bcd_string,
+ const char *alnum_long)
+{
+ struct opname *op;
+ char mcc[3+1];
+ char mnc[2+1];
+
+ if (strlen(numeric_bcd_string) != 5)
+ return -EINVAL;
+
+ op = talloc(__opc_ctx, struct opname);
+ if (!op)
+ return -ENOMEM;
+
+ memset(mcc, 0, sizeof(mcc));
+ memset(mnc, 0, sizeof(mnc));
+
+ strncpy(mcc, numeric_bcd_string, 3);
+ strncpy(mnc, numeric_bcd_string+3, 2);
+
+ strncpy(op->alnum_long, alnum_long, sizeof(op->alnum_long-1));
+ op->numeric.mcc = atoi(mcc);
+ op->numeric.mnc = atoi(mnc);
+
+ return _opname_add(g, op);
+}
+
+int gsmd_opname_init(struct gsmd *g)
+{
+ INIT_LLIST_HEAD(&g->operators);
+
+ __opc_ctx = talloc_named_const(gsmd_tallocs, 1, "operator_cache");
+
+ return 0;
+}
Added: developers/seanchiang/gsm/src/gsmd/select.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/select.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/select.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,101 @@
+/* select() FD handling for GSM Daemon.
+ * (C) 2000-2006 by Harald Welte <laforge at gnumonks.org>
+ *
+ * Based on code originally written by myself for ulogd.
+ *
+ * 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.
+ *
+ */
+
+#include <fcntl.h>
+#include <common/linux_list.h>
+
+#include "gsmd.h"
+
+#include <gsmd/select.h>
+
+static int maxfd = 0;
+static LLIST_HEAD(gsmd_fds);
+
+int gsmd_register_fd(struct gsmd_fd *fd)
+{
+ int flags;
+
+ /* make FD nonblocking */
+ flags = fcntl(fd->fd, F_GETFL);
+ if (flags < 0)
+ return -1;
+ flags |= O_NONBLOCK;
+ flags = fcntl(fd->fd, F_SETFL, flags);
+ if (flags < 0)
+ return -1;
+
+ /* Register FD */
+ if (fd->fd > maxfd)
+ maxfd = fd->fd;
+
+ llist_add_tail(&fd->list, &gsmd_fds);
+
+ return 0;
+}
+
+void gsmd_unregister_fd(struct gsmd_fd *fd)
+{
+ llist_del(&fd->list);
+}
+
+int gsmd_select_main()
+{
+ struct gsmd_fd *ufd, *ufd2;
+ fd_set readset, writeset, exceptset;
+ int i;
+
+ FD_ZERO(&readset);
+ FD_ZERO(&writeset);
+ FD_ZERO(&exceptset);
+
+ /* prepare read and write fdsets */
+ llist_for_each_entry(ufd, &gsmd_fds, list) {
+ if (ufd->when & GSMD_FD_READ)
+ FD_SET(ufd->fd, &readset);
+
+ if (ufd->when & GSMD_FD_WRITE)
+ FD_SET(ufd->fd, &writeset);
+
+ if (ufd->when & GSMD_FD_EXCEPT)
+ FD_SET(ufd->fd, &exceptset);
+ }
+
+ i = select(maxfd+1, &readset, &writeset, &exceptset, NULL);
+ if (i > 0) {
+ /* call registered callback functions */
+ llist_for_each_entry_safe(ufd, ufd2, &gsmd_fds, list) {
+ int flags = 0;
+
+ if (FD_ISSET(ufd->fd, &readset))
+ flags |= GSMD_FD_READ;
+
+ if (FD_ISSET(ufd->fd, &writeset))
+ flags |= GSMD_FD_WRITE;
+
+ if (FD_ISSET(ufd->fd, &exceptset))
+ flags |= GSMD_FD_EXCEPT;
+
+ if (flags)
+ ufd->cb(ufd->fd, flags, ufd->data);
+ }
+ }
+ return i;
+}
Added: developers/seanchiang/gsm/src/gsmd/sms_cb.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/sms_cb.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/sms_cb.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,203 @@
+/* gsmd SMS functions
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "gsmd.h"
+
+#include <gsmd/gsmd.h>
+#include <gsmd/usock.h>
+#include <gsmd/select.h>
+#include <gsmd/atcmd.h>
+#include <gsmd/usock.h>
+
+enum ts0705_mem_type {
+ GSM0705_MEMTYPE_NONE,
+ GSM0705_MEMTYPE_BROADCAST,
+ GSM0705_MEMTYPE_BROADCAST,
+ GSM0705_MEMTYPE_ME_MESSAGE,
+ GSM0705_MEMTYPE_MT,
+ GSM0705_MEMTYPE_SIM,
+ GSM0705_MEMTYPE_TA,
+ GSM0705_MEMTYPE_SR,
+};
+
+static const char *ts0705_memtype_name = {
+ [GSM0705_MEMTYPE_NONE] = "NONE",
+ [GSM0705_MEMTYPE_BROADCAST] = "BM",
+ [GSM0705_MEMTYPE_ME_MESSAGE] = "ME",
+ [GSM0705_MEMTYPE_MT] = "MT",
+ [GSM0705_MEMTYPE_SIM] = "SM",
+ [GSM0705_MEMTYPE_TA] = "TA",
+ [GSM0705_MEMTYPE_SR] = "SR",
+};
+
+static inline int parse_memtype(char *memtype)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ts0705_memtype_name); i++) {
+ if (!strcmp(ts0705_memtype_name[i], memtype))
+ return i;
+ }
+
+ return GSM0705_MEMTYPE_NONE;
+}
+
+struct __gsmd_sms_storage {
+ u_int8 memtype;
+ u_int8_t pad[3]
+ u_int16_t used;
+ u_int16_t total;
+} __attribute__ ((packed));
+
+struct gsmd_sms_storage {
+ struct __gsmd_sms_storage mem[3];
+} __attribute__ ((packed));
+
+static int usock_cpms_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd = ucmd_alloc(sizeof(struct gsmd_sms_storage));
+
+ DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu);
+
+ if (!ucmd)
+ return -ENOMEM;
+
+
+
+
+ ucmd->hdr.version = GSMD_PROTO_VERSION;
+ ucmd->hdr.msg_type = GSMD_MSG_SMS;
+ ucmd->hdr.msg_subtype = GSMD_SMS_GETMSG_STORAGE;
+ ucmd->hdr.len = ...;
+ ucmd->hdr.id = cmd->id;
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+/* main unix socket SMS receiver */
+static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ struct gsmd_atcmd *cmd;
+
+ switch (gph->msg_subtype) {
+ case GSMD_SMS_GET_SERVICE_CENTRE:
+
+ break;
+ case GSMD_SMS_SET_SERVICE_CENTRE:
+ break;
+ case GSMD_SMS_SET_MSG_STORAGE:
+ break;
+ case GSMD_SMS_GET_MSG_STORAGE:
+ cmd = atcmd_fill("AT+CPMS?", 8, ...);
+ break;
+ }
+
+ return atcmd_submit(gu->gsmd, cmd);
+}
+
+/* main unix socket Cell Broadcast receiver */
+static int usock_rcv_cb(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+
+ switch (gph->msg_subtype) {
+ case GSMD_CB_SUBSCRIBE:
+ break;
+ case GSMD_CB_UNSUBSCRIBE:
+ break;
+ }
+
+ return
+}
+
+
+/* Unsolicited messages related to SMS / CB */
+static int cmti_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+}
+
+static int cmt_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+}
+
+static int cbmi_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+}
+
+static int cbm_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+}
+
+static int cdsi_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+}
+
+static int cds_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+}
+
+
+static const struct gsmd_unsolocit gsm0705_unsolicit[] = {
+ { "+CMTI", &cmti_parse }, /* SMS Deliver Index (stored in ME/TA) */
+ { "+CMT", &cmt_parse }, /* SMS Deliver to TE */
+ { "+CBMI", &cbmi_parse }, /* Cell Broadcast Message Index */
+ { "+CBM", &cbm_parse }, /* Cell Broadcast Message */
+ { "+CDSI", &cdsi_parse }, /* SMS Status Report */
+ { "+CDS", &cds_parse }, /* SMS Status Index (stored in ME/TA) */
+};
+
+
+int sms_cb_init(struct gsmd *gsmd)
+{
+ struct gsmd_atcmd *atcmd;
+
+ atcmd = atcmd_fill("AT+CSMS=0", NULL, gu, 0);
+ if (!atcmd)
+ return -ENOMEM;
+ atcmd_submit(gsmd, atcmd);
+
+ /* Switch into "text mode" (Section 3.2.3) */
+ atcdm = atcmd_fill("AT+CMGF=1", 9, &sms_cb_init_cb, gu, 0);
+ if (!atcmd)
+ return -ENOMEM;
+
+ return atcmd_submit(gsmd, atcmd);
+}
Added: developers/seanchiang/gsm/src/gsmd/talloc.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/talloc.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/talloc.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,1133 @@
+/*
+ Samba Unix SMB/CIFS implementation.
+
+ Samba trivial allocation library - new interface
+
+ NOTE: Please read talloc_guide.txt for full documentation
+
+ Copyright (C) Andrew Tridgell 2004
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ inspired by http://swapped.cc/halloc/
+*/
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if 1
+/* nfsim additions */
+//#define HAVE_SYS_TYPES_H
+//#define HAVE_UNISTD_H
+#define HAVE_STDARG_H
+//#define HAVE_STDINT_H
+#define HAVE_VA_COPY
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include "gsmd.h"
+#include <gsmd/talloc.h>
+
+/* use this to force every realloc to change the pointer, to stress test
+ code that might not cope */
+#define ALWAYS_REALLOC 0
+
+
+#define MAX_TALLOC_SIZE 0x10000000
+#define TALLOC_MAGIC 0xe814ec4f
+#define TALLOC_MAGIC_FREE 0x7faebef3
+#define TALLOC_MAGIC_REFERENCE ((const char *)1)
+
+/* by default we abort when given a bad pointer (such as when talloc_free() is
+ * called on a pointer that came from malloc() */
+#ifndef TALLOC_ABORT
+#define TALLOC_ABORT(reason) abort()
+#endif
+
+#ifndef discard_const_p
+#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
+# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
+#else
+# define discard_const_p(type, ptr) ((type *)(ptr))
+#endif
+#endif
+
+/* this null_context is only used if talloc_enable_leak_report() or
+ talloc_enable_leak_report_full() is called, otherwise it remains
+ NULL
+*/
+static const void *null_context;
+static void *cleanup_context;
+
+
+struct talloc_reference_handle {
+ struct talloc_reference_handle *next, *prev;
+ void *ptr;
+};
+
+typedef int (*talloc_destructor_t)(void *);
+
+struct talloc_chunk {
+ struct talloc_chunk *next, *prev;
+ struct talloc_chunk *parent, *child;
+ struct talloc_reference_handle *refs;
+ size_t size;
+ talloc_destructor_t destructor;
+ const char *name;
+ union {
+ unsigned magic;
+ double align_dummy;
+ } u;
+};
+
+/* panic if we get a bad magic value */
+static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
+{
+ struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
+ if (tc->u.magic != TALLOC_MAGIC) {
+ if (tc->u.magic == TALLOC_MAGIC_FREE) {
+ TALLOC_ABORT("Bad talloc magic value - double free");
+ } else {
+ TALLOC_ABORT("Bad talloc magic value - unknown value");
+ }
+ }
+
+ return tc;
+}
+
+/* hook into the front of the list */
+#define _TLIST_ADD(list, p) \
+do { \
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ (list)->prev = (p); \
+ (p)->next = (list); \
+ (p)->prev = NULL; \
+ (list) = (p); \
+ }\
+} while (0)
+
+/* remove an element from a list - element doesn't have to be in list. */
+#define _TLIST_REMOVE(list, p) \
+do { \
+ if ((p) == (list)) { \
+ (list) = (p)->next; \
+ if (list) (list)->prev = NULL; \
+ } else { \
+ if ((p)->prev) (p)->prev->next = (p)->next; \
+ if ((p)->next) (p)->next->prev = (p)->prev; \
+ } \
+ if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
+} while (0)
+
+
+/*
+ return the parent chunk of a pointer
+*/
+static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ while (tc->prev) tc=tc->prev;
+ return tc->parent;
+}
+
+void *talloc_parent(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+ return (void *)(tc+1);
+}
+
+/*
+ Allocate a bit of memory as a child of an existing pointer
+*/
+void *_talloc(const void *context, size_t size)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL) {
+ context = null_context;
+ }
+
+ if (size >= MAX_TALLOC_SIZE) {
+ return NULL;
+ }
+
+ tc = malloc(sizeof(*tc)+size);
+ if (tc == NULL) return NULL;
+
+ tc->size = size;
+ tc->u.magic = TALLOC_MAGIC;
+ tc->destructor = NULL;
+ tc->child = NULL;
+ tc->name = NULL;
+ tc->refs = NULL;
+
+ if (context) {
+ struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
+
+ tc->parent = parent;
+
+ if (parent->child) {
+ parent->child->parent = NULL;
+ }
+
+ _TLIST_ADD(parent->child, tc);
+ } else {
+ tc->next = tc->prev = tc->parent = NULL;
+ }
+
+ return (void *)(tc+1);
+}
+
+
+/*
+ setup a destructor to be called on free of a pointer
+ the destructor should return 0 on success, or -1 on failure.
+ if the destructor fails then the free is failed, and the memory can
+ be continued to be used
+*/
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *))
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->destructor = destructor;
+}
+
+/*
+ increase the reference count on a piece of memory.
+*/
+void talloc_increase_ref_count(const void *ptr)
+{
+ talloc_reference(null_context, ptr);
+}
+
+/*
+ helper for talloc_reference()
+*/
+static int talloc_reference_destructor(void *ptr)
+{
+ struct talloc_reference_handle *handle = ptr;
+ struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr);
+ struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr);
+ if (tc1->destructor != (talloc_destructor_t)-1) {
+ tc1->destructor = NULL;
+ }
+ _TLIST_REMOVE(tc2->refs, handle);
+ talloc_free(handle);
+ return 0;
+}
+
+/*
+ make a secondary reference to a pointer, hanging off the given context.
+ the pointer remains valid until both the original caller and this given
+ context are freed.
+
+ the major use for this is when two different structures need to reference the
+ same underlying data, and you want to be able to free the two instances
+ separately, and in either order
+*/
+void *talloc_reference(const void *context, const void *ptr)
+{
+ struct talloc_chunk *tc;
+ struct talloc_reference_handle *handle;
+ if (ptr == NULL) return NULL;
+
+ tc = talloc_chunk_from_ptr(ptr);
+ handle = talloc_named_const(context, sizeof(*handle),
+ TALLOC_MAGIC_REFERENCE);
+
+ if (handle == NULL) return NULL;
+
+ /* note that we hang the destructor off the handle, not the
+ main context as that allows the caller to still setup their
+ own destructor on the context if they want to */
+ talloc_set_destructor(handle, talloc_reference_destructor);
+ handle->ptr = discard_const_p(void, ptr);
+ _TLIST_ADD(tc->refs, handle);
+ return handle->ptr;
+}
+
+/*
+ remove a secondary reference to a pointer. This undo's what
+ talloc_reference() has done. The context and pointer arguments
+ must match those given to a talloc_reference()
+*/
+static int talloc_unreference(const void *context, const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_reference_handle *h;
+
+ if (context == NULL) {
+ context = null_context;
+ }
+
+ for (h=tc->refs;h;h=h->next) {
+ struct talloc_chunk *p = talloc_parent_chunk(h);
+ if ((p==NULL && context==NULL) || p+1 == context) break;
+ }
+ if (h == NULL) {
+ return -1;
+ }
+
+ talloc_set_destructor(h, NULL);
+ _TLIST_REMOVE(tc->refs, h);
+ talloc_free(h);
+ return 0;
+}
+
+/*
+ remove a specific parent context from a pointer. This is a more
+ controlled varient of talloc_free()
+*/
+int talloc_unlink(const void *context, void *ptr)
+{
+ struct talloc_chunk *tc_p, *new_p;
+ void *new_parent;
+
+ if (ptr == NULL) {
+ return -1;
+ }
+
+ if (context == NULL) {
+ context = null_context;
+ }
+
+ if (talloc_unreference(context, ptr) == 0) {
+ return 0;
+ }
+
+ if (context == NULL) {
+ if (talloc_parent_chunk(ptr) != NULL) {
+ return -1;
+ }
+ } else {
+ if (talloc_chunk_from_ptr(context)
+ != talloc_parent_chunk(ptr)) {
+ return -1;
+ }
+ }
+
+ tc_p = talloc_chunk_from_ptr(ptr);
+
+ if (tc_p->refs == NULL) {
+ return talloc_free(ptr);
+ }
+
+ new_p = talloc_parent_chunk(tc_p->refs);
+ if (new_p) {
+ new_parent = new_p+1;
+ } else {
+ new_parent = NULL;
+ }
+
+ if (talloc_unreference(new_parent, ptr) != 0) {
+ return -1;
+ }
+
+ talloc_steal(new_parent, ptr);
+
+ return 0;
+}
+
+/*
+ add a name to an existing pointer - va_list version
+*/
+static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
+ PRINTF_ATTRIBUTE(2,0);
+
+static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->name = talloc_vasprintf(ptr, fmt, ap);
+ if (tc->name) {
+ talloc_set_name_const(tc->name, ".name");
+ }
+}
+
+/*
+ add a name to an existing pointer
+*/
+void talloc_set_name(const void *ptr, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ more efficient way to add a name to a pointer - the name must point to a
+ true string constant
+*/
+void talloc_set_name_const(const void *ptr, const char *name)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ tc->name = name;
+}
+
+/*
+ create a named talloc pointer. Any talloc pointer can be named, and
+ talloc_named() operates just like talloc() except that it allows you
+ to name the pointer.
+*/
+void *talloc_named(const void *context, size_t size, const char *fmt, ...)
+{
+ va_list ap;
+ void *ptr;
+
+ ptr = _talloc(context, size);
+ if (ptr == NULL) return NULL;
+
+ va_start(ap, fmt);
+ talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+
+ return ptr;
+}
+
+/*
+ create a named talloc pointer. Any talloc pointer can be named, and
+ talloc_named() operates just like talloc() except that it allows you
+ to name the pointer.
+*/
+void *talloc_named_const(const void *context, size_t size, const char *name)
+{
+ void *ptr;
+
+ ptr = _talloc(context, size);
+ if (ptr == NULL) {
+ return NULL;
+ }
+
+ talloc_set_name_const(ptr, name);
+
+ return ptr;
+}
+
+/*
+ return the name of a talloc ptr, or "UNNAMED"
+*/
+const char *talloc_get_name(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ if (tc->name == TALLOC_MAGIC_REFERENCE) {
+ return ".reference";
+ }
+ if (tc->name) {
+ return tc->name;
+ }
+ return "UNNAMED";
+}
+
+
+/*
+ check if a pointer has the given name. If it does, return the pointer,
+ otherwise return NULL
+*/
+void *talloc_check_name(const void *ptr, const char *name)
+{
+ const char *pname;
+ if (ptr == NULL) return NULL;
+ pname = talloc_get_name(ptr);
+ if (pname == name || strcmp(pname, name) == 0) {
+ return discard_const_p(void, ptr);
+ }
+ return NULL;
+}
+
+
+/*
+ this is for compatibility with older versions of talloc
+*/
+void *talloc_init(const char *fmt, ...)
+{
+ va_list ap;
+ void *ptr;
+
+ ptr = _talloc(NULL, 0);
+ if (ptr == NULL) return NULL;
+
+ va_start(ap, fmt);
+ talloc_set_name_v(ptr, fmt, ap);
+ va_end(ap);
+
+ return ptr;
+}
+
+/*
+ this is a replacement for the Samba3 talloc_destroy_pool functionality. It
+ should probably not be used in new code. It's in here to keep the talloc
+ code consistent across Samba 3 and 4.
+*/
+static void talloc_free_children(void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (ptr == NULL) {
+ return;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ while (tc->child) {
+ /* we need to work out who will own an abandoned child
+ if it cannot be freed. In priority order, the first
+ choice is owner of any remaining reference to this
+ pointer, the second choice is our parent, and the
+ final choice is the null context. */
+ void *child = tc->child+1;
+ const void *new_parent = null_context;
+ if (tc->child->refs) {
+ struct talloc_chunk *p =
+ talloc_parent_chunk(tc->child->refs);
+ if (p) new_parent = p+1;
+ }
+ if (talloc_free(child) == -1) {
+ if (new_parent == null_context) {
+ struct talloc_chunk *p =
+ talloc_parent_chunk(ptr);
+ if (p) new_parent = p+1;
+ }
+ talloc_steal(new_parent, child);
+ }
+ }
+}
+
+/*
+ free a talloc pointer. This also frees all child pointers of this
+ pointer recursively
+
+ return 0 if the memory is actually freed, otherwise -1. The memory
+ will not be freed if the ref_count is > 1 or the destructor (if
+ any) returns non-zero
+*/
+int talloc_free(void *ptr)
+{
+ struct talloc_chunk *tc;
+
+ if (ptr == NULL) {
+ return -1;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (tc->refs) {
+ talloc_reference_destructor(tc->refs);
+ return -1;
+ }
+
+ if (tc->destructor) {
+ talloc_destructor_t d = tc->destructor;
+ if (d == (talloc_destructor_t)-1) {
+ return -1;
+ }
+ tc->destructor = (talloc_destructor_t)-1;
+ if (d(ptr) == -1) {
+ tc->destructor = d;
+ return -1;
+ }
+ tc->destructor = NULL;
+ }
+
+ talloc_free_children(ptr);
+
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->u.magic = TALLOC_MAGIC_FREE;
+
+ free(tc);
+ return 0;
+}
+
+
+
+/*
+ A talloc version of realloc. The context argument is only used if
+ ptr is NULL
+*/
+void *_talloc_realloc(const void *context, void *ptr, size_t size,
+ const char *name)
+{
+ struct talloc_chunk *tc;
+ void *new_ptr;
+
+ /* size zero is equivalent to free() */
+ if (size == 0) {
+ talloc_free(ptr);
+ return NULL;
+ }
+
+ if (size >= MAX_TALLOC_SIZE) {
+ return NULL;
+ }
+
+ /* realloc(NULL) is equavalent to malloc() */
+ if (ptr == NULL) {
+ return talloc_named_const(context, size, name);
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ /* don't allow realloc on referenced pointers */
+ if (tc->refs) {
+ return NULL;
+ }
+
+ /* by resetting magic we catch users of the old memory */
+ tc->u.magic = TALLOC_MAGIC_FREE;
+
+#if ALWAYS_REALLOC
+ new_ptr = malloc(size + sizeof(*tc));
+ if (new_ptr) {
+ memcpy(new_ptr, tc, tc->size + sizeof(*tc));
+ free(tc);
+ }
+#else
+ new_ptr = realloc(tc, size + sizeof(*tc));
+#endif
+ if (!new_ptr) {
+ tc->u.magic = TALLOC_MAGIC;
+ return NULL;
+ }
+
+ tc = new_ptr;
+ tc->u.magic = TALLOC_MAGIC;
+ if (tc->parent) {
+ tc->parent->child = new_ptr;
+ }
+ if (tc->child) {
+ tc->child->parent = new_ptr;
+ }
+
+ if (tc->prev) {
+ tc->prev->next = tc;
+ }
+ if (tc->next) {
+ tc->next->prev = tc;
+ }
+
+ tc->size = size;
+ talloc_set_name_const(tc+1, name);
+
+ return (void *)(tc+1);
+}
+
+/*
+ move a lump of memory from one talloc context to another return the
+ ptr on success, or NULL if it could not be transferred.
+ passing NULL as ptr will always return NULL with no side effects.
+*/
+void *talloc_steal(const void *new_ctx, const void *ptr)
+{
+ struct talloc_chunk *tc, *new_tc;
+
+ if (!ptr) {
+ return NULL;
+ }
+
+ if (new_ctx == NULL) {
+ new_ctx = null_context;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ if (new_ctx == NULL) {
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->parent = tc->next = tc->prev = NULL;
+ return discard_const_p(void, ptr);
+ }
+
+ new_tc = talloc_chunk_from_ptr(new_ctx);
+
+ if (tc == new_tc) {
+ return discard_const_p(void, ptr);
+ }
+
+ if (tc->parent) {
+ _TLIST_REMOVE(tc->parent->child, tc);
+ if (tc->parent->child) {
+ tc->parent->child->parent = tc->parent;
+ }
+ } else {
+ if (tc->prev) tc->prev->next = tc->next;
+ if (tc->next) tc->next->prev = tc->prev;
+ }
+
+ tc->parent = new_tc;
+ if (new_tc->child) new_tc->child->parent = NULL;
+ _TLIST_ADD(new_tc->child, tc);
+
+ return discard_const_p(void, ptr);
+}
+
+/*
+ return the total size of a talloc pool (subtree)
+*/
+off_t talloc_total_size(const void *ptr)
+{
+ off_t total = 0;
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ total = tc->size;
+ for (c=tc->child;c;c=c->next) {
+ total += talloc_total_size(c+1);
+ }
+ return total;
+}
+
+/*
+ return the total number of blocks in a talloc pool (subtree)
+*/
+off_t talloc_total_blocks(const void *ptr)
+{
+ off_t total = 0;
+ struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+
+ total++;
+ for (c=tc->child;c;c=c->next) {
+ total += talloc_total_blocks(c+1);
+ }
+ return total;
+}
+
+/*
+ return the number of external references to a pointer
+*/
+static int talloc_reference_count(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ struct talloc_reference_handle *h;
+ int ret = 0;
+
+ for (h=tc->refs;h;h=h->next) {
+ ret++;
+ }
+ return ret;
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_depth(const void *ptr, FILE *f, int depth)
+{
+ struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+
+ for (c=tc->child;c;c=c->next) {
+ if (c->name == TALLOC_MAGIC_REFERENCE) {
+ struct talloc_reference_handle *handle = (void *)(c+1);
+ const char *name2 = talloc_get_name(handle->ptr);
+ fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
+ } else {
+ const char *name = talloc_get_name(c+1);
+ fprintf(f, "%*s%-30s contains %6lu bytes "
+ "in %3lu blocks (ref %d)\n",
+ depth * 4, "", name,
+ (unsigned long)talloc_total_size(c+1),
+ (unsigned long)talloc_total_blocks(c+1),
+ talloc_reference_count(c+1));
+ talloc_report_depth(c+1, f, depth+1);
+ }
+ }
+
+}
+
+/*
+ report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_full(const void *ptr, FILE *f)
+{
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) return;
+
+ fprintf(f, "full talloc report on '%s' "
+ "(total %lu bytes in %lu blocks)\n",
+ talloc_get_name(ptr),
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+
+ talloc_report_depth(ptr, f, 1);
+ fflush(f);
+}
+
+/*
+ report on memory usage by all children of a pointer
+*/
+void talloc_report(const void *ptr, FILE *f)
+{
+ struct talloc_chunk *c, *tc;
+
+ if (ptr == NULL) {
+ ptr = null_context;
+ }
+ if (ptr == NULL) return;
+
+ fprintf(f, "talloc report on '%s' (total %lu bytes in %lu blocks)\n",
+ talloc_get_name(ptr),
+ (unsigned long)talloc_total_size(ptr),
+ (unsigned long)talloc_total_blocks(ptr));
+
+ tc = talloc_chunk_from_ptr(ptr);
+
+ for (c=tc->child;c;c=c->next) {
+ fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
+ talloc_get_name(c+1),
+ (unsigned long)talloc_total_size(c+1),
+ (unsigned long)talloc_total_blocks(c+1));
+ }
+ fflush(f);
+}
+
+/*
+ report on any memory hanging off the null context
+*/
+static void talloc_report_null(void)
+{
+ if (talloc_total_size(null_context) != 0) {
+ talloc_report(null_context, stderr);
+ }
+}
+
+/*
+ report on any memory hanging off the null context
+*/
+static void talloc_report_null_full(void)
+{
+ if (talloc_total_size(null_context) != 0) {
+ talloc_report_full(null_context, stderr);
+ }
+}
+
+/*
+ enable tracking of the NULL context
+*/
+void talloc_enable_null_tracking(void)
+{
+ if (null_context == NULL) {
+ null_context = talloc_named_const(NULL, 0, "null_context");
+ }
+}
+
+/*
+ enable leak reporting on exit
+*/
+void talloc_enable_leak_report(void)
+{
+ talloc_enable_null_tracking();
+ atexit(talloc_report_null);
+}
+
+/*
+ enable full leak reporting on exit
+*/
+void talloc_enable_leak_report_full(void)
+{
+ talloc_enable_null_tracking();
+ atexit(talloc_report_null_full);
+}
+
+/*
+ talloc and zero memory.
+*/
+void *_talloc_zero(const void *ctx, size_t size, const char *name)
+{
+ void *p = talloc_named_const(ctx, size, name);
+
+ if (p) {
+ memset(p, '\0', size);
+ }
+
+ return p;
+}
+
+
+/*
+ memdup with a talloc.
+*/
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
+{
+ void *newp = talloc_named_const(t, size, name);
+
+ if (newp) {
+ memcpy(newp, p, size);
+ }
+
+ return newp;
+}
+
+/*
+ strdup with a talloc
+*/
+char *talloc_strdup(const void *t, const char *p)
+{
+ char *ret;
+ if (!p) {
+ return NULL;
+ }
+ ret = talloc_memdup(t, p, strlen(p) + 1);
+ if (ret) {
+ talloc_set_name_const(ret, ret);
+ }
+ return ret;
+}
+
+/*
+ strndup with a talloc
+*/
+char *talloc_strndup(const void *t, const char *p, size_t n)
+{
+ size_t len;
+ char *ret;
+
+ for (len=0; len<n && p[len]; len++) ;
+
+ ret = _talloc(t, len + 1);
+ if (!ret) { return NULL; }
+ memcpy(ret, p, len);
+ ret[len] = 0;
+ talloc_set_name_const(ret, ret);
+ return ret;
+}
+
+#ifndef VA_COPY
+#ifdef HAVE_VA_COPY
+#define VA_COPY(dest, src) va_copy(dest, src)
+#elif defined(HAVE___VA_COPY)
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#else
+#define VA_COPY(dest, src) (dest) = (src)
+#endif
+#endif
+
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
+{
+ int len;
+ char *ret;
+ va_list ap2;
+
+ VA_COPY(ap2, ap);
+
+ len = vsnprintf(NULL, 0, fmt, ap2);
+
+ ret = _talloc(t, len+1);
+ if (ret) {
+ VA_COPY(ap2, ap);
+ vsnprintf(ret, len+1, fmt, ap2);
+ talloc_set_name_const(ret, ret);
+ }
+
+ return ret;
+}
+
+
+/*
+ Perform string formatting, and return a pointer to newly allocated
+ memory holding the result, inside a memory pool.
+ */
+char *talloc_asprintf(const void *t, const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = talloc_vasprintf(t, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+
+/**
+ * Realloc @p s to append the formatted result of @p fmt and @p ap,
+ * and return @p s, which may have moved. Good for gradually
+ * accumulating output into a string buffer.
+ **/
+
+static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+ PRINTF_ATTRIBUTE(2,0);
+
+static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+{
+ struct talloc_chunk *tc;
+ int len, s_len;
+ va_list ap2;
+
+ if (s == NULL) {
+ return talloc_vasprintf(NULL, fmt, ap);
+ }
+
+ tc = talloc_chunk_from_ptr(s);
+
+ VA_COPY(ap2, ap);
+
+ s_len = tc->size - 1;
+ len = vsnprintf(NULL, 0, fmt, ap2);
+
+ s = talloc_realloc(NULL, s, char, s_len + len+1);
+ if (!s) return NULL;
+
+ VA_COPY(ap2, ap);
+
+ vsnprintf(s+s_len, len+1, fmt, ap2);
+ talloc_set_name_const(s, s);
+
+ return s;
+}
+
+/*
+ Realloc @p s to append the formatted result of @p fmt and return @p
+ s, which may have moved. Good for gradually accumulating output
+ into a string buffer.
+ */
+char *talloc_asprintf_append(char *s, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ s = talloc_vasprintf_append(s, fmt, ap);
+ va_end(ap);
+ return s;
+}
+
+/*
+ alloc an array, checking for integer overflow in the array size
+*/
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count,
+ const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return talloc_named_const(ctx, el_size * count, name);
+}
+
+/*
+ alloc an zero array, checking for integer overflow in the array size
+*/
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count,
+ const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return _talloc_zero(ctx, el_size * count, name);
+}
+
+
+/*
+ realloc an array, checking for integer overflow in the array size
+*/
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size,
+ unsigned count, const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+ return _talloc_realloc(ctx, ptr, el_size * count, name);
+}
+
+/*
+ a function version of talloc_realloc(), so it can be passed as a function
+ pointer to libraries that want a realloc function (a realloc function
+ encapsulates all the basic capabilities of an allocation library, which is
+ why this is useful)
+*/
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
+{
+ return _talloc_realloc(context, ptr, size, NULL);
+}
+
+
+static void talloc_autofree(void)
+{
+ talloc_free(cleanup_context);
+ cleanup_context = NULL;
+}
+
+/*
+ return a context which will be auto-freed on exit
+ this is useful for reducing the noise in leak reports
+*/
+void *talloc_autofree_context(void)
+{
+ if (cleanup_context == NULL) {
+ cleanup_context = talloc_named_const(NULL, 0,
+ "autofree_context");
+ atexit(talloc_autofree);
+ }
+ return cleanup_context;
+}
+
+size_t talloc_get_size(const void *context)
+{
+ struct talloc_chunk *tc;
+
+ if (context == NULL)
+ return 0;
+
+ tc = talloc_chunk_from_ptr(context);
+
+ return tc->size;
+}
Added: developers/seanchiang/gsm/src/gsmd/unsolicited.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/unsolicited.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/unsolicited.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,525 @@
+/* gsmd unsolicited message handling
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "gsmd.h"
+
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+#include <gsmd/extrsp.h>
+#include <gsmd/ts0707.h>
+#include <gsmd/unsolicited.h>
+#include <gsmd/talloc.h>
+
+struct gsmd_ucmd *usock_build_event(u_int8_t type, u_int8_t subtype, u_int8_t len)
+{
+ struct gsmd_ucmd *ucmd = ucmd_alloc(len);
+
+ if (!ucmd)
+ return NULL;
+
+ ucmd->hdr.version = GSMD_PROTO_VERSION;
+ ucmd->hdr.msg_type = type;
+ ucmd->hdr.msg_subtype = subtype;
+ ucmd->hdr.len = len;
+
+ return ucmd;
+}
+
+static struct gsmd_ucmd *ucmd_copy(const struct gsmd_ucmd *orig)
+{
+ struct gsmd_ucmd *copy = ucmd_alloc(orig->hdr.len);
+
+ if (copy)
+ memcpy(copy, orig, orig->hdr.len);
+
+ return copy;
+}
+
+int usock_evt_send(struct gsmd *gsmd, struct gsmd_ucmd *ucmd, u_int32_t evt)
+{
+ struct gsmd_user *gu;
+ int num_sent = 0;
+
+ DEBUGP("entering evt=%u\n", evt);
+
+ llist_for_each_entry(gu, &gsmd->users, list) {
+ if (gu->subscriptions & (1 << evt)) {
+ if (num_sent == 0)
+ usock_cmd_enqueue(ucmd, gu);
+ else {
+ struct gsmd_ucmd *cpy = ucmd_copy(ucmd);
+ if (!cpy) {
+ fprintf(stderr,
+ "can't allocate memory for "
+ "copy of ucmd\n");
+ return num_sent;
+ }
+ usock_cmd_enqueue(cpy, gu);
+ }
+ num_sent++;
+ }
+ }
+
+ if (num_sent == 0)
+ talloc_free(ucmd);
+
+ return num_sent;
+}
+
+static int ring_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ /* FIXME: generate ring event */
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CALL,
+ sizeof(struct gsmd_evt_auxdata));
+ struct gsmd_evt_auxdata *aux;
+ if (!ucmd)
+ return -ENOMEM;
+
+ aux = (struct gsmd_evt_auxdata *)ucmd->buf;
+
+ aux->u.call.type = GSMD_CALL_UNSPEC;
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CALL);
+}
+
+static int cring_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
+{
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CALL,
+ sizeof(struct gsmd_evt_auxdata));
+ struct gsmd_evt_auxdata *aux;
+ if (!ucmd)
+ return -ENOMEM;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ if (!strcmp(param, "VOICE")) {
+ /* incoming voice call */
+ aux->u.call.type = GSMD_CALL_VOICE;
+ } else if (!strcmp(param, "SYNC")) {
+ aux->u.call.type = GSMD_CALL_DATA_SYNC;
+ } else if (!strcmp(param, "REL ASYNC")) {
+ aux->u.call.type = GSMD_CALL_DATA_REL_ASYNC;
+ } else if (!strcmp(param, "REL SYNC")) {
+ aux->u.call.type = GSMD_CALL_DATA_REL_SYNC;
+ } else if (!strcmp(param, "FAX")) {
+ aux->u.call.type = GSMD_CALL_FAX;
+ } else if (!strncmp(param, "GPRS ", 5)) {
+ /* FIXME: change event type to GPRS */
+ talloc_free(ucmd);
+ return 0;
+ }
+ /* FIXME: parse all the ALT* profiles, Chapter 6.11 */
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CALL);
+}
+
+/* Chapter 7.2, network registration */
+static int creg_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ const char *comma = strchr(param, ',');
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_NETREG,
+ sizeof(struct gsmd_evt_auxdata));
+ struct gsmd_evt_auxdata *aux;
+ if (!ucmd)
+ return -ENOMEM;
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ aux->u.netreg.state = atoi(param);
+ if (comma) {
+ /* we also have location area code and cell id to parse (hex) */
+ aux->u.netreg.lac = strtoul(comma+2, NULL, 16);
+ comma = strchr(comma+1, ',');
+ if (!comma)
+ return -EINVAL;
+ aux->u.netreg.ci = strtoul(comma+2, NULL, 16);
+ }
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_NETREG);
+}
+
+/* Chapter 7.11, call waiting */
+static int ccwa_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ const char *token;
+ unsigned int type;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_CALL_WAIT,
+ sizeof(struct gsmd_addr));
+ struct gsmd_addr *gaddr;
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ gaddr = (struct gsmd_addr *) ucmd->buf;
+ memset(gaddr, 0, sizeof(*gaddr));
+
+ /* parse address (phone number) */
+ token = strtok(buf, ",");
+ if (!token)
+ return -EINVAL;
+ strncpy(gaddr->number, token, GSMD_ADDR_MAXLEN);
+
+ /* parse type */
+ token = strtok(NULL, ",");
+ if (!token)
+ return -EINVAL;
+ type = atoi(token) & 0xff;
+ gaddr->type = type;
+
+ /* FIXME: parse class */
+ token = strtok(NULL, ",");
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_CALL_WAIT);
+}
+
+/* Chapter 7.14, unstructured supplementary service data */
+static int cusd_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ /* FIXME: parse */
+ return 0;
+}
+
+/* Chapter 7.15, advise of charge */
+static int cccm_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ /* FIXME: parse */
+ return 0;
+}
+
+/* Chapter 10.1.13, GPRS event reporting */
+static int cgev_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ /* FIXME: parse */
+ return 0;
+}
+
+/* Chapter 10.1.14, GPRS network registration status */
+static int cgreg_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ /* FIXME: parse */
+ return 0;
+}
+
+/* Chapter 7.6, calling line identification presentation */
+static int clip_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CLIP,
+ sizeof(struct gsmd_evt_auxdata));
+ struct gsmd_evt_auxdata *aux;
+ const char *comma = strchr(param, ',');
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ if (!comma)
+ return -EINVAL;
+
+
+ if (comma - param > GSMD_ADDR_MAXLEN)
+ return -EINVAL;
+
+ memcpy(aux->u.clip.addr.number, param, comma-param);
+ /* FIXME: parse of subaddr, etc. */
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CLIP);
+}
+
+/* Chapter 7.9, calling line identification presentation */
+static int colp_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_OUT_COLP,
+ sizeof(struct gsmd_evt_auxdata));
+ struct gsmd_evt_auxdata *aux;
+ const char *comma = strchr(param, ',');
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ if (!comma)
+ return -EINVAL;
+
+ if (comma - param > GSMD_ADDR_MAXLEN)
+ return -EINVAL;
+
+ memcpy(aux->u.colp.addr.number, param, comma-param);
+ /* FIXME: parse of subaddr, etc. */
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_COLP);
+}
+
+static int ctzv_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_TIMEZONE,
+ sizeof(struct gsmd_evt_auxdata));
+ struct gsmd_evt_auxdata *aux;
+ int tz;
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ /* timezones are expressed in quarters of hours +/- GMT (-48...+48) */
+ tz = atoi(param);
+
+ if (tz < -48 || tz > 48)
+ return -EINVAL;
+
+ aux->u.timezone.tz = tz;
+
+ return usock_evt_send(gsmd, ucmd, GSMD_EVT_TIMEZONE);
+}
+
+static int copn_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ struct gsm_extrsp *er = extrsp_parse(gsmd_tallocs, param);
+ int rc = 0;
+
+ if (!er)
+ return -ENOMEM;
+
+ extrsp_dump(er);
+
+ if (er->num_tokens == 2 &&
+ er->tokens[0].type == GSMD_ECMD_RTT_STRING &&
+ er->tokens[1].type == GSMD_ECMD_RTT_STRING)
+ rc = gsmd_opname_add(gsmd, er->tokens[0].u.string,
+ er->tokens[1].u.string);
+
+ talloc_free(er);
+
+ return rc;
+}
+
+static const struct gsmd_unsolicit gsm0707_unsolicit[] = {
+ { "RING", &ring_parse },
+ { "+CRING", &cring_parse },
+ { "+CREG", &creg_parse }, /* Network registration */
+ { "+CCWA", &ccwa_parse }, /* Call waiting */
+ { "+CUSD", &cusd_parse }, /* Unstructured supplementary data */
+ { "+CCCM", &cccm_parse }, /* Advice of Charge */
+ { "+CGEV", &cgev_parse }, /* GPRS Event */
+ { "+CGREG", &cgreg_parse }, /* GPRS Registration */
+ { "+CLIP", &clip_parse },
+ { "+COLP", &colp_parse },
+ { "+CTZV", &ctzv_parse }, /* Timezone */
+ { "+COPN", &copn_parse }, /* operator names, treat as unsolicited */
+ /*
+ { "+CKEV", &ckev_parse },
+ { "+CDEV", &cdev_parse },
+ { "+CIEV", &ciev_parse },
+ { "+CLAV", &clav_parse },
+ { "+CCWV", &ccwv_parse },
+ { "+CLAV", &clav_parse },
+ { "+CSSU", &cssu_parse },
+ */
+};
+
+/* called by midlevel parser if a response seems unsolicited */
+int unsolicited_parse(struct gsmd *g, char *buf, int len, const char *param)
+{
+ int i, rc;
+ struct gsmd_vendor_plugin *vpl = g->vendorpl;
+
+ /* call vendor-specific unsolicited code parser */
+ if (vpl && vpl->num_unsolicit) {
+ for (i = 0; i < vpl->num_unsolicit; i++) {
+ const char *colon;
+ if (strncmp(buf, vpl->unsolicit[i].prefix,
+ strlen(vpl->unsolicit[i].prefix)))
+ continue;
+
+ colon = strchr(buf, ':') + 2;
+ if (colon > buf+len)
+ colon = NULL;
+
+ rc = vpl->unsolicit[i].parse(buf, len, colon, g);
+ if (rc < 0)
+ gsmd_log(GSMD_ERROR, "error %d during parse of "
+ "vendor unsolicied response `%s'\n",
+ rc, buf);
+ return rc;
+ }
+ }
+
+ /* call generic unsolicited code parser */
+ for (i = 0; i < ARRAY_SIZE(gsm0707_unsolicit); i++) {
+ const char *colon;
+ if (strncmp(buf, gsm0707_unsolicit[i].prefix,
+ strlen(gsm0707_unsolicit[i].prefix)))
+ continue;
+
+ colon = strchr(buf, ':') + 2;
+ if (colon > buf+len)
+ colon = NULL;
+
+ rc = gsm0707_unsolicit[i].parse(buf, len, colon, g);
+ if (rc < 0)
+ gsmd_log(GSMD_ERROR, "error %d during parse of "
+ "unsolicied response `%s'\n", rc, buf);
+ return rc;
+ }
+
+ gsmd_log(GSMD_NOTICE, "no parser for unsolicited response `%s'\n", buf);
+
+ return -ENOENT;
+}
+
+static unsigned int errors_creating_events[] = {
+ GSM0707_CME_PHONE_FAILURE,
+ GSM0707_CME_PHONE_NOCONNECT,
+ GSM0707_CME_PHONE_ADAPT_RESERVED,
+ GSM0707_CME_PH_SIM_PIN_REQUIRED,
+ GSM0707_CME_PH_FSIM_PIN_REQUIRED,
+ GSM0707_CME_PH_FSIM_PUK_REQUIRED,
+ GSM0707_CME_SIM_NOT_INSERTED,
+ GSM0707_CME_SIM_PIN_REQUIRED,
+ GSM0707_CME_SIM_PUK_REQUIRED,
+ GSM0707_CME_SIM_FAILURE,
+ GSM0707_CME_SIM_BUSY,
+ GSM0707_CME_SIM_WRONG,
+ GSM0707_CME_SIM_PIN2_REQUIRED,
+ GSM0707_CME_SIM_PUK2_REQUIRED,
+ GSM0707_CME_MEMORY_FULL,
+ GSM0707_CME_MEMORY_FAILURE,
+ GSM0707_CME_NETPERS_PIN_REQUIRED,
+ GSM0707_CME_NETPERS_PUK_REQUIRED,
+ GSM0707_CME_NETSUBSET_PIN_REQUIRED,
+ GSM0707_CME_NETSUBSET_PUK_REQUIRED,
+ GSM0707_CME_PROVIDER_PIN_REQUIRED,
+ GSM0707_CME_PROVIDER_PUK_REQUIRED,
+ GSM0707_CME_CORPORATE_PIN_REQUIRED,
+ GSM0707_CME_CORPORATE_PUK_REQUIRED,
+};
+
+static int is_in_array(unsigned int val, unsigned int *arr, unsigned int arr_len)
+{
+ unsigned int i;
+
+ for (i = 0; i < arr_len; i++) {
+ if (arr[i] == val)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int generate_event_from_cme(struct gsmd *g, unsigned int cme_error)
+{
+ struct gsmd_ucmd *gu;
+ struct gsmd_evt_auxdata *eaux;
+ if (!is_in_array(cme_error, errors_creating_events,
+ ARRAY_SIZE(errors_creating_events)))
+ return 0;
+
+ gu = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_PIN, sizeof(*eaux));
+ if (!gu)
+ return -1;
+ eaux = ((void *)gu) + sizeof(*gu);
+
+ switch (cme_error) {
+ case GSM0707_CME_PH_SIM_PIN_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_SIM_PIN;
+ break;
+ case GSM0707_CME_PH_FSIM_PIN_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_FSIM_PIN;
+ break;
+ case GSM0707_CME_PH_FSIM_PUK_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_FSIM_PUK;
+ break;
+ case GSM0707_CME_SIM_PIN_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_SIM_PIN;
+ break;
+ case GSM0707_CME_SIM_PUK_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_SIM_PUK;
+ break;
+ case GSM0707_CME_SIM_PIN2_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_SIM_PIN2;
+ break;
+ case GSM0707_CME_SIM_PUK2_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_SIM_PUK2;
+ break;
+ case GSM0707_CME_NETPERS_PIN_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_NET_PIN;
+ break;
+ case GSM0707_CME_NETPERS_PUK_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_NET_PUK;
+ break;
+ case GSM0707_CME_NETSUBSET_PIN_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_NETSUB_PIN;
+ break;
+ case GSM0707_CME_NETSUBSET_PUK_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_NETSUB_PUK;
+ break;
+ case GSM0707_CME_PROVIDER_PIN_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_SP_PIN;
+ break;
+ case GSM0707_CME_PROVIDER_PUK_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_SP_PUK;
+ break;
+ case GSM0707_CME_CORPORATE_PIN_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_CORP_PIN;
+ break;
+ case GSM0707_CME_CORPORATE_PUK_REQUIRED:
+ eaux->u.pin.type = GSMD_PIN_PH_CORP_PUK;
+ break;
+
+ case GSM0707_CME_SIM_FAILURE:
+ case GSM0707_CME_SIM_BUSY:
+ case GSM0707_CME_SIM_WRONG:
+ case GSM0707_CME_MEMORY_FULL:
+ case GSM0707_CME_MEMORY_FAILURE:
+ case GSM0707_CME_PHONE_FAILURE:
+ case GSM0707_CME_PHONE_NOCONNECT:
+ case GSM0707_CME_PHONE_ADAPT_RESERVED:
+ case GSM0707_CME_SIM_NOT_INSERTED:
+ /* FIXME */
+ return 0;
+ break;
+ default:
+ return 0;
+ break;
+ }
+ return usock_evt_send(g, gu, GSMD_EVT_PIN);
+}
Added: developers/seanchiang/gsm/src/gsmd/usock.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/usock.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/usock.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,1006 @@
+/* gsmd unix domain socket handling
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "gsmd.h"
+
+#include <gsmd/gsmd.h>
+#include <gsmd/usock.h>
+#include <gsmd/select.h>
+#include <gsmd/atcmd.h>
+#include <gsmd/usock.h>
+#include <gsmd/talloc.h>
+#include <gsmd/ts0707.h>
+
+static void *__ucmd_ctx, *__gu_ctx;
+
+struct gsmd_ucmd *ucmd_alloc(int extra_size)
+{
+ return talloc_size(__ucmd_ctx,
+ sizeof(struct gsmd_ucmd) + extra_size);
+}
+
+void usock_cmd_enqueue(struct gsmd_ucmd *ucmd, struct gsmd_user *gu)
+{
+ DEBUGP("enqueueing usock cmd %p for user %p\n", ucmd, gu);
+
+ /* add to per-user list of finished cmds */
+ llist_add_tail(&ucmd->list, &gu->finished_ucmds);
+
+ /* mark socket of user as we-want-to-write */
+ gu->gfd.when |= GSMD_FD_WRITE;
+}
+
+/* callback for completed passthrough gsmd_atcmd's */
+static int usock_cmd_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ int rlen = strlen(resp)+1;
+ struct gsmd_ucmd *ucmd = ucmd_alloc(rlen);
+
+ DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu);
+
+ if (!ucmd)
+ return -ENOMEM;
+
+ /* FIXME: pass error values back somehow */
+ ucmd->hdr.version = GSMD_PROTO_VERSION;
+ ucmd->hdr.msg_type = GSMD_MSG_PASSTHROUGH;
+ ucmd->hdr.msg_subtype = GSMD_PASSTHROUGH_RESP;
+ ucmd->hdr.len = strlen(resp)+1;
+ ucmd->hdr.id = cmd->id;
+ memcpy(ucmd->buf, resp, ucmd->hdr.len);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+typedef int usock_msg_handler(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len);
+
+static int usock_rcv_passthrough(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+ struct gsmd_atcmd *cmd;
+ cmd = atcmd_fill((char *)gph+sizeof(*gph), gph->len, &usock_cmd_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+
+ DEBUGP("submitting cmd=%p, gu=%p\n", cmd, gu);
+
+ return atcmd_submit(gu->gsmd, cmd);
+}
+
+static int usock_rcv_event(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+ u_int32_t *evtmask = (u_int32_t *) ((char *)gph + sizeof(*gph), gph->id);
+
+ if (len < sizeof(*gph) + sizeof(u_int32_t))
+ return -EINVAL;
+
+ if (gph->msg_subtype != GSMD_EVT_SUBSCRIPTIONS)
+ return -EINVAL;
+
+ gu->subscriptions = *evtmask;
+}
+
+static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ struct gsmd_atcmd *cmd = NULL;
+ struct gsmd_addr *ga;
+ struct gsmd_dtmf *gd;
+ int atcmd_len;
+
+ switch (gph->msg_subtype) {
+ case GSMD_VOICECALL_DIAL:
+ if (len < sizeof(*gph) + sizeof(*ga))
+ return -EINVAL;
+ ga = (struct gsmd_addr *) ((void *)gph + sizeof(*gph));
+ ga->number[GSMD_ADDR_MAXLEN] = '\0';
+ cmd = atcmd_fill("ATD", 5 + strlen(ga->number),
+ &usock_cmd_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "ATD%s;", ga->number);
+ /* FIXME: number type! */
+ break;
+ case GSMD_VOICECALL_HANGUP:
+ cmd = atcmd_fill("ATH0", 5, &usock_cmd_cb, gu, gph->id);
+ break;
+ case GSMD_VOICECALL_ANSWER:
+ cmd = atcmd_fill("ATA", 4, &usock_cmd_cb, gu, gph->id);
+ break;
+ case GSMD_VOICECALL_DTMF:
+ if (len < sizeof(*gph) + sizeof(*gd))
+ return -EINVAL;
+
+ gd = (struct gsmd_dtmf *) ((void *)gph + sizeof(*gph));
+ if (len < sizeof(*gph) + sizeof(*gd) + gd->len)
+ return -EINVAL;
+
+ /* FIXME: we don't yet support DTMF of multiple digits */
+ if (gd->len != 1)
+ return -EINVAL;
+
+ atcmd_len = 1 + strlen("AT+VTS=") + (gd->len * 2);
+ cmd = atcmd_fill("AT+VTS=", atcmd_len, &usock_cmd_cb,
+ gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+
+ sprintf(cmd->buf, "AT+VTS=%c;", gd->dtmf[0]);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (cmd)
+ return atcmd_submit(gu->gsmd, cmd);
+ else
+ return 0;
+}
+
+static int null_cmd_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ gsmd_log(GSMD_DEBUG, "null cmd cb\n");
+ return 0;
+}
+
+/* PIN command callback. Gets called for response to AT+CPIN cmcd */
+static int pin_cmd_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ gsmd_log(GSMD_DEBUG, "pin cmd cb\n");
+
+ /* We need to verify if there is some error */
+ switch (cmd->ret) {
+ case 0:
+ break;
+ case GSM0707_CME_INCORRECT_PASSWORD:
+ /* prompt for pin again */
+ break;
+ default:
+ /* something went wrong */
+ break;
+ }
+ return 0;
+}
+
+static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ struct gsmd_pin *gp = (struct gsmd_pin *) ((void *)gph + sizeof(*gph));
+ struct gsmd_atcmd *cmd;
+
+ if (gph->len < sizeof(*gp) || len < sizeof(*gp)+sizeof(*gph))
+ return -EINVAL;
+
+ gsmd_log(GSMD_DEBUG, "pin type=%u, pin='%s', newpin='%s'\n",
+ gp->type, gp->pin, gp->newpin);
+
+ switch (gph->msg_subtype) {
+ case GSMD_PIN_INPUT:
+ /* FIXME */
+ break;
+ default:
+ gsmd_log(GSMD_ERROR, "unknown pin type %u\n",
+ gph->msg_subtype);
+ return -EINVAL;
+ }
+
+ cmd = atcmd_fill("AT+CPIN=\"", 9+GSMD_PIN_MAXLEN+3+GSMD_PIN_MAXLEN+2,
+ &pin_cmd_cb, gu, 0);
+ if (!cmd)
+ return -ENOMEM;
+
+ strcat(cmd->buf, gp->pin);
+
+ switch (gp->type) {
+ case GSMD_PIN_SIM_PUK:
+ case GSMD_PIN_SIM_PUK2:
+ strcat(cmd->buf, "\",\"");
+ strcat(cmd->buf, gp->newpin);
+ break;
+ default:
+ break;
+ }
+
+ strcat(cmd->buf, "\"");
+
+ return atcmd_submit(gu->gsmd, cmd);
+}
+
+static int usock_rcv_phone(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ struct gsmd_atcmd *cmd;
+
+ switch (gph->msg_subtype) {
+ case GSMD_PHONE_POWERUP:
+ cmd = atcmd_fill("AT+CFUN=1", 9+1,
+ &null_cmd_cb, gu, 0);
+ gu->gsmd->dev_state.on = 1;
+ break;
+
+ case GSMD_PHONE_POWERDOWN:
+ cmd = atcmd_fill("AT+CFUN=0", 9+1,
+ &null_cmd_cb, gu, 0);
+ gu->gsmd->dev_state.on = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (!cmd)
+ return -ENOMEM;
+
+ return atcmd_submit(gu->gsmd, cmd);
+}
+
+static int network_vmail_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_voicemail *vmail;
+ struct gsmd_ucmd *ucmd;
+ char *comma;
+
+ DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu);
+
+ ucmd = ucmd_alloc(sizeof(*vmail));
+ if (!ucmd)
+ return -ENOMEM;
+
+ /* FIXME: pass error values back somehow */
+ ucmd->hdr.version = GSMD_PROTO_VERSION;
+ ucmd->hdr.msg_type = GSMD_MSG_NETWORK;
+ ucmd->hdr.len = sizeof(*vmail);
+ ucmd->hdr.id = cmd->id;
+
+ if (cmd->buf[7] == '=') {
+ /* response to set command */
+ ucmd->hdr.msg_subtype = GSMD_NETWORK_VMAIL_SET;
+ /* FIXME: */
+ return 0;
+ } else {
+ /* response to get command */
+ char *tok = strtok(resp, ",");
+ if (!tok)
+ goto out_free_einval;
+ ucmd->hdr.msg_subtype = GSMD_NETWORK_VMAIL_GET;
+ vmail->enable = atoi(tok);
+
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_einval;
+ strncpy(vmail->addr.number, tok, GSMD_ADDR_MAXLEN);
+ vmail->addr.number[GSMD_ADDR_MAXLEN] = '\0';
+
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_einval;
+ vmail->addr.type = atoi(tok);
+ }
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+
+out_free_einval:
+ gsmd_log(GSMD_ERROR, "can't understand voicemail response\n");
+ talloc_free(ucmd);
+ return -EINVAL;
+}
+
+static struct gsmd_ucmd *gsmd_ucmd_fill(int len, u_int8_t msg_type, u_int8_t msg_subtype,
+ u_int16_t id)
+{
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = ucmd_alloc(len);
+ if (!ucmd)
+ return NULL;
+
+ ucmd->hdr.version = GSMD_PROTO_VERSION;
+ ucmd->hdr.msg_type = msg_type;
+ ucmd->hdr.msg_subtype = msg_subtype;
+ ucmd->hdr.len = len;
+ ucmd->hdr.id = id;
+
+ return ucmd;
+}
+
+static int network_sigq_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_signal_quality *gsq;
+ struct gsmd_ucmd *ucmd;
+ char *comma;
+
+ ucmd = gsmd_ucmd_fill(sizeof(*gsq), GSMD_MSG_NETWORK,
+ GSMD_NETWORK_SIGQ_GET, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ gsq = (struct gsmd_signal_quality *) ucmd->buf;
+ gsq->rssi = atoi(resp);
+ comma = strchr(resp, ',');
+ if (!comma) {
+ talloc_free(ucmd);
+ return -EIO;
+ }
+ gsq->ber = atoi(comma+1);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int network_oper_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_signal_quality *gsq;
+ struct gsmd_ucmd *ucmd;
+ char *comma;
+
+ ucmd = gsmd_ucmd_fill(sizeof(*gsq), GSMD_MSG_NETWORK,
+ GSMD_NETWORK_OPER_GET, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ /* FIXME: implementation */
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ struct gsmd_atcmd *cmd;
+ struct gsmd_voicemail *vmail = (struct gsmd_voicemail *) gph->data;
+
+ switch (gph->msg_subtype) {
+ case GSMD_NETWORK_REGISTER:
+ cmd = atcmd_fill("AT+COPS", 9+1,
+ &null_cmd_cb, gu, 0);
+ break;
+ case GSMD_NETWORK_VMAIL_GET:
+ cmd = atcmd_fill("AT+CSVM?", 8+1, &network_vmail_cb, gu, 0);
+ break;
+ case GSMD_NETWORK_VMAIL_SET:
+ cmd = atcmd_fill("AT+CSVM=", 8+1, &network_vmail_cb, gu, 0);
+ break;
+ case GSMD_NETWORK_SIGQ_GET:
+ cmd = atcmd_fill("AT+CSQ", 6+1, &network_sigq_cb, gu, 0);
+ break;
+ case GSMD_NETWORK_OPER_GET:
+ cmd = atcmd_fill("AT+COPS?", 8+1, &network_oper_cb, gu, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (!cmd)
+ return -ENOMEM;
+
+ return atcmd_submit(gu->gsmd, cmd);
+}
+
+static int sms_list_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+#if 1
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_LIST, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ /* FIXME: implementation */
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+#endif
+ return 0;
+}
+
+static int sms_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ /* FIXME: implementation */
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_READ, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_SEND, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_WRITE, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_DELETE, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ /* FIXME: TEXT mode support!! */
+ struct gsmd_atcmd *cmd = NULL;
+ struct gsmd_sms_delete *gsd;
+ struct gsmd_sms *gs;
+ struct gsmd_sms_write *gsw;
+ int *stat, *index;
+ int atcmd_len;
+ char buf[1024];
+
+ switch (gph->msg_subtype) {
+ case GSMD_SMS_LIST:
+ /* FIXME: only support PDU mode!! */
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ stat = (int *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *stat);
+
+ atcmd_len = 1 + strlen("AT+CMGL=") + strlen(buf);
+ cmd = atcmd_fill("AT+CMGL=", atcmd_len,
+ &sms_list_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGL=%s", buf);
+ break;
+ case GSMD_SMS_READ:
+ /* FIXME: only support PDU mode!! */
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ index = (int *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *index);
+
+ atcmd_len = 1 + strlen("AT+CMGR=") + strlen(buf);
+ cmd = atcmd_fill("AT+CMGR=", atcmd_len,
+ &sms_read_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGR=%s", buf);
+ break;
+#if 0
+ case GSMD_SMS_SEND:
+ /* FIXME: only support PDU mode!! */
+ if(len < sizeof(*gph) + sizeof(*gs))
+ return -EINVAL;
+ gs = (struct gsmd_sms *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *index);
+
+ atcmd_len = 1 + strlen("AT+CMGR=") + 1;
+ cmd = atcmd_fill("AT+CMGR=", atcmd_len,
+ &sms_send_cb, gu, gph->id);
+ if (!cmd)GSMD_SMS_WRITE
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGR=%d", index);
+ break;
+ case GSMD_SMS_WRITE:
+ /* FIXME: only support PDU mode!! */
+ if(len < sizeof(*gph) + sizeof(*gsw))
+ return -EINVAL;
+ &index = (int *) ((void *)gph + sizeof(*gph));
+
+ atcmd_len = 1 + strlen("AT+CMGR=") + 1;
+ cmd = atcmd_fill("AT+CMGR=", atcmd_len,
+ &sms_write_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGR=%d", index);
+ break;
+#endif
+ case GSMD_SMS_DELETE:
+ if(len < sizeof(*gph) + sizeof(*gsd))
+ return -EINVAL;
+ gsd = (struct gsmd_sms_delete *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d,%d", gsd->index, gsd->delflg);
+
+ atcmd_len = 1 + strlen("AT+CMGR=") + strlen(buf);
+ cmd = atcmd_fill("AT+CMGD=", atcmd_len,
+ &sms_delete_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGD=%s", buf);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+#if 1
+ printf("%s\n",cmd->buf);
+ if (cmd)
+ return atcmd_submit(gu->gsmd, cmd);
+ else
+ return 0;
+#endif
+}
+
+static int phonebook_find_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ /* FIXME: implementation */
+#if 1
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_FIND, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+#endif
+ return 0;
+}
+
+static int phonebook_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_phonebook *gp;
+ struct gsmd_ucmd *ucmd;
+ char *fcomma, *lcomma;
+ char *ptr;
+ /* FIXME: We should check this case "When the entry is empty" */
+ ucmd = gsmd_ucmd_fill(sizeof(*gp), GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_READ, 0);
+
+ if (!ucmd)
+ return -ENOMEM;
+ gp = (struct gsmd_phonebook *) ucmd->buf;
+
+ ptr = strchr(resp, ' ');
+ gp->index = atoi(ptr+1);
+
+ fcomma = strchr(resp, '"');
+ lcomma = strchr(fcomma+1, '"');
+ strncpy(gp->numb, fcomma+1, (lcomma-fcomma-1));
+ gp->numb[(lcomma-fcomma)-1] = '\0';
+
+ gp->type = atoi(lcomma+2);
+
+ ptr = strrchr(resp, ',');
+ fcomma = ptr+1;
+ lcomma = strchr(fcomma+1, '"');
+ strncpy(gp->text, fcomma+1, (lcomma-fcomma-1));
+ gp->text[(lcomma-fcomma)-1] = '\0';
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int phonebook_readrg_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ /* FIXME: implementation */
+
+#if 1
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_READRG, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+#endif
+
+ return 0;
+}
+
+static int phonebook_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_WRITE, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int phonebook_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_DELETE, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int phonebook_support_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_phonebook_support *gps;
+ struct gsmd_ucmd *ucmd;
+ char *fcomma, *lcomma;
+ char *dash;
+
+ ucmd = gsmd_ucmd_fill(sizeof(*gps), GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_GET_SUPPORT, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ gps = (struct gsmd_phonebook_support *) ucmd->buf;
+
+ dash = strchr(resp, '-');
+ if (!dash) {
+ talloc_free(ucmd);
+ return -EIO;
+ }
+ gps->index = atoi(dash+1);
+
+ fcomma = strchr(resp, ',');
+ if (!fcomma) {
+ talloc_free(ucmd);
+ return -EIO;
+ }
+ gps->nlength = atoi(fcomma+1);
+
+ lcomma = strrchr(resp, ',');
+ if (!lcomma) {
+ talloc_free(ucmd);
+ return -EIO;
+ }
+ gps->tlength = atoi(lcomma+1);
+
+ usock_cmd_enqueue(ucmd, gu);
+ return 0;
+}
+
+static int usock_rcv_phonebook(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ struct gsmd_atcmd *cmd = NULL;
+ struct gsmd_phonebook_readrg *gpr;
+ struct gsmd_phonebook *gp;
+ struct gsmd_phonebook_find *gpf;
+ int *index;
+ int atcmd_len;
+ char buf[1024];
+
+ switch (gph->msg_subtype) {
+ case GSMD_PHONEBOOK_FIND:
+ if(len < sizeof(*gph) + sizeof(*gpf))
+ return -EINVAL;
+ gpf = (struct gsmd_phonebook_find *) ((void *)gph + sizeof(*gph));
+
+ atcmd_len = 1 + strlen("AT+CPBF=\"") + strlen(gpf->findtext) + strlen("\"");
+ cmd = atcmd_fill("AT+CPBF=\"", atcmd_len,
+ &phonebook_find_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBF=\"%s\"", gpf->findtext);
+ break;
+ case GSMD_PHONEBOOK_READ:
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ index = (int *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *index);
+
+ atcmd_len = 1 + strlen("AT+CPBR=") + strlen(buf);
+ cmd = atcmd_fill("AT+CPBR=", atcmd_len,
+ &phonebook_read_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBR=%d", *index);
+ break;
+ case GSMD_PHONEBOOK_READRG:
+ if(len < sizeof(*gph) + sizeof(*gpr))
+ return -EINVAL;
+ gpr = (struct gsmd_phonebook_readrg *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d,%d", gpr->index1, gpr->index2);
+
+ atcmd_len = 1 + strlen("AT+CPBR=") + strlen(buf);
+ cmd = atcmd_fill("AT+CPBR=", atcmd_len,
+ &phonebook_readrg_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBR=%s", buf);
+ break;
+ case GSMD_PHONEBOOK_WRITE:
+ if(len < sizeof(*gph) + sizeof(*gp))
+ return -EINVAL;
+ gp = (struct gsmd_phonebook *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d,\"%s\",%d,\"%s\"", gp->index, gp->numb, gp->type, gp->text);
+
+ atcmd_len = 1 + strlen("AT+CPBW=") + strlen(buf);
+ cmd = atcmd_fill("AT+CPBW=", atcmd_len,
+ &phonebook_write_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBW=%s", buf);
+ break;
+ case GSMD_PHONEBOOK_DELETE:
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ index = (int *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *index);
+
+ atcmd_len = 1 + strlen("AT+CPBW=") + strlen(buf);
+ cmd = atcmd_fill("AT+CPBW=", atcmd_len,
+ &phonebook_delete_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBW=%s", buf);
+ break;
+ case GSMD_PHONEBOOK_GET_SUPPORT:
+ cmd = atcmd_fill("AT+CPBR=?", 9+1,
+ &phonebook_support_cb, gu, gph->id);
+ break;
+ default:
+ return -EINVAL;
+ }
+#if 1
+ printf("%s\n", cmd->buf);
+ if (cmd)
+ return atcmd_submit(gu->gsmd, cmd);
+ else
+ return 0;
+#endif
+}
+
+static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = {
+ [GSMD_MSG_PASSTHROUGH] = &usock_rcv_passthrough,
+ [GSMD_MSG_EVENT] = &usock_rcv_event,
+ [GSMD_MSG_VOICECALL] = &usock_rcv_voicecall,
+ [GSMD_MSG_PIN] = &usock_rcv_pin,
+ [GSMD_MSG_PHONE] = &usock_rcv_phone,
+ [GSMD_MSG_NETWORK] = &usock_rcv_network,
+ [GSMD_MSG_SMS] = &usock_rcv_sms,
+ [GSMD_MSG_PHONEBOOK] = &usock_rcv_phonebook,
+};
+
+static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len)
+{
+ struct gsmd_msg_hdr *gph = (struct gsmd_msg_hdr *)buf;
+ usock_msg_handler *umh;
+
+ if (gph->version != GSMD_PROTO_VERSION)
+ return -EINVAL;
+
+ if (gph->msg_type >= __NUM_GSMD_MSGS)
+ return -EINVAL;
+
+ umh = pcmd_type_handlers[gph->msg_type];
+ if (!umh)
+ return -EINVAL;
+
+ return umh(gu, gph, len);
+}
+
+/* callback for read/write on client (libgsmd) socket */
+static int gsmd_usock_user_cb(int fd, unsigned int what, void *data)
+{
+ struct gsmd_user *gu = data;
+
+ /* FIXME: check some kind of backlog and limit it */
+
+ if (what & GSMD_FD_READ) {
+ char buf[1024];
+ int rcvlen;
+ /* read data from socket, determine what he wants */
+ rcvlen = read(fd, buf, sizeof(buf));
+ if (rcvlen == 0) {
+ DEBUGP("EOF, this client has just vanished\n");
+ /* EOF, this client has just vanished */
+ gsmd_unregister_fd(&gu->gfd);
+ close(fd);
+ /* destroy whole user structure */
+ llist_del(&gu->list);
+ /* FIXME: delete busy ucmds from finished_ucmds */
+ talloc_free(gu);
+ return 0;
+ } else if (rcvlen < 0)
+ return rcvlen;
+ else
+ return usock_rcv_pcmd(gu, buf, rcvlen);
+ }
+
+ if (what & GSMD_FD_WRITE) {
+ /* write data from pending replies to socket */
+ struct gsmd_ucmd *ucmd, *uctmp;
+ llist_for_each_entry_safe(ucmd, uctmp, &gu->finished_ucmds,
+ list) {
+ int rc;
+
+ rc = write(fd, &ucmd->hdr, sizeof(ucmd->hdr) + ucmd->hdr.len);
+ if (rc < 0) {
+ DEBUGP("write return %d\n", rc);
+ return rc;
+ }
+ if (rc == 0) {
+ DEBUGP("write returns zero!!\n");
+ break;
+ }
+ if (rc != sizeof(ucmd->hdr) + ucmd->hdr.len) {
+ DEBUGP("short write\n");
+ break;
+ }
+
+ DEBUGP("successfully sent cmd %p to user %p, freeing\n", ucmd, gu);
+ llist_del(&ucmd->list);
+ talloc_free(ucmd);
+ }
+ if (llist_empty(&gu->finished_ucmds))
+ gu->gfd.when &= ~GSMD_FD_WRITE;
+ }
+
+ return 0;
+}
+
+/* callback for read on master-listen-socket */
+static int gsmd_usock_cb(int fd, unsigned int what, void *data)
+{
+ struct gsmd *g = data;
+ struct gsmd_user *newuser;
+
+ /* FIXME: implement this */
+ if (what & GSMD_FD_READ) {
+ /* new incoming connection */
+ newuser = talloc(__gu_ctx, struct gsmd_user);
+ if (!newuser)
+ return -ENOMEM;
+
+ newuser->gfd.fd = accept(fd, NULL, 0);
+ if (newuser->gfd.fd < 0) {
+ DEBUGP("error accepting incoming conn: `%s'\n",
+ strerror(errno));
+ talloc_free(newuser);
+ }
+ newuser->gfd.when = GSMD_FD_READ;
+ newuser->gfd.data = newuser;
+ newuser->gfd.cb = &gsmd_usock_user_cb;
+ newuser->gsmd = g;
+ newuser->subscriptions = 0xffffffff;
+ INIT_LLIST_HEAD(&newuser->finished_ucmds);
+
+ llist_add(&newuser->list, &g->users);
+ gsmd_register_fd(&newuser->gfd);
+ }
+
+ return 0;
+}
+
+/* handling of socket with incoming client connections */
+int usock_init(struct gsmd *g)
+{
+ struct sockaddr_un sun;
+ int fd, rc;
+
+ __ucmd_ctx = talloc_named_const(gsmd_tallocs, 1, "ucmd");
+ __gu_ctx = talloc_named_const(gsmd_tallocs, 1, "gsmd_user");
+
+ fd = socket(PF_UNIX, GSMD_UNIX_SOCKET_TYPE, 0);
+ if (fd < 0)
+ return fd;
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET));
+
+ rc = bind(fd, (struct sockaddr *)&sun, sizeof(sun));
+ if (rc < 0) {
+ close(fd);
+ return rc;
+ }
+
+ rc = listen(fd, 10);
+ if (rc < 0) {
+ close(fd);
+ return rc;
+ }
+
+ g->gfd_sock.fd = fd;
+ g->gfd_sock.when = GSMD_FD_READ | GSMD_FD_EXCEPT;
+ g->gfd_sock.data = g;
+ g->gfd_sock.cb = &gsmd_usock_cb;
+
+ return gsmd_register_fd(&g->gfd_sock);
+}
Added: developers/seanchiang/gsm/src/gsmd/vendor.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/vendor.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/vendor.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,61 @@
+/* gsmd vendor plugin core
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <errno.h>
+
+#include <common/linux_list.h>
+
+#include "gsmd.h"
+
+#include <gsmd/gsmd.h>
+#include <gsmd/vendorplugin.h>
+
+static LLIST_HEAD(vendorpl_list);
+
+int gsmd_vendor_plugin_register(struct gsmd_vendor_plugin *pl)
+{
+ llist_add(&pl->list, &vendorpl_list);
+
+ return 0;
+}
+
+void gsmd_vendor_plugin_unregister(struct gsmd_vendor_plugin *pl)
+{
+ llist_del(&pl->list);
+}
+
+int gsmd_vendor_plugin_find(struct gsmd *g)
+{
+ struct gsmd_vendor_plugin *pl;
+
+ if (g->vendorpl)
+ return -EEXIST;
+
+ llist_for_each_entry(pl, &vendorpl_list, list) {
+ if (pl->detect(g) == 1) {
+ g->vendorpl = pl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
Added: developers/seanchiang/gsm/src/gsmd/vendor_ti.c
===================================================================
--- developers/seanchiang/gsm/src/gsmd/vendor_ti.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/vendor_ti.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,317 @@
+/* TI [Calypso] compatible gsmd plugin
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "gsmd.h"
+
+#include <gsmd/gsmd.h>
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+#include <gsmd/talloc.h>
+#include <gsmd/extrsp.h>
+#include <gsmd/atcmd.h>
+#include <gsmd/vendorplugin.h>
+#include <gsmd/unsolicited.h>
+
+#if 0
+#include "vendorplugin.h"
+
+static int
+ti_getopt(struct gsmd *gh, int optname, void *optval, int *optlen)
+{
+ switch (optname) {
+ case GSMD_OPT_CIPHER_IND:
+ /* FIXME: send AT%CPRI=? */
+ break;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int
+ti_setopt(struct gsmd *gh, int optname, const void *optval, int optlen)
+{
+ switch (optname) {
+ case GSMD_OPT_CIPHER_IND:
+ /* FIXME: send AT%CPRI= */
+ break;
+ default:
+ return -EINVAL;
+ }
+}
+
+#endif
+
+
+static int csq_parse(char *buf, int len, const char *param,
+ struct gsmd *gsmd)
+{
+ char *tok;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_SIGNAL,
+ sizeof(*aux));
+
+ DEBUGP("entering csq_parse param=`%s'\n", param);
+ if (!ucmd)
+ return -EINVAL;
+
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+ tok = strtok(buf, ",");
+ if (!tok)
+ goto out_free_io;
+
+ aux->u.signal.sigq.rssi = atoi(tok);
+
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+
+ aux->u.signal.sigq.ber = atoi(tok);
+
+ DEBUGP("sending EVT_SIGNAL\n");
+ usock_evt_send(gsmd, ucmd, GSMD_EVT_SIGNAL);
+
+ return 0;
+
+out_free_io:
+ free(ucmd);
+ return -EIO;
+}
+
+static int cpri_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
+{
+ char *tok1, *tok2;
+
+ tok1 = strtok(buf, ",");
+ if (!tok1)
+ return -EIO;
+
+ tok2 = strtok(NULL, ",");
+ if (!tok2) {
+ switch (atoi(tok1)) {
+ case 0:
+ gsmd->dev_state.ciph_ind.flags &= ~GSMD_CIPHIND_ACTIVE;
+ break;
+ case 1:
+ gsmd->dev_state.ciph_ind.flags |= GSMD_CIPHIND_ACTIVE;
+ break;
+ case 2:
+ gsmd->dev_state.ciph_ind.flags |= GSMD_CIPHIND_DISABLED_SIM;
+ break;
+ }
+ } else {
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_CIPHER,
+ sizeof(*aux));
+ if (!ucmd)
+ return -ENOMEM;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ aux->u.cipher.net_state_gsm = atoi(tok1);
+ aux->u.cipher.net_state_gsm = atoi(tok2);
+
+ usock_evt_send(gsmd, ucmd, GSMD_EVT_CIPHER);
+ }
+
+ return 0;
+}
+
+static int ctzv_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
+{
+ /* FIXME: decide what to do with it. send as event to clients? or keep
+ * locally? Offer option to sync system RTC? */
+ return 0;
+}
+
+/* Call Progress Information */
+static int cpi_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
+{
+ char *tok;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_OUT_STATUS,
+ sizeof(*aux));
+
+ DEBUGP("entering cpi_parse param=`%s'\n", param);
+ if (!ucmd)
+ return -EINVAL;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ /* Format: cId, msgType, ibt, tch, dir,[mode],[number],[type],[alpha],[cause],line */
+
+ /* call ID */
+ tok = strtok(buf, ",");
+ if (!tok)
+ goto out_free_io;
+
+ /* message type (layer 3) */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+ aux->u.call_status.prog = atoi(tok);
+
+ /* in-band tones */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+
+ if (*tok == '1')
+ aux->u.call_status.ibt = 1;
+ else
+ aux->u.call_status.ibt = 0;
+
+ /* TCH allocated */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+
+ if (*tok == '1')
+ aux->u.call_status.tch = 1;
+ else
+ aux->u.call_status.tch = 0;
+
+ /* direction */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_send;
+
+ switch (*tok) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ aux->u.call_status.dir = (*tok - '0');
+ break;
+ default:
+ break;
+ }
+
+ /* mode */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_send;
+
+out_send:
+ usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_STATUS);
+
+ return 0;
+
+out_free_io:
+ talloc_free(ucmd);
+ return -EIO;
+}
+
+static const struct gsmd_unsolicit ticalypso_unsolicit[] = {
+ { "%CSQ", &csq_parse }, /* Signal Quality */
+ { "%CPRI", &cpri_parse }, /* Ciphering Indication */
+ { "%CPI", &cpi_parse }, /* Call Progress Information */
+ { "%CTZV", &ctzv_parse }, /* network time and data */
+
+ /* FIXME: parse all the below and generate the respective events */
+
+ /* %CPROAM: CPHS Home Country Roaming Indicator */
+ /* %CPVWI: CPHS Voice Message Waiting */
+ /* %CGREG: reports extended information about GPRS registration state */
+ /* %CNIV: reports network name information */
+ /* %CPKY: Press Key */
+ /* %CMGRS: Message Retransmission Service */
+ /* %CGEV: reports GPRS network events */
+};
+
+static int cpi_detect_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd *g = ctx;
+ struct gsm_extrsp *er;
+
+ if (strncmp(resp, "%CPI: ", 6))
+ return -EINVAL;
+ resp += 6;
+
+ er = extrsp_parse(cmd, resp);
+ if (!er)
+ return -EINVAL;
+
+ if (extrsp_supports(er, 0, 3))
+ return gsmd_simplecmd(g, "AT%CPI=3");
+ else if (extrsp_supports(er, 0, 2))
+ return gsmd_simplecmd(g, "AT%CPI=2");
+ else
+ DEBUGP("Call Progress Indication mode 2 or 3 not supported!!\n");
+
+ talloc_free(er);
+ return 0;
+}
+
+static int ticalypso_detect(struct gsmd *g)
+{
+ /* FIXME: do actual detection of vendor if we have multiple vendors */
+ return 1;
+}
+
+static int ticalypso_initsettings(struct gsmd *g)
+{
+ int rc;
+ struct gsmd_atcmd *cmd;
+
+ /* use +CTZR: to report time zone changes */
+ rc |= gsmd_simplecmd(g, "AT+CTZR=1");
+ /* use %CTZV: Report time and date */
+ rc |= gsmd_simplecmd(g, "AT%CTZV=1");
+ /* use %CGREG */
+ //rc |= gsmd_simplecmd(g, "AT%CGREG=3");
+ /* enable %CPRI: ciphering indications */
+ rc |= gsmd_simplecmd(g, "AT%CPRI=1");
+ /* enable %CSQ: signal quality reports */
+ rc |= gsmd_simplecmd(g, "AT%CSQ=1");
+ /* send unsolicited commands at any time */
+ rc |= gsmd_simplecmd(g, "AT%CUNS=0");
+
+ /* enable %CPI: call progress indication */
+ cmd = atcmd_fill("AT%CPI=?", 9, &cpi_detect_cb, g, 0);
+ if (cmd)
+ atcmd_submit(g, cmd);
+
+ return rc;
+}
+
+static struct gsmd_vendor_plugin plugin_ticalypso = {
+ .name = "TI Calypso",
+ .num_unsolicit = ARRAY_SIZE(ticalypso_unsolicit),
+ .unsolicit = ticalypso_unsolicit,
+ .detect = &ticalypso_detect,
+ .initsettings = &ticalypso_initsettings,
+};
+
+/* FIXME: this will be _init() when we make this a plugin */
+int ticalypso_init(void)
+{
+ return gsmd_vendor_plugin_register(&plugin_ticalypso);
+}
Added: developers/seanchiang/gsm/src/gsmd/vendorplugin.h
===================================================================
--- developers/seanchiang/gsm/src/gsmd/vendorplugin.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/gsmd/vendorplugin.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,33 @@
+#ifndef __GSMD_VENDORPLUG_H
+#define __GSMD_VENDORPLUG_H
+
+#ifdef __GSMD__
+
+#include "gsmd.h"
+
+/* gsmd vendor-specific plugin */
+
+enum gsmd_options {
+ GSMD_OPT_NONE,
+ GSMD_OPT_CIPHER_IND,
+};
+
+/* CIPHER_IND */
+enum gsmd_cipher_ind {
+ GSMD_CIPHER_IND_OFF,
+ GSMD_CIPHER_IND_ON,
+ GSMD_CIPHER_IND_SIM_FORBID,
+};
+
+struct gsmd_vendorspecific {
+ /* callback function to parse unknown unsolicited responses */
+ int (*parse_unsolicit)(void);
+ int (*getopt)(struct gsmd *gh, int optname, void *optval, int *optlen);
+ int (*setopt)(struct gsmd *gh, int optname, const void *optval, int optlen);
+};
+
+/* ciphering indications */
+
+#endif /* __GSMD__ */
+
+#endif
Added: developers/seanchiang/gsm/src/libgsmd/Makefile.am
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,10 @@
+LIBVERSION= 0:0:0
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS = -std=gnu99
+
+lib_LTLIBRARIES = libgsmd.la
+
+libgsmd_la_LDFLAGS = -Wc,-nostartfiles -version-info $(LIBVERSION)
+libgsmd_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c libgsmd_phone.c libgsmd_network.c libgsmd_pin.c libgsmd_sms.c libgsmd_phonebook.c
+
+noinst_HEADERS = lgsm_internals.h
Added: developers/seanchiang/gsm/src/libgsmd/lgsm_internals.h
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/lgsm_internals.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/lgsm_internals.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,15 @@
+#ifndef _LGSM_INTERNALS_H
+#define _LGSM_INTERNALS_H
+
+#include <gsmd/usock.h>
+
+struct lgsm_handle {
+ int fd;
+ lgsm_msg_handler *handler[__NUM_GSMD_MSGS];
+};
+
+int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh);
+struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len);
+#define lgsm_gmh_free(x) free(x)
+
+#endif /* _LGSM_INTERNALS_H */
Added: developers/seanchiang/gsm/src/libgsmd/libgsmd.c
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/libgsmd.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/libgsmd.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,187 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <gsmd/usock.h>
+#include <libgsmd/libgsmd.h>
+
+#include "lgsm_internals.h"
+
+static int lgsm_get_packet(struct lgsm_handle *lh)
+{
+ static char buf[GSMD_MSGSIZE_MAX];
+ struct gsmd_msg_hdr *hdr = (struct gsmd_msg_hdr *) buf;
+ int rc = read(lh->fd, buf, sizeof(buf));
+ if (rc <= 0)
+ return rc;
+
+ if (hdr->version != GSMD_PROTO_VERSION)
+ return -EINVAL;
+
+ switch (hdr->msg_type) {
+ case GSMD_MSG_PASSTHROUGH:
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int lgsm_open_backend(struct lgsm_handle *lh, const char *device)
+{
+ int rc;
+
+ if (!strcmp(device, LGSMD_DEVICE_GSMD)) {
+ struct sockaddr_un sun;
+
+ /* use unix domain socket to gsm daemon */
+ lh->fd = socket(PF_UNIX, GSMD_UNIX_SOCKET_TYPE, 0);
+ if (lh->fd < 0)
+ return lh->fd;
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET));
+
+ rc = connect(lh->fd, (struct sockaddr *)&sun, sizeof(sun));
+ if (rc < 0) {
+ close(lh->fd);
+ lh->fd = -1;
+ return rc;
+ }
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+/* handle a packet that was received on the gsmd socket */
+int lgsm_handle_packet(struct lgsm_handle *lh, char *buf, int len)
+{
+ struct gsmd_msg_hdr *gmh = (struct gsmd_msg_hdr *)buf;
+ lgsm_msg_handler *handler;
+
+ if (len < sizeof(*gmh))
+ return -EINVAL;
+
+ if (len - sizeof(*gmh) < gmh->len)
+ return -EINVAL;
+
+ if (gmh->msg_type >= __NUM_GSMD_MSGS)
+ return -EINVAL;
+
+ handler = lh->handler[gmh->msg_type];
+
+ if (handler)
+ return handler(lh, gmh);
+ else {
+ fprintf(stderr, "unable to handle packet type=%u\n", gmh->msg_type);
+ return 0;
+ }
+}
+
+int lgsm_register_handler(struct lgsm_handle *lh, int type, lgsm_msg_handler *handler)
+{
+ if (type >= __NUM_GSMD_MSGS)
+ return -EINVAL;
+
+ lh->handler[type] = handler;
+
+ return 0;
+}
+
+void lgsm_unregister_handler(struct lgsm_handle *lh, int type)
+{
+ if (type < __NUM_GSMD_MSGS)
+ lh->handler[type] = NULL;
+}
+
+/* blocking read and processing of packets until packet matching 'id' is found */
+int lgsm_blocking_wait_packet(struct lgsm_handle *lh, u_int16_t id,
+ struct gsmd_msg_hdr *gmh, int rlen)
+{
+ int rc;
+ fd_set readset;
+
+ FD_ZERO(&readset);
+
+ while (1) {
+ FD_SET(lh->fd, &readset);
+ rc = select(lh->fd+1, &readset, NULL, NULL, NULL);
+ if (rc <= 0)
+ return rc;
+
+ rc = read(lh->fd, (char *)gmh, rlen);
+ if (rc <= 0)
+ return rc;
+
+ if (gmh->id == id) {
+ /* we've found the matching packet, return to calling function */
+ return rc;
+ } else
+ rc = lgsm_handle_packet(lh, (char *)gmh, rc);
+ }
+}
+
+int lgsm_fd(struct lgsm_handle *lh)
+{
+ return lh->fd;
+}
+
+struct lgsm_handle *lgsm_init(const char *device)
+{
+ struct lgsm_handle *lh = malloc(sizeof(*lh));
+
+ memset(lh, 0, sizeof(*lh));
+ lh->fd = -1;
+
+ if (lgsm_open_backend(lh, device) < 0) {
+ free(lh);
+ return NULL;
+ }
+
+ lgsm_evt_init(lh);
+
+ return lh;
+}
+
+int lgsm_exit(struct lgsm_handle *lh)
+{
+ free(lh);
+
+ return 0;
+}
+
+
+static u_int16_t next_msg_id;
+
+int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+ gmh->id = next_msg_id++;
+ return send(lh->fd, (char *) gmh, sizeof(*gmh) + gmh->len, 0);
+}
+
+struct gsmd_msg_hdr *lgsm_gmh_fill(int type, int subtype, int payload_len)
+{
+ struct gsmd_msg_hdr *gmh = malloc(sizeof(*gmh)+payload_len);
+ if (!gmh)
+ return NULL;
+
+ memset(gmh, 0, sizeof(*gmh)+payload_len);
+
+ gmh->version = GSMD_PROTO_VERSION;
+ gmh->msg_type = type;
+ gmh->msg_subtype = subtype;
+ gmh->len = payload_len;
+
+ return gmh;
+}
+
Added: developers/seanchiang/gsm/src/libgsmd/libgsmd_event.c
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/libgsmd_event.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/libgsmd_event.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,80 @@
+/* libgsmd event demultiplexer handler
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libgsmd/voicecall.h>
+#include <libgsmd/event.h>
+
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+
+#include "lgsm_internals.h"
+
+static lgsm_evt_handler *evt_handlers[__NUM_GSMD_EVT];
+
+int lgsm_evt_handler_register(struct lgsm_handle *lh, int evt_type,
+ lgsm_evt_handler *handler)
+{
+ if (evt_type >= __NUM_GSMD_EVT)
+ return -EINVAL;
+
+ evt_handlers[evt_type] = handler;
+
+ return 0;
+}
+
+void lgsm_evt_handler_unregister(struct lgsm_handle *lh, int evt_type)
+{
+ if (evt_type < __NUM_GSMD_EVT)
+ evt_handlers[evt_type] = NULL;
+}
+
+
+static int evt_demux_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+ struct gsmd_evt_auxdata *aux = gmh->data;
+
+ if (gmh->len < sizeof(*aux))
+ return -EIO;
+
+ if (gmh->msg_type != GSMD_MSG_EVENT ||
+ gmh->msg_subtype >= __NUM_GSMD_EVT)
+ return -EINVAL;
+
+ if (evt_handlers[gmh->msg_subtype])
+ return evt_handlers[gmh->msg_subtype](lh, gmh->msg_subtype, aux);
+ else
+ return 0;
+}
+
+int lgsm_evt_init(struct lgsm_handle *lh)
+{
+ return lgsm_register_handler(lh, GSMD_MSG_EVENT, &evt_demux_msghandler);
+}
+
+void lgsm_evt_exit(struct lgsm_handle *lh)
+{
+ lgsm_unregister_handler(lh, GSMD_MSG_EVENT);
+}
Added: developers/seanchiang/gsm/src/libgsmd/libgsmd_input.c
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/libgsmd_input.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/libgsmd_input.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,35 @@
+/* libgsmd core
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include <libgsmd/libgsmd.h>
+
+#include "lgsm_internals.h"
+
+
Added: developers/seanchiang/gsm/src/libgsmd/libgsmd_network.c
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/libgsmd_network.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/libgsmd_network.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,49 @@
+/* libgsmd network related functions
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/misc.h>
+
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+
+#include "lgsm_internals.h"
+
+int lgsm_netreg_register(struct lgsm_handle *lh, int oper)
+{
+ /* FIXME: implement oper selection */
+ return lgsm_send_simple(lh, GSMD_MSG_NETWORK, GSMD_NETWORK_REGISTER);
+}
+
+int lgsm_signal_quality(struct lgsm_handle *lh)
+{
+ return lgsm_send_simple(lh, GSMD_MSG_NETWORK, GSMD_NETWORK_SIGQ_GET);
+}
+
+int lgsmd_operator_name(struct lgsm_handle *lh)
+{
+ return lgsm_send_simple(lh, GSMD_MSG_NETWORK, GSMD_NETWORK_OPER_GET);
+}
Added: developers/seanchiang/gsm/src/libgsmd/libgsmd_passthrough.c
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/libgsmd_passthrough.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/libgsmd_passthrough.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,91 @@
+/* libgsmd passthrough
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <gsmd/usock.h>
+#include <libgsmd/libgsmd.h>
+
+#include "lgsm_internals.h"
+
+#define PT_BUF_SIZE 1024
+static char passthrough_buf[sizeof(struct gsmd_msg_hdr)+PT_BUF_SIZE];
+static char passthrough_rbuf[sizeof(struct gsmd_msg_hdr)+PT_BUF_SIZE];
+
+int lgsm_passthrough_send(struct lgsm_handle *lh, const char *tx)
+{
+ struct gsmd_msg_hdr *gmh = (struct gsmd_msg_hdr *)passthrough_buf;
+ char *tx_buf = (char *)gmh + sizeof(*gmh);
+ int len = strlen(tx);
+
+ if (len > PT_BUF_SIZE)
+ return -EINVAL;
+
+ gmh->version = GSMD_PROTO_VERSION;
+ gmh->msg_type = GSMD_MSG_PASSTHROUGH;
+ gmh->msg_subtype = GSMD_PASSTHROUGH_REQ;
+ gmh->len = len+1;
+ strcpy(tx_buf, tx);
+
+ if (lgsm_send(lh, gmh) < len+sizeof(*gmh))
+ return -EIO;
+
+ return gmh->id;
+}
+
+int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned int *rx_len)
+{
+ struct gsmd_msg_hdr *rgmh = (struct gsmd_msg_hdr *)passthrough_rbuf;
+ char *rx_buf = (char *)rgmh + sizeof(*rgmh);
+ int rc;
+
+ rc = lgsm_passthrough_send(lh, tx);
+ if (rc < 0)
+ return rc;
+
+ /* since we synchronously want to wait for a response, we need to
+ * _internally_ loop over incoming packets and call the callbacks for
+ * intermediate messages (if applicable) */
+ rc = lgsm_blocking_wait_packet(lh, rc, passthrough_rbuf,
+ sizeof(passthrough_rbuf));
+ if (rc <= 0)
+ return rc;
+
+ if (rc < sizeof(*rgmh))
+ return -EINVAL;
+
+ if (rc < sizeof(*rgmh) + rgmh->len)
+ return -EINVAL;
+
+ /* FIXME: make sure rx_buf is zero-terminated */
+ strcpy(rx, rx_buf);
+ *rx_len = rgmh->len;
+
+ return rx_len;
+}
Added: developers/seanchiang/gsm/src/libgsmd/libgsmd_phone.c
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/libgsmd_phone.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/libgsmd_phone.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,46 @@
+/* libgsmd phone related functions
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/misc.h>
+
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+
+#include "lgsm_internals.h"
+
+int lgsm_phone_power(struct lgsm_handle *lh, int power)
+{
+ int type;
+
+ if (power)
+ type = GSMD_PHONE_POWERUP;
+ else
+ type = GSMD_PHONE_POWERDOWN;
+
+ return lgsm_send_simple(lh, GSMD_MSG_PHONE, type);
+}
Added: developers/seanchiang/gsm/src/libgsmd/libgsmd_pin.c
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/libgsmd_pin.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/libgsmd_pin.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,78 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#include <gsmd/event.h>
+#include <libgsmd/libgsmd.h>
+
+static const char *pin_type_names[__NUM_GSMD_PIN] = {
+ [GSMD_PIN_NONE] = "NONE",
+ [GSMD_PIN_SIM_PIN] = "SIM PIN",
+ [GSMD_PIN_SIM_PUK] = "SIM PUK",
+ [GSMD_PIN_PH_SIM_PIN] = "Phone-to-SIM PIN",
+ [GSMD_PIN_PH_FSIM_PIN] = "Phone-to-very-first SIM PIN",
+ [GSMD_PIN_PH_FSIM_PUK] = "Phone-to-very-first SIM PUK",
+ [GSMD_PIN_SIM_PIN2] = "SIM PIN2",
+ [GSMD_PIN_SIM_PUK2] = "SIM PUK2",
+ [GSMD_PIN_PH_NET_PIN] = "Network personalization PIN",
+ [GSMD_PIN_PH_NET_PUK] = "Network personalizaiton PUK",
+ [GSMD_PIN_PH_NETSUB_PIN]= "Network subset personalisation PIN",
+ [GSMD_PIN_PH_NETSUB_PUK]= "Network subset personalisation PUK",
+ [GSMD_PIN_PH_SP_PIN] = "Service provider personalisation PIN",
+ [GSMD_PIN_PH_SP_PUK] = "Service provider personalisation PUK",
+ [GSMD_PIN_PH_CORP_PIN] = "Corporate personalisation PIN",
+ [GSMD_PIN_PH_CORP_PUK] = "Corporate personalisation PUK",
+};
+
+const char *lgsm_pin_name(enum gsmd_pin_type ptype)
+{
+ if (ptype >= __NUM_GSMD_PIN)
+ return "unknown";
+
+ return pin_type_names[ptype];
+}
+
+int lgsm_pin(struct lgsm_handle *lh, unsigned int type, char *pin, char *newpin)
+{
+ int rc;
+ struct {
+ struct gsmd_msg_hdr gmh;
+ struct gsmd_pin gp;
+ } __attribute__ ((packed)) *gm;
+
+ if (strlen(pin) > GSMD_PIN_MAXLEN ||
+ (newpin && strlen(newpin) > GSMD_PIN_MAXLEN) ||
+ type >= __NUM_GSMD_PIN)
+ return -EINVAL;
+
+ gm = (void *) lgsm_gmh_fill(GSMD_MSG_PIN, GSMD_PIN_INPUT,
+ sizeof(struct gsmd_pin));
+ if (!gm)
+ return -ENOMEM;
+
+ gm->gp.type = type;
+
+ gm->gp.pin[0] = '\0';
+ strcat(gm->gp.pin, pin);
+
+ switch (type) {
+ case GSMD_PIN_SIM_PUK:
+ case GSMD_PIN_SIM_PUK2:
+ /* GSM 07.07 explicitly states that only those two PUK types
+ * require a new pin to be specified! Don't know if this is a
+ * bug or a feature. */
+ if (!newpin)
+ return -EINVAL;
+ gm->gp.newpin[0] = '\0';
+ strcat(gm->gp.newpin, newpin);
+ break;
+ default:
+ break;
+ }
+ printf("sending pin='%s', newpin='%s'\n", gm->gp.pin, gm->gp.newpin);
+ rc = lgsm_send(lh, &gm->gmh);
+ free(gm);
+
+ return rc;
+}
Added: developers/seanchiang/gsm/src/libgsmd/libgsmd_voicecall.c
===================================================================
--- developers/seanchiang/gsm/src/libgsmd/libgsmd_voicecall.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/libgsmd/libgsmd_voicecall.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,115 @@
+/* libgsmd voice call support
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libgsmd/voicecall.h>
+
+#include "lgsm_internals.h"
+
+int lgsm_send_simple(struct lgsm_handle *lh, int type, int sub_type)
+{
+ struct gsmd_msg_hdr *gmh;
+ int rc;
+
+ gmh = lgsm_gmh_fill(type, sub_type, 0);
+ if (!gmh)
+ return -ENOMEM;
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);
+ return -EIO;
+ }
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsm_voice_out_init(struct lgsm_handle *lh,
+ const struct lgsm_addr *number)
+{
+ struct gsmd_msg_hdr *gmh;
+ struct gsmd_addr *ga;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_VOICECALL,
+ GSMD_VOICECALL_DIAL, sizeof(*ga));
+ if (!gmh)
+ return -ENOMEM;
+ ga = (struct gsmd_addr *) gmh->data;
+ ga->type = number->type; /* FIXME: is this correct? */
+ memcpy(ga->number, number->addr, sizeof(ga->number));
+ ga->number[sizeof(ga->number)-1] = '\0';
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsm_voice_dtmf(struct lgsm_handle *lh, char dtmf_char)
+{
+ struct gsmd_msg_hdr *gmh;
+ struct gsmd_dtmf *gd;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_VOICECALL,
+ GSMD_VOICECALL_DTMF, sizeof(*gd)+1);
+ if (!gmh)
+ return -ENOMEM;
+ gd = (struct gsmd_dtmf *) gmh->data;
+ gd->len = 1;
+ gd->dtmf[0] = dtmf_char;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gd)+1) {
+ lgsm_gmh_free(gmh);;
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsm_voice_in_accept(struct lgsm_handle *lh)
+{
+ return lgsm_send_simple(lh, GSMD_MSG_VOICECALL, GSMD_VOICECALL_ANSWER);
+}
+
+int lgsm_voice_hangup(struct lgsm_handle *lh)
+{
+ return lgsm_send_simple(lh, GSMD_MSG_VOICECALL, GSMD_VOICECALL_HANGUP);
+}
+
+int lgsm_voice_volume_set(struct lgsm_handle *lh, int volume)
+{
+ /* FIXME: we need to pass along the parameter */
+ return lgsm_send_simple(lh, GSMD_MSG_VOICECALL, GSMD_VOICECALL_VOL_SET);
+}
Added: developers/seanchiang/gsm/src/util/Makefile.am
===================================================================
--- developers/seanchiang/gsm/src/util/Makefile.am 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/Makefile.am 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,10 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS = -std=gnu99
+
+bin_PROGRAMS = libgsmd-tool
+
+libgsmd_tool_SOURCES = libgsmd-tool.c shell.c event.c pin.c atcmd.c
+libgsmd_tool_LDADD = ../libgsmd/libgsmd.la
+libgsmd_tool_LDFLAGS = -dynamic
+
+noinst_HEADERS = atcmd.h event.h pin.h shell.h
Added: developers/seanchiang/gsm/src/util/atcmd.c
===================================================================
--- developers/seanchiang/gsm/src/util/atcmd.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/atcmd.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,99 @@
+/* libgsmd tool
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <libgsmd/libgsmd.h>
+
+#define STDIN_BUF_SIZE 1024
+
+/* this is the handler for receiving passthrough responses */
+static int pt_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+ char *payload = (char *)gmh + sizeof(*gmh);
+ printf("RSTR=`%s'\n", payload);
+}
+
+int atcmd_main(struct lgsm_handle *lgsmh)
+{
+ int rc;
+ char buf[STDIN_BUF_SIZE+1];
+ char rbuf[STDIN_BUF_SIZE+1];
+ int rlen = sizeof(rbuf);
+ fd_set readset;
+
+ lgsm_register_handler(lgsmh, GSMD_MSG_PASSTHROUGH, &pt_msghandler);
+
+#if 1
+ fcntl(0, F_SETFD, O_NONBLOCK);
+ fcntl(1, F_SETFD, O_NONBLOCK);
+ fcntl(2, F_SETFD, O_NONBLOCK);
+ fcntl(lgsm_fd(lgsmh), F_SETFD, O_NONBLOCK);
+#endif
+
+ FD_ZERO(&readset);
+
+ while (1) {
+ fd_set readset;
+ int gsm_fd = lgsm_fd(lgsmh);
+
+ FD_SET(0, &readset);
+ FD_SET(gsm_fd, &readset);
+
+ rc = select(gsm_fd+1, &readset, NULL, NULL, NULL);
+ if (rc <= 0)
+ break;
+ if (FD_ISSET(gsm_fd, &readset)) {
+ /* we've received something on the gsmd socket, pass it
+ * on to the library */
+ rc = read(gsm_fd, buf, sizeof(buf));
+ if (rc <= 0) {
+ printf("ERROR reding from gsm_fd\n");
+ break;
+ }
+ rc = lgsm_handle_packet(lgsmh, buf, rc);
+ if (rc < 0)
+ printf("ERROR processing packet: %d(%s)\n", rc, strerror(rc));
+ }
+ if (FD_ISSET(0, &readset)) {
+ /* we've received something on stdin. send it as passthrough
+ * to gsmd */
+ rc = fscanf(stdin, "%s", buf);
+ if (rc == EOF) {
+ printf("EOF\n");
+ return -1;
+ }
+ if (rc <= 0) {
+ printf("NULL\n");
+ continue;
+ }
+ printf("STR=`%s'\n", buf);
+ }
+ /* this is a synchronous call for a passthrough command */
+ lgsm_passthrough(lgsmh, buf, rbuf, &rlen);
+ printf("RSTR=`%s'\n", rbuf);
+ }
+}
Added: developers/seanchiang/gsm/src/util/atcmd.h
===================================================================
--- developers/seanchiang/gsm/src/util/atcmd.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/atcmd.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,2 @@
+
+extern int atcmd_main(struct lgsm_handle *lgsmh);
Added: developers/seanchiang/gsm/src/util/event.c
===================================================================
--- developers/seanchiang/gsm/src/util/event.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/event.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,141 @@
+/* libgsmd tool
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <common/linux_list.h>
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/event.h>
+
+static int incall_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ printf("EVENT: Incoming call type = %u\n", aux->u.call.type);
+
+ return 0;
+}
+
+static int clip_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ printf("EVENT: Incoming call clip = %s\n", aux->u.clip.addr.number);
+
+ return 0;
+}
+
+static int colp_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ printf("EVENT: Outgoing call colp = %s\n", aux->u.colp.addr.number);
+
+ return 0;
+}
+
+static int netreg_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ printf("EVENT: Netreg ");
+
+ switch (aux->u.netreg.state) {
+ case 0:
+ printf("not searching for network ");
+ break;
+ case 1:
+ printf("registered (home network) ");
+ break;
+ case 2:
+ printf("searching for network ");
+ break;
+ case 3:
+ printf("registration denied ");
+ break;
+ case 5:
+ printf("registered (roaming) ");
+ break;
+ }
+
+ if (aux->u.netreg.lac)
+ printf("LocationAreaCode = 0x%04X ", aux->u.netreg.lac);
+ if (aux->u.netreg.ci)
+ printf("CellID = 0x%04X ", aux->u.netreg.ci);
+
+ printf("\n");
+
+ return 0;
+}
+
+static int sigq_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ printf("EVENT: Signal Quality: %u\n", aux->u.signal.sigq.rssi);
+ return 0;
+}
+
+static const char *cprog_names[] = {
+ [GSMD_CALLPROG_SETUP] = "SETUP",
+ [GSMD_CALLPROG_DISCONNECT] = "DISCONNECT",
+ [GSMD_CALLPROG_ALERT] = "ALERT",
+ [GSMD_CALLPROG_CALL_PROCEED] = "PROCEED",
+ [GSMD_CALLPROG_SYNC] = "SYNC",
+ [GSMD_CALLPROG_PROGRESS] = "PROGRESS",
+ [GSMD_CALLPROG_CONNECTED] = "CONNECTED",
+ [GSMD_CALLPROG_RELEASE] = "RELEASE",
+ [GSMD_CALLPROG_REJECT] = "REJECT",
+ [GSMD_CALLPROG_UNKNOWN] = "UNKNOWN",
+};
+
+static const char *cdir_names[] = {
+ [GSMD_CALL_DIR_MO] = "Outgoing",
+ [GSMD_CALL_DIR_MT] = "Incoming",
+ [GSMD_CALL_DIR_CCBS] = "CCBS",
+ [GSMD_CALL_DIR_MO_REDIAL] = "Outgoing Redial",
+};
+
+static int cprog_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ const char *name, *dir;
+
+ if (aux->u.call_status.prog >= ARRAY_SIZE(cprog_names))
+ name = "UNDEFINED";
+ else
+ name = cprog_names[aux->u.call_status.prog];
+
+ if (aux->u.call_status.dir >= ARRAY_SIZE(cdir_names))
+ dir = "";
+ else
+ dir = cdir_names[aux->u.call_status.dir];
+
+ printf("EVENT: %s Call Progress: %s\n", dir, name);
+
+ return 0;
+}
+
+int event_init(struct lgsm_handle *lh)
+{
+ int rc;
+
+ rc = lgsm_evt_handler_register(lh, GSMD_EVT_IN_CALL, &incall_handler);
+ rc |= lgsm_evt_handler_register(lh, GSMD_EVT_IN_CLIP, &clip_handler);
+ rc |= lgsm_evt_handler_register(lh, GSMD_EVT_OUT_COLP, &colp_handler);
+ rc |= lgsm_evt_handler_register(lh, GSMD_EVT_NETREG, &netreg_handler);
+ rc |= lgsm_evt_handler_register(lh, GSMD_EVT_SIGNAL, &sigq_handler);
+ rc |= lgsm_evt_handler_register(lh, GSMD_EVT_OUT_STATUS, &cprog_handler);
+
+ return rc;
+}
+
Added: developers/seanchiang/gsm/src/util/event.h
===================================================================
--- developers/seanchiang/gsm/src/util/event.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/event.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,2 @@
+
+extern int event_init(struct lgsm_handle *lh);
Added: developers/seanchiang/gsm/src/util/libgsmd-tool.c
===================================================================
--- developers/seanchiang/gsm/src/util/libgsmd-tool.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/libgsmd-tool.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,147 @@
+/* libgsmd tool
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <libgsmd/libgsmd.h>
+
+#include "pin.h"
+#include "event.h"
+#include "shell.h"
+#include "atcmd.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+static struct lgsm_handle *lgsmh;
+static int verbose = 0;
+
+enum mode_enum {
+ MODE_NONE,
+ MODE_SHELL,
+ MODE_EVENTLOG,
+ MODE_ATCMD,
+};
+
+static char *modes[] = {
+ [MODE_NONE] = "",
+ [MODE_SHELL] = "shell",
+ [MODE_EVENTLOG] = "eventlog",
+ [MODE_ATCMD] = "atcmd",
+};
+
+static int parse_mode(char *modestr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(modes); i++) {
+ if (!strcmp(modes[i], modestr))
+ return i;
+ }
+
+ return -1;
+}
+
+static struct option opts[] = {
+ { "help", 0, 0, 'h' },
+ { "version", 0, 0, 'V' },
+ { "verbose", 0, 0, 'v' },
+ { "mode", 1, 0, 'm' },
+ { "pin", 1, 0, 'p' },
+ { 0, 0, 0, 0 }
+};
+
+static void help(void)
+{
+ printf("Usage:\n"
+ "\t-h\t--help\tPrint this Help message\n"
+ "\t-V\t--version\tPrint version number\n"
+ "\t-v\t--verbose\tBe more verbose\n"
+ "\t-m\t--mode\tSet mode {shell,eventlog,atcmd}\n"
+ );
+}
+
+int main(int argc, char **argv)
+{
+ char *pin = NULL;
+ int rc, i, mode;
+
+ printf("libgsm-tool - (C) 2006 by Harald Welte\n"
+ "This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n");
+
+ while (1) {
+ int c, option_index = 0;
+ c = getopt_long(argc, argv, "vVhm:p:", opts, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ /* FIXME */
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ case 'm':
+ mode = parse_mode(optarg);
+ if (mode < 0) {
+ fprintf(stderr, "unknown/unsupported mode `%s'\n", optarg);
+ exit(2);
+ }
+ break;
+ case 'p':
+ pin = optarg;
+ break;
+ }
+ }
+
+ lgsmh = lgsm_init(LGSMD_DEVICE_GSMD);
+ if (!lgsmh) {
+ fprintf(stderr, "Can't connect to gsmd\n");
+ exit(1);
+ }
+
+ pin_init(lgsmh, pin);
+ event_init(lgsmh);
+
+ switch (mode) {
+ case MODE_ATCMD:
+ atcmd_main(lgsmh);
+ break;
+ case MODE_SHELL:
+ shell_main(lgsmh);
+ break;
+ }
+
+ exit(0);
+}
Added: developers/seanchiang/gsm/src/util/pin.c
===================================================================
--- developers/seanchiang/gsm/src/util/pin.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/pin.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,78 @@
+/* libgsmd tool
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/event.h>
+#include <libgsmd/pin.h>
+
+#define PIN_SIZE 8
+
+static char *pin;
+static char pinbuf[PIN_SIZE+1];
+static char pinbuf2[PIN_SIZE+1];
+
+static int pin_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ int rc;
+ int type = aux->u.pin.type;
+ char *newpin = NULL;
+
+ printf("EVENT: PIN request (type='%s') ", lgsm_pin_name(aux->u.pin.type));
+
+ /* FIXME: read pin from STDIN and send it back via lgsm_pin */
+ if (type == 1 && pin) {
+ printf("Auto-responding with pin `%s'\n", pin);
+ lgsm_pin(lh, type, pin, NULL);
+ } else {
+ do {
+ printf("Please enter %s: ", lgsm_pin_name(type));
+ rc = fscanf(stdin, "%8s", &pinbuf);
+ } while (rc < 1);
+
+ switch (type) {
+ case GSMD_PIN_SIM_PUK:
+ case GSMD_PIN_SIM_PUK2:
+ do {
+ printf("Please enter new PIN: ");
+ rc = fscanf(stdin, "%8s", &pinbuf2);
+ newpin = pinbuf2;
+ } while (rc < 1);
+ break;
+ default:
+ break;
+ }
+
+ return lgsm_pin(lh, type, pinbuf, newpin);
+ }
+
+ return 0;
+}
+
+int pin_init(struct lgsm_handle *lh, const char *pin_preset)
+{
+ pin = pin_preset;
+ return lgsm_evt_handler_register(lh, GSMD_EVT_PIN, &pin_handler);
+}
+
Added: developers/seanchiang/gsm/src/util/pin.h
===================================================================
--- developers/seanchiang/gsm/src/util/pin.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/pin.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,2 @@
+
+extern int pin_init(struct lgsm_handle *lh, const char *pin_preset);
Added: developers/seanchiang/gsm/src/util/shell.c
===================================================================
--- developers/seanchiang/gsm/src/util/shell.c 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/shell.c 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,307 @@
+/* libgsmd tool
+ *
+ * (C) 2006-2007 by OpenMoko, Inc.
+ * Written by Harald Welte <laforge at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/voicecall.h>
+#include <libgsmd/misc.h>
+#include <libgsmd/phonebook.h>
+#include <libgsmd/sms.h>
+#include <gsmd/usock.h>
+
+#define STDIN_BUF_SIZE 1024
+
+/* this is the handler for receiving passthrough responses */
+static int pt_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+ char *payload = (char *)gmh + sizeof(*gmh);
+ printf("RSTR=`%s'\n", payload);
+}
+
+/* this is the handler for receiving phonebook responses */
+static int pb_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+ struct gsmd_phonebook *gp;
+ struct gsmd_phonebook_support *gps;
+ char *payload;
+
+ switch (gmh->msg_subtype) {
+ case GSMD_PHONEBOOK_FIND:
+ break;
+ case GSMD_PHONEBOOK_READRG:
+ payload = (char *)gmh + sizeof(*gmh);
+ printf("%s\n", payload);
+ break;
+ case GSMD_PHONEBOOK_READ:
+ gp = (struct gsmd_phonebook *) ((char *)gmh + sizeof(*gmh));
+ printf("%d, %s, %d, %s\n", gp->index, gp->numb, gp->type, gp->text);
+ break;
+ case GSMD_PHONEBOOK_WRITE:
+ case GSMD_PHONEBOOK_DELETE:
+ payload = (char *)gmh + sizeof(*gmh);
+ printf("%s\n", payload);
+ break;
+ case GSMD_PHONEBOOK_GET_SUPPORT:
+ gps = (struct gsmd_phonebook_support *) ((char *)gmh + sizeof(*gmh));
+ printf("(1-%d), %d, %d\n", gps->index, gps->nlength, gps->tlength);
+ break;
+ default:
+ return -EINVAL;
+ }
+}
+
+/* this is the handler for receiving sms responses */
+static int sms_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+ char *payload;
+
+ switch (gmh->msg_subtype) {
+ case GSMD_SMS_LIST:
+ break;
+ case GSMD_SMS_READ:
+ case GSMD_SMS_SEND:
+ case GSMD_SMS_WRITE:
+ case GSMD_SMS_DELETE:
+ payload = (char *)gmh + sizeof(*gmh);
+ printf("%s\n", payload);
+ break;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int shell_help(void)
+{
+ printf( "\tA\tAnswer incoming call\n"
+ "\tD\tDial outgoing number\n"
+ "\tH\tHangup call\n"
+ "\tO\tPower On\n"
+ "\to\tPower Off\n"
+ "\tR\tRegister Netowrk\n"
+ "\tT\tSend DTMF Tone\n"
+ "\tpd\tPB Delete (pb=index)\n"
+ "\tpr\tPB Read (pr=index)\n"
+ "\tprr\tPB Read Range (prr=index1,index2)\n"
+ "\tpf\tPB Find (pff=indtext)\n"
+ "\tpw\tPB Write (pw=index,number,text)\n"
+ "\tps\tPB Support\n"
+ "\tsd\tSMS Delete (sd=index,delflg)\n"
+ "\tsl\tSMS List (sl=stat)\n"
+ "\tsr\tSMS Read (sr=index)\n"
+ "\tss\tSMS Send (ss=number,text)\n"
+ "\tsw\tSMS Write (sw=stat,number,text)\n"
+ "\tq\tQuit\n"
+ );
+}
+
+int shell_main(struct lgsm_handle *lgsmh)
+{
+ int rc;
+ char buf[STDIN_BUF_SIZE+1];
+ char rbuf[STDIN_BUF_SIZE+1];
+ int rlen = sizeof(rbuf);
+ fd_set readset;
+ char *ptr, *fcomma, *lcomma;
+
+ lgsm_register_handler(lgsmh, GSMD_MSG_PASSTHROUGH, &pt_msghandler);
+ lgsm_register_handler(lgsmh, GSMD_MSG_PHONEBOOK, &pb_msghandler);
+ lgsm_register_handler(lgsmh, GSMD_MSG_SMS, &sms_msghandler);
+
+ fcntl(0, F_SETFD, O_NONBLOCK);
+ fcntl(lgsm_fd(lgsmh), F_SETFD, O_NONBLOCK);
+
+ FD_ZERO(&readset);
+
+ printf("# ");
+
+ while (1) {
+ fd_set readset;
+ int gsm_fd = lgsm_fd(lgsmh);
+ FD_SET(0, &readset);
+ FD_SET(gsm_fd, &readset);
+
+ rc = select(gsm_fd+1, &readset, NULL, NULL, NULL);
+ if (rc <= 0)
+ break;
+ if (FD_ISSET(gsm_fd, &readset)) {
+ /* we've received something on the gsmd socket, pass it
+ * on to the library */
+ rc = read(gsm_fd, buf, sizeof(buf));
+ if (rc <= 0) {
+ printf("ERROR reding from gsm_fd\n");
+ break;
+ }
+ rc = lgsm_handle_packet(lgsmh, buf, rc);
+ }
+ if (FD_ISSET(0, &readset)) {
+ /* we've received something on stdin. */
+ printf("# ");
+ rc = fscanf(stdin, "%s", buf);
+ if (rc == EOF) {
+ printf("EOF\n");
+ return -1;
+ }
+ if (rc <= 0) {
+ printf("NULL\n");
+ continue;
+ }
+ if (!strcmp(buf, "h")) {
+ shell_help();
+ } else if (!strcmp(buf, "?")) {
+ shell_help();
+ } else if (!strcmp(buf, "H")) {
+ printf("Hangup\n");
+ lgsm_voice_hangup(lgsmh);
+ } else if (buf[0] == 'D') {
+ struct lgsm_addr addr;
+ if (strlen(buf) < 2)
+ continue;
+ printf("Dial %s\n", buf+1);
+ addr.type = 129;
+ strncpy(addr.addr, buf+1, sizeof(addr.addr)-1);
+ addr.addr[sizeof(addr.addr)-1] = '\0';
+ lgsm_voice_out_init(lgsmh, &addr);
+ } else if (!strcmp(buf, "A")) {
+ printf("Answer\n");
+ lgsm_voice_in_accept(lgsmh);
+ } else if (!strcmp(buf, "O")) {
+ printf("Power-On\n");
+ lgsm_phone_power(lgsmh, 1);
+ } else if (!strcmp(buf, "o")) {
+ printf("Power-Off\n");
+ lgsm_phone_power(lgsmh, 0);
+ } else if (!strcmp(buf, "R")) {
+ printf("Register\n");
+ lgsm_netreg_register(lgsmh, 0);
+ } else if (!strcmp(buf, "q")) {
+ exit(0);
+ } else if (buf[0] == 'T') {
+ if (strlen(buf) < 2)
+ continue;
+ printf("DTMF: %c\n", buf[1]);
+ lgsm_voice_dtmf(lgsmh, buf[1]);
+ } else if ( !strncmp(buf, "pd", 2)) {
+ printf("Delete Phonebook Entry\n");
+ ptr = strchr(buf, '=');
+ lgsmd_pb_del_entry(lgsmh, atoi(ptr+1));
+ } else if ( !strncmp(buf, "prr", 3)) {
+ printf("Read Phonebook Entries\n");
+ struct lgsm_phonebook_readrg pb_readrg;
+
+ ptr = strchr(buf, '=');
+ pb_readrg.index1 = atoi(ptr+1);
+ ptr = strchr(buf, ',');
+ pb_readrg.index2 = atoi(ptr+1);
+
+ lgsm_pb_read_entryies(lgsmh, &pb_readrg);
+ } else if ( !strncmp(buf, "pr", 2)) {
+ printf("Read Phonebook Entry\n");
+ ptr = strchr(buf, '=');
+ lgsm_pb_read_entry(lgsmh, atoi(ptr+1));
+ } else if ( !strncmp(buf, "pf", 2)) {
+ printf("Find Phonebook Entry\n");
+ struct lgsm_phonebook_find pb_find;
+
+ ptr = strchr(buf, '=');
+ strncpy(pb_find.findtext, ptr+1, sizeof(pb_find.findtext)-1);
+ pb_find.findtext[strlen(ptr+1)] = '\0';
+
+ lgsm_pb_find_entry(lgsmh, &pb_find);
+ } else if ( !strncmp(buf, "pw", 2)) {
+ printf("Write Phonebook Entry\n");
+ struct lgsm_phonebook pb;
+
+ ptr = strchr(buf, '=');
+ pb.index = atoi(ptr+1);
+
+ fcomma = strchr(buf, ',');
+ lcomma = strrchr(buf, ',');
+ strncpy(pb.numb, fcomma+1, (lcomma-fcomma-1));
+ pb.numb[(lcomma-fcomma-1)] = '\0';
+ if ( '+' == pb.numb[0] )
+ pb.type = LGSM_PB_ATYPE_INTL;
+ else
+ pb.type = LGSM_PB_ATYPE_OTHE;
+ strncpy(pb.text, lcomma+1, strlen(lcomma+1));
+ pb.text[strlen(lcomma+1)] = '\0';
+
+ lgsmd_pb_write_entry(lgsmh, &pb);
+ } else if ( !strncmp(buf, "ps", 2)) {
+ printf("Get Phonebook Support\n");
+ lgsm_pb_get_support(lgsmh);
+ } else if ( !strncmp(buf, "sd", 2)) {
+ printf("Delete SMS\n");
+ struct lgsm_sms_delete sms_del;
+
+ ptr = strchr(buf, '=');
+ sms_del.index = atoi(ptr+1);
+ ptr = strchr(buf, ',');
+ sms_del.delflg = atoi(ptr+1);
+
+ lgsmd_sms_delete(lgsmh, &sms_del);
+ } else if ( !strncmp(buf, "sl", 2)) {
+ printf("List SMS\n");
+ ptr = strchr(buf, '=');
+
+ lgsm_sms_list(lgsmh, atoi(ptr+1));
+ } else if ( !strncmp(buf, "sr", 2)) {
+ printf("Read SMS\n");
+ ptr = strchr(buf, '=');
+
+ lgsm_sms_read(lgsmh, atoi(ptr+1));
+ } else if ( !strncmp(buf, "ss", 2)) {
+ printf("Send SMS\n");
+ struct lgsm_sms sms;
+
+ ptr = strchr(buf, '=');
+ fcomma = strchr(buf, ',');
+ strncpy(sms.addr, ptr+1, (fcomma-ptr-1));
+ sms.addr[fcomma-ptr-1] = '\0';
+ strncpy(sms.data, fcomma+1, strlen(fcomma+1));
+ sms.data[strlen(fcomma+1)] = '\0';
+
+ lgsmd_sms_send(lgsmh, &sms);
+ } else if ( !strncmp(buf, "sw", 2)) {
+ printf("Write SMS\n");
+ struct lgsm_sms_write sms_write;
+
+ ptr = strchr(buf, '=');
+ sms_write.stat = atoi(ptr+1);
+ fcomma = strchr(buf, ',');
+ lcomma = strrchr(buf, ',');
+ strncpy(sms_write.sms.addr, fcomma+1, (lcomma-fcomma-1));
+ sms_write.sms.addr[lcomma-fcomma-1] = '\0';
+ strncpy(sms_write.sms.data, lcomma+1, strlen(lcomma+1));
+ sms_write.sms.data[strlen(lcomma+1)] = '\0';
+
+ lgsmd_sms_write(lgsmh, &sms_write);
+ } else {
+ printf("Unknown command `%s'\n", buf);
+ }
+ }
+ }
+}
Added: developers/seanchiang/gsm/src/util/shell.h
===================================================================
--- developers/seanchiang/gsm/src/util/shell.h 2007-03-20 07:24:45 UTC (rev 1425)
+++ developers/seanchiang/gsm/src/util/shell.h 2007-03-20 07:29:51 UTC (rev 1426)
@@ -0,0 +1,2 @@
+
+extern int shell_main(struct lgsm_handle *lgsmh);
More information about the commitlog
mailing list