pax_global_header00006660000000000000000000000064145363042410014514gustar00rootroot0000000000000052 comment=9c0309fcd3142411c921c14f7dd675cac086bab6 libmbim-1.31.2-dev/000077500000000000000000000000001453630424100137675ustar00rootroot00000000000000libmbim-1.31.2-dev/.gitignore000066400000000000000000000000171453630424100157550ustar00rootroot00000000000000*~ *.bz2 *.pyc libmbim-1.31.2-dev/.gitlab-ci.yml000066400000000000000000000042021453630424100164210ustar00rootroot00000000000000include: - project: freedesktop/ci-templates ref: 290b79e0e78eab67a83766f4e9691be554fc4afd file: - templates/ubuntu.yml stages: - container prep - build .common_variables: variables: FDO_UPSTREAM_REPO: mobile-broadband/libmbim FDO_DISTRIBUTION_VERSION: '20.04' FDO_DISTRIBUTION_TAG: '2021-11-05.1' FDO_DISTRIBUTION_PACKAGES: ca-certificates git gcc libgirepository1.0-dev libglib2.0-dev gtk-doc-tools libglib2.0-doc gobject-introspection bash-completion valac meson ninja-build help2man build container: extends: - .fdo.container-build@ubuntu - .common_variables stage: container prep only: - main - merge_requests - tags - schedules build-no-introspection: stage: build extends: - .fdo.distribution-image@ubuntu - .common_variables only: - main - merge_requests - tags - schedules script: - meson setup build --prefix=/usr -Dwerror=true -Dintrospection=false - ninja -C build - ninja -C build install build-debug: stage: build extends: - .fdo.distribution-image@ubuntu - .common_variables only: - main - merge_requests - tags - schedules script: - meson setup build --buildtype=debug --prefix=/usr -Dgtk_doc=true -Dwerror=true - ninja -C build - ninja -C build install - ninja -C build dist - ninja -C build uninstall build-no-deprecated: stage: build extends: - .fdo.distribution-image@ubuntu - .common_variables only: - main - merge_requests - tags - schedules script: - CFLAGS="-DMBIM_DISABLE_DEPRECATED" meson setup build --prefix=/usr -Dwerror=true -Dintrospection=false - ninja -C build - ninja -C build install build-release: stage: build extends: - .fdo.distribution-image@ubuntu - .common_variables only: - main - merge_requests - tags - schedules script: - meson setup build --buildtype=release --prefix=/usr -Dgtk_doc=true -Dwerror=true - ninja -C build - ninja -C build install - ninja -C build dist - ninja -C build uninstall libmbim-1.31.2-dev/AUTHORS000066400000000000000000000013221453630424100150350ustar00rootroot00000000000000Current maintainers: Aleksander Morgado Dan Williams Other contributors: Ben Chan Iñigo Martínez Som_SP som Yegor Yefremov Greg Suarez Bjørn Mork Daniele Palmas Eric Caruso Roshan Pius ZhangMingjie Ivan Mikhanchuk lywpljw Emil Ljungdahl Lubomir Rintel Prathmesh Prabhu Shawn J. Goff diekleinekuh Arnaud Desmier Boris Egorov Carlo Lobrano Christof Meerwald Collin McMillan David Ward Jack Song Jaroslav Stepanek King.Sun Marius B. Kotsbak Michal Mazur Nicolas Cavallari Philip Withnall Raju Scott Lee Shih-Yuan Lee (FourDollars) Yunlian Jiang goapunk ljw lvmaorui maorui lv wicadmin libmbim-1.31.2-dev/LICENSES/000077500000000000000000000000001453630424100151745ustar00rootroot00000000000000libmbim-1.31.2-dev/LICENSES/GPL-2.0-or-later.txt000066400000000000000000000432541453630424100204070ustar00rootroot00000000000000 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. Copyright (C) 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. , 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. libmbim-1.31.2-dev/LICENSES/LGPL-2.1-or-later.txt000066400000000000000000000636421453630424100205270ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libmbim-1.31.2-dev/NEWS000066400000000000000000000707051453630424100144770ustar00rootroot00000000000000 Overview of changes in libmbim 1.30 ---------------------------------------- * Build: ** Flag types are now generated in their own 'mbim-flag-types.[c|h]' files. ** A new 'enable_fuzzer' option is available to build LLVM LibFuzzer based unit testers. * New Intel Mutual Authentication service, including the following operations: * MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_FCC_LOCK * New Intel Tools service, including the following operations: * MBIM_CID_INTEL_TOOLS_TRACE_CONFIG * New Google service, including the following operations: * MBIM_CID_GOOGLE_CARRIER_LOCK * Extended the Microsoft-defined Basic Connect Extensions service, including the following operations: * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_RESET * libmbim-glib: ** mbim_message_validate() is updated to ensure that the given message is complete and not a partial fragment. ** mbim_device_command_finish() is updated to ensure that the returned message is complete and not a partial fragment. ** Updated string reading logic to perform a UTF-8 validity check explicitly when converting from UTF-16. ** The message and field parsing logic is updated to ensure unaligned values can be read, given that the new MBIM extensions no longer ensure field alignment. ** Additional field validations have been added when parsing TLVs, fragment headers and string/struct arrays. ** Fixed reading 'ms-struct-array' items that may have struct elements with variable size. ** Added new 'NONE' values in MbimCellularClass, MbimSimClass, MbimDataClass, MbimSmsCaps and MbimDataClassV3, so that all flag types have one to indicate an empty bitmask. ** New MbimTraceCommand enum, used in the Intel Tools service. ** New MbimCarrierLockStatus, MbimCarrierLockModemState and MbimCarrierLockCause enums, used in the Google service. ** Extended the list of MbimStatusError values with new errors reported by the operations in the Google service. ** The MbimSmsStatusFlag type is now defined as flags, not as enum. * mbimcli: ** New '--ms-device-reset' action. ** New '--google-set-carrier-lock' and '--google-query-carrier-lock' actions. ** New '--intel-query-fcc-lock' and '--intel-set-fcc-lock' actions. ** New '--intel-set-trace-config' and '--intel-query-trace-config' actions. ** New generic '--printable' action to decode MBIM messages. * mbim-proxy: ** New '--verbose-full' option to request enabling logs that include personal information. * Several other improvements and fixes. * All fixes and improvements that were backported to 1.28.x releases are also present in libmbim 1.30.0. Overview of changes in libmbim 1.28 ---------------------------------------- * There is no longer an upstream-provided source tarball, please use the signed git tag '1.28.0' instead to refer to the sources of this release. * License boilerplate in the sources has been changed by SPDX identifiers. * This version includes support for most operations in MBIM Extensions v2 (for 5G NSA) and v3 (for 5G SA). The enabling of the updated extensions requires the user of the library to explicitly request what version wants to be used, via the new 'MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2' or 'MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3' flags in the device open request. Please note that if one process enables the v2 or v3 support, it will apply to operations done by other processes as well. When using the proxy, the current version support is propagated to all clients of the proxy automatically. * The verbose message logging will now by default hide all fields that are considered personal information. Extended message logging including all field contents should be explicitly requested. * Build: ** The GNU autotools (autoconf/automake/libtool) support has been fully removed, this release requires the use of the meson build system. ** The 'instrospection' meson option is now a boolean. ** New boolean 'man' meson option to allow disabling the man page generation. * Extended the Basic Connect service, including the following operations: * MBIM_CID_BASIC_CONNECT_REGISTER_STATE (MBIMEx v2.0) * MBIM_CID_BASIC_CONNECT_PACKET_SERVICE (MBIMEx v2.0) * MBIM_CID_BASIC_CONNECT_SIGNAL_STATE (MBIMEx v2.0) * MBIM_CID_BASIC_CONNECT_SUBCRIBER_READY_STATUS (MBIMEx v3.0) * MBIM_CID_BASIC_CONNECT_PACKET_SERVICE (MBIMEx v3.0) * MBIM_CID_BASIC_CONNECT_CONNECT (MBIMEx v3.0) * MBIM_CID_BASIC_CONNECT_IP_PACKET_FILTERS (MBIMEx v3.0) * Extended the Microsoft-defined Basic Connect Extensions service, including the following operations: * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LOCATION_INFO_STATUS (MBIMEx v1.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PROVISIONED_CONTEXTS (MBIMEx v1.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_BASE_STATIONS_INFO (MBIMEx v1.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_VERSION (MBIMEx v2.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_CAPS (MBIMEx v3.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_MODEM_CONFIGURATION (MBIMEx v3.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS (MBIMEx v3.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_INFO (MBIMEx v3.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_BASE_STATIONS_INFO (MBIMEx v3.0) * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_WAKE_REASON (MBIMEx v3.0) * Extended the Microsoft-defined UICC Low Level Access service, including the following operations: * MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APPLICATION_LIST * MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_FILE_STATUS * MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_BINARY * MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD * New Microsoft-defined Voice Extensions service, including the following operations: * MBIM_CID_MS_VOICE_EXTENSIONS_NITZ * Extended the Intel-defined Firmware Update service, including the following operations: * MBIM_CID_INTEL_FIRMWARE_UPDATE_MODEM_REBOOT (MBIMEx v2.0) * New Intel-defined Thermal RF service, including the following operations: * MBIM_CID_INTEL_THERMAL_RF_RFIM * Extended the QDU service, including the following operations: * MBIM_CID_QDU_QUECTEL_REBOOT * MBIM_CID_QDU_QUECTEL_READ_VERSION * libmbim-glib: ** Updated the net link operations to support devices exposed by the wwan subsystem. ** New mbim_message_get_printable_full() method to print the contents of a given message specifying the specific MBIMEx version in use. ** New mbim_message_validate() method to validate the contents of the headers in a MBIM message, to be used before accessing its contents. ** Updated all MbimMessage getters so that an implicit validation is done in the g_return_* macros. This validation will not be done if those macros are disabled during build. ** New MBIM_DEVICE_CONSECUTIVE_TIMEOUTS signal in the MbimDevice to report the number of consecutive MBIM request timeouts detected. ** New mbim_device_[get|set|check]_ms_mbimex_version() methods to manage the MBIMEx version support in the MbimDevice. ** New MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_[V2|V3] flags in mbim_device_open_full() to allow enabling MBIMEx v2.0 or v3.0 support. ** New MbimTlv type to support the variable-sized fields in MBIMEx v3.0 operations. ** Ensure CLOSED state always in mbim_device_close(), even on error. ** Disallow device close if an open operation is ongoing. ** Extended MbimDataClass with 5G NSA/SA values, used in MBIMEx v2.0, and added new MbimDataClassV3 and MbimDataSubclass types, used in MBIMEX v3.0. ** Extended MbimCtrlCaps and MbimSubscriberReadyState with values reported in MBIMEX v3.0 extensions. ** New MbimWakeType, MbimAccessMediaType, MbimModemConfigurationStatus, MbimFrequencyRange, MbimContextRoamingControl, MbimContextMediaType, MbimContextState, MbimContextOperation, MbimMicoMode, MbimLadnInfo, MbimDefaultPduActivationHint, MbimDrxCycle, MbimSubscriberReadyStatusFlag enums used in MBIMEx v3.0 specific operations. ** New MbimUiccApplicationType, MbimUiccFileAccessibility, MbimUiccFileType and MbimUiccFileStructure enums, used in the MS UICC Low Level Access service. ** New MbimIntelServingCellInfo enum, used in the Intel Thermal RF service. ** New MbimIntelBootMode enum, used in the Intel Firmware Update service. ** New MbimQduQuectelRebootType and MbimQduQuectelVersionType enums used in the Quectel-defined QDU service updates. ** Extended the list of MbimNwError values with values from the 3GPP specs. ** Deprecated MBIM_NW_ERROR_UNKNOWN, use NONE instead. ** Deprecated MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_BLACKLIST, use NETWORK_DENYLIST instead. ** Fixed the public format for CDMA language in the SMS service. * mbimcli: ** New '--device-open-ms-mbimex-v2' option to request to enable MBIMEX v2.0 support. ** New '--device-open-ms-mbimex-v3' option to request to enable MBIMEX v3.0 support. ** New '--verbose-full' option to request enabling logs that include personal information. ** New '--set-ip-packet-filters' action. ** New '--set-provisioned-contexts' action. ** New '--set-signal-state' action. ** New '--set-network-idle-hint' action. ** New '--query-network-idle-hint' action. ** New '--set-emergency-mode' action. ** New '--query-emergency-mode' action. ** New '--set-service-activation' action. ** New '--ms-query-location-info-status' action. ** New '--ms-query-provisioned-contexts' action. ** New '--ms-set-provisioned-contexts' action. ** New '--ms-query-base-stations' action ** New '--ms-query-version' action. ** New '--ms-query-registration-parameters' action. ** New '--ms-set-registration-parameters' action. ** New '--ms-query-modem-configuration' action. ** New '--ms-query-wake-reason' action. ** New '--ms-query-uicc-application-list' action. ** New '--ms-query-uicc-file-status' action. ** New '--ms-query-uicc-read-binary' action. ** New '--ms-query-uicc-read-record' action. ** New '--ms-set-uicc-open-channel' action. ** New '--ms-set-uicc-close-channel' action. ** New '--ms-query-uicc-atr' action. ** New '--ms-set-uicc-apdu' action. ** New '--ms-set-uicc-reset' action. ** New '--ms-query-uicc-reset' action. ** New '--ms-set-uicc-terminal-capability' action. ** New '--ms-query-uicc-terminal-capability' action. ** New '--ms-query-nitz' action. ** New '--intel-query-rfim' action. ** New '--intel-set-rfim' action. ** Updated '--connect' action to deprecate 'apn' and prefer 'access-string'. ** Updated '--connect' action to support 'compression' and 'context-type'. ** Updated '--intel-modem-reboot' action to optionally receive the boot mode type argument. ** Fixed the Quectel specific operations so that they have the --quectel prefix and do not overwrite the ones in the Basic Connect service. * Several other improvements and fixes. The following features which were backported to 1.26.x releases are also present in libmbim 1.28.0: * mbim-codegen: explicitly require python3. * compat: deprecate the MbimLteAttachStatus type. * libmbim-glib: added support for a new Quectel service. * mbimcli: new '--quectel-query-radio-state' and '--quectel-set-radio-state' operations, which provide a way to FCC unlock EM120 modules in new Lenovo laptops. Overview of changes in libmbim 1.26 ---------------------------------------- * Build now requires GLib/GObject/GIO 2.56. * The GUdev optional build/runtime requirement is now fully dropped, it's no longer used. * Building from git no longer requires autoconf-archive, the needed AX_ macros are now shipped inside m4/. * In addition to building from a source release tarball, or building from git checkouts using the GNU autotools suite (autoconf/automake/libtool), this release includes the initial support for the meson build system. The meson port is not fully complete yet, as there are some missing things in the doc generation steps, but for system integration or development purposes, the port should be fully operational. This major release, including all its stable updates in the 1.26.x series, will be the last ones providing support for GNU autotools. The next major release will likely be a meson-only one, and will therefore not be based on a source release tarball any more, but on specific git tags instead. * Implemented new link management operations, exclusively for the cdc_mbim driver for now. These new operations allow creating or deleting VLAN network interfaces in order to run multiplexed data sessions over one single physical network interface. * Added support for the Microsoft-defined SAR service, including the following operations: ** MBIM_CID_MS_SAR_CONFIG ** MBIM_CID_MS_SAR_TRANSMISSION_STATUS * Added support for the Microsoft-defined UICC Low Level Access service, including the following operations: ** MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_ATR ** MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_OPEN_CHANNEL ** MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_CLOSE_CHANNEL ** MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APDU ** MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_TERMINAL_CAPABILITY ** MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_RESET * Added support for the Qualcomm-defined QDU service, including the following operations: ** MBIM_CID_QDU_UPDATE_SESSION ** MBIM_CID_QDU_FILE_OPEN ** MBIM_CID_QDU_FILE_WRITE * Extended the Microsoft-defined Basic Connect Extensions service, including the following operations: ** MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_CAPS ** MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_SYS_CAPS ** MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_SLOT_INFO_STATUS ** MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_SLOT_MAPPINGS * libmbim-glib: ** Logic updated to make sure full packets are written at once, instead of writing them in chunks. ** Updated the "LTE attach status" APIs in order to avoid creating unneeded struct types in the interface. The older methods have been deprecated and maintained in the library for compatibility purposes only. * mbim-proxy: ** Internal buffer size updated from 512 bytes to 4096 bytes. * mbimcli: ** New '--ms-set-sar-config' and '--ms-query-sar-config' actions. ** New '--ms-set-transmission-status' and '--ms-query-transmission-status' actions. ** Updated '--enter-pin', '--disable-pin' and '--unlock-pin' to allow other PIN types, not just assuming PIN1. ** New '--link-add', '--link-delete', '--link-list' and '--link-delete-all' actions. ** New '--ms-query-sys-caps' action. ** New '--ms-query-slot-info-status' action. ** New '--ms-query-device-slot-mappings' and '--ms-set-device-slot-mappings' actions. ** Renamed '--ms-query-lte-attach-status' to '--ms-query-lte-attach-info', and kept the old name for compatibility purposes. * mbim-network: ** When using the mbim-proxy, skip trying to manage the MBIM session and transaction ids as that is implicitly done by the proxy already. * Several other minor improvements and fixes. The following features which were backported to 1.24.x releases are also present in libmbim 1.26.0: * Fixed merged subscribe list reporting and handling in the proxy. * Fixed transaction id handling when multiple fragments are involved. * Fixed read overflows on malformed messages. * Skip warnings if descriptors file cannot be read, as in new MBIM backends other than cdc_mbim. Overview of changes in libmbim 1.24 ---------------------------------------- * Build now requires GLib/GObject/GIO 2.48. * Added new GObject Introspection support in the library, that can be explicitly requested during configure with --enable-introspection=yes. With the new introspection support, the libmbim-glib library can now be used directly from e.g. python programs, as in the example included with the release. * Added release version information to all the types and methods of the public library API, and added new per-version indices in the documentation. * Added g_autoptr() support to all public types. * Several other minor improvements and fixes. Overview of changes in libmbim 1.22 ---------------------------------------- * Build updated with several improvements: ** The build has been updated to use by default all warnings enabled by AX_COMPILER_FLAGS(), and therefore when building the release from a git checkout, autoconf-archive >= 2017.03.21 is now required. This new build dependency isn't required when building from the release tarball. ** Also when building from a git checkout, beware because by default --enable-compile-warnings=error is enabled, which implies -Werror. If you'd like to build from git and avoid -Werror, you should explicitly use --enable-compile-warnings=yes (to keep the warnings but without being errors), --enable-compile-warnings=no (to disable all the extra warnings enabled by default) or --disable-Werror (to unconditionally make all compiler warnings non-fatal). * libmbim-glib: ** Message parsing logic improved to avoid reading fields out of bounds, e.g. if the messages sent by the modem are malformed or not in line with the specs. * Several other minor improvements and fixes. The following features which were backported to 1.20.x releases are also present in libmbim 1.22.0: * libmbim-glib: fixed handling of fragmented indication messages. * mbimcli: added --query-provisioned-contexts. * mbim-proxy: fix logic when symlinks to cdc-wdm ports are used. Overview of changes in libmbim 1.20 ---------------------------------------- * Build updated with several fixes: ** Explicitly define max allowed GLib version. ** Fix issues with -Werror=type-limits. ** Made compiler warning options compatible with clang. * mbim-proxy: ** Fixed client subscription to service indications using wildcard. ** Fixed client subscription update logic when services/cids are being removed. ** New '--empty-timeout=[SECS}' option to specify the empty lifetime duration. ** New '--no-exit' option to avoid the proxy from exiting. * Several other minor improvements and fixes. The following features which were backported to 1.18.x releases are also present in libmbim 1.20.0: * mbim-proxy: default empty lifetime set to 300s. Overview of changes in libmbim 1.18 ---------------------------------------- * Build now looks for the correct python provider in the system during configure. * New Microsoft Basic Connect Extensions service, that includes new commands to manage Protocol Configuration Operations (PCO) as well as LTE attach status and settings. * libmbim-glib: ** Added support to fully print all message contents, including all fields, when traces are enabled. ** Added support for QMI indications over MBIM. ** Added additional cause codes to MbimNwError. ** Fixed signal emission in device, so that it's done before completing transaction task. * mbim-proxy: ** Fixed the management of subscribed events, so that the lists are maintained per-device. * mbimcli: ** New '--ms-query-pco' action. ** New '--ms-query-lte-attach-configuration' action. ** New '--ms-query-lte-attach-status' action. * Several other minor improvements and fixes. The following features which were backported to 1.16.x releases are also present in libmbim 1.18.0: * mbimcli: ** Fix SNR reporting in --atds-query-signal output. ** Longer timeout (60s) in --disconnect. ** Add "ip-type" property to --connect * libmbim-glib: ** Fix printing message in Intel Firmware Update service. ** Fix error reporting when unknown status. Overview of changes in libmbim 1.16 ---------------------------------------- * Build now requires GLib 2.36. * All the code base was ported to use the GTask based asynchronous operations support instead of the deprecated GSimpleAsyncResult. * New AT&T Device Service support, that includes operator-specific commands to query signal info or cell location. * New Intel Firmware Update Service support, that includes commands to request the Intel-based module to reboot in firmware download mode. * libmbim-glib: ** Added MBIM_STATUS_ERROR_CONTEXT_NOT_SUPPORTED to MbimStatusError. ** Avoid using iconv() directly for the UTF-16BE conversions, which makes it possible to use libmbim on systems with a stub iconv() implementation. ** Added support to detect already open MBIM channels on the Sierra Wireless EM7345. * mbimcli: ** New '--query-ip-packet-filters' action. ** New '--query-pin-list' action. ** New '--atds-query-signal' and '--atds-query-location' actions. ** New '--intel-modem-reboot' action. * Several other minor improvements and fixes. The following features which were backported to 1.14.x releases are also present in libmbim 1.16.0: * libmbim-glib: ** Prefer realpath() to canonicalize_file_name(). ** Added MBIM_READY_INFO_FLAG_NONE to MbimReadyInfoFlag. * mbim-proxy: ** Avoid receiving signals from the parent process. * mbimcli: ** Add cancellability to the query-ip-configuration action. Overview of changes in libmbim 1.14 ---------------------------------------- * New support for the 'QMI over MBIM' service, so that clients can use libqmi to build messages and libmbim to transport them. * The GUDev library, which we use to read the max message size from the USB descriptor, is now optional. When configuring, it will be used by default only if it's found. It can also be explicitly disabled using the new configure switch '--without-udev' or explicitly enabled using '--with-udev'. If GUDev isn't used, libmbim-glib will rely on sysfs directly. * libmbim-glib updates: ** Added support for building messages of custom services. * mbim-network updates: ** Added support for loading profiles from different paths using the new '--profile' option. This makes it possible to use mbim-network with multiple devices running in the same system. ** Added support to allow specifying APN user (APN_USER), password (APN_PASS) and authentication type (APN_AUTH) in the profile. ** Added support to allow using the mbim-proxy setup by configuring it in the profile file (PROXY=yes). * Several other minor improvements and fixes. The following features which were backported to 1.12.x releases are also present in libmbim 1.14.0: * mbimcli updates: ** Updated '--connect' arguments to allow specifying "key=value" pairs. The old legacy "[(APN),(PAP|CHAP|MSCHAPV2),(Username),(Password)]" format is kept as valid for backwards compatibility, although it should be assumed deprecated. ** Longer timeouts for connect/register operations. ** Report IP configuration when connected. ** Allow specifying session ids. * libmbim-glib updates: ** Probing retry interval increased to 5s. Overview of changes in libmbim 1.12 ---------------------------------------- * New `--enable-mbim-username' option during configure, which allows specifying which will be the user owning the /dev/cdc-wdm character devices of all MBIM modems (udev rules are installed to change file ownership). If this option is used, the mbim-proxy will only allow connections from processes running by the specified user or by the root user. * Function error messages can now be returned by the MbimDevice as responses to `Command', `Open' or `Close' messages. Users of the library should not assume the type of message returned to the previous actions. * The MbimProxy will monitor for 'NotOpened' errors, and when one detected it will directly close the internal MbimDevice. Any subsequent request sent by clients to that specific device will be aborted with a proxy-generated 'NotOpened' error. Clients will need to explicitly reopen the ports in that case. * The API now has a new mbim_message_response_get_result() method which allows getting a GError from a message which may be of a specific type (e.g. a `Command Done' message in response to a `Command' request) or instead the generic `Function Error' message type. Users of the library can use this new method to avoid assuming the type of message returned. E.g. the following check: mbim_message_command_done_get_result (response, &error); Can be updated as: mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error); And the same logic can be applied to `Open' and `Close' messages. * Other bugfixes and minor improvements: ** Attach timeout and idle events to the thread-default context. ** Fix bashisms in the mbim-network script. Overview of changes in libmbim 1.10 ---------------------------------------- * API break: Flag values in 'MbimRegistrationFlag' were updated to match the ones in the MBIM documentation. * Implemented a new 'mbim-proxy', which allows sharing a single MBIM control port among different processes. The usage of the proxy is optional, and can be requested by specifying the MBIM_DEVICE_OPEN_FLAGS_PROXY flag in the new mbim_device_open_full() method. The 'mbimcli' command line tool was also extended with a new '--device-open-proxy,-p' option, to allow requesting the use of the proxy process. * New 'removed' signal added to the MbimDevice, to notify when the underlying connection to the device is lost (e.g. lost connection to the mbim-proxy, or lost access to the MBIM control port). * Added support for registering and using custom services. * Added additional GMM cause codes to MbimNwError. * Transactions are now matched not only by ID but also by type. * Several other minor improvements and fixes. Overview of changes in libmbim 1.8 ---------------------------------------- * Added support for additional MBIM messages: MBIM_CID_MS_FIRMWARE_ID_GET MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY * Updated mbimcli with new commands: --set-radio-state --ms-query-firmware-id --ms-notify-host-shutdown --dss-connect --dss-disconnect * Several enums and functions were renamed, and marked as deprecated. A small layer is given to provide backwards compatibility. * Several other minor improvements and fixes. Overview of changes in libmbim 1.6 ---------------------------------------- * Updated mbimcli with new commands: --phonebook-query-configuration --phonebook-read --phonebook-read-all --phonebook-write --phonebook-delete --phonebook-delete-all * Added generation of man pages for mbimcli and mbim-network. * Several other minor improvements and fixes. Overview of changes in libmbim 1.4 ---------------------------------------- * Added support for additional MBIM messages: MBIM_SMS_CONFIGURATION MBIM_SMS_READ MBIM_SMS_SEND MBIM_SMS_DELETE MBIM_SMS_MESSAGE_STORE_STATUS MBIM_USSD MBIM_PHONEBOOK_CONFIGURATION MBIM_PHONEBOOK_READ MBIM_PHONEBOOK_DELETE MBIM_PHONEBOOK_WRITE MBIM_STK_PAC MBIM_STK_TERMINAL_RESPONSE MBIM_STK_ENVELOPE MBIM_DEVICE_SERVICE_SUBSCRIBER_LIST MBIM_AUTH_AKA MBIM_AUTH_AKAP MBIM_AUTH_SIM MBIM_PACKET_STATISTICS MBIM_NETWORK_IDLE_HINT MBIM_EMERGENCY_MODE MBIM_IP_PACKET_FILTERS MBIM_DSS_CONNECT MBIM_MULTICARRIER_PROVIDERS * Updated mbimcli with new commands: --query-packet-statistics * Use gtester to run unit tests. Overview of changes in libmbim 1.2 ---------------------------------------- * Added support for additional MBIM messages: MBIM_VISIBLE_PROVIDERS MBIM_PREFERRED_PROVIDERS MBIM_HOME_PROVIDER MBIM_SERVICE_ACTIVATION * Updated mbimcli with new commands: --query-visible-providers --query-preferred-providers --query-home-provider --query-signal-state --no-open --noop * Updated mbim-network with session support, keeping TRID sequence between commands. * New symbols to check library version. Overview of changes in libmbim 1.0 ---------------------------------------- * Updated mbimcli with new commands: --enter-pin --change-pin --enable-pin --disable-pin --enter-puk --query-registration-state --register-automatic --query-packet-service-state --attach-packet-service --detach-packet-service --query-connection-state --connect --disconnect --no-close * Removed the 'basic-connect' prefix from mbimcli commands. * New 'mbim-network' script to help launch a connection through the shell. * Added gtk-doc documentation Overview of changes in libmbim 0.0.1 ---------------------------------------- Initial release.libmbim-1.31.2-dev/README.md000066400000000000000000000017021453630424100152460ustar00rootroot00000000000000 # libmbim libmbim is a glib-based library for talking to WWAN modems and devices which speak the Mobile Broadband Interface Model (MBIM) protocol. ## Documentation Project documentation is kept in: https://modemmanager.org/docs/libmbim/ ## License * `libmbim-glib` library is released under the LGPL-2.1-or-later license. * `mbimcli` and `mbim-network` tools are released under the GPL-2.0-or-later license. License texts can be found under the `LICENSES` folder. ## Code of Conduct Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms, which you can find in the following link: https://www.freedesktop.org/wiki/CodeOfConduct CoC issues may be raised to the project maintainers at the following address: libmbim-devel-owner@lists.freedesktop.org libmbim-1.31.2-dev/RELEASING000066400000000000000000000051411453630424100152240ustar00rootroot00000000000000 The libmbim releases are generated using meson. 0.1) For major releases: * Increment mbim_minor_version and reset mbim_micro_version. * Assuming API/ABI compatibility, increment both current and age. 0.2) For stable branch releases: * Increment mbim_micro_version. 1) Add signed tag: $ git tag -s 1.28.0 The description included in the signed tag could be: Release 1.28.0 2) Configure and build the whole project, making sure gtk-doc and introspection are enabled: $ meson setup build \ --prefix=/usr \ --buildtype=release \ -Dintrospection=true \ -Dgtk_doc=true $ ninja -C build 3) Run the test suite and install locally: $ ninja -C build test $ sudo ninja -C build install 4) Create directories for the manpages and gtk-doc documentation in freedesktop.org, and also update the 'latest' links: $ ssh fd.o [fd.o] $ cd ${libmbim}/man/ [fd.o] $ rm latest [fd.o] $ mkdir -p ${VERSION} [fd.o] $ ln -s ${VERSION} latest [fd.o] $ cd ${libmbim}/libmbim-glib/ [fd.o] $ rm latest [fd.o] $ mkdir -p ${VERSION} [fd.o] $ ln -s ${VERSION} latest 5) Generate HTML for the manpages: $ roffit < build/docs/man/mbimcli.1 > mbimcli.1.html $ roffit < build/docs/man/mbim-network.1 > mbim-network.1.html 6) Upload manpages in HTML to freedesktop.org: $ scp *.1.html fd.o:${libmbim}/man/${VERSION}/ 7) Copy documentation from /usr/share/gtk-doc and fix online references manually $ mkdir html $ cp -r /usr/share/gtk-doc/html/libmbim-glib/* html/ $ for FILE in $(ls html/*.html); do \ sed -i 's|]* href="\.\./glib/[^"]*| 0: template += ( ' if (success) {\n' ' /* Memory allocated variables as output */\n') for field in fields: translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) # set as output memory allocated values inner_template = '' if field['format'] == 'string' or \ field['format'] == 'string-array' or \ field['format'] == 'struct' or \ field['format'] == 'ms-struct' or \ field['format'] == 'struct-array' or \ field['format'] == 'ref-struct-array' or \ field['format'] == 'ms-struct-array' or \ field['format'] == 'ipv4-array' or \ field['format'] == 'ipv6-array' or \ field['format'] == 'tlv' or \ field['format'] == 'tlv-string' or \ field['format'] == 'tlv-guint16-array' or \ field['format'] == 'tlv-list': inner_template = (' if (out_${field} != NULL)\n' ' *out_${field} = _${field};\n') template += (string.Template(inner_template).substitute(translations)) template += ( ' } else {\n') for field in fields: translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) translations['struct'] = field['struct-type'] if 'struct-type' in field else '' translations['struct_underscore'] = utils.build_underscore_name_from_camelcase (translations['struct']) inner_template = '' if field['format'] == 'string' or \ field['format'] == 'ipv4-array' or \ field['format'] == 'ipv6-array' or \ field['format'] == 'tlv-string' or \ field['format'] == 'tlv-guint16-array': inner_template = (' g_free (_${field});\n') elif field['format'] == 'string-array': inner_template = (' g_strfreev (_${field});\n') elif field['format'] == 'struct' or field['format'] == 'ms-struct': inner_template = (' ${struct_underscore}_free (_${field});\n') elif field['format'] == 'struct-array' or field['format'] == 'ref-struct-array' or field['format'] == 'ms-struct-array': inner_template = (' ${struct_underscore}_array_free (_${field});\n') elif field['format'] == 'tlv': inner_template = (' if (_${field})\n' ' mbim_tlv_unref (_${field});\n') elif field['format'] == 'tlv-list': inner_template = (' g_list_free_full (_${field}, (GDestroyNotify)mbim_tlv_unref);\n') template += (string.Template(inner_template).substitute(translations)) template += ( ' }\n') if fields != []: template += ( '\n' ' return success;\n' '}\n') else: template += ( '\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations)) """ Emit message printable """ def _emit_message_printable(self, cfile, message_type, fields): translations = { 'message' : self.name, 'underscore' : utils.build_underscore_name(self.name), 'service' : self.service, 'underscore' : utils.build_underscore_name (self.fullname), 'message_type' : message_type, 'message_type_upper' : message_type.upper() } template = ( '\n' 'static gchar *\n' '${underscore}_${message_type}_get_printable (\n' ' const MbimMessage *message,\n' ' const gchar *line_prefix,\n' ' GError **error)\n' '{\n' ' GString *str;\n') if fields != []: template += ( ' GError *inner_error = NULL;\n' ' guint32 offset = 0;\n') for field in fields: if 'always-read' in field: translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) inner_template = (' guint32 _${field};\n') template += (string.Template(inner_template).substitute(translations)) for field in fields: if 'personal-info' in field: template += ( ' gboolean show_field;\n' '\n' ' show_field = mbim_utils_get_show_personal_info ();\n') break if fields != []: if message_type == 'set' or message_type == 'query': template += ( '\n' ' if (!mbim_message_command_get_raw_information_buffer (message, NULL))\n' ' return NULL;\n') elif message_type == 'response': template += ( '\n' ' if (!mbim_message_command_done_get_raw_information_buffer (message, NULL))\n' ' return NULL;\n') elif message_type == 'notification': template += ( '\n' ' if (!mbim_message_indicate_status_get_raw_information_buffer (message, NULL))\n' ' return NULL;\n') template += ( '\n' ' str = g_string_new ("");\n') for field in fields: translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) translations['field_format'] = field['format'] translations['field_format_underscore'] = utils.build_underscore_name_from_camelcase(field['format']) translations['public'] = field['public-format'] if 'public-format' in field else field['format'] translations['field_name'] = field['name'] translations['array_size_field'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) if 'array-size-field' in field else '' translations['struct_name'] = utils.build_underscore_name_from_camelcase(field['struct-type']) if 'struct-type' in field else '' translations['struct_type'] = field['struct-type'] if 'struct-type' in field else '' translations['array_size'] = field['array-size'] if 'array-size' in field else '' if 'personal-info' in field: translations['if_show_field'] = 'if (show_field) ' else: translations['if_show_field'] = '' inner_template = ( '\n' ' g_string_append_printf (str, "%s ${field_name} = ", line_prefix);\n') if 'available-if' in field: condition = field['available-if'] translations['condition_field'] = utils.build_underscore_name_from_camelcase(condition['field']) translations['condition_operation'] = condition['operation'] translations['condition_value'] = condition['value'] inner_template += ( ' if (_${condition_field} ${condition_operation} ${condition_value}) {\n') else: inner_template += ( ' {\n') if 'always-read' in field: inner_template += ( ' if (!_mbim_message_read_guint32 (message, offset, &_${field}, &inner_error))\n' ' goto out;\n' ' offset += 4;\n' ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%" G_GUINT32_FORMAT "\'", _${field});\n' ' }\n') elif field['format'] == 'byte-array' or \ field['format'] == 'unsized-byte-array' or \ field['format'] == 'ref-byte-array' or \ field['format'] == 'uicc-ref-byte-array' or \ field['format'] == 'ref-byte-array-no-offset': inner_template += ( ' guint i;\n' ' const guint8 *tmp;\n' ' guint32 tmpsize;\n' '\n') if field['format'] == 'byte-array': inner_template += ( ' if (!_mbim_message_read_byte_array (message, 0, offset, FALSE, FALSE, ${array_size}, &tmp, NULL, &inner_error, FALSE))\n' ' goto out;\n' ' tmpsize = ${array_size};\n' ' offset += ${array_size};\n') elif field['format'] == 'unsized-byte-array': inner_template += ( ' if (!_mbim_message_read_byte_array (message, 0, offset, FALSE, FALSE, 0, &tmp, &tmpsize, &inner_error, FALSE))\n' ' goto out;\n' ' offset += tmpsize;\n') elif field['format'] == 'ref-byte-array': inner_template += ( ' if (!_mbim_message_read_byte_array (message, 0, offset, TRUE, TRUE, 0, &tmp, &tmpsize, &inner_error, FALSE))\n' ' goto out;\n' ' offset += 8;\n') elif field['format'] == 'uicc-ref-byte-array': inner_template += ( ' if (!_mbim_message_read_byte_array (message, 0, offset, TRUE, TRUE, 0, &tmp, &tmpsize, &inner_error, TRUE))\n' ' goto out;\n' ' offset += 8;\n') elif field['format'] == 'ref-byte-array-no-offset': inner_template += ( ' if (!_mbim_message_read_byte_array (message, 0, offset, FALSE, TRUE, 0, &tmp, &tmpsize, &inner_error, FALSE))\n' ' goto out;\n' ' offset += 4;\n') inner_template += ( ' ${if_show_field}{\n' ' g_string_append (str, "\'");\n' ' for (i = 0; i < tmpsize; i++)\n' ' g_string_append_printf (str, "%02x%s", tmp[i], (i == (tmpsize - 1)) ? "" : ":" );\n' ' g_string_append (str, "\'");\n' ' }\n') elif field['format'] == 'uuid': inner_template += ( ' MbimUuid tmp;\n' ' g_autofree gchar *tmpstr = NULL;\n' '\n' ' if (!_mbim_message_read_uuid (message, offset, NULL, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 16;\n' ' tmpstr = mbim_uuid_get_printable (&tmp);\n' ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%s\'", tmpstr);\n' ' }\n') elif field['format'] == 'guint16' or \ field['format'] == 'guint32' or \ field['format'] == 'guint64': inner_template += ( ' ${field_format} tmp;\n' '\n') if field['format'] == 'guint16' : inner_template += ( ' if (!_mbim_message_read_guint16 (message, offset, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 2;\n') elif field['format'] == 'guint32' : inner_template += ( ' if (!_mbim_message_read_guint32 (message, offset, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 4;\n') elif field['format'] == 'guint64' : inner_template += ( ' if (!_mbim_message_read_guint64 (message, offset, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 8;\n') if 'public-format' in field: if field['public-format'] == 'gboolean': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%s\'", tmp ? "true" : "false");\n' ' }\n' '\n') else: translations['public_underscore'] = utils.build_underscore_name_from_camelcase(field['public-format']) translations['public_underscore_upper'] = utils.build_underscore_name_from_camelcase(field['public-format']).upper() inner_template += ( ' ${if_show_field}{\n' '#if defined __${public_underscore_upper}_IS_ENUM__\n' ' g_string_append_printf (str, "\'%s\'", ${public_underscore}_get_string ((${public})tmp));\n' '#elif defined __${public_underscore_upper}_IS_FLAGS__\n' ' g_autofree gchar *tmpstr = NULL;\n' '\n' ' tmpstr = ${public_underscore}_build_string_from_mask ((${public})tmp);\n' ' g_string_append_printf (str, "\'%s\'", tmpstr);\n' '#else\n' '# error neither enum nor flags\n' '#endif\n' ' }\n' '\n') elif field['format'] == 'guint16': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%" G_GUINT16_FORMAT "\'", tmp);\n' ' }\n') elif field['format'] == 'guint32': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%" G_GUINT32_FORMAT "\'", tmp);\n' ' }\n') elif field['format'] == 'guint64': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%" G_GUINT64_FORMAT "\'", tmp);\n' ' }\n') elif field['format'] == 'string': translations['encoding'] = 'MBIM_STRING_ENCODING_UTF8' if 'encoding' in field and field['encoding'] == 'utf-8' else 'MBIM_STRING_ENCODING_UTF16' inner_template += ( ' g_autofree gchar *tmp = NULL;\n' '\n' ' if (!_mbim_message_read_string (message, 0, offset, ${encoding}, &tmp, NULL, &inner_error))\n' ' goto out;\n' ' offset += 8;\n' ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%s\'", tmp);\n' ' }\n') elif field['format'] == 'string-array': translations['encoding'] = 'MBIM_STRING_ENCODING_UTF8' if 'encoding' in field and field['encoding'] == 'utf-8' else 'MBIM_STRING_ENCODING_UTF16' inner_template += ( ' g_auto(GStrv) tmp = NULL;\n' ' guint i;\n' '\n' ' if (!_mbim_message_read_string_array (message, _${array_size_field}, 0, offset, ${encoding}, &tmp, &inner_error))\n' ' goto out;\n' ' offset += (8 * _${array_size_field});\n' '\n' ' ${if_show_field}{\n' ' g_string_append (str, "\'");\n' ' for (i = 0; i < _${array_size_field}; i++) {\n' ' g_string_append (str, tmp[i]);\n' ' if (i < (_${array_size_field} - 1))\n' ' g_string_append (str, ", ");\n' ' }\n' ' g_string_append (str, "\'");\n' ' }\n') elif field['format'] == 'struct': inner_template += ( ' g_autoptr(${struct_type}) tmp = NULL;\n' ' guint32 bytes_read = 0;\n' '\n' ' tmp = _mbim_message_read_${struct_name}_struct (message, offset, 0, &bytes_read, &inner_error);\n' ' if (!tmp)\n' ' goto out;\n' ' offset += bytes_read;\n' ' ${if_show_field}{\n' ' g_autofree gchar *new_line_prefix = NULL;\n' ' g_autofree gchar *struct_str = NULL;\n' '\n' ' g_string_append (str, "{\\n");\n' ' new_line_prefix = g_strdup_printf ("%s ", line_prefix);\n' ' struct_str = _mbim_message_print_${struct_name}_struct (tmp, new_line_prefix);\n' ' g_string_append (str, struct_str);\n' ' g_string_append_printf (str, "%s }", line_prefix);\n' ' }\n') elif field['format'] == 'ms-struct': inner_template += ( ' g_autoptr(${struct_type}) tmp = NULL;\n' '\n' ' if (!_mbim_message_read_${struct_name}_ms_struct (message, offset, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 8;\n' ' ${if_show_field}{\n' ' g_autofree gchar *new_line_prefix = NULL;\n' '\n' ' g_string_append (str, "{\\n");\n' ' new_line_prefix = g_strdup_printf ("%s ", line_prefix);\n' ' if (tmp) {\n' ' g_autofree gchar *struct_str = NULL;\n' ' struct_str = _mbim_message_print_${struct_name}_struct (tmp, new_line_prefix);\n' ' g_string_append (str, struct_str);\n' ' }\n' ' g_string_append_printf (str, "%s }", line_prefix);\n' ' }\n') elif field['format'] == 'struct-array' or field['format'] == 'ref-struct-array' or field['format'] == 'ms-struct-array': inner_template += ( ' g_autoptr(${struct_type}Array) tmp = NULL;\n') if field['format'] == 'ms-struct-array': inner_template += ( ' guint32 tmp_count = 0;\n') inner_template += ( '\n') if field['format'] == 'struct-array': inner_template += ( ' if (!_mbim_message_read_${struct_name}_struct_array (message, _${array_size_field}, offset, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 4;\n') elif field['format'] == 'ref-struct-array': inner_template += ( ' if (!_mbim_message_read_${struct_name}_ref_struct_array (message, _${array_size_field}, offset, &tmp, &inner_error))\n' ' goto out;\n' ' offset += (8 * _${array_size_field});\n') elif field['format'] == 'ms-struct-array': inner_template += ( ' if (!_mbim_message_read_${struct_name}_ms_struct_array (message, offset, &tmp_count, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 8;\n') inner_template += ( ' ${if_show_field}{\n' ' guint i;\n' ' g_autofree gchar *new_line_prefix = NULL;\n' '\n' ' new_line_prefix = g_strdup_printf ("%s ", line_prefix);\n' ' g_string_append (str, "\'{\\n");\n') if field['format'] == 'ms-struct-array': inner_template += ( ' for (i = 0; i < tmp_count; i++) {\n') else: inner_template += ( ' for (i = 0; i < _${array_size_field}; i++) {\n') inner_template += ( ' g_autofree gchar *struct_str = NULL;\n' '\n' ' g_string_append_printf (str, "%s [%u] = {\\n", line_prefix, i);\n' ' struct_str = _mbim_message_print_${struct_name}_struct (tmp[i], new_line_prefix);\n' ' g_string_append (str, struct_str);\n' ' g_string_append_printf (str, "%s },\\n", line_prefix);\n' ' }\n' ' g_string_append_printf (str, "%s }\'", line_prefix);\n' ' }\n') elif field['format'] == 'ref-ipv4' or \ field['format'] == 'ipv4-array' or \ field['format'] == 'ref-ipv6' or \ field['format'] == 'ipv6-array': if field['format'] == 'ref-ipv4': inner_template += ( ' const MbimIPv4 *tmp;\n') elif field['format'] == 'ipv4-array': inner_template += ( ' g_autofree MbimIPv4 *tmp = NULL;\n') elif field['format'] == 'ref-ipv6': inner_template += ( ' const MbimIPv6 *tmp;\n') elif field['format'] == 'ipv6-array': inner_template += ( ' g_autofree MbimIPv6 *tmp = NULL;\n') inner_template += ( ' guint array_size;\n' ' guint i;\n' '\n') if field['format'] == 'ref-ipv4': inner_template += ( ' array_size = 1;\n' ' if (!_mbim_message_read_ipv4 (message, offset, TRUE, &tmp, NULL, &inner_error))\n' ' goto out;\n' ' offset += 4;\n') elif field['format'] == 'ipv4-array': inner_template += ( ' array_size = _${array_size_field};\n' ' if (!_mbim_message_read_ipv4_array (message, _${array_size_field}, offset, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 4;\n') elif field['format'] == 'ref-ipv6': inner_template += ( ' array_size = 1;\n' ' if (!_mbim_message_read_ipv6 (message, offset, TRUE, &tmp, NULL, &inner_error))\n' ' goto out;\n' ' offset += 4;\n') elif field['format'] == 'ipv6-array': inner_template += ( ' array_size = _${array_size_field};\n' ' if (!_mbim_message_read_ipv6_array (message, _${array_size_field}, offset, &tmp, &inner_error))\n' ' goto out;\n' ' offset += 4;\n') inner_template += ( ' ${if_show_field}{\n' ' g_string_append (str, "\'");\n' ' if (tmp) {\n' ' for (i = 0; i < array_size; i++) {\n' ' g_autoptr(GInetAddress) addr = NULL;\n' ' g_autofree gchar *tmpstr = NULL;\n' '\n') if field['format'] == 'ref-ipv4' or \ field['format'] == 'ipv4-array': inner_template += ( ' addr = g_inet_address_new_from_bytes ((guint8 *)&(tmp[i].addr), G_SOCKET_FAMILY_IPV4);\n') elif field['format'] == 'ref-ipv6' or \ field['format'] == 'ipv6-array': inner_template += ( ' addr = g_inet_address_new_from_bytes ((guint8 *)&(tmp[i].addr), G_SOCKET_FAMILY_IPV6);\n') inner_template += ( ' tmpstr = g_inet_address_to_string (addr);\n' ' g_string_append_printf (str, "%s", tmpstr);\n' ' if (i < (array_size - 1))\n' ' g_string_append (str, ", ");\n' ' }\n' ' }\n' ' g_string_append (str, "\'");\n' ' }\n') elif field['format'] == 'tlv' or \ field['format'] == 'tlv-string' or \ field['format'] == 'tlv-guint16-array': inner_template += ( ' g_autoptr(MbimTlv) tmp = NULL;\n' ' guint32 bytes_read = 0;\n' '\n' ' if (!_mbim_message_read_tlv (message, offset, &tmp, &bytes_read, &inner_error))\n' ' goto out;\n' ' offset += bytes_read;\n' '\n' ' ${if_show_field}{\n' ' g_autofree gchar *tlv_str = NULL;\n' ' g_autofree gchar *new_line_prefix = NULL;\n' '\n' ' new_line_prefix = g_strdup_printf ("%s ", line_prefix);\n' ' tlv_str = _mbim_tlv_print (tmp, new_line_prefix);\n' ' g_string_append_printf (str, "\'%s\'", tlv_str);\n' ' }\n') elif field['format'] == 'tlv-list': inner_template += ( ' GList *tmp = NULL;\n' ' guint32 bytes_read = 0;\n' '\n' ' if (!_mbim_message_read_tlv_list (message, offset, &tmp, &bytes_read, &inner_error))\n' ' goto out;\n' ' offset += bytes_read;\n' '\n' ' ${if_show_field}{\n' ' g_autofree gchar *new_line_prefix = NULL;\n' ' GList *walker = NULL;\n' '\n' ' new_line_prefix = g_strdup_printf ("%s ", line_prefix);\n' ' g_string_append (str, "\'[ ");\n' ' for (walker = tmp; walker; walker = g_list_next (walker)) {\n' ' g_autofree gchar *tlv_str = NULL;\n' '\n' ' tlv_str = _mbim_tlv_print ((MbimTlv *)walker->data, new_line_prefix);\n' ' g_string_append_printf (str, "%s,", tlv_str);\n' ' }\n' ' g_string_append_printf (str, "\\n%s ]\'", line_prefix);\n' ' }\n' ' g_list_free_full (tmp, (GDestroyNotify)mbim_tlv_unref);\n') else: raise ValueError('Field format \'%s\' not printable' % field['format']) if 'personal-info' in field: inner_template += ( ' if (!show_field)\n' ' g_string_append (str, "\'###\'");\n') inner_template += ( ' }\n' ' g_string_append (str, "\\n");\n') template += (string.Template(inner_template).substitute(translations)) if fields != []: template += ( '\n' ' out:\n' ' if (inner_error) {\n' ' g_string_append_printf (str, "n/a: %s", inner_error->message);\n' ' g_clear_error (&inner_error);\n' ' }\n') template += ( '\n' ' return g_string_free (str, FALSE);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) """ Emit the section content """ def emit_section_content(self, sfile): translations = { 'name_dashed' : utils.build_dashed_name(self.name), 'underscore' : utils.build_underscore_name(self.fullname) } template = ( '\n' '\n') sfile.write(string.Template(template).substitute(translations)) if self.has_query: template = ( '${underscore}_query_new\n') sfile.write(string.Template(template).substitute(translations)) if self.has_set: template = ( '${underscore}_set_new\n') sfile.write(string.Template(template).substitute(translations)) if self.has_response: template = ( '${underscore}_response_parse\n') sfile.write(string.Template(template).substitute(translations)) if self.has_notification: template = ( '${underscore}_notification_parse\n') sfile.write(string.Template(template).substitute(translations)) libmbim-1.31.2-dev/build-aux/mbim-codegen/ObjectList.py000066400000000000000000000273561453630424100226400ustar00rootroot00000000000000# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- # # SPDX-License-Identifier: LGPL-2.1-or-later # # Copyright (C) 2013 - 2018 Aleksander Morgado # import string from Message import Message from Struct import Struct import utils """ Check field to see if it holds a struct """ def set_struct_usage(struct, fields): for field in fields: if field['format'] == 'struct' and field['struct-type'] == struct.name: struct.single_member = True break if field['format'] == 'ms-struct' and field['struct-type'] == struct.name: struct.single_member = True struct.ms_struct = True break if field['format'] == 'ref-struct-array' and field['struct-type'] == struct.name: struct.ref_struct_array_member = True break if field['format'] == 'struct-array' and field['struct-type'] == struct.name: struct.struct_array_member = True break if field['format'] == 'ms-struct-array' and field['struct-type'] == struct.name: struct.ms_struct_array_member = True break """ The ObjectList class handles the generation of all commands and types for a given specific service """ class ObjectList: """ Constructor """ def __init__(self, objects_dictionary): self.command_list = [] self.struct_list = [] self.service_list = [] # Loop items in the list, creating Message objects for the messages service_iter = '' mbimex_service_iter = '' mbimex_version_iter = '' for object_dictionary in objects_dictionary: if object_dictionary['type'] == 'Command': if service_iter == '': raise ValueError('Service name not specified before the first command') self.command_list.append(Message(service_iter, mbimex_service_iter, mbimex_version_iter, object_dictionary)) elif object_dictionary['type'] == 'Struct': self.struct_list.append(Struct(service_iter, mbimex_service_iter, mbimex_version_iter, object_dictionary)) elif object_dictionary['type'] == 'Service': service_iter = object_dictionary['name'] self.service_list.append(service_iter) if 'mbimex-service' in object_dictionary: mbimex_service_iter = object_dictionary['mbimex-service'] mbimex_version_iter = object_dictionary['mbimex-version'] else: mbimex_service_iter = '' mbimex_version_iter = '' else: raise ValueError('Cannot handle object type \'%s\'' % object_dictionary['type']) if not self.service_list: raise ValueError('Service name not specified') # Populate struct usages for struct in self.struct_list: for command in self.command_list: set_struct_usage(struct, command.query) set_struct_usage(struct, command.set) set_struct_usage(struct, command.response) set_struct_usage(struct, command.notification) """ Emit the structs and commands handling implementation """ def emit(self, hfile, cfile): # Emit all structs for item in self.struct_list: item.emit(hfile, cfile) # Emit all commands for item in self.command_list: item.emit(hfile, cfile) """ Emit support for printing messages in a single service """ def emit_printable_service(self, hfile, cfile, service): translations = { 'service_underscore' : utils.build_underscore_name(service), 'service' : service } template = ( '\n' 'G_GNUC_INTERNAL\n' 'gchar *\n' '__mbim_message_${service_underscore}_get_printable_fields (\n' ' const MbimMessage *message,\n' ' const gchar *line_prefix,\n' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' 'static const GetPrintableCallbacks ${service_underscore}_get_printable_callbacks[] = {\n') for item in self.command_list: if item.service == service: translations['message'] = utils.build_underscore_name (item.fullname) translations['cid'] = item.cid_enum_name inner_template = ( ' [${cid}] = {\n') if item.has_query: inner_template += ( ' .query_cb = ${message}_query_get_printable,\n') if item.has_set: inner_template += ( ' .set_cb = ${message}_set_get_printable,\n') if item.has_response: inner_template += ( ' .response_cb = ${message}_response_get_printable,\n') if item.has_notification: inner_template += ( ' .notification_cb = ${message}_notification_get_printable,\n') inner_template += ( ' },\n') template += (string.Template(inner_template).substitute(translations)) template += ( '};\n' '\n' 'gchar *\n' '__mbim_message_${service_underscore}_get_printable_fields (\n' ' const MbimMessage *message,\n' ' const gchar *line_prefix,\n' ' GError **error)\n' '{\n' ' guint32 cid;\n' '\n' ' switch (mbim_message_get_message_type (message)) {\n' ' case MBIM_MESSAGE_TYPE_COMMAND: {\n' ' cid = mbim_message_command_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (${service_underscore}_get_printable_callbacks)) {\n' ' switch (mbim_message_command_get_command_type (message)) {\n' ' case MBIM_MESSAGE_COMMAND_TYPE_QUERY:\n' ' if (${service_underscore}_get_printable_callbacks[cid].query_cb)\n' ' return ${service_underscore}_get_printable_callbacks[cid].query_cb (message, line_prefix, error);\n' ' break;\n' ' case MBIM_MESSAGE_COMMAND_TYPE_SET:\n' ' if (${service_underscore}_get_printable_callbacks[cid].set_cb)\n' ' return ${service_underscore}_get_printable_callbacks[cid].set_cb (message, line_prefix, error);\n' ' break;\n' ' case MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN:\n' ' default:\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Invalid command type\");\n' ' return NULL;\n' ' }\n' ' }\n' ' break;\n' ' }\n' '\n' ' case MBIM_MESSAGE_TYPE_COMMAND_DONE:\n' ' cid = mbim_message_command_done_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (${service_underscore}_get_printable_callbacks)) {\n' ' if (${service_underscore}_get_printable_callbacks[cid].response_cb)\n' ' return ${service_underscore}_get_printable_callbacks[cid].response_cb (message, line_prefix, error);\n' ' }\n' ' break;\n' '\n' ' case MBIM_MESSAGE_TYPE_INDICATE_STATUS:\n' ' cid = mbim_message_indicate_status_get_cid (message);\n' ' if (cid < G_N_ELEMENTS (${service_underscore}_get_printable_callbacks)) {\n' ' if (${service_underscore}_get_printable_callbacks[cid].notification_cb)\n' ' return ${service_underscore}_get_printable_callbacks[cid].notification_cb (message, line_prefix, error);\n' ' }\n' ' break;\n' '\n' ' case MBIM_MESSAGE_TYPE_OPEN: \n' ' case MBIM_MESSAGE_TYPE_CLOSE: \n' ' case MBIM_MESSAGE_TYPE_INVALID: \n' ' case MBIM_MESSAGE_TYPE_HOST_ERROR: \n' ' case MBIM_MESSAGE_TYPE_OPEN_DONE: \n' ' case MBIM_MESSAGE_TYPE_CLOSE_DONE: \n' ' case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: \n' ' default:\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"No contents expected in this message type\");\n' ' return NULL;\n' ' }\n' '\n' ' g_set_error (error,\n' ' MBIM_CORE_ERROR,\n' ' MBIM_CORE_ERROR_UNSUPPORTED,\n' ' \"Unsupported message\");\n' ' return NULL;\n' '}\n') cfile.write(string.Template(template).substitute(translations)) def emit_printable(self, hfile, cfile): template = ( '\n' '/*****************************************************************************/\n' '/* Service helpers for printable fields */\n' '\n' '#if defined (LIBMBIM_GLIB_COMPILATION)\n') hfile.write(template) template = ( '\n' 'typedef struct {\n' ' gchar * (* query_cb) (const MbimMessage *message, const gchar *line_prefix, GError **error);\n' ' gchar * (* set_cb) (const MbimMessage *message, const gchar *line_prefix, GError **error);\n' ' gchar * (* response_cb) (const MbimMessage *message, const gchar *line_prefix, GError **error);\n' ' gchar * (* notification_cb) (const MbimMessage *message, const gchar *line_prefix, GError **error);\n' '} GetPrintableCallbacks;\n') cfile.write(template) for service in self.service_list: self.emit_printable_service(hfile, cfile, service) template = ( '\n' '#endif\n') hfile.write(template) """ Emit the section for a single service """ def emit_sections_service(self, sfile, service): translations = { 'service_dashed' : utils.build_dashed_name(service), 'service' : service } # Emit section header template = ( '\n' '
\n' 'mbim-${service_dashed}\n' '${service}\n') sfile.write(string.Template(template).substitute(translations)) # Emit subsection per type for struct in self.struct_list: if struct.service == service: struct.emit_section_content(sfile) # Emit subsection per command for command in self.command_list: if command.service == service: command.emit_section_content(sfile) sfile.write( '
\n') def emit_sections(self, sfile): for service in self.service_list: self.emit_sections_service(sfile, service) libmbim-1.31.2-dev/build-aux/mbim-codegen/Struct.py000066400000000000000000001603171453630424100220550ustar00rootroot00000000000000# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*- # # SPDX-License-Identifier: LGPL-2.1-or-later # # Copyright (C) 2013 - 2018 Aleksander Morgado # import string import utils """ The Struct class takes care of emitting the struct type """ class Struct: """ Constructor """ def __init__(self, service, mbimex_service, mbimex_version, dictionary): # The message service, e.g. "Basic Connect" self.service = service self.mbimex_service = mbimex_service self.mbimex_version = mbimex_version self.name = dictionary['name'] self.contents = dictionary['contents'] self.since = dictionary['since'] if 'since' in dictionary else None if self.since is None: raise ValueError('Struct ' + self.name + ' requires a "since" tag specifying the major version where it was introduced') # Whether the struct is used as a single field, or as an array of # fields. Will be updated after having created the object. self.single_member = False self.ms_struct = False self.ref_struct_array_member = False self.struct_array_member = False self.ms_struct_array_member = False # Check whether the struct is composed of fixed-sized fields self.size = 0 for field in self.contents: if field['format'] == 'guint16': self.size += 2 elif field['format'] == 'guint32': self.size += 4 elif field['format'] == 'gint32': self.size += 4 elif field['format'] == 'guint64': self.size += 8 elif field['format'] == 'uuid': self.size += 16 elif field['format'] == 'ipv4': self.size += 4 elif field['format'] == 'ipv6': self.size += 16 else: self.size = 0 break """ Emit the new struct type """ def _emit_type(self, hfile): translations = { 'name' : self.name, 'since' : self.since } template = ( '\n' '/**\n' ' * ${name}:\n') for field in self.contents: translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['name']) if field['format'] == 'uuid': inner_template = ( ' * @${field_name_underscore}: a #MbimUuid.\n') elif field['format'] =='byte-array': inner_template = (' * @${field_name_underscore}: an array of #guint8 values.\n') elif field['format'] in ['unsized-byte-array', 'ref-byte-array', 'ref-byte-array-no-offset']: inner_template = '' if 'array-size-field' not in field: inner_template += (' * @${field_name_underscore}_size: size of the ${field_name_underscore} array.\n') inner_template += (' * @${field_name_underscore}: an array of #guint8 values.\n') elif field['format'] == 'guint16': if 'public-format' in field: translations['public'] = field['public-format'] inner_template = ( ' * @${field_name_underscore}: a #${public} given as a #guint16.\n') else: inner_template = ( ' * @${field_name_underscore}: a #guint16.\n') elif field['format'] == 'guint32': if 'public-format' in field: translations['public'] = field['public-format'] inner_template = ( ' * @${field_name_underscore}: a #${public} given as a #guint32.\n') else: inner_template = ( ' * @${field_name_underscore}: a #guint32.\n') elif field['format'] == 'gint32': inner_template = ( ' * @${field_name_underscore}: a #gint32.\n') elif field['format'] == 'guint32-array': inner_template = ( ' * @${field_name_underscore}: an array of #guint32 values.\n') elif field['format'] == 'guint64': if 'public-format' in field: translations['public'] = field['public-format'] inner_template = ( ' * @${field_name_underscore}: a #${public} given as a #guint64.\n') else: inner_template = ( ' * @${field_name_underscore}: a #guint64.\n') elif field['format'] == 'string': inner_template = ( ' * @${field_name_underscore}: a string.\n') elif field['format'] == 'string-array': inner_template = ( ' * @${field_name_underscore}: an array of strings.\n') elif field['format'] == 'ipv4': inner_template = ( ' * @${field_name_underscore}: a #MbimIPv4.\n') elif field['format'] == 'ipv6': inner_template = ( ' * @${field_name_underscore}: a #MbimIPv6\n') else: raise ValueError('Cannot handle format \'%s\' in struct' % field['format']) template += string.Template(inner_template).substitute(translations) template += ( ' *\n' ' * A ${name} element.\n' ' *\n' ' * Since: ${since}\n' ' */\n' 'typedef struct {\n') for field in self.contents: translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['name']) if field['format'] == 'uuid': inner_template = ( ' MbimUuid ${field_name_underscore};\n') elif field['format'] == 'byte-array': translations['array_size'] = field['array-size'] inner_template = ( ' guint8 ${field_name_underscore}[${array_size}];\n') elif field['format'] in ['unsized-byte-array', 'ref-byte-array', 'ref-byte-array-no-offset']: inner_template = '' if 'array-size-field' not in field: inner_template += ( ' guint32 ${field_name_underscore}_size;\n') inner_template += ( ' guint8 *${field_name_underscore};\n') elif field['format'] == 'guint16': inner_template = ( ' guint16 ${field_name_underscore};\n') elif field['format'] == 'guint32': inner_template = ( ' guint32 ${field_name_underscore};\n') elif field['format'] == 'gint32': inner_template = ( ' gint32 ${field_name_underscore};\n') elif field['format'] == 'guint32-array': inner_template = ( ' guint32 *${field_name_underscore};\n') elif field['format'] == 'guint64': inner_template = ( ' guint64 ${field_name_underscore};\n') elif field['format'] == 'string': inner_template = ( ' gchar *${field_name_underscore};\n') elif field['format'] == 'string-array': inner_template = ( ' gchar **${field_name_underscore};\n') elif field['format'] == 'ipv4': inner_template = ( ' MbimIPv4 ${field_name_underscore};\n') elif field['format'] == 'ipv6': inner_template = ( ' MbimIPv6 ${field_name_underscore};\n') else: raise ValueError('Cannot handle format \'%s\' in struct' % field['format']) template += string.Template(inner_template).substitute(translations) template += ( '} ${name};\n') hfile.write(string.Template(template).substitute(translations)) """ Emit the type's free methods """ def _emit_free(self, hfile, cfile): translations = { 'name' : self.name, 'since' : self.since, 'name_underscore' : utils.build_underscore_name_from_camelcase(self.name) } template = '' if self.single_member == True: template = ( '\n' '/**\n' ' * ${name_underscore}_free:\n' ' * @var: a #${name}.\n' ' *\n' ' * Frees the memory allocated for the #${name}.\n' ' *\n' ' * Since: ${since}\n' ' */\n' 'void ${name_underscore}_free (${name} *var);\n' 'G_DEFINE_AUTOPTR_CLEANUP_FUNC (${name}, ${name_underscore}_free)\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' 'static void\n' '_${name_underscore}_free (${name} *var)\n' '{\n' ' if (!var)\n' ' return;\n' '\n') for field in self.contents: translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['name']) inner_template = '' if field['format'] == 'uuid': pass elif field['format'] in ['unsized-byte-array', 'ref-byte-array', 'ref-byte-array-no-offset']: inner_template += ( ' g_free (var->${field_name_underscore});\n') elif field['format'] == 'guint16': pass elif field['format'] == 'guint32': pass elif field['format'] == 'gint32': pass elif field['format'] == 'guint32-array': inner_template += ( ' g_free (var->${field_name_underscore});\n') elif field['format'] == 'guint64': pass elif field['format'] == 'string': inner_template += ( ' g_free (var->${field_name_underscore});\n') elif field['format'] == 'string-array': inner_template += ( ' g_strfreev (var->${field_name_underscore});\n') elif field['format'] == 'ipv4': pass elif field['format'] == 'ipv6': pass else: raise ValueError('Cannot handle format \'%s\' in struct clear' % field['format']) template += string.Template(inner_template).substitute(translations) template += ( ' g_free (var);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) if self.single_member == True: template = ( '\n' 'void\n' '${name_underscore}_free (${name} *var)\n' '{\n' ' _${name_underscore}_free (var);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) if self.struct_array_member == True or self.ref_struct_array_member == True or self.ms_struct_array_member == True: # TypeArray was introduced in 1.24 translations['array_since'] = self.since if utils.version_compare('1.24', self.since) > 0 else '1.24' template = ( '\n' '/**\n' ' * ${name}Array:\n' ' *\n' ' * A NULL-terminated array of ${name} elements.\n' ' *\n' ' * Since: ${array_since}\n' ' */\n' 'typedef ${name} *${name}Array;\n' '/**\n' ' * ${name_underscore}_array_free:\n' ' * @array: a #NULL terminated array of #${name} structs.\n' ' *\n' ' * Frees the memory allocated for the array of #${name} structs.\n' ' *\n' ' * Since: ${since}\n' ' */\n' 'void ${name_underscore}_array_free (${name}Array *array);\n' 'G_DEFINE_AUTOPTR_CLEANUP_FUNC (${name}Array, ${name_underscore}_array_free)\n') hfile.write(string.Template(template).substitute(translations)) template = ( '\n' 'void\n' '${name_underscore}_array_free (${name}Array *array)\n' '{\n' ' guint32 i;\n' '\n' ' if (!array)\n' ' return;\n' '\n' ' for (i = 0; array[i]; i++)\n' ' _${name_underscore}_free (array[i]);\n' ' g_free (array);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) """ Emit the type's print methods """ def _emit_print(self, cfile): translations = { 'name' : self.name, 'name_underscore' : utils.build_underscore_name_from_camelcase(self.name), 'struct_size' : self.size } template = ( '\n' 'static gchar *\n' '_mbim_message_print_${name_underscore}_struct (\n' ' const ${name} *self,\n' ' const gchar *line_prefix)\n' '{\n' ' GString *str;\n') for field in self.contents: if 'personal-info' in field: template += ( ' gboolean show_field;\n' '\n' ' show_field = mbim_utils_get_show_personal_info ();\n') break template += ( '\n' ' str = g_string_new ("");\n' '\n') for field in self.contents: translations['field_name'] = field['name'] translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['name']) translations['public'] = field['public-format'] if 'public-format' in field else field['format'] translations['public_underscore'] = utils.build_underscore_name_from_camelcase(field['public-format']) if 'public-format' in field else '' translations['public_underscore_upper'] = utils.build_underscore_name_from_camelcase(field['public-format']).upper() if 'public-format' in field else '' if 'personal-info' in field: translations['if_show_field'] = 'if (show_field) ' else: translations['if_show_field'] = '' inner_template = ( ' g_string_append_printf (str, "%s ${field_name} = ", line_prefix);\n' ' {\n') if field['format'] == 'uuid': inner_template += ( ' ${if_show_field}{\n' ' g_autofree gchar *tmpstr = NULL;\n' '\n' ' tmpstr = mbim_uuid_get_printable (&(self->${field_name_underscore}));\n' ' g_string_append_printf (str, "\'%s\'", tmpstr);\n' ' }\n') elif field['format'] in ['byte-array', 'ref-byte-array', 'ref-byte-array-no-offset', 'unsized-byte-array']: inner_template += ( ' ${if_show_field}{\n' ' guint i;\n' ' guint array_size;\n' '\n') if field['format'] == 'byte-array': translations['array_size'] = field['array-size'] inner_template += ( ' array_size = ${array_size};\n') elif 'array-size-field' in field: translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) inner_template += ( ' array_size = self->${array_size_field_name_underscore};\n') else: inner_template += ( ' array_size = self->${field_name_underscore}_size;\n') inner_template += ( ' g_string_append (str, "\'");\n' ' for (i = 0; i < array_size; i++)\n' ' g_string_append_printf (str, "%02x%s", self->${field_name_underscore}[i], (i == (array_size - 1)) ? "" : ":" );\n' ' g_string_append (str, "\'");\n' ' }\n') elif field['format'] in ['guint16', 'guint32', 'guint64']: if 'public-format' in field: if field['public-format'] == 'gboolean': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%s\'", (${public})self->${field_name_underscore} ? "true" : "false");\n' ' }\n' '\n') else: inner_template += ( ' ${if_show_field}{\n' '#if defined __${public_underscore_upper}_IS_ENUM__\n' ' g_string_append_printf (str, "\'%s\'", ${public_underscore}_get_string ((${public})self->${field_name_underscore}));\n' '#elif defined __${public_underscore_upper}_IS_FLAGS__\n' ' g_autofree gchar *tmpstr = NULL;\n' '\n' ' tmpstr = ${public_underscore}_build_string_from_mask ((${public})self->${field_name_underscore});\n' ' g_string_append_printf (str, "\'%s\'", tmpstr);\n' '#else\n' '# error neither enum nor flags\n' '#endif\n' ' }\n' '\n') elif field['format'] == 'guint16': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%" G_GUINT16_FORMAT "\'", self->${field_name_underscore});\n' ' }\n') elif field['format'] == 'guint32': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%" G_GUINT32_FORMAT "\'", self->${field_name_underscore});\n' ' }\n') elif field['format'] == 'guint64': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%" G_GUINT64_FORMAT "\'", self->${field_name_underscore});\n' ' }\n') elif field['format'] == 'gint32': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%" G_GINT32_FORMAT "\'", self->${field_name_underscore});\n' ' }\n') elif field['format'] == 'guint32-array': translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) inner_template += ( ' ${if_show_field}{\n' ' guint i;\n' '\n' ' g_string_append (str, "\'");\n' ' for (i = 0; i < self->${array_size_field_name_underscore}; i++)\n' ' g_string_append_printf (str, "%" G_GUINT32_FORMAT "%s", self->${field_name_underscore}[i], (i == (self->${array_size_field_name_underscore} - 1)) ? "" : "," );\n' ' g_string_append (str, "\'");\n' ' }\n') elif field['format'] == 'string': inner_template += ( ' ${if_show_field}{\n' ' g_string_append_printf (str, "\'%s\'", self->${field_name_underscore});\n' ' }\n') elif field['format'] == 'string-array': translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) inner_template += ( ' ${if_show_field}{\n' ' guint i;\n' '\n' ' g_string_append (str, "\'");\n' ' for (i = 0; i < self->${array_size_field_name_underscore}; i++)\n' ' g_string_append_printf (str, "%s%s", self->${field_name_underscore}[i], (i == (self->${array_size_field_name_underscore} - 1)) ? "" : "," );\n' ' g_string_append (str, "\'");\n' ' }\n') elif field['format'] == 'ipv4' or \ field['format'] == 'ipv6': inner_template += ( ' ${if_show_field}{\n' ' g_autoptr(GInetAddress) addr = NULL;\n' ' g_autofree gchar *tmpstr = NULL;\n' '\n') if field['format'] == 'ipv4': inner_template += ( ' addr = g_inet_address_new_from_bytes ((guint8 *)&(self->${field_name_underscore}.addr), G_SOCKET_FAMILY_IPV4);\n') elif field['format'] == 'ipv6': inner_template += ( ' addr = g_inet_address_new_from_bytes ((guint8 *)&(self->${field_name_underscore}.addr), G_SOCKET_FAMILY_IPV6);\n') inner_template += ( ' tmpstr = g_inet_address_to_string (addr);\n' ' g_string_append_printf (str, "\'%s\'", tmpstr);\n' ' }\n') else: raise ValueError('Cannot handle format \'%s\' in struct' % field['format']) if 'personal-info' in field: inner_template += ( ' if (!show_field)\n' ' g_string_append (str, "\'###\'");\n') inner_template += ( ' }\n' ' g_string_append (str, "\\n");\n') template += (string.Template(inner_template).substitute(translations)) template += ( ' return g_string_free (str, FALSE);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) """ Emit the type's read methods """ def _emit_read(self, cfile): translations = { 'name' : self.name, 'name_underscore' : utils.build_underscore_name_from_camelcase(self.name), 'struct_size' : self.size } template = ( '\n' 'static ${name} *\n' '_mbim_message_read_${name_underscore}_struct (\n' ' const MbimMessage *self,\n' ' guint32 relative_offset,\n' ' guint32 explicit_struct_size,\n' ' guint32 *bytes_read,\n' ' GError **error)\n' '{\n' ' gboolean success = FALSE;\n' ' ${name} *out;\n' ' guint32 offset = relative_offset;\n') if self.ms_struct_array_member == True: template += ( ' guint32 extra_bytes_read = 0;\n') template += ( '\n' ' g_assert (self != NULL);\n' '\n' ' out = g_new0 (${name}, 1);\n' '\n') for field in self.contents: translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['name']) inner_template = '' if field['format'] == 'uuid': inner_template += ( '\n' ' if (!_mbim_message_read_uuid (self, offset, NULL, &(out->${field_name_underscore}), error))\n' ' goto out;\n' ' offset += 16;\n') elif field['format'] in ['ref-byte-array', 'ref-byte-array-no-offset']: # Unsupported because ms-struct-array requires the read bytes of the struct to contain the size read # fro the variable buffer, which is currently not implemented for this type. if self.ms_struct_array_member == True: raise ValueError('type unsupported in \'ms-struct-array\'') translations['has_offset'] = 'TRUE' if field['format'] == 'ref-byte-array' else 'FALSE' if 'array-size-field' in field: translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) inner_template += ( '\n' ' {\n' ' const guint8 *tmp;\n' '\n' ' if (!_mbim_message_read_byte_array (self, relative_offset, offset, ${has_offset}, FALSE, out->${array_size_field_name_underscore}, &tmp, NULL, error, FALSE))\n' ' goto out;\n' ' out->${field_name_underscore} = g_malloc (out->${array_size_field_name_underscore});\n' ' memcpy (out->${field_name_underscore}, tmp, out->${array_size_field_name_underscore});\n' ' offset += 4;\n' ' }\n') else: inner_template += ( '\n' ' {\n' ' const guint8 *tmp;\n' '\n' ' if (!_mbim_message_read_byte_array (self, relative_offset, offset, ${has_offset}, TRUE, 0, &tmp, &(out->${field_name_underscore}_size), error, FALSE))\n' ' goto out;\n' ' out->${field_name_underscore} = g_malloc (out->${field_name_underscore}_size);\n' ' memcpy (out->${field_name_underscore}, tmp, out->${field_name_underscore}_size);\n' ' offset += 8;\n' ' }\n') elif field['format'] == 'unsized-byte-array': # Unsupported because ms-struct-array requires the read bytes of the struct to contain the size read # fro the variable buffer, which is currently not implemented for this type. if self.ms_struct_array_member == True: raise ValueError('type unsupported in \'ms-struct-array\'') inner_template += ( '\n' ' {\n' ' const guint8 *tmp;\n' '\n') if self.ref_struct_array_member == True: # When the unsized-byte-array is given inside a struct, its length may already be known, e.g. if the # array is a ref-struct-array of OL pairs (the 'L' length of the array item implicitly defines the # length of the byte array. In this case, we must provide an explicit_array_size and avoid trying # to read until the end of the message. inner_template += ( ' out->${field_name_underscore}_size = explicit_struct_size - (offset - relative_offset);\n' ' if (!_mbim_message_read_byte_array (self, relative_offset, offset, FALSE, FALSE, out->${field_name_underscore}_size, &tmp, NULL, error, FALSE))\n' ' goto out;\n') else: inner_template += ( ' if (!_mbim_message_read_byte_array (self, relative_offset, offset, FALSE, FALSE, 0, &tmp, &(out->${field_name_underscore}_size), error, FALSE))\n' ' goto out;\n') inner_template += ( ' out->${field_name_underscore} = g_malloc (out->${field_name_underscore}_size);\n' ' memcpy (out->${field_name_underscore}, tmp, out->${field_name_underscore}_size);\n' ' offset += out->${field_name_underscore}_size;\n' ' }\n') elif field['format'] == 'byte-array': translations['array_size'] = field['array-size'] inner_template += ( '\n' ' {\n' ' const guint8 *tmp;\n' '\n' ' if (!_mbim_message_read_byte_array (self, relative_offset, offset, FALSE, FALSE, ${array_size}, &tmp, NULL, error, FALSE))\n' ' goto out;\n' ' memcpy (out->${field_name_underscore}, tmp, ${array_size});\n' ' offset += ${array_size};\n' ' }\n') elif field['format'] == 'guint16': inner_template += ( '\n' ' if (!_mbim_message_read_guint16 (self, offset, &out->${field_name_underscore}, error))\n' ' goto out;\n' ' offset += 2;\n') elif field['format'] == 'guint32': inner_template += ( '\n' ' if (!_mbim_message_read_guint32 (self, offset, &out->${field_name_underscore}, error))\n' ' goto out;\n' ' offset += 4;\n') elif field['format'] == 'gint32': inner_template += ( '\n' ' if (!_mbim_message_read_gint32 (self, offset, &out->${field_name_underscore}, error))\n' ' goto out;\n' ' offset += 4;\n') elif field['format'] == 'guint32-array': translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) inner_template += ( '\n' ' if (!_mbim_message_read_guint32_array (self, out->${array_size_field_name_underscore}, offset, &out->${field_name_underscore}, error))\n' ' goto out;\n' ' offset += (4 * out->${array_size_field_name_underscore});\n') elif field['format'] == 'guint64': inner_template += ( '\n' ' if (!_mbim_message_read_guint64 (self, offset, &out->${field_name_underscore}, error))\n' ' goto out;\n' ' offset += 8;\n') elif field['format'] == 'string': translations['encoding'] = 'MBIM_STRING_ENCODING_UTF8' if 'encoding' in field and field['encoding'] == 'utf-8' else 'MBIM_STRING_ENCODING_UTF16' if self.ms_struct_array_member == True: inner_template += ( '\n' ' {\n' ' guint32 str_bytes_read;\n' '\n' ' if (!_mbim_message_read_string (self, relative_offset, offset, ${encoding}, &out->${field_name_underscore}, &str_bytes_read, error))\n' ' goto out;\n' ' if (str_bytes_read % 4)\n' ' str_bytes_read = (str_bytes_read + (4 - (str_bytes_read % 4)));\n' ' extra_bytes_read += str_bytes_read;\n' ' offset += 8;\n' ' }\n') else: inner_template += ( '\n' ' if (!_mbim_message_read_string (self, relative_offset, offset, ${encoding}, &out->${field_name_underscore}, NULL, error))\n' ' goto out;\n' ' offset += 8;\n') elif field['format'] == 'string-array': # Unsupported because ms-struct-array requires the read bytes of the struct to contain the size read # fro the variable buffer, which is currently not implemented for this type. if self.ms_struct_array_member == True: raise ValueError('type \'ref-byte-array\' unsupported in \'ms-struct-array\'') translations['encoding'] = 'MBIM_STRING_ENCODING_UTF8' if 'encoding' in field and field['encoding'] == 'utf-8' else 'MBIM_STRING_ENCODING_UTF16' translations['array_size_field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) inner_template += ( '\n' ' if (!_mbim_message_read_string_array (self, out->${array_size_field_name_underscore}, relative_offset, offset, ${encoding}, &out->${field_name_underscore}, error))\n' ' goto out;\n' ' offset += (8 * out->${array_size_field_name_underscore});\n') elif field['format'] == 'ipv4': inner_template += ( '\n' ' if (!_mbim_message_read_ipv4 (self, offset, FALSE, NULL, &(out->${field_name_underscore}), error))\n' ' goto out;\n' ' offset += 4;\n') elif field['format'] == 'ipv6': inner_template += ( '\n' ' if (!_mbim_message_read_ipv6 (self, offset, FALSE, NULL, &(out->${field_name_underscore}), error))\n' ' goto out;\n' ' offset += 16;\n') else: raise ValueError('Cannot handle format \'%s\' in struct' % field['format']) template += string.Template(inner_template).substitute(translations) template += ( '\n' ' success = TRUE;\n' '\n' ' out:\n' ' if (success) {\n' ' guint32 total_bytes_read = (offset - relative_offset);\n' '\n') if self.ms_struct_array_member == True: template += ( ' total_bytes_read += extra_bytes_read;\n') # Until now we have validated that all fields read did fit in the contents of the message, # but we have not validated that the fields fit in the given explicit struct size, if given. template += ( ' if (!explicit_struct_size || total_bytes_read <= explicit_struct_size) {\n' ' if (bytes_read)\n' ' *bytes_read = total_bytes_read;\n' ' return out;\n' ' }\n' ' g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,\n' ' \"Read %u bytes from struct with size %u\", total_bytes_read, explicit_struct_size);\n' ' }\n' '\n' ' _${name_underscore}_free (out);\n' ' return NULL;\n' '}\n') cfile.write(string.Template(template).substitute(translations)) if self.ms_struct == True: template = ( '\n' 'static gboolean\n' '_mbim_message_read_${name_underscore}_ms_struct (\n' ' const MbimMessage *self,\n' ' guint32 relative_offset,\n' ' ${name} **out_struct,\n' ' GError **error)\n' '{\n' ' ${name} *out;\n' ' guint32 offset;\n' ' guint32 size;\n' '\n' ' g_assert (self != NULL);\n' '\n' ' if (!_mbim_message_read_guint32 (self, relative_offset, &offset, error))\n' ' return FALSE;\n' ' relative_offset += 4;\n' '\n' ' if (!_mbim_message_read_guint32 (self, relative_offset, &size, error))\n' ' return FALSE;\n' ' relative_offset += 4;\n' '\n' ' if (!offset) {\n' ' *out_struct = NULL;\n' ' return TRUE;\n' ' }\n' '\n' ' out = _mbim_message_read_${name_underscore}_struct (self, offset, size, NULL, error);\n' ' if (!out)\n' ' return FALSE;\n' ' *out_struct = out;\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations)) if self.struct_array_member == True: # struct size is REQUIRED to be non-zero at this point, because that ensures # that the struct has exclusively fixed-sized variables, required to iterate # the elements with "offset += ${struct_size}". if self.size == 0: raise ValueError('Struct ' + self.name + ' has unexpected variable length fields') template = ( '\n' 'static gboolean\n' '_mbim_message_read_${name_underscore}_struct_array (\n' ' const MbimMessage *self,\n' ' guint32 array_size,\n' ' guint32 relative_offset_array_start,\n' ' ${name}Array **out_array,\n' ' GError **error)\n' '{\n' ' g_autoptr(GPtrArray) out = NULL;\n' ' guint32 i;\n' ' guint32 offset;\n' '\n' ' if (!array_size) {\n' ' *out_array = NULL;\n' ' return TRUE;\n' ' }\n' '\n' ' if (!_mbim_message_read_guint32 (self, relative_offset_array_start, &offset, error))\n' ' return FALSE;\n' '\n' ' out = g_ptr_array_new_with_free_func ((GDestroyNotify)_${name_underscore}_free);\n' '\n' ' for (i = 0; i < array_size; i++, offset += ${struct_size}) {\n' ' ${name} *array_item;\n' '\n' ' array_item = _mbim_message_read_${name_underscore}_struct (self, offset, ${struct_size}, NULL, error);\n' ' if (!array_item)\n' ' return FALSE;\n' ' g_ptr_array_add (out, array_item);\n' ' }\n' '\n' ' g_ptr_array_add (out, NULL);\n' ' *out_array = (${name}Array *) g_ptr_array_free (g_steal_pointer (&out), FALSE);\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations)) if self.ref_struct_array_member == True: template = ( '\n' 'static gboolean\n' '_mbim_message_read_${name_underscore}_ref_struct_array (\n' ' const MbimMessage *self,\n' ' guint32 array_size,\n' ' guint32 relative_offset_array_start,\n' ' ${name}Array **out_array,\n' ' GError **error)\n' '{\n' ' g_autoptr(GPtrArray) out = NULL;\n' ' guint32 i;\n' ' guint32 offset;\n' '\n' ' if (!array_size) {\n' ' *out_array = NULL;\n' ' return TRUE;\n' ' }\n' '\n' ' out = g_ptr_array_new_with_free_func ((GDestroyNotify)_${name_underscore}_free);\n' '\n' ' offset = relative_offset_array_start;\n' ' for (i = 0; i < array_size; i++, offset += 8) {\n' ' guint32 tmp_offset;\n' ' guint32 tmp_length;\n' ' ${name} *array_item;\n' '\n' ' if (!_mbim_message_read_guint32 (self, offset, &tmp_offset, error)) \n' ' return FALSE;\n' ' if (!_mbim_message_read_guint32 (self, offset + 4, &tmp_length, error)) \n' ' return FALSE;\n' '\n' ' array_item = _mbim_message_read_${name_underscore}_struct (self, tmp_offset, tmp_length, NULL, error);\n' ' if (!array_item)\n' ' return FALSE;\n' ' g_ptr_array_add (out, array_item);\n' ' }\n' '\n' ' g_ptr_array_add (out, NULL);\n' ' *out_array = (${name}Array *) g_ptr_array_free (g_steal_pointer (&out), FALSE);\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations)) if self.ms_struct_array_member == True: template = ( '\n' 'static gboolean\n' '_mbim_message_read_${name_underscore}_ms_struct_array (\n' ' const MbimMessage *self,\n' ' guint32 offset,\n' ' guint32 *out_array_size,\n' ' ${name}Array **out_array,\n' ' GError **error)\n' '{\n' ' g_autoptr(GPtrArray) out = NULL;\n' ' guint32 i;\n' ' guint32 intermediate_struct_offset;\n' ' guint32 intermediate_struct_size;\n' ' guint32 array_size;\n' ' guint32 bytes_read = 0;\n' '\n' ' if (!_mbim_message_read_guint32 (self, offset, &intermediate_struct_offset, error))\n' ' return FALSE;\n' ' offset += 4;\n' '\n' ' if (!_mbim_message_read_guint32 (self, offset, &intermediate_struct_size, error))\n' ' return FALSE;\n' ' offset += 4;\n' '\n' ' if (!intermediate_struct_offset) {\n' ' *out_array_size = 0;\n' ' *out_array = NULL;\n' ' return TRUE;\n' ' }\n' '\n' ' if (!_mbim_message_read_guint32 (self, intermediate_struct_offset, &array_size, error))\n' ' return FALSE;\n' '\n' ' if (!array_size) {\n' ' *out_array_size = 0;\n' ' *out_array = NULL;\n' ' return TRUE;\n' ' }\n' '\n' ' intermediate_struct_offset += 4;\n' '\n' ' out = g_ptr_array_new_with_free_func ((GDestroyNotify)_${name_underscore}_free);\n' '\n' ' for (i = 0; i < array_size; i++, intermediate_struct_offset += bytes_read) {\n' ' ${name} *array_item;\n' '\n' ' array_item = _mbim_message_read_${name_underscore}_struct (self, intermediate_struct_offset, 0, &bytes_read, error);\n' ' if (!array_item)\n' ' return FALSE;\n' ' g_ptr_array_add (out, array_item);\n' ' }\n' '\n' ' g_ptr_array_add (out, NULL);\n' ' *out_array_size = array_size;\n' ' *out_array = (${name}Array *) g_ptr_array_free (g_steal_pointer (&out), FALSE);\n' ' return TRUE;\n' '}\n') cfile.write(string.Template(template).substitute(translations)) """ Emit the type's append methods """ def _emit_append(self, cfile): translations = { 'name' : self.name, 'name_underscore' : utils.build_underscore_name_from_camelcase(self.name), 'struct_size' : self.size } template = ( '\n' 'static GByteArray *\n' '_${name_underscore}_struct_new (const ${name} *value)\n' '{\n' ' MbimStructBuilder *builder;\n' '\n' ' g_assert (value != NULL);\n' '\n' ' builder = _mbim_struct_builder_new ();\n') for field in self.contents: translations['field'] = utils.build_underscore_name_from_camelcase(field['name']) translations['array_size'] = field['array-size'] if 'array-size' in field else '' translations['array_size_field'] = utils.build_underscore_name_from_camelcase(field['array-size-field']) if 'array-size-field' in field else '' translations['pad_array'] = field['pad-array'] if 'pad-array' in field else 'TRUE' if field['format'] == 'uuid': inner_template = (' _mbim_struct_builder_append_uuid (builder, &(value->${field}));\n') elif field['format'] == 'byte-array': inner_template = (' _mbim_struct_builder_append_byte_array (builder, FALSE, FALSE, ${pad_array}, value->${field}, ${array_size}, FALSE);\n') elif field['format'] == 'unsized-byte-array': inner_template = (' _mbim_struct_builder_append_byte_array (builder, FALSE, FALSE, ${pad_array}, value->${field}, value->${field}_size, FALSE);\n') elif field['format'] in ['ref-byte-array', 'ref-byte-array-no-offset']: translations['has_offset'] = 'TRUE' if field['format'] == 'ref-byte-array' else 'FALSE' if 'array-size-field' in field: inner_template = (' _mbim_struct_builder_append_byte_array (builder, ${has_offset}, FALSE, ${pad_array}, value->${field}, value->${array_size_field}, FALSE);\n') else: inner_template = (' _mbim_struct_builder_append_byte_array (builder, ${has_offset}, TRUE, ${pad_array}, value->${field}, value->${field}_size, FALSE);\n') elif field['format'] == 'guint16': inner_template = (' _mbim_struct_builder_append_guint16 (builder, value->${field});\n') elif field['format'] == 'guint32': inner_template = (' _mbim_struct_builder_append_guint32 (builder, value->${field});\n') elif field['format'] == 'gint32': inner_template = (' _mbim_struct_builder_append_gint32 (builder, value->${field});\n') elif field['format'] == 'guint32-array': inner_template = (' _mbim_struct_builder_append_guint32_array (builder, value->${field}, value->${array_size_field});\n') elif field['format'] == 'guint64': inner_template = (' _mbim_struct_builder_append_guint64 (builder, value->${field});\n') elif field['format'] == 'string': inner_template = (' _mbim_struct_builder_append_string (builder, value->${field});\n') elif field['format'] == 'string-array': inner_template = (' _mbim_struct_builder_append_string_array (builder, value->${field}, value->${array_size_field});\n') elif field['format'] == 'ipv4': inner_template = (' _mbim_struct_builder_append_ipv4 (builder, &value->${field}, FALSE);\n') elif field['format'] == 'ipv6': inner_template = (' _mbim_struct_builder_append_ipv6 (builder, &value->${field}, FALSE);\n') else: raise ValueError('Cannot handle format \'%s\' in struct' % field['format']) template += string.Template(inner_template).substitute(translations) template += ( '\n' ' return _mbim_struct_builder_complete (builder);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) template = ( '\n' 'static void\n' '_mbim_struct_builder_append_${name_underscore}_struct (\n' ' MbimStructBuilder *builder,\n' ' const ${name} *value)\n' '{\n' ' GByteArray *raw;\n' '\n' ' raw = _${name_underscore}_struct_new (value);\n' ' g_byte_array_append (builder->fixed_buffer, raw->data, raw->len);\n' ' g_byte_array_unref (raw);\n' '}\n' '\n' 'static void\n' '_mbim_message_command_builder_append_${name_underscore}_struct (\n' ' MbimMessageCommandBuilder *builder,\n' ' const ${name} *value)\n' '{\n' ' _mbim_struct_builder_append_${name_underscore}_struct (builder->contents_builder, value);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) if self.struct_array_member == True: template = ( '\n' 'static void\n' '_mbim_struct_builder_append_${name_underscore}_struct_array (\n' ' MbimStructBuilder *builder,\n' ' const ${name} *const *values,\n' ' guint32 n_values)\n' '{\n' ' guint32 offset;\n' ' guint32 i;\n' ' GByteArray *raw_all = NULL;\n' '\n' ' for (i = 0; i < n_values; i++) {\n' ' GByteArray *raw;\n' '\n' ' raw = _${name_underscore}_struct_new (values[i]);\n' ' if (!raw_all)\n' ' raw_all = raw;\n' ' else {\n' ' g_byte_array_append (raw_all, raw->data, raw->len);\n' ' g_byte_array_unref (raw);\n' ' }\n' ' }\n' '\n' ' if (!raw_all) {\n' ' offset = 0;\n' ' g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset));\n' ' } else {\n' ' guint32 offset_offset;\n' '\n' ' /* Offset of the offset */\n' ' offset_offset = builder->fixed_buffer->len;\n' ' /* Length *not* in LE yet */\n' ' offset = builder->variable_buffer->len;\n' ' /* Add the offset value */\n' ' g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset));\n' ' /* Configure the value to get updated */\n' ' g_array_append_val (builder->offsets, offset_offset);\n' ' /* Add the final array itself */\n' ' g_byte_array_append (builder->variable_buffer, raw_all->data, raw_all->len);\n' ' g_byte_array_unref (raw_all);\n' ' }\n' '}\n' '\n' 'static void\n' '_mbim_message_command_builder_append_${name_underscore}_struct_array (\n' ' MbimMessageCommandBuilder *builder,\n' ' const ${name} *const *values,\n' ' guint32 n_values)\n' '{\n' ' _mbim_struct_builder_append_${name_underscore}_struct_array (builder->contents_builder, values, n_values);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) if self.ref_struct_array_member == True: template = ( '\n' 'static void\n' '_mbim_struct_builder_append_${name_underscore}_ref_struct_array (\n' ' MbimStructBuilder *builder,\n' ' const ${name} *const *values,\n' ' guint32 n_values)\n' '{\n' ' guint32 offset;\n' ' guint32 i;\n' '\n' ' for (i = 0; i < n_values; i++) {\n' ' guint32 length;\n' ' guint32 offset_offset;\n' ' GByteArray *raw;\n' ' static const guint8 padding = 0x00;\n' '\n' ' raw = _${name_underscore}_struct_new (values[i]);\n' ' g_assert (raw->len > 0);\n' '\n' ' /* Offset of the offset */\n' ' offset_offset = builder->fixed_buffer->len;\n' '\n' ' /* Length *not* in LE yet */\n' ' offset = builder->variable_buffer->len;\n' ' /* Add the offset value */\n' ' g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset));\n' ' /* Configure the value to get updated */\n' ' g_array_append_val (builder->offsets, offset_offset);\n' '\n' ' /* Add the length value */\n' ' length = GUINT32_TO_LE (raw->len);\n' ' g_byte_array_append (builder->fixed_buffer, (guint8 *)&length, sizeof (length));\n' '\n' ' /* And finally, the bytearray itself to the variable buffer */\n' ' g_byte_array_append (builder->variable_buffer, (const guint8 *)raw->data, (guint)raw->len);\n' ' /* Align the structs at 4 byte boundary, as we may have unsized byte arrays */\n' ' while (builder->variable_buffer->len % 4 != 0)\n' ' g_byte_array_append (builder->variable_buffer, &padding, sizeof (padding));\n' ' g_byte_array_unref (raw);\n' ' }\n' '}\n' '\n' 'static void\n' '_mbim_message_command_builder_append_${name_underscore}_ref_struct_array (\n' ' MbimMessageCommandBuilder *builder,\n' ' const ${name} *const *values,\n' ' guint32 n_values)\n' '{\n' ' _mbim_struct_builder_append_${name_underscore}_ref_struct_array (builder->contents_builder, values, n_values);\n' '}\n') cfile.write(string.Template(template).substitute(translations)) # append operations not implemented for self.ms_struct_array_member == True """ Emit the struct handling implementation """ def emit(self, hfile, cfile): utils.add_separator(hfile, 'Struct', self.name); utils.add_separator(cfile, 'Struct', self.name); # Emit type self._emit_type(hfile) # Emit type's free self._emit_free(hfile, cfile) # Emit type's read self._emit_read(cfile) # Emit type's print self._emit_print(cfile) # Emit type's append self._emit_append(cfile) """ Emit the section contents """ def emit_section_content(self, sfile): translations = { 'struct_name' : self.name, 'name_underscore' : utils.build_underscore_name_from_camelcase(self.name) } template = ( '\n' '${struct_name}\n') if self.struct_array_member == True or self.ref_struct_array_member == True or self.ms_struct_array_member == True: template += ( '${struct_name}Array\n') if self.single_member == True: template += ( '${name_underscore}_free\n') if self.struct_array_member == True or self.ref_struct_array_member == True or self.ms_struct_array_member == True: template += ( '${name_underscore}_array_free\n') sfile.write(string.Template(template).substitute(translations)) libmbim-1.31.2-dev/build-aux/mbim-codegen/mbim-codegen000077500000000000000000000041241453630424100224640ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- # # SPDX-License-Identifier: LGPL-2.1-or-later # # Copyright (C) 2013-2018 Aleksander Morgado # import os import sys import optparse import json from ObjectList import ObjectList import utils def codegen_main(): # Input arguments arg_parser = optparse.OptionParser('%prog [options]') arg_parser.add_option('', '--output', metavar='OUTFILES', help='Generate C code in OUTFILES.[ch]') (opts, args) = arg_parser.parse_args(); if args == None: raise RuntimeError('Input JSON file is mandatory') if opts.output == None: raise RuntimeError('Output file pattern is mandatory') # Prepare output file names output_file_c = open(opts.output + ".c", 'w') output_file_h = open(opts.output + ".h", 'w') output_file_sections = open(opts.output + ".sections", 'w') # Build message list from all input files object_list_json = [] for input_file in args: database_file_contents = utils.read_json_file(input_file) object_list_json += json.loads(database_file_contents) object_list = ObjectList(object_list_json) # Add common stuff to the output files utils.add_copyright(output_file_c); utils.add_copyright(output_file_h); utils.add_header_start(output_file_h, os.path.basename(opts.output)) utils.add_source_start(output_file_c, os.path.basename(opts.output)) for input_file in args: utils.add_header_sections(output_file_h, os.path.splitext(os.path.basename(input_file))[0]) # Emit the message creation/parsing code object_list.emit(output_file_h, output_file_c) # Emit the message printable support object_list.emit_printable(output_file_h, output_file_c) # Emit sections object_list.emit_sections(output_file_sections) utils.add_header_stop(output_file_h, os.path.basename(opts.output)) output_file_c.close() output_file_h.close() output_file_sections.close() sys.exit(0) if __name__ == "__main__": codegen_main() libmbim-1.31.2-dev/build-aux/mbim-codegen/utils.py000066400000000000000000000132371453630424100217270ustar00rootroot00000000000000# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- # # SPDX-License-Identifier: LGPL-2.1-or-later # # Copyright (C) 2012 Lanedo GmbH # Copyright (C) 2013 - 2018 Aleksander Morgado # # Implementation originally developed in 'libqmi'. # import string import re """ Add the common copyright header to the given file """ def add_copyright(f): f.write( "\n" "/* GENERATED CODE... DO NOT EDIT */\n" "\n" "/* SPDX-License-Identifier: LGPL-2.1-or-later */\n" "/*\n" " * Copyright (C) 2013 - 2018 Aleksander Morgado \n" " */\n" "\n"); """ Build a header guard string based on the given filename """ def build_header_guard(output_name): return "__LIBMBIM_GLIB_" + output_name.replace('-', '_').upper() + "__" """ Write the common header start chunk """ def add_header_start(f, output_name): translations = { 'guard' : build_header_guard(output_name) } template = ( "\n" "#include \n" "#include \n" "#include \n" "\n" "#include \"mbim-message.h\"\n" "#include \"mbim-device.h\"\n" "#include \"mbim-enums.h\"\n" "#include \"mbim-tlv.h\"\n" "\n" "#ifndef ${guard}\n" "#define ${guard}\n" "\n" "G_BEGIN_DECLS\n") f.write(string.Template(template).substitute(translations)) """ Write the header documentation sections """ def add_header_sections(f, input_name): translations = { 'section_name' : "mbim-" + remove_prefix(input_name,"mbim-service-"), 'service_name' : string.capwords(remove_prefix(input_name,"mbim-service-").replace('-', ' ')) } template = ( "\n" "/**\n" " * SECTION:${section_name}\n" " * @title: ${service_name} service\n" " * @short_description: Support for the ${service_name} service.\n" " *\n" " * This section implements support for requests, responses and notifications in the\n" " * ${service_name} service.\n" " */\n") f.write(string.Template(template).substitute(translations)) """ Write the common header stop chunk """ def add_header_stop(f, output_name): template = string.Template ( "\n" "G_END_DECLS\n" "\n" "#endif /* ${guard} */\n") f.write(template.substitute(guard = build_header_guard(output_name))) """ Write the common source file start chunk """ def add_source_start(f, output_name): template = string.Template ( "\n" "#include \n" "\n" "#include \"${name}.h\"\n" "#include \"mbim-message-private.h\"\n" "#include \"mbim-tlv-private.h\"\n" "#include \"mbim-enum-types.h\"\n" "#include \"mbim-flag-types.h\"\n" "#include \"mbim-error-types.h\"\n" "#include \"mbim-device.h\"\n" "#include \"mbim-utils.h\"\n") f.write(template.substitute(name = output_name)) """ Write a separator comment in the file """ def add_separator(f, separator_type, separator_name): template = string.Template ( "\n" "/*****************************************************************************/\n" "/* ${type}: ${name} */\n") f.write(template.substitute(type = separator_type, name = separator_name)) """ Build an underscore name from the given full name e.g.: "This is a message" --> "this_is_a_message" """ def build_underscore_name(name): return name.replace(' ', '_').replace('-', '_').lower() """ Build an underscore uppercase name from the given full name e.g.: "This is a message" --> "THIS_IS_A_MESSAGE" """ def build_underscore_uppercase_name(name): return name.replace(' ', '_').replace('-', '_').upper() """ Build an underscore name from the given camelcase name e.g.: "ThisIsAMessage" --> "this_is_a_message" """ def build_underscore_name_from_camelcase(camelcase): s0 = camelcase.replace('IP','Ip') s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', s0) return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() """ Build a camelcase name from the given full name e.g.: "This is a message" --> "ThisIsAMessage" """ def build_camelcase_name(name): return string.capwords(name).replace(' ', '') """ Build a dashed lowercase name from the given full name e.g.: "This is a message" --> "this-is-a-message" """ def build_dashed_name(name): return name.lower().replace(' ', '-') """ Remove the given prefix from the string """ def remove_prefix(line, prefix): return line[len(prefix):] if line.startswith(prefix) else line """ Read the contents of the JSON file, skipping lines prefixed with '//', which are considered comments. """ def read_json_file(path): f = open(path) out = '' for line in f.readlines(): stripped = line.strip() if stripped.startswith('//'): # Skip this line # We add an empty line instead so that errors when parsing the JSON # report the proper line number out += "\n" else: out += line return out """ Compare two version strings given in MAJOR.MINOR format. Just to avoid needing to include e.g. packaging.version.parse just for this """ def version_compare(v1,v2): major_v1 = int(v1.partition(".")[0]) major_v2 = int(v2.partition(".")[0]) if major_v2 > major_v1: return 1 if major_v2 < major_v1: return -1 # major_v2 == major_v1 minor_v1 = int(v1.partition(".")[2]) minor_v2 = int(v2.partition(".")[2]) if minor_v2 > minor_v1: return 1 if minor_v2 < minor_v1: return -1 # minor_v2 == minor_v1 return 0 libmbim-1.31.2-dev/build-aux/mbim-mkenums000077500000000000000000000732421453630424100202200ustar00rootroot00000000000000#!/usr/bin/env python3 # qmi-mkenums is ported from glib-mkenums. # Same license applies. # If the code below looks horrible and unpythonic, do not panic. # # It is. # # This is a manual conversion from the original Perl script to # Python. Improvements are welcome. # from __future__ import print_function, unicode_literals import argparse import os import re import sys import tempfile import io import errno import codecs import locale VERSION_STR = '''glib-mkenums version 2.64.2 glib-mkenums comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of glib-mkenums under the terms of the GNU General Public License which can be found in the GLib source package. Sources, examples and contact information are available at http://www.gtk.org''' # pylint: disable=too-few-public-methods class Color: '''ANSI Terminal colors''' GREEN = '\033[1;32m' BLUE = '\033[1;34m' YELLOW = '\033[1;33m' RED = '\033[1;31m' END = '\033[0m' def print_color(msg, color=Color.END, prefix='MESSAGE'): '''Print a string with a color prefix''' if os.isatty(sys.stderr.fileno()): real_prefix = '{start}{prefix}{end}'.format(start=color, prefix=prefix, end=Color.END) else: real_prefix = prefix print('{prefix}: {msg}'.format(prefix=real_prefix, msg=msg), file=sys.stderr) def print_error(msg): '''Print an error, and terminate''' print_color(msg, color=Color.RED, prefix='ERROR') sys.exit(1) def print_warning(msg, fatal=False): '''Print a warning, and optionally terminate''' if fatal: color = Color.RED prefix = 'ERROR' else: color = Color.YELLOW prefix = 'WARNING' print_color(msg, color, prefix) if fatal: sys.exit(1) def print_info(msg): '''Print a message''' print_color(msg, color=Color.GREEN, prefix='INFO') def get_rspfile_args(rspfile): ''' Response files are useful on Windows where there is a command-line character limit of 8191 because when passing sources as arguments to glib-mkenums this limit can be exceeded in large codebases. There is no specification for response files and each tool that supports it generally writes them out in slightly different ways, but some sources are: https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-response-files https://docs.microsoft.com/en-us/windows/desktop/midl/the-response-file-command ''' import shlex if not os.path.isfile(rspfile): sys.exit('Response file {!r} does not exist'.format(rspfile)) try: with open(rspfile, 'r') as f: cmdline = f.read() except OSError as e: sys.exit('Response file {!r} could not be read: {}' .format(rspfile, e.strerror)) return shlex.split(cmdline) def write_output(output): global output_stream print(output, file=output_stream) # Python 2 defaults to ASCII in case stdout is redirected. # This should make it match Python 3, which uses the locale encoding. if sys.stdout.encoding is None: output_stream = codecs.getwriter( locale.getpreferredencoding())(sys.stdout) else: output_stream = sys.stdout # Some source files aren't UTF-8 and the old perl version didn't care. # Replace invalid data with a replacement character to keep things working. # https://bugzilla.gnome.org/show_bug.cgi?id=785113#c20 def replace_and_warn(err): # 7 characters of context either side of the offending character print_warning('UnicodeWarning: {} at {} ({})'.format( err.reason, err.start, err.object[err.start - 7:err.end + 7])) return ('?', err.end) codecs.register_error('replace_and_warn', replace_and_warn) # glib-mkenums.py # Information about the current enumeration flags = None # Is enumeration a bitmask? option_underscore_name = '' # Overridden underscore variant of the enum name # for example to fix the cases we don't get the # mixed-case -> underscorized transform right. option_lowercase_name = '' # DEPRECATED. A lower case name to use as part # of the *_get_type() function, instead of the # one that we guess. For instance, when an enum # uses abnormal capitalization and we can not # guess where to put the underscores. option_since = '' # User provided version info for the enum. seenbitshift = 0 # Have we seen bitshift operators? enum_prefix = None # Prefix for this enumeration enumname = '' # Name for this enumeration enumshort = '' # $enumname without prefix enumname_prefix = '' # prefix of $enumname enumindex = 0 # Global enum counter firstenum = 1 # Is this the first enumeration per file? entries = [] # [ name, val ] for each entry sandbox = None # sandbox for safe evaluation of expressions output = '' # Filename to write result into def parse_trigraph(opts): result = {} for opt in re.split(r'\s*,\s*', opts): opt = re.sub(r'^\s*', '', opt) opt = re.sub(r'\s*$', '', opt) m = re.search(r'(\w+)(?:=(.+))?', opt) assert m is not None groups = m.groups() key = groups[0] if len(groups) > 1: val = groups[1] else: val = 1 result[key] = val return result def parse_entries(file, file_name): global entries, enumindex, enumname, seenbitshift, flags looking_for_name = False while True: line = file.readline() if not line: break line = line.strip() # read lines until we have no open comments while re.search(r'/\*([^*]|\*(?!/))*$', line): line += file.readline() # strip comments w/o options line = re.sub(r'''/\*(?!<) ([^*]+|\*(?!/))* \*/''', '', line, flags=re.X) line = line.rstrip() # skip empty lines if len(line.strip()) == 0: continue if looking_for_name: m = re.match(r'\s*(\w+)', line) if m: enumname = m.group(1) return True # Handle include files m = re.match(r'\#include\s*<([^>]*)>', line) if m: newfilename = os.path.join("..", m.group(1)) newfile = io.open(newfilename, encoding="utf-8", errors="replace_and_warn") if not parse_entries(newfile, newfilename): return False else: continue m = re.match(r'\s*\}\s*(\w+)', line) if m: enumname = m.group(1) enumindex += 1 return 1 m = re.match(r'\s*\}', line) if m: enumindex += 1 looking_for_name = True continue m = re.match(r'''\s* (\w+)\s* # name (?:=( # value \s*\w+\s*\(.*\)\s* # macro with multiple args | # OR (?:[^,/]|/(?!\*))* # anything but a comma or comment ))?,?\s* (?:/\*< # options (([^*]|\*(?!/))*) >\s*\*/)?,? \s*$''', line, flags=re.X) if m: groups = m.groups() name = groups[0] value = None options = None if len(groups) > 1: value = groups[1] if len(groups) > 2: options = groups[2] if flags is None and value is not None and '<<' in value: seenbitshift = 1 if options is not None: options = parse_trigraph(options) if 'skip' not in options: entries.append((name, value, options.get('nick'))) else: entries.append((name, value)) elif re.match(r's*\#', line): pass else: print_warning('Failed to parse "{}" in {}'.format(line, file_name)) return False help_epilog = '''Production text substitutions: \u0040EnumName\u0040 PrefixTheXEnum \u0040enum_name\u0040 prefix_the_xenum \u0040ENUMNAME\u0040 PREFIX_THE_XENUM \u0040ENUMSHORT\u0040 THE_XENUM \u0040ENUMPREFIX\u0040 PREFIX \u0040enumsince\u0040 the user-provided since value given (mbim-mkenums only) \u0040VALUENAME\u0040 PREFIX_THE_XVALUE \u0040valuenick\u0040 the-xvalue \u0040valuenum\u0040 the integer value (limited support, Since: 2.26) \u0040type\u0040 either enum or flags \u0040Type\u0040 either Enum or Flags \u0040TYPE\u0040 either ENUM or FLAGS \u0040filename\u0040 name of current input file \u0040basename\u0040 base name of the current input file (Since: 2.22) ''' # production variables: idprefix = "" # "G", "Gtk", etc symprefix = "" # "g", "gtk", etc, if not just lc($idprefix) fhead = "" # output file header fprod = "" # per input file production ftail = "" # output file trailer eprod = "" # per enum text (produced prior to value itarations) vhead = "" # value header, produced before iterating over enum values vprod = "" # value text, produced for each enum value vtail = "" # value tail, produced after iterating over enum values comment_tmpl = "" # comment template def read_template_file(file): global idprefix, symprefix, fhead, fprod, ftail, eprod, vhead, vprod, vtail, comment_tmpl tmpl = {'file-header': fhead, 'file-production': fprod, 'file-tail': ftail, 'enumeration-production': eprod, 'value-header': vhead, 'value-production': vprod, 'value-tail': vtail, 'comment': comment_tmpl, } in_ = 'junk' ifile = io.open(file, encoding="utf-8", errors="replace_and_warn") for line in ifile: m = re.match(r'\/\*\*\*\s+(BEGIN|END)\s+([\w-]+)\s+\*\*\*\/', line) if m: if in_ == 'junk' and m.group(1) == 'BEGIN' and m.group(2) in tmpl: in_ = m.group(2) continue elif in_ == m.group(2) and m.group(1) == 'END' and m.group(2) in tmpl: in_ = 'junk' continue else: sys.exit("Malformed template file " + file) if in_ != 'junk': tmpl[in_] += line if in_ != 'junk': sys.exit("Malformed template file " + file) fhead = tmpl['file-header'] fprod = tmpl['file-production'] ftail = tmpl['file-tail'] eprod = tmpl['enumeration-production'] vhead = tmpl['value-header'] vprod = tmpl['value-production'] vtail = tmpl['value-tail'] comment_tmpl = tmpl['comment'] parser = argparse.ArgumentParser(epilog=help_epilog, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('--identifier-prefix', default='', dest='idprefix', help='Identifier prefix') parser.add_argument('--symbol-prefix', default='', dest='symprefix', help='Symbol prefix') parser.add_argument('--fhead', default=[], dest='fhead', action='append', help='Output file header') parser.add_argument('--ftail', default=[], dest='ftail', action='append', help='Output file footer') parser.add_argument('--fprod', default=[], dest='fprod', action='append', help='Put out TEXT every time a new input file is being processed.') parser.add_argument('--eprod', default=[], dest='eprod', action='append', help='Per enum text, produced prior to value iterations') parser.add_argument('--vhead', default=[], dest='vhead', action='append', help='Value header, produced before iterating over enum values') parser.add_argument('--vprod', default=[], dest='vprod', action='append', help='Value text, produced for each enum value.') parser.add_argument('--vtail', default=[], dest='vtail', action='append', help='Value tail, produced after iterating over enum values') parser.add_argument('--comments', default='', dest='comment_tmpl', help='Comment structure') parser.add_argument('--enums-only', default=False, action='store_true', dest='enumsonly', help='Only process enums, not flags') parser.add_argument('--flags-only', default=False, action='store_true', dest='flagsonly', help='Only process flags, not enums') parser.add_argument('--template', default='', dest='template', help='Template file') parser.add_argument('--output', default=None, dest='output') parser.add_argument('--version', '-v', default=False, action='store_true', dest='version', help='Print version information') parser.add_argument('args', nargs='*', help='One or more input files, or a single argument @rspfile_path ' 'pointing to a file that contains the actual arguments') # Support reading an rspfile of the form @filename which contains the args # to be parsed if len(sys.argv) == 2 and sys.argv[1].startswith('@'): args = get_rspfile_args(sys.argv[1][1:]) else: args = sys.argv[1:] options = parser.parse_args(args) if options.version: print(VERSION_STR) sys.exit(0) def unescape_cmdline_args(arg): arg = arg.replace('\\n', '\n') arg = arg.replace('\\r', '\r') return arg.replace('\\t', '\t') if options.template != '': read_template_file(options.template) idprefix += options.idprefix symprefix += options.symprefix enumsonly = options.enumsonly flagsonly = options.flagsonly # This is a hack to maintain some semblance of backward compatibility with # the old, Perl-based glib-mkenums. The old tool had an implicit ordering # on the arguments and templates; each argument was parsed in order, and # all the strings appended. This allowed developers to write: # # glib-mkenums \ # --fhead ... \ # --template a-template-file.c.in \ # --ftail ... # # And have the fhead be prepended to the file-head stanza in the template, # as well as the ftail be appended to the file-tail stanza in the template. # Short of throwing away ArgumentParser and going over sys.argv[] element # by element, we can simulate that behaviour by ensuring some ordering in # how we build the template strings: # # - the head stanzas are always prepended to the template # - the prod stanzas are always appended to the template # - the tail stanzas are always appended to the template # # Within each instance of the command line argument, we append each value # to the array in the order in which it appears on the command line. fhead = ''.join([unescape_cmdline_args(x) for x in options.fhead]) + fhead vhead = ''.join([unescape_cmdline_args(x) for x in options.vhead]) + vhead fprod += ''.join([unescape_cmdline_args(x) for x in options.fprod]) eprod += ''.join([unescape_cmdline_args(x) for x in options.eprod]) vprod += ''.join([unescape_cmdline_args(x) for x in options.vprod]) ftail = ftail + ''.join([unescape_cmdline_args(x) for x in options.ftail]) vtail = vtail + ''.join([unescape_cmdline_args(x) for x in options.vtail]) if options.comment_tmpl != '': comment_tmpl = unescape_cmdline_args(options.comment_tmpl) elif comment_tmpl == "": # default to C-style comments comment_tmpl = "/* \u0040comment\u0040 */" output = options.output if output is not None: (out_dir, out_fn) = os.path.split(options.output) out_suffix = '_' + os.path.splitext(out_fn)[1] if out_dir == '': out_dir = '.' fd, filename = tempfile.mkstemp(dir=out_dir) os.close(fd) tmpfile = io.open(filename, "w", encoding="utf-8") output_stream = tmpfile else: tmpfile = None # put auto-generation comment comment = comment_tmpl.replace('\u0040comment\u0040', 'This file is generated by glib-mkenums, do ' 'not modify it. This code is licensed under ' 'the same license as the containing project. ' 'Note that it links to GLib, so must comply ' 'with the LGPL linking clauses.') write_output("\n" + comment + '\n') def replace_specials(prod): prod = prod.replace(r'\\a', r'\a') prod = prod.replace(r'\\b', r'\b') prod = prod.replace(r'\\t', r'\t') prod = prod.replace(r'\\n', r'\n') prod = prod.replace(r'\\f', r'\f') prod = prod.replace(r'\\r', r'\r') prod = prod.rstrip() return prod def warn_if_filename_basename_used(section, prod): for substitution in ('\u0040filename\u0040', '\u0040basename\u0040'): if substitution in prod: print_warning('{} used in {} section.'.format(substitution, section)) if len(fhead) > 0: prod = fhead warn_if_filename_basename_used('file-header', prod) prod = replace_specials(prod) write_output(prod) def process_file(curfilename): global entries, flags, seenbitshift, enum_prefix firstenum = True try: curfile = io.open(curfilename, encoding="utf-8", errors="replace_and_warn") except IOError as e: if e.errno == errno.ENOENT: print_warning('No file "{}" found.'.format(curfilename)) return raise while True: line = curfile.readline() if not line: break line = line.strip() # read lines until we have no open comments while re.search(r'/\*([^*]|\*(?!/))*$', line): line += curfile.readline() # strip comments w/o options line = re.sub(r'''/\*(?!<) ([^*]+|\*(?!/))* \*/''', '', line) # ignore forward declarations if re.match(r'\s*typedef\s+enum.*;', line): continue m = re.match(r'''\s*typedef\s+enum\s*[_A-Za-z]*[_A-Za-z0-9]*\s* ({)?\s* (?:/\*< (([^*]|\*(?!/))*) >\s*\*/)? \s*({)?''', line, flags=re.X) if m: groups = m.groups() if len(groups) >= 2 and groups[1] is not None: options = parse_trigraph(groups[1]) if 'skip' in options: continue enum_prefix = options.get('prefix', None) flags = options.get('flags', None) if 'flags' in options: if flags is None: flags = 1 else: flags = int(flags) option_lowercase_name = options.get('lowercase_name', None) option_underscore_name = options.get('underscore_name', None) option_since = options.get('since', None) else: enum_prefix = None flags = None option_lowercase_name = None option_underscore_name = None option_since = None if option_lowercase_name is not None: if option_underscore_name is not None: print_warning("lowercase_name overridden with underscore_name") option_lowercase_name = None else: print_warning("lowercase_name is deprecated, use underscore_name") # Didn't have trailing '{' look on next lines if groups[0] is None and (len(groups) < 4 or groups[3] is None): while True: line = curfile.readline() if not line: print_error("Syntax error when looking for opening { in enum") if re.match(r'\s*\{', line): break seenbitshift = 0 entries = [] # Now parse the entries parse_entries(curfile, curfilename) # figure out if this was a flags or enums enumeration if flags is None: flags = seenbitshift if flags and enumsonly: continue elif not flags and flagsonly: continue # Autogenerate a prefix if enum_prefix is None: for entry in entries: if len(entry) < 3 or entry[2] is None: name = entry[0] if enum_prefix is not None: enum_prefix = os.path.commonprefix([name, enum_prefix]) else: enum_prefix = name if enum_prefix is None: enum_prefix = "" else: # Trim so that it ends in an underscore enum_prefix = re.sub(r'_[^_]*$', '_', enum_prefix) else: # canonicalize user defined prefixes enum_prefix = enum_prefix.upper() enum_prefix = enum_prefix.replace('-', '_') enum_prefix = re.sub(r'(.*)([^_])$', r'\1\2_', enum_prefix) fixed_entries = [] for e in entries: name = e[0] num = e[1] if len(e) < 3 or e[2] is None: nick = re.sub(r'^' + enum_prefix, '', name) nick = nick.replace('_', '-').lower() e = (name, num, nick) fixed_entries.append(e) entries = fixed_entries # Spit out the output if option_underscore_name is not None: enumlong = option_underscore_name.upper() enumsym = option_underscore_name.lower() enumshort = re.sub(r'^[A-Z][A-Z0-9]*_', '', enumlong) enumname_prefix = re.sub('_' + enumshort + '$', '', enumlong) elif symprefix == '' and idprefix == '': # enumname is e.g. GMatchType enspace = re.sub(r'^([A-Z][a-z]*).*$', r'\1', enumname) enumshort = re.sub(r'^[A-Z][a-z]*', '', enumname) enumshort = re.sub(r'([^A-Z])([A-Z])', r'\1_\2', enumshort) enumshort = re.sub(r'([A-Z][A-Z])([A-Z][0-9a-z])', r'\1_\2', enumshort) enumshort = enumshort.upper() enumname_prefix = re.sub(r'^([A-Z][a-z]*).*$', r'\1', enumname).upper() enumlong = enspace.upper() + "_" + enumshort enumsym = enspace.lower() + "_" + enumshort.lower() if option_lowercase_name is not None: enumsym = option_lowercase_name else: enumshort = enumname if idprefix: enumshort = re.sub(r'^' + idprefix, '', enumshort) else: enumshort = re.sub(r'/^[A-Z][a-z]*', '', enumshort) enumshort = re.sub(r'([^A-Z])([A-Z])', r'\1_\2', enumshort) enumshort = re.sub(r'([A-Z][A-Z])([A-Z][0-9a-z])', r'\1_\2', enumshort) enumshort = enumshort.upper() if symprefix: enumname_prefix = symprefix.upper() else: enumname_prefix = idprefix.upper() enumlong = enumname_prefix + "_" + enumshort enumsym = enumlong.lower() if option_since is not None: enumsince = option_since else: enumsince = "" if firstenum: firstenum = False if len(fprod) > 0: prod = fprod base = os.path.basename(curfilename) prod = prod.replace('\u0040filename\u0040', curfilename) prod = prod.replace('\u0040basename\u0040', base) prod = replace_specials(prod) write_output(prod) if len(eprod) > 0: prod = eprod prod = prod.replace('\u0040enum_name\u0040', enumsym) prod = prod.replace('\u0040EnumName\u0040', enumname) prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort) prod = prod.replace('\u0040ENUMNAME\u0040', enumlong) prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix) prod = prod.replace('\u0040enumsince\u0040', enumsince) if flags: prod = prod.replace('\u0040type\u0040', 'flags') else: prod = prod.replace('\u0040type\u0040', 'enum') if flags: prod = prod.replace('\u0040Type\u0040', 'Flags') else: prod = prod.replace('\u0040Type\u0040', 'Enum') if flags: prod = prod.replace('\u0040TYPE\u0040', 'FLAGS') else: prod = prod.replace('\u0040TYPE\u0040', 'ENUM') prod = replace_specials(prod) write_output(prod) if len(vhead) > 0: prod = vhead prod = prod.replace('\u0040enum_name\u0040', enumsym) prod = prod.replace('\u0040EnumName\u0040', enumname) prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort) prod = prod.replace('\u0040ENUMNAME\u0040', enumlong) prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix) prod = prod.replace('\u0040enumsince\u0040', enumsince) if flags: prod = prod.replace('\u0040type\u0040', 'flags') else: prod = prod.replace('\u0040type\u0040', 'enum') if flags: prod = prod.replace('\u0040Type\u0040', 'Flags') else: prod = prod.replace('\u0040Type\u0040', 'Enum') if flags: prod = prod.replace('\u0040TYPE\u0040', 'FLAGS') else: prod = prod.replace('\u0040TYPE\u0040', 'ENUM') prod = replace_specials(prod) write_output(prod) if len(vprod) > 0: prod = vprod next_num = 0 prod = replace_specials(prod) for name, num, nick in entries: tmp_prod = prod if '\u0040valuenum\u0040' in prod: # only attempt to eval the value if it is requested # this prevents us from throwing errors otherwise if num is not None: # use sandboxed evaluation as a reasonable # approximation to C constant folding inum = eval(num, {}, {}) # make sure it parsed to an integer if not isinstance(inum, int): sys.exit("Unable to parse enum value '%s'" % num) num = inum else: num = next_num tmp_prod = tmp_prod.replace('\u0040valuenum\u0040', str(num)) next_num = int(num) + 1 tmp_prod = tmp_prod.replace('\u0040VALUENAME\u0040', name) tmp_prod = tmp_prod.replace('\u0040valuenick\u0040', nick) if flags: tmp_prod = tmp_prod.replace('\u0040type\u0040', 'flags') else: tmp_prod = tmp_prod.replace('\u0040type\u0040', 'enum') if flags: tmp_prod = tmp_prod.replace('\u0040Type\u0040', 'Flags') else: tmp_prod = tmp_prod.replace('\u0040Type\u0040', 'Enum') if flags: tmp_prod = tmp_prod.replace('\u0040TYPE\u0040', 'FLAGS') else: tmp_prod = tmp_prod.replace('\u0040TYPE\u0040', 'ENUM') tmp_prod = tmp_prod.rstrip() write_output(tmp_prod) if len(vtail) > 0: prod = vtail prod = prod.replace('\u0040enum_name\u0040', enumsym) prod = prod.replace('\u0040EnumName\u0040', enumname) prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort) prod = prod.replace('\u0040ENUMNAME\u0040', enumlong) prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix) prod = prod.replace('\u0040enumsince\u0040', enumsince) if flags: prod = prod.replace('\u0040type\u0040', 'flags') else: prod = prod.replace('\u0040type\u0040', 'enum') if flags: prod = prod.replace('\u0040Type\u0040', 'Flags') else: prod = prod.replace('\u0040Type\u0040', 'Enum') if flags: prod = prod.replace('\u0040TYPE\u0040', 'FLAGS') else: prod = prod.replace('\u0040TYPE\u0040', 'ENUM') prod = replace_specials(prod) write_output(prod) for fname in sorted(options.args): process_file(fname) if len(ftail) > 0: prod = ftail warn_if_filename_basename_used('file-tail', prod) prod = replace_specials(prod) write_output(prod) # put auto-generation comment comment = comment_tmpl comment = comment.replace('\u0040comment\u0040', 'Generated data ends here') write_output("\n" + comment + "\n") if tmpfile is not None: tmpfilename = tmpfile.name tmpfile.close() try: os.unlink(options.output) except OSError as error: if error.errno != errno.ENOENT: raise error os.rename(tmpfilename, options.output) libmbim-1.31.2-dev/build-aux/templates/000077500000000000000000000000001453630424100176575ustar00rootroot00000000000000libmbim-1.31.2-dev/build-aux/templates/mbim-enum-types.c.template000066400000000000000000000026241453630424100246710ustar00rootroot00000000000000/*** BEGIN file-header ***/ /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ static const G@Type@Value @enum_name@_values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; /* Define type-specific symbols */ GType @enum_name@_get_type (void) { static gsize g_define_type_id_initialized = 0; if (g_once_init_enter (&g_define_type_id_initialized)) { GType g_define_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), @enum_name@_values); g_once_init_leave (&g_define_type_id_initialized, g_define_type_id); } return g_define_type_id_initialized; } /* Enum-specific method to get the value as a string. * We get the nick of the GEnumValue. Note that this will be * valid even if the GEnumClass is not referenced anywhere. */ const gchar * @enum_name@_get_string (@EnumName@ val) { guint i; for (i = 0; @enum_name@_values[i].value_nick; i++) { if ((gint)val == @enum_name@_values[i].value) return @enum_name@_values[i].value_nick; } return NULL; } /*** END value-tail ***/ /*** BEGIN file-tail ***/ /*** END file-tail ***/ libmbim-1.31.2-dev/build-aux/templates/mbim-enum-types.h.template000066400000000000000000000014661453630424100247010ustar00rootroot00000000000000/*** BEGIN file-header ***/ #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) G_GNUC_CONST; #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) /* Define type-specific symbols */ #define __@ENUMNAME@_IS_@TYPE@__ /** * @enum_name@_get_string: * @val: a @EnumName@. * * Gets the nickname string for the #@EnumName@ specified at @val. * * Returns: (transfer none): a string with the nickname, or %NULL if not found. Do not free the returned value. * * Since: @enumsince@ */ const gchar *@enum_name@_get_string (@EnumName@ val); /*** END value-header ***/ /*** BEGIN file-tail ***/ G_END_DECLS /*** END file-tail ***/ libmbim-1.31.2-dev/build-aux/templates/mbim-error-quarks.c.template000066400000000000000000000017431453630424100252210ustar00rootroot00000000000000/*** BEGIN file-header ***/ #include /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ #define ERROR_PREFIX @ENUMNAME@_DBUS_PREFIX static const GDBusErrorEntry @enum_name@_entries[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, ERROR_PREFIX ".@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ }; #undef ERROR_PREFIX GQuark @enum_name@_quark (void) { static volatile gsize quark_volatile = 0; if (!quark_volatile) g_dbus_error_register_error_domain ("@enum_name@_quark", &quark_volatile, @enum_name@_entries, G_N_ELEMENTS (@enum_name@_entries)); return (GQuark) quark_volatile; } /*** END value-tail ***/ /*** BEGIN file-tail ***/ /*** END file-tail ***/ libmbim-1.31.2-dev/build-aux/templates/mbim-error-types.c.template000066400000000000000000000032411453630424100250520ustar00rootroot00000000000000/*** BEGIN file-header ***/ /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ static const G@Type@Value @enum_name@_values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; /* @enum_name@_quark() implemented in mbim-errors-quarks.c */ GType @enum_name@_get_type (void) { static gsize g_define_type_id_initialized = 0; if (g_once_init_enter (&g_define_type_id_initialized)) { GType g_define_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), @enum_name@_values); g_once_init_leave (&g_define_type_id_initialized, g_define_type_id); } return g_define_type_id_initialized; } /* Enum-specific method to get the value as a string. * We get the nick of the GEnumValue. Note that this will be * valid even if the GEnumClass is not referenced anywhere. */ /** * @enum_name@_get_string: * @val: a @EnumName@. * * Gets the nickname string for the #@EnumName@ specified at @val. * * Returns: (transfer none): a string with the nickname, or %NULL if not found. Do not free the returned value. */ const gchar * @enum_name@_get_string (@EnumName@ val) { guint i; for (i = 0; @enum_name@_values[i].value_nick; i++) { if ((gint)val == @enum_name@_values[i].value) return @enum_name@_values[i].value_nick; } return NULL; } /*** END value-tail ***/ /*** BEGIN file-tail ***/ /*** END file-tail ***/ libmbim-1.31.2-dev/build-aux/templates/mbim-error-types.h.template000066400000000000000000000010621453630424100250560ustar00rootroot00000000000000/*** BEGIN file-header ***/ #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ GQuark @enum_name@_quark (void); GType @enum_name@_get_type (void) G_GNUC_CONST; #define @ENUMNAME@ (@enum_name@_quark ()) #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) const gchar *@enum_name@_get_string (@EnumName@ val); /*** END value-header ***/ /*** BEGIN file-tail ***/ G_END_DECLS /*** END file-tail ***/ libmbim-1.31.2-dev/build-aux/templates/mbim-flag-types.c.template000066400000000000000000000044241453630424100246360ustar00rootroot00000000000000/*** BEGIN file-header ***/ /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ static const G@Type@Value @enum_name@_values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; /* Define type-specific symbols */ GType @enum_name@_get_type (void) { static gsize g_define_type_id_initialized = 0; if (g_once_init_enter (&g_define_type_id_initialized)) { GType g_define_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), @enum_name@_values); g_once_init_leave (&g_define_type_id_initialized, g_define_type_id); } return g_define_type_id_initialized; } /* Flags-specific method to build a string with the given mask. * We get a comma separated list of the nicks of the GFlagsValues. * Note that this will be valid even if the GFlagsClass is not referenced * anywhere. */ gchar * @enum_name@_build_string_from_mask (@EnumName@ mask) { guint i; gboolean first = TRUE; GString *str = NULL; for (i = 0; @enum_name@_values[i].value_nick; i++) { /* We also look for exact matches */ if ((guint)mask == @enum_name@_values[i].value) { if (str) g_string_free (str, TRUE); return g_strdup (@enum_name@_values[i].value_nick); } /* Build list with single-bit masks */ if (mask & @enum_name@_values[i].value) { guint c; gulong number = @enum_name@_values[i].value; for (c = 0; number; c++) number &= number - 1; if (c == 1) { if (!str) str = g_string_new (""); g_string_append_printf (str, "%s%s", first ? "" : ", ", @enum_name@_values[i].value_nick); if (first) first = FALSE; } } } return (str ? g_string_free (str, FALSE) : NULL); } /*** END value-tail ***/ /*** BEGIN file-tail ***/ /*** END file-tail ***/ libmbim-1.31.2-dev/build-aux/templates/mbim-flag-types.h.template000066400000000000000000000016271453630424100246450ustar00rootroot00000000000000/*** BEGIN file-header ***/ #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) G_GNUC_CONST; #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) /* Define type-specific symbols */ #define __@ENUMNAME@_IS_@TYPE@__ /** * @enum_name@_build_string_from_mask: * @mask: bitmask of @EnumName@ values. * * Builds a string containing a comma-separated list of nicknames for * each #@EnumName@ in @mask. * * Returns: (transfer full): a string with the list of nicknames, or %NULL if none given. The returned value should be freed with g_free(). * * Since: @enumsince@ */ gchar *@enum_name@_build_string_from_mask (@EnumName@ mask); /*** END value-header ***/ /*** BEGIN file-tail ***/ G_END_DECLS /*** END file-tail ***/ libmbim-1.31.2-dev/data/000077500000000000000000000000001453630424100147005ustar00rootroot00000000000000libmbim-1.31.2-dev/data/mbim-service-atds.json000066400000000000000000000146421453630424100211150ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "ATDS" }, // ********************************************************************************* { "name" : "Signal", "type" : "Command", "since" : "1.16", "query" : [], "response" : [ // 0-31: dBm = -113 + (2*rssi) // 99: unknown/undetectable { "name" : "Rssi", "format" : "guint32" }, // 0: BER < 0.2% // 1: 0.2% < BER < 0.4% // 2: 0.4% < BER < 0.8% // 3: 0.8% < BER < 1.6% // 4: 1.6% < BER < 3.2% // 5: 3.2% < BER < 6.4% // 6: 6.4% < BER < 12.8% // 7: 12.8% < BER // 99: unknown/undetectable { "name" : "ErrorRate", "format" : "guint32" }, // 0: -120 or less dBm // <96: dBm = -120+rscp // 96: -24 or greater dBm // 255: unknown/undetectable { "name" : "Rscp", "format" : "guint32" }, // 0: -24 or less dBm // <49: dBm = -24 + ((float)ecno/2) // 49: 0.5 or greater dBm // 255: unknown/undetectable { "name" : "Ecno", "format" : "guint32" }, // 0: -19.5 or less dBm // <34: dBm = -19.5 + ((float)rsrq/2) // 34: -2.5 or greater dBm // 255: unknown/undetectable { "name" : "Rsrq", "format" : "guint32" }, // 0: -140 or less dBm // <97: dBm = -140 + rsrp // 97: -43 or greater dBm // 255: unknown/undetectable { "name" : "Rsrp", "format" : "guint32" }, // 0: -5 or less dB // <35: dB = -5 + rssnr // 35: 30 or greater dB // 255: unknown/undetectable { "name" : "Rssnr", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "Location", "type" : "Command", "since" : "1.16", "query" : [], "response" : [ { "name" : "Lac", "format" : "guint32" }, { "name" : "Tac", "format" : "guint32" }, { "name" : "CellId", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "MbimAtdsProvider", "type" : "Struct", "since" : "1.16", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "ProviderState", "format" : "guint32", "public-format" : "MbimProviderState" }, { "name" : "ProviderName", "format" : "string" }, { "name" : "PlmnMode", "format" : "guint32", "public-format" : "MbimAtdsProviderPlmnMode" }, { "name" : "Rssi", "format" : "guint32" }, { "name" : "ErrorRate", "format" : "guint32" } ] }, { "name" : "Operators", "type" : "Command", "since" : "1.16", "query" : [], "response" : [ { "name" : "ProvidersCount", "format" : "guint32" }, { "name" : "Providers", "format" : "ref-struct-array" , "struct-type" : "MbimAtdsProvider", "array-size-field" : "ProvidersCount" } ] }, // ********************************************************************************* { "name" : "RAT", "type" : "Command", "since" : "1.16", "set" : [ { "name" : "Mode", "format" : "guint32", "public-format" : "MbimAtdsRatMode" } ], "query" : [], "response" : [ { "name" : "Mode", "format" : "guint32", "public-format" : "MbimAtdsRatMode" } ] }, // ********************************************************************************* { "name" : "Register State", "type" : "Command", "since" : "1.16", "query" : [], "response" : [ { "name" : "NwError", "format" : "guint32", "public-format" : "MbimNwError" }, { "name" : "RegisterState", "format" : "guint32", "public-format" : "MbimRegisterState" }, { "name" : "RegisterMode", "format" : "guint32", "public-format" : "MbimRegisterMode" }, { "name" : "AvailableDataClasses", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "CurrentCellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "ProviderId", "format" : "string" }, { "name" : "ProviderName", "format" : "string" }, { "name" : "RoamingText", "format" : "string" }, { "name" : "RegistrationFlag", "format" : "guint32", "public-format" : "MbimRegistrationFlag" } ] } ] libmbim-1.31.2-dev/data/mbim-service-auth.json000066400000000000000000000073001453630424100211140ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "Auth" }, // ********************************************************************************* { "name" : "Aka", "type" : "Command", "since" : "1.4", "query" : [ { "name" : "Rand", "format" : "byte-array", "array-size" : "16" }, { "name" : "Autn", "format" : "byte-array", "array-size" : "16" } ], "response" : [ { "name" : "Res", "format" : "byte-array", "array-size" : "16" }, { "name" : "ResLen", "format" : "guint32" }, { "name" : "IntegratingKey", "format" : "byte-array", "array-size" : "16" }, { "name" : "CipheringKey", "format" : "byte-array", "array-size" : "16" }, { "name" : "Auts", "format" : "byte-array", "array-size" : "14" } ] }, // ********************************************************************************* { "name" : "Akap", "type" : "Command", "since" : "1.4", "query" : [ { "name" : "Rand", "format" : "byte-array", "array-size" : "16" }, { "name" : "Autn", "format" : "byte-array", "array-size" : "16" }, { "name" : "NetworkName", "format" : "string" } ], "response" : [ { "name" : "Res", "format" : "byte-array", "array-size" : "16" }, { "name" : "ResLen", "format" : "guint32" }, { "name" : "IntegratingKey", "format" : "byte-array", "array-size" : "16" }, { "name" : "CipheringKey", "format" : "byte-array", "array-size" : "16" }, { "name" : "Auts", "format" : "byte-array", "array-size" : "14" } ] }, // ********************************************************************************* { "name" : "Sim", "type" : "Command", "since" : "1.4", "query" : [ { "name" : "Rand1", "format" : "byte-array", "array-size" : "16" }, { "name" : "Rand2", "format" : "byte-array", "array-size" : "16" }, { "name" : "Rand3", "format" : "byte-array", "array-size" : "16" }, { "name" : "N", "format" : "guint32" } ], "response" : [ { "name" : "Sres1", "format" : "guint32" }, { "name" : "Kc1", "format" : "guint64" }, { "name" : "Sres2", "format" : "guint32" }, { "name" : "Kc2", "format" : "guint64" }, { "name" : "Sres3", "format" : "guint32" }, { "name" : "Kc3", "format" : "guint64" }, { "name" : "N", "format" : "guint32" } ] } ] libmbim-1.31.2-dev/data/mbim-service-basic-connect.json000066400000000000000000001237411453630424100226730ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "Basic Connect" }, // ********************************************************************************* { "name" : "Device Caps", "type" : "Command", "since" : "1.0", "query" : [], "response" : [ { "name" : "DeviceType", "format" : "guint32", "public-format" : "MbimDeviceType" }, { "name" : "CellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "VoiceClass", "format" : "guint32", "public-format" : "MbimVoiceClass" }, { "name" : "SimClass", "format" : "guint32", "public-format" : "MbimSimClass" }, { "name" : "DataClass", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "SmsCaps", "format" : "guint32", "public-format" : "MbimSmsCaps" }, { "name" : "ControlCaps", "format" : "guint32", "public-format" : "MbimCtrlCaps" }, { "name" : "MaxSessions", "format" : "guint32" }, { "name" : "CustomDataClass", "format" : "string", "max-size" : "22" }, { "name" : "DeviceId", "format" : "string", "max-size" : "36", "personal-info" : "true" }, { "name" : "FirmwareInfo", "format" : "string", "max-size" : "60" }, { "name" : "HardwareInfo", "format" : "string", "max-size" : "60" } ] }, // ********************************************************************************* { "name" : "Subscriber Ready Status", "type" : "Command", "since-ex" : { "query" : "1.0", "response" : "1.0", "notification" : "1.8" }, "query" : [], "response" : [ { "name" : "ReadyState", "format" : "guint32", "public-format" : "MbimSubscriberReadyState" }, { "name" : "SubscriberId", "format" : "string", "personal-info" : "true" }, { "name" : "SimIccId", "format" : "string", "personal-info" : "true" }, { "name" : "ReadyInfo", "format" : "guint32", "public-format" : "MbimReadyInfoFlag" }, { "name" : "TelephoneNumbersCount", "format" : "guint32" }, { "name" : "TelephoneNumbers", "format" : "string-array", "array-size-field" : "TelephoneNumbersCount", "personal-info" : "true" } ], "notification" : [ { "name" : "ReadyState", "format" : "guint32", "public-format" : "MbimSubscriberReadyState" }, { "name" : "SubscriberId", "format" : "string", "personal-info" : "true" }, { "name" : "SimIccId", "format" : "string", "personal-info" : "true" }, { "name" : "ReadyInfo", "format" : "guint32", "public-format" : "MbimReadyInfoFlag" }, { "name" : "TelephoneNumbersCount", "format" : "guint32" }, { "name" : "TelephoneNumbers", "format" : "string-array", "array-size-field" : "TelephoneNumbersCount", "personal-info" : "true"} ] }, // ********************************************************************************* { "name" : "Radio State", "type" : "Command", "since" : "1.0", "set" : [ { "name" : "RadioState", "format" : "guint32", "public-format" : "MbimRadioSwitchState" } ], "query" : [], "response" : [ { "name" : "HwRadioState", "format" : "guint32", "public-format" : "MbimRadioSwitchState" }, { "name" : "SwRadioState", "format" : "guint32", "public-format" : "MbimRadioSwitchState" } ], "notification" : [ { "name" : "HwRadioState", "format" : "guint32", "public-format" : "MbimRadioSwitchState" }, { "name" : "SwRadioState", "format" : "guint32", "public-format" : "MbimRadioSwitchState" } ] }, // ********************************************************************************* { "name" : "Pin", "type" : "Command", "since" : "1.0", "set" : [ { "name" : "PinType", "format" : "guint32", "public-format" : "MbimPinType" }, { "name" : "PinOperation", "format" : "guint32", "public-format" : "MbimPinOperation" }, { "name" : "Pin", "format" : "string" }, { "name" : "NewPin", "format" : "string" } ], "query" : [], "response" : [ { "name" : "PinType", "format" : "guint32", "public-format" : "MbimPinType" }, { "name" : "PinState", "format" : "guint32", "public-format" : "MbimPinState" }, { "name" : "RemainingAttempts", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "MbimPinDesc", "type" : "Struct", "since" : "1.0", "contents" : [ { "name" : "PinMode", "format" : "guint32", "public-format" : "MbimPinMode" }, { "name" : "PinFormat", "format" : "guint32", "public-format" : "MbimPinFormat" }, { "name" : "PinLengthMin", "format" : "guint32" }, { "name" : "PinLengthMax", "format" : "guint32" } ] }, { "name" : "Pin List", "type" : "Command", "since" : "1.0", "query" : [], "response" : [ { "name" : "PinDescPin1", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescPin2", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescDeviceSimPin", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescDeviceFirstSimPin", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescNetworkPin", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescNetworkSubsetPin", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescServiceProviderPin", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescCorporatePin", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescSubsidyLock", "format" : "struct", "struct-type" : "MbimPinDesc" }, { "name" : "PinDescCustom", "format" : "struct", "struct-type" : "MbimPinDesc" } ] }, // ********************************************************************************* { "name" : "MbimProvider", "type" : "Struct", "since" : "1.2", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "ProviderState", "format" : "guint32", "public-format" : "MbimProviderState" }, { "name" : "ProviderName", "format" : "string" }, { "name" : "CellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "Rssi", "format" : "guint32" }, { "name" : "ErrorRate", "format" : "guint32" } ] }, { "name" : "Home Provider", "type" : "Command", "since" : "1.2", "set" : [ { "name" : "Provider", "format" : "struct" , "struct-type" : "MbimProvider" } ], "query" : [], "response" : [ { "name" : "Provider", "format" : "struct", "struct-type" : "MbimProvider" } ] }, // ********************************************************************************* { "name" : "Preferred Providers", "type" : "Command", "since-ex" : { "set" : "1.2", "query" : "1.2", "response" : "1.2", "notification" : "1.8" }, "set" : [ { "name" : "ProvidersCount", "format" : "guint32" }, { "name" : "Providers", "format" : "ref-struct-array" , "struct-type" : "MbimProvider", "array-size-field" : "ProvidersCount" } ], "query" : [], "response" : [ { "name" : "ProvidersCount", "format" : "guint32" }, { "name" : "Providers", "format" : "ref-struct-array" , "struct-type" : "MbimProvider", "array-size-field" : "ProvidersCount" } ], "notification" : [ { "name" : "ProvidersCount", "format" : "guint32" }, { "name" : "Providers", "format" : "ref-struct-array" , "struct-type" : "MbimProvider", "array-size-field" : "ProvidersCount" } ] }, // ********************************************************************************* { "name" : "Visible Providers", "type" : "Command", "since" : "1.2", "query" : [ { "name" : "Action", "format": "guint32", "public-format" : "MbimVisibleProvidersAction" } ], "response" : [ { "name" : "ProvidersCount", "format" : "guint32" }, { "name" : "Providers", "format" : "ref-struct-array" , "struct-type" : "MbimProvider", "array-size-field" : "ProvidersCount" } ] }, // ********************************************************************************* { "name" : "Register State", "type" : "Command", "since" : "1.0", "set" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "RegisterAction", "format" : "guint32", "public-format" : "MbimRegisterAction" }, { "name" : "DataClass", "format" : "guint32", "public-format" : "MbimDataClass" } ], "query" : [], "response" : [ { "name" : "NwError", "format" : "guint32", "public-format" : "MbimNwError" }, { "name" : "RegisterState", "format" : "guint32", "public-format" : "MbimRegisterState" }, { "name" : "RegisterMode", "format" : "guint32", "public-format" : "MbimRegisterMode" }, { "name" : "AvailableDataClasses", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "CurrentCellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "ProviderId", "format" : "string" }, { "name" : "ProviderName", "format" : "string" }, { "name" : "RoamingText", "format" : "string" }, { "name" : "RegistrationFlag", "format" : "guint32", "public-format" : "MbimRegistrationFlag" } ], "notification" : [ { "name" : "NwError", "format" : "guint32", "public-format" : "MbimNwError" }, { "name" : "RegisterState", "format" : "guint32", "public-format" : "MbimRegisterState" }, { "name" : "RegisterMode", "format" : "guint32", "public-format" : "MbimRegisterMode" }, { "name" : "AvailableDataClasses", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "CurrentCellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "ProviderId", "format" : "string" }, { "name" : "ProviderName", "format" : "string" }, { "name" : "RoamingText", "format" : "string" }, { "name" : "RegistrationFlag", "format" : "guint32", "public-format" : "MbimRegistrationFlag" } ] }, // ********************************************************************************* { "name" : "Signal State", "type" : "Command", "since" : "1.0", "set" : [ { "name" : "SignalStrengthInterval", "format" : "guint32" }, { "name" : "RssiThreshold", "format" : "guint32" }, { "name" : "ErrorRateThreshold", "format" : "guint32" } ], "query" : [], "response" : [ { "name" : "Rssi", "format" : "guint32" }, { "name" : "ErrorRate", "format" : "guint32" }, { "name" : "SignalStrengthInterval", "format" : "guint32" }, { "name" : "RssiThreshold", "format" : "guint32" }, { "name" : "ErrorRateThreshold", "format" : "guint32" } ], "notification" : [ { "name" : "Rssi", "format" : "guint32" }, { "name" : "ErrorRate", "format" : "guint32" }, { "name" : "SignalStrengthInterval", "format" : "guint32" }, { "name" : "RssiThreshold", "format" : "guint32" }, { "name" : "ErrorRateThreshold", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "Packet Service", "type" : "Command", "since" : "1.0", "set" : [ { "name" : "PacketServiceAction", "format" : "guint32", "public-format" : "MbimPacketServiceAction" } ], "query" : [], "response" : [ { "name" : "NwError", "format" : "guint32" }, { "name" : "PacketServiceState", "format" : "guint32", "public-format" : "MbimPacketServiceState" }, { "name" : "HighestAvailableDataClass", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "UplinkSpeed", "format" : "guint64" }, { "name" : "DownlinkSpeed", "format" : "guint64" } ], "notification" : [ { "name" : "NwError", "format" : "guint32" }, { "name" : "PacketServiceState", "format" : "guint32", "public-format" : "MbimPacketServiceState" }, { "name" : "HighestAvailableDataClass", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "UplinkSpeed", "format" : "guint64" }, { "name" : "DownlinkSpeed", "format" : "guint64" } ] }, // ********************************************************************************* { "name" : "Connect", "type" : "Command", "since" : "1.0", "set" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "ActivationCommand", "format" : "guint32", "public-format" : "MbimActivationCommand" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "ContextType", "format" : "uuid" } ], "query" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "ActivationState", "format" : "guint32", "public-format" : "MbimActivationState" }, { "name" : "VoiceCallState", "format" : "guint32", "public-format" : "MbimVoiceCallState" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "NwError", "format" : "guint32" } ], "response" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "ActivationState", "format" : "guint32", "public-format" : "MbimActivationState" }, { "name" : "VoiceCallState", "format" : "guint32", "public-format" : "MbimVoiceCallState" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "NwError", "format" : "guint32" } ], "notification" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "ActivationState", "format" : "guint32", "public-format" : "MbimActivationState" }, { "name" : "VoiceCallState", "format" : "guint32", "public-format" : "MbimVoiceCallState" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "NwError", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "MbimProvisionedContextElement", "type" : "Struct", "since" : "1.0", "contents" : [ { "name" : "ContextId", "format" : "guint32" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" } ] }, { "name" : "Provisioned Contexts", "type" : "Command", "since" : "1.0", "set" : [ { "name" : "ContextId", "format" : "guint32" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" }, { "name" : "ProviderId", "format" : "string" } ], "query" : [], "response" : [ { "name" : "ProvisionedContextsCount", "format" : "guint32" }, { "name" : "ProvisionedContexts", "format" : "ref-struct-array", "struct-type" : "MbimProvisionedContextElement", "array-size-field" : "ProvisionedContextsCount" } ], "notification" : [ { "name" : "ProvisionedContextsCount", "format" : "guint32" }, { "name" : "ProvisionedContexts", "format" : "ref-struct-array", "struct-type" : "MbimProvisionedContextElement", "array-size-field" : "ProvisionedContextsCount" } ] }, // ********************************************************************************* { "name" : "Service Activation", "type" : "Command", "since" : "1.2", "set" : [ { "name" : "Buffer", "format" : "unsized-byte-array" } ], "response" : [ { "name" : "NwError", "format" : "guint32", "public-format" : "MbimNwError" }, { "name" : "Buffer", "format" : "unsized-byte-array" } ] }, // ********************************************************************************* { "name" : "MbimIPv4Element", "type" : "Struct", "since" : "1.0", "contents" : [ { "name" : "OnLinkPrefixLength", "format" : "guint32" }, { "name" : "IPv4Address", "format" : "ipv4" } ] }, { "name" : "MbimIPv6Element", "type" : "Struct", "since" : "1.0", "contents" : [ { "name" : "OnLinkPrefixLength", "format" : "guint32" }, { "name" : "IPv6Address", "format" : "ipv6" } ] }, { "name" : "IP Configuration", "type" : "Command", "since" : "1.0", "query" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "IPv4ConfigurationAvailable", "format" : "guint32", "public-format" : "MbimIPConfigurationAvailableFlag" }, { "name" : "IPv6ConfigurationAvailable", "format" : "guint32", "public-format" : "MbimIPConfigurationAvailableFlag" }, { "name" : "IPv4AddressCount", "format" : "guint32" }, { "name" : "IPv4Address", "format" : "struct-array", "struct-type" : "MbimIPv4Element", "array-size-field" : "IPv4AddressCount" }, { "name" : "IPv6AddressCount", "format" : "guint32" }, { "name" : "IPv6Address", "format" : "struct-array", "struct-type" : "MbimIPv6Element", "array-size-field" : "IPv6AddressCount" }, { "name" : "IPv4Gateway", "format" : "ref-ipv4" }, { "name" : "IPv6Gateway", "format" : "ref-ipv6" }, { "name" : "IPv4DnsServerCount", "format" : "guint32" }, { "name" : "IPv4DnsServer", "format" : "ipv4-array", "array-size-field" : "IPv4DnsServerCount" }, { "name" : "IPv6DnsServerCount", "format" : "guint32" }, { "name" : "IPv6DnsServer", "format" : "ipv6-array", "array-size-field" : "IPv6DnsServerCount" }, { "name" : "IPv4Mtu", "format" : "guint32" }, { "name" : "IPv6Mtu", "format" : "guint32" } ], "response" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "IPv4ConfigurationAvailable", "format" : "guint32", "public-format" : "MbimIPConfigurationAvailableFlag" }, { "name" : "IPv6ConfigurationAvailable", "format" : "guint32", "public-format" : "MbimIPConfigurationAvailableFlag" }, { "name" : "IPv4AddressCount", "format" : "guint32" }, { "name" : "IPv4Address", "format" : "struct-array", "struct-type" : "MbimIPv4Element", "array-size-field" : "IPv4AddressCount" }, { "name" : "IPv6AddressCount", "format" : "guint32" }, { "name" : "IPv6Address", "format" : "struct-array", "struct-type" : "MbimIPv6Element", "array-size-field" : "IPv6AddressCount" }, { "name" : "IPv4Gateway", "format" : "ref-ipv4" }, { "name" : "IPv6Gateway", "format" : "ref-ipv6" }, { "name" : "IPv4DnsServerCount", "format" : "guint32" }, { "name" : "IPv4DnsServer", "format" : "ipv4-array", "array-size-field" : "IPv4DnsServerCount" }, { "name" : "IPv6DnsServerCount", "format" : "guint32" }, { "name" : "IPv6DnsServer", "format" : "ipv6-array", "array-size-field" : "IPv6DnsServerCount" }, { "name" : "IPv4Mtu", "format" : "guint32" }, { "name" : "IPv6Mtu", "format" : "guint32" } ], "notification" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "IPv4ConfigurationAvailable", "format" : "guint32", "public-format" : "MbimIPConfigurationAvailableFlag" }, { "name" : "IPv6ConfigurationAvailable", "format" : "guint32", "public-format" : "MbimIPConfigurationAvailableFlag" }, { "name" : "IPv4AddressCount", "format" : "guint32" }, { "name" : "IPv4Address", "format" : "struct-array", "struct-type" : "MbimIPv4Element", "array-size-field" : "IPv4AddressCount" }, { "name" : "IPv6AddressCount", "format" : "guint32" }, { "name" : "IPv6Address", "format" : "struct-array", "struct-type" : "MbimIPv6Element", "array-size-field" : "IPv6AddressCount" }, { "name" : "IPv4Gateway", "format" : "ref-ipv4" }, { "name" : "IPv6Gateway", "format" : "ref-ipv6" }, { "name" : "IPv4DnsServerCount", "format" : "guint32" }, { "name" : "IPv4DnsServer", "format" : "ipv4-array", "array-size-field" : "IPv4DnsServerCount" }, { "name" : "IPv6DnsServerCount", "format" : "guint32" }, { "name" : "IPv6DnsServer", "format" : "ipv6-array", "array-size-field" : "IPv6DnsServerCount" }, { "name" : "IPv4Mtu", "format" : "guint32" }, { "name" : "IPv6Mtu", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "MbimDeviceServiceElement", "type" : "Struct", "since" : "1.0", "contents" : [ { "name" : "DeviceServiceId", "format" : "uuid" }, { "name" : "DssPayload", "format" : "guint32" }, { "name" : "MaxDssInstances", "format" : "guint32" }, { "name" : "CidsCount", "format" : "guint32" }, { "name" : "Cids", "format" : "guint32-array", "array-size-field" : "CidsCount" } ] }, { "name" : "Device Services", "type" : "Command", "since" : "1.0", "query" : [], "response" : [ { "name" : "DeviceServicesCount", "format" : "guint32" }, { "name" : "MaxDssSessions", "format" : "guint32" }, { "name" : "DeviceServices", "format" : "ref-struct-array", "struct-type" : "MbimDeviceServiceElement", "array-size-field" : "DeviceServicesCount" } ] }, // ********************************************************************************* { "name" : "MbimEventEntry", "type" : "Struct", "since" : "1.4", "contents" : [ { "name" : "DeviceServiceId", "format" : "uuid" }, { "name" : "CidsCount", "format" : "guint32" }, { "name" : "Cids", "format" : "guint32-array", "array-size-field" : "CidsCount" } ] }, { "name" : "Device Service Subscribe List", "type" : "Command", "since" : "1.8", "set" : [ { "name" : "EventsCount", "format" : "guint32" }, { "name" : "Events", "format" : "ref-struct-array", "struct-type" : "MbimEventEntry", "array-size-field" : "EventsCount" } ], "response" : [ { "name" : "EventsCount", "format" : "guint32" }, { "name" : "Events", "format" : "ref-struct-array", "struct-type" : "MbimEventEntry", "array-size-field" : "EventsCount" } ] }, // ********************************************************************************* { "name" : "Packet Statistics", "type" : "Command", "since" : "1.4", "query" : [], "response" : [ { "name" : "InDiscards", "format" : "guint32" }, { "name" : "InErrors", "format" : "guint32" }, { "name" : "InOctets", "format" : "guint64" }, { "name" : "InPackets", "format" : "guint64" }, { "name" : "OutOctets", "format" : "guint64" }, { "name" : "OutPackets", "format" : "guint64" }, { "name" : "OutErrors", "format" : "guint32" }, { "name" : "OutDiscards", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "Network Idle Hint", "type" : "Command", "since" : "1.4", "query" : [], "set" : [ { "name" : "State", "format" : "guint32", "public-format" : "MbimNetworkIdleHintState" } ], "response" : [ { "name" : "State", "format" : "guint32", "public-format" : "MbimNetworkIdleHintState" } ] }, // ********************************************************************************* { "name" : "Emergency Mode", "type" : "Command", "since-ex" : { "set" : "1.4", "query" : "1.4", "response" : "1.4", "notification" : "1.8" }, "query" : [], "set" : [ { "name" : "State", "format" : "guint32", "public-format" : "MbimEmergencyModeState" } ], "response" : [ { "name" : "State", "format" : "guint32", "public-format" : "MbimEmergencyModeState" } ], "notification" : [ { "name" : "State", "format" : "guint32", "public-format" : "MbimEmergencyModeState" } ] }, // ********************************************************************************* { "name" : "MbimPacketFilter", "type" : "Struct", "since" : "1.4", "contents" : [ { "name" : "FilterSize", "format" : "guint32" }, { "name" : "PacketFilter", "format" : "ref-byte-array", "array-size-field" : "FilterSize" }, { "name" : "PacketMask", "format" : "ref-byte-array", "array-size-field" : "FilterSize" } ] }, { "name" : "IP Packet Filters", "type" : "Command", "since" : "1.4", "query" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "PacketFiltersCount", "format" : "guint32" }, { "name" : "PacketFilters", "format" : "ref-struct-array", "struct-type" : "MbimPacketFilter", "array-size-field" : "PacketFiltersCount" } ], "set" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "PacketFiltersCount", "format" : "guint32" }, { "name" : "PacketFilters", "format" : "ref-struct-array", "struct-type" : "MbimPacketFilter", "array-size-field" : "PacketFiltersCount" } ], "response" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "PacketFiltersCount", "format" : "guint32" }, { "name" : "PacketFilters", "format" : "ref-struct-array", "struct-type" : "MbimPacketFilter", "array-size-field" : "PacketFiltersCount" } ] }, // ********************************************************************************* { "name" : "Multicarrier Providers", "type" : "Command", "since-ex" : { "set" : "1.4", "query" : "1.4", "response" : "1.4", "notification" : "1.8" }, "set" : [ { "name" : "ProvidersCount", "format" : "guint32" }, { "name" : "Providers", "format" : "ref-struct-array" , "struct-type" : "MbimProvider", "array-size-field" : "ProvidersCount" } ], "query" : [], "response" : [ { "name" : "ProvidersCount", "format" : "guint32" }, { "name" : "Providers", "format" : "ref-struct-array" , "struct-type" : "MbimProvider", "array-size-field" : "ProvidersCount" } ], "notification" : [ { "name" : "ProvidersCount", "format" : "guint32" }, { "name" : "Providers", "format" : "ref-struct-array" , "struct-type" : "MbimProvider", "array-size-field" : "ProvidersCount" } ] } ] libmbim-1.31.2-dev/data/mbim-service-dss.json000066400000000000000000000012531453630424100207450ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "DSS" }, // ********************************************************************************* { "name" : "Connect", "type" : "Command", "since" : "1.4", "set" : [ { "name" : "DeviceServiceId", "format" : "uuid" }, { "name" : "DssSessionId", "format" : "guint32" }, { "name" : "DssLinkState", "format" : "guint32", "public-format" : "MbimDssLinkState" } ], "response" : [] } ] libmbim-1.31.2-dev/data/mbim-service-fibocom.json000066400000000000000000000011661453630424100215750ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Fibocom" }, // ********************************************************************************* { "name" : "AT Command", "type" : "Command", "since" : "1.32", "set" : [ { "name" : "CommandReq", "format" : "unsized-byte-array", "pad-array" : "FALSE"} ], "response" : [ { "name" : "CommandResp", "format" : "unsized-byte-array"} ] } ] libmbim-1.31.2-dev/data/mbim-service-google.json000066400000000000000000000031221453630424100214250ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Google" }, // ********************************************************************************* { "name" : "Carrier Lock", "type" : "Command", "since" : "1.30", "set" : [ { "name" : "Data", "format" : "ref-byte-array-no-offset" } ], "query" : [], "response" : [ { "name" : "CarrierLockStatus", "format" : "guint32", "public-format" : "MbimCarrierLockStatus" }, { "name" : "CarrierLockModemState", "format" : "guint32", "public-format" : "MbimCarrierLockModemState" }, { "name" : "CarrierLockCause", "format" : "guint32", "public-format" : "MbimCarrierLockCause" } ], "notification" : [ { "name" : "CarrierLockStatus", "format" : "guint32", "public-format" : "MbimCarrierLockStatus" }, { "name" : "CarrierLockModemState", "format" : "guint32", "public-format" : "MbimCarrierLockModemState" }, { "name" : "CarrierLockCause", "format" : "guint32", "public-format" : "MbimCarrierLockCause" } ] } ] libmbim-1.31.2-dev/data/mbim-service-intel-firmware-update-v2.json000066400000000000000000000012721453630424100247070ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Intel Firmware Update V2", "mbimex-service" : "Intel Firmware Update", "mbimex-version" : "2.0" }, // ********************************************************************************* { "name" : "Modem Reboot", "type" : "Command", "since" : "1.28", "set" : [ { "name" : "BootMode", "format" : "guint32", "public-format" : "MbimIntelBootMode" }, { "name" : "Timeout", "format" : "guint32" } ] } ] libmbim-1.31.2-dev/data/mbim-service-intel-firmware-update.json000066400000000000000000000005371453630424100243650ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Intel Firmware Update" }, // ********************************************************************************* { "name" : "Modem Reboot", "type" : "Command", "since" : "1.16", "set" : [] } ] libmbim-1.31.2-dev/data/mbim-service-intel-mutual-authentication.json000066400000000000000000000016501453630424100256120ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Intel Mutual Authentication" }, // ********************************************************************************* { "name" : "FCC Lock", "service" : "Intel Mutual Authentication", "type" : "Command", "since" : "1.30", "query" : [], "set" : [ { "name" : "ResponsePresent", "format" : "guint32", "public-format" : "gboolean" }, { "name" : "Response", "format" : "guint32" } ], "response" : [ { "name" : "ChallengePresent", "format" : "guint32", "public-format" : "gboolean" }, { "name" : "Challenge", "format" : "guint32" } ] } ] libmbim-1.31.2-dev/data/mbim-service-intel-thermal-rf.json000066400000000000000000000062341453630424100233320ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Intel Thermal RF" }, // *********************************************************************************** { "name" : "MbimIntelRfimFrequencyValue", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ServingCellInfo", "format" : "guint32", "public-format" : "MbimIntelServingCellInfo" }, { "name" : "CenterFrequency", "format" : "guint64" }, { "name" : "Bandwidth", "format" : "guint32" }, // 0: -140 or less dBm // <97: dBm = -140 + rsrp // 97: -43 or greater dBm // 0xFFFFFFFF: unknown/undetectable { "name" : "RSRP", "format" : "guint32" }, // 0: -19.5 or less dB // <34: dB = -19.5 + ((float)rsrq/2) // 34: -2.5 or greater dB // 0xFFFFFFFF: unknown/undetectable { "name" : "RSRQ", "format" : "guint32" }, // 0: -23 or less dB //<127: ((float)sinr/2) - 23 // 127: 40 or greater dB // 0xFFFFFFFF: unknown/undetectable { "name" : "SINR", "format" : "guint32" }, // 0-31: dBm = -113 + (2*rssi) // 99: unknown/undetectable { "name" : "RSSI", "format" : "guint32" }, { "name" : "ConnectionStatus", "format" : "guint32", "public-format" : "gboolean" } ] }, { "name" : "RFIM", "type" : "Command", "service" : "Intel Thermal RF", "since" : "1.28", "set" : [ { "name" : "ActivationState", "format" : "guint32", "public-format" : "gboolean" } ], "query" : [], "response" : [ { "name" : "RfimFrequencyValuesCount", "format" : "guint32" }, { "name" : "RfimFrequencyValues", "format" : "ref-struct-array", "struct-type" : "MbimIntelRfimFrequencyValue", "array-size-field" : "RfimFrequencyValuesCount" } ], "notification" : [ { "name" : "RfimFrequencyValuesCount", "format" : "guint32" }, { "name" : "RfimFrequencyValues", "format" : "ref-struct-array", "struct-type" : "MbimIntelRfimFrequencyValue", "array-size-field" : "RfimFrequencyValuesCount" } ] } ] libmbim-1.31.2-dev/data/mbim-service-intel-tools.json000066400000000000000000000017731453630424100224340ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Intel Tools" }, // ********************************************************************************* { "name" : "Trace Config", "type" : "Command", "since" : "1.30", "set" : [ { "name" : "TraceCmd", "format" : "guint32", "public-format" : "MbimTraceCommand" }, { "name" : "TraceValue", "format" : "guint32" } ], "query" : [ { "name" : "TraceCmd", "format" : "guint32", "public-format" : "MbimTraceCommand" } ], "response" : [ { "name" : "TraceCmd", "format" : "guint32", "public-format" : "MbimTraceCommand" }, { "name" : "Result", "format" : "guint32" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ms-basic-connect-extensions-v2.json000066400000000000000000000014751453630424100260310ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Ms Basic Connect Extensions V2", "mbimex-service" : "Ms Basic Connect Extensions", "mbimex-version" : "2.0" }, // ********************************************************************************* { "name" : "Version", "type" : "Command", "since" : "1.28", "query" : [ { "name" : "MbimVersion", "format" : "guint16" }, { "name" : "MbimExtendedVersion", "format" : "guint16" } ], "response" : [ { "name" : "MbimVersion", "format" : "guint16" }, { "name" : "MbimExtendedVersion", "format" : "guint16" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ms-basic-connect-extensions-v3.json000066400000000000000000000336741453630424100260400ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Ms Basic Connect Extensions V3", "mbimex-service" : "Ms Basic Connect Extensions", "mbimex-version" : "3.0" }, // ********************************************************************************* { "name" : "Device Caps", "type" : "Command", "since" : "1.28", // query same as in v1 "response" : [ { "name" : "DeviceType", "format" : "guint32", "public-format" : "MbimDeviceType" }, { "name" : "CellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "VoiceClass", "format" : "guint32", "public-format" : "MbimVoiceClass" }, { "name" : "SimClass", "format" : "guint32", "public-format" : "MbimSimClass" }, { "name" : "DataClass", "format" : "guint32", "public-format" : "MbimDataClassV3" }, { "name" : "SmsCaps", "format" : "guint32", "public-format" : "MbimSmsCaps" }, { "name" : "ControlCaps", "format" : "guint32", "public-format" : "MbimCtrlCaps" }, { "name" : "DataSubclass", "format" : "guint64", "public-format" : "MbimDataSubclass" }, { "name" : "MaxSessions", "format" : "guint32" }, { "name" : "ExecutorIndex", "format" : "guint32" }, { "name" : "WcdmaBandClass", "format" : "guint32" }, { "name" : "LteBandClass", "format" : "tlv-guint16-array" }, { "name" : "NrBandClass", "format" : "tlv-guint16-array" }, { "name" : "CustomDataClass", "format" : "tlv-string" }, { "name" : "DeviceId", "format" : "tlv-string", "personal-info" : "true" }, { "name" : "FirmwareInfo", "format" : "tlv-string" }, { "name" : "HardwareInfo", "format" : "tlv-string" } ] }, //********************************************************************************** { "name" : "Modem Configuration", "type" : "Command", "since" : "1.28", "query" : [], "response" : [ { "name" : "ConfigurationStatus", "format" : "guint32", "public-format" : "MbimModemConfigurationStatus" }, { "name" : "ConfigurationName", "format" : "tlv-string" }, { "name" : "UnnamedIes", "format" : "tlv-list" } ], "notification" : [ { "name" : "ModemConfigurationStatus", "format" : "guint32", "public-format" : "MbimModemConfigurationStatus" }, { "name" : "ConfigurationName", "format" : "tlv-string" }, { "name" : "UnnamedIes", "format" : "tlv-list" } ] }, //************************************************************************************ { "name" : "Registration Parameters", "type" : "Command", "since" : "1.28", "set" : [ { "name" : "MicoMode", "format" : "guint32", "public-format" : "MbimMicoMode" }, { "name" : "DrxCycle", "format" : "guint32", "public-format" : "MbimDrxCycle" }, { "name" : "LadnInfo", "format" : "guint32", "public-format" : "MbimLadnInfo" }, { "name" : "DefaultPduActivationHint", "format" : "guint32", "public-format" : "MbimDefaultPduActivationHint" }, { "name" : "ReRegisterIfNedeed", "format" : "guint32", "public-format" : "gboolean" }, { "name" : "UnnamedIes", "format" : "tlv-list" } ], "query" : [], "response" : [ { "name" : "MicoMode", "format" : "guint32", "public-format" : "MbimMicoMode" }, { "name" : "DrxCycle", "format" : "guint32", "public-format" : "MbimDrxCycle" }, { "name" : "LadnInfo", "format" : "guint32", "public-format" : "MbimLadnInfo" }, { "name" : "DefaultPduActivationHint", "format" : "guint32", "public-format" : "MbimDefaultPduActivationHint" }, { "name" : "ReRegisterIfNedeed", "format" : "guint32", "public-format" : "gboolean" }, { "name" : "UnnamedIes", "format" : "tlv-list" } ] }, // ********************************************************************************* { "name" : "Lte Attach Info", "type" : "Command", "since" : "1.28", // query same as in v1 "response" : [ { "name" : "LteAttachState", "format" : "guint32", "public-format" : "MbimLteAttachState" }, { "name" : "NwError", "format" : "guint32", "public-format" : "MbimNwError" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" } ], "notification" : [ { "name" : "LteAttachState", "format" : "guint32", "public-format" : "MbimLteAttachState" }, { "name" : "NwError", "format" : "guint32", "public-format" : "MbimNwError" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" } ] }, // ********************************************************************************* { "name" : "MbimCellInfoServingNr", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "Nci", "format" : "guint64" }, { "name" : "PhysicalCellID", "format" : "guint32" }, { "name" : "Nrarfcn", "format" : "guint32" }, { "name" : "Tac", "format" : "guint32" }, { "name" : "Rsrp", "format" : "guint32" }, { "name" : "Rsrq", "format" : "guint32" }, { "name" : "Sinr", "format" : "guint32" }, { "name" : "TimingAdvance", "format" : "guint64" } ] }, { "name" : "MbimCellInfoNeighboringNr", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "SystemSubType", "format" : "guint32", "public-format" : "MbimDataSubclass" }, { "name" : "ProviderId", "format" : "string" }, { "name" : "CellId", "format" : "string" }, { "name" : "PhysicalCellID", "format" : "guint32" }, { "name" : "Tac", "format" : "guint32" }, { "name" : "Rsrp", "format" : "guint32" }, { "name" : "Rsrq", "format" : "guint32" }, { "name" : "Sinr", "format" : "guint32" } ] }, { "name" : "Base Stations Info", "type" : "Command", "since" : "1.28", "query" : [ { "name" : "MaxGsmCount", "format" : "guint32" }, { "name" : "MaxUmtsCount", "format" : "guint32" }, { "name" : "MaxTdscdmaCount", "format" : "guint32" }, { "name" : "MaxLteCount", "format" : "guint32" }, { "name" : "MaxCdmaCount", "format" : "guint32" }, { "name" : "MaxNrCount", "format" : "guint32" } ], "response" : [ { "name" : "SystemType", "format" : "guint32", "public-format" : "MbimDataClassV3" }, { "name" : "SystemSubType", "format" : "guint32", "public-format" : "MbimDataSubclass" }, { "name" : "GsmServingCell", "format" : "ms-struct", "struct-type" : "MbimCellInfoServingGsm" }, { "name" : "UmtsServingCell", "format" : "ms-struct", "struct-type" : "MbimCellInfoServingUmts" }, { "name" : "TdscdmaServingCell", "format" : "ms-struct", "struct-type" : "MbimCellInfoServingTdscdma" }, { "name" : "LteServingCell", "format" : "ms-struct", "struct-type" : "MbimCellInfoServingLte" }, { "name" : "GsmNeighboringCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringGsm" }, { "name" : "UmtsNeighboringCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringUmts" }, { "name" : "TdscdmaNeighboringCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringTdscdma" }, { "name" : "LteNeighboringCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringLte" }, { "name" : "CdmaCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoCdma" }, { "name" : "NrServingCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoServingNr" }, { "name" : "NrNeighborCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringNr" } ] }, //************************************************************************************ { "name" : "Wake Reason", "type" : "Command", "since" : "1.28", "query" : [], "response" : [ { "name" : "WakeType", "format" : "guint32", "public-format" : "MbimWakeType" }, { "name" : "SessionId", "format" : "guint32" }, { "name" : "WakeTlv", "format" : "tlv" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ms-basic-connect-extensions.json000066400000000000000000000654241453630424100255100ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Ms Basic Connect Extensions" }, // ********************************************************************************* { "name" : "MbimPcoValue", "type" : "Struct", "since" : "1.18", "contents" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "PcoDataSize", "format" : "guint32" }, { "name" : "PcoDataType", "format" : "guint32", "public-format" : "MbimPcoType" }, { "name" : "PcoDataBuffer", "format" : "ref-byte-array-no-offset", "array-size-field" : "PcoDataSize" } ] }, { "name" : "PCO", "type" : "Command", "since" : "1.18", "query" : [ { "name" : "PcoValue", "format" : "struct", "struct-type" : "MbimPcoValue" } ], "response" : [ { "name" : "PcoValue", "format" : "struct", "struct-type" : "MbimPcoValue" } ], "notification" : [ { "name" : "PcoValue", "format" : "struct", "struct-type" : "MbimPcoValue" } ] }, // ********************************************************************************* { "name" : "MbimLteAttachConfiguration", "type" : "Struct", "since" : "1.18", "contents" : [ { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "Roaming", "format" : "guint32", "public-format" : "MbimLteAttachContextRoamingControl" }, { "name" : "Source", "format" : "guint32", "public-format" : "MbimContextSource" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" } ] }, { "name" : "Lte Attach Configuration", "type" : "Command", "since" : "1.18", "set" : [ { "name" : "Operation", "format" : "guint32", "public-format" : "MbimLteAttachContextOperation" }, { "name" : "ConfigurationCount", "format" : "guint32" }, { "name" : "Configurations", "format" : "ref-struct-array" , "struct-type" : "MbimLteAttachConfiguration", "array-size-field" : "ConfigurationCount" } ], "query" : [], "response" : [ { "name" : "ConfigurationCount", "format" : "guint32" }, { "name" : "Configurations", "format" : "ref-struct-array" , "struct-type" : "MbimLteAttachConfiguration", "array-size-field" : "ConfigurationCount" } ], "notification" : [ { "name" : "ConfigurationCount", "format" : "guint32" }, { "name" : "Configurations", "format" : "ref-struct-array" , "struct-type" : "MbimLteAttachConfiguration", "array-size-field" : "ConfigurationCount" } ] }, // ********************************************************************************* { "name" : "Lte Attach Info", "type" : "Command", "since" : "1.26", "query" : [], "response" : [ { "name" : "LteAttachState", "format" : "guint32", "public-format" : "MbimLteAttachState" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" } ], "notification" : [ { "name" : "LteAttachState", "format" : "guint32", "public-format" : "MbimLteAttachState" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" } ] }, //********************************************************************************** { "name" : "Sys Caps", "type" : "Command", "since" : "1.26", "query" : [], "response" : [ { "name" : "NumberOfExecutors", "format" : "guint32" }, { "name" : "NumberOfSlots", "format" : "guint32" }, { "name" : "Concurrency", "format" : "guint32" }, { "name" : "ModemId", "format" : "guint64" } ] }, //********************************************************************************** { "name" : "Slot Info Status", "type" : "Command", "since" : "1.26", "query" : [ { "name" : "SlotIndex", "format" : "guint32" } ], "response" : [ { "name" : "SlotIndex", "format" : "guint32" }, { "name" : "State", "format" : "guint32", "public-format" : "MbimUiccSlotState" } ], "notification" : [ { "name" : "SlotIndex", "format" : "guint32" }, { "name" : "State", "format" : "guint32", "public-format" : "MbimUiccSlotState" } ] }, //************************************************************************************ { "name" : "MbimSlot", "type" : "Struct", "since" : "1.26", "contents" : [ { "name" : "Slot", "format" : "guint32" } ] }, { "name" : "Device Slot Mappings", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "MapCount", "format" : "guint32" }, { "name" : "SlotMap", "format" : "ref-struct-array", "struct-type" : "MbimSlot", "array-size-field" : "MapCount" } ], "query" : [], "response" : [ { "name" : "MapCount", "format" : "guint32" }, { "name" : "SlotMap", "format" : "ref-struct-array", "struct-type" : "MbimSlot", "array-size-field" : "MapCount" } ] }, //************************************************************************************ { "name" : "Device Caps", "type" : "Command", "since" : "1.26", "query" : [], "response" : [ { "name" : "DeviceType", "format" : "guint32", "public-format" : "MbimDeviceType" }, { "name" : "CellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "VoiceClass", "format" : "guint32", "public-format" : "MbimVoiceClass" }, { "name" : "SmsClass", "format" : "guint32", "public-format" : "MbimSimClass" }, { "name" : "DataClass", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "SmsCaps", "format" : "guint32", "public-format" : "MbimSmsCaps" }, { "name" : "ControlCaps", "format" : "guint32", "public-format" : "MbimCtrlCaps" }, { "name" : "MaxSessions", "format" : "guint32" }, { "name" : "CustomDataClass", "format" : "string", "max-size" : "22" }, { "name" : "DeviceId", "format" : "string", "max-size" : "36", "personal-info" : "true" }, { "name" : "FirmwareInfo", "format" : "string", "max-size" : "60" }, { "name" : "HardwareInfo", "format" : "string", "max-size" : "60" }, { "name" : "ExecutorIndex", "format" : "guint32" } ] }, //************************************************************************************ { "name" : "Location Info Status", "type" : "Command", "since" : "1.28", "query" : [], "response" : [ { "name" : "LocationAreaCode", "format" : "guint32" }, { "name" : "TrackingAreaCode", "format" : "guint32" }, { "name" : "CellID", "format" : "guint32" } ], "notification" : [ { "name" : "LocationAreaCode", "format" : "guint32" }, { "name" : "TrackingAreaCode", "format" : "guint32" }, { "name" : "CellID", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "MbimProvisionedContextElementV2", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ContextId", "format" : "guint32" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "State", "format" : "guint32", "public-format" : "MbimContextState" }, { "name" : "Roaming", "format" : "guint32", "public-format" : "MbimContextRoamingControl" }, { "name" : "MediaType", "format" : "guint32", "public-format" : "MbimContextMediaType" }, { "name" : "Source", "format" : "guint32", "public-format" : "MbimContextSource" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" } ] }, { "name" : "Provisioned Contexts", "type" : "Command", "since" : "1.28", "set" : [ { "name" : "Operation", "format" : "guint32", "public-format" : "MbimContextOperation" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "State", "format" : "guint32", "public-format" : "MbimContextState" }, { "name" : "Roaming", "format" : "guint32", "public-format" : "MbimContextRoamingControl" }, { "name" : "MediaType", "format" : "guint32", "public-format" : "MbimContextMediaType" }, { "name" : "Source", "format" : "guint32", "public-format" : "MbimContextSource" }, { "name" : "AccessString", "format" : "string" }, { "name" : "UserName", "format" : "string", "personal-info" : "true" }, { "name" : "Password", "format" : "string", "personal-info" : "true" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" } ], "query" : [], "response" : [ { "name" : "ProvisionedContextsCount", "format" : "guint32" }, { "name" : "ProvisionedContexts", "format" : "ref-struct-array", "struct-type" : "MbimProvisionedContextElementV2", "array-size-field" : "ProvisionedContextsCount" } ], "notification" : [ { "name" : "ProvisionedContextsCount", "format" : "guint32" }, { "name" : "ProvisionedContexts", "format" : "ref-struct-array", "struct-type" : "MbimProvisionedContextElementV2", "array-size-field" : "ProvisionedContextsCount" } ] }, // ********************************************************************************* { "name" : "MbimCellInfoServingGsm", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "LocationAreaCode", "format" : "guint32" }, { "name" : "CellId", "format" : "guint32" }, { "name" : "TimingAdvance", "format" : "guint32" }, { "name" : "Arfcn", "format" : "guint32" }, { "name" : "BaseStationId", "format" : "guint32" }, { "name" : "RxLevel", "format" : "guint32" } ] }, { "name" : "MbimCellInfoServingUmts", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "LocationAreaCode", "format" : "guint32" }, { "name" : "CellId", "format" : "guint32" }, { "name" : "FrequencyInfoUL", "format" : "guint32" }, { "name" : "FrequencyInfoDL", "format" : "guint32" }, { "name" : "FrequencyInfoNT", "format" : "guint32" }, { "name" : "Uarfcn", "format" : "guint32" }, { "name" : "PrimaryScramblingCode", "format" : "guint32" }, { "name" : "Rscp", "format" : "gint32" }, { "name" : "Ecno", "format" : "gint32" }, { "name" : "PathLoss", "format" : "guint32" } ] }, { "name" : "MbimCellInfoServingTdscdma", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "LocationAreaCode", "format" : "guint32" }, { "name" : "CellId", "format" : "guint32" }, { "name" : "Uarfcn", "format" : "guint32" }, { "name" : "CellParameterID", "format" : "guint32" }, { "name" : "TimingAdvance", "format" : "guint32" }, { "name" : "Rscp", "format" : "gint32" }, { "name" : "PathLoss", "format" : "guint32" } ] }, { "name" : "MbimCellInfoServingLte", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "CellId", "format" : "guint32" }, { "name" : "Earfcn", "format" : "guint32" }, { "name" : "PhysicalCellId", "format" : "guint32" }, { "name" : "Tac", "format" : "guint32" }, { "name" : "Rsrp", "format" : "gint32" }, { "name" : "Rsrq", "format" : "gint32" }, { "name" : "TimingAdvance", "format" : "guint32" } ] }, { "name" : "MbimCellInfoNeighboringGsm", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "LocationAreaCode", "format" : "guint32" }, { "name" : "CellId", "format" : "guint32" }, { "name" : "Arfcn", "format" : "guint32" }, { "name" : "BaseStationId", "format" : "guint32" }, { "name" : "RxLevel", "format" : "guint32" } ] }, { "name" : "MbimCellInfoNeighboringUmts", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "LocationAreaCode", "format" : "guint32" }, { "name" : "CellId", "format" : "guint32" }, { "name" : "Uarfcn", "format" : "guint32" }, { "name" : "PrimaryScramblingCode", "format" : "guint32" }, { "name" : "Rscp", "format" : "gint32" }, { "name" : "Ecno", "format" : "gint32" }, { "name" : "PathLoss", "format" : "guint32" } ] }, { "name" : "MbimCellInfoNeighboringTdscdma", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "LocationAreaCode", "format" : "guint32" }, { "name" : "CellId", "format" : "guint32" }, { "name" : "Uarfcn", "format" : "guint32" }, { "name" : "CellParameterID", "format" : "guint32" }, { "name" : "TimingAdvance", "format" : "guint32" }, { "name" : "Rscp", "format" : "gint32" }, { "name" : "PathLoss", "format" : "guint32" } ] }, { "name" : "MbimCellInfoNeighboringLte", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ProviderId", "format" : "string" }, { "name" : "CellId", "format" : "guint32" }, { "name" : "Earfcn", "format" : "guint32" }, { "name" : "PhysicalCellId", "format" : "guint32" }, { "name" : "Tac", "format" : "guint32" }, { "name" : "Rsrp", "format" : "gint32" }, { "name" : "Rsrq", "format" : "gint32" } ] }, { "name" : "MbimCellInfoCdma", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ServingCellFlag", "format" : "guint32" }, { "name" : "Nid", "format" : "guint32" }, { "name" : "Sid", "format" : "guint32" }, { "name" : "BaseStationId", "format" : "guint32" }, { "name" : "BaseLatitude", "format" : "guint32" }, { "name" : "BaseLongitude", "format" : "guint32" }, { "name" : "RefPn", "format" : "guint32" }, { "name" : "GpsSeconds", "format" : "guint32" }, { "name" : "PilotStrength", "format" : "guint32" } ] }, { "name" : "Base Stations Info", "type" : "Command", "since" : "1.28", "query" : [ { "name" : "MaxGsmCount", "format" : "guint32" }, { "name" : "MaxUmtsCount", "format" : "guint32" }, { "name" : "MaxTdscdmaCount", "format" : "guint32" }, { "name" : "MaxLteCount", "format" : "guint32" } , { "name" : "MaxCdmaCount", "format" : "guint32" } ], "response" : [ { "name" : "SystemType", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "GsmServingCell", "format" : "ms-struct", "struct-type" : "MbimCellInfoServingGsm" }, { "name" : "UmtsServingCell", "format" : "ms-struct", "struct-type" : "MbimCellInfoServingUmts" }, { "name" : "TdscdmaServingCell", "format" : "ms-struct", "struct-type" : "MbimCellInfoServingTdscdma" }, { "name" : "LteServingCell", "format" : "ms-struct", "struct-type" : "MbimCellInfoServingLte" }, { "name" : "GsmNeighboringCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringGsm" }, { "name" : "UmtsNeighboringCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringUmts" }, { "name" : "TdscdmaNeighboringCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringTdscdma" }, { "name" : "LteNeighboringCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoNeighboringLte" }, { "name" : "CdmaCells", "format" : "ms-struct-array", "struct-type" : "MbimCellInfoCdma" } ] }, // ********************************************************************************* { "name" : "Device Reset", "type" : "Command", "since" : "1.30", "set" : [], "response" : [] } ] libmbim-1.31.2-dev/data/mbim-service-ms-basic-connect-v2.json000066400000000000000000000176161453630424100236400ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "Ms Basic Connect V2", "mbimex-service" : "Basic Connect", "mbimex-version" : "2.0" }, // ********************************************************************************* { "name" : "Register State", "type" : "Command", "since" : "1.28", // set same as in v1 // query same as in v1 "response" : [ { "name" : "NwError", "format" : "guint32", "public-format" : "MbimNwError" }, { "name" : "RegisterState", "format" : "guint32", "public-format" : "MbimRegisterState" }, { "name" : "RegisterMode", "format" : "guint32", "public-format" : "MbimRegisterMode" }, { "name" : "AvailableDataClasses", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "CurrentCellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "ProviderId", "format" : "string" }, { "name" : "ProviderName", "format" : "string" }, { "name" : "RoamingText", "format" : "string" }, { "name" : "RegistrationFlag", "format" : "guint32", "public-format" : "MbimRegistrationFlag" }, { "name" : "PreferredDataClasses", "format" : "guint32", "public-format" : "MbimDataClass" } ], "notification" : [ { "name" : "NwError", "format" : "guint32", "public-format" : "MbimNwError" }, { "name" : "RegisterState", "format" : "guint32", "public-format" : "MbimRegisterState" }, { "name" : "RegisterMode", "format" : "guint32", "public-format" : "MbimRegisterMode" }, { "name" : "AvailableDataClasses", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "CurrentCellularClass", "format" : "guint32", "public-format" : "MbimCellularClass" }, { "name" : "ProviderId", "format" : "string" }, { "name" : "ProviderName", "format" : "string" }, { "name" : "RoamingText", "format" : "string" }, { "name" : "RegistrationFlag", "format" : "guint32", "public-format" : "MbimRegistrationFlag" }, { "name" : "PreferredDataClasses", "format" : "guint32", "public-format" : "MbimDataClass" } ] }, // ********************************************************************************* { "name" : "Packet Service", "type" : "Command", "since" : "1.28", // set same as in v1 // query same as in v1 "response" : [ { "name" : "NwError", "format" : "guint32" }, { "name" : "PacketServiceState", "format" : "guint32", "public-format" : "MbimPacketServiceState" }, { "name" : "CurrentDataClass", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "UplinkSpeed", "format" : "guint64" }, { "name" : "DownlinkSpeed", "format" : "guint64" }, { "name" : "FrequencyRange", "format" : "guint32", "public-format" : "MbimFrequencyRange" } ], "notification" : [ { "name" : "NwError", "format" : "guint32" }, { "name" : "PacketServiceState", "format" : "guint32", "public-format" : "MbimPacketServiceState" }, { "name" : "CurrentDataClass", "format" : "guint32", "public-format" : "MbimDataClass" }, { "name" : "UplinkSpeed", "format" : "guint64" }, { "name" : "DownlinkSpeed", "format" : "guint64" }, { "name" : "FrequencyRange", "format" : "guint32", "public-format" : "MbimFrequencyRange" } ] }, // ********************************************************************************* { "name" : "MbimRsrpSnrInfo", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "Rsrp", "format" : "guint32" }, { "name" : "Snr", "format" : "guint32" }, { "name" : "RsrpThreshold", "format" : "guint32" }, { "name" : "SnrThreshold", "format" : "guint32" }, { "name" : "SystemType", "format" : "guint32", "public-format" : "MbimDataClass" } ] }, { "name" : "Signal State", "type" : "Command", "since" : "1.28", // set same as in v1 // query same as in v1 "response" : [ { "name" : "Rssi", "format" : "guint32" }, { "name" : "ErrorRate", "format" : "guint32" }, { "name" : "SignalStrengthInterval", "format" : "guint32" }, { "name" : "RssiThreshold", "format" : "guint32" }, { "name" : "ErrorRateThreshold", "format" : "guint32" }, { "name" : "RsrpSnr", "format" : "ms-struct-array" , "struct-type" : "MbimRsrpSnrInfo" } ], "notification" : [ { "name" : "Rssi", "format" : "guint32" }, { "name" : "ErrorRate", "format" : "guint32" }, { "name" : "SignalStrengthInterval", "format" : "guint32" }, { "name" : "RssiThreshold", "format" : "guint32" }, { "name" : "ErrorRateThreshold", "format" : "guint32" }, { "name" : "RsrpSnr", "format" : "ms-struct-array" , "struct-type" : "MbimRsrpSnrInfo" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ms-basic-connect-v3.json000066400000000000000000000311751453630424100236350ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "Ms Basic Connect V3", "mbimex-service" : "Basic Connect", "mbimex-version" : "3.0" }, // ********************************************************************************* { "name" : "Subscriber Ready Status", "type" : "Command", "since" : "1.28", // query same as in v1 "response" : [ { "name" : "ReadyState", "format" : "guint32", "public-format" : "MbimSubscriberReadyState" }, { "name" : "Flags", "format" : "guint32", "public-format" : "MbimSubscriberReadyStatusFlag" }, { "name" : "SubscriberId", "format" : "string", "personal-info" : "true" }, { "name" : "SimIccId", "format" : "string", "personal-info" : "true" }, { "name" : "ReadyInfo", "format" : "guint32", "public-format" : "MbimReadyInfoFlag" }, { "name" : "TelephoneNumbersCount", "format" : "guint32" }, { "name" : "TelephoneNumbers", "format" : "string-array", "array-size-field" : "TelephoneNumbersCount", "personal-info" : "true" } ], "notification" : [ { "name" : "ReadyState", "format" : "guint32", "public-format" : "MbimSubscriberReadyState" }, { "name" : "Flags", "format" : "guint32", "public-format" : "MbimSubscriberReadyStatusFlag" }, { "name" : "SubscriberId", "format" : "string", "personal-info" : "true" }, { "name" : "SimIccId", "format" : "string", "personal-info" : "true" }, { "name" : "ReadyInfo", "format" : "guint32", "public-format" : "MbimReadyInfoFlag" }, { "name" : "TelephoneNumbersCount", "format" : "guint32" }, { "name" : "TelephoneNumbers", "format" : "string-array", "array-size-field" : "TelephoneNumbersCount", "personal-info" : "true"} ] }, // ********************************************************************************* { "name" : "MbimTai", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "PlmnMcc", "format" : "guint16" }, { "name" : "PlmnMnc", "format" : "guint16" }, { "name" : "Tac", "format" : "guint32" } ] }, { "name" : "Packet Service", "type" : "Command", "since" : "1.28", // set same as in v1 // query same as in v1 "response" : [ { "name" : "NwError", "format" : "guint32" }, { "name" : "PacketServiceState", "format" : "guint32", "public-format" : "MbimPacketServiceState" }, { "name" : "HighestAvailableDataClass", "format" : "guint32", "public-format" : "MbimDataClassV3" }, { "name" : "UplinkSpeed", "format" : "guint64" }, { "name" : "DownlinkSpeed", "format" : "guint64" }, { "name" : "FrequencyRange", "format" : "guint32", "public-format" : "MbimFrequencyRange" }, { "name" : "DataSubclass", "format" : "guint32", "public-format" : "MbimDataSubclass" }, { "name" : "Tai", "format" : "struct", "struct-type" : "MbimTai" } ], "notification" : [ { "name" : "NwError", "format" : "guint32" }, { "name" : "PacketServiceState", "format" : "guint32", "public-format" : "MbimPacketServiceState" }, { "name" : "HighestAvailableDataClass", "format" : "guint32", "public-format" : "MbimDataClassV3" }, { "name" : "UplinkSpeed", "format" : "guint64" }, { "name" : "DownlinkSpeed", "format" : "guint64" }, { "name" : "FrequencyRange", "format" : "guint32", "public-format" : "MbimFrequencyRange" }, { "name" : "DataSubclass", "format" : "guint32", "public-format" : "MbimDataSubclass" }, { "name" : "Tai", "format" : "struct", "struct-type" : "MbimTai" } ] }, // ********************************************************************************* { "name" : "Connect", "service" : "Basic Connect", "type" : "Command", "since" : "1.28", "set" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "ActivationCommand", "format" : "guint32", "public-format" : "MbimActivationCommand" }, { "name" : "Compression", "format" : "guint32", "public-format" : "MbimCompression" }, { "name" : "AuthProtocol", "format" : "guint32", "public-format" : "MbimAuthProtocol" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "MediaPreference", "format" : "guint32", "public-format" : "MbimAccessMediaType" }, { "name" : "AccessString", "format" : "tlv-string" }, { "name" : "UserName", "format" : "tlv-string", "personal-info" : "true" }, { "name" : "Password", "format" : "tlv-string", "personal-info" : "true" }, { "name" : "UnnamedIes", "format" : "tlv-list" } ], "query" : [ { "name" : "SessionId", "format" : "guint32" } ], "response" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "ActivationState", "format" : "guint32", "public-format" : "MbimActivationState" }, { "name" : "VoiceCallState", "format" : "guint32", "public-format" : "MbimVoiceCallState" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "NwError", "format" : "guint32" }, { "name" : "MediaPreference", "format" : "guint32", "public-format" : "MbimAccessMediaType" }, { "name" : "AccessString", "format" : "tlv-string" }, { "name" : "UnnamedIes", "format" : "tlv-list" } ], "notification" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "ActivationState", "format" : "guint32", "public-format" : "MbimActivationState" }, { "name" : "VoiceCallState", "format" : "guint32", "public-format" : "MbimVoiceCallState" }, { "name" : "IpType", "format" : "guint32", "public-format" : "MbimContextIpType" }, { "name" : "ContextType", "format" : "uuid" }, { "name" : "NwError", "format" : "guint32" }, { "name" : "MediaPreference", "format" : "guint32", "public-format" : "MbimAccessMediaType" }, { "name" : "AccessString", "format" : "tlv-string" }, { "name" : "UnnamedIes", "format" : "tlv-list" } ] }, // ********************************************************************************* { "name" : "MbimPacketFilterV3", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "FilterSize", "format" : "guint32" }, { "name" : "PacketFilter", "format" : "ref-byte-array", "array-size-field" : "FilterSize" }, { "name" : "PacketMask", "format" : "ref-byte-array", "array-size-field" : "FilterSize" }, { "name" : "FilterId", "format" : "guint32" } ] }, { "name" : "IP Packet Filters", "type" : "Command", "since" : "1.28", "query" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "PacketFiltersCount", "format" : "guint32" }, { "name" : "PacketFilters", "format" : "ref-struct-array", "struct-type" : "MbimPacketFilterV3", "array-size-field" : "PacketFiltersCount" } ], "set" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "PacketFiltersCount", "format" : "guint32" }, { "name" : "PacketFilters", "format" : "ref-struct-array", "struct-type" : "MbimPacketFilterV3", "array-size-field" : "PacketFiltersCount" } ], "response" : [ { "name" : "SessionId", "format" : "guint32" }, { "name" : "PacketFiltersCount", "format" : "guint32" }, { "name" : "PacketFilters", "format" : "ref-struct-array", "struct-type" : "MbimPacketFilterV3", "array-size-field" : "PacketFiltersCount" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ms-firmware-id.json000066400000000000000000000006501453630424100227770ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "MS Firmware ID" }, // ********************************************************************************* { "name" : "Get", "type" : "Command", "since" : "1.8", "query" : [], "response" : [ { "name" : "FirmwareId", "format" : "uuid" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ms-host-shutdown.json000066400000000000000000000005231453630424100234160ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "MS Host Shutdown" }, // ********************************************************************************* { "name" : "Notify", "type" : "Command", "since" : "1.8", "set" : [] } ] libmbim-1.31.2-dev/data/mbim-service-ms-sar.json000066400000000000000000000074771453630424100213740ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "MS SAR" }, // ********************************************************************************* { "name" : "MbimSarConfigState", "type" : "Struct", "since" : "1.26", "contents" : [ { "name" : "AntennaIndex", "format" : "guint32" }, { "name" : "BackoffIndex", "format" : "guint32" } ] }, { "name" : "Config", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "Mode", "format" : "guint32", "public-format" : "MbimSarControlMode" }, { "name" : "BackoffState", "format" : "guint32", "public-format" : "MbimSarBackoffState" }, { "name" : "ConfigStatesCount", "format" : "guint32" }, { "name" : "ConfigStates", "format" : "ref-struct-array" , "struct-type" : "MbimSarConfigState", "array-size-field" : "ConfigStatesCount" } ], "query" : [], "response" : [ { "name" : "Mode", "format" : "guint32", "public-format" : "MbimSarControlMode" }, { "name" : "BackoffState", "format" : "guint32", "public-format" : "MbimSarBackoffState" }, { "name" : "WifiIntegration", "format" : "guint32", "public-format" : "MbimSarWifiHardwareState" }, { "name" : "ConfigStatesCount", "format" : "guint32" }, { "name" : "ConfigStates", "format" : "ref-struct-array" , "struct-type" : "MbimSarConfigState", "array-size-field" : "ConfigStatesCount" } ] }, // ********************************************************************************* { "name" : "Transmission status", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "ChannelNotification", "format" : "guint32" , "public-format" : "MbimTransmissionNotificationStatus"}, { "name" : "HysteresisTimer", "format" : "guint32" } ], "query" : [], "response" : [ { "name" : "ChannelNotification", "format" : "guint32" , "public-format" : "MbimTransmissionNotificationStatus"}, { "name" : "TransmissionStatus", "format" : "guint32" , "public-format" : "MbimTransmissionState"}, { "name" : "HysteresisTimer", "format" : "guint32" } ], "notification" : [ { "name" : "ChannelNotification", "format" : "guint32" , "public-format" : "MbimTransmissionNotificationStatus"}, { "name" : "TransmissionStatus", "format" : "guint32" , "public-format" : "MbimTransmissionState"}, { "name" : "HysteresisTimer", "format" : "guint32" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ms-uicc-low-level-access.json000066400000000000000000000236071453630424100246660ustar00rootroot00000000000000[ // ************************************************************************ { "type" : "Service", "name" : "MS UICC Low Level Access" }, // ************************************************************************ { "name" : "ATR", "type" : "Command", "since" : "1.26", "query" : [], "response" : [ { "name" : "atr", "format" : "uicc-ref-byte-array" } ] }, // ************************************************************************ { "name" : "Open Channel", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "AppId", "format" : "uicc-ref-byte-array" }, { "name" : "SelectP2Arg", "format" : "guint32" }, { "name" : "ChannelGroup", "format" : "guint32" } ], "response" : [ { "name" : "Status", "format" : "guint32" }, { "name" : "Channel", "format" : "guint32" }, { "name" : "Response", "format" : "uicc-ref-byte-array" } ] }, // ************************************************************************ { "name" : "Close Channel", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "Channel", "format" : "guint32" }, { "name" : "ChannelGroup", "format" : "guint32" } ], "response" : [ { "name" : "Status", "format" : "guint32" } ] }, // ************************************************************************ { "name" : "APDU", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "Channel", "format" : "guint32" }, { "name" : "SecureMessaging", "format" : "guint32", "public-format" : "MbimUiccSecureMessaging" }, { "name" : "ClassByteType", "format" : "guint32", "public-format" : "MbimUiccClassByteType" }, { "name" : "Command", "format" : "uicc-ref-byte-array" } ], "response" : [ { "name" : "Status", "format" : "guint32" }, { "name" : "Response", "format" : "uicc-ref-byte-array" } ] }, // ************************************************************************ { "name" : "MbimTerminalCapabilityInfo", "type" : "Struct", "since" : "1.26", "contents" : [ { "name" : "TerminalCapabilityData", "format" : "unsized-byte-array", "pad-array" : "FALSE" } ] }, { "name" : "Terminal Capability", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "TerminalCapabilityCount", "format" : "guint32" }, { "name" : "TerminalCapability", "format" : "ref-struct-array" , "struct-type" : "MbimTerminalCapabilityInfo", "array-size-field" : "TerminalCapabilityCount" } ], "query" : [], "response" : [ { "name" : "TerminalCapabilityCount", "format" : "guint32" }, { "name" : "TerminalCapability", "format" : "ref-struct-array" , "struct-type" : "MbimTerminalCapabilityInfo", "array-size-field" : "TerminalCapabilityCount" } ] }, // ********************************************************************************* { "name" : "Reset", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "PassThroughAction", "format" : "guint32", "public-format" : "MbimUiccPassThroughAction" } ], "query" : [], "response" : [ { "name" : "PassThroughStatus", "format" : "guint32", "public-format" : "MbimUiccPassThroughStatus" } ] }, // ********************************************************************************* { "name" : "MbimUiccApplication", "type" : "Struct", "since" : "1.28", "contents" : [ { "name" : "ApplicationType", "format" : "guint32", "public-format" : "MbimUiccApplicationType" }, { "name" : "ApplicationId", "format" : "ref-byte-array" }, { "name" : "ApplicationName", "format" : "string", "encoding" : "utf-8" }, { "name" : "PinKeyReferenceCount", "format" : "guint32" }, { "name" : "PinKeyReferences", "format" : "ref-byte-array" } ] }, { "name" : "Application List", "type" : "Command", "since" : "1.28", "query" : [], "response" : [ { "name" : "Version", "format" : "guint32" }, { "name" : "ApplicationCount", "format" : "guint32" }, { "name" : "ActiveApplicationIndex", "format" : "guint32" }, { "name" : "ApplicationListSizeBytes", "format" : "guint32" }, { "name" : "Applications", "format" : "ref-struct-array" , "struct-type" : "MbimUiccApplication", "array-size-field" : "ApplicationCount" } ] }, // ********************************************************************************* { "name" : "File Status", "type" : "Command", "since" : "1.28", "query" : [ { "name" : "Version", "format" : "guint32" }, { "name" : "ApplicationId", "format" : "ref-byte-array" }, { "name" : "FilePath", "format" : "ref-byte-array" } ], "response" : [ { "name" : "Version", "format" : "guint32" }, { "name" : "StatusWord1", "format" : "guint32" }, { "name" : "StatusWord2", "format" : "guint32" }, { "name" : "FileAccessibility", "format" : "guint32", "public-format" : "MbimUiccFileAccessibility" }, { "name" : "FileType", "format" : "guint32", "public-format" : "MbimUiccFileType" }, { "name" : "FileStructure", "format" : "guint32", "public-format" : "MbimUiccFileStructure" }, { "name" : "FileItemCount", "format" : "guint32" }, { "name" : "FileItemSize", "format" : "guint32" }, { "name" : "AccessConditionRead", "format" : "guint32", "public-format" : "MbimPinType" }, { "name" : "AccessConditionUpdate", "format" : "guint32", "public-format" : "MbimPinType" }, { "name" : "AccessConditionActivate", "format" : "guint32", "public-format" : "MbimPinType" }, { "name" : "AccessConditionDeactivate", "format" : "guint32", "public-format" : "MbimPinType" } ] }, // ********************************************************************************* { "name" : "Read Binary", "type" : "Command", "since" : "1.28", "query" : [ { "name" : "Version", "format" : "guint32" }, { "name" : "ApplicationId", "format" : "ref-byte-array" }, { "name" : "FilePath", "format" : "ref-byte-array" }, { "name" : "ReadOffset", "format" : "guint32" }, { "name" : "ReadSize", "format" : "guint32" }, { "name" : "LocalPin", "format" : "string" }, { "name" : "Data", "format" : "ref-byte-array" } ], "response" : [ { "name" : "Version", "format" : "guint32" }, { "name" : "StatusWord1", "format" : "guint32" }, { "name" : "StatusWord2", "format" : "guint32" }, { "name" : "Data", "format" : "ref-byte-array" } ] }, // ********************************************************************************* { "name" : "Read Record", "type" : "Command", "since" : "1.28", "query" : [ { "name" : "Version", "format" : "guint32" }, { "name" : "ApplicationId", "format" : "ref-byte-array" }, { "name" : "FilePath", "format" : "ref-byte-array" }, { "name" : "RecordNumber", "format" : "guint32" }, { "name" : "LocalPin", "format" : "string" }, { "name" : "Data", "format" : "ref-byte-array" } ], "response" : [ { "name" : "Version", "format" : "guint32" }, { "name" : "StatusWord1", "format" : "guint32" }, { "name" : "StatusWord2", "format" : "guint32" }, { "name" : "Data", "format" : "ref-byte-array" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ms-voice-extensions.json000066400000000000000000000047001453630424100240730ustar00rootroot00000000000000[ // ************************************************************************ { "type" : "Service", "name" : "MS Voice Extensions" }, // ************************************************************************ { "name" : "NITZ", "type" : "Command", "since" : "1.28", "query" : [ ], "response" : [ { "name" : "Year", "format" : "guint32" }, { "name" : "Month", "format" : "guint32" }, { "name" : "Day", "format" : "guint32" }, { "name" : "Hour", "format" : "guint32" }, { "name" : "Minute", "format" : "guint32" }, { "name" : "Second", "format" : "guint32" }, { "name" : "TimeZoneOffsetMinutes", "format" : "guint32" }, { "name" : "DaylightSavingTimeOffsetMinutes", "format" : "guint32" }, { "name" : "DataClass", "format" : "guint32", "public-format" : "MbimDataClass" } ], "notification" : [ { "name" : "Year", "format" : "guint32" }, { "name" : "Month", "format" : "guint32" }, { "name" : "Day", "format" : "guint32" }, { "name" : "Hour", "format" : "guint32" }, { "name" : "Minute", "format" : "guint32" }, { "name" : "Second", "format" : "guint32" }, { "name" : "TimeZoneOffsetMinutes", "format" : "guint32" }, { "name" : "DaylightSavingTimeOffsetMinutes", "format" : "guint32" }, { "name" : "DataClass", "format" : "guint32", "public-format" : "MbimDataClass" } ] } ] libmbim-1.31.2-dev/data/mbim-service-phonebook.json000066400000000000000000000076161453630424100221510ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "Phonebook" }, // ********************************************************************************* { "name" : "Configuration", "type" : "Command", "since" : "1.4", "query" : [], "response" : [ { "name" : "State", "format" : "guint32", "public-format" : "MbimPhonebookState" }, { "name" : "NumberOfEntries", "format" : "guint32" }, { "name" : "UsedEntries", "format" : "guint32" }, { "name" : "MaxNumberLength", "format" : "guint32" }, { "name" : "MaxName", "format" : "guint32" } ], "notification" : [ { "name" : "State", "format" : "guint32", "public-format" : "MbimPhonebookState" }, { "name" : "NumberOfEntries", "format" : "guint32" }, { "name" : "UsedEntries", "format" : "guint32" }, { "name" : "MaxNumberLength", "format" : "guint32" }, { "name" : "MaxName", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "MbimPhonebookEntry", "type" : "Struct", "since" : "1.4", "contents" : [ { "name" : "EntryIndex", "format" : "guint32" }, { "name" : "Number", "format" : "string", "personal-info" : "true" }, { "name" : "Name", "format" : "string", "personal-info" : "true" } ] }, { "name" : "Read", "type" : "Command", "since" : "1.4", "query" : [ { "name" : "FilterFlag", "format" : "guint32", "public-format" : "MbimPhonebookFlag" }, { "name" : "FilterMessageIndex", "format" : "guint32" } ], "response" : [ { "name" : "EntryCount", "format" : "guint32" }, { "name" : "Entries", "format" : "ref-struct-array", "struct-type" : "MbimPhonebookEntry", "array-size-field" : "EntryCount" } ] }, // ********************************************************************************* { "name" : "Delete", "type" : "Command", "since" : "1.4", "set" : [ { "name" : "FilterFlag", "format" : "guint32", "public-format" : "MbimPhonebookFlag" }, { "name" : "FilterMessageIndex", "format" : "guint32" } ], "response" : [] }, // ********************************************************************************* { "name" : "Write", "type" : "Command", "since" : "1.4", "set" : [ { "name" : "SaveFlag", "format" : "guint32", "public-format" : "MbimPhonebookWriteFlag" }, { "name" : "SaveIndex", "format" : "guint32" }, { "name" : "Number", "format" : "string", "personal-info" : "true" }, { "name" : "Name", "format" : "string", "personal-info" : "true" } ], "response" : [] } ] libmbim-1.31.2-dev/data/mbim-service-proxy-control.json000066400000000000000000000015361453630424100230170ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "Proxy Control" }, // ********************************************************************************* { "name" : "Configuration", "type" : "Command", "since" : "1.10", "set" : [ { "name" : "DevicePath", "format" : "string" }, { "name" : "Timeout", "format" : "guint32" } ], "response" : [] }, // ********************************************************************************* { "name" : "Version", "type" : "Command", "since" : "1.28", "notification" : [ { "name" : "MbimVersion", "format" : "guint16" }, { "name" : "MbimExtendedVersion", "format" : "guint16" } ] } ] libmbim-1.31.2-dev/data/mbim-service-qdu.json000066400000000000000000000071221453630424100207460ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "QDU" }, // ********************************************************************************* { "name" : "Update Session", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "SessionAction", "format" : "guint32", "public-format" : "MbimQduSessionAction" }, { "name" : "SessionType", "format" : "guint32", "public-format" : "MbimQduSessionType" } ], "query" : [], "response" : [ { "name" : "CurrentSessionType", "format" : "guint32", "public-format" : "MbimQduSessionType" }, { "name" : "CurrentSessionStatus", "format" : "guint32", "public-format" : "MbimQduSessionStatus" }, { "name" : "LastSessionType", "format" : "guint32", "public-format" : "MbimQduSessionType" }, { "name" : "LastSessionResult", "format" : "guint32", "public-format" : "MbimQduSessionResult" }, { "name" : "LastSessionErrorOffset", "format" : "guint32" }, { "name" : "LastSessionErrorSize", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "File Open", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "FileType", "format" : "guint32", "public-format" : "MbimQduFileType" }, { "name" : "FileSize", "format" : "guint32" } ], "query" : [], "response" : [ { "name" : "MaxTransferSize", "format" : "guint32" }, { "name" : "MaxWindowSize", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "File Write", "type" : "Command", "since" : "1.26", "set" : [ { "name" : "DataBuffer", "format" : "unsized-byte-array", "pad-array" : "FALSE" } ], "response" : []}, // ********************************************************************************* { "name" : "Quectel Reboot", "type" : "Command", "since" : "1.28", "set" : [ { "name" : "RebootType", "format" : "guint16", "public-format" : "MbimQduQuectelRebootType" } ], "response" : []}, // ********************************************************************************* { "name" : "Quectel Read Version", "type" : "Command", "since" : "1.28", "set" : [ { "name" : "VersionType", "format" : "guint16", "public-format" : "MbimQduQuectelVersionType" } ], "response" : [ { "name" : "VersionId", "format" : "guint32" }, { "name" : "Version", "format" : "string", "max-size" : "120" } ] } ] libmbim-1.31.2-dev/data/mbim-service-qmi.json000066400000000000000000000016221453630424100207420ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "QMI" }, // ********************************************************************************* { "name" : "msg", "type" : "Command", "since-ex" : { "set" : "1.14", "response" : "1.14", "notification" : "1.18" }, "set" : [ { "name" : "QmiMsg", "format" : "unsized-byte-array", "pad-array" : "FALSE" } ], "response" : [ { "name" : "QMUX", "format" : "unsized-byte-array", "pad-array" : "FALSE" } ], "notification" : [ { "name" : "QMUX", "format" : "unsized-byte-array", "pad-array" : "FALSE" } ]} ] libmbim-1.31.2-dev/data/mbim-service-quectel.json000066400000000000000000000013351453630424100216170ustar00rootroot00000000000000[ // ********************************************************************************* { "type" : "Service", "name" : "Quectel" }, // ********************************************************************************* { "name" : "Radio State", "type" : "Command", "since" : "1.26.2", "set" : [ { "name" : "RadioState", "format" : "guint32", "public-format" : "MbimQuectelRadioSwitchState" } ], "query" : [], "response" : [ { "name" : "RadioState", "format" : "guint32", "public-format" : "MbimQuectelRadioSwitchState" } ] } ] libmbim-1.31.2-dev/data/mbim-service-sms.json000066400000000000000000000224241453630424100207610ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "SMS" }, // ********************************************************************************* { "name" : "Configuration", "type" : "Command", "since" : "1.4", "set" : [ { "name" : "Format", "format" : "guint32", "public-format" : "MbimSmsFormat" }, { "name" : "ScAddress", "format" : "string" } ], "query" : [], "response" : [ { "name" : "SmsStorageState", "format" : "guint32", "public-format" : "MbimSmsStorageState" }, { "name" : "Format", "format" : "guint32", "public-format" : "MbimSmsFormat" }, { "name" : "MaxMessages", "format" : "guint32" }, { "name" : "CdmaShortMessageSize", "format" : "guint32" }, { "name" : "ScAddress", "format" : "string" } ] }, // ********************************************************************************* { "name" : "MbimSmsPduReadRecord", "type" : "Struct", "since" : "1.4", "contents" : [ { "name" : "MessageIndex", "format" : "guint32" }, { "name" : "MessageStatus", "format" : "guint32", "public-format" : "MbimSmsStatus" }, { "name" : "PduData", "format" : "ref-byte-array", "personal-info" : "true" } ] }, { "name" : "MbimSmsCdmaReadRecord", "type" : "Struct", "since" : "1.4", "contents" : [ { "name" : "MessageIndex", "format" : "guint32" }, { "name" : "MessageStatus", "format" : "guint32", "public-format" : "MbimSmsStatus" }, { "name" : "Address", "format" : "string", "personal-info" : "true" }, { "name" : "Timestamp", "format" : "string" }, { "name" : "Encoding", "format" : "guint32", "public-format" : "MbimSmsCdmaEncoding" }, { "name" : "Language", "format" : "guint32", "public-format" : "MbimSmsCdmaLang" }, { "name" : "EncodedMessage", "format" : "ref-byte-array", "personal-info" : "true" }, { "name" : "EncodedMessageSizeInCharacters", "format" : "guint32" } ] }, { "name" : "Read", "type" : "Command", "since" : "1.4", "query" : [ { "name" : "Format", "format" : "guint32", "public-format" : "MbimSmsFormat" }, { "name" : "Flag", "format" : "guint32", "public-format" : "MbimSmsFlag" }, { "name" : "MessageIndex", "format" : "guint32" } ], "response" : [ { "name" : "Format", "format" : "guint32", "public-format" : "MbimSmsFormat" }, { "name" : "MessagesCount", "format" : "guint32" }, { "name" : "PduMessages", "format" : "ref-struct-array" , "struct-type" : "MbimSmsPduReadRecord", "array-size-field" : "MessagesCount", "available-if" : { "field" : "Format", "operation" : "==", "value" : "MBIM_SMS_FORMAT_PDU" } }, { "name" : "CdmaMessages", "format" : "ref-struct-array" , "struct-type" : "MbimSmsCdmaReadRecord", "array-size-field" : "MessagesCount", "available-if" : { "field" : "Format", "operation" : "==", "value" : "MBIM_SMS_FORMAT_CDMA" } } ], "notification" : [ { "name" : "Format", "format" : "guint32", "public-format" : "MbimSmsFormat" }, { "name" : "MessagesCount", "format" : "guint32" }, { "name" : "PduMessages", "format" : "ref-struct-array" , "struct-type" : "MbimSmsPduReadRecord", "array-size-field" : "MessagesCount", "available-if" : { "field" : "Format", "operation" : "==", "value" : "MBIM_SMS_FORMAT_PDU" } }, { "name" : "CdmaMessages", "format" : "ref-struct-array" , "struct-type" : "MbimSmsCdmaReadRecord", "array-size-field" : "MessagesCount", "available-if" : { "field" : "Format", "operation" : "==", "value" : "MBIM_SMS_FORMAT_CDMA" } } ] }, // ********************************************************************************* { "name" : "MbimSmsPduSendRecord", "type" : "Struct", "since" : "1.4", "contents" : [ { "name" : "PduData", "format" : "ref-byte-array", "personal-info" : "true" } ] }, { "name" : "MbimSmsCdmaSendRecord", "type" : "Struct", "since" : "1.4", "contents" : [ { "name" : "Encoding", "format" : "guint32", "public-format" : "MbimSmsCdmaEncoding" }, { "name" : "Language", "format" : "guint32", "public-format" : "MbimSmsCdmaLang" }, { "name" : "Address", "format" : "string", "personal-info" : "true" }, { "name" : "EncodedMessage", "format" : "ref-byte-array", "personal-info" : "true" }, { "name" : "EncodedMessageSizeInCharacters", "format" : "guint32" } ] }, { "name" : "Send", "type" : "Command", "since" : "1.4", "set" : [ { "name" : "Format", "format" : "guint32", "public-format" : "MbimSmsFormat" }, { "name" : "PduMessage", "format" : "struct", "struct-type" : "MbimSmsPduSendRecord", "available-if" : { "field" : "Format", "operation" : "==", "value" : "MBIM_SMS_FORMAT_PDU" } }, { "name" : "CdmaMessage", "format" : "struct", "struct-type" : "MbimSmsCdmaSendRecord", "available-if" : { "field" : "Format", "operation" : "==", "value" : "MBIM_SMS_FORMAT_CDMA" } } ], "response" : [ { "name" : "MessageReference", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "Delete", "type" : "Command", "since" : "1.4", "set" : [ { "name" : "Flag", "format" : "guint32", "public-format" : "MbimSmsFlag" }, { "name" : "MessageIndex", "format" : "guint32" } ], "response" : [] }, // ********************************************************************************* { "name" : "Message Store Status", "type" : "Command", "since" : "1.4", "query" : [], "response" : [ { "name" : "Flag", "format" : "guint32", "public-format" : "MbimSmsStatusFlag" }, { "name" : "MessageIndex", "format" : "guint32" } ], "notification" : [ { "name" : "Flag", "format" : "guint32", "public-format" : "MbimSmsStatusFlag" }, { "name" : "MessageIndex", "format" : "guint32" } ] } ] libmbim-1.31.2-dev/data/mbim-service-stk.json000066400000000000000000000036211453630424100207560ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "STK" }, // ********************************************************************************* { "name" : "Pac", "type" : "Command", "since" : "1.4", "query" : [], "set" : [ { "name" : "PacHostControl", "format" : "byte-array", "array-size" : "32" } ], "response" : [ { "name" : "PacSupport", "format" : "byte-array", "array-size" : "256" } ], "notification" : [ { "name" : "PacType", "format" : "guint32", "public-format" : "MbimStkPacType" }, { "name" : "DataBuffer", "format" : "unsized-byte-array" } ] }, // ********************************************************************************* { "name" : "Terminal Response", "type" : "Command", "since" : "1.4", "set" : [ { "name" : "Response", "format" : "ref-byte-array-no-offset" } ], "response" : [ { "name" : "ResultData", "format" : "ref-byte-array" }, { "name" : "StatusWords", "format" : "guint32" } ] }, // ********************************************************************************* { "name" : "Envelope", "type" : "Command", "since" : "1.4", "query" : [], "set" : [ { "name" : "Data", "format" : "unsized-byte-array" } ], // This response is only for the 'query', the 'set' one is empty... "response" : [ { "name" : "EnvelopeSupport", "format" : "byte-array", "array-size" : "32" } ] } ] libmbim-1.31.2-dev/data/mbim-service-ussd.json000066400000000000000000000034411453630424100211330ustar00rootroot00000000000000 [ // ********************************************************************************* { "type" : "Service", "name" : "USSD" }, // ********************************************************************************* { "name" : "", "type" : "Command", "since" : "1.4", "set" : [ { "name" : "Action", "format" : "guint32", "public-format" : "MbimUssdAction" }, { "name" : "DataCodingScheme", "format" : "guint32" }, { "name" : "Payload", "format" : "ref-byte-array" } ], "response" : [ { "name" : "Response", "format" : "guint32", "public-format" : "MbimUssdResponse" }, { "name" : "SessionState", "format" : "guint32", "public-format" : "MbimUssdSessionState" }, { "name" : "DataCodingScheme", "format" : "guint32" }, { "name" : "Payload", "format" : "ref-byte-array" } ], "notification" : [ { "name" : "Response", "format" : "guint32", "public-format" : "MbimUssdResponse" }, { "name" : "SessionState", "format" : "guint32", "public-format" : "MbimUssdSessionState" }, { "name" : "DataCodingScheme", "format" : "guint32" }, { "name" : "Payload", "format" : "ref-byte-array" } ] } ] libmbim-1.31.2-dev/docs/000077500000000000000000000000001453630424100147175ustar00rootroot00000000000000libmbim-1.31.2-dev/docs/libmbim-icon.svg000066400000000000000000000145521453630424100200100ustar00rootroot00000000000000 image/svg+xml libmbim-1.31.2-dev/docs/libmbim-logo.png000066400000000000000000000136361453630424100200070ustar00rootroot00000000000000PNG  IHDRbKGD pHYs  tIME iTXtCommentCreated with GIMPd.eIDATx{xTǿ90L2p)Iȕ`a+j(VEeeyV]ieպXB(kBL$ 33œ93$y<{/# F HhAB#F$4L"WSpP+- } S.#kHhu$ Iab3S(' K[Y Ҹt* b;-4:F xx"\ <~/ @"D3j$0 P3j$WձV bB M \ \ (>S9# ր&j 11 /{pQyo@ ?؇`kjF 3dU2,8=ZK-fEw|O3Ё@T f*+XMh6 qi1`]8k@*i4Y=(b|73p$X8  }?˰00Wf/Ao}^qx|bF̕X3{E/NyP)Z!Hh\t6لˮ  0pmꄆj Y5 341쫳Oȇ5|, P9$Fn΀s 8qnj2,t3$8fKӡcuO];I"q[|̆UeZJB. "(Ҡ m(Mk)C>k fΌ2\q P=)BG-xg\:I o/o^aѠL;F(U>@pj*hkFA]g9el6hD.OMŭ)5̨ŚTc@ijg1GSK6$$'z$[ ]&XITf *'+g`':=hu݊wgm0_ݎ7Œ)͌o6GW Tτ/-v3Ès1p> ՌQ_oocpjL b# 伄z{ pO L]yQSrWIA83J5d<ʜW~ݏ_>_386jAU)UMŽY+`ID^)H6TǙk_!0eby]x&i,Xknk@>&0 (C%ѳ췡?O3 )D%2O=U+öV.QMY=fk B"D{M&D+W`fm)@ =tF4%΂,>;[t[OAB>u!=S3뱣q'/90p띁D蚏 [L  KȻ ^Φ]eXVH ?m570'Z</l eLԚ5âMD) ``~#z ^KɐC#ɟul3AIJF٬1M}Ւ^ͮ Q&eX 2x:CTh8Ƶs]`%ㆌ9!m,A(ފ3s|r2;g-OEtJl@2,ߘsU}=8,䇦XS g!u&CxX{ @ ߍ&G/uaȺ|d̲h2$Ѫ4XS X dջoR ydXE֢D g z Ihピ)VcェºRq 7zCG&F`7 m|qw7bHX-'}.EqY $eHC{=AB2w0|]qsKB DԪYT~gIGB>p=Ʃ*YOI- `VmL2L_bK,\vN;pњ]?'} ׯ^hx JrJqlHVr)8d ~j~z72 ] snGNٲ1N!aLP6lz=';p RK~ӟS .60(I) pQQ\Du/u$Ѣ9E#--=x僗Pi6ީܫ,Oؐ!7P <0p+ 9 ńjۙko[Va?+i&ϸM6.7J&x{ <%TdQ6ls~V<_Ttߗ< kqEٺ7")!t-슗f/eHh$K KlOm_/‹ڔ2DY4Sfңխ|ۋ >OBf#?ʮfQSۋ܅0hoqy]X1̬ ;vZ;<hÄ޿iT9 !ApM ')|$ljxĻX9!5?,JyuzUΩ E@ÄAȏh#M>12,*n2:*lSlދUnu_)hܐ$0 ;E?; gYOlst(J_+yXΉ -fjʆ\{,lFy%]]E ʺR.i_ -.Ъxpj~ҔFf2B),ТHhqÜisdzOkj'@hДAs GNyHhKYDZ'eSL K+w9^x6Jm %&Њno֭ݴiYftβoBL7Z,o|m<57iSǑwV>݆[ nC lcY^| maoBEYWh%榕^fHoFQw9,ο:{N٫{TP!4DT7,ǩ_Ty7HI/)S?E)S{wGjn;x\$njx Ê#I7|ǥ.AA]G HhA]LjٱcЅഴ4*M*Z(--R2#A$4  -NGEc֭Xbˑ Z ł<V^]v!ޘx`ƍ@nn.t:QVV{}~ n<ψ#F7ZRXX(۲e{7n8d8ץjR~il6+zOqqxĉ>}Z|GENRQtÕAO4΄`oDqLEg4ŷzK!7$%%E[-yV+9r$ltÕAX hC`۱f {oOOOxgpرwXv-v2MĘ{l6m6i?IcTl6l2,]HIIFAOON<={`Ϟ=cdL:up2r-(,,DFFT*N<-[UѷX%%%ͅ^GUUlقfio&y10c#bѾ Ǐ'xbw^Z񷵵ٲ/]Tܽ{x$O.f+xIWk`H 6`ժUHH&cZyfO81xŐ<쳒a`VsXV:ۛ>|rT=~%ݮNxZ yq.7- RSSf3t?$ɰaǟ$ XUNxZ )//1Lya=p8E'BbتIodZ:)Hh1lwG'Hh`_mH'Hh@nHBR Z,.7L'ƭjK-\pRt's'ДĚzKv*xѢERLO:uvv;dx]w5+dOTc}ry=XlC=$kL ᶮ֭C]]^/.\K/aҥxvU~شiJJJpi5 ۂkbidöoߎ۷=j}n0j۫[Ҷmې7 {ҷhcw8TT6l؀GydBdOڢEPQQ1bgeeEܫTxW_jSIhaܹsDOHMME]]^|EL&Epkע=ظ.ɞx#ֻ8^lsT3f&_ݻQSSnhZXV̙3aZ.ܹDUU:::daXx]鏖sj؅k0Sh1QF1YhAB#F$4 HhAB#A$4  A  HhAFD :[줜$&,=B^ : HhA :E|r)P1Au$A  AF HhAb_L\GX>IENDB`libmbim-1.31.2-dev/docs/libmbim-logo.svg000066400000000000000000000167331453630424100200230ustar00rootroot00000000000000 image/svg+xml libmbim libmbim-1.31.2-dev/docs/man/000077500000000000000000000000001453630424100154725ustar00rootroot00000000000000libmbim-1.31.2-dev/docs/man/meson.build000066400000000000000000000011431453630424100176330ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez help2man = find_program('help2man') mans = [ ['mbimcli', [help2man, '--output=@OUTPUT@', '--name=Control MBIM devices', '--help-option="--help-all"', mbimcli], [mbimcli_sources]], ['mbim-network', [help2man, '--output=@OUTPUT@', '--name=Simple network management of MBIM devices', mbim_network], []], ] foreach man: mans custom_target( man[0], output: man[0] + '.1', command: man[1], depend_files: man[2], install: true, install_dir: mbim_mandir / 'man1', ) endforeach libmbim-1.31.2-dev/docs/reference/000077500000000000000000000000001453630424100166555ustar00rootroot00000000000000libmbim-1.31.2-dev/docs/reference/libmbim-glib/000077500000000000000000000000001453630424100212035ustar00rootroot00000000000000libmbim-1.31.2-dev/docs/reference/libmbim-glib/libmbim-glib-common.sections000066400000000000000000000547051453630424100266030ustar00rootroot00000000000000
mbim-version Version checks MBIM_MAJOR_VERSION MBIM_MINOR_VERSION MBIM_MICRO_VERSION MBIM_CHECK_VERSION
mbim-uuid MbimService MbimContextType MbimUuid MBIM_UUID_INVALID MBIM_UUID_ATDS MBIM_UUID_BASIC_CONNECT MBIM_UUID_SMS MBIM_UUID_USSD MBIM_UUID_PHONEBOOK MBIM_UUID_STK MBIM_UUID_AUTH MBIM_UUID_DSS MBIM_UUID_MS_FIRMWARE_ID MBIM_UUID_MS_HOST_SHUTDOWN MBIM_UUID_PROXY_CONTROL MBIM_UUID_QMI MBIM_UUID_QDU MBIM_UUID_INTEL_FIRMWARE_UPDATE MBIM_UUID_MS_BASIC_CONNECT_EXTENSIONS MBIM_UUID_MS_SAR MBIM_UUID_MS_UICC_LOW_LEVEL_ACCESS MBIM_UUID_QUECTEL MBIM_UUID_INTEL_THERMAL_RF MBIM_UUID_MS_VOICE_EXTENSIONS MBIM_UUID_INTEL_MUTUAL_AUTHENTICATION MBIM_UUID_INTEL_TOOLS MBIM_UUID_GOOGLE MBIM_UUID_FIBOCOM mbim_service_get_string mbim_service_lookup_name mbim_register_custom_service mbim_unregister_custom_service mbim_service_id_is_custom mbim_context_type_get_string mbim_uuid_cmp mbim_uuid_from_printable mbim_uuid_get_printable mbim_uuid_from_service mbim_uuid_to_service mbim_uuid_from_context_type mbim_uuid_to_context_type MBIM_PACKED mbim_service_build_string_from_mask mbim_context_type_build_string_from_mask
mbim-cid MbimCidAtds MbimCidBasicConnect MbimCidSms MbimCidUssd MbimCidPhonebook MbimCidStk MbimCidAuth MbimCidDss MbimCidMsFirmwareId MbimCidMsHostShutdown MbimCidProxyControl MbimCidQmi MbimCidQdu MbimCidIntelFirmwareUpdate MbimCidMsBasicConnectExtensions MbimCidMsSar MbimCidMsUiccLowLevelAccess MbimCidQuectel MbimCidIntelThermalRf MbimCidMsVoiceExtensions MbimCidIntelMutualAuthentication MbimCidIntelTools MbimCidGoogle MbimCidFibocom mbim_cid_can_set mbim_cid_can_query mbim_cid_can_notify mbim_cid_get_printable mbim_cid_atds_get_string mbim_cid_basic_connect_get_string mbim_cid_sms_get_string mbim_cid_ussd_get_string mbim_cid_phonebook_get_string mbim_cid_stk_get_string mbim_cid_auth_get_string mbim_cid_dss_get_string mbim_cid_ms_firmware_id_get_string mbim_cid_ms_host_shutdown_get_string mbim_cid_proxy_control_get_string mbim_cid_qmi_get_string mbim_cid_qdu_get_string mbim_cid_intel_firmware_update_get_string mbim_cid_ms_basic_connect_extensions_get_string mbim_cid_ms_sar_get_string mbim_cid_ms_uicc_low_level_access_get_string mbim_cid_quectel_get_string mbim_cid_intel_thermal_rf_get_string mbim_cid_ms_voice_extensions_get_string mbim_cid_intel_mutual_authentication_get_string mbim_cid_intel_tools_get_string mbim_cid_google_get_string mbim_cid_fibocom_get_string mbim_cid_atds_build_string_from_mask mbim_cid_basic_connect_build_string_from_mask mbim_cid_sms_build_string_from_mask mbim_cid_ussd_build_string_from_mask mbim_cid_phonebook_build_string_from_mask mbim_cid_stk_build_string_from_mask mbim_cid_auth_build_string_from_mask mbim_cid_dss_build_string_from_mask mbim_cid_ms_firmware_id_build_string_from_mask mbim_cid_ms_host_shutdown_build_string_from_mask mbim_cid_proxy_control_build_string_from_mask mbim_cid_qmi_build_string_from_mask mbim_cid_qdu_build_string_from_mask mbim_cid_intel_firmware_update_build_string_from_mask mbim_cid_ms_basic_connect_extensions_build_string_from_mask mbim_cid_ms_sar_build_string_from_mask mbim_cid_ms_uicc_low_level_access_build_string_from_mask mbim_cid_quectel_build_string_from_mask mbim_cid_intel_thermal_rf_build_string_from_mask mbim_cid_ms_voice_extensions_build_string_from_mask mbim_cid_intel_mutual_authentication_build_string_from_mask mbim_cid_intel_tools_build_string_from_mask mbim_cid_google_build_string_from_mask mbim_cid_fibocom_build_string_from_mask MBIM_TYPE_CID_ATDS MBIM_TYPE_CID_AUTH MBIM_TYPE_CID_BASIC_CONNECT MBIM_TYPE_CID_DSS MBIM_TYPE_CID_PHONEBOOK MBIM_TYPE_CID_SMS MBIM_TYPE_CID_STK MBIM_TYPE_CID_USSD MBIM_TYPE_CID_MS_FIRMWARE_ID MBIM_TYPE_CID_MS_HOST_SHUTDOWN MBIM_TYPE_CID_PROXY_CONTROL MBIM_TYPE_CID_QMI MBIM_TYPE_CID_QDU MBIM_TYPE_CID_INTEL_FIRMWARE_UPDATE MBIM_TYPE_CID_MS_BASIC_CONNECT_EXTENSIONS MBIM_TYPE_CID_MS_SAR MBIM_TYPE_CID_MS_UICC_LOW_LEVEL_ACCESS MBIM_TYPE_CID_QUECTEL MBIM_TYPE_CID_INTEL_THERMAL_RF MBIM_TYPE_CID_MS_VOICE_EXTENSIONS MBIM_TYPE_CID_INTEL_MUTUAL_AUTHENTICATION MBIM_TYPE_CID_INTEL_TOOLS MBIM_TYPE_CID_GOOGLE MBIM_TYPE_CID_FIBOCOM mbim_cid_atds_get_type mbim_cid_auth_get_type mbim_cid_basic_connect_get_type mbim_cid_dss_get_type mbim_cid_phonebook_get_type mbim_cid_sms_get_type mbim_cid_stk_get_type mbim_cid_ussd_get_type mbim_cid_ms_firmware_id_get_type mbim_cid_ms_host_shutdown_get_type mbim_cid_proxy_control_get_type mbim_cid_qmi_get_type mbim_cid_qdu_get_type mbim_cid_intel_firmware_update_get_type mbim_cid_ms_basic_connect_extensions_get_type mbim_cid_ms_uicc_low_level_access_get_type mbim_cid_ms_sar_get_type mbim_cid_quectel_get_type mbim_cid_intel_thermal_rf_get_type mbim_cid_ms_voice_extensions_get_type mbim_cid_intel_mutual_authentication_get_type mbim_cid_intel_tools_get_type mbim_cid_google_get_type mbim_cid_fibocom_get_type
mbim-message MbimMessage MbimMessageType MbimIPv4 MbimIPv6 MbimMessageCommandType mbim_message_new mbim_message_dup mbim_message_ref mbim_message_unref mbim_message_validate mbim_message_get_printable mbim_message_get_printable_full mbim_message_get_raw mbim_message_get_message_type mbim_message_get_message_length mbim_message_get_transaction_id mbim_message_set_transaction_id mbim_message_type_get_string mbim_message_open_new mbim_message_open_get_max_control_transfer mbim_message_open_done_get_status_code mbim_message_open_done_get_result mbim_message_close_new mbim_message_close_done_get_status_code mbim_message_close_done_get_result mbim_message_error_new mbim_message_function_error_new mbim_message_error_get_error_status_code mbim_message_error_get_error mbim_message_command_new mbim_message_command_append mbim_message_command_get_service mbim_message_command_get_service_id mbim_message_command_get_cid mbim_message_command_get_command_type mbim_message_command_get_raw_information_buffer mbim_message_command_type_get_string mbim_message_command_done_get_service mbim_message_command_done_get_service_id mbim_message_command_done_get_cid mbim_message_command_done_get_status_code mbim_message_command_done_get_result mbim_message_command_done_get_raw_information_buffer mbim_message_indicate_status_get_service mbim_message_indicate_status_get_service_id mbim_message_indicate_status_get_cid mbim_message_indicate_status_get_raw_information_buffer mbim_message_response_get_result mbim_message_open_done_new mbim_message_close_done_new mbim_message_proxy_control_configuration_response_parse mbim_message_proxy_control_configuration_set_new mbim_message_proxy_control_version_notification_parse mbim_message_type_build_string_from_mask mbim_message_command_type_build_string_from_mask MBIM_TYPE_MESSAGE mbim_message_get_type
mbim-device MbimDevice MBIM_DEVICE_FILE MBIM_DEVICE_IN_SESSION MBIM_DEVICE_TRANSACTION_ID MBIM_DEVICE_CONSECUTIVE_TIMEOUTS MBIM_DEVICE_SIGNAL_REMOVED MBIM_DEVICE_SIGNAL_INDICATE_STATUS MBIM_DEVICE_SIGNAL_ERROR MbimDevice mbim_device_new mbim_device_new_finish mbim_device_get_file mbim_device_peek_file mbim_device_get_path mbim_device_get_path_display mbim_device_is_open mbim_device_get_ms_mbimex_version mbim_device_set_ms_mbimex_version mbim_device_check_ms_mbimex_version mbim_device_get_consecutive_timeouts mbim_device_open mbim_device_open_finish MbimDeviceOpenFlags mbim_device_open_full mbim_device_open_full_finish mbim_device_close mbim_device_close_finish mbim_device_close_force mbim_device_get_transaction_id mbim_device_get_next_transaction_id mbim_device_command mbim_device_command_finish MBIM_DEVICE_SESSION_ID_AUTOMATIC MBIM_DEVICE_SESSION_ID_MIN MBIM_DEVICE_SESSION_ID_MAX mbim_device_check_link_supported mbim_device_list_links mbim_device_add_link mbim_device_add_link_finish mbim_device_delete_link mbim_device_delete_link_finish mbim_device_delete_all_links mbim_device_delete_all_links_finish MbimDeviceClass MBIM_DEVICE MBIM_DEVICE_CLASS MBIM_DEVICE_GET_CLASS MBIM_IS_DEVICE MBIM_IS_DEVICE_CLASS MBIM_TYPE_DEVICE MbimDevicePrivate mbim_device_get_type
mbim-proxy MbimProxy MBIM_PROXY_SOCKET_PATH MBIM_PROXY_N_CLIENTS MBIM_PROXY_N_DEVICES MbimProxy mbim_proxy_new mbim_proxy_get_n_clients mbim_proxy_get_n_devices MbimProxyClass MBIM_PROXY MBIM_PROXY_CLASS MBIM_PROXY_GET_CLASS MBIM_IS_PROXY MBIM_IS_PROXY_CLASS MBIM_TYPE_PROXY MbimProxyPrivate mbim_proxy_get_type
mbim-enums MbimAtdsProviderPlmnMode MbimAtdsRatMode MbimDeviceType MbimCellularClass MbimVoiceClass MbimSimClass MbimDataClass MbimSmsCaps MbimCtrlCaps MbimSubscriberReadyState MbimReadyInfoFlag MbimRadioSwitchState MbimPinType MbimPinState MbimPinOperation MbimPinMode MbimPinFormat MbimProviderState MbimVisibleProvidersAction MbimNwError MbimRegisterAction MbimRegisterState MbimRegisterMode MbimRegistrationFlag MbimPacketServiceAction MbimPacketServiceState MbimActivationCommand MbimCompression MbimAuthProtocol MbimContextIpType MbimActivationState MbimVoiceCallState MbimIPConfigurationAvailableFlag MbimSmsStorageState MbimSmsFormat MbimSmsFlag MbimSmsCdmaLang MbimSmsCdmaEncoding MbimSmsStatus MbimSmsStatusFlag MbimUssdAction MbimUssdResponse MbimUssdSessionState MbimPhonebookFlag MbimPhonebookState MbimPhonebookWriteFlag MbimStkPacProfile MbimStkPacType MbimNetworkIdleHintState MbimEmergencyModeState MbimDssLinkState MbimQduFileType MbimQduSessionAction MbimQduSessionType MbimQduSessionStatus MbimQduSessionResult MbimQduQuectelRebootType MbimQduQuectelVersionType MbimPcoType MbimContextSource MbimLteAttachContextOperation MbimLteAttachContextRoamingControl MbimLteAttachState MbimSarBackoffState MbimSarControlMode MbimSarWifiHardwareState MbimTransmissionNotificationStatus MbimTransmissionState MbimUiccSlotState MbimUiccSecureMessaging MbimUiccClassByteType MbimUiccPassThroughAction MbimUiccPassThroughStatus MbimFrequencyRange MbimContextRoamingControl MbimContextMediaType MbimContextState MbimContextOperation MbimMicoMode MbimDefaultPduActivationHint MbimLadnInfo MbimDrxCycle MbimSubscriberReadyStatusFlag MbimDataClassV3 MbimDataSubclass MbimModemConfigurationStatus MbimWakeType MbimQuectelRadioSwitchState MbimAccessMediaType MbimIntelServingCellInfo MbimIntelBootMode MbimUiccApplicationType MbimUiccFileAccessibility MbimUiccFileType MbimUiccFileStructure MbimTraceCommand MbimCarrierLockStatus MbimCarrierLockModemState MbimCarrierLockCause mbim_device_type_get_string mbim_cellular_class_build_string_from_mask mbim_voice_class_get_string mbim_sim_class_build_string_from_mask mbim_data_class_build_string_from_mask mbim_sms_caps_build_string_from_mask mbim_ctrl_caps_build_string_from_mask mbim_subscriber_ready_state_get_string mbim_ready_info_flag_build_string_from_mask mbim_radio_switch_state_get_string mbim_pin_type_get_string mbim_pin_state_get_string mbim_pin_operation_get_string mbim_pin_mode_get_string mbim_pin_format_get_string mbim_provider_state_build_string_from_mask mbim_visible_providers_action_get_string mbim_nw_error_get_string mbim_register_action_get_string mbim_register_state_get_string mbim_register_mode_get_string mbim_registration_flag_build_string_from_mask mbim_packet_service_action_get_string mbim_packet_service_state_get_string mbim_activation_command_get_string mbim_compression_get_string mbim_auth_protocol_get_string mbim_context_ip_type_get_string mbim_activation_state_get_string mbim_voice_call_state_get_string mbim_ip_configuration_available_flag_build_string_from_mask mbim_sms_storage_state_get_string mbim_sms_format_get_string mbim_sms_flag_get_string mbim_sms_cdma_lang_get_string mbim_sms_cdma_encoding_get_string mbim_sms_status_get_string mbim_sms_status_flag_build_string_from_mask mbim_ussd_action_get_string mbim_ussd_response_get_string mbim_ussd_session_state_get_string mbim_phonebook_flag_get_string mbim_phonebook_state_get_string mbim_phonebook_write_flag_get_string mbim_stk_pac_profile_get_string mbim_stk_pac_type_get_string mbim_network_idle_hint_state_get_string mbim_emergency_mode_state_get_string mbim_dss_link_state_get_string mbim_atds_provider_plmn_mode_get_string mbim_atds_rat_mode_get_string mbim_pco_type_get_string mbim_context_source_get_string mbim_lte_attach_context_operation_get_string mbim_lte_attach_context_roaming_control_get_string mbim_lte_attach_state_get_string mbim_sar_backoff_state_get_string mbim_sar_control_mode_get_string mbim_sar_wifi_hardware_state_get_string mbim_transmission_notification_status_get_string mbim_transmission_state_get_string mbim_qdu_file_type_get_string mbim_qdu_session_action_get_string mbim_qdu_session_result_get_string mbim_qdu_session_status_get_string mbim_qdu_session_type_get_string mbim_qdu_quectel_reboot_type_get_string mbim_qdu_quectel_version_type_get_string mbim_uicc_slot_state_get_string mbim_uicc_secure_messaging_get_string mbim_uicc_class_byte_type_get_string mbim_uicc_pass_through_action_get_string mbim_uicc_pass_through_status_get_string mbim_frequency_range_build_string_from_mask mbim_context_roaming_control_get_string mbim_context_media_type_get_string mbim_context_state_get_string mbim_context_operation_get_string mbim_mico_mode_get_string mbim_default_pdu_activation_hint_get_string mbim_ladn_info_get_string mbim_drx_cycle_get_string mbim_subscriber_ready_status_flag_build_string_from_mask mbim_data_class_v3_build_string_from_mask mbim_data_subclass_build_string_from_mask mbim_modem_configuration_status_get_string mbim_wake_type_get_string mbim_quectel_radio_switch_state_get_string mbim_access_media_type_get_string mbim_intel_serving_cell_info_get_string mbim_intel_boot_mode_get_string mbim_uicc_application_type_get_string mbim_uicc_file_accessibility_get_string mbim_uicc_file_type_get_string mbim_uicc_file_structure_get_string mbim_trace_command_get_string mbim_carrier_lock_status_get_string mbim_carrier_lock_modem_state_get_string mbim_carrier_lock_cause_get_string MBIM_TYPE_ACTIVATION_COMMAND MBIM_TYPE_ACTIVATION_STATE MBIM_TYPE_ATDS_PROVIDER_PLMN_MODE MBIM_TYPE_ATDS_RAT_MODE MBIM_TYPE_AUTH_PROTOCOL MBIM_TYPE_CELLULAR_CLASS MBIM_TYPE_COMPRESSION MBIM_TYPE_CONTEXT_IP_TYPE MBIM_TYPE_CONTEXT_TYPE MBIM_TYPE_CTRL_CAPS MBIM_TYPE_DATA_CLASS MBIM_TYPE_DEVICE_TYPE MBIM_TYPE_IP_CONFIGURATION_AVAILABLE_FLAG MBIM_TYPE_MESSAGE_COMMAND_TYPE MBIM_TYPE_MESSAGE_TYPE MBIM_TYPE_NW_ERROR MBIM_TYPE_PACKET_SERVICE_ACTION MBIM_TYPE_PACKET_SERVICE_STATE MBIM_TYPE_PIN_FORMAT MBIM_TYPE_PIN_MODE MBIM_TYPE_PIN_OPERATION MBIM_TYPE_PIN_STATE MBIM_TYPE_PIN_TYPE MBIM_TYPE_PROVIDER_STATE MBIM_TYPE_VISIBLE_PROVIDERS_ACTION MBIM_TYPE_RADIO_SWITCH_STATE MBIM_TYPE_READY_INFO_FLAG MBIM_TYPE_REGISTER_ACTION MBIM_TYPE_REGISTER_MODE MBIM_TYPE_REGISTER_STATE MBIM_TYPE_REGISTRATION_FLAG MBIM_TYPE_SERVICE MBIM_TYPE_SIM_CLASS MBIM_TYPE_SMS_CAPS MBIM_TYPE_SUBSCRIBER_READY_STATE MBIM_TYPE_VOICE_CALL_STATE MBIM_TYPE_VOICE_CLASS MBIM_TYPE_SMS_CDMA_ENCODING MBIM_TYPE_SMS_CDMA_LANG MBIM_TYPE_SMS_FLAG MBIM_TYPE_SMS_FORMAT MBIM_TYPE_SMS_STATUS MBIM_TYPE_SMS_STATUS_FLAG MBIM_TYPE_SMS_STORAGE_STATE MBIM_TYPE_USSD_ACTION MBIM_TYPE_USSD_RESPONSE MBIM_TYPE_USSD_SESSION_STATE MBIM_TYPE_PHONEBOOK_FLAG MBIM_TYPE_PHONEBOOK_STATE MBIM_TYPE_PHONEBOOK_WRITE_FLAG MBIM_TYPE_STK_PAC_PROFILE MBIM_TYPE_STK_PAC_TYPE MBIM_TYPE_NETWORK_IDLE_HINT_STATE MBIM_TYPE_EMERGENCY_MODE_STATE MBIM_TYPE_DSS_LINK_STATE MBIM_TYPE_PCO_TYPE MBIM_TYPE_CONTEXT_SOURCE MBIM_TYPE_LTE_ATTACH_CONTEXT_OPERATION MBIM_TYPE_LTE_ATTACH_CONTEXT_ROAMING_CONTROL MBIM_TYPE_LTE_ATTACH_STATE MBIM_TYPE_SAR_BACKOFF_STATE MBIM_TYPE_SAR_CONTROL_MODE MBIM_TYPE_SAR_WIFI_HARDWARE_STATE MBIM_TYPE_TRANSMISSION_NOTIFICATION_STATUS MBIM_TYPE_TRANSMISSION_STATE MBIM_TYPE_QDU_FILE_TYPE MBIM_TYPE_QDU_SESSION_ACTION MBIM_TYPE_QDU_SESSION_RESULT MBIM_TYPE_QDU_SESSION_STATUS MBIM_TYPE_QDU_SESSION_TYPE MBIM_TYPE_QDU_QUECTEL_REBOOT_TYPE MBIM_TYPE_QDU_QUECTEL_VERSION_TYPE MBIM_TYPE_UICC_SLOT_STATE MBIM_TYPE_UICC_SECURE_MESSAGING MBIM_TYPE_UICC_CLASS_BYTE_TYPE MBIM_TYPE_UICC_PASS_THROUGH_ACTION MBIM_TYPE_UICC_PASS_THROUGH_STATUS MBIM_TYPE_FREQUENCY_RANGE MBIM_TYPE_CONTEXT_ROAMING_CONTROL MBIM_TYPE_CONTEXT_MEDIA_TYPE MBIM_TYPE_CONTEXT_STATE MBIM_TYPE_CONTEXT_OPERATION MBIM_TYPE_MICO_MODE MBIM_TYPE_DEFAULT_PDU_ACTIVATION_HINT MBIM_TYPE_LADN_INFO MBIM_TYPE_DRX_CYCLE MBIM_TYPE_SUBSCRIBER_READY_STATUS_FLAG MBIM_TYPE_DATA_CLASS_V3 MBIM_TYPE_DATA_SUBCLASS MBIM_TYPE_MODEM_CONFIGURATION_STATUS MBIM_TYPE_WAKE_TYPE MBIM_TYPE_QUECTEL_RADIO_SWITCH_STATE MBIM_TYPE_ACCESS_MEDIA_TYPE MBIM_TYPE_INTEL_SERVING_CELL_INFO MBIM_TYPE_INTEL_BOOT_MODE MBIM_TYPE_UICC_APPLICATION_TYPE MBIM_TYPE_UICC_FILE_ACCESSIBILITY MBIM_TYPE_UICC_FILE_TYPE MBIM_TYPE_UICC_FILE_STRUCTURE MBIM_TYPE_TRACE_COMMAND MBIM_TYPE_CARRIER_LOCK_STATUS MBIM_TYPE_CARRIER_LOCK_MODEM_STATE MBIM_TYPE_CARRIER_LOCK_CAUSE mbim_activation_command_get_type mbim_activation_state_get_type mbim_auth_protocol_get_type mbim_cellular_class_get_type mbim_compression_get_type mbim_context_ip_type_get_type mbim_context_type_get_type mbim_ctrl_caps_get_type mbim_data_class_get_type mbim_device_type_get_type mbim_ip_configuration_available_flag_get_type mbim_message_command_type_get_type mbim_message_type_get_type mbim_nw_error_get_type mbim_packet_service_action_get_type mbim_packet_service_state_get_type mbim_pin_format_get_type mbim_pin_mode_get_type mbim_pin_operation_get_type mbim_pin_state_get_type mbim_pin_type_get_type mbim_provider_state_get_type mbim_visible_providers_action_get_type mbim_radio_switch_state_get_type mbim_ready_info_flag_get_type mbim_register_action_get_type mbim_register_mode_get_type mbim_register_state_get_type mbim_registration_flag_get_type mbim_service_get_type mbim_sim_class_get_type mbim_sms_caps_get_type mbim_subscriber_ready_state_get_type mbim_voice_call_state_get_type mbim_voice_class_get_type mbim_sms_cdma_encoding_get_type mbim_sms_cdma_lang_get_type mbim_sms_flag_get_type mbim_sms_format_get_type mbim_sms_status_flag_get_type mbim_sms_status_get_type mbim_sms_storage_state_get_type mbim_ussd_action_get_type mbim_ussd_response_get_type mbim_ussd_session_state_get_type mbim_phonebook_flag_get_type mbim_phonebook_state_get_type mbim_phonebook_write_flag_get_type mbim_stk_pac_profile_get_type mbim_stk_pac_type_get_type mbim_network_idle_hint_state_get_type mbim_emergency_mode_state_get_type mbim_dss_link_state_get_type mbim_atds_provider_plmn_mode_get_type mbim_atds_rat_mode_get_type mbim_pco_type_get_type mbim_context_source_get_type mbim_lte_attach_context_operation_get_type mbim_lte_attach_context_roaming_control_get_type mbim_lte_attach_state_get_type mbim_sar_backoff_state_get_type mbim_sar_control_mode_get_type mbim_sar_wifi_hardware_state_get_type mbim_transmission_notification_status_get_type mbim_transmission_state_get_type mbim_qdu_file_type_get_type mbim_qdu_session_action_get_type mbim_qdu_session_result_get_type mbim_qdu_session_status_get_type mbim_qdu_session_type_get_type mbim_qdu_quectel_reboot_type_get_type mbim_qdu_quectel_version_type_get_type mbim_uicc_slot_state_get_type mbim_uicc_class_byte_type_get_type mbim_uicc_secure_messaging_get_type mbim_uicc_pass_through_action_get_type mbim_uicc_pass_through_status_get_type mbim_frequency_range_get_type mbim_context_roaming_control_get_type mbim_context_media_type_get_type mbim_context_state_get_type mbim_context_operation_get_type mbim_mico_mode_get_type mbim_default_pdu_activation_hint_get_type mbim_ladn_info_get_type mbim_drx_cycle_get_type mbim_subscriber_ready_status_flag_get_type mbim_data_class_v3_get_type mbim_data_subclass_get_type mbim_modem_configuration_status_get_type mbim_wake_type_get_type mbim_quectel_radio_switch_state_get_type mbim_access_media_type_get_type mbim_intel_serving_cell_info_get_type mbim_intel_boot_mode_get_type mbim_uicc_application_type_get_type mbim_uicc_file_accessibility_get_type mbim_uicc_file_type_get_type mbim_uicc_file_structure_get_type mbim_trace_command_get_type mbim_carrier_lock_status_get_type mbim_carrier_lock_modem_state_get_type mbim_carrier_lock_cause_get_type
mbim-errors MbimCoreError MbimProtocolError MbimStatusError mbim_core_error_get_string mbim_protocol_error_get_string mbim_status_error_get_string MBIM_DBUS_ERROR_PREFIX MBIM_CORE_ERROR_DBUS_PREFIX MBIM_PROTOCOL_ERROR_DBUS_PREFIX MBIM_STATUS_ERROR_DBUS_PREFIX mbim_core_error_quark mbim_protocol_error_quark mbim_status_error_quark MBIM_CORE_ERROR MBIM_PROTOCOL_ERROR MBIM_STATUS_ERROR MBIM_TYPE_CORE_ERROR MBIM_TYPE_PROTOCOL_ERROR MBIM_TYPE_STATUS_ERROR mbim_core_error_get_type mbim_protocol_error_get_type mbim_status_error_get_type
mbim-utils mbim_utils_get_traces_enabled mbim_utils_set_traces_enabled mbim_utils_set_show_personal_info mbim_utils_get_show_personal_info
mbim-tlv MbimTlv MbimTlvType mbim_tlv_new mbim_tlv_dup mbim_tlv_ref mbim_tlv_unref mbim_tlv_get_raw mbim_tlv_get_tlv_type mbim_tlv_get_tlv_data mbim_tlv_type_get_string mbim_tlv_string_new mbim_tlv_string_get mbim_tlv_guint16_array_get mbim_tlv_wake_command_get mbim_tlv_wake_packet_get mbim_tlv_type_build_string_from_mask MBIM_TYPE_TLV MBIM_TYPE_TLV_TYPE mbim_tlv_get_type mbim_tlv_type_get_type
mbim-compat MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBER_LIST MBIM_REGISTRATION_FLAG_MANUAL_PACKET_SERVICE_AUTOMATIC_ATTACH mbim_message_device_service_subscriber_list_response_parse mbim_message_device_service_subscriber_list_set_new MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_STATUS MbimLteAttachStatus mbim_lte_attach_status_free mbim_message_ms_basic_connect_extensions_lte_attach_status_query_new mbim_message_ms_basic_connect_extensions_lte_attach_status_response_parse mbim_message_ms_basic_connect_extensions_lte_attach_status_notification_parse MBIM_NW_ERROR_UNKNOWN MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_BLACKLIST mbim_sms_status_flag_get_string MbimDeprecatedCidBasicConnect MbimDeprecatedRegistrationFlag MbimDeprecatedCidMsBasicConnectExtensions MbimDeprecatedLteAttachStatus MbimDeprecatedNwError
libmbim-1.31.2-dev/docs/reference/libmbim-glib/libmbim-glib-docs.xml000066400000000000000000000172761453630424100252160ustar00rootroot00000000000000 ]> libmbim-glib Reference Manual For libmbim-glib &version;. The latest version of this documentation can be found on-line at https://www.freedesktop.org/software/libmbim/libmbim-glib/latest/. 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 The libmbim-glib authors Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You may obtain a copy of the GNU Free Documentation License from the Free Software Foundation by visiting their Web site or by writing to:
The Free Software Foundation, Inc. 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
Core Generic Services Microsoft-defined services Qualcomm-defined services AT&T-defined services Intel-defined Services Quectel-defined Services Google-defined Services Fibocom-defined Services libmbim-defined Services Compatibility Object Hierarchy API Index Index of deprecated symbols Index of new symbols in 1.0 Index of new symbols in 1.2 Index of new symbols in 1.4 Index of new symbols in 1.8 Index of new symbols in 1.10 Index of new symbols in 1.12 Index of new symbols in 1.14 Index of new symbols in 1.16 Index of new symbols in 1.18 Index of new symbols in 1.24 Index of new symbols in 1.24.4 Index of new symbols in 1.26 Index of new symbols in 1.26.2 Index of new symbols in 1.28 Index of new symbols in 1.30 Index of new symbols in 1.32
libmbim-1.31.2-dev/docs/reference/libmbim-glib/meson.build000066400000000000000000000033711453630424100233510ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez subdir('xml') doc_module = 'libmbim-glib' src_dirs = [ generated_inc, libmbim_glib_inc, ] private_headers = [ 'mbim-helpers.h', 'mbim-helpers-netlink.h', 'mbim-message-private.h', 'mbim-net-port-manager.h', 'mbim-net-port-manager-wdm.h', 'mbim-net-port-manager-wwan.h', 'wwan.h', ] scan_args = [ '--rebuild-types', '--deprecated-guards="MBIM_DISABLE_DEPRECATED"', ] glib_prefix = glib_dep.get_pkgconfig_variable('prefix') fixxref_args = [ '--html-dir=' + (mbim_prefix / gnome.gtkdoc_html_dir(doc_module)), '--extra-dir=' + (glib_prefix / gnome.gtkdoc_html_dir('glib')), '--extra-dir=' + (glib_prefix / gnome.gtkdoc_html_dir('gio')), ] name = doc_module + '-sections.txt' ''' FIXME: gen_sections should be used in the `input` field but it would add a dependency over file paths that are not yet created, so the `depends` section is used to generate alternate dependency. This is fixed in newer meson versions. ''' sections_txt = custom_target( name, input: 'libmbim-glib-common.sections', output: name, capture: true, command: [find_program('cat'), '@INPUT@'] + gen_sections, depends: gen_sections_deps, ) version_xml = configure_file( input: 'version.xml.in', output: '@BASENAME@', configuration: version_conf, ) gnome.gtkdoc( doc_module, main_xml: doc_module + '-docs.xml', src_dir: src_dirs, ignore_headers: private_headers, include_directories: top_inc, gobject_typesfile: doc_module + '.types', dependencies: libmbim_glib_dep, namespace: 'mbim', scan_args: scan_args, fixxref_args: fixxref_args, content_files: [sections_txt, version_xml], install: true, check: true, ) libmbim-1.31.2-dev/docs/reference/libmbim-glib/version.xml.in000066400000000000000000000000121453630424100240100ustar00rootroot00000000000000@VERSION@ libmbim-1.31.2-dev/docs/reference/libmbim-glib/xml/000077500000000000000000000000001453630424100220035ustar00rootroot00000000000000libmbim-1.31.2-dev/docs/reference/libmbim-glib/xml/gtkdocentities.ent.in000066400000000000000000000004461453630424100261440ustar00rootroot00000000000000 libmbim-1.31.2-dev/docs/reference/libmbim-glib/xml/meson.build000066400000000000000000000010071453630424100241430ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez ent_conf = { 'PACKAGE': mbim_name, 'PACKAGE_BUGREPORT': mbim_name + '-devel@lists.freedesktop.org', 'PACKAGE_NAME': mbim_name, 'PACKAGE_STRING': '@0@ @1@'.format(mbim_name, mbim_version), 'PACKAGE_TARNAME': mbim_name, 'PACKAGE_URL': '', 'PACKAGE_VERSION': mbim_version, } gtkdocentities_ent = configure_file( input: 'gtkdocentities.ent.in', output: '@BASENAME@', configuration: ent_conf, ) libmbim-1.31.2-dev/examples/000077500000000000000000000000001453630424100156055ustar00rootroot00000000000000libmbim-1.31.2-dev/examples/simple-tester-python/000077500000000000000000000000001453630424100217215ustar00rootroot00000000000000libmbim-1.31.2-dev/examples/simple-tester-python/README000066400000000000000000000016401453630424100226020ustar00rootroot00000000000000 The simple-tester-python program makes use of the 'libmbim-glib' library through GObject Introspection. The program will: * Open a connection to the mbim-proxy, or launch the mbim-proxy itself if it isn't already running. * Query device capabilities The output will look like this: $ ./simple-tester-python /dev/cdc-wdm0 device type: embedded cellular class: gsm voice class: no-voice sim class: removable data class: gprs, edge, umts, hsdpa, hsupa, lte sms capabilities: pdu-receive, pdu-send control capabilities: reg-manual max sessions: 8 custom data class: None device id: 013937003110648 firmware info: FIH7160_V1.1_MODEM_01.1349.12 hardware info: XMM7160_V1.1_MBIM_GNSS_NAND_RE Note that the program requires libmbim-glib to be installed in the system and the introspection typelibs available in the standard paths. Have fun!libmbim-1.31.2-dev/examples/simple-tester-python/simple-tester-python000077500000000000000000000101171453630424100257630ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation; either version 2 of the License, or (at your option) any # later version. # # 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 Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser 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. # # Copyright (C) 2020 Aleksander Morgado # import sys, signal, gi gi.require_version('Mbim', '1.0') from gi.repository import GLib, Gio, Mbim main_loop = None def signal_handler(data): main_loop.quit() def close_ready(mbimdev,result,user_data=None): try: mbimdev.close_finish(result) except GLib.GError as error: sys.stderr.write("Couldn't close MBIM device: %s\n" % error.message) main_loop.quit() def query_device_caps_ready(mbimdev,result,user_data=None): try: response = mbimdev.command_finish(result) response.command_done_get_result() success, devtype, cellclass, voiceclass, simclass, dataclass, smscaps, controlcaps, maxsessions, customdataclass, deviceid, firmwareinfo, hardwareinfo = response.device_caps_response_parse() if success: print("device type: %s" % Mbim.DeviceType.get_string(devtype)) print("cellular class: %s" % Mbim.CellularClass.build_string_from_mask(cellclass)) print("voice class: %s" % Mbim.VoiceClass.get_string(voiceclass)) print("sim class: %s" % Mbim.SimClass.build_string_from_mask(simclass)) print("data class: %s" % Mbim.DataClass.build_string_from_mask(dataclass)) print("sms capabilities: %s" % Mbim.SmsCaps.build_string_from_mask(smscaps)) print("control capabilities: %s" % Mbim.CtrlCaps.build_string_from_mask(controlcaps)) print("max sessions: %u" % maxsessions) print("custom data class: %s" % customdataclass) print("device id: %s" % deviceid) print("firmware info: %s" % firmwareinfo) print("hardware info: %s" % hardwareinfo) except GLib.GError as error: sys.stderr.write("Couldn't run MBIM command: %s\n" % error.message) mbimdev.close(10, None, close_ready, None) def open_full_ready(mbimdev,result,user_data=None): try: mbimdev.open_full_finish(result) except GLib.GError as error: sys.stderr.write("Couldn't open MBIM device: %s\n" % error.message) main_loop.quit() return request = Mbim.Message.device_caps_query_new () mbimdev.command(request, 10, None, query_device_caps_ready, None) def new_ready(unused,result,user_data=None): try: mbimdev = Mbim.Device.new_finish(result) except GLib.GError as error: sys.stderr.write("Couldn't create MBIM device: %s\n" % error.message) main_loop.quit() return mbimdev.open_full(Mbim.DeviceOpenFlags.PROXY, 10, None, open_full_ready, None) if __name__ == "__main__": # Process input arguments if len(sys.argv) != 2: sys.stderr.write('error: wrong number of arguments\n') sys.stdout.write('usage: simple-tester-python \n') sys.exit(1) # Create Mbim device asynchronously file = Gio.File.new_for_path(sys.argv[1]) Mbim.Device.new (file, None, new_ready, None) # Main loop main_loop = GLib.MainLoop() GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGHUP, signal_handler, None) GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, signal_handler, None) try: main_loop.run() except KeyboardInterrupt: pass libmbim-1.31.2-dev/meson.build000066400000000000000000000137671453630424100161470ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez project( 'libmbim', 'c', version: '1.31.2', license: ['GPL-2.0-or-later', 'LGPL-2.1-or-later'], default_options: [ 'buildtype=debugoptimized', 'c_std=gnu89', 'warning_level=2', ], meson_version: '>= 0.53.0', ) mbim_name = meson.project_name() mbim_version = meson.project_version() version_array = mbim_version.split('.') mbim_major_version = version_array[0].to_int() mbim_minor_version = version_array[1].to_int() mbim_micro_version = version_array[2].to_int() mbim_prefix = get_option('prefix') mbim_bindir = get_option('bindir') mbim_datadir = get_option('datadir') mbim_includedir = get_option('includedir') mbim_libexecdir = get_option('libexecdir') mbim_mandir = get_option('mandir') mbim_glib_include_subdir = mbim_name + '-glib' mbim_glib_pkgincludedir = mbim_includedir / mbim_glib_include_subdir # libtool versioning for libmbim-glib (-version-info c:r:a) # - If the interface is unchanged, but the implementation has changed or been fixed, then increment r # - Otherwise, increment c and zero r. # - If the interface has grown (that is, the new library is compatible with old code), increment a. # - If the interface has changed in an incompatible way (that is, functions have changed or been removed), then zero a. current = 12 revision = 0 age = 8 mbim_glib_version = '@0@.@1@.@2@'.format(current - age, age, revision) mbim_gir_version = '1.0' gnome = import('gnome') i18n = import('i18n') pkg = import('pkgconfig') python = import('python').find_installation('python3') source_root = meson.current_source_dir() data_dir = source_root / 'data' templates_dir = source_root / 'build-aux/templates' mbim_codegen = find_program(source_root / 'build-aux/mbim-codegen/mbim-codegen') mbim_mkenums = find_program(source_root / 'build-aux/mbim-mkenums') top_inc = include_directories('.') cc = meson.get_compiler('c') config_h = configuration_data() config_h.set_quoted('PACKAGE_VERSION', mbim_version) # compiler flags common_flags = ['-DHAVE_CONFIG_H'] # compiler flags that are always enabled, even in release builds cc_flags = cc.get_supported_arguments([ # warning on unused parameters is overkill, never do that '-Wno-unused-parameter', # function type cast disabled: used throughout the code especially to # cast GAsyncReadyCallbacks with the real object type instead of GObject '-Wno-cast-function-type', # all message protocol structs are packed, never complain about it '-Wno-packed', ]) # strict flags to use in debug builds if get_option('buildtype').contains('debug') cc_flags += cc.get_supported_arguments([ '-fno-strict-aliasing', '-Waggregate-return', '-Wcast-align', '-Wdeclaration-after-statement', '-Wdouble-promotion', '-Wduplicated-branches', '-Wduplicated-cond', '-Wfloat-equal', '-Wformat=2', '-Wformat-nonliteral', '-Wformat-security', '-Winit-self', '-Winline', '-Wjump-misses-init', '-Wlogical-op', '-Wnested-externs', '-Wmissing-declarations', '-Wmissing-format-attribute', '-Wmissing-include-dirs', '-Wmissing-noreturn', '-Wmissing-prototypes', '-Wnull-dereference', '-Wpointer-arith', '-Wredundant-decls', '-Wrestrict', '-Wreturn-type', '-Wshadow', '-Wstrict-prototypes', '-Wsuggest-attribute=format', '-Wswitch-default', '-Wswitch-enum', '-Wundef', '-Wunused-but-set-variable', '-Wwrite-strings', ]) endif add_project_arguments(common_flags + cc_flags, language: 'c') glib_version = '2.56' glib_dep = dependency('glib-2.0', version: '>= ' + glib_version) gio_unix_dep = dependency('gio-unix-2.0') deps = [ glib_dep, dependency('gio-2.0'), dependency('gobject-2.0'), ] c_flags = [ '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_' + glib_version.underscorify(), '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_' + glib_version.underscorify(), '-DGLIB_DISABLE_DEPRECATION_WARNINGS', ] glib_deps = declare_dependency( dependencies: deps, compile_args: c_flags, ) enable_bash_completion = get_option('bash_completion') if enable_bash_completion bash_completion_dep = dependency('bash-completion') bash_completion_completionsdir = bash_completion_dep.get_pkgconfig_variable( 'completionsdir', # bash-completion 2.10 changed the substitutions define_variable: bash_completion_dep.version().version_compare('>= 2.10') ? ['datadir', mbim_datadir] : ['prefix', mbim_prefix], ) endif # MBIM username mbim_username = get_option('mbim_username') enable_mbim_username = (mbim_username != '') if enable_mbim_username config_h.set_quoted('MBIM_USERNAME', mbim_username) # FIXME: udev base directory, prefix can't be overrided udev_udevdir = get_option('udevdir') if udev_udevdir == '' udev_udevdir = dependency('udev').get_pkgconfig_variable('udevdir') endif else mbim_username = 'no (root)' endif config_h.set('MBIM_USERNAME_ENABLED', enable_mbim_username) # introspection support enable_gir = get_option('introspection') if enable_gir dependency('gobject-introspection-1.0', version: '>= 0.9.6') endif version_conf = { 'MBIM_MAJOR_VERSION': mbim_major_version, 'MBIM_MINOR_VERSION': mbim_minor_version, 'MBIM_MICRO_VERSION': mbim_micro_version, 'VERSION': mbim_version, } subdir('src') subdir('utils') enable_gtk_doc = get_option('gtk_doc') if enable_gtk_doc subdir('docs/reference/libmbim-glib') endif enable_man = get_option('man') if enable_man subdir('docs/man') endif enable_fuzzer = get_option('fuzzer') configure_file( output: 'config.h', configuration: config_h, ) summary({ 'compiler': cc.get_id(), 'cflags': cc_flags, 'Documentation': enable_gtk_doc, 'bash completion': enable_bash_completion, 'gobject introspection': enable_gir, 'man pages': enable_man, 'fuzzer': enable_fuzzer, }, section: 'Build') summary({ 'prefix': mbim_prefix, 'udev base directory': (enable_mbim_username ? udev_udevdir : 'disabled'), }, section: 'System paths') summary({ 'MBIM username': mbim_username, }, section: 'Features') libmbim-1.31.2-dev/meson_options.txt000066400000000000000000000014131453630424100174230ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez option('mbim_username', type: 'string', value: '', description: 'user allowed to access MBIM devices') option('udevdir', type: 'string', value: '', description: 'where udev base directory is') option('introspection', type: 'boolean', value: true, description: 'build introspection support') option('gtk_doc', type: 'boolean', value: false, description: 'use gtk-doc to build documentation') option('man', type: 'boolean', value: true, description: 'build man pages using help2man') option('bash_completion', type: 'boolean', value: true, description: 'install bash completion files') option('fuzzer', type: 'boolean', value: false, description: 'build fuzzer tests') libmbim-1.31.2-dev/src/000077500000000000000000000000001453630424100145565ustar00rootroot00000000000000libmbim-1.31.2-dev/src/common/000077500000000000000000000000001453630424100160465ustar00rootroot00000000000000libmbim-1.31.2-dev/src/common/mbim-common.c000066400000000000000000000026111453630424100204240ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2017 Google Inc. */ #include #include #include "mbim-common.h" /*****************************************************************************/ gchar * mbim_common_str_hex (gconstpointer mem, gsize size, gchar delimiter) { const guint8 *data = mem; gsize i; gsize j; gsize new_str_length; gchar *new_str; /* Get new string length. If input string has N bytes, we need: * - 1 byte for last NUL char * - 2N bytes for hexadecimal char representation of each byte... * - N-1 bytes for the separator ':' * So... a total of (1+2N+N-1) = 3N bytes are needed... */ new_str_length = 3 * size; /* Allocate memory for new array and initialize contents to NUL */ new_str = g_malloc0 (new_str_length); /* Print hexadecimal representation of each byte... */ for (i = 0, j = 0; i < size; i++, j += 3) { /* Print character in output string... */ snprintf (&new_str[j], 3, "%02X", data[i]); /* And if needed, add separator */ if (i != (size - 1) ) new_str[j + 2] = delimiter; } /* Set output string */ return new_str; } libmbim-1.31.2-dev/src/common/mbim-common.h000066400000000000000000000010001453630424100204200ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2017 Google Inc. */ #ifndef _COMMON_MBIM_COMMON_H_ #define _COMMON_MBIM_COMMON_H_ #include gchar *mbim_common_str_hex (gconstpointer mem, gsize size, gchar delimiter); #endif /* _COMMON_MBIM_COMMON_H_ */ libmbim-1.31.2-dev/src/common/meson.build000066400000000000000000000006051453630424100202110ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez libmbim_common = static_library( 'mbim-common', sources: 'mbim-common.c', include_directories: top_inc, dependencies: glib_dep, ) libmbim_common_dep = declare_dependency( include_directories: '.', dependencies: glib_dep, link_with: libmbim_common, ) subdir('test') libmbim-1.31.2-dev/src/common/test/000077500000000000000000000000001453630424100170255ustar00rootroot00000000000000libmbim-1.31.2-dev/src/common/test/meson.build000066400000000000000000000004031453630424100211640ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez test_name = 'test-common' executable( test_name, sources: test_name + '.c', include_directories: top_inc, dependencies: libmbim_common_dep, ) libmbim-1.31.2-dev/src/common/test/test-common.c000066400000000000000000000020561453630424100214410ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Google Inc. */ #include #include "mbim-common.h" static void test_common_str_hex (void) { static const guint8 buffer [] = { 0x00, 0xDE, 0xAD, 0xC0, 0xDE }; gchar *str; str = mbim_common_str_hex (NULL, 0, ':'); g_assert (str == NULL); str = mbim_common_str_hex (buffer, 0, ':'); g_assert (str == NULL); str = mbim_common_str_hex (buffer, 1, ':'); g_assert_cmpstr (str, ==, "00"); g_free (str); str = mbim_common_str_hex (buffer, 2, '-'); g_assert_cmpstr (str, ==, "00-DE"); g_free (str); str = mbim_common_str_hex (buffer, 5, '.'); g_assert_cmpstr (str, ==, "00.DE.AD.C0.DE"); g_free (str); } /*****************************************************************************/ int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/common/str_hex", test_common_str_hex); return g_test_run (); } libmbim-1.31.2-dev/src/libmbim-glib/000077500000000000000000000000001453630424100171045ustar00rootroot00000000000000libmbim-1.31.2-dev/src/libmbim-glib/76-mbim-device-ownership.rules.in000066400000000000000000000004371453630424100252200ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # do not edit this file, it will be overwritten on update ACTION!="add|change|move", GOTO="mbim_device_ownership_end" KERNEL=="cdc-wdm*", DRIVERS=="cdc_mbim", SUBSYSTEM=="usbmisc", OWNER="@MBIM_USERNAME@" LABEL="mbim_device_ownership_end" libmbim-1.31.2-dev/src/libmbim-glib/generated/000077500000000000000000000000001453630424100210425ustar00rootroot00000000000000libmbim-1.31.2-dev/src/libmbim-glib/generated/meson.build000066400000000000000000000125701453630424100232110ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez generated_inc = include_directories('.') gen_sources = [] gen_headers = [] gen_sections = [] gen_sections_deps = [] # Error types enum_types = 'mbim-error-types' gen_headers += custom_target( enum_types + '.h', input: mbim_errors_header, output: enum_types + '.h', command: [ python, mbim_mkenums, '--fhead', '#ifndef __LIBMBIM_GLIB_ERROR_TYPES_H__\n#define __LIBMBIM_GLIB_ERROR_TYPES_H__\n#include "mbim-errors.h"\n', '--template', files(templates_dir / enum_types + '.h.template'), '--ftail', '#endif /* __LIBMBIM_GLIB_ERROR_TYPES_H__ */\n', '@INPUT@'], capture: true, install: true, install_dir: mbim_glib_pkgincludedir, ) gen_sources += custom_target( enum_types + '.c', input: mbim_errors_header, output: enum_types + '.c', command: [ python, mbim_mkenums, '--fhead', '#include "mbim-errors.h"\n#include "mbim-error-types.h"\n', '--template', files(templates_dir / enum_types + '.c.template'), '@INPUT@'], capture: true, ) enum_types = 'mbim-error-quarks' gen_sources += custom_target( enum_types + '.c', input: mbim_errors_header, output: enum_types + '.c', command: [ python, mbim_mkenums, '--fhead', '#include "mbim-errors.h"\n#include "mbim-error-types.h"\n', '--template', files(templates_dir / enum_types + '.c.template'), '@INPUT@'], capture: true, ) # Enum types enum_types = 'mbim-enum-types' gen_headers += custom_target( enum_types + '.h', input: mbim_enums_headers, output: enum_types + '.h', command: [ python, mbim_mkenums, '--enums-only', '--fhead', '#ifndef __LIBMBIM_GLIB_ENUM_TYPES_H__\n#define __LIBMBIM_GLIB_ENUM_TYPES_H__\n#include "mbim-uuid.h"\n#include "mbim-cid.h"\n#include "mbim-message.h"\n#include "mbim-enums.h"\n#include "mbim-tlv.h"\n', '--template', files(templates_dir / enum_types + '.h.template'), '--ftail', '#endif /* __LIBMBIM_GLIB_ENUM_TYPES_H__ */\n', '@INPUT@'], capture: true, install: true, install_dir: mbim_glib_pkgincludedir, ) gen_sources += custom_target( enum_types + '.c', input: mbim_enums_headers, output: enum_types + '.c', command: [ python, mbim_mkenums, '--enums-only', '--fhead', '#include "mbim-enum-types.h"\n', '--template', files(templates_dir / enum_types + '.c.template'), '@INPUT@'], capture: true, ) # Flag types enum_types = 'mbim-flag-types' gen_headers += custom_target( enum_types + '.h', input: mbim_enums_headers, output: enum_types + '.h', command: [ python, mbim_mkenums, '--flags-only', '--fhead', '#ifndef __LIBMBIM_GLIB_FLAG_TYPES_H__\n#define __LIBMBIM_GLIB_FLAG_TYPES_H__\n#include "mbim-uuid.h"\n#include "mbim-cid.h"\n#include "mbim-message.h"\n#include "mbim-enums.h"\n#include "mbim-tlv.h"\n', '--template', files(templates_dir / enum_types + '.h.template'), '--ftail', '#endif /* __LIBMBIM_GLIB_FLAG_TYPES_H__ */\n', '@INPUT@'], capture: true, install: true, install_dir: mbim_glib_pkgincludedir, ) gen_sources += custom_target( enum_types + '.c', input: mbim_enums_headers, output: enum_types + '.c', command: [ python, mbim_mkenums, '--flags-only', '--fhead', '#include "mbim-flag-types.h"\n', '--template', files(templates_dir / enum_types + '.c.template'), '@INPUT@'], capture: true, ) services_data = [ ['atds'], ['auth'], ['basic-connect', 'ms-basic-connect-v2', 'ms-basic-connect-v3'], ['dss'], ['intel-firmware-update', 'intel-firmware-update-v2'], ['intel-thermal-rf'], ['ms-basic-connect-extensions', 'ms-basic-connect-extensions-v2', 'ms-basic-connect-extensions-v3'], ['ms-uicc-low-level-access'], ['ms-firmware-id'], ['ms-host-shutdown'], ['ms-sar'], ['ms-voice-extensions'], ['phonebook'], ['proxy-control'], ['qdu'], ['quectel'], ['qmi'], ['sms'], ['stk'], ['ussd'], ['intel-mutual-authentication'], ['intel-tools'], ['google'], ['fibocom'], ] foreach service_data: services_data service = service_data[0] name = 'mbim-' + service input = [] foreach service_file: service_data input += data_dir / 'mbim-service-@0@.json'.format(service_file) endforeach generated = custom_target( name, input: input, output: [name + '.c', name + '.h', name + '.sections'], command: [mbim_codegen, '--output', '@OUTDIR@' / name, '@INPUT@'], install: true, install_dir: [false, mbim_glib_pkgincludedir, false], ) gen_sources += generated[0] gen_headers += generated[1] # FIXME: the third target generated by custom target can't by used because is not a known # source file, to the path has to be used. the first workaround is to use the # build paths to point to the files, and the second workaround is to use # custom target objects to force its building. gen_sections += [meson.current_build_dir() / name + '.sections'] gen_sections_deps += [generated] endforeach c_flags = [ '-DLIBMBIM_GLIB_COMPILATION', '-DG_LOG_DOMAIN="Mbim"', '-Wno-unused-function', ] libmbim_glib_generated = static_library( 'mbim-glib-generated', sources: gen_sources + gen_headers, include_directories: libmbim_glib_inc, dependencies: glib_deps, c_args: c_flags, ) generated_dep = declare_dependency( sources: gen_headers, include_directories: [libmbim_glib_inc, generated_inc], dependencies: glib_deps, ) libmbim-1.31.2-dev/src/libmbim-glib/kernel/000077500000000000000000000000001453630424100203645ustar00rootroot00000000000000libmbim-1.31.2-dev/src/libmbim-glib/kernel/if_link.h000066400000000000000000000007761453630424100221620ustar00rootroot00000000000000 #ifndef _MBIM_IF_LINK_H #define _MBIM_IF_LINK_H #include /* Instead of checking if the libc or kernel provided headers * include the enum value we require, in this case we define * a new one ourselves. We cannot check if a single enum value * was defined in an included header via preprocessor directives. */ enum { /* device (sysfs) name as parent, used instead * of IFLA_LINK where there's no parent netdev. */ MBIM_IFLA_PARENT_DEV_NAME = 56, }; #endif /* _MBIM_IF_LINK_H */ libmbim-1.31.2-dev/src/libmbim-glib/kernel/wwan.h000066400000000000000000000002701453630424100215100ustar00rootroot00000000000000 #ifndef _MBIM_WWAN_H #define _MBIM_WWAN_H /* kernel values defined in linux/wwan.h */ enum { MBIM_IFLA_WWAN_UNSPEC, MBIM_IFLA_WWAN_LINK_ID, /* u32 */ }; #endif /* _MBIM_WWAN_H */ libmbim-1.31.2-dev/src/libmbim-glib/libmbim-glib.h000066400000000000000000000027701453630424100216110ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2022 Intel Corporation */ #ifndef _LIBMBIM_GLIB_H_ #define _LIBMBIM_GLIB_H_ #define __LIBMBIM_GLIB_H_INSIDE__ /* libmbim-glib headers */ #include "mbim-version.h" #include "mbim-utils.h" #include "mbim-uuid.h" #include "mbim-cid.h" #include "mbim-message.h" #include "mbim-device.h" #include "mbim-enums.h" #include "mbim-proxy.h" #include "mbim-tlv.h" /* generated */ #include "mbim-enum-types.h" #include "mbim-flag-types.h" #include "mbim-error-types.h" #include "mbim-basic-connect.h" #include "mbim-sms.h" #include "mbim-ussd.h" #include "mbim-auth.h" #include "mbim-phonebook.h" #include "mbim-stk.h" #include "mbim-dss.h" #include "mbim-ms-firmware-id.h" #include "mbim-ms-host-shutdown.h" #include "mbim-ms-sar.h" #include "mbim-qmi.h" #include "mbim-atds.h" #include "mbim-qdu.h" #include "mbim-intel-firmware-update.h" #include "mbim-ms-basic-connect-extensions.h" #include "mbim-ms-uicc-low-level-access.h" #include "mbim-quectel.h" #include "mbim-intel-thermal-rf.h" #include "mbim-ms-voice-extensions.h" #include "mbim-intel-mutual-authentication.h" #include "mbim-intel-tools.h" #include "mbim-google.h" #include "mbim-fibocom.h" /* backwards compatibility */ #include "mbim-compat.h" #endif /* _LIBMBIM_GLIB_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-cid.c000066400000000000000000000564211453630424100207410ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2022 Intel Corporation */ #include "mbim-cid.h" #include "mbim-uuid.h" #include "mbim-enum-types.h" typedef struct { gboolean set; gboolean query; gboolean notify; } CidConfig; #define NO_SET FALSE #define NO_QUERY FALSE #define NO_NOTIFY FALSE #define SET TRUE #define QUERY TRUE #define NOTIFY TRUE /* Note: index of the array is CID-1 */ #define MBIM_CID_BASIC_CONNECT_LAST MBIM_CID_BASIC_CONNECT_MULTICARRIER_PROVIDERS static const CidConfig cid_basic_connect_config [MBIM_CID_BASIC_CONNECT_LAST] = { { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_DEVICE_CAPS */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS */ { SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_RADIO_STATE */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_PIN */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_PIN_LIST */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_HOME_PROVIDER */ { SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_PREFERRED_PROVIDERS */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_VISIBLE_PROVIDERS */ { SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_REGISTER_STATE */ { SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_PACKET_SERVICE */ { SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_SIGNAL_STATE */ { SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_CONNECT */ { SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_SERVICE_ACTIVATION */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_IP_CONFIGURATION */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_DEVICE_SERVICES */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* 17 reserved */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* 18 reserved */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBE_LIST */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_PACKET_STATISTICS */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_NETWORK_IDLE_HINT */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_EMERGENCY_MODE */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_BASIC_CONNECT_IP_PACKET_FILTERS */ { SET, QUERY, NOTIFY }, /* MBIM_CID_BASIC_CONNECT_MULTICARRIER_PROVIDERS */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_SMS_LAST MBIM_CID_SMS_MESSAGE_STORE_STATUS static const CidConfig cid_sms_config [MBIM_CID_SMS_LAST] = { { SET, QUERY, NOTIFY }, /* MBIM_CID_SMS_CONFIGURATION */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_SMS_READ */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_SMS_SEND */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_SMS_DELETE */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_SMS_MESSAGE_STORE_STATUS */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_USSD_LAST MBIM_CID_USSD static const CidConfig cid_ussd_config [MBIM_CID_USSD_LAST] = { { SET, NO_QUERY, NOTIFY }, /* MBIM_CID_USSD */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_PHONEBOOK_LAST MBIM_CID_PHONEBOOK_WRITE static const CidConfig cid_phonebook_config [MBIM_CID_PHONEBOOK_LAST] = { { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_PHONEBOOK_CONFIGURATION */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_PHONEBOOK_READ */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_PHONEBOOK_DELETE */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_PHONEBOOK_WRITE */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_STK_LAST MBIM_CID_STK_ENVELOPE static const CidConfig cid_stk_config [MBIM_CID_STK_LAST] = { { SET, QUERY, NOTIFY }, /* MBIM_CID_STK_PAC */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_STK_TERMINAL_RESPONSE */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_STK_ENVELOPE */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_AUTH_LAST MBIM_CID_AUTH_SIM static const CidConfig cid_auth_config [MBIM_CID_AUTH_LAST] = { { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_AUTH_AKA */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_AUTH_AKAP */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_AUTH_SIM */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_DSS_LAST MBIM_CID_DSS_CONNECT static const CidConfig cid_dss_config [MBIM_CID_DSS_LAST] = { { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_DSS_CONNECT */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_MS_FIRMWARE_ID_LAST MBIM_CID_MS_FIRMWARE_ID_GET static const CidConfig cid_ms_firmware_id_config [MBIM_CID_MS_FIRMWARE_ID_LAST] = { { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_FIRMWARE_ID_GET */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_MS_HOST_SHUTDOWN_LAST MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY static const CidConfig cid_ms_host_shutdown_config [MBIM_CID_MS_HOST_SHUTDOWN_LAST] = { { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_MS_SAR_LAST MBIM_CID_MS_SAR_TRANSMISSION_STATUS static const CidConfig cid_ms_sar_config [MBIM_CID_MS_SAR_LAST] = { { SET, QUERY, NOTIFY }, /* MBIM_CID_MS_SAR_CONFIG */ { SET, QUERY, NOTIFY }, /* MBIM_CID_MS_SAR_TRANSMISSION_STATUS */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_PROXY_CONTROL_LAST MBIM_CID_PROXY_CONTROL_VERSION static const CidConfig cid_proxy_control_config [MBIM_CID_PROXY_CONTROL_LAST] = { { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_PROXY_CONTROL_CONFIGURATION */ { NO_SET, NO_QUERY, NOTIFY }, /* MBIM_CID_PROXY_CONTROL_VERSION */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_QMI_LAST MBIM_CID_QMI_MSG static const CidConfig cid_qmi_config [MBIM_CID_QMI_LAST] = { { SET, NO_QUERY, NOTIFY }, /* MBIM_CID_QMI_MSG */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_ATDS_LAST MBIM_CID_ATDS_REGISTER_STATE static const CidConfig cid_atds_config [MBIM_CID_ATDS_LAST] = { { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_ATDS_SIGNAL */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_ATDS_LOCATION */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_ATDS_OPERATORS */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_ATDS_RAT */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_ATDS_REGISTER_STATE */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_INTEL_FIRMWARE_UPDATE_LAST MBIM_CID_INTEL_FIRMWARE_UPDATE_MODEM_REBOOT static const CidConfig cid_intel_firmware_update_config [MBIM_CID_INTEL_FIRMWARE_UPDATE_LAST] = { { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_INTEL_FIRMWARE_UPDATE_MODEM_REBOOT */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LAST MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS static const CidConfig cid_ms_basic_connect_extensions_config [MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LAST] = { { SET, QUERY, NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PROVISIONED_CONTEXTS */ { SET, QUERY, NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_DENYLIST */ { SET, QUERY, NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_CONFIG */ { SET, QUERY, NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_STATUS */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_SYS_CAPS */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_CAPS */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_SLOT_MAPPINGS */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_SLOT_INFO_STATUS */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PCO */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_RESET */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_BASE_STATIONS_INFO */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LOCATION_INFO_STATUS */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_VERSION */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_QDU_LAST MBIM_CID_QDU_FILE_WRITE static const CidConfig cid_qdu_config [MBIM_CID_QDU_LAST] = { { SET, QUERY, NOTIFY }, /* MBIM_CID_QDU_UPDATE_SESSION */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_QDU_FILE_OPEN */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_QDU_FILE_WRITE */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_LAST MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD static const CidConfig cid_ms_uicc_low_level_access_config [MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_LAST] = { { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_ATR */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_OPEN_CHANNEL */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_CLOSE_CHANNEL */ { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APDU */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_TERMINAL_CAPABILITY */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_RESET */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APPLICATION_LIST */ { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_FILE_STATUS */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_BINARY */ { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_QUECTEL_LAST MBIM_CID_QUECTEL_RADIO_STATE static const CidConfig cid_quectel_config [MBIM_CID_QUECTEL_LAST] = { { NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_QUECTEL_RADIO_STATE */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_INTEL_THERMAL_RF_LAST MBIM_CID_INTEL_THERMAL_RF_RFIM static const CidConfig cid_intel_thermal_rf_config [MBIM_CID_INTEL_THERMAL_RF_LAST] = { { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { SET, QUERY, NOTIFY }, /* MBIM_CID_INTEL_THERMAL_RF_RFIM */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_MS_VOICE_EXTENSIONS_LAST MBIM_CID_MS_VOICE_EXTENSIONS_NITZ static const CidConfig cid_ms_voice_extensions_config [MBIM_CID_MS_VOICE_EXTENSIONS_LAST] = { { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, QUERY, NOTIFY }, /* MBIM_CID_MS_VOICE_EXTENSIONS_NITZ */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_LAST MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_FCC_LOCK static const CidConfig cid_intel_mutual_authentication_config [MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_LAST] = { { SET, QUERY, NO_NOTIFY }, /* MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_FCC_LOCK */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_INTEL_TOOLS_LAST MBIM_CID_INTEL_TOOLS_TRACE_CONFIG static const CidConfig cid_intel_tools_config [MBIM_CID_INTEL_TOOLS_LAST] = { { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { NO_SET, NO_QUERY, NO_NOTIFY }, /* Unused */ { SET , QUERY , NO_NOTIFY }, /* MBIM_CID_INTEL_TOOLS_TRACE_CONFIG */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_GOOGLE_LAST MBIM_CID_GOOGLE_CARRIER_LOCK static const CidConfig cid_google_config [MBIM_CID_GOOGLE_LAST] = { { SET, QUERY, NOTIFY }, /* MBIM_CID_GOOGLE_CARRIER_LOCK */ }; /* Note: index of the array is CID-1 */ #define MBIM_CID_FIBOCOM_LAST MBIM_CID_FIBOCOM_AT_COMMAND static const CidConfig cid_fibocom_config [MBIM_CID_FIBOCOM_LAST] = { { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_FIBOCOM_AT_COMMAND */ }; gboolean mbim_cid_can_set (MbimService service, guint cid) { /* CID = 0 is never a valid command */ g_return_val_if_fail (cid > 0, FALSE); /* Known service required */ g_return_val_if_fail (service > MBIM_SERVICE_INVALID, FALSE); g_return_val_if_fail (service < MBIM_SERVICE_LAST, FALSE); switch (service) { case MBIM_SERVICE_BASIC_CONNECT: return cid_basic_connect_config[cid - 1].set; case MBIM_SERVICE_SMS: return cid_sms_config[cid - 1].set; case MBIM_SERVICE_USSD: return cid_ussd_config[cid - 1].set; case MBIM_SERVICE_PHONEBOOK: return cid_phonebook_config[cid - 1].set; case MBIM_SERVICE_STK: return cid_stk_config[cid - 1].set; case MBIM_SERVICE_AUTH: return cid_auth_config[cid - 1].set; case MBIM_SERVICE_DSS: return cid_dss_config[cid - 1].set; case MBIM_SERVICE_MS_FIRMWARE_ID: return cid_ms_firmware_id_config[cid - 1].set; case MBIM_SERVICE_MS_HOST_SHUTDOWN: return cid_ms_host_shutdown_config[cid - 1].set; case MBIM_SERVICE_MS_SAR: return cid_ms_sar_config[cid - 1].set; case MBIM_SERVICE_PROXY_CONTROL: return cid_proxy_control_config[cid - 1].set; case MBIM_SERVICE_QMI: return cid_qmi_config[cid - 1].set; case MBIM_SERVICE_ATDS: return cid_atds_config[cid - 1].set; case MBIM_SERVICE_INTEL_FIRMWARE_UPDATE: return cid_intel_firmware_update_config[cid - 1].set; case MBIM_SERVICE_QDU: return cid_qdu_config[cid - 1].set; case MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS: return cid_ms_basic_connect_extensions_config[cid - 1].set; case MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS: return cid_ms_uicc_low_level_access_config[cid - 1].set; case MBIM_SERVICE_QUECTEL: return cid_quectel_config[cid - 1].set; case MBIM_SERVICE_INTEL_THERMAL_RF: return cid_intel_thermal_rf_config[cid - 1].set; case MBIM_SERVICE_MS_VOICE_EXTENSIONS: return cid_ms_voice_extensions_config[cid - 1].set; case MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: return cid_intel_mutual_authentication_config[cid - 1].set; case MBIM_SERVICE_INTEL_TOOLS: return cid_intel_tools_config[cid - 1].set; case MBIM_SERVICE_GOOGLE: return cid_google_config[cid - 1].set; case MBIM_SERVICE_FIBOCOM: return cid_fibocom_config[cid - 1].set; case MBIM_SERVICE_INVALID: case MBIM_SERVICE_LAST: default: g_assert_not_reached (); return FALSE; } } gboolean mbim_cid_can_query (MbimService service, guint cid) { /* CID = 0 is never a valid command */ g_return_val_if_fail (cid > 0, FALSE); /* Known service required */ g_return_val_if_fail (service > MBIM_SERVICE_INVALID, FALSE); g_return_val_if_fail (service < MBIM_SERVICE_LAST, FALSE); switch (service) { case MBIM_SERVICE_BASIC_CONNECT: return cid_basic_connect_config[cid - 1].query; case MBIM_SERVICE_SMS: return cid_sms_config[cid - 1].query; case MBIM_SERVICE_USSD: return cid_ussd_config[cid - 1].query; case MBIM_SERVICE_PHONEBOOK: return cid_phonebook_config[cid - 1].query; case MBIM_SERVICE_STK: return cid_stk_config[cid - 1].query; case MBIM_SERVICE_AUTH: return cid_auth_config[cid - 1].query; case MBIM_SERVICE_DSS: return cid_dss_config[cid - 1].query; case MBIM_SERVICE_MS_FIRMWARE_ID: return cid_ms_firmware_id_config[cid - 1].query; case MBIM_SERVICE_MS_HOST_SHUTDOWN: return cid_ms_host_shutdown_config[cid - 1].query; case MBIM_SERVICE_MS_SAR: return cid_ms_sar_config[cid - 1].query; case MBIM_SERVICE_PROXY_CONTROL: return cid_proxy_control_config[cid - 1].query; case MBIM_SERVICE_QMI: return cid_qmi_config[cid - 1].query; case MBIM_SERVICE_ATDS: return cid_atds_config[cid - 1].query; case MBIM_SERVICE_INTEL_FIRMWARE_UPDATE: return cid_intel_firmware_update_config[cid - 1].query; case MBIM_SERVICE_QDU: return cid_qdu_config[cid - 1].query; case MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS: return cid_ms_basic_connect_extensions_config[cid - 1].query; case MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS: return cid_ms_uicc_low_level_access_config[cid - 1].query; case MBIM_SERVICE_QUECTEL: return cid_quectel_config[cid - 1].query; case MBIM_SERVICE_INTEL_THERMAL_RF: return cid_intel_thermal_rf_config[cid - 1].query; case MBIM_SERVICE_MS_VOICE_EXTENSIONS: return cid_ms_voice_extensions_config[cid - 1].query; case MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: return cid_intel_mutual_authentication_config[cid - 1].query; case MBIM_SERVICE_INTEL_TOOLS: return cid_intel_tools_config[cid - 1].query; case MBIM_SERVICE_GOOGLE: return cid_google_config[cid - 1].query; case MBIM_SERVICE_FIBOCOM: return cid_fibocom_config[cid - 1].query; case MBIM_SERVICE_INVALID: case MBIM_SERVICE_LAST: default: g_assert_not_reached (); return FALSE; } } gboolean mbim_cid_can_notify (MbimService service, guint cid) { /* CID = 0 is never a valid command */ g_return_val_if_fail (cid > 0, FALSE); /* Known service required */ g_return_val_if_fail (service > MBIM_SERVICE_INVALID, FALSE); g_return_val_if_fail (service < MBIM_SERVICE_LAST, FALSE); switch (service) { case MBIM_SERVICE_BASIC_CONNECT: return cid_basic_connect_config[cid - 1].notify; case MBIM_SERVICE_SMS: return cid_sms_config[cid - 1].notify; case MBIM_SERVICE_USSD: return cid_ussd_config[cid - 1].notify; case MBIM_SERVICE_PHONEBOOK: return cid_phonebook_config[cid - 1].notify; case MBIM_SERVICE_STK: return cid_stk_config[cid - 1].notify; case MBIM_SERVICE_AUTH: return cid_auth_config[cid - 1].notify; case MBIM_SERVICE_DSS: return cid_dss_config[cid - 1].notify; case MBIM_SERVICE_MS_FIRMWARE_ID: return cid_ms_firmware_id_config[cid - 1].notify; case MBIM_SERVICE_MS_HOST_SHUTDOWN: return cid_ms_host_shutdown_config[cid - 1].notify; case MBIM_SERVICE_MS_SAR: return cid_ms_sar_config[cid - 1].notify; case MBIM_SERVICE_PROXY_CONTROL: return cid_proxy_control_config[cid - 1].notify; case MBIM_SERVICE_QMI: return cid_qmi_config[cid - 1].notify; case MBIM_SERVICE_ATDS: return cid_atds_config[cid - 1].notify; case MBIM_SERVICE_INTEL_FIRMWARE_UPDATE: return cid_intel_firmware_update_config[cid - 1].notify; case MBIM_SERVICE_QDU: return cid_qdu_config[cid - 1].notify; case MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS: return cid_ms_basic_connect_extensions_config[cid - 1].notify; case MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS: return cid_ms_uicc_low_level_access_config[cid - 1].notify; case MBIM_SERVICE_QUECTEL: return cid_quectel_config[cid - 1].notify; case MBIM_SERVICE_INTEL_THERMAL_RF: return cid_intel_thermal_rf_config[cid - 1].notify; case MBIM_SERVICE_MS_VOICE_EXTENSIONS: return cid_ms_voice_extensions_config[cid - 1].notify; case MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: return cid_intel_mutual_authentication_config[cid - 1].notify; case MBIM_SERVICE_INTEL_TOOLS: return cid_intel_tools_config[cid - 1].notify; case MBIM_SERVICE_GOOGLE: return cid_google_config[cid - 1].notify; case MBIM_SERVICE_FIBOCOM: return cid_fibocom_config[cid - 1].notify; case MBIM_SERVICE_INVALID: case MBIM_SERVICE_LAST: default: g_assert_not_reached (); return FALSE; } } const gchar * mbim_cid_get_printable (MbimService service, guint cid) { /* CID = 0 is never a valid command */ g_return_val_if_fail (cid > 0, NULL); /* Known service required */ g_return_val_if_fail (service < MBIM_SERVICE_LAST, NULL); switch (service) { case MBIM_SERVICE_INVALID: return "invalid"; case MBIM_SERVICE_BASIC_CONNECT: return mbim_cid_basic_connect_get_string (cid); case MBIM_SERVICE_SMS: return mbim_cid_sms_get_string (cid); case MBIM_SERVICE_USSD: return mbim_cid_ussd_get_string (cid); case MBIM_SERVICE_PHONEBOOK: return mbim_cid_phonebook_get_string (cid); case MBIM_SERVICE_STK: return mbim_cid_stk_get_string (cid); case MBIM_SERVICE_AUTH: return mbim_cid_auth_get_string (cid); case MBIM_SERVICE_DSS: return mbim_cid_dss_get_string (cid); case MBIM_SERVICE_MS_FIRMWARE_ID: return mbim_cid_ms_firmware_id_get_string (cid); case MBIM_SERVICE_MS_HOST_SHUTDOWN: return mbim_cid_ms_host_shutdown_get_string (cid); case MBIM_SERVICE_MS_SAR: return mbim_cid_ms_sar_get_string (cid); case MBIM_SERVICE_PROXY_CONTROL: return mbim_cid_proxy_control_get_string (cid); case MBIM_SERVICE_QMI: return mbim_cid_qmi_get_string (cid); case MBIM_SERVICE_ATDS: return mbim_cid_atds_get_string (cid); case MBIM_SERVICE_INTEL_FIRMWARE_UPDATE: return mbim_cid_intel_firmware_update_get_string (cid); case MBIM_SERVICE_QDU: return mbim_cid_qdu_get_string (cid); case MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS: return mbim_cid_ms_basic_connect_extensions_get_string (cid); case MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS: return mbim_cid_ms_uicc_low_level_access_get_string (cid); case MBIM_SERVICE_QUECTEL: return mbim_cid_quectel_get_string (cid); case MBIM_SERVICE_INTEL_THERMAL_RF: return mbim_cid_intel_thermal_rf_get_string (cid); case MBIM_SERVICE_MS_VOICE_EXTENSIONS: return mbim_cid_ms_voice_extensions_get_string (cid); case MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: return mbim_cid_intel_mutual_authentication_get_string (cid); case MBIM_SERVICE_INTEL_TOOLS: return mbim_cid_intel_tools_get_string (cid); case MBIM_SERVICE_GOOGLE: return mbim_cid_google_get_string (cid); case MBIM_SERVICE_FIBOCOM: return mbim_cid_fibocom_get_string (cid); case MBIM_SERVICE_LAST: default: g_assert_not_reached (); return NULL; } } libmbim-1.31.2-dev/src/libmbim-glib/mbim-cid.h000066400000000000000000000455111453630424100207440ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2018 Aleksander Morgado * Copyright (C) 2022 Intel Corporation */ #ifndef _LIBMBIM_GLIB_MBIM_CID_H_ #define _LIBMBIM_GLIB_MBIM_CID_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif #include #include "mbim-uuid.h" G_BEGIN_DECLS /** * SECTION: mbim-cid * @title: Command IDs * @short_description: Generic command handling routines. * * This section defines the interface of the known command IDs. */ /** * MbimCidBasicConnect: * @MBIM_CID_BASIC_CONNECT_UNKNOWN: Unknown command. * @MBIM_CID_BASIC_CONNECT_DEVICE_CAPS: Device capabilities. * @MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS: Subscriber ready status. * @MBIM_CID_BASIC_CONNECT_RADIO_STATE: Radio state. * @MBIM_CID_BASIC_CONNECT_PIN: PIN. * @MBIM_CID_BASIC_CONNECT_PIN_LIST: PIN list. * @MBIM_CID_BASIC_CONNECT_HOME_PROVIDER: Home provider. * @MBIM_CID_BASIC_CONNECT_PREFERRED_PROVIDERS: Preferred providers. * @MBIM_CID_BASIC_CONNECT_VISIBLE_PROVIDERS: Visible providers. * @MBIM_CID_BASIC_CONNECT_REGISTER_STATE: Register state. * @MBIM_CID_BASIC_CONNECT_PACKET_SERVICE: Packet service. * @MBIM_CID_BASIC_CONNECT_SIGNAL_STATE: Signal state. * @MBIM_CID_BASIC_CONNECT_CONNECT: Connect. * @MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS: Provisioned contexts. * @MBIM_CID_BASIC_CONNECT_SERVICE_ACTIVATION: Service activation. * @MBIM_CID_BASIC_CONNECT_IP_CONFIGURATION: IP configuration. * @MBIM_CID_BASIC_CONNECT_DEVICE_SERVICES: Device services. * @MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBE_LIST: Device service subscribe list. Since 1.8. * @MBIM_CID_BASIC_CONNECT_PACKET_STATISTICS: Packet statistics. * @MBIM_CID_BASIC_CONNECT_NETWORK_IDLE_HINT: Network idle hint. * @MBIM_CID_BASIC_CONNECT_EMERGENCY_MODE: Emergency mode. * @MBIM_CID_BASIC_CONNECT_IP_PACKET_FILTERS: IP packet filters. * @MBIM_CID_BASIC_CONNECT_MULTICARRIER_PROVIDERS: Multicarrier providers. * * MBIM commands in the %MBIM_SERVICE_BASIC_CONNECT service. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CID_BASIC_CONNECT_UNKNOWN = 0, MBIM_CID_BASIC_CONNECT_DEVICE_CAPS = 1, MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS = 2, MBIM_CID_BASIC_CONNECT_RADIO_STATE = 3, MBIM_CID_BASIC_CONNECT_PIN = 4, MBIM_CID_BASIC_CONNECT_PIN_LIST = 5, MBIM_CID_BASIC_CONNECT_HOME_PROVIDER = 6, MBIM_CID_BASIC_CONNECT_PREFERRED_PROVIDERS = 7, MBIM_CID_BASIC_CONNECT_VISIBLE_PROVIDERS = 8, MBIM_CID_BASIC_CONNECT_REGISTER_STATE = 9, MBIM_CID_BASIC_CONNECT_PACKET_SERVICE = 10, MBIM_CID_BASIC_CONNECT_SIGNAL_STATE = 11, MBIM_CID_BASIC_CONNECT_CONNECT = 12, MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS = 13, MBIM_CID_BASIC_CONNECT_SERVICE_ACTIVATION = 14, MBIM_CID_BASIC_CONNECT_IP_CONFIGURATION = 15, MBIM_CID_BASIC_CONNECT_DEVICE_SERVICES = 16, /* 17, 18 reserved */ MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBE_LIST = 19, MBIM_CID_BASIC_CONNECT_PACKET_STATISTICS = 20, MBIM_CID_BASIC_CONNECT_NETWORK_IDLE_HINT = 21, MBIM_CID_BASIC_CONNECT_EMERGENCY_MODE = 22, MBIM_CID_BASIC_CONNECT_IP_PACKET_FILTERS = 23, MBIM_CID_BASIC_CONNECT_MULTICARRIER_PROVIDERS = 24, } MbimCidBasicConnect; /** * MbimCidSms: * @MBIM_CID_SMS_UNKNOWN: Unknown command. * @MBIM_CID_SMS_CONFIGURATION: SMS configuration. * @MBIM_CID_SMS_READ: Read. * @MBIM_CID_SMS_SEND: Send. * @MBIM_CID_SMS_DELETE: Delete. * @MBIM_CID_SMS_MESSAGE_STORE_STATUS: Store message status. * * MBIM commands in the %MBIM_SERVICE_SMS service. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CID_SMS_UNKNOWN = 0, MBIM_CID_SMS_CONFIGURATION = 1, MBIM_CID_SMS_READ = 2, MBIM_CID_SMS_SEND = 3, MBIM_CID_SMS_DELETE = 4, MBIM_CID_SMS_MESSAGE_STORE_STATUS = 5, } MbimCidSms; /** * MbimCidUssd: * @MBIM_CID_USSD_UNKNOWN: Unknown command. Since 1.4. * @MBIM_CID_USSD: USSD operation. * * MBIM commands in the %MBIM_SERVICE_USSD service. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CID_USSD_UNKNOWN = 0, MBIM_CID_USSD = 1, } MbimCidUssd; /** * MbimCidPhonebook: * @MBIM_CID_PHONEBOOK_UNKNOWN: Unknown command. * @MBIM_CID_PHONEBOOK_CONFIGURATION: Configuration. * @MBIM_CID_PHONEBOOK_READ: Read. * @MBIM_CID_PHONEBOOK_DELETE: Delete. * @MBIM_CID_PHONEBOOK_WRITE: Write. * * MBIM commands in the %MBIM_SERVICE_PHONEBOOK service. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CID_PHONEBOOK_UNKNOWN = 0, MBIM_CID_PHONEBOOK_CONFIGURATION = 1, MBIM_CID_PHONEBOOK_READ = 2, MBIM_CID_PHONEBOOK_DELETE = 3, MBIM_CID_PHONEBOOK_WRITE = 4, } MbimCidPhonebook; /** * MbimCidStk: * @MBIM_CID_STK_UNKNOWN: Unknown command. * @MBIM_CID_STK_PAC: PAC. * @MBIM_CID_STK_TERMINAL_RESPONSE: Terminal response. * @MBIM_CID_STK_ENVELOPE: Envelope. * * MBIM commands in the %MBIM_SERVICE_STK service. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CID_STK_UNKNOWN = 0, MBIM_CID_STK_PAC = 1, MBIM_CID_STK_TERMINAL_RESPONSE = 2, MBIM_CID_STK_ENVELOPE = 3, } MbimCidStk; /** * MbimCidAuth: * @MBIM_CID_AUTH_UNKNOWN: Unknow command * @MBIM_CID_AUTH_AKA: AKA. * @MBIM_CID_AUTH_AKAP: AKAP. * @MBIM_CID_AUTH_SIM: SIM. * * MBIM commands in the %MBIM_SERVICE_AUTH service. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CID_AUTH_UNKNOWN = 0, MBIM_CID_AUTH_AKA = 1, MBIM_CID_AUTH_AKAP = 2, MBIM_CID_AUTH_SIM = 3, } MbimCidAuth; /** * MbimCidDss: * @MBIM_CID_DSS_UNKNOWN: Unknown command. * @MBIM_CID_DSS_CONNECT: Connect. * * MBIM commands in the %MBIM_SERVICE_DSS service. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CID_DSS_UNKNOWN = 0, MBIM_CID_DSS_CONNECT = 1 } MbimCidDss; /** * MbimCidMsFirmwareId: * @MBIM_CID_MS_FIRMWARE_ID_UNKNOWN: Unknown command. * @MBIM_CID_MS_FIRMWARE_ID_GET: Get Firmware ID. * * MBIM commands in the %MBIM_SERVICE_MS_FIRMWARE_ID service. * * Since: 1.8 */ typedef enum { /*< since=1.0 >*/ MBIM_CID_MS_FIRMWARE_ID_UNKNOWN = 0, MBIM_CID_MS_FIRMWARE_ID_GET = 1 } MbimCidMsFirmwareId; /** * MbimCidMsHostShutdown: * @MBIM_CID_MS_HOST_SHUTDOWN_UNKNOWN: Unknown command. * @MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY: Notify that the host is shutting down. * * MBIM commands in the %MBIM_SERVICE_MS_HOST_SHUTDOWN service. * * Since: 1.8 */ typedef enum { /*< since=1.8 >*/ MBIM_CID_MS_HOST_SHUTDOWN_UNKNOWN = 0, MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY = 1 } MbimCidMsHostShutdown; /** * MbimCidMsSar: * @MBIM_CID_MS_SAR_UNKNOWN: Unknown command. * @MBIM_CID_MS_SAR_CONFIG: SAR backoff mode and level configuration. * @MBIM_CID_MS_SAR_TRANSMISSION_STATUS: Transmission status indication setup. * * MBIM commands in the %MBIM_SERVICE_MS_SAR service. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_CID_MS_SAR_UNKNOWN = 0, MBIM_CID_MS_SAR_CONFIG = 1, MBIM_CID_MS_SAR_TRANSMISSION_STATUS = 2 } MbimCidMsSar; /** * MbimCidProxyControl: * @MBIM_CID_PROXY_CONTROL_UNKNOWN: Unknown command. * @MBIM_CID_PROXY_CONTROL_CONFIGURATION: Configuration. * @MBIM_CID_PROXY_CONTROL_VERSION: MBIM and MBIMEx Version reporting. * * MBIM commands in the %MBIM_SERVICE_PROXY_CONTROL service. * * Since: 1.10 */ typedef enum { /*< since=1.10 >*/ MBIM_CID_PROXY_CONTROL_UNKNOWN = 0, MBIM_CID_PROXY_CONTROL_CONFIGURATION = 1, MBIM_CID_PROXY_CONTROL_VERSION = 2, } MbimCidProxyControl; /** * MbimCidQmi: * @MBIM_CID_QMI_UNKNOWN: Unknown command. * @MBIM_CID_QMI_MSG: Send QMI request and receive QMI response. * * MBIM commands in the %MBIM_SERVICE_QMI service. * * Since: 1.14 */ typedef enum { /*< since=1.14 >*/ MBIM_CID_QMI_UNKNOWN = 0, MBIM_CID_QMI_MSG = 1 } MbimCidQmi; /** * MbimCidAtds: * @MBIM_CID_ATDS_UNKNOWN: Unknown command. * @MBIM_CID_ATDS_SIGNAL: Radio signal information. * @MBIM_CID_ATDS_LOCATION: Cell location information. * @MBIM_CID_ATDS_OPERATORS: Operator selection. * @MBIM_CID_ATDS_RAT: Radio Access Technology selection. * @MBIM_CID_ATDS_REGISTER_STATE: Registration state. * * MBIM commands in the %MBIM_SERVICE_ATDS service. * * Since: 1.16 */ typedef enum { /*< since=1.16 >*/ MBIM_CID_ATDS_UNKNOWN = 0, MBIM_CID_ATDS_SIGNAL = 1, MBIM_CID_ATDS_LOCATION = 2, MBIM_CID_ATDS_OPERATORS = 3, MBIM_CID_ATDS_RAT = 4, MBIM_CID_ATDS_REGISTER_STATE = 9, } MbimCidAtds; /** * MbimCidIntelFirmwareUpdate: * @MBIM_CID_INTEL_FIRMWARE_UPDATE_UNKNOWN: Unknown command. * @MBIM_CID_INTEL_FIRMWARE_UPDATE_MODEM_REBOOT: Reboot modem for firmware update. * * MBIM commands in the %MBIM_SERVICE_INTEL_FIRMWARE_UPDATE service. * * Since: 1.16 */ typedef enum { /*< since=1.16 >*/ MBIM_CID_INTEL_FIRMWARE_UPDATE_UNKNOWN = 0, MBIM_CID_INTEL_FIRMWARE_UPDATE_MODEM_REBOOT = 1, } MbimCidIntelFirmwareUpdate; /** * MbimCidQdu: * @MBIM_CID_QDU_UNKNOWN: Unknown command. * @MBIM_CID_QDU_UPDATE_SESSION: Update session command. * @MBIM_CID_QDU_FILE_OPEN: Open QDU file for firmware update. * @MBIM_CID_QDU_FILE_WRITE: Write QDU file for firmware update. * @MBIM_CID_QDU_QUECTEL_REBOOT: Reboot to Emergency Download (Quectel specific). Since 1.28. * @MBIM_CID_QDU_QUECTEL_READ_VERSION: Read firmware version (Quectel specific). Since 1.28. * * MBIM commands in the %MBIM_SERVICE_QDU service. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_CID_QDU_UNKNOWN = 0, MBIM_CID_QDU_UPDATE_SESSION = 1, MBIM_CID_QDU_FILE_OPEN = 2, MBIM_CID_QDU_FILE_WRITE = 3, MBIM_CID_QDU_QUECTEL_REBOOT = 4, MBIM_CID_QDU_QUECTEL_READ_VERSION = 7 } MbimCidQdu; /** * MbimCidMsBasicConnectExtensions: * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_UNKNOWN: Unknown command. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PROVISIONED_CONTEXTS: Provisioned contexts (v2). * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_DENYLIST: Network denylist. Since 1.28. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_CONFIGURATION: LTE attach configuration. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_INFO: LTE attach status information. Since 1.26. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_SYS_CAPS: System capabilities. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_CAPS: Device capabilities (v2). * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_SLOT_MAPPINGS: Device slot mappings. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_SLOT_INFO_STATUS: Slot info status. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PCO: Protocol configuration operations (PCO). * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_RESET: Device reset. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_BASE_STATIONS_INFO: Base stations info. Since 1.28. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LOCATION_INFO_STATUS: Location info status. Since 1.28. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_VERSION: Protocol version query and report, defined in MBIMEx v2.0. Since 1.28. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_MODEM_CONFIGURATION: Modem configuration status, defined in MBIMEx v3.0. Since 1.28. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS: Registration parameters, defined in MBIMEx v3.0. Since 1.28. * @MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_WAKE_REASON: Protocol wake reason query and report, defined in MBIMEx v3.0. Since 1.28 * * MBIM commands in the %MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS service. * * Since: 1.18 */ typedef enum { /*< since=1.18 >*/ MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_UNKNOWN = 0, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PROVISIONED_CONTEXTS = 1, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_DENYLIST = 2, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_CONFIGURATION = 3, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_INFO = 4, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_SYS_CAPS = 5, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_CAPS = 6, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_SLOT_MAPPINGS = 7, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_SLOT_INFO_STATUS = 8, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PCO = 9, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_DEVICE_RESET = 10, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_BASE_STATIONS_INFO = 11, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LOCATION_INFO_STATUS = 12, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_VERSION = 15, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_MODEM_CONFIGURATION = 16, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS = 17, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_WAKE_REASON = 19, } MbimCidMsBasicConnectExtensions; /* Command helpers */ /** * MbimCidMsUiccLowLevelAccess: * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_UNKNOWN: Unknown command. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_ATR: ATR. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_OPEN_CHANNEL: Open Channel. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_CLOSE_CHANNEL: Close Channel. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APDU: Apdu. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_TERMINAL_CAPABILITY: Terminal capabilities. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_RESET: Reset. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APPLICATION_LIST: Retrieve application list. Since 1.28. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_FILE_STATUS: Retrieve information about a specific UICC file. Since 1.28. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_BINARY: Read a UICC binary file. Since 1.28. * @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD: Read a UICC linear fixed or cyclic file. Since 1.28. * * MBIM commands in the %MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS service. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_UNKNOWN = 0, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_ATR = 1, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_OPEN_CHANNEL = 2, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_CLOSE_CHANNEL = 3, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APDU = 4, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_TERMINAL_CAPABILITY = 5, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_RESET = 6, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APPLICATION_LIST = 7, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_FILE_STATUS = 8, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_BINARY = 9, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD = 10, } MbimCidMsUiccLowLevelAccess; /** * MbimCidQuectel: * @MBIM_CID_QUECTEL_UNKNOWN: Unknown command. * @MBIM_CID_QUECTEL_RADIO_STATE: Radio state. * * MBIM commands in the %MBIM_SERVICE_QUECTEL service. * * Since: 1.26.2 */ typedef enum { /*< since=1.26.2 >*/ MBIM_CID_QUECTEL_UNKNOWN = 0, MBIM_CID_QUECTEL_RADIO_STATE = 1, } MbimCidQuectel; /** * MbimCidIntelThermalRf: * @MBIM_CID_INTEL_THERMAL_RF_UNKNOWN: Unknown command. * @MBIM_CID_INTEL_THERMAL_RF_RFIM: RFIM frequency command. * * MBIM commands in the %MBIM_SERVICE_INTEL_THERMAL_RF service. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_CID_INTEL_THERMAL_RF_UNKNOWN = 0, MBIM_CID_INTEL_THERMAL_RF_RFIM = 9, } MbimCidIntelThermalRf; /** * MbimCidMsVoiceExtensions: * @MBIM_CID_MS_VOICE_EXTENSIONS_UNKNOWN: Unknown command. * @MBIM_CID_MS_VOICE_EXTENSIONS_NITZ: Network Identity and Time Zone information command. * * MBIM commands in the %MBIM_SERVICE_MS_VOICE_EXTENSIONS service. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_CID_MS_VOICE_EXTENSIONS_UNKNOWN = 0, MBIM_CID_MS_VOICE_EXTENSIONS_NITZ = 10, } MbimCidMsVoiceExtensions; /** * MbimCidIntelMutualAuthentication: * @MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_UNKNOWN: Unknown command. * @MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_FCC_LOCK: FCC lock set. * * MBIM commands in the %MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION service. * * Since: 1.30 */ typedef enum { /*< since=1.30 >*/ MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_UNKNOWN = 0, MBIM_CID_INTEL_MUTUAL_AUTHENTICATION_FCC_LOCK = 1, } MbimCidIntelMutualAuthentication; /** * MbimCidIntelTools: * @MBIM_CID_INTEL_TOOLS_UNKNOWN: Unknown command. * @MBIM_CID_INTEL_TOOLS_TRACE_CONFIG: Configure Modem traces. * * MBIM commands in the %MBIM_SERVICE_INTEL_TOOLS service. * * Since: 1.30 */ typedef enum { /*< since=1.30 >*/ MBIM_CID_INTEL_TOOLS_UNKNOWN = 0, MBIM_CID_INTEL_TOOLS_TRACE_CONFIG = 8, } MbimCidIntelTools; /** * MbimCidGoogle: * @MBIM_CID_GOOGLE_UNKNOWN: Unknown command. * @MBIM_CID_GOOGLE_CARRIER_LOCK: Carrier lock. * * MBIM commands in the %MBIM_SERVICE_GOOGLE service. * * Since: 1.30 */ typedef enum { /*< since=1.30 >*/ MBIM_CID_GOOGLE_UNKNOWN = 0, MBIM_CID_GOOGLE_CARRIER_LOCK = 1, } MbimCidGoogle; /** * MbimCidFibocom: * @MBIM_CID_FIBOCOM_UNKNOWN: Unknown command. * @MBIM_CID_FIBOCOM_AT_COMMAND: AT over MBIM message. * * MBIM commands in the %MBIM_SERVICE_FIBOCOM service. * * Since: 1.32 */ typedef enum { /*< since=1.32 >*/ MBIM_CID_FIBOCOM_UNKNOWN = 0, MBIM_CID_FIBOCOM_AT_COMMAND = 1, } MbimCidFibocom; /** * mbim_cid_can_set: * @service: a #MbimService. * @cid: a command ID. * * Checks whether the given command allows setting. * * Returns: %TRUE if the command allows setting, %FALSE otherwise. * * Since: 1.0 */ gboolean mbim_cid_can_set (MbimService service, guint cid); /** * mbim_cid_can_query: * @service: a #MbimService. * @cid: a command ID. * * Checks whether the given command allows querying. * * Returns: %TRUE if the command allows querying, %FALSE otherwise. * * Since: 1.0 */ gboolean mbim_cid_can_query (MbimService service, guint cid); /** * mbim_cid_can_notify: * @service: a #MbimService. * @cid: a command ID. * * Checks whether the given command allows notifying. * * Returns: %TRUE if the command allows notifying, %FALSE otherwise. * * Since: 1.0 */ gboolean mbim_cid_can_notify (MbimService service, guint cid); /** * mbim_cid_get_printable: * @service: a #MbimService. * @cid: a command ID. * * Gets a printable string for the command specified by the @service and the * @cid. * * Returns: a constant string. * * Since: 1.0 */ const gchar *mbim_cid_get_printable (MbimService service, guint cid); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_CID_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-compat.c000066400000000000000000000072131453630424100214600ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014 Aleksander Morgado */ #include "mbim-compat.h" #ifndef MBIM_DISABLE_DEPRECATED /*****************************************************************************/ /* 'Service Subscriber List' rename to 'Service Subscribe List' */ MbimMessage * mbim_message_device_service_subscriber_list_set_new ( guint32 events_count, const MbimEventEntry *const *events, GError **error) { return (mbim_message_device_service_subscribe_list_set_new ( events_count, events, error)); } gboolean mbim_message_device_service_subscriber_list_response_parse ( const MbimMessage *message, guint32 *events_count, MbimEventEntry ***events, GError **error) { return (mbim_message_device_service_subscribe_list_response_parse ( message, events_count, events, error)); } /*****************************************************************************/ /* 'LTE Attach Status' rename to 'LTE Attach Info', to avoid the unneeded * MbimLteAttachStatus struct */ void mbim_lte_attach_status_free (MbimDeprecatedLteAttachStatus *var) { if (!var) return; g_free (var->access_string); g_free (var->user_name); g_free (var->password); g_free (var); } MbimMessage * mbim_message_ms_basic_connect_extensions_lte_attach_status_query_new (GError **error) { return mbim_message_ms_basic_connect_extensions_lte_attach_info_query_new (error); } gboolean mbim_message_ms_basic_connect_extensions_lte_attach_status_response_parse ( const MbimMessage *message, MbimDeprecatedLteAttachStatus **out_lte_attach_status, GError **error) { g_autoptr(MbimLteAttachStatus) var = NULL; var = g_new0 (MbimDeprecatedLteAttachStatus, 1); if (!mbim_message_ms_basic_connect_extensions_lte_attach_info_response_parse ( message, &var->lte_attach_state, &var->ip_type, &var->access_string, &var->user_name, &var->password, &var->compression, &var->auth_protocol, error)) return FALSE; *out_lte_attach_status = g_steal_pointer (&var); return TRUE; } gboolean mbim_message_ms_basic_connect_extensions_lte_attach_status_notification_parse ( const MbimMessage *message, MbimDeprecatedLteAttachStatus **out_lte_attach_status, GError **error) { g_autoptr(MbimLteAttachStatus) var = NULL; var = g_new0 (MbimDeprecatedLteAttachStatus, 1); if (!mbim_message_ms_basic_connect_extensions_lte_attach_info_notification_parse ( message, &var->lte_attach_state, &var->ip_type, &var->access_string, &var->user_name, &var->password, &var->compression, &var->auth_protocol, error)) return FALSE; *out_lte_attach_status = g_steal_pointer (&var); return TRUE; } /*****************************************************************************/ /* MbimSmsStatusFlag is flags, not an enum */ const gchar * mbim_sms_status_flag_get_string (MbimSmsStatusFlag val) { const gchar *sms_status_flag_values[] = { [MBIM_SMS_STATUS_FLAG_NONE] = "none", [MBIM_SMS_STATUS_FLAG_MESSAGE_STORE_FULL] = "message-store-full", [MBIM_SMS_STATUS_FLAG_NEW_MESSAGE] = "new-message", }; return ((guint)val < G_N_ELEMENTS (sms_status_flag_values)) ? sms_status_flag_values[val] : NULL; } #endif /* MBIM_DISABLE_DEPRECATED */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-compat.h000066400000000000000000000254061453630424100214710ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014-2021 Aleksander Morgado */ #ifndef _LIBMBIM_GLIB_MBIM_COMPAT_H_ #define _LIBMBIM_GLIB_MBIM_COMPAT_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif #include #include "mbim-basic-connect.h" #include "mbim-ms-basic-connect-extensions.h" #include "mbim-cid.h" G_BEGIN_DECLS /** * SECTION: mbim-compat * @title: Deprecated API * @short_description: Types and functions flagged as deprecated. * * This section defines types and functions that have been deprecated. */ #ifndef MBIM_DISABLE_DEPRECATED /*****************************************************************************/ /* Registration flags name fixup */ /* The following type exists just so that we can get deprecation warnings */ G_DEPRECATED typedef int MbimDeprecatedRegistrationFlag; /** * MBIM_REGISTRATION_FLAG_MANUAL_PACKET_SERVICE_AUTOMATIC_ATTACH: * * Modem should auto-attach to the network after registration. * * Since: 1.0 * Deprecated: 1.8: Use MBIM_REGISTRATION_FLAG_PACKET_SERVICE_AUTOMATIC_ATTACH instead. */ #define MBIM_REGISTRATION_FLAG_MANUAL_PACKET_SERVICE_AUTOMATIC_ATTACH (MbimDeprecatedRegistrationFlag) MBIM_REGISTRATION_FLAG_PACKET_SERVICE_AUTOMATIC_ATTACH /*****************************************************************************/ /* 'Service Subscriber List' rename to 'Service Subscribe List' */ /* The following type exists just so that we can get deprecation warnings */ #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wtypedef-redefinition" #endif G_DEPRECATED typedef int MbimDeprecatedCidBasicConnect; #if defined(__clang__) # pragma clang diagnostic pop #endif /** * MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBER_LIST: * * Device service subscribe list. * * Since: 1.0 * Deprecated: 1.8: Use MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBE_LIST instead. */ #define MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBER_LIST (MbimDeprecatedCidBasicConnect) MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBE_LIST /** * mbim_message_device_service_subscriber_list_set_new: * @events_count: the 'EventsCount' field, given as a #guint32. * @events: the 'Events' field, given as an array of #MbimEventEntrys. * @error: return location for error or %NULL. * * Create a new request for the 'Device Service Subscribe List' set command in the 'Basic Connect' service. * * Returns: a newly allocated #MbimMessage, which should be freed with mbim_message_unref(). * * Since: 1.0 * Deprecated: 1.8: Use mbim_message_device_service_subscribe_list_set_new() instead. */ G_DEPRECATED_FOR (mbim_message_device_service_subscribe_list_set_new) MbimMessage *mbim_message_device_service_subscriber_list_set_new ( guint32 events_count, const MbimEventEntry *const *events, GError **error); /** * mbim_message_device_service_subscriber_list_response_parse: * @message: the #MbimMessage. * @events_count: return location for a #guint32, or %NULL if the 'EventsCount' field is not needed. * @events: return location for a newly allocated array of #MbimEventEntrys, or %NULL if the 'Events' field is not needed. Free the returned value with mbim_event_entry_array_free(). * @error: return location for error or %NULL. * * Create a new request for the 'Events' response command in the 'Basic Connect' service. * * Returns: %TRUE if the message was correctly parsed, %FALSE if @error is set. * * Since: 1.0 * Deprecated: 1.8: Use mbim_message_device_service_subscribe_list_response_parse() instead. */ G_DEPRECATED_FOR (mbim_message_device_service_subscribe_list_response_parse) gboolean mbim_message_device_service_subscriber_list_response_parse ( const MbimMessage *message, guint32 *events_count, MbimEventEntry ***events, GError **error); /*****************************************************************************/ /* 'LTE Attach Status' rename to 'LTE Attach Info', to avoid the unneeded * MbimLteAttachStatus struct */ /* The following type exists just so that we can get deprecation warnings */ #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wtypedef-redefinition" #endif G_DEPRECATED typedef int MbimDeprecatedCidMsBasicConnectExtensions; #if defined(__clang__) # pragma clang diagnostic pop #endif /** * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_STATUS: * * LTE attach info. * * Since: 1.18 * Deprecated: 1.26: Use MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_INFO instead. */ #define MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_STATUS (MbimDeprecatedCidMsBasicConnectExtensions)MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_LTE_ATTACH_INFO /** * MbimLteAttachStatus: * @lte_attach_state: a #guint32. * @ip_type: a #guint32. * @access_string: a string. * @user_name: a string. * @password: a string. * @compression: a #guint32. * @auth_protocol: a #guint32. * * LTE attach status information. * * Since: 1.18 * Deprecated: 1.26 */ /* The following type exists just so that we don't getdeprecation warnings on * our own methods */ typedef struct { guint32 lte_attach_state; guint32 ip_type; gchar *access_string; gchar *user_name; gchar *password; guint32 compression; guint32 auth_protocol; } MbimDeprecatedLteAttachStatus; G_DEPRECATED typedef MbimDeprecatedLteAttachStatus MbimLteAttachStatus; /** * mbim_lte_attach_status_free: * @var: a #MbimLteAttachStatus. * * Frees the memory allocated for the #MbimLteAttachStatus. * * Since: 1.18 * Deprecated: 1.26 */ G_DEPRECATED void mbim_lte_attach_status_free (MbimDeprecatedLteAttachStatus *var); #if defined(__clang__) || defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimLteAttachStatus, mbim_lte_attach_status_free) #if defined(__clang__) || defined (__GNUC__) # pragma GCC diagnostic pop #endif /** * mbim_message_ms_basic_connect_extensions_lte_attach_status_query_new: * @error: return location for error or %NULL. * * Create a new request for the 'Lte Attach Status' query command in the 'Ms Basic Connect Extensions' service. * * Returns: a newly allocated #MbimMessage, which should be freed with mbim_message_unref(). * * Since: 1.18 * Deprecated: 1.26: Use mbim_message_ms_basic_connect_extensions_lte_attach_info_query_new() instead. */ G_DEPRECATED_FOR (mbim_message_ms_basic_connect_extensions_lte_attach_info_query_new) MbimMessage *mbim_message_ms_basic_connect_extensions_lte_attach_status_query_new ( GError **error); /** * mbim_message_ms_basic_connect_extensions_lte_attach_status_response_parse: * @message: the #MbimMessage. * @out_lte_attach_status: (out)(optional)(transfer full): return location for a newly allocated #MbimLteAttachStatus, or %NULL if the 'LteAttachStatus' field is not needed. Free the returned value with mbim_lte_attach_status_free(). * @error: return location for error or %NULL. * * Parses and returns parameters of the 'Lte Attach Status' response command in the 'Ms Basic Connect Extensions' service. * * Returns: %TRUE if the message was correctly parsed, %FALSE if @error is set. * * Since: 1.18 * Deprecated: 1.26: Use mbim_message_ms_basic_connect_extensions_lte_attach_info_response_parse() instead. */ G_DEPRECATED_FOR (mbim_message_ms_basic_connect_extensions_lte_attach_info_response_parse) gboolean mbim_message_ms_basic_connect_extensions_lte_attach_status_response_parse ( const MbimMessage *message, MbimDeprecatedLteAttachStatus **out_lte_attach_status, GError **error); /** * mbim_message_ms_basic_connect_extensions_lte_attach_status_notification_parse: * @message: the #MbimMessage. * @out_lte_attach_status: (out)(optional)(transfer full): return location for a newly allocated #MbimLteAttachStatus, or %NULL if the 'LteAttachStatus' field is not needed. Free the returned value with mbim_lte_attach_status_free(). * @error: return location for error or %NULL. * * Parses and returns parameters of the 'Lte Attach Status' notification command in the 'Ms Basic Connect Extensions' service. * * Returns: %TRUE if the message was correctly parsed, %FALSE if @error is set. * * Since: 1.18 * Deprecated: 1.26: Use mbim_message_ms_basic_connect_extensions_lte_attach_info_notification_parse() instead. */ G_DEPRECATED_FOR (mbim_message_ms_basic_connect_extensions_lte_attach_info_notification_parse) gboolean mbim_message_ms_basic_connect_extensions_lte_attach_status_notification_parse ( const MbimMessage *message, MbimDeprecatedLteAttachStatus **out_lte_attach_status, GError **error); /*****************************************************************************/ /* Network errors fixup */ /* The following type exists just so that we can get deprecation warnings */ #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wtypedef-redefinition" #endif G_DEPRECATED typedef int MbimDeprecatedNwError; #if defined(__clang__) # pragma clang diagnostic pop #endif /** * MBIM_NW_ERROR_UNKNOWN: * * Network error not set. * * Since: 1.0 * Deprecated: 1.28: Use %MBIM_NW_ERROR_NONE instead. */ #define MBIM_NW_ERROR_UNKNOWN (MbimDeprecatedNwError) MBIM_NW_ERROR_NONE /*****************************************************************************/ /* Rename blacklist to denylist */ /* The following type exists just so that we can get deprecation warnings */ #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wtypedef-redefinition" #endif G_DEPRECATED typedef int MbimDeprecatedCidMsBasicConnectExtensions; #if defined(__clang__) # pragma clang diagnostic pop #endif /** * MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_BLACKLIST: * * Network deny list. * * Since: 1.18 * Deprecated: 1.28: Use MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_DENYLIST instead. */ #define MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_BLACKLIST (MbimDeprecatedCidMsBasicConnectExtensions) MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_NETWORK_DENYLIST /*****************************************************************************/ /* MbimSmsStatusFlag is flags, not an enum */ /** * mbim_sms_status_flag_get_string: * @val: a MbimSmsStatusFlag. * * Gets the nickname string for the #MbimSmsStatusFlag specified at @val. * * Returns: (transfer none): a string with the nickname, or %NULL if not found. Do not free the returned value. * * Since: 1.4 * Deprecated: 1.30: Use mbim_sms_status_flag_build_string_from_mask() instead. */ G_DEPRECATED_FOR (mbim_sms_status_flag_build_string_from_mask) const gchar *mbim_sms_status_flag_get_string (MbimSmsStatusFlag val); #endif /* MBIM_DISABLE_DEPRECATED */ G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_COMPAT_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-device.c000066400000000000000000003064131453630424100214400ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013-2021 Aleksander Morgado * Copyright (C) 2014 Smith Micro Software, Inc. * Copyright (C) 2021 Intel Corporation * * Implementation based on the 'QmiDevice' GObject from libqmi-glib. */ #include #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #define IOCTL_WDM_MAX_COMMAND _IOR('H', 0xA0, guint16) #define OPEN_RETRY_TIMEOUT_SECS 5 #define OPEN_CLOSE_TIMEOUT_SECS 2 #include "mbim-common.h" #include "mbim-utils.h" #include "mbim-device.h" #include "mbim-message.h" #include "mbim-message-private.h" #include "mbim-error-types.h" #include "mbim-enum-types.h" #include "mbim-helpers.h" #include "mbim-proxy.h" #include "mbim-proxy-control.h" #include "mbim-net-port-manager.h" #include "mbim-net-port-manager-wdm.h" #include "mbim-net-port-manager-wwan.h" #include "mbim-basic-connect.h" #include "mbim-ms-basic-connect-extensions.h" /* maximum number of printed data bytes when personal info * should be hidden */ #define MAX_PRINTED_BYTES 12 static void async_initable_iface_init (GAsyncInitableIface *iface); G_DEFINE_TYPE_EXTENDED (MbimDevice, mbim_device, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)) enum { PROP_0, PROP_FILE, PROP_TRANSACTION_ID, PROP_IN_SESSION, PROP_CONSECUTIVE_TIMEOUTS, PROP_LAST }; static GParamSpec *properties[PROP_LAST]; enum { SIGNAL_INDICATE_STATUS, SIGNAL_ERROR, SIGNAL_REMOVED, SIGNAL_LAST }; static guint signals[SIGNAL_LAST] = { 0 }; typedef enum { TRANSACTION_TYPE_UNKNOWN = -1, TRANSACTION_TYPE_HOST = 0, TRANSACTION_TYPE_MODEM = 1, TRANSACTION_TYPE_LAST = 2 } TransactionType; typedef enum { OPEN_STATUS_CLOSED = 0, OPEN_STATUS_OPENING = 1, OPEN_STATUS_OPEN = 2 } OpenStatus; struct _MbimDevicePrivate { /* File */ GFile *file; gchar *path; gchar *path_display; /* WWAN interface */ gchar *wwan_iface; /* I/O channel, set when the file is open */ GIOChannel *iochannel; GSource *iochannel_source; GByteArray *response; OpenStatus open_status; guint32 open_transaction_id; GError *pending_error_indication; /* Support for mbim-proxy */ GSocketClient *socket_client; GSocketConnection *socket_connection; /* HT to keep track of ongoing host/function transactions * Host transactions: created by us * Modem transactions: modem-created indications with multiple fragments */ GHashTable *transactions[TRANSACTION_TYPE_LAST]; /* Transaction ID in the device */ guint32 transaction_id; /* Flag to specify whether we're in a session */ gboolean in_session; /* message size */ guint16 max_control_transfer; /* MBIM extensions major and minor versions agreed with the device */ guint8 ms_mbimex_version_major; guint8 ms_mbimex_version_minor; /* Link management */ MbimNetPortManager *net_port_manager; /* Number of consecutive timeouts detected */ guint consecutive_timeouts; }; #define MAX_SPAWN_RETRIES 10 #define MAX_CONTROL_TRANSFER 4096 #define MAX_TIME_BETWEEN_FRAGMENTS_MS 1250 static void device_report_error (MbimDevice *self, guint32 transaction_id, const GError *error); /*****************************************************************************/ /* Message transactions (private) */ typedef struct { MbimDevice *self; guint32 transaction_id; TransactionType type; } TransactionWaitContext; typedef struct { MbimMessage *fragments; MbimMessageType type; guint32 transaction_id; GSource *timeout_source; GCancellable *cancellable; gulong cancellable_id; TransactionWaitContext *wait_ctx; } TransactionContext; static void transaction_context_free (TransactionContext *ctx) { if (ctx->fragments) mbim_message_unref (ctx->fragments); if (ctx->timeout_source) { if (!g_source_is_destroyed (ctx->timeout_source)) g_source_destroy (ctx->timeout_source); g_source_unref (ctx->timeout_source); } if (ctx->cancellable) { if (ctx->cancellable_id) g_cancellable_disconnect (ctx->cancellable, ctx->cancellable_id); g_object_unref (ctx->cancellable); } if (ctx->wait_ctx) g_slice_free (TransactionWaitContext, ctx->wait_ctx); g_slice_free (TransactionContext, ctx); } /* #define TRACE_TRANSACTION 1 */ #ifdef TRACE_TRANSACTION static void transaction_task_trace (GTask *task, const gchar *state) { MbimDevice *self; TransactionContext *ctx; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); g_debug ("[%s,%u] transaction %s: %s", self->priv->path_display, ctx->transaction_id, mbim_message_type_get_string (ctx->type), state); } #else # define transaction_task_trace(...) #endif static GTask * transaction_task_new (MbimDevice *self, MbimMessageType type, guint32 transaction_id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; TransactionContext *ctx; task = g_task_new (self, cancellable, callback, user_data); ctx = g_slice_new0 (TransactionContext); ctx->type = type; ctx->transaction_id = transaction_id; ctx->cancellable = (cancellable ? g_object_ref (cancellable) : NULL); g_task_set_task_data (task, ctx, (GDestroyNotify) transaction_context_free); transaction_task_trace (task, "new"); return task; } static void transaction_task_complete_and_free (GTask *task, const GError *error) { TransactionContext *ctx; MbimDevice *self; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); if (error) { /* Increase number of consecutive timeouts */ if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_TIMEOUT) || g_error_matches (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_TIMEOUT_FRAGMENT)) { self->priv->consecutive_timeouts++; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CONSECUTIVE_TIMEOUTS]); g_debug ("[%s] number of consecutive timeouts: %u", self->priv->path_display, self->priv->consecutive_timeouts); } transaction_task_trace (task, "complete: error"); g_task_return_error (task, g_error_copy (error)); } else { /* Reset number of consecutive timeouts */ if (self->priv->consecutive_timeouts > 0) { g_debug ("[%s] reseted number of consecutive timeouts", self->priv->path_display); self->priv->consecutive_timeouts = 0; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CONSECUTIVE_TIMEOUTS]); } transaction_task_trace (task, "complete: response"); g_assert (ctx->fragments != NULL); g_task_return_pointer (task, mbim_message_ref (ctx->fragments), (GDestroyNotify) mbim_message_unref); } g_object_unref (task); } static GTask * device_release_transaction (MbimDevice *self, TransactionType type, MbimMessageType expected_type, guint32 transaction_id) { GTask *task; TransactionContext *ctx; g_assert ((type != TRANSACTION_TYPE_UNKNOWN) && (type < TRANSACTION_TYPE_LAST)); /* Only return transaction if it was released from the HT */ if (!self->priv->transactions[type]) return NULL; task = g_hash_table_lookup (self->priv->transactions[type], GUINT_TO_POINTER (transaction_id)); if (!task) return NULL; ctx = g_task_get_task_data (task); if ((ctx->type == expected_type) || (expected_type == MBIM_MESSAGE_TYPE_INVALID)) { /* If found, remove it from the HT */ transaction_task_trace (task, "release"); g_hash_table_remove (self->priv->transactions[type], GUINT_TO_POINTER (transaction_id)); return task; } return NULL; } static gboolean transaction_timed_out (TransactionWaitContext *wait_ctx) { GTask *task; TransactionContext *ctx; g_autoptr(GError) error = NULL; task = device_release_transaction (wait_ctx->self, wait_ctx->type, MBIM_MESSAGE_TYPE_INVALID, wait_ctx->transaction_id); if (!task) /* transaction already completed */ return FALSE; ctx = g_task_get_task_data (task); ctx->timeout_source = NULL; /* If no fragment was received, complete transaction with a timeout error */ if (!ctx->fragments) { error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_TIMEOUT, "Transaction timed out"); } else { /* Fragment timeout... */ error = g_error_new (MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_TIMEOUT_FRAGMENT, "Fragment timed out"); /* Also notify to the modem */ device_report_error (wait_ctx->self, wait_ctx->transaction_id, error); } transaction_task_complete_and_free (task, error); return G_SOURCE_REMOVE; } static void transaction_cancelled (GCancellable *cancellable, TransactionWaitContext *wait_ctx) { GTask *task; TransactionContext *ctx; g_autoptr(GError) error = NULL; task = device_release_transaction (wait_ctx->self, wait_ctx->type, MBIM_MESSAGE_TYPE_INVALID, wait_ctx->transaction_id); /* The transaction may have already been cancelled before we stored it in * the tracking table */ if (!task) return; ctx = g_task_get_task_data (task); ctx->cancellable_id = 0; /* Complete transaction with an abort error */ error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_ABORTED, "Transaction aborted"); transaction_task_complete_and_free (task, error); } static gboolean device_store_transaction (MbimDevice *self, TransactionType type, GTask *task, guint timeout_ms, GError **error) { TransactionContext *ctx; g_assert ((type != TRANSACTION_TYPE_UNKNOWN) && (type < TRANSACTION_TYPE_LAST)); transaction_task_trace (task, "store"); if (G_UNLIKELY (!self->priv->transactions[type])) self->priv->transactions[type] = g_hash_table_new (g_direct_hash, g_direct_equal); ctx = g_task_get_task_data (task); /* When storing the transaction in the device, we have two options: either this * is a completely new transaction, or this is a transaction that had already been * previously stored (e.g. when waiting for more fragments). In the latter case, * make sure we don't reset the wait context or the timeout. */ /* don't add timeout and setup wait context if one already exists */ if (!ctx->timeout_source) { g_assert (!ctx->wait_ctx); ctx->wait_ctx = g_slice_new (TransactionWaitContext); ctx->wait_ctx->self = self; ctx->wait_ctx->transaction_id = ctx->transaction_id; ctx->wait_ctx->type = type; ctx->timeout_source = g_timeout_source_new (timeout_ms); g_source_set_callback (ctx->timeout_source, (GSourceFunc)transaction_timed_out, ctx->wait_ctx, NULL); g_source_attach (ctx->timeout_source, g_main_context_get_thread_default ()); } /* Indication transactions don't have cancellable */ if (ctx->cancellable && !ctx->cancellable_id) { /* Note: transaction_cancelled() will also be called directly if the * cancellable is already cancelled */ ctx->cancellable_id = g_cancellable_connect (ctx->cancellable, (GCallback)transaction_cancelled, ctx->wait_ctx, NULL); if (!ctx->cancellable_id) { g_set_error_literal (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_ABORTED, "Request is already cancelled"); return FALSE; } } /* Keep in the HT */ g_hash_table_insert (self->priv->transactions[type], GUINT_TO_POINTER (ctx->transaction_id), task); return TRUE; } /*****************************************************************************/ GFile * mbim_device_get_file (MbimDevice *self) { GFile *file = NULL; g_return_val_if_fail (MBIM_IS_DEVICE (self), NULL); g_object_get (G_OBJECT (self), MBIM_DEVICE_FILE, &file, NULL); return file; } GFile * mbim_device_peek_file (MbimDevice *self) { g_return_val_if_fail (MBIM_IS_DEVICE (self), NULL); return self->priv->file; } const gchar * mbim_device_get_path (MbimDevice *self) { g_return_val_if_fail (MBIM_IS_DEVICE (self), NULL); return self->priv->path; } const gchar * mbim_device_get_path_display (MbimDevice *self) { g_return_val_if_fail (MBIM_IS_DEVICE (self), NULL); return self->priv->path_display; } gboolean mbim_device_is_open (MbimDevice *self) { g_return_val_if_fail (MBIM_IS_DEVICE (self), FALSE); return (self->priv->open_status == OPEN_STATUS_OPEN); } guint8 mbim_device_get_ms_mbimex_version (MbimDevice *self, guint8 *out_ms_mbimex_version_minor) { g_return_val_if_fail (MBIM_IS_DEVICE (self), 0); if (out_ms_mbimex_version_minor) *out_ms_mbimex_version_minor = self->priv->ms_mbimex_version_minor; return self->priv->ms_mbimex_version_major; } gboolean mbim_device_set_ms_mbimex_version (MbimDevice *self, guint8 ms_mbimex_version_major, guint8 ms_mbimex_version_minor, GError **error) { g_return_val_if_fail (MBIM_IS_DEVICE (self), FALSE); /* no checks that may make this method fail for now */ self->priv->ms_mbimex_version_major = ms_mbimex_version_major; self->priv->ms_mbimex_version_minor = ms_mbimex_version_minor; return TRUE; } gboolean mbim_device_check_ms_mbimex_version (MbimDevice *self, guint8 ms_mbimex_version_major, guint8 ms_mbimex_version_minor) { g_return_val_if_fail (MBIM_IS_DEVICE (self), FALSE); return ((self->priv->ms_mbimex_version_major > ms_mbimex_version_major) || ((self->priv->ms_mbimex_version_major == ms_mbimex_version_major) && (self->priv->ms_mbimex_version_minor >= ms_mbimex_version_minor))); } guint mbim_device_get_consecutive_timeouts (MbimDevice *self) { g_return_val_if_fail (MBIM_IS_DEVICE (self), 0); return self->priv->consecutive_timeouts; } /*****************************************************************************/ static void reload_wwan_iface_name (MbimDevice *self) { g_autofree gchar *cdc_wdm_device_name = NULL; guint i; g_autoptr(GError) error = NULL; static const gchar *driver_names[] = { "usbmisc", /* kernel >= 3.6 */ "usb" }; /* kernel < 3.6 */ g_clear_pointer (&self->priv->wwan_iface, g_free); cdc_wdm_device_name = mbim_helpers_get_devname (self->priv->path, &error); if (!cdc_wdm_device_name) { g_warning ("[%s] invalid path for cdc-wdm control port: %s", self->priv->path_display, error->message); return; } for (i = 0; i < G_N_ELEMENTS (driver_names) && !self->priv->wwan_iface; i++) { g_autofree gchar *sysfs_path = NULL; g_autoptr(GFile) sysfs_file = NULL; g_autoptr(GFileEnumerator) enumerator = NULL; GFileInfo *file_info = NULL; /* WWAN iface name loading only applicable for cdc_mbim driver right now * (so MBIM port exposed by the cdc-wdm driver in the usbmisc subsystem), * not for any other subsystem or driver */ sysfs_path = g_strdup_printf ("/sys/class/%s/%s/device/net/", driver_names[i], cdc_wdm_device_name); sysfs_file = g_file_new_for_path (sysfs_path); enumerator = g_file_enumerate_children (sysfs_file, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (!enumerator) continue; /* Ignore errors when enumerating */ while ((file_info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL) { const gchar *name; name = g_file_info_get_name (file_info); if (name) { /* We only expect ONE file in the sysfs directory corresponding * to this control port, if more found for any reason, warn about it */ if (self->priv->wwan_iface) g_warning ("[%s] invalid additional wwan iface found: %s", self->priv->path_display, name); else self->priv->wwan_iface = g_strdup (name); } g_object_unref (file_info); } if (!self->priv->wwan_iface) g_warning ("[%s] wwan iface not found", self->priv->path_display); } /* wwan_iface won't be set at this point if the kernel driver in use isn't in * the usbmisc subsystem */ } static gboolean setup_net_port_manager (MbimDevice *self, GError **error) { /* If we have a valid one already, use that one */ if (self->priv->net_port_manager) return TRUE; reload_wwan_iface_name (self); if (!self->priv->wwan_iface) /* If wwan_iface is not set wwan subsystem is probably in use */ self->priv->net_port_manager = MBIM_NET_PORT_MANAGER (mbim_net_port_manager_wwan_new (error)); else self->priv->net_port_manager = MBIM_NET_PORT_MANAGER (mbim_net_port_manager_wdm_new (self->priv->wwan_iface, error)); return !!self->priv->net_port_manager; } /*****************************************************************************/ /* Link management */ typedef struct { guint session_id; gchar *ifname; } AddLinkResult; static void add_link_result_free (AddLinkResult *ctx) { g_free (ctx->ifname); g_free (ctx); } gchar * mbim_device_add_link_finish (MbimDevice *self, GAsyncResult *res, guint *session_id, GError **error) { AddLinkResult *ctx; gchar *ifname; ctx = g_task_propagate_pointer (G_TASK (res), error); if (!ctx) return NULL; if (session_id) *session_id = ctx->session_id; ifname = g_steal_pointer (&ctx->ifname); add_link_result_free (ctx); return ifname; } static void device_add_link_ready (MbimNetPortManager *net_port_manager, GAsyncResult *res, GTask *task) { GError *error = NULL; AddLinkResult *ctx; ctx = g_new0 (AddLinkResult, 1); ctx->ifname = mbim_net_port_manager_add_link_finish (net_port_manager, &ctx->session_id, res, &error); if (!ctx->ifname) { g_prefix_error (&error, "Could not allocate link: "); g_task_return_error (task, error); add_link_result_free (ctx); } else g_task_return_pointer (task, ctx, (GDestroyNotify) add_link_result_free); g_object_unref (task); } void mbim_device_add_link (MbimDevice *self, guint session_id, const gchar *base_ifname, const gchar *ifname_prefix, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; GError *error = NULL; g_return_if_fail (MBIM_IS_DEVICE (self)); g_return_if_fail (base_ifname); g_return_if_fail ((session_id <= MBIM_DEVICE_SESSION_ID_MAX) || (session_id == MBIM_DEVICE_SESSION_ID_AUTOMATIC)); task = g_task_new (self, cancellable, callback, user_data); if (!setup_net_port_manager (self, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } g_assert (self->priv->net_port_manager); mbim_net_port_manager_add_link (self->priv->net_port_manager, session_id, base_ifname, ifname_prefix, 5, cancellable, (GAsyncReadyCallback) device_add_link_ready, task); } gboolean mbim_device_delete_link_finish (MbimDevice *self, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void device_del_link_ready (MbimNetPortManager *net_port_manager, GAsyncResult *res, GTask *task) { GError *error = NULL; if (!mbim_net_port_manager_del_link_finish (net_port_manager, res, &error)) g_task_return_error (task, error); else g_task_return_boolean (task, TRUE); g_object_unref (task); } void mbim_device_delete_link (MbimDevice *self, const gchar *ifname, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; GError *error = NULL; g_return_if_fail (MBIM_IS_DEVICE (self)); g_return_if_fail (ifname); task = g_task_new (self, cancellable, callback, user_data); if (!setup_net_port_manager (self, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } g_assert (self->priv->net_port_manager); mbim_net_port_manager_del_link (self->priv->net_port_manager, ifname, 5, /* timeout */ cancellable, (GAsyncReadyCallback) device_del_link_ready, task); } /*****************************************************************************/ gboolean mbim_device_delete_all_links_finish (MbimDevice *self, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void device_del_all_links_ready (MbimNetPortManager *net_port_manager, GAsyncResult *res, GTask *task) { GError *error = NULL; if (!mbim_net_port_manager_del_all_links_finish (net_port_manager, res, &error)) g_task_return_error (task, error); else g_task_return_boolean (task, TRUE); g_object_unref (task); } void mbim_device_delete_all_links (MbimDevice *self, const gchar *base_ifname, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; GError *error = NULL; g_return_if_fail (MBIM_IS_DEVICE (self)); g_return_if_fail (base_ifname); task = g_task_new (self, cancellable, callback, user_data); if (!setup_net_port_manager (self, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } g_assert (self->priv->net_port_manager); mbim_net_port_manager_del_all_links (self->priv->net_port_manager, base_ifname, cancellable, (GAsyncReadyCallback) device_del_all_links_ready, task); } /*****************************************************************************/ gboolean mbim_device_list_links (MbimDevice *self, const gchar *base_ifname, GPtrArray **out_links, GError **error) { g_return_val_if_fail (MBIM_IS_DEVICE (self), FALSE); g_return_val_if_fail (base_ifname, FALSE); if (!setup_net_port_manager (self, error)) return FALSE; g_assert (self->priv->net_port_manager); return mbim_net_port_manager_list_links (self->priv->net_port_manager, base_ifname, out_links, error); } /*****************************************************************************/ gboolean mbim_device_check_link_supported (MbimDevice *self, GError **error) { g_return_val_if_fail (MBIM_IS_DEVICE (self), FALSE); /* if we can setup a net port manager, link management is supported */ return setup_net_port_manager (self, error); } /*****************************************************************************/ /* Open device */ static void indication_ready (MbimDevice *self, GAsyncResult *res) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) indication = NULL; if (!(indication = g_task_propagate_pointer (G_TASK (res), &error))) { g_debug ("[%s] error processing indication message: %s", self->priv->path_display, error->message); return; } /* Indications in the internal proxy control service are not emitted as * signals, they're consumed internally */ { guint16 mbim_version; guint16 ms_mbimex_version; if ((mbim_message_indicate_status_get_service (indication) == MBIM_SERVICE_PROXY_CONTROL) && (mbim_message_indicate_status_get_cid (indication) == MBIM_CID_PROXY_CONTROL_VERSION) && mbim_message_proxy_control_version_notification_parse (indication, &mbim_version, &ms_mbimex_version, NULL)) { self->priv->ms_mbimex_version_major = (ms_mbimex_version >> 8) & 0xFF; self->priv->ms_mbimex_version_minor = ms_mbimex_version & 0xFF; g_debug ("[%s] version information update reported: version %x.%02x, extended version %x.%02x", self->priv->path_display, (mbim_version >> 8) & 0xFF, mbim_version & 0xFF, self->priv->ms_mbimex_version_major, self->priv->ms_mbimex_version_minor); return; } } g_signal_emit (self, signals[SIGNAL_INDICATE_STATUS], 0, indication); } static void finalize_pending_open_request (MbimDevice *self) { GTask *task; g_autoptr(GError) error = NULL; if (!self->priv->open_transaction_id) return; /* Grab transaction. This is a _DONE message, so look for the request * that generated the _DONE */ task = device_release_transaction (self, TRANSACTION_TYPE_HOST, MBIM_MESSAGE_TYPE_OPEN, self->priv->open_transaction_id); /* If there is a valid open_transaction_id, there must be a valid transaction */ g_assert (task); /* Clear right away before completing the transaction */ self->priv->open_transaction_id = 0; error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNKNOWN_STATE, "device state is unknown"); transaction_task_complete_and_free (task, error); } static void process_message (MbimDevice *self, const MbimMessage *message) { gboolean is_partial_fragment; is_partial_fragment = (_mbim_message_is_fragment (message) && _mbim_message_fragment_get_total (message) > 1); if (mbim_utils_get_traces_enabled ()) { g_autofree gchar *printable = NULL; if (mbim_utils_get_show_personal_info () || (((GByteArray *)message)->len < MAX_PRINTED_BYTES)) { printable = mbim_common_str_hex (((GByteArray *)message)->data, ((GByteArray *)message)->len, ':'); } else { g_autofree gchar *tmp = NULL; tmp = mbim_common_str_hex (((GByteArray *)message)->data, MAX_PRINTED_BYTES, ':'); printable = g_strdup_printf ("%s...", tmp); } g_debug ("[%s] received message...%s\n" ">>>>>> RAW:\n" ">>>>>> length = %u\n" ">>>>>> data = %s\n", self->priv->path_display, is_partial_fragment ? " (partial fragment)" : "", ((GByteArray *)message)->len, printable); if (is_partial_fragment) { g_autofree gchar *translated = NULL; translated = mbim_message_get_printable_full (message, self->priv->ms_mbimex_version_major, self->priv->ms_mbimex_version_minor, ">>>>>> ", TRUE, NULL); g_debug ("[%s] received message fragment (translated)...\n%s", self->priv->path_display, translated); } } switch (MBIM_MESSAGE_GET_MESSAGE_TYPE (message)) { case MBIM_MESSAGE_TYPE_OPEN_DONE: case MBIM_MESSAGE_TYPE_CLOSE_DONE: case MBIM_MESSAGE_TYPE_COMMAND_DONE: case MBIM_MESSAGE_TYPE_INDICATE_STATUS: { g_autoptr(GError) error = NULL; GTask *task; TransactionContext *ctx; TransactionType transaction_type = TRANSACTION_TYPE_UNKNOWN; if (MBIM_MESSAGE_GET_MESSAGE_TYPE (message) == MBIM_MESSAGE_TYPE_INDICATE_STATUS) { /* Grab transaction */ transaction_type = TRANSACTION_TYPE_MODEM; task = device_release_transaction (self, transaction_type, MBIM_MESSAGE_TYPE_INDICATE_STATUS, mbim_message_get_transaction_id (message)); if (!task) /* Create new transaction for the indication */ task = transaction_task_new (self, MBIM_MESSAGE_TYPE_INDICATE_STATUS, mbim_message_get_transaction_id (message), NULL, /* no cancellable */ (GAsyncReadyCallback) indication_ready, NULL); } else { /* Grab transaction. This is a _DONE message, so look for the request * that generated the _DONE */ transaction_type = TRANSACTION_TYPE_HOST; task = device_release_transaction (self, transaction_type, (MBIM_MESSAGE_GET_MESSAGE_TYPE (message) - 0x80000000), mbim_message_get_transaction_id (message)); if (!task) { g_debug ("[%s] no transaction matched in received message", self->priv->path_display); /* Attempt to print a user friendly dump of the packet anyway */ if (mbim_utils_get_traces_enabled ()) { g_autofree gchar *printable = NULL; printable = mbim_message_get_printable_full (message, self->priv->ms_mbimex_version_major, self->priv->ms_mbimex_version_minor, ">>>>>> ", is_partial_fragment, NULL); if (printable) g_debug ("[%s] received unexpected message (translated)...\n%s", self->priv->path_display, printable); } /* If we're opening and we get a CLOSE_DONE message without any * matched transaction, finalize the open request right away to * trigger a close before open */ if (self->priv->open_status == OPEN_STATUS_OPENING && MBIM_MESSAGE_GET_MESSAGE_TYPE (message) == MBIM_MESSAGE_TYPE_CLOSE_DONE) finalize_pending_open_request (self); return; } /* If the message doesn't have fragments, we're done */ if (!_mbim_message_is_fragment (message)) { ctx = g_task_get_task_data (task); g_assert (ctx->fragments == NULL); ctx->fragments = mbim_message_dup (message); transaction_task_complete_and_free (task, NULL); return; } } /* More than one fragment expected; is this the first one? */ ctx = g_task_get_task_data (task); if (!ctx->fragments) ctx->fragments = _mbim_message_fragment_collector_init (message, &error); else _mbim_message_fragment_collector_add (ctx->fragments, message, &error); if (error) { device_report_error (self, ctx->transaction_id, error); transaction_task_complete_and_free (task, error); return; } /* Did we get all needed fragments? */ if (_mbim_message_fragment_collector_complete (ctx->fragments)) { /* Now, translate the whole message */ if (mbim_utils_get_traces_enabled ()) { g_autofree gchar *printable = NULL; printable = mbim_message_get_printable_full (ctx->fragments, self->priv->ms_mbimex_version_major, self->priv->ms_mbimex_version_minor, ">>>>>> ", FALSE, NULL); g_debug ("[%s] received message (translated)...\n%s", self->priv->path_display, printable); } transaction_task_complete_and_free (task, NULL); return; } /* Need more fragments, store transaction */ g_assert (device_store_transaction (self, transaction_type, task, MAX_TIME_BETWEEN_FRAGMENTS_MS, NULL)); return; } case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: { g_autoptr(GError) error_indication = NULL; GTask *task; if (mbim_utils_get_traces_enabled ()) { g_autofree gchar *printable = NULL; printable = mbim_message_get_printable_full (message, self->priv->ms_mbimex_version_major, self->priv->ms_mbimex_version_minor, ">>>>>> ", FALSE, NULL); g_debug ("[%s] received message (translated)...\n%s", self->priv->path_display, printable); } /* Build indication error before task completion, to ensure the message * is valid by the time it is sent. This error will be cleared if the device * gets closed while the transaction response is processed. */ g_assert (!self->priv->pending_error_indication); self->priv->pending_error_indication = mbim_message_error_get_error (message); /* Try to match this transaction just per transaction ID */ task = device_release_transaction (self, TRANSACTION_TYPE_HOST, MBIM_MESSAGE_TYPE_INVALID, mbim_message_get_transaction_id (message)); if (!task) { g_debug ("[%s] No transaction matched in received function error message", self->priv->path_display); } else { TransactionContext *ctx; ctx = g_task_get_task_data (task); if (ctx->fragments) mbim_message_unref (ctx->fragments); ctx->fragments = mbim_message_dup (message); transaction_task_complete_and_free (task, NULL); } /* Signals are emitted regardless of whether the transaction matched or not, * and emitted after the task completion. If the device is forced closed during * the transaction response processing, no error signal will be emitted. */ error_indication = g_steal_pointer (&self->priv->pending_error_indication); if (error_indication) g_signal_emit (self, signals[SIGNAL_ERROR], 0, error_indication); return; } case MBIM_MESSAGE_TYPE_INVALID: case MBIM_MESSAGE_TYPE_OPEN: case MBIM_MESSAGE_TYPE_CLOSE: case MBIM_MESSAGE_TYPE_COMMAND: case MBIM_MESSAGE_TYPE_HOST_ERROR: default: /* Shouldn't expect host-generated messages as replies */ g_message ("[%s] Host-generated message received: ignoring", self->priv->path_display); return; } } static void parse_response (MbimDevice *self) { do { const MbimMessage *message; guint32 len; g_autoptr(GError) error = NULL; message = (const MbimMessage *)self->priv->response; /* Invalid message? */ if (!_mbim_message_validate_internal (message, TRUE, &error)) { /* No full message yet */ if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INCOMPLETE_MESSAGE)) return; /* Invalid MBIM message */ g_warning ("[%s] discarding %u bytes in stream as message validation fails: %s", self->priv->path_display, self->priv->response->len, error->message); g_byte_array_remove_range (self->priv->response, 0, self->priv->response->len); return; } /* Play with the received message */ len = mbim_message_get_message_length (message); process_message (self, message); /* If we were force-closed during the processing of a message, we'd be * losing the response array directly, so check just in case */ if (!self->priv->response) break; /* Remove message from buffer */ g_byte_array_remove_range (self->priv->response, 0, len); } while (self->priv->response->len > 0); } static gboolean data_available (GIOChannel *source, GIOCondition condition, MbimDevice *self) { gsize bytes_read; GIOStatus status; gchar buffer[MAX_CONTROL_TRANSFER + 1]; if (condition & G_IO_HUP) { g_debug ("[%s] unexpected port hangup!", self->priv->path_display); if (self->priv->response && self->priv->response->len) g_byte_array_remove_range (self->priv->response, 0, self->priv->response->len); mbim_device_close_force (self, NULL); g_signal_emit (self, signals[SIGNAL_REMOVED], 0 ); return FALSE; } if (condition & G_IO_ERR) { if (self->priv->response && self->priv->response->len) g_byte_array_remove_range (self->priv->response, 0, self->priv->response->len); return TRUE; } /* If not ready yet, prepare the response with default initial size. */ if (G_UNLIKELY (!self->priv->response)) self->priv->response = g_byte_array_sized_new (500); /* The parse_response() message may end up triggering a close of the * MbimDevice or even a full unref. We are going to make sure a valid * reference is available for as long as we need it in the while() * loop. */ g_object_ref (self); { do { g_autoptr(GError) error = NULL; /* Port is closed; we're done */ if (!self->priv->iochannel_source) break; status = g_io_channel_read_chars (source, buffer, self->priv->max_control_transfer, &bytes_read, &error); if (status == G_IO_STATUS_ERROR && error) g_warning ("[%s] error reading from the IOChannel: '%s'", self->priv->path_display, error->message); /* If no bytes read, just let g_io_channel wait for more data */ if (bytes_read == 0) break; if (bytes_read > 0) g_byte_array_append (self->priv->response, (const guint8 *)buffer, bytes_read); /* Try to parse what we already got */ parse_response (self); /* And keep on if we were told to keep on */ } while (bytes_read == self->priv->max_control_transfer || status == G_IO_STATUS_AGAIN); } g_object_unref (self); return TRUE; } /* "MBIM Control Model Functional Descriptor" */ struct usb_cdc_mbim_desc { guint8 bLength; guint8 bDescriptorType; guint8 bDescriptorSubType; guint16 bcdMBIMVersion; guint16 wMaxControlMessage; guint8 bNumberFilters; guint8 bMaxFilterSize; guint16 wMaxSegmentSize; guint8 bmNetworkCapabilities; } __attribute__ ((packed)); static gchar * get_descriptors_filepath (MbimDevice *self) { static const gchar *subsystems[] = { "usbmisc", "usb" }; g_autofree gchar *device_basename = NULL; g_autofree gchar *descriptors_path = NULL; guint i; device_basename = g_path_get_basename (self->priv->path); for (i = 0; i < G_N_ELEMENTS (subsystems); i++) { g_autofree gchar *tmp = NULL; g_autofree gchar *path = NULL; /* parent sysfs can be built directly using subsystem and name; e.g. for subsystem * usbmisc and name cdc-wdm0: * $ realpath /sys/class/usbmisc/cdc-wdm0/device * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.5/2-1.5:2.0 */ tmp = g_strdup_printf ("/sys/class/%s/%s/device", subsystems[i], device_basename); path = realpath (tmp, NULL); if (path && g_file_test (path, G_FILE_TEST_EXISTS)) { /* Now look for the parent dir with descriptors file. */ g_autofree gchar *dirname = NULL; dirname = g_path_get_dirname (path); descriptors_path = g_build_path (G_DIR_SEPARATOR_S, dirname, "descriptors", NULL); break; } } if (descriptors_path && !g_file_test (descriptors_path, G_FILE_TEST_EXISTS)) { g_warning ("[%s] descriptors file doesn't exist", self->priv->path_display); return NULL; } return g_steal_pointer (&descriptors_path); } static guint16 read_max_control_transfer (MbimDevice *self) { static const guint8 mbim_signature[4] = { 0x0c, 0x24, 0x1b, 0x00 }; g_autoptr(GError) error = NULL; g_autofree gchar *descriptors_path = NULL; g_autofree gchar *contents = NULL; gsize length = 0; guint i; /* Build descriptors filepath */ descriptors_path = get_descriptors_filepath (self); if (!descriptors_path) { /* If descriptors file doesn't exist, it's probably because we're using * some other kernel driver, not the cdc_wdm/cdc_mbim pair, so fallback to * the default and avoid warning about it. */ g_debug ("[%s] couldn't find descriptors file, possibly not using cdc_mbim", self->priv->path_display); g_debug ("[%s] fallback to default max control message size: %u", self->priv->path_display, MAX_CONTROL_TRANSFER); return MAX_CONTROL_TRANSFER; } if (!g_file_get_contents (descriptors_path, &contents, &length, &error)) { g_warning ("[%s] couldn't read descriptors file: %s", self->priv->path_display, error->message); return MAX_CONTROL_TRANSFER; } i = 0; while (i <= (length - sizeof (struct usb_cdc_mbim_desc))) { /* Try to match the MBIM descriptor signature */ if ((memcmp (&contents[i], mbim_signature, sizeof (mbim_signature)) == 0)) { guint16 max; /* Found! */ max = GUINT16_FROM_LE (((struct usb_cdc_mbim_desc *)&contents[i])->wMaxControlMessage); g_debug ("[%s] read max control message size from descriptors file: %" G_GUINT16_FORMAT, self->priv->path_display, max); return max; } /* The first byte of the descriptor info is the length; so keep on * skipping descriptors until we match the MBIM one */ i += contents[i]; } g_warning ("[%s] couldn't find MBIM signature in descriptors file", self->priv->path_display); return MAX_CONTROL_TRANSFER; } typedef struct { guint spawn_retries; } CreateIoChannelContext; static void create_iochannel_context_free (CreateIoChannelContext *ctx) { g_slice_free (CreateIoChannelContext, ctx); } static gboolean create_iochannel_finish (MbimDevice *self, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void setup_iochannel (GTask *task) { MbimDevice *self; GError *inner_error = NULL; self = g_task_get_source_object (task); /* We don't want UTF-8 encoding, we're playing with raw binary data */ g_io_channel_set_encoding (self->priv->iochannel, NULL, NULL); /* We don't want to get the channel buffered */ g_io_channel_set_buffered (self->priv->iochannel, FALSE); /* Let the GIOChannel own the FD */ g_io_channel_set_close_on_unref (self->priv->iochannel, TRUE); /* We don't want to get blocked while writing stuff */ if (!g_io_channel_set_flags (self->priv->iochannel, G_IO_FLAG_NONBLOCK, &inner_error)) { g_io_channel_shutdown (self->priv->iochannel, FALSE, NULL); g_io_channel_unref (self->priv->iochannel); self->priv->iochannel = NULL; g_clear_object (&self->priv->socket_connection); g_clear_object (&self->priv->socket_client); g_task_return_error (task, inner_error); g_object_unref (task); return; } self->priv->iochannel_source = g_io_create_watch (self->priv->iochannel, G_IO_IN | G_IO_ERR | G_IO_HUP); g_source_set_callback (self->priv->iochannel_source, (GSourceFunc)data_available, self, NULL); g_source_attach (self->priv->iochannel_source, g_main_context_get_thread_default ()); g_task_return_boolean (task, TRUE); g_object_unref (task); } static void create_iochannel_with_fd (GTask *task) { MbimDevice *self; gint fd; guint16 max; self = g_task_get_source_object (task); errno = 0; fd = open (self->priv->path, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); if (fd < 0) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Cannot open device file '%s': %s", self->priv->path_display, strerror (errno)); g_object_unref (task); return; } /* Query message size */ if (ioctl (fd, IOCTL_WDM_MAX_COMMAND, &max) < 0) { g_debug ("[%s] couldn't query maximum message size: " "IOCTL_WDM_MAX_COMMAND failed: %s", self->priv->path_display, strerror (errno)); /* Fallback, try to read the descriptor file */ max = read_max_control_transfer (self); } else { g_debug ("[%s] queried max control message size: %" G_GUINT16_FORMAT, self->priv->path_display, max); } self->priv->max_control_transfer = max; /* Create new GIOChannel */ self->priv->iochannel = g_io_channel_unix_new (fd); setup_iochannel (task); } static void create_iochannel_with_socket (GTask *task); static gboolean wait_for_proxy_cb (GTask *task) { create_iochannel_with_socket (task); return FALSE; } static void spawn_child_setup (void) { if (setpgid (0, 0) < 0) g_warning ("couldn't setup proxy specific process group"); } static void create_iochannel_with_socket (GTask *task) { MbimDevice *self; CreateIoChannelContext *ctx; g_autoptr(GSocketAddress) socket_address = NULL; GError *error = NULL; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); /* Create socket client */ if (self->priv->socket_client) g_object_unref (self->priv->socket_client); self->priv->socket_client = g_socket_client_new (); g_socket_client_set_family (self->priv->socket_client, G_SOCKET_FAMILY_UNIX); g_socket_client_set_socket_type (self->priv->socket_client, G_SOCKET_TYPE_STREAM); g_socket_client_set_protocol (self->priv->socket_client, G_SOCKET_PROTOCOL_DEFAULT); /* Setup socket address */ socket_address = (g_unix_socket_address_new_with_type ( MBIM_PROXY_SOCKET_PATH, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT)); /* Connect to address */ if (self->priv->socket_connection) g_object_unref (self->priv->socket_connection); self->priv->socket_connection = (g_socket_client_connect ( self->priv->socket_client, G_SOCKET_CONNECTABLE (socket_address), NULL, &error)); if (!self->priv->socket_connection) { g_auto(GStrv) argc = NULL; g_autoptr(GSource) source = NULL; g_debug ("[%s] cannot connect to proxy: %s", self->priv->path_display, error->message); g_clear_error (&error); g_clear_object (&self->priv->socket_client); /* Don't retry forever */ ctx->spawn_retries++; if (ctx->spawn_retries > MAX_SPAWN_RETRIES) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Couldn't spawn the mbim-proxy"); g_object_unref (task); return; } g_debug ("[%s] spawning new mbim-proxy (try %u)...", self->priv->path_display, ctx->spawn_retries); argc = g_new0 (gchar *, 2); argc[0] = g_strdup (LIBEXEC_PATH "/mbim-proxy"); if (!g_spawn_async (NULL, /* working directory */ argc, NULL, /* envp */ G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, (GSpawnChildSetupFunc) spawn_child_setup, NULL, /* child_setup_user_data */ NULL, &error)) { g_debug ("[%s] error spawning mbim-proxy: %s", self->priv->path_display, error->message); g_clear_error (&error); } /* Wait some ms and retry */ source = g_timeout_source_new (100); g_source_set_callback (source, (GSourceFunc)wait_for_proxy_cb, task, NULL); g_source_attach (source, g_main_context_get_thread_default ()); return; } self->priv->iochannel = g_io_channel_unix_new ( g_socket_get_fd ( g_socket_connection_get_socket (self->priv->socket_connection))); /* try to read the descriptor file */ self->priv->max_control_transfer = read_max_control_transfer (self); setup_iochannel (task); } static void create_iochannel (MbimDevice *self, gboolean proxy, GAsyncReadyCallback callback, gpointer user_data) { CreateIoChannelContext *ctx; GTask *task; ctx = g_slice_new (CreateIoChannelContext); ctx->spawn_retries = 0; task = g_task_new (self, NULL, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify)create_iochannel_context_free); if (self->priv->iochannel) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE, "Already open"); g_object_unref (task); return; } g_assert (self->priv->file); g_assert (self->priv->path); if (proxy) create_iochannel_with_socket (task); else create_iochannel_with_fd (task); } typedef enum { DEVICE_OPEN_CONTEXT_STEP_FIRST = 0, DEVICE_OPEN_CONTEXT_STEP_CREATE_IOCHANNEL, DEVICE_OPEN_CONTEXT_STEP_FLAGS_PROXY, DEVICE_OPEN_CONTEXT_STEP_CLOSE_MESSAGE, DEVICE_OPEN_CONTEXT_STEP_OPEN_MESSAGE, DEVICE_OPEN_CONTEXT_STEP_DEVICE_SERVICES, DEVICE_OPEN_CONTEXT_STEP_MS_EXT_VERSION, DEVICE_OPEN_CONTEXT_STEP_LAST } DeviceOpenContextStep; typedef struct { DeviceOpenContextStep step; MbimDeviceOpenFlags flags; guint timeout; GTimer *timer; gboolean close_before_open; } DeviceOpenContext; static void device_open_context_free (DeviceOpenContext *ctx) { g_timer_destroy (ctx->timer); g_slice_free (DeviceOpenContext, ctx); } gboolean mbim_device_open_full_finish (MbimDevice *self, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } gboolean mbim_device_open_finish (MbimDevice *self, GAsyncResult *res, GError **error) { return mbim_device_open_full_finish (self, res, error); } static void device_open_context_step (GTask *task); static void ms_ext_version_message_ready (MbimDevice *self, GAsyncResult *res, GTask *task) { g_autoptr(MbimMessage) response = NULL; GError *error = NULL; guint16 mbim_version; guint16 ms_mbimex_version; DeviceOpenContext *ctx; ctx = g_task_get_task_data (task); response = mbim_device_command_finish (self, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) || !mbim_message_ms_basic_connect_extensions_v2_version_response_parse ( response, &mbim_version, &ms_mbimex_version, &error)){ g_task_return_error (task, error); g_object_unref (task); return; } /* We fully ignore the MBIM version for now, we just assume it's 1.0, which * is the only known release from the USB-IF for now. */ self->priv->ms_mbimex_version_major = (ms_mbimex_version >> 8) & 0xFF; self->priv->ms_mbimex_version_minor = ms_mbimex_version & 0xFF; g_debug ("[%s] successfully exchanged version information: version %x.%02x, extended version %x.%02x", self->priv->path_display, (mbim_version >> 8) & 0xFF, mbim_version & 0xFF, self->priv->ms_mbimex_version_major, self->priv->ms_mbimex_version_minor); ctx->step++; device_open_context_step (task); } static void ms_ext_version_message (GTask *task) { MbimDevice *self; DeviceOpenContext *ctx; g_autoptr(MbimMessage) request = NULL; guint32 mbim_version = 0; guint32 ms_mbimex_version = 0; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); if ((ctx->flags & MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2) && (ctx->flags & MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3)) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "Cannot request both MBIMEx v2.0 and v3.0 at the same time"); g_object_unref (task); return; } /* User requested MBIMEx 2.0 or 3.0, so we'll report it along with MBIM 1.0 */ mbim_version = 0x01 << 8 | 0x00; if (ctx->flags & MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2) ms_mbimex_version = 0x02 << 8 | 0x00; else if (ctx->flags & MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3) ms_mbimex_version = 0x03 << 8 | 0x00; else g_assert_not_reached (); request = mbim_message_ms_basic_connect_extensions_v2_version_query_new (mbim_version, ms_mbimex_version, NULL); g_assert (request); mbim_device_command (self, request, ctx->timeout, g_task_get_cancellable (task), (GAsyncReadyCallback)ms_ext_version_message_ready, task); } static void device_services_message_ready (MbimDevice *device, GAsyncResult *res, GTask *task) { g_autoptr(MbimMessage) response = NULL; g_autoptr(MbimDeviceServiceElementArray) device_services = NULL; GError *error = NULL; guint32 device_services_count; guint32 max_dss_sessions; DeviceOpenContext *ctx; guint i; ctx = g_task_get_task_data (task); response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) || !mbim_message_device_services_response_parse ( response, &device_services_count, &max_dss_sessions, &device_services, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } if (device_services_count == 0) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "No supported services reported by the modem"); g_object_unref (task); return; } for (i = 0; i < device_services_count; i++) { MbimService service; guint32 j; service = mbim_uuid_to_service (&device_services[i]->device_service_id); for (j = 0; j < device_services[i]->cids_count; j++) { if ((service == MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS) && device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_VERSION) { /* version command is supported, go on */ ctx->step++; device_open_context_step (task); return; } } } /* the version command isn't supported, so we can just jump to the end */ ctx->step = DEVICE_OPEN_CONTEXT_STEP_LAST;; device_open_context_step (task); } static void device_services_message (GTask *task) { MbimDevice *self; DeviceOpenContext *ctx; g_autoptr(MbimMessage) request = NULL; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); request = mbim_message_device_services_query_new (NULL); g_assert (request); mbim_device_command (self, request, ctx->timeout, g_task_get_cancellable (task), (GAsyncReadyCallback)device_services_message_ready, task); } static void open_message_ready (MbimDevice *self, GAsyncResult *res, GTask *task) { DeviceOpenContext *ctx; g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; ctx = g_task_get_task_data (task); /* Cleanup, as no longer needed */ self->priv->open_transaction_id = 0; response = mbim_device_command_finish (self, res, &error); if (!response) { /* If we get reported that the state is unknown, try to close before open */ if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNKNOWN_STATE)) { ctx->close_before_open = TRUE; ctx->step = DEVICE_OPEN_CONTEXT_STEP_CLOSE_MESSAGE; device_open_context_step (task); return; } /* Check if we should be retrying after a timeout */ if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_TIMEOUT)) { device_open_context_step (task); return; } g_debug ("[%s] error reported in open operation: closed", self->priv->path_display); self->priv->open_status = OPEN_STATUS_CLOSED; g_task_return_error (task, g_steal_pointer (&error)); g_object_unref (task); return; } if (!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_OPEN_DONE, &error)) { g_debug ("[%s] getting open done result failed: closed", self->priv->path_display); self->priv->open_status = OPEN_STATUS_CLOSED; g_task_return_error (task, g_steal_pointer (&error)); g_object_unref (task); return; } /* go on */ ctx->step++; device_open_context_step (task); } static void open_message (GTask *task) { MbimDevice *self; g_autoptr(MbimMessage) request = NULL; self = g_task_get_source_object (task); /* Launch 'Open' command */ self->priv->open_transaction_id = mbim_device_get_next_transaction_id (self); request = mbim_message_open_new (self->priv->open_transaction_id, self->priv->max_control_transfer); mbim_device_command (self, request, OPEN_RETRY_TIMEOUT_SECS, g_task_get_cancellable (task), (GAsyncReadyCallback)open_message_ready, task); } static void close_message_before_open_ready (MbimDevice *self, GAsyncResult *res, GTask *task) { DeviceOpenContext *ctx; g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; ctx = g_task_get_task_data (task); response = mbim_device_command_finish (self, res, &error); if (!response) g_debug ("[%s] error reported in close before open: %s (ignored)", self->priv->path_display, error->message); else if (!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_CLOSE_DONE, &error)) g_debug ("[%s] getting close done result failed: %s (ignored)", self->priv->path_display, error->message); /* go on */ ctx->step++; device_open_context_step (task); } static void close_message_before_open (GTask *task) { MbimDevice *self; g_autoptr(MbimMessage) request = NULL; self = g_task_get_source_object (task); /* Launch 'Close' command */ request = mbim_message_close_new (mbim_device_get_next_transaction_id (self)); mbim_device_command (self, request, OPEN_CLOSE_TIMEOUT_SECS, g_task_get_cancellable (task), (GAsyncReadyCallback)close_message_before_open_ready, task); } static void proxy_cfg_message_ready (MbimDevice *self, GAsyncResult *res, GTask *task) { DeviceOpenContext *ctx; GError *error = NULL; g_autoptr(MbimMessage) response = NULL; ctx = g_task_get_task_data (task); response = mbim_device_command_finish (self, res, &error); if (!response) { /* Hard error if proxy cfg command fails */ g_debug ("[%s] proxy configuration failed: closed", self->priv->path_display); self->priv->open_status = OPEN_STATUS_CLOSED; g_task_return_error (task, error); g_object_unref (task); return; } ctx->step++; device_open_context_step (task); } static void proxy_cfg_message (GTask *task) { MbimDevice *self; DeviceOpenContext *ctx; g_autoptr(MbimMessage) request = NULL; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); request = mbim_message_proxy_control_configuration_set_new (self->priv->path, ctx->timeout, NULL); g_assert (request); /* This message is no longer a direct reply; as the proxy will also try to open the device * directly. If it cannot open the device, it will return an error. */ mbim_device_command (self, request, ctx->timeout, g_task_get_cancellable (task), (GAsyncReadyCallback)proxy_cfg_message_ready, task); } static void create_iochannel_ready (MbimDevice *self, GAsyncResult *res, GTask *task) { DeviceOpenContext *ctx; GError *error = NULL; if (!create_iochannel_finish (self, res, &error)) { g_debug ("[%s] creating iochannel failed: closed", self->priv->path_display); self->priv->open_status = OPEN_STATUS_CLOSED; g_task_return_error (task, error); g_object_unref (task); return; } /* Go on */ ctx = g_task_get_task_data (task); ctx->step++; device_open_context_step (task); } static void device_open_context_step (GTask *task) { MbimDevice *self; DeviceOpenContext *ctx; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); /* Timed out? */ if (g_timer_elapsed (ctx->timer, NULL) > ctx->timeout) { g_debug ("[%s] open operation timed out: closed", self->priv->path_display); self->priv->open_status = OPEN_STATUS_CLOSED; g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_TIMEOUT, "Operation timed out: device is closed"); g_object_unref (task); return; } switch (ctx->step) { case DEVICE_OPEN_CONTEXT_STEP_FIRST: if (self->priv->open_status == OPEN_STATUS_OPEN) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE, "Already open"); g_object_unref (task); return; } if (self->priv->open_status == OPEN_STATUS_OPENING) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE, "Already opening"); g_object_unref (task); return; } g_debug ("[%s] opening device...", self->priv->path_display); g_assert (self->priv->open_status == OPEN_STATUS_CLOSED); self->priv->open_status = OPEN_STATUS_OPENING; ctx->step++; /* Fall through */ case DEVICE_OPEN_CONTEXT_STEP_CREATE_IOCHANNEL: create_iochannel (self, !!(ctx->flags & MBIM_DEVICE_OPEN_FLAGS_PROXY), (GAsyncReadyCallback)create_iochannel_ready, task); return; case DEVICE_OPEN_CONTEXT_STEP_FLAGS_PROXY: if (ctx->flags & MBIM_DEVICE_OPEN_FLAGS_PROXY) { proxy_cfg_message (task); return; } ctx->step++; /* Fall through */ case DEVICE_OPEN_CONTEXT_STEP_CLOSE_MESSAGE: /* Only send an explicit close during open if needed */ if (ctx->close_before_open) { ctx->close_before_open = FALSE; close_message_before_open (task); return; } ctx->step++; /* Fall through */ case DEVICE_OPEN_CONTEXT_STEP_OPEN_MESSAGE: /* If the device is already in-session, avoid the open message */ if (!self->priv->in_session) { open_message (task); return; } ctx->step++; /* Fall through */ case DEVICE_OPEN_CONTEXT_STEP_DEVICE_SERVICES: if (ctx->flags & (MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2 | MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3)) { device_services_message (task); return; } ctx->step++; /* Fall through */ case DEVICE_OPEN_CONTEXT_STEP_MS_EXT_VERSION: if (ctx->flags & (MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2 | MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3)) { ms_ext_version_message (task); return; } ctx->step++; /* Fall through */ case DEVICE_OPEN_CONTEXT_STEP_LAST: /* Nothing else to process, complete without error */ self->priv->open_status = OPEN_STATUS_OPEN; g_task_return_boolean (task, TRUE); g_object_unref (task); return; default: break; } g_assert_not_reached (); } void mbim_device_open_full (MbimDevice *self, MbimDeviceOpenFlags flags, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { DeviceOpenContext *ctx; GTask *task; g_return_if_fail (MBIM_IS_DEVICE (self)); g_return_if_fail (timeout > 0); ctx = g_slice_new0 (DeviceOpenContext); ctx->step = DEVICE_OPEN_CONTEXT_STEP_FIRST; ctx->flags = flags; ctx->timeout = timeout; ctx->timer = g_timer_new (); ctx->close_before_open = FALSE; task = g_task_new (self, cancellable, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify)device_open_context_free); /* Start processing */ device_open_context_step (task); } void mbim_device_open (MbimDevice *self, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { mbim_device_open_full (self, MBIM_DEVICE_OPEN_FLAGS_NONE, timeout, cancellable, callback, user_data); } /*****************************************************************************/ /* Close channel */ static gboolean destroy_iochannel (MbimDevice *self, GError **error) { GError *inner_error = NULL; /* Already closed? */ if (!self->priv->iochannel && !self->priv->socket_connection && !self->priv->socket_client) return TRUE; g_debug ("[%s] channel destroyed", self->priv->path_display); if (self->priv->iochannel) { g_io_channel_shutdown (self->priv->iochannel, TRUE, &inner_error); g_io_channel_unref (self->priv->iochannel); self->priv->iochannel = NULL; } /* Failures when closing still make the device to get closed */ g_clear_object (&self->priv->socket_connection); g_clear_object (&self->priv->socket_client); /* Pending error indications are always cleared if the channel is * closed */ g_clear_error (&self->priv->pending_error_indication); if (self->priv->iochannel_source) { g_source_destroy (self->priv->iochannel_source); g_source_unref (self->priv->iochannel_source); self->priv->iochannel_source = NULL; } if (self->priv->response) { g_byte_array_unref (self->priv->response); self->priv->response = NULL; } if (inner_error) { g_propagate_error (error, inner_error); return FALSE; } return TRUE; } gboolean mbim_device_close_force (MbimDevice *self, GError **error) { g_return_val_if_fail (MBIM_IS_DEVICE (self), FALSE); self->priv->open_status = OPEN_STATUS_CLOSED; return destroy_iochannel (self, error); } typedef struct { guint timeout; } DeviceCloseContext; static void device_close_context_free (DeviceCloseContext *ctx) { g_slice_free (DeviceCloseContext, ctx); } gboolean mbim_device_close_finish (MbimDevice *self, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void close_message_ready (MbimDevice *self, GAsyncResult *res, GTask *task) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(GError) iochannel_error = NULL; response = mbim_device_command_finish (self, res, &error); if (response) mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_CLOSE_DONE, &error); self->priv->open_status = OPEN_STATUS_CLOSED; destroy_iochannel (self, &iochannel_error); if (error) g_task_return_error (task, g_steal_pointer (&error)); else if (iochannel_error) g_task_return_error (task, g_steal_pointer (&iochannel_error)); else g_task_return_boolean (task, TRUE); g_object_unref (task); } void mbim_device_close (MbimDevice *self, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(MbimMessage) request = NULL; DeviceCloseContext *ctx; GTask *task; g_return_if_fail (MBIM_IS_DEVICE (self)); ctx = g_slice_new (DeviceCloseContext); ctx->timeout = timeout; task = g_task_new (self, cancellable, callback, user_data); g_task_set_task_data (task, ctx, (GDestroyNotify)device_close_context_free); /* If already closed, we're done */ if (self->priv->open_status == OPEN_STATUS_CLOSED) { g_task_return_boolean (task, TRUE); g_object_unref (task); return; } /* If we're opening, fail with error. We could say we would abort the * ongoing open attempt, but the way to abort that attempt is with the * cancellable given in the open operation, not with an additional close. */ if (self->priv->open_status == OPEN_STATUS_OPENING) { g_task_return_new_error ( task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE, "Cannot close device: not yet fully open"); g_object_unref (task); return; } g_debug ("[%s] closing device...", self->priv->path_display); g_assert (self->priv->open_status == OPEN_STATUS_OPEN); /* If the device is in-session, avoid the close message */ if (self->priv->in_session) { GError *error = NULL; self->priv->open_status = OPEN_STATUS_CLOSED; if (!destroy_iochannel (self, &error)) g_task_return_error (task, error); else g_task_return_boolean (task, TRUE); g_object_unref (task); return; } /* Launch 'Close' command */ request = mbim_message_close_new (mbim_device_get_next_transaction_id (self)); mbim_device_command (self, request, 10, cancellable, (GAsyncReadyCallback) close_message_ready, task); } /*****************************************************************************/ guint32 mbim_device_get_next_transaction_id (MbimDevice *self) { guint32 next; g_return_val_if_fail (MBIM_IS_DEVICE (self), 0); next = self->priv->transaction_id; /* Don't go further than 8bits in the CTL service */ if (self->priv->transaction_id == G_MAXUINT32) /* Reset! */ self->priv->transaction_id = 0x01; else self->priv->transaction_id++; return next; } /*****************************************************************************/ guint32 mbim_device_get_transaction_id (MbimDevice *self) { g_return_val_if_fail (MBIM_IS_DEVICE (self), 0); return self->priv->transaction_id; } /*****************************************************************************/ static gboolean device_write (MbimDevice *self, const guint8 *data, guint32 data_length, GError **error) { gsize written; GIOStatus write_status; written = 0; write_status = G_IO_STATUS_AGAIN; while (write_status == G_IO_STATUS_AGAIN) { write_status = g_io_channel_write_chars (self->priv->iochannel, (gconstpointer)data, (gssize)data_length, &written, error); switch (write_status) { case G_IO_STATUS_ERROR: g_prefix_error (error, "Cannot write message: "); return FALSE; case G_IO_STATUS_EOF: /* We shouldn't get EOF when writing */ g_assert_not_reached (); break; case G_IO_STATUS_NORMAL: /* All good, we'll exit the loop now */ break; case G_IO_STATUS_AGAIN: /* We're in a non-blocking channel and therefore we're up to receive * EAGAIN; just retry in this case. TODO: in an idle? */ break; default: g_assert_not_reached (); break; } } return TRUE; } static gboolean device_send (MbimDevice *self, MbimMessage *message, GError **error) { const guint8 *raw_message; guint32 raw_message_len; g_autofree struct fragment_info *fragments = NULL; guint n_fragments; guint i; raw_message = mbim_message_get_raw (message, &raw_message_len, NULL); g_assert (raw_message); if (mbim_utils_get_traces_enabled ()) { g_autofree gchar *hex = NULL; g_autofree gchar *printable = NULL; if (mbim_utils_get_show_personal_info () || (raw_message_len < MAX_PRINTED_BYTES)) { hex = mbim_common_str_hex (raw_message, raw_message_len, ':'); } else { g_autofree gchar *tmp = NULL; tmp = mbim_common_str_hex (raw_message, MAX_PRINTED_BYTES, ':'); hex = g_strdup_printf ("%s...", tmp); } g_debug ("[%s] sent message...\n" "<<<<<< RAW:\n" "<<<<<< length = %u\n" "<<<<<< data = %s\n", self->priv->path_display, ((GByteArray *)message)->len, hex); printable = mbim_message_get_printable_full (message, self->priv->ms_mbimex_version_major, self->priv->ms_mbimex_version_minor, "<<<<<< ", FALSE, NULL); g_debug ("[%s] sent message (translated)...\n%s", self->priv->path_display, printable); } /* Single fragment? Send it! */ if (raw_message_len <= MAX_CONTROL_TRANSFER) return device_write (self, raw_message, raw_message_len, error); /* The message to send must be able to handle fragments */ g_assert (_mbim_message_is_fragment (message)); fragments = _mbim_message_split_fragments (message, MAX_CONTROL_TRANSFER, &n_fragments); for (i = 0; i < n_fragments; i++) { g_autoptr(GByteArray) full_fragment = NULL; g_autofree gchar *printable_headers = NULL; /* Build compiled fragment headers */ full_fragment = g_byte_array_new (); g_byte_array_append (full_fragment, (guint8 *)&fragments[i].header, sizeof (fragments[i].header)); g_byte_array_append (full_fragment, (guint8 *)&fragments[i].fragment_header, sizeof (fragments[i].fragment_header)); /* Build placeholder message with only headers for printable purposes only */ if (mbim_utils_get_traces_enabled ()) printable_headers = mbim_message_get_printable_full ((MbimMessage *)full_fragment, self->priv->ms_mbimex_version_major, self->priv->ms_mbimex_version_minor, "<<<<<< ", TRUE, NULL); /* Append the actual fragment data */ g_byte_array_append (full_fragment, (guint8 *)fragments[i].data, fragments[i].data_length); if (mbim_utils_get_traces_enabled ()) { g_autofree gchar *printable_full = NULL; printable_full = mbim_common_str_hex ((const guint8 *)full_fragment->data, full_fragment->len, ':'); g_debug ("[%s] sent fragment (%u)...\n" "<<<<<< RAW:\n" "<<<<<< length = %u\n" "<<<<<< data = %s\n", self->priv->path_display, i, full_fragment->len, printable_full); g_debug ("[%s] sent fragment (translated)...\n%s", self->priv->path_display, printable_headers); } /* Write whole packet to MBIM device. * Here send whole packet rather than seperated elements, such as header, * fragment_header, data, because some MBIM devices may have errors on * seperated fragment case, such as "MBIM protocol error: LengthMismatch" */ if (!device_write (self, (guint8 *)full_fragment->data, full_fragment->len, error)) return FALSE; } return TRUE; } /*****************************************************************************/ /* Report error */ typedef struct { MbimDevice *self; MbimMessage *message; } ReportErrorContext; static void device_report_error_context_free (ReportErrorContext *ctx) { mbim_message_unref (ctx->message); g_object_unref (ctx->self); g_slice_free (ReportErrorContext, ctx); } static gboolean device_report_error_in_idle (ReportErrorContext *ctx) { /* Device must be open */ if (ctx->self->priv->iochannel) { g_autoptr(GError) error = NULL; if (!device_send (ctx->self, ctx->message, &error)) g_warning ("[%s] couldn't send host error message: %s", ctx->self->priv->path_display, error->message); } device_report_error_context_free (ctx); return FALSE; } static void device_report_error (MbimDevice *self, guint32 transaction_id, const GError *error) { ReportErrorContext *ctx; g_autoptr(GSource) source = NULL; /* Only protocol errors to be reported to the modem */ if (error->domain != MBIM_PROTOCOL_ERROR) return; ctx = g_slice_new (ReportErrorContext); ctx->self = g_object_ref (self); ctx->message = mbim_message_error_new (transaction_id, error->code); source = g_idle_source_new (); g_source_set_callback (source, (GSourceFunc)device_report_error_in_idle, ctx, NULL); g_source_attach (source, g_main_context_get_thread_default ()); } /*****************************************************************************/ /* Command */ MbimMessage * mbim_device_command_finish (MbimDevice *self, GAsyncResult *res, GError **error) { return g_task_propagate_pointer (G_TASK (res), error); } void mbim_device_command (MbimDevice *self, MbimMessage *message, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(GError) error = NULL; GTask *task; guint32 transaction_id; g_return_if_fail (MBIM_IS_DEVICE (self)); g_return_if_fail (message != NULL); /* If the message comes without a explicit transaction ID, add one * ourselves */ transaction_id = mbim_message_get_transaction_id (message); if (!transaction_id) { transaction_id = mbim_device_get_next_transaction_id (self); mbim_message_set_transaction_id (message, transaction_id); } task = transaction_task_new (self, MBIM_MESSAGE_GET_MESSAGE_TYPE (message), transaction_id, cancellable, callback, user_data); /* Device must be open */ if (!self->priv->iochannel) { error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE, "Device must be open to send commands"); transaction_task_complete_and_free (task, error); return; } /* Setup context to match response */ if (!device_store_transaction (self, TRANSACTION_TYPE_HOST, task, timeout * 1000, &error)) { g_prefix_error (&error, "Cannot store transaction: "); transaction_task_complete_and_free (task, error); return; } if (!device_send (self, message, &error)) { /* Match transaction so that we remove it from our tracking table */ task = device_release_transaction (self, TRANSACTION_TYPE_HOST, MBIM_MESSAGE_GET_MESSAGE_TYPE (message), mbim_message_get_transaction_id (message)); transaction_task_complete_and_free (task, error); return; } /* Just return, we'll get response asynchronously */ } /*****************************************************************************/ /* New MBIM device */ MbimDevice * mbim_device_new_finish (GAsyncResult *res, GError **error) { GObject *ret; GObject *source_object; source_object = g_async_result_get_source_object (res); ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); g_object_unref (source_object); return (ret ? MBIM_DEVICE (ret) : NULL); } void mbim_device_new (GFile *file, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_async_initable_new_async (MBIM_TYPE_DEVICE, G_PRIORITY_DEFAULT, cancellable, callback, user_data, MBIM_DEVICE_FILE, file, NULL); } /*****************************************************************************/ /* Async init */ static gboolean initable_init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) { return g_task_propagate_boolean (G_TASK (result), error); } static void query_info_async_ready (GFile *file, GAsyncResult *res, GTask *task) { GError *error = NULL; GFileInfo *info; info = g_file_query_info_finish (file, res, &error); if (!info) { g_prefix_error (&error, "Couldn't query file info: "); g_task_return_error (task, error); g_object_unref (task); return; } /* Our MBIM device must be of SPECIAL type */ if (g_file_info_get_file_type (info) != G_FILE_TYPE_SPECIAL) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Wrong file type"); g_object_unref (task); return; } g_object_unref (info); /* Done we are */ g_task_return_boolean (task, TRUE); g_object_unref (task); } static void initable_init_async (GAsyncInitable *initable, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { MbimDevice *self; GTask *task; self = MBIM_DEVICE (initable); task = g_task_new (self, cancellable, callback, user_data); /* We need a proper file to initialize */ if (!self->priv->file) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "Cannot initialize MBIM device: No file given"); g_object_unref (task); return; } /* Check the file type. Note that this is just a quick check to avoid * creating MbimDevices pointing to a location already known not to be a MBIM * device. */ g_file_query_info_async (self->priv->file, G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, cancellable, (GAsyncReadyCallback)query_info_async_ready, task); } /*****************************************************************************/ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { MbimDevice *self = MBIM_DEVICE (object); switch (prop_id) { case PROP_FILE: g_assert (self->priv->file == NULL); self->priv->file = g_value_dup_object (value); self->priv->path = g_file_get_path (self->priv->file); self->priv->path_display = g_filename_display_name (self->priv->path); break; case PROP_TRANSACTION_ID: self->priv->transaction_id = g_value_get_uint (value); break; case PROP_IN_SESSION: self->priv->in_session = g_value_get_boolean (value); break; case PROP_CONSECUTIVE_TIMEOUTS: g_assert_not_reached (); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { MbimDevice *self = MBIM_DEVICE (object); switch (prop_id) { case PROP_FILE: g_value_set_object (value, self->priv->file); break; case PROP_TRANSACTION_ID: g_value_set_uint (value, self->priv->transaction_id); break; case PROP_IN_SESSION: g_value_set_boolean (value, self->priv->in_session); break; case PROP_CONSECUTIVE_TIMEOUTS: g_value_set_uint (value, self->priv->consecutive_timeouts); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void mbim_device_init (MbimDevice *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), MBIM_TYPE_DEVICE, MbimDevicePrivate); /* Initialize transaction ID */ self->priv->transaction_id = 0x01; self->priv->open_status = OPEN_STATUS_CLOSED; /* By default, assume v1.0 supported */ self->priv->ms_mbimex_version_major = 0x01; } static void dispose (GObject *object) { MbimDevice *self = MBIM_DEVICE (object); g_clear_object (&self->priv->file); self->priv->open_status = OPEN_STATUS_CLOSED; destroy_iochannel (self, NULL); g_clear_object (&self->priv->net_port_manager); G_OBJECT_CLASS (mbim_device_parent_class)->dispose (object); } static void finalize (GObject *object) { MbimDevice *self = MBIM_DEVICE (object); guint i; /* Transactions keep refs to the device, so it's actually * impossible to have any content in the HT */ for (i = 0; i < TRANSACTION_TYPE_LAST; i++) { if (self->priv->transactions[i]) { g_assert (g_hash_table_size (self->priv->transactions[i]) == 0); g_hash_table_unref (self->priv->transactions[i]); self->priv->transactions[i] = NULL; } } g_free (self->priv->path); g_free (self->priv->path_display); g_free (self->priv->wwan_iface); G_OBJECT_CLASS (mbim_device_parent_class)->finalize (object); } static void async_initable_iface_init (GAsyncInitableIface *iface) { iface->init_async = initable_init_async; iface->init_finish = initable_init_finish; } static void mbim_device_class_init (MbimDeviceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (MbimDevicePrivate)); object_class->get_property = get_property; object_class->set_property = set_property; object_class->finalize = finalize; object_class->dispose = dispose; /** * MbimDevice:device-file * * Since: 1.0 */ properties[PROP_FILE] = g_param_spec_object (MBIM_DEVICE_FILE, "Device file", "File to the underlying MBIM device", G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_FILE, properties[PROP_FILE]); /** * MbimDevice:device-transaction-id * * Since: 1.2 */ properties[PROP_TRANSACTION_ID] = g_param_spec_uint (MBIM_DEVICE_TRANSACTION_ID, "Transaction ID", "Current transaction ID", 0x01, G_MAXUINT32, 0x01, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_TRANSACTION_ID, properties[PROP_TRANSACTION_ID]); /** * MbimDevice:device-in-session * * Since: 1.4 */ properties[PROP_IN_SESSION] = g_param_spec_boolean (MBIM_DEVICE_IN_SESSION, "In session", "Flag to specify if the device is within a session", FALSE, G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_IN_SESSION, properties[PROP_IN_SESSION]); /** * MbimDevice:device-consecutive-timeouts: * * Since: 1.28 */ properties[PROP_CONSECUTIVE_TIMEOUTS] = g_param_spec_uint (MBIM_DEVICE_CONSECUTIVE_TIMEOUTS, "Consecutive timeouts", "Number of consecutive timeouts detected in requests sent to the device", 0, G_MAXUINT, 0, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_CONSECUTIVE_TIMEOUTS, properties[PROP_CONSECUTIVE_TIMEOUTS]); /** * MbimDevice::device-indicate-status: * @self: the #MbimDevice * @message: the #MbimMessage indication * * The ::device-indication-status signal is emitted when a MBIM indication is received. * * Since: 1.0 */ signals[SIGNAL_INDICATE_STATUS] = g_signal_new (MBIM_DEVICE_SIGNAL_INDICATE_STATUS, G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, MBIM_TYPE_MESSAGE); /** * MbimDevice::device-error: * @self: the #MbimDevice * @message: the #MbimMessage error * * The ::device-error signal is emitted when a MBIM error is received. * * Since: 1.0 */ signals[SIGNAL_ERROR] = g_signal_new (MBIM_DEVICE_SIGNAL_ERROR, G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_ERROR); /** * MbimDevice::device-removed: * @self: the #MbimDevice * @message: None * * The ::device-removed signal is emitted when an unexpected port hang-up is received. * * Since: 1.10 */ signals[SIGNAL_REMOVED] = g_signal_new (MBIM_DEVICE_SIGNAL_REMOVED, G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); } libmbim-1.31.2-dev/src/libmbim-glib/mbim-device.h000066400000000000000000000554201453630424100214440ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2021 Aleksander Morgado * Copyright (C) 2021 Intel Corporation */ #ifndef _LIBMBIM_GLIB_MBIM_DEVICE_H_ #define _LIBMBIM_GLIB_MBIM_DEVICE_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif #include #include #include "mbim-message.h" G_BEGIN_DECLS /** * SECTION:mbim-device * @title: MbimDevice * @short_description: Generic MBIM device handling routines * * #MbimDevice is a generic type in charge of controlling the access to the * managed MBIM port. * * A #MbimDevice can only handle one single MBIM port. */ #define MBIM_TYPE_DEVICE (mbim_device_get_type ()) #define MBIM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MBIM_TYPE_DEVICE, MbimDevice)) #define MBIM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MBIM_TYPE_DEVICE, MbimDeviceClass)) #define MBIM_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MBIM_TYPE_DEVICE)) #define MBIM_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MBIM_TYPE_DEVICE)) #define MBIM_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MBIM_TYPE_DEVICE, MbimDeviceClass)) typedef struct _MbimDevice MbimDevice; typedef struct _MbimDeviceClass MbimDeviceClass; typedef struct _MbimDevicePrivate MbimDevicePrivate; /** * MBIM_DEVICE_FILE: * * Symbol defining the #MbimDevice:device-file property. * * Since: 1.0 */ #define MBIM_DEVICE_FILE "device-file" /** * MBIM_DEVICE_TRANSACTION_ID: * * Symbol defining the #MbimDevice:device-transaction-id property. * * Since: 1.2 */ #define MBIM_DEVICE_TRANSACTION_ID "device-transaction-id" /** * MBIM_DEVICE_IN_SESSION: * * Symbol defining the #MbimDevice:device-in-session property. * * Since: 1.4 */ #define MBIM_DEVICE_IN_SESSION "device-in-session" /** * MBIM_DEVICE_CONSECUTIVE_TIMEOUTS: * * Symbol defining the #MbimDevice:device-consecutive-timeouts property. * * Since: 1.28 */ #define MBIM_DEVICE_CONSECUTIVE_TIMEOUTS "device-consecutive-timeouts" /** * MBIM_DEVICE_SIGNAL_INDICATE_STATUS: * * Symbol defining the #MbimDevice::device-indicate-status signal. * * Since: 1.0 */ #define MBIM_DEVICE_SIGNAL_INDICATE_STATUS "device-indicate-status" /** * MBIM_DEVICE_SIGNAL_ERROR: * * Symbol defining the #MbimDevice::device-error signal. * * Since: 1.0 */ #define MBIM_DEVICE_SIGNAL_ERROR "device-error" /** * MBIM_DEVICE_SIGNAL_REMOVED: * * Symbol defining the #MbimDevice::device-removed signal. * * Since: 1.10 */ #define MBIM_DEVICE_SIGNAL_REMOVED "device-removed" /** * MbimDevice: * * The #MbimDevice structure contains private data and should only be accessed * using the provided API. * * Since: 1.0 */ struct _MbimDevice { /*< private >*/ GObject parent; MbimDevicePrivate *priv; }; struct _MbimDeviceClass { /*< private >*/ GObjectClass parent; }; GType mbim_device_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimDevice, g_object_unref) /** * mbim_device_new: * @file: a #GFile. * @cancellable: optional #GCancellable object, #NULL to ignore. * @callback: a #GAsyncReadyCallback to call when the initialization is finished. * @user_data: the data to pass to callback function. * * Asynchronously creates a #MbimDevice object to manage @file. * When the operation is finished, @callback will be invoked. You can then call * mbim_device_new_finish() to get the result of the operation. * * Since: 1.0 */ void mbim_device_new (GFile *file, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); /** * mbim_device_new_finish: * @res: a #GAsyncResult. * @error: Return location for error or %NULL. * * Finishes an operation started with mbim_device_new(). * * Returns: (transfer full): a newly created #MbimDevice, or #NULL if @error is set. * * Since: 1.0 */ MbimDevice *mbim_device_new_finish (GAsyncResult *res, GError **error); /** * mbim_device_get_file: (skip) * @self: a #MbimDevice. * * Get the #GFile associated with this #MbimDevice. * * Returns: (transfer full): a #GFile that must be freed with g_object_unref(). * * Since: 1.0 */ GFile *mbim_device_get_file (MbimDevice *self); /** * mbim_device_peek_file: (skip) * @self: a #MbimDevice. * * Get the #GFile associated with this #MbimDevice, without increasing the reference count * on the returned object. * * Returns: (transfer none): a #GFile. Do not free the returned object, it is owned by @self. * * Since: 1.0 */ GFile *mbim_device_peek_file (MbimDevice *self); /** * mbim_device_get_path: * @self: a #MbimDevice. * * Get the system path of the underlying MBIM device. * * Returns: the system path of the device. * * Since: 1.0 */ const gchar *mbim_device_get_path (MbimDevice *self); /** * mbim_device_get_path_display: * @self: a #MbimDevice. * * Get the system path of the underlying MBIM device in UTF-8. * * Returns: UTF-8 encoded system path of the device. * * Since: 1.0 */ const gchar *mbim_device_get_path_display (MbimDevice *self); /** * mbim_device_is_open: * @self: a #MbimDevice. * * Checks whether the #MbimDevice is open for I/O. * * Returns: %TRUE if @self is open, %FALSE otherwise. * * Since: 1.0 */ gboolean mbim_device_is_open (MbimDevice *self); /** * mbim_device_get_ms_mbimex_version: * @self: a #MbimDevice. * @out_ms_mbimex_version_minor: output location for the minor version number of * the MS MBIMEx support, or %NULL if not needed. * * Get the version number of the MS MBIMEx support. * * The reported version will be 1 if the initialization sequence to agree on * which version to use hasn't been run (e.g. with mbim_device_open_full() and * the explicit %MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2 or * %MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3 flag). * * Returns: the major version number of the MS MBIMEx support. * * Since: 1.28 */ guint8 mbim_device_get_ms_mbimex_version (MbimDevice *self, guint8 *out_ms_mbimex_version_minor); /** * mbim_device_set_ms_mbimex_version: * @self: a #MbimDevice. * @ms_mbimex_version_major: major version number of the MS MBIMEx support. * @ms_mbimex_version_minor: minor version number of the MS MBIMEx support. * @error: Return location for error or %NULL. * * Set the version number of the MS MBIMEx support assumed in the device * instance, which may have been set already by a different process or * device instance. * * If this operation specifies the wrong MBIMEx version agreed between host * and device, the message processing on this device instance may fail. * * This operation does not do any MBIMEx version exchange with the device, * the only way to do that is with mbim_device_open_full() and the explicit * %MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2 or %MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3 * flag. * * Returns: %TRUE if successful, %FALSE if @error is set. * * Since: 1.28 */ gboolean mbim_device_set_ms_mbimex_version (MbimDevice *self, guint8 ms_mbimex_version_major, guint8 ms_mbimex_version_minor, GError **error); /** * mbim_device_check_ms_mbimex_version: * @self: a #MbimDevice. * @ms_mbimex_version_major: major version number of the MS MBIMEx support. * @ms_mbimex_version_minor: minor version number of the MS MBIMEx support. * * Checks the version number of the MS MBIMEx support in the device instance * against the one given as input. * * Returns: %TRUE if the version of the device instance is the same as or newer * than the passed-in version. * * Since: 1.28 */ gboolean mbim_device_check_ms_mbimex_version (MbimDevice *self, guint8 ms_mbimex_version_major, guint8 ms_mbimex_version_minor); /** * MbimDeviceOpenFlags: * @MBIM_DEVICE_OPEN_FLAGS_NONE: None. * @MBIM_DEVICE_OPEN_FLAGS_PROXY: Try to open the port through the 'mbim-proxy'. * @MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2: Try to enable MS MBIMEx 2.0 support. Since 1.28. * @MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3: Try to enable MS MBIMEx 3.0 support. Since 1.28. * * Flags to specify which actions to be performed when the device is open. * * Since: 1.10 */ typedef enum { /*< since=1.10 >*/ MBIM_DEVICE_OPEN_FLAGS_NONE = 0, MBIM_DEVICE_OPEN_FLAGS_PROXY = 1 << 0, MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2 = 1 << 1, MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3 = 1 << 2, } MbimDeviceOpenFlags; /** * mbim_device_open_full: * @self: a #MbimDevice. * @flags: a set of #MbimDeviceOpenFlags. * @timeout: maximum time, in seconds, to wait for the device to be opened. * @cancellable: optional #GCancellable object, #NULL to ignore. * @callback: a #GAsyncReadyCallback to call when the operation is finished. * @user_data: the data to pass to callback function. * * Asynchronously opens a #MbimDevice for I/O. * * This method is an extension of the generic mbim_device_open(), which allows * launching the #MbimDevice with proxy support. * * When the operation is finished @callback will be called. You can then call * mbim_device_open_full_finish() to get the result of the operation. * * Since: 1.10 */ void mbim_device_open_full (MbimDevice *self, MbimDeviceOpenFlags flags, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); /** * mbim_device_open_full_finish: * @self: a #MbimDevice. * @res: a #GAsyncResult. * @error: Return location for error or %NULL. * * Finishes an asynchronous open operation started with mbim_device_open_full(). * * Returns: %TRUE if successful, %FALSE if @error is set. * * Since: 1.10 */ gboolean mbim_device_open_full_finish (MbimDevice *self, GAsyncResult *res, GError **error); /** * mbim_device_open: * @self: a #MbimDevice. * @timeout: maximum time, in seconds, to wait for the device to be opened. * @cancellable: optional #GCancellable object, #NULL to ignore. * @callback: a #GAsyncReadyCallback to call when the operation is finished. * @user_data: the data to pass to callback function. * * Asynchronously opens a #MbimDevice for I/O. * * When the operation is finished @callback will be called. You can then call * mbim_device_open_finish() to get the result of the operation. * * Since: 1.0 */ void mbim_device_open (MbimDevice *self, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); /** * mbim_device_open_finish: * @self: a #MbimDevice. * @res: a #GAsyncResult. * @error: Return location for error or %NULL. * * Finishes an asynchronous open operation started with mbim_device_open(). * * Returns: %TRUE if successful, %FALSE if @error is set. * * Since: 1.0 */ gboolean mbim_device_open_finish (MbimDevice *self, GAsyncResult *res, GError **error); /** * mbim_device_close: * @self: a #MbimDevice. * @timeout: maximum time, in seconds, to wait for the device to be closed. * @cancellable: optional #GCancellable object, #NULL to ignore. * @callback: a #GAsyncReadyCallback to call when the operation is finished. * @user_data: the data to pass to callback function. * * Asynchronously closes a #MbimDevice for I/O. * * When the operation is finished @callback will be called. You can then call * mbim_device_close_finish() to get the result of the operation. * * Since: 1.0 */ void mbim_device_close (MbimDevice *self, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); /** * mbim_device_close_finish: * @self: a #MbimDevice. * @res: a #GAsyncResult. * @error: Return location for error or %NULL. * * Finishes an asynchronous close operation started with mbim_device_close(). * * Returns: %TRUE if successful, %FALSE if @error is set. * * Since: 1.0 */ gboolean mbim_device_close_finish (MbimDevice *self, GAsyncResult *res, GError **error); /** * mbim_device_close_force: * @self: a #MbimDevice. * @error: Return location for error or %NULL. * * Forces the #MbimDevice to be closed. * * Returns: %TRUE if @self if no error happens, otherwise %FALSE and @error is set. * * Since: 1.0 */ gboolean mbim_device_close_force (MbimDevice *self, GError **error); /** * mbim_device_get_next_transaction_id: * @self: A #MbimDevice. * * Acquire the next transaction ID of this #MbimDevice. * The internal transaction ID gets incremented. * * Returns: the next transaction ID. * * Since: 1.0 */ guint32 mbim_device_get_next_transaction_id (MbimDevice *self); /** * mbim_device_get_transaction_id: * @self: A #MbimDevice. * * Acquire the transaction ID of this #MbimDevice without * incrementing the internal transaction ID. * * Returns: the current transaction ID. * * Since: 1.24.4 */ guint32 mbim_device_get_transaction_id (MbimDevice *self); /** * mbim_device_get_consecutive_timeouts: * @self: a #MbimDevice. * * Gets the number of consecutive transaction timeouts in the device. * * Returns: a #guint. * * Since: 1.28 */ guint mbim_device_get_consecutive_timeouts (MbimDevice *self); /** * mbim_device_command: * @self: a #MbimDevice. * @message: the message to send. * @timeout: maximum time, in seconds, to wait for the response. * @cancellable: a #GCancellable, or %NULL. * @callback: a #GAsyncReadyCallback to call when the operation is finished. * @user_data: the data to pass to callback function. * * Asynchronously sends a #MbimMessage to the device. * * When the operation is finished @callback will be called. You can then call * mbim_device_command_finish() to get the result of the operation. * * Since: 1.0 */ void mbim_device_command (MbimDevice *self, MbimMessage *message, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); /** * mbim_device_command_finish: * @self: a #MbimDevice. * @res: a #GAsyncResult. * @error: Return location for error or %NULL. * * Finishes an operation started with mbim_device_command(). * * The returned #MbimMessage is ensured to be valid and complete (i.e. not a * partial fragment). There is no need to call mbim_message_validate() again. * * Returns: a #MbimMessage response, or #NULL if @error is set. The returned value should be freed with mbim_message_unref(). * * Since: 1.0 */ MbimMessage *mbim_device_command_finish (MbimDevice *self, GAsyncResult *res, GError **error); /** * MBIM_DEVICE_SESSION_ID_AUTOMATIC: * * Symbol defining a session id that will be automatically allocated during * runtime when creating net links. * * Since: 1.26 */ #define MBIM_DEVICE_SESSION_ID_AUTOMATIC G_MAXUINT /** * MBIM_DEVICE_SESSION_ID_MIN: * * Symbol defining the minimum supported session id.. * * Since: 1.26 */ #define MBIM_DEVICE_SESSION_ID_MIN 0 /** * MBIM_DEVICE_SESSION_ID_MAX: * * Symbol defining the maximum supported session id. * * Since: 1.26 */ #define MBIM_DEVICE_SESSION_ID_MAX 0xFF /** * mbim_device_add_link: * @self: a #MbimDevice. * @session_id: the session id for the link, in the * [#MBIM_DEVICE_SESSION_ID_MIN,#MBIM_DEVICE_SESSION_ID_MAX] range, or * #MBIM_DEVICE_SESSION_ID_AUTOMATIC to find the first available session id. * @base_ifname: the interface which the new link will be created on. * @ifname_prefix: the prefix suggested to be used for the name of the new link * created. * @cancellable: a #GCancellable, or %NULL. * @callback: a #GAsyncReadyCallback to call when the operation is finished. * @user_data: the data to pass to callback function. * * Asynchronously creates a new virtual network device node on top of * @base_ifname. This allows having multiple net interfaces running on top of * another using multiplexing. * * If the kernel driver doesn't allow this functionality, a * %MBIM_CORE_ERROR_UNSUPPORTED error will be returned. * * The operation may fail if the given interface name is not associated to the * MBIM control port managed by the #MbimDevice. * * Depending on the kernel driver in use, the given @ifname_prefix may be * ignored. The user should not assume that the returned link interface name is * prefixed with @ifname_prefix as it may not be the case. * * When the operation is finished @callback will be called. You can then call * mbim_device_add_link_finish() to get the result of the operation. * * Since: 1.26 */ void mbim_device_add_link (MbimDevice *self, guint session_id, const gchar *base_ifname, const gchar *ifname_prefix, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); /** * mbim_device_add_link_finish: * @self: a #MbimDevice. * @res: a #GAsyncResult. * @session_id: the session ID for the link created. * @error: Return location for error or %NULL. * * Finishes an operation started with mbim_device_add_link(). * * Returns: The name of the net interface created, %NULL if @error is set. * * Since: 1.26 */ gchar *mbim_device_add_link_finish (MbimDevice *self, GAsyncResult *res, guint *session_id, GError **error); /** * mbim_device_delete_link: * @self: a #MbimDevice. * @ifname: the name of the link to remove. * @cancellable: a #GCancellable, or %NULL. * @callback: a #GAsyncReadyCallback to call when the operation is finished. * @user_data: the data to pass to callback function. * * Asynchronously deletes a virtual network interface that has been previously * created with mbim_device_add_link(). * * If the kernel driver doesn't allow this functionality, a * %MBIM_CORE_ERROR_UNSUPPORTED error will be returned. * * When the operation is finished @callback will be called. You can then call * mbim_device_delete_link_finish() to get the result of the operation. * * Since: 1.26 */ void mbim_device_delete_link (MbimDevice *self, const gchar *ifname, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); /** * mbim_device_delete_link_finish: * @self: a #MbimDevice. * @res: a #GAsyncResult. * @error: Return location for error or %NULL. * * Finishes an operation started with mbim_device_delete_link(). * * Returns: %TRUE if successful, %FALSE if @error is set. * * Since: 1.26 */ gboolean mbim_device_delete_link_finish (MbimDevice *self, GAsyncResult *res, GError **error); /** * mbim_device_delete_all_links: * @self: a #MbimDevice. * @base_ifname: the interface where all links are available. * @cancellable: a #GCancellable, or %NULL. * @callback: a #GAsyncReadyCallback to call when the operation is finished. * @user_data: the data to pass to callback function. * * Asynchronously deletes all virtual network interfaces that have been previously * created with mbim_device_add_link() in @base_ifname. * * When the operation is finished @callback will be called. You can then call * mbim_device_delete_link_finish() to get the result of the operation. * * * There is no guarantee that other processes haven't created new links by the * time this method returns. This method should be used with caution, or in setups * where only one single process is expected to do MBIM network interface link * management. * * * Since: 1.26 */ void mbim_device_delete_all_links (MbimDevice *self, const gchar *base_ifname, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); /** * mbim_device_delete_all_links_finish: * @self: a #MbimDevice. * @res: a #GAsyncResult. * @error: Return location for error or %NULL. * * Finishes an operation started with mbim_device_delete_all_links(). * * Returns: %TRUE if successful, %FALSE if @error is set. * * Since: 1.26 */ gboolean mbim_device_delete_all_links_finish (MbimDevice *self, GAsyncResult *res, GError **error); /** * mbim_device_list_links: * @self: a #MbimDevice. * @base_ifname: the base interface. * @out_links: (out)(transfer full)(element-type utf8): a placeholder for the * output #GPtrArray of link names. * @error: Return location for error or %NULL. * * Synchronously lists all virtual network interfaces that have been previously * created with mbim_device_add_link() in @base_ifname. * * Returns: %TRUE if successful, %FALSE if @error is set. * * Since: 1.26 */ gboolean mbim_device_list_links (MbimDevice *self, const gchar *base_ifname, GPtrArray **out_links, GError **error); /** * mbim_device_check_link_supported: * @self: a #MbimDevice. * @error: Return location for error or %NULL. * * Checks whether link management is supported by the kernel. * * Returns: %TRUE if link management is supported, or %FALSE if @error is set. * * Since: 1.26 */ gboolean mbim_device_check_link_supported (MbimDevice *self, GError **error); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_DEVICE_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-enums.h000066400000000000000000002237141453630424100213370ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado */ #ifndef _LIBMBIM_GLIB_MBIM_ENUMS_H_ #define _LIBMBIM_GLIB_MBIM_ENUMS_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif G_BEGIN_DECLS /** * SECTION: mbim-enums * @title: Enumerations and Flags * @short_description: Common enumeration and flag types. * * This section defines common enum and flag types used in the interface. */ /*****************************************************************************/ /* 'Device Caps' enums */ /** * MbimDeviceType: * @MBIM_DEVICE_TYPE_UNKNOWN: Unknown type. * @MBIM_DEVICE_TYPE_EMBEDDED: Device is embedded in the system. * @MBIM_DEVICE_TYPE_REMOVABLE: Device is removable. * @MBIM_DEVICE_TYPE_REMOTE: Device is remote. * * Type of device. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_DEVICE_TYPE_UNKNOWN = 0, MBIM_DEVICE_TYPE_EMBEDDED = 1, MBIM_DEVICE_TYPE_REMOVABLE = 2, MBIM_DEVICE_TYPE_REMOTE = 3 } MbimDeviceType; /** * MbimCellularClass: * @MBIM_CELLULAR_CLASS_NONE: None. Since 1.30. * @MBIM_CELLULAR_CLASS_GSM: Device is 3GPP. * @MBIM_CELLULAR_CLASS_CDMA: Device is 3GPP2. * * Cellular class. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CELLULAR_CLASS_NONE = 0, MBIM_CELLULAR_CLASS_GSM = 1 << 0, MBIM_CELLULAR_CLASS_CDMA = 1 << 1 } MbimCellularClass; /** * MbimVoiceClass: * @MBIM_VOICE_CLASS_UNKNOWN: Unknown voice class. * @MBIM_VOICE_CLASS_NO_VOICE: Device doesn't support voice. * @MBIM_VOICE_CLASS_SEPARATED_VOICE_DATA: Device supports separate voice and data connections. * @MBIM_VOICE_CLASS_SIMULTANEOUS_VOICE_DATA: Device supports simultaneous voice and data connections. * * Voice class. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_VOICE_CLASS_UNKNOWN = 0, MBIM_VOICE_CLASS_NO_VOICE = 1, MBIM_VOICE_CLASS_SEPARATED_VOICE_DATA = 2, MBIM_VOICE_CLASS_SIMULTANEOUS_VOICE_DATA = 3 } MbimVoiceClass; /** * MbimSimClass: * @MBIM_SIM_CLASS_NONE: None. Since 1.30. * @MBIM_SIM_CLASS_LOGICAL: No physical SIM. * @MBIM_SIM_CLASS_REMOVABLE: Physical removable SIM. * * SIM class. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_SIM_CLASS_NONE = 0, MBIM_SIM_CLASS_LOGICAL = 1 << 0, MBIM_SIM_CLASS_REMOVABLE = 1 << 1 } MbimSimClass; /** * MbimDataClass: * @MBIM_DATA_CLASS_NONE: None. Since 1.30. * @MBIM_DATA_CLASS_GPRS: GPRS. * @MBIM_DATA_CLASS_EDGE: EDGE. * @MBIM_DATA_CLASS_UMTS: UMTS. * @MBIM_DATA_CLASS_HSDPA: HSDPA. * @MBIM_DATA_CLASS_HSUPA: HSUPA. * @MBIM_DATA_CLASS_LTE: LTE. * @MBIM_DATA_CLASS_5G_NSA: 5G NSA (MS MBIMEx v2.0). Since 1.28. * @MBIM_DATA_CLASS_5G_SA: 5G SA (MS MBIMEx v2.0). Since 1.28. * @MBIM_DATA_CLASS_1XRTT: 1xRTT. * @MBIM_DATA_CLASS_1XEVDO: 1xEV-DO. * @MBIM_DATA_CLASS_1XEVDO_REVA: 1xEV-DO RevA * @MBIM_DATA_CLASS_1XEVDV: 1xEV-DV. * @MBIM_DATA_CLASS_3XRTT: 3xRTT. * @MBIM_DATA_CLASS_1XEVDO_REVB: 1xEV-DO RevB. * @MBIM_DATA_CLASS_UMB: UMB. * @MBIM_DATA_CLASS_CUSTOM: Custom. * * Data class. * * Both 5G related values are introduced in MBIM Extension v2.0, but given * the update is compatible with the original MBIM enumeration, devices may * report them without having enabled MBIM Extension v2.0 support. * * This type is updated in MBIM Extension v3.0 in a non-backwards compatible * way, see #MbimDataClassV3. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_DATA_CLASS_NONE = 0, MBIM_DATA_CLASS_GPRS = 1 << 0, MBIM_DATA_CLASS_EDGE = 1 << 1, MBIM_DATA_CLASS_UMTS = 1 << 2, MBIM_DATA_CLASS_HSDPA = 1 << 3, MBIM_DATA_CLASS_HSUPA = 1 << 4, MBIM_DATA_CLASS_LTE = 1 << 5, MBIM_DATA_CLASS_5G_NSA = 1 << 6, MBIM_DATA_CLASS_5G_SA = 1 << 7, /* Bits 8 to 15 reserved for future 3GPP classes */ MBIM_DATA_CLASS_1XRTT = 1 << 16, MBIM_DATA_CLASS_1XEVDO = 1 << 17, MBIM_DATA_CLASS_1XEVDO_REVA = 1 << 18, MBIM_DATA_CLASS_1XEVDV = 1 << 19, MBIM_DATA_CLASS_3XRTT = 1 << 20, MBIM_DATA_CLASS_1XEVDO_REVB = 1 << 21, MBIM_DATA_CLASS_UMB = 1 << 22, /* Bits 23 to 30 reserved for future 3GPP2 classes */ MBIM_DATA_CLASS_CUSTOM = 1 << 31 } MbimDataClass; /** * MbimSmsCaps: * @MBIM_SMS_CAPS_NONE: None. Since 1.30. * @MBIM_SMS_CAPS_PDU_RECEIVE: Can receive in PDU mode. * @MBIM_SMS_CAPS_PDU_SEND: Can send in PDU mode. * @MBIM_SMS_CAPS_TEXT_RECEIVE: Can receive in text mode. * @MBIM_SMS_CAPS_TEXT_SEND: Can send in text mode. * * SMS capabilities. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_SMS_CAPS_NONE = 0, MBIM_SMS_CAPS_PDU_RECEIVE = 1 << 0, MBIM_SMS_CAPS_PDU_SEND = 1 << 1, MBIM_SMS_CAPS_TEXT_RECEIVE = 1 << 2, MBIM_SMS_CAPS_TEXT_SEND = 1 << 3 } MbimSmsCaps; /** * MbimCtrlCaps: * @MBIM_CTRL_CAPS_NONE: None. Since 1.28. * @MBIM_CTRL_CAPS_REG_MANUAL: Device allows manual network selection. * @MBIM_CTRL_CAPS_HW_RADIO_SWITCH: Device has a hardware radio power switch. * @MBIM_CTRL_CAPS_CDMA_MOBILE_IP: The CDMA function supports Mobile IP. * @MBIM_CTRL_CAPS_CDMA_SIMPLE_IP: The CDMA function supports Simple IP. * @MBIM_CTRL_CAPS_MULTI_CARRIER: Device can work with multiple providers. * @MBIM_CTRL_CAPS_ESIM: Device supports eSIM (MS MBIMEx v3.0). Since 1.28. * @MBIM_CTRL_CAPS_UE_POLICY_ROUTE_SELECTION: Device supports including the route selection descriptors as part of the UE policies (MS MBIMEx v3.0). Since 1.28. * @MBIM_CTRL_CAPS_SIM_HOT_SWAP_CAPABLE: Device supports SIM hot-swap (MS MBIMEx v3.0). Since 1.28. * * Control capabilities. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CTRL_CAPS_NONE = 0, MBIM_CTRL_CAPS_REG_MANUAL = 1 << 0, MBIM_CTRL_CAPS_HW_RADIO_SWITCH = 1 << 1, MBIM_CTRL_CAPS_CDMA_MOBILE_IP = 1 << 2, MBIM_CTRL_CAPS_CDMA_SIMPLE_IP = 1 << 3, MBIM_CTRL_CAPS_MULTI_CARRIER = 1 << 4, MBIM_CTRL_CAPS_ESIM = 1 << 5, MBIM_CTRL_CAPS_UE_POLICY_ROUTE_SELECTION = 1 << 6, MBIM_CTRL_CAPS_SIM_HOT_SWAP_CAPABLE = 1 << 7, } MbimCtrlCaps; /*****************************************************************************/ /* 'Subscriber Ready Status' enums */ /** * MbimSubscriberReadyState: * @MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED: Not initialized. * @MBIM_SUBSCRIBER_READY_STATE_INITIALIZED: Initialized. * @MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED: SIM not inserted. * @MBIM_SUBSCRIBER_READY_STATE_BAD_SIM: Bad SIM. * @MBIM_SUBSCRIBER_READY_STATE_FAILURE: Failure. * @MBIM_SUBSCRIBER_READY_STATE_NOT_ACTIVATED: Not activated. * @MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED: Device locked. * @MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE: The card is ready but does not * have any enabled profiles (MS MBIMEx). Since 1.28. * * Ready state of the subscriber. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED = 0, MBIM_SUBSCRIBER_READY_STATE_INITIALIZED = 1, MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED = 2, MBIM_SUBSCRIBER_READY_STATE_BAD_SIM = 3, MBIM_SUBSCRIBER_READY_STATE_FAILURE = 4, MBIM_SUBSCRIBER_READY_STATE_NOT_ACTIVATED = 5, MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED = 6, MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE = 7, } MbimSubscriberReadyState; /** * MbimReadyInfoFlag: * @MBIM_READY_INFO_FLAG_NONE: Device in normal mode. Since 1.16. * @MBIM_READY_INFO_FLAG_PROTECT_UNIQUE_ID: Request to avoid displaying subscriber ID. * * Flag specifying how the ready info is treated. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_READY_INFO_FLAG_NONE = 0, MBIM_READY_INFO_FLAG_PROTECT_UNIQUE_ID = 1 << 0 } MbimReadyInfoFlag; /*****************************************************************************/ /* 'Radio State' enums */ /** * MbimRadioSwitchState: * @MBIM_RADIO_SWITCH_STATE_OFF: Radio is off. * @MBIM_RADIO_SWITCH_STATE_ON: Radio is on. * * Radio switch state. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_RADIO_SWITCH_STATE_OFF = 0, MBIM_RADIO_SWITCH_STATE_ON = 1 } MbimRadioSwitchState; /*****************************************************************************/ /* 'Pin' enums */ /** * MbimPinType: * @MBIM_PIN_TYPE_UNKNOWN: Unknown or unset. * @MBIM_PIN_TYPE_CUSTOM: The PIN type is a custom type and is none of the other PIN types listed in this enumeration. * @MBIM_PIN_TYPE_PIN1: The PIN1 key. * @MBIM_PIN_TYPE_PIN2: The PIN2 key. * @MBIM_PIN_TYPE_DEVICE_SIM_PIN: The device to SIM key. * @MBIM_PIN_TYPE_DEVICE_FIRST_SIM_PIN: The device to very first SIM key. * @MBIM_PIN_TYPE_NETWORK_PIN: The network personalization key. * @MBIM_PIN_TYPE_NETWORK_SUBSET_PIN: The network subset personalization key. * @MBIM_PIN_TYPE_SERVICE_PROVIDER_PIN: The service provider (SP) personalization key. * @MBIM_PIN_TYPE_CORPORATE_PIN: The corporate personalization key. * @MBIM_PIN_TYPE_SUBSIDY_PIN: The subsidy unlock key. * @MBIM_PIN_TYPE_PUK1: The Personal Identification Number1 Unlock Key (PUK1). * @MBIM_PIN_TYPE_PUK2: The Personal Identification Number2 Unlock Key (PUK2). * @MBIM_PIN_TYPE_DEVICE_FIRST_SIM_PUK: The device to very first SIM PIN unlock key. * @MBIM_PIN_TYPE_NETWORK_PUK: The network personalization unlock key. * @MBIM_PIN_TYPE_NETWORK_SUBSET_PUK: The network subset personalization unlock key. * @MBIM_PIN_TYPE_SERVICE_PROVIDER_PUK: The service provider (SP) personalization unlock key. * @MBIM_PIN_TYPE_CORPORATE_PUK: The corporate personalization unlock key. * @MBIM_PIN_TYPE_NEV: The NEV key (MS UICC low-level access). Since 1.28. * @MBIM_PIN_TYPE_ADM: The administrative key (MS UICC low-level access). Since 1.28. * * PIN Types. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_PIN_TYPE_UNKNOWN = 0, MBIM_PIN_TYPE_CUSTOM = 1, MBIM_PIN_TYPE_PIN1 = 2, MBIM_PIN_TYPE_PIN2 = 3, MBIM_PIN_TYPE_DEVICE_SIM_PIN = 4, MBIM_PIN_TYPE_DEVICE_FIRST_SIM_PIN = 5, MBIM_PIN_TYPE_NETWORK_PIN = 6, MBIM_PIN_TYPE_NETWORK_SUBSET_PIN = 7, MBIM_PIN_TYPE_SERVICE_PROVIDER_PIN = 8, MBIM_PIN_TYPE_CORPORATE_PIN = 9, MBIM_PIN_TYPE_SUBSIDY_PIN = 10, MBIM_PIN_TYPE_PUK1 = 11, MBIM_PIN_TYPE_PUK2 = 12, MBIM_PIN_TYPE_DEVICE_FIRST_SIM_PUK = 13, MBIM_PIN_TYPE_NETWORK_PUK = 14, MBIM_PIN_TYPE_NETWORK_SUBSET_PUK = 15, MBIM_PIN_TYPE_SERVICE_PROVIDER_PUK = 16, MBIM_PIN_TYPE_CORPORATE_PUK = 17, MBIM_PIN_TYPE_NEV = 18, MBIM_PIN_TYPE_ADM = 19, } MbimPinType; /** * MbimPinState: * @MBIM_PIN_STATE_UNLOCKED: The device does not require a PIN. * @MBIM_PIN_STATE_LOCKED: The device requires the user to enter a PIN. * * PIN States. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_PIN_STATE_UNLOCKED = 0, MBIM_PIN_STATE_LOCKED = 1 } MbimPinState; /** * MbimPinOperation: * @MBIM_PIN_OPERATION_ENTER: Enter the specified PIN into the device. * @MBIM_PIN_OPERATION_ENABLE: Enable the specified PIN. * @MBIM_PIN_OPERATION_DISABLE: Disable the specified PIN. * @MBIM_PIN_OPERATION_CHANGE: Change the specified PIN. * * Operation to perform on the PIN. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_PIN_OPERATION_ENTER = 0, MBIM_PIN_OPERATION_ENABLE = 1, MBIM_PIN_OPERATION_DISABLE = 2, MBIM_PIN_OPERATION_CHANGE = 3 } MbimPinOperation; /*****************************************************************************/ /* 'Pin List' enums */ /** * MbimPinMode: * @MBIM_PIN_MODE_NOT_SUPPORTED: Not supported. * @MBIM_PIN_MODE_ENABLED: Enabled. * @MBIM_PIN_MODE_DISABLED: Disabled. * * Whether the lock is enabled or disabled. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_PIN_MODE_NOT_SUPPORTED = 0, MBIM_PIN_MODE_ENABLED = 1, MBIM_PIN_MODE_DISABLED = 2 } MbimPinMode; /** * MbimPinFormat: * @MBIM_PIN_FORMAT_UNKNOWN: Unknown format. * @MBIM_PIN_FORMAT_NUMERIC: Numeric-only format. * @MBIM_PIN_FORMAT_ALPHANUMERIC: Alphanumeric format. * * Format of the expected PIN code. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_PIN_FORMAT_UNKNOWN = 0, MBIM_PIN_FORMAT_NUMERIC = 1, MBIM_PIN_FORMAT_ALPHANUMERIC = 2 } MbimPinFormat; /*****************************************************************************/ /* 'Home Provider' enums */ /** * MbimProviderState: * @MBIM_PROVIDER_STATE_UNKNOWN: Unknown. * @MBIM_PROVIDER_STATE_HOME: Home operator. * @MBIM_PROVIDER_STATE_FORBIDDEN: Provider blocked. * @MBIM_PROVIDER_STATE_PREFERRED: Provider is in the preferred list. * @MBIM_PROVIDER_STATE_VISIBLE: Provider is visible. * @MBIM_PROVIDER_STATE_REGISTERED: Currently registered to the provider. * @MBIM_PROVIDER_STATE_PREFERRED_MULTICARRIER: Provider is a preferred multicarrier network. * * State of the provider. * * Since: 1.2 */ typedef enum { /*< since=1.2 >*/ MBIM_PROVIDER_STATE_UNKNOWN = 0, MBIM_PROVIDER_STATE_HOME = 1 << 0, MBIM_PROVIDER_STATE_FORBIDDEN = 1 << 1, MBIM_PROVIDER_STATE_PREFERRED = 1 << 2, MBIM_PROVIDER_STATE_VISIBLE = 1 << 3, MBIM_PROVIDER_STATE_REGISTERED = 1 << 4, MBIM_PROVIDER_STATE_PREFERRED_MULTICARRIER = 1 << 5 } MbimProviderState; /*****************************************************************************/ /* Connect V3' enums */ /** * MbimAccessMediaType: * @MBIM_ACCESS_MEDIA_TYPE_UNKNOWN: None, or unknown. * @MBIM_ACCESS_MEDIA_TYPE_3GPP: 3GPP only. * @MBIM_ACCESS_MEDIA_TYPE_3GPP_PREFERRED: 3GPP Preferred. * * Access type preference. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_ACCESS_MEDIA_TYPE_UNKNOWN = 0, MBIM_ACCESS_MEDIA_TYPE_3GPP = 1, MBIM_ACCESS_MEDIA_TYPE_3GPP_PREFERRED = 2, } MbimAccessMediaType; /*****************************************************************************/ /* 'Visible Providers' enums */ /** * MbimVisibleProvidersAction: * @MBIM_VISIBLE_PROVIDERS_ACTION_FULL_SCAN: Full scan. * @MBIM_VISIBLE_PROVIDERS_ACTION_RESTRICTED_SCAN: Locate preferred multicarrier providers. * * Type of action to perform when listing visible providers. * * Since: 1.2 */ typedef enum { /*< since=1.2 >*/ MBIM_VISIBLE_PROVIDERS_ACTION_FULL_SCAN = 0, MBIM_VISIBLE_PROVIDERS_ACTION_RESTRICTED_SCAN = 1 } MbimVisibleProvidersAction; /*****************************************************************************/ /* 'Register State' enums */ /** * MbimNwError: * @MBIM_NW_ERROR_NONE: No error. Since 1.28. * @MBIM_NW_ERROR_IMSI_UNKNOWN_IN_HLR: IMSI unknown in the HLR. * @MBIM_NW_ERROR_ILLEGAL_MS: Illegal MS. Since 1.10. * @MBIM_NW_ERROR_IMSI_UNKNOWN_IN_VLR: IMSI unknown in the VLR. * @MBIM_NW_ERROR_IMEI_NOT_ACCEPTED: IMEI not accepted. Since 1.10. * @MBIM_NW_ERROR_ILLEGAL_ME: Illegal ME. * @MBIM_NW_ERROR_GPRS_NOT_ALLOWED: GPRS not allowed. * @MBIM_NW_ERROR_GPRS_AND_NON_GPRS_NOT_ALLOWED: GPRS and non-GPRS not allowed. * @MBIM_NW_ERROR_MS_IDENTITY_NOT_DERIVED_BY_NETWORK: MS identity cannot be derived by the network. Since 1.10. * @MBIM_NW_ERROR_IMPLICITLY_DETACHED: Implicitly detached. Since 1.10. * @MBIM_NW_ERROR_PLMN_NOT_ALLOWED: PLMN not allowed. * @MBIM_NW_ERROR_LOCATION_AREA_NOT_ALLOWED: Location area not allowed. * @MBIM_NW_ERROR_ROAMING_NOT_ALLOWED_IN_LOCATION_AREA: Roaming not allowed in the location area. * @MBIM_NW_ERROR_GPRS_NOT_ALLOWED_IN_PLMN: GPRS not allowed in PLMN. * @MBIM_NW_ERROR_NO_CELLS_IN_LOCATION_AREA: No cells in location area. * @MBIM_NW_ERROR_MSC_TEMPORARILY_NOT_REACHABLE: MSC temporarily not reachable. Since 1.10. * @MBIM_NW_ERROR_NETWORK_FAILURE: Network failure. * @MBIM_NW_ERROR_MAC_FAILURE: MAC failure. Since 1.10. * @MBIM_NW_ERROR_SYNCH_FAILURE: Synch failure. Since 1.10. * @MBIM_NW_ERROR_CONGESTION: Congestion. * @MBIM_NW_ERROR_GSM_AUTHENTICATION_UNACCEPTABLE: GSM authentication unacceptable. Since 1.10. * @MBIM_NW_ERROR_NOT_AUTHORIZED_FOR_CSG: Not authorized for this CSG. Since 1.10. * @MBIM_NW_ERROR_INSUFFICIENT_RESOURCES: Insufficient resources. Since 1.18. * @MBIM_NW_ERROR_MISSING_OR_UNKNOWN_APN: Missing or unknown access point name. Since 1.10. * @MBIM_NW_ERROR_UNKNOWN_PDP_ADDRESS_OR_TYPE: Unknown PDP address or PDP type. Since 1.18. * @MBIM_NW_ERROR_USER_AUTHENTICATION_FAILED: User authentication failed. Since 1.18. * @MBIM_NW_ERROR_ACTIVATION_REJECTED_BY_GGSN_OR_GW: Activation rejected by GGSN, Serving GW or PDN GW. Since 1.18. * @MBIM_NW_ERROR_ACTIVATION_REJECTED_UNSPECIFIED: Activation rejected, unspecified. Since 1.18. * @MBIM_NW_ERROR_SERVICE_OPTION_NOT_SUPPORTED: Service option not supported. Since 1.10. * @MBIM_NW_ERROR_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED: Requested service option not subscribed. Since 1.10. * @MBIM_NW_ERROR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER: Service option temporarily out of order. Since 1.10. * @MBIM_NW_ERROR_NO_PDP_CONTEXT_ACTIVATED: No PDP context activated. Since 1.10. * @MBIM_NW_ERROR_SEMANTIC_ERROR_IN_THE_TFT_OPERATION: Semantic error in the TFT operation. Since 1.28. * @MBIM_NW_ERROR_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION: Syntactical error in the TFT operation. Since 1.28. * @MBIM_NW_ERROR_UNKNOWN_PDP_CONTEXT: Unknown PDP context. Since 1.28. * @MBIM_NW_ERROR_SEMANTIC_ERRORS_IN_PACKET_FILTER: Semantic errors in packet filter. Since 1.28. * @MBIM_NW_ERROR_SYNTACTICAL_ERRORS_IN_PACKET_FILTER: Syntactical errors in packet filter. Since 1.28. * @MBIM_NW_ERROR_PDP_CONTEXT_WITHOUT_TFT_ALREADY_ACTIVATED: PDP context without TFT already activated. Since 1.28. * @MBIM_NW_ERROR_REQUEST_REJECTED_OR_BEARER_CONTROL_MODE_VIOLATION: Request rejected, Bearer Control Mode violation. Since 1.28. * @MBIM_NW_ERROR_LAST_PDN_DISCONNECTION_NOT_ALLOWED: Last PDN disconnection not allowed. Since 1.28. * @MBIM_NW_ERROR_PDP_TYPE_IPV4_ONLY_ALLOWED: PDP type IPv4 only allowed. Since 1.18. * @MBIM_NW_ERROR_PDP_TYPE_IPV6_ONLY_ALLOWED: PDP type IPv6 only allowed. Since 1.18. * @MBIM_NW_ERROR_NO_NETWORK_SLICES_AVAILABLE: No network slices available Since 1.28. * @MBIM_NW_ERROR_MAXIMUM_NUMBER_OF_PDP_CONTEXTS_REACHED: Maximum number of PDP contexts reached. Since 1.18. * @MBIM_NW_ERROR_REQUESTED_APN_NOT_SUPPORTED_IN_CURRENT_RAT_AND_PLMN: Requested APN not supported in current RAT and PLMN combination. Since 1.18. * @MBIM_NW_ERROR_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE_AND_DNN: Insufficient resources for specific slice and DNN. Since 1.28. * @MBIM_NW_ERROR_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE: Insufficient resources for specific slice. Since 1.28. * @MBIM_NW_ERROR_NGKSI_ALREADY_IN_USE: NgKSI already in use. Since 1.28. * @MBIM_NW_ERROR_NON_3GPP_ACCESS_TO_5GCN_NOT_ALLOWED: Non-3GPP access to 5GCN not allowe. Since 1.28. * @MBIM_NW_ERROR_SERVING_NETWORK_NOT_AUTHORIZED: Serving network not authorized. Since 1.28. * @MBIM_NW_ERROR_TEMPORARILY_NOT_AUTHORIZED_FOR_THIS_SNPN: Temporarily not authorized for this SNPN. Since 1.28. * @MBIM_NW_ERROR_PERMANENTLY_NOT_AUTHORIZED_FOR_THIS_SNPN: Permanently not authorized for this SNPN. Since 1.28. * @MBIM_NW_ERROR_NOT_AUTHORIZED_FOR_THIS_CAG_OR_AUTHORIZED_FOR_CAG_CELLS_ONLY: Not authorized for this CAG or authorized for CAG cells. Since 1.28. * @MBIM_NW_ERROR_WIRELINE_ACCESS_AREA_NOT_ALLOWED: Wireline access area not allowed. Since 1.28. * @MBIM_NW_ERROR_PAYLOAD_WAS_NOT_FORWARDED: Payload was not forwarded. Since 1.28. * @MBIM_NW_ERROR_DNN_NOT_SUPPORTED_OR_NOT_SUBSCRIBED_IN_THE_SLICE: DNN not supported or not subscribed in the slice. Since 1.28. * @MBIM_NW_ERROR_INSUFFICIENT_USER_PLANE_RESOURCES_FOR_THE_PDU_SESSION: Insufficient user-plane resources for the PDU session. Since 1.28. * @MBIM_NW_ERROR_SEMANTICALLY_INCORRECT_MESSAGE: Semantically incorrect message. Since 1.10. * @MBIM_NW_ERROR_INVALID_MANDATORY_INFORMATION: Invalid mandatory information. Since 1.10. * @MBIM_NW_ERROR_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED: Message type non-existent or not implemented. Since 1.10. * @MBIM_NW_ERROR_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE: Message type not compatible with protocol state. Since 1.10. * @MBIM_NW_ERROR_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED: Information element non-existent or not implemented. Since 1.10. * @MBIM_NW_ERROR_CONDITIONAL_IE_ERROR: Conditional IE error. Since 1.10. * @MBIM_NW_ERROR_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE: Message not compatible with protocol state. Since 1.10. * @MBIM_NW_ERROR_PROTOCOL_ERROR_UNSPECIFIED: Protocol error, unspecified. Since 1.10. * @MBIM_NW_ERROR_APN_RESTRICTION_VALUE_INCOMPATIBLE_WITH_ACTIVE_PDP_CONTEXT: APN restriction value incompatible with active PDP context. Since 1.18. * @MBIM_NW_ERROR_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED: Multiple accesses to a PDN connection not allowed. Since 1.18. * * Network errors. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_NW_ERROR_NONE = 0, MBIM_NW_ERROR_IMSI_UNKNOWN_IN_HLR = 2, MBIM_NW_ERROR_ILLEGAL_MS = 3, MBIM_NW_ERROR_IMSI_UNKNOWN_IN_VLR = 4, MBIM_NW_ERROR_IMEI_NOT_ACCEPTED = 5, MBIM_NW_ERROR_ILLEGAL_ME = 6, MBIM_NW_ERROR_GPRS_NOT_ALLOWED = 7, MBIM_NW_ERROR_GPRS_AND_NON_GPRS_NOT_ALLOWED = 8, MBIM_NW_ERROR_MS_IDENTITY_NOT_DERIVED_BY_NETWORK = 9, MBIM_NW_ERROR_IMPLICITLY_DETACHED = 10, MBIM_NW_ERROR_PLMN_NOT_ALLOWED = 11, MBIM_NW_ERROR_LOCATION_AREA_NOT_ALLOWED = 12, MBIM_NW_ERROR_ROAMING_NOT_ALLOWED_IN_LOCATION_AREA = 13, MBIM_NW_ERROR_GPRS_NOT_ALLOWED_IN_PLMN = 14, MBIM_NW_ERROR_NO_CELLS_IN_LOCATION_AREA = 15, MBIM_NW_ERROR_MSC_TEMPORARILY_NOT_REACHABLE = 16, MBIM_NW_ERROR_NETWORK_FAILURE = 17, MBIM_NW_ERROR_MAC_FAILURE = 20, MBIM_NW_ERROR_SYNCH_FAILURE = 21, MBIM_NW_ERROR_CONGESTION = 22, MBIM_NW_ERROR_GSM_AUTHENTICATION_UNACCEPTABLE = 23, MBIM_NW_ERROR_NOT_AUTHORIZED_FOR_CSG = 25, MBIM_NW_ERROR_INSUFFICIENT_RESOURCES = 26, MBIM_NW_ERROR_MISSING_OR_UNKNOWN_APN = 27, MBIM_NW_ERROR_UNKNOWN_PDP_ADDRESS_OR_TYPE = 28, MBIM_NW_ERROR_USER_AUTHENTICATION_FAILED = 29, MBIM_NW_ERROR_ACTIVATION_REJECTED_BY_GGSN_OR_GW = 30, MBIM_NW_ERROR_ACTIVATION_REJECTED_UNSPECIFIED = 31, MBIM_NW_ERROR_SERVICE_OPTION_NOT_SUPPORTED = 32, MBIM_NW_ERROR_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED = 33, MBIM_NW_ERROR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER = 34, MBIM_NW_ERROR_NO_PDP_CONTEXT_ACTIVATED = 40, MBIM_NW_ERROR_SEMANTIC_ERROR_IN_THE_TFT_OPERATION = 41, MBIM_NW_ERROR_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION = 42, MBIM_NW_ERROR_UNKNOWN_PDP_CONTEXT = 43, MBIM_NW_ERROR_SEMANTIC_ERRORS_IN_PACKET_FILTER = 44, MBIM_NW_ERROR_SYNTACTICAL_ERRORS_IN_PACKET_FILTER = 45, MBIM_NW_ERROR_PDP_CONTEXT_WITHOUT_TFT_ALREADY_ACTIVATED = 46, MBIM_NW_ERROR_REQUEST_REJECTED_OR_BEARER_CONTROL_MODE_VIOLATION = 48, MBIM_NW_ERROR_LAST_PDN_DISCONNECTION_NOT_ALLOWED = 49, MBIM_NW_ERROR_PDP_TYPE_IPV4_ONLY_ALLOWED = 50, MBIM_NW_ERROR_PDP_TYPE_IPV6_ONLY_ALLOWED = 51, MBIM_NW_ERROR_NO_NETWORK_SLICES_AVAILABLE = 62, MBIM_NW_ERROR_MAXIMUM_NUMBER_OF_PDP_CONTEXTS_REACHED = 65, MBIM_NW_ERROR_REQUESTED_APN_NOT_SUPPORTED_IN_CURRENT_RAT_AND_PLMN = 66, MBIM_NW_ERROR_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE_AND_DNN = 67, MBIM_NW_ERROR_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE = 69, MBIM_NW_ERROR_NGKSI_ALREADY_IN_USE = 71, MBIM_NW_ERROR_NON_3GPP_ACCESS_TO_5GCN_NOT_ALLOWED = 72, MBIM_NW_ERROR_SERVING_NETWORK_NOT_AUTHORIZED = 73, MBIM_NW_ERROR_TEMPORARILY_NOT_AUTHORIZED_FOR_THIS_SNPN = 74, MBIM_NW_ERROR_PERMANENTLY_NOT_AUTHORIZED_FOR_THIS_SNPN = 75, MBIM_NW_ERROR_NOT_AUTHORIZED_FOR_THIS_CAG_OR_AUTHORIZED_FOR_CAG_CELLS_ONLY = 76, MBIM_NW_ERROR_WIRELINE_ACCESS_AREA_NOT_ALLOWED = 77, MBIM_NW_ERROR_PAYLOAD_WAS_NOT_FORWARDED = 90, MBIM_NW_ERROR_DNN_NOT_SUPPORTED_OR_NOT_SUBSCRIBED_IN_THE_SLICE = 91, MBIM_NW_ERROR_INSUFFICIENT_USER_PLANE_RESOURCES_FOR_THE_PDU_SESSION = 92, MBIM_NW_ERROR_SEMANTICALLY_INCORRECT_MESSAGE = 95, MBIM_NW_ERROR_INVALID_MANDATORY_INFORMATION = 96, MBIM_NW_ERROR_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED = 97, MBIM_NW_ERROR_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98, MBIM_NW_ERROR_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED = 99, MBIM_NW_ERROR_CONDITIONAL_IE_ERROR = 100, MBIM_NW_ERROR_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101, MBIM_NW_ERROR_PROTOCOL_ERROR_UNSPECIFIED = 111, MBIM_NW_ERROR_APN_RESTRICTION_VALUE_INCOMPATIBLE_WITH_ACTIVE_PDP_CONTEXT = 112, MBIM_NW_ERROR_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED = 113 } MbimNwError; /** * MbimRegisterAction: * @MBIM_REGISTER_ACTION_AUTOMATIC: Automatic registration. * @MBIM_REGISTER_ACTION_MANUAL: Manual registration. * * Type of registration requested. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_REGISTER_ACTION_AUTOMATIC = 0, MBIM_REGISTER_ACTION_MANUAL = 1 } MbimRegisterAction; /** * MbimRegisterState: * @MBIM_REGISTER_STATE_UNKNOWN: Unknown registration state. * @MBIM_REGISTER_STATE_DEREGISTERED: Not registered. * @MBIM_REGISTER_STATE_SEARCHING: Searching. * @MBIM_REGISTER_STATE_HOME: Registered in home network. * @MBIM_REGISTER_STATE_ROAMING: Registered in roaming network. * @MBIM_REGISTER_STATE_PARTNER: Registered in a preferred roaming network. * @MBIM_REGISTER_STATE_DENIED: Registration denied. * * Registration state. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_REGISTER_STATE_UNKNOWN = 0, MBIM_REGISTER_STATE_DEREGISTERED = 1, MBIM_REGISTER_STATE_SEARCHING = 2, MBIM_REGISTER_STATE_HOME = 3, MBIM_REGISTER_STATE_ROAMING = 4, MBIM_REGISTER_STATE_PARTNER = 5, MBIM_REGISTER_STATE_DENIED = 6 } MbimRegisterState; /** * MbimRegisterMode: * @MBIM_REGISTER_MODE_UNKNOWN: Unknown. * @MBIM_REGISTER_MODE_AUTOMATIC: Automatic registration. * @MBIM_REGISTER_MODE_MANUAL: Manual registration. * * Type of registration requested. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_REGISTER_MODE_UNKNOWN = 0, MBIM_REGISTER_MODE_AUTOMATIC = 1, MBIM_REGISTER_MODE_MANUAL = 2 } MbimRegisterMode; /** * MbimRegistrationFlag: * @MBIM_REGISTRATION_FLAG_NONE: None. * @MBIM_REGISTRATION_FLAG_MANUAL_SELECTION_NOT_AVAILABLE: Network doesn't support manual network selection. * @MBIM_REGISTRATION_FLAG_PACKET_SERVICE_AUTOMATIC_ATTACH: Modem should auto-attach to the network after registration. Since 1.8. * * Registration flags. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_REGISTRATION_FLAG_NONE = 0, MBIM_REGISTRATION_FLAG_MANUAL_SELECTION_NOT_AVAILABLE = 1 << 0, MBIM_REGISTRATION_FLAG_PACKET_SERVICE_AUTOMATIC_ATTACH = 1 << 1, } MbimRegistrationFlag; /*****************************************************************************/ /* 'Wake Reason' enums */ /** * MbimWakeType: * @MBIM_WAKE_TYPE_CID_RESPONSE: A CID response wakes device. * @MBIM_WAKE_TYPE_CID_INDICATION: A CID indication wakes device. * @MBIM_WAKE_TYPE_PACKET: An incoming packet wakes device. * * Wake type. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_WAKE_TYPE_CID_RESPONSE = 0, MBIM_WAKE_TYPE_CID_INDICATION = 1, MBIM_WAKE_TYPE_PACKET = 2, } MbimWakeType; /*****************************************************************************/ /* 'Packet Service' enums */ /** * MbimPacketServiceAction: * @MBIM_PACKET_SERVICE_ACTION_ATTACH: Attach. * @MBIM_PACKET_SERVICE_ACTION_DETACH: Detach. * * Packet Service Action. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_PACKET_SERVICE_ACTION_ATTACH = 0, MBIM_PACKET_SERVICE_ACTION_DETACH = 1 } MbimPacketServiceAction; /** * MbimPacketServiceState: * @MBIM_PACKET_SERVICE_STATE_UNKNOWN: Unknown. * @MBIM_PACKET_SERVICE_STATE_ATTACHING: Attaching. * @MBIM_PACKET_SERVICE_STATE_ATTACHED: Attached. * @MBIM_PACKET_SERVICE_STATE_DETACHING: Detaching. * @MBIM_PACKET_SERVICE_STATE_DETACHED: Detached. * * Packet Service State. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_PACKET_SERVICE_STATE_UNKNOWN = 0, MBIM_PACKET_SERVICE_STATE_ATTACHING = 1, MBIM_PACKET_SERVICE_STATE_ATTACHED = 2, MBIM_PACKET_SERVICE_STATE_DETACHING = 3, MBIM_PACKET_SERVICE_STATE_DETACHED = 4 } MbimPacketServiceState; /*****************************************************************************/ /* 'Connect' enums */ /** * MbimActivationCommand: * @MBIM_ACTIVATION_COMMAND_DEACTIVATE: Deactivate. * @MBIM_ACTIVATION_COMMAND_ACTIVATE: Activate. * * Activation Command. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_ACTIVATION_COMMAND_DEACTIVATE = 0, MBIM_ACTIVATION_COMMAND_ACTIVATE = 1 } MbimActivationCommand; /** * MbimCompression: * @MBIM_COMPRESSION_NONE: None. * @MBIM_COMPRESSION_ENABLE: Enable. * * Compression. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_COMPRESSION_NONE = 0, MBIM_COMPRESSION_ENABLE = 1 } MbimCompression; /** * MbimAuthProtocol: * @MBIM_AUTH_PROTOCOL_NONE: None. * @MBIM_AUTH_PROTOCOL_PAP: Pap. * @MBIM_AUTH_PROTOCOL_CHAP: Chap. * @MBIM_AUTH_PROTOCOL_MSCHAPV2: V2. * * Auth Protocol. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_AUTH_PROTOCOL_NONE = 0, MBIM_AUTH_PROTOCOL_PAP = 1, MBIM_AUTH_PROTOCOL_CHAP = 2, MBIM_AUTH_PROTOCOL_MSCHAPV2 = 3 } MbimAuthProtocol; /** * MbimContextIpType: * @MBIM_CONTEXT_IP_TYPE_DEFAULT: It is up to the function to decide, the host does not care. * @MBIM_CONTEXT_IP_TYPE_IPV4: IPv4 context. * @MBIM_CONTEXT_IP_TYPE_IPV6: IPv6 context. * @MBIM_CONTEXT_IP_TYPE_IPV4V6: The context is IPv4, IPv6 or dualstack IPv4v6. * @MBIM_CONTEXT_IP_TYPE_IPV4_AND_IPV6: Both an IPv4 and an IPv6 context. * * Context IP Type. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CONTEXT_IP_TYPE_DEFAULT = 0, MBIM_CONTEXT_IP_TYPE_IPV4 = 1, MBIM_CONTEXT_IP_TYPE_IPV6 = 2, MBIM_CONTEXT_IP_TYPE_IPV4V6 = 3, MBIM_CONTEXT_IP_TYPE_IPV4_AND_IPV6 = 4 } MbimContextIpType; /** * MbimActivationState: * @MBIM_ACTIVATION_STATE_UNKNOWN: Unknown. * @MBIM_ACTIVATION_STATE_ACTIVATED: Activated. * @MBIM_ACTIVATION_STATE_ACTIVATING: Activating. * @MBIM_ACTIVATION_STATE_DEACTIVATED: Deactivated. * @MBIM_ACTIVATION_STATE_DEACTIVATING: Deactivating. * * Activation State. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_ACTIVATION_STATE_UNKNOWN = 0, MBIM_ACTIVATION_STATE_ACTIVATED = 1, MBIM_ACTIVATION_STATE_ACTIVATING = 2, MBIM_ACTIVATION_STATE_DEACTIVATED = 3, MBIM_ACTIVATION_STATE_DEACTIVATING = 4 } MbimActivationState; /** * MbimVoiceCallState: * @MBIM_VOICE_CALL_STATE_NONE: None. * @MBIM_VOICE_CALL_STATE_IN_PROGRESS: Progress. * @MBIM_VOICE_CALL_STATE_HANG_UP: Up. * * Voice Call State. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_VOICE_CALL_STATE_NONE = 0, MBIM_VOICE_CALL_STATE_IN_PROGRESS = 1, MBIM_VOICE_CALL_STATE_HANG_UP = 2 } MbimVoiceCallState; /*****************************************************************************/ /* 'IP Configuration' enums */ /** * MbimIPConfigurationAvailableFlag: * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE: No info available. * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS: Address info available. * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY: Gateway info available. * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS: DNS info available. * @MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU: MTU info available. * * Mask of available information about an IP address. * * Since: 1.0 */ typedef enum { /*< underscore_name=mbim_ip_configuration_available_flag,since=1.0 >*/ MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE = 0, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS = 1 << 0, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY = 1 << 1, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS = 1 << 2, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU = 1 << 3, } MbimIPConfigurationAvailableFlag; /*****************************************************************************/ /* 'SMS Configuration' enums */ /** * MbimSmsStorageState: * @MBIM_SMS_STORAGE_STATE_NOT_INITIALIZED: Storage not initialized. * @MBIM_SMS_STORAGE_STATE_INITIALIZED: Storage initialized. * * State of the SMS storage. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_SMS_STORAGE_STATE_NOT_INITIALIZED = 0, MBIM_SMS_STORAGE_STATE_INITIALIZED = 1 } MbimSmsStorageState; /** * MbimSmsFormat: * @MBIM_SMS_FORMAT_PDU: PDU format. * @MBIM_SMS_FORMAT_CDMA: CDMA format. * * SMS format. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_SMS_FORMAT_PDU = 0, MBIM_SMS_FORMAT_CDMA = 1 } MbimSmsFormat; /*****************************************************************************/ /* 'SMS Read' enums */ /** * MbimSmsFlag: * @MBIM_SMS_FLAG_ALL: All. * @MBIM_SMS_FLAG_INDEX: Index. * @MBIM_SMS_FLAG_NEW: New. * @MBIM_SMS_FLAG_OLD: Old. * @MBIM_SMS_FLAG_SENT: Sent. * @MBIM_SMS_FLAG_DRAFT: Draft. * * Flags to use when requesting to read SMS. @MBIM_SMS_FLAG_ALL and * @MBIM_SMS_FLAG_NEW are mandatory, all the others are optional. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_SMS_FLAG_ALL = 0, MBIM_SMS_FLAG_INDEX = 1, MBIM_SMS_FLAG_NEW = 2, MBIM_SMS_FLAG_OLD = 3, MBIM_SMS_FLAG_SENT = 4, MBIM_SMS_FLAG_DRAFT = 5 } MbimSmsFlag; /** * MbimSmsCdmaLang: * @MBIM_SMS_CDMA_LANG_UNKNOWN: Unknown language. * @MBIM_SMS_CDMA_LANG_ENGLISH: English. * @MBIM_SMS_CDMA_LANG_FRENCH: French. * @MBIM_SMS_CDMA_LANG_SPANISH: Spanish. * @MBIM_SMS_CDMA_LANG_JAPANESE: Japanese. * @MBIM_SMS_CDMA_LANG_KOREAN: Korean. * @MBIM_SMS_CDMA_LANG_CHINESE: Chinese. * @MBIM_SMS_CDMA_LANG_HEBREW: Hebrew. * * Language of a CDMA SMS. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_SMS_CDMA_LANG_UNKNOWN = 0, MBIM_SMS_CDMA_LANG_ENGLISH = 1, MBIM_SMS_CDMA_LANG_FRENCH = 2, MBIM_SMS_CDMA_LANG_SPANISH = 3, MBIM_SMS_CDMA_LANG_JAPANESE = 4, MBIM_SMS_CDMA_LANG_KOREAN = 5, MBIM_SMS_CDMA_LANG_CHINESE = 6, MBIM_SMS_CDMA_LANG_HEBREW = 7 } MbimSmsCdmaLang; /** * MbimSmsCdmaEncoding: * @MBIM_SMS_CDMA_ENCODING_OCTET: Octet. * @MBIM_SMS_CDMA_ENCODING_EPM: EPM. * @MBIM_SMS_CDMA_ENCODING_7BIT_ASCII: 7-bit ASCII. * @MBIM_SMS_CDMA_ENCODING_LA5: LA5. * @MBIM_SMS_CDMA_ENCODING_UNICODE: Unicode. * @MBIM_SMS_CDMA_ENCODING_SHIFT_JIS: Shift JIS. * @MBIM_SMS_CDMA_ENCODING_KOREAN: Korean. * @MBIM_SMS_CDMA_ENCODING_LATIN_HEBREW: Latin hebrew. * @MBIM_SMS_CDMA_ENCODING_LATIN: Latin. * @MBIM_SMS_CDMA_ENCODING_GSM_7BIT: 7-bit GSM. * * Type of encoding of a CDMA SMS. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_SMS_CDMA_ENCODING_OCTET = 0, MBIM_SMS_CDMA_ENCODING_EPM = 1, MBIM_SMS_CDMA_ENCODING_7BIT_ASCII = 2, MBIM_SMS_CDMA_ENCODING_LA5 = 3, MBIM_SMS_CDMA_ENCODING_UNICODE = 4, MBIM_SMS_CDMA_ENCODING_SHIFT_JIS = 5, MBIM_SMS_CDMA_ENCODING_KOREAN = 6, MBIM_SMS_CDMA_ENCODING_LATIN_HEBREW = 7, MBIM_SMS_CDMA_ENCODING_LATIN = 8, MBIM_SMS_CDMA_ENCODING_GSM_7BIT = 9 } MbimSmsCdmaEncoding; /** * MbimSmsStatus: * @MBIM_SMS_STATUS_NEW: New. * @MBIM_SMS_STATUS_OLD: Old. * @MBIM_SMS_STATUS_DRAFT: Draft. * @MBIM_SMS_STATUS_SENT: Sent. * * Status of a SMS message. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_SMS_STATUS_NEW = 0, MBIM_SMS_STATUS_OLD = 1, MBIM_SMS_STATUS_DRAFT = 2, MBIM_SMS_STATUS_SENT = 3 } MbimSmsStatus; /*****************************************************************************/ /* 'SMS Message Store Status' enums */ /** * MbimSmsStatusFlag: * @MBIM_SMS_STATUS_FLAG_NONE: None. * @MBIM_SMS_STATUS_FLAG_MESSAGE_STORE_FULL: Message store is full. * @MBIM_SMS_STATUS_FLAG_NEW_MESSAGE: New non-Class 0 message arrived. * * SMS status flags. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_SMS_STATUS_FLAG_NONE = 0, MBIM_SMS_STATUS_FLAG_MESSAGE_STORE_FULL = 1 << 0, MBIM_SMS_STATUS_FLAG_NEW_MESSAGE = 1 << 1, } MbimSmsStatusFlag; /*****************************************************************************/ /* 'USSD' enums */ /** * MbimUssdAction: * @MBIM_USSD_ACTION_INITIATE: Initiate USSD session. * @MBIM_USSD_ACTION_CONTINUE: Continue USSD session. * @MBIM_USSD_ACTION_CANCEL: Cancel USSD session. * * USSD action. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_USSD_ACTION_INITIATE = 0, MBIM_USSD_ACTION_CONTINUE = 1, MBIM_USSD_ACTION_CANCEL = 2 } MbimUssdAction; /** * MbimUssdResponse: * @MBIM_USSD_RESPONSE_NO_ACTION_REQUIRED: No action required. * @MBIM_USSD_RESPONSE_ACTION_REQUIRED: An action is required. * @MBIM_USSD_RESPONSE_TERMINATED_BY_NETWORK: Terminated by network * @MBIM_USSD_RESPONSE_OTHER_LOCAL_CLIENT: Other local client. * @MBIM_USSD_RESPONSE_OPERATION_NOT_SUPPORTED: Operation not supported. * @MBIM_USSD_RESPONSE_NETWORK_TIMEOUT: Network timeout. * * USSD response. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_USSD_RESPONSE_NO_ACTION_REQUIRED = 0, MBIM_USSD_RESPONSE_ACTION_REQUIRED = 1, MBIM_USSD_RESPONSE_TERMINATED_BY_NETWORK = 2, MBIM_USSD_RESPONSE_OTHER_LOCAL_CLIENT = 3, MBIM_USSD_RESPONSE_OPERATION_NOT_SUPPORTED = 4, MBIM_USSD_RESPONSE_NETWORK_TIMEOUT = 5 } MbimUssdResponse; /** * MbimUssdSessionState: * @MBIM_USSD_SESSION_STATE_NEW_SESSION: New session. * @MBIM_USSD_SESSION_STATE_EXISTING_SESSION: Existing session. * * Session state. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_USSD_SESSION_STATE_NEW_SESSION = 0, MBIM_USSD_SESSION_STATE_EXISTING_SESSION = 1 } MbimUssdSessionState; /*****************************************************************************/ /* 'Phonebook configuration' enums */ /** * MbimPhonebookState: * @MBIM_PHONEBOOK_STATE_NOT_INITIALIZED: Not initialized. * @MBIM_PHONEBOOK_STATE_INITIALIZED: Initialized * * Phonebook state. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_PHONEBOOK_STATE_NOT_INITIALIZED = 0, MBIM_PHONEBOOK_STATE_INITIALIZED = 1 } MbimPhonebookState; /*****************************************************************************/ /* 'Phonebook read' enums */ /** * MbimPhonebookFlag: * @MBIM_PHONEBOOK_FLAG_ALL: Request all. * @MBIM_PHONEBOOK_FLAG_INDEX: Request single entry by index. * * Flags to use when reading the phonebook. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_PHONEBOOK_FLAG_ALL = 0, MBIM_PHONEBOOK_FLAG_INDEX = 1 } MbimPhonebookFlag; /** * MbimPhonebookWriteFlag: * @MBIM_PHONEBOOK_WRITE_FLAG_SAVE_UNUSED: Store the record in an unused slot. * @MBIM_PHONEBOOK_WRITE_FLAG_SAVE_INDEX: Index where to store the record. * * Flags to use when writing the phonebook. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_PHONEBOOK_WRITE_FLAG_SAVE_UNUSED = 0, MBIM_PHONEBOOK_WRITE_FLAG_SAVE_INDEX = 1, } MbimPhonebookWriteFlag; /*****************************************************************************/ /* 'STK PAC' enums */ /** * MbimStkPacProfile: * @MBIM_STK_PAC_PROFILE_NOT_HANDLED_BY_FUNCTION_HANDLED_BY_HOST: Command not handled by function but handled by host. * @MBIM_STK_PAC_PROFILE_NOT_HANDLED_BY_FUNCTION_MAY_BE_HANDLED_BY_HOST: Command not handled by function but may be handled by host. * @MBIM_STK_PAC_PROFILE_HANDLED_BY_FUNCTION_ONLY_TRANSPARENT_TO_HOST: Command handled by function without informing the host. * @MBIM_STK_PAC_PROFILE_HANDLED_BY_FUNCTION_NOTIFICATION_TO_HOST_POSSIBLE: Command handled by function without informing the host, but notifications may be sent to host. * @MBIM_STK_PAC_PROFILE_HANDLED_BY_FUNCTION_NOTIFICATIONS_TO_HOST_ENABLED: Command handled by function, and the function wil also send notification to the host. * @MBIM_STK_PAC_PROFILE_HANDLED_BY_FUNCTION_CAN_BE_OVERRIDEN_BY_HOST: Command handled by function, but the host may request full control of the command. * @MBIM_STK_PAC_PROFILE_HANDLED_BY_HOST_FUNCTION_NOT_ABLE_TO_HANDLE: Command will be forwarded to the host. If the host decides not to receive the command, the function will not handle it. * @MBIM_STK_PAC_PROFILE_HANDLED_BY_HOST_FUNCTION_ABLE_TO_HANDLE: Command will be forwarded to the host. If the host decides not to receive the command, the function will handle it. * * Proactive command profile. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_STK_PAC_PROFILE_NOT_HANDLED_BY_FUNCTION_HANDLED_BY_HOST = 0, MBIM_STK_PAC_PROFILE_NOT_HANDLED_BY_FUNCTION_MAY_BE_HANDLED_BY_HOST = 1, MBIM_STK_PAC_PROFILE_HANDLED_BY_FUNCTION_ONLY_TRANSPARENT_TO_HOST = 2, MBIM_STK_PAC_PROFILE_HANDLED_BY_FUNCTION_NOTIFICATION_TO_HOST_POSSIBLE = 3, MBIM_STK_PAC_PROFILE_HANDLED_BY_FUNCTION_NOTIFICATIONS_TO_HOST_ENABLED = 4, MBIM_STK_PAC_PROFILE_HANDLED_BY_FUNCTION_CAN_BE_OVERRIDEN_BY_HOST = 5, MBIM_STK_PAC_PROFILE_HANDLED_BY_HOST_FUNCTION_NOT_ABLE_TO_HANDLE = 6, MBIM_STK_PAC_PROFILE_HANDLED_BY_HOST_FUNCTION_ABLE_TO_HANDLE = 7 } MbimStkPacProfile; /** * MbimStkPacType: * @MBIM_STK_PAC_TYPE_PROACTIVE_COMMAND: Host is requested to handle the Proactive command. * @MBIM_STK_PAC_TYPE_NOTIFICATION: Proactive command is handled by the function, but the host is notified. * * Type of proactive command. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_STK_PAC_TYPE_PROACTIVE_COMMAND = 0, MBIM_STK_PAC_TYPE_NOTIFICATION = 1 } MbimStkPacType; /*****************************************************************************/ /* 'Network idle hint' enums */ /** * MbimNetworkIdleHintState: * @MBIM_NETWORK_IDLE_HINT_STATE_DISABLED: Disabled. * @MBIM_NETWORK_IDLE_HINT_STATE_ENABLED: Enabled. * * Enable or disable network idle hint. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_NETWORK_IDLE_HINT_STATE_DISABLED = 0, MBIM_NETWORK_IDLE_HINT_STATE_ENABLED = 1 } MbimNetworkIdleHintState; /*****************************************************************************/ /* 'Emergency mode' enums */ /** * MbimEmergencyModeState: * @MBIM_EMERGENCY_MODE_STATE_OFF: Off. * @MBIM_EMERGENCY_MODE_STATE_ON: On. * * Emergency mode state. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_EMERGENCY_MODE_STATE_OFF = 0, MBIM_EMERGENCY_MODE_STATE_ON = 1 } MbimEmergencyModeState; /*****************************************************************************/ /* 'DSS connect' enums */ /** * MbimDssLinkState: * @MBIM_DSS_LINK_STATE_DEACTIVATE: Deactivate. * @MBIM_DSS_LINK_STATE_ACTIVATE: Activate. * * Action performed in the link state. * * Since: 1.4 */ typedef enum { /*< since=1.4 >*/ MBIM_DSS_LINK_STATE_DEACTIVATE = 0, MBIM_DSS_LINK_STATE_ACTIVATE = 1 } MbimDssLinkState; /*****************************************************************************/ /* 'QDU update session' enums */ /** * MbimQduSessionAction: * @MBIM_QDU_SESSION_ACTION_START: Start. * @MBIM_QDU_SESSION_ACTION_STOP: Stop. * * Action performed for the session initialization. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_QDU_SESSION_ACTION_START = 0, MBIM_QDU_SESSION_ACTION_STOP = 1, } MbimQduSessionAction; /*****************************************************************************/ /* 'QDU session type' enums */ /** * MbimQduSessionType: * @MBIM_QDU_SESSION_TYPE_NONE: No update session. * @MBIM_QDU_SESSION_TYPE_LE: LE-based update procedure. * * QDU session types. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_QDU_SESSION_TYPE_NONE = 0, MBIM_QDU_SESSION_TYPE_LE = 1, } MbimQduSessionType; /*****************************************************************************/ /* 'QDU session status' enums */ /** * MbimQduSessionStatus: * @MBIM_QDU_SESSION_STATUS_INACTIVE: Update session is not active. * @MBIM_QDU_SESSION_STATUS_FILE_TRANSFER: Updated files are being transferred from host to function or function is waiting host to send updated files. * @MBIM_QDU_SESSION_STATUS_APPLY_UPDATE: The function is applying the update package. * * QDU session status. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_QDU_SESSION_STATUS_INACTIVE = 0, MBIM_QDU_SESSION_STATUS_FILE_TRANSFER = 1, MBIM_QDU_SESSION_STATUS_APPLY_UPDATE = 2, } MbimQduSessionStatus; /*****************************************************************************/ /* 'QDU session result' enums */ /** * MbimQduSessionResult: * @MBIM_QDU_SESSION_RESULT_SUCCESS: Success * @MBIM_QDU_SESSION_RESULT_FAILURE: Failure * * QDU session result. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_QDU_SESSION_RESULT_SUCCESS = 0, MBIM_QDU_SESSION_RESULT_FAILURE = 1, } MbimQduSessionResult; /*****************************************************************************/ /* 'QDU file type' enums */ /** * MbimQduFileType: * @MBIM_QDU_FILE_TYPE_LITTLE_ENDIAN_PACKAGE: LE Package * * QDU session result. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_QDU_FILE_TYPE_LITTLE_ENDIAN_PACKAGE = 0, } MbimQduFileType; /*****************************************************************************/ /* 'QDU Quectel Reboot' enums */ /** * MbimQduQuectelRebootType: * @MBIM_QDU_QUECTEL_REBOOT_TYPE_EDL: Reboot to Emergency Download mode * * QDU Quectel Reboot session type. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_QDU_QUECTEL_REBOOT_TYPE_EDL = 17, } MbimQduQuectelRebootType; /*****************************************************************************/ /* 'QDU Quectel Version' enums */ /** * MbimQduQuectelVersionType: * @MBIM_QDU_QUECTEL_VERSION_TYPE_FW_BUILD_ID: Firmware Build ID * * QDU Quectel Read Version session type. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_QDU_QUECTEL_VERSION_TYPE_FW_BUILD_ID = 256, } MbimQduQuectelVersionType; /*****************************************************************************/ /* 'ATDS RAT' enums */ /** * MbimAtdsRatMode: * @MBIM_ATDS_RAT_MODE_AUTOMATIC: Automatic. * @MBIM_ATDS_RAT_MODE_2G_ONLY: 2G only. * @MBIM_ATDS_RAT_MODE_3G_ONLY: 3G only. * @MBIM_ATDS_RAT_MODE_4G_ONLY: 4G only. * * RAT mode preferences. * * Since: 1.16 */ typedef enum { /*< since=1.16 >*/ MBIM_ATDS_RAT_MODE_AUTOMATIC = 0, MBIM_ATDS_RAT_MODE_2G_ONLY = 1, MBIM_ATDS_RAT_MODE_3G_ONLY = 2, MBIM_ATDS_RAT_MODE_4G_ONLY = 3, } MbimAtdsRatMode; /*****************************************************************************/ /* 'ATDS Operators' enums */ /** * MbimAtdsProviderPlmnMode: * @MBIM_ATDS_PROVIDER_PLMN_MODE_GSM: GSM. * @MBIM_ATDS_PROVIDER_PLMN_MODE_UTRAN: UTRAN (UMTS). * @MBIM_ATDS_PROVIDER_PLMN_MODE_LTE: LTE. * * Provider PLMN mode. * * Since: 1.16 */ typedef enum { /*< since=1.16 >*/ MBIM_ATDS_PROVIDER_PLMN_MODE_GSM = 0, MBIM_ATDS_PROVIDER_PLMN_MODE_UTRAN = 6, MBIM_ATDS_PROVIDER_PLMN_MODE_LTE = 7, } MbimAtdsProviderPlmnMode; /*****************************************************************************/ /* 'PCO' enums */ /** * MbimPcoType: * @MBIM_PCO_TYPE_COMPLETE: The PCO structure is complete. * @MBIM_PCO_TYPE_PARTIAL: The PCO structure is a subset of what was received from the network. * * Type of PCO structure. * * Since: 1.18 */ typedef enum { /*< since=1.18 >*/ MBIM_PCO_TYPE_COMPLETE = 0, MBIM_PCO_TYPE_PARTIAL = 1 } MbimPcoType; /*****************************************************************************/ /* 'LTE Attach Configuration' enums */ /** * MbimLteAttachContextOperation: * @MBIM_LTE_ATTACH_CONTEXT_OPERATION_DEFAULT: Overwrite existing contexts. * @MBIM_LTE_ATTACH_CONTEXT_OPERATION_RESTORE_FACTORY: Restore factory preconfigured contexts. * * Command to run when updating LTE attach configuration. * * Since: 1.18 */ typedef enum { /*< since=1.18 >*/ MBIM_LTE_ATTACH_CONTEXT_OPERATION_DEFAULT = 0, MBIM_LTE_ATTACH_CONTEXT_OPERATION_RESTORE_FACTORY = 1 } MbimLteAttachContextOperation; /** * MbimLteAttachContextRoamingControl: * @MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_HOME: Context allowed to be used on home network. * @MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_PARTNER: Context allowed to be used on partner network. * @MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_NON_PARTNER: Context allowed to be used on non-partner network. * * Type of roaming control. * * Since: 1.18 */ typedef enum { /*< since=1.18 >*/ MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_HOME = 0, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_PARTNER = 1, MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_NON_PARTNER = 2 } MbimLteAttachContextRoamingControl; /** * MbimContextSource: * @MBIM_CONTEXT_SOURCE_ADMIN: Context created by enterprise IT. * @MBIM_CONTEXT_SOURCE_USER: Context created by user. * @MBIM_CONTEXT_SOURCE_OPERATOR: Context created by operator. * @MBIM_CONTEXT_SOURCE_MODEM: Context created by modem manufacturer. * @MBIM_CONTEXT_SOURCE_DEVICE: Context created by OS APN database. * * Source of context creation. * * Since: 1.18 */ typedef enum { /*< since=1.18 >*/ MBIM_CONTEXT_SOURCE_ADMIN = 0, MBIM_CONTEXT_SOURCE_USER = 1, MBIM_CONTEXT_SOURCE_OPERATOR = 2, MBIM_CONTEXT_SOURCE_MODEM = 3, MBIM_CONTEXT_SOURCE_DEVICE = 4 } MbimContextSource; /** * MbimLteAttachState: * @MBIM_LTE_ATTACH_STATE_DETACHED: Detached. * @MBIM_LTE_ATTACH_STATE_ATTACHED: Attached. * * LTE attach state. * * Since: 1.18 */ typedef enum { /*< since=1.18 >*/ MBIM_LTE_ATTACH_STATE_DETACHED = 0, MBIM_LTE_ATTACH_STATE_ATTACHED = 1 } MbimLteAttachState; /*****************************************************************************/ /* 'SAR config' enums */ /** * MbimSarControlMode: * @MBIM_SAR_CONTROL_MODE_DEVICE: SAR backoff is controlled by the modem directly. * @MBIM_SAR_CONTROL_MODE_OS: SAR backoff is controlled by the host operating system. * * SAR backoff mechanism control modes. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_SAR_CONTROL_MODE_DEVICE = 0, MBIM_SAR_CONTROL_MODE_OS = 1 } MbimSarControlMode; /** * MbimSarBackoffState: * @MBIM_SAR_BACKOFF_STATE_DISABLED: SAR backoff is disabled. * @MBIM_SAR_BACKOFF_STATE_ENABLED: SAR backoff is enabled. * * SAR backoff state. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_SAR_BACKOFF_STATE_DISABLED = 0, MBIM_SAR_BACKOFF_STATE_ENABLED = 1 } MbimSarBackoffState; /** * MbimSarWifiHardwareState: * @MBIM_SAR_WIFI_HARDWARE_STATE_INTEGRATED: Integrated. * @MBIM_SAR_WIFI_HARDWARE_STATE_NOT_INTEGRATED: Not integrated. * * Whether the Wi-Fi and cellular SAR are integrated at hardware level. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_SAR_WIFI_HARDWARE_STATE_INTEGRATED = 0, MBIM_SAR_WIFI_HARDWARE_STATE_NOT_INTEGRATED = 1 } MbimSarWifiHardwareState; /** * MbimTransmissionNotificationStatus: * @MBIM_TRANSMISSION_NOTIFICATION_STATUS_DISABLED: Notification disabled. * @MBIM_TRANSMISSION_NOTIFICATION_STATUS_ENABLED: Notification enabled. * * Whether modem channel transmission status notification is disabled or enabled. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_TRANSMISSION_NOTIFICATION_STATUS_DISABLED = 0, MBIM_TRANSMISSION_NOTIFICATION_STATUS_ENABLED = 1 } MbimTransmissionNotificationStatus; /** * MbimTransmissionState: * @MBIM_TRANSMISSION_STATE_INACTIVE: Modem was not actively transmitting data. * @MBIM_TRANSMISSION_STATE_ACTIVE: Modem was actively transmitting data. * * Whether modem is having TX traffic every hysteresis timeout. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_TRANSMISSION_STATE_INACTIVE = 0, MBIM_TRANSMISSION_STATE_ACTIVE = 1 } MbimTransmissionState; /*****************************************************************************/ /* 'Slot Info Status' enums */ /** * MbimUiccSlotState: * @MBIM_UICC_SLOT_STATE_UNKNOWN: The modem is still in the process of initializing so the SIM slot state is not deterministic. * @MBIM_UICC_SLOT_SATE_OFF_EMPTY: The UICC slot is powered off and no card is present. * @MBIM_UICC_SLOT_STATE_OFF: The UICC slot is powered off. * @MBIM_UICC_SLOT_STATE_EMPTY: The UICC slot is empty(there is no card in it). * @MBIM_UICC_SLOT_STATE_NOT_READY: The UICC slot is occupied and powered on but the card within it is not yet ready. * @MBIM_UICC_SLOT_STATE_ACTIVE: The UICC slot is occupied and the card within it is ready. * @MBIM_UICC_SLOT_STATE_ERROR: The UICC slot is occupied and powreed on but the card is in an error state and cannot be used until it is next reset. * @MBIM_UICC_SLOT_STATE_ACTIVE_ESIM: The card in the slot is an eSIM with an active profile and is ready to accept commands. * @MBIM_UICC_SLOT_STATE_ACTIVE_ESIM_NO_PROFILES: The card in the slot is an eSIM with no profiles(or no active profiles) and is ready to accept commands. * * MbimUiccSlotState * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_UICC_SLOT_STATE_UNKNOWN = 0, MBIM_UICC_SLOT_SATE_OFF_EMPTY = 1, MBIM_UICC_SLOT_STATE_OFF = 2, MBIM_UICC_SLOT_STATE_EMPTY = 3, MBIM_UICC_SLOT_STATE_NOT_READY = 4, MBIM_UICC_SLOT_STATE_ACTIVE = 5, MBIM_UICC_SLOT_STATE_ERROR = 6, MBIM_UICC_SLOT_STATE_ACTIVE_ESIM = 7, MBIM_UICC_SLOT_STATE_ACTIVE_ESIM_NO_PROFILES = 8 } MbimUiccSlotState; /*****************************************************************************/ /* 'UICC APDU' enums */ /** * MbimUiccSecureMessaging: * @MBIM_UICC_SECURE_MESSAGING_NONE: No secure messaging. * @MBIM_UICC_SECURE_MESSAGING_NO_HDR_AUTH: Secure, command header not authenticated. * * Specifies whether apdu is exchanged using secure messaging. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_UICC_SECURE_MESSAGING_NONE = 0, MBIM_UICC_SECURE_MESSAGING_NO_HDR_AUTH = 1, } MbimUiccSecureMessaging; /** * MbimUiccClassByteType: * @MBIM_UICC_CLASS_BYTE_TYPE_INTER_INDUSTRY: Defined according to first interindustry definition in ISO 7816-4. * @MBIM_UICC_CLASS_BYTE_TYPE_EXTENDED: Defined according to extended definition in ETSI 102 221. * * Specifies the type of class byte definition. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_UICC_CLASS_BYTE_TYPE_INTER_INDUSTRY = 0, MBIM_UICC_CLASS_BYTE_TYPE_EXTENDED = 1, } MbimUiccClassByteType; /* 'UICC Reset' enums */ /** * MbimUiccPassThroughAction: * @MBIM_UICC_PASS_THROUGH_ACTION_DISABLE: Disable pass through. * @MBIM_UICC_PASS_THROUGH_ACTION_ENABLE: Enable pass through. * * Pass through actions host can specify to modem. Upon reset * treats UICC as if pass through or as a regular UICC * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_UICC_PASS_THROUGH_ACTION_DISABLE = 0, MBIM_UICC_PASS_THROUGH_ACTION_ENABLE = 1, } MbimUiccPassThroughAction; /** * MbimUiccPassThroughStatus: * @MBIM_UICC_PASS_THROUGH_STATUS_DISABLED: Pass through disabled. * @MBIM_UICC_PASS_THROUGH_STATUS_ENABLED: Pass through enabled. * * Pass through status of the modem specifies to the host. * * Since: 1.26 */ typedef enum { /*< since=1.26 >*/ MBIM_UICC_PASS_THROUGH_STATUS_DISABLED = 0, MBIM_UICC_PASS_THROUGH_STATUS_ENABLED = 1, } MbimUiccPassThroughStatus; /*****************************************************************************/ /* 'Modem Configuration' enums */ /** * MbimModemConfigurationStatus: * @MBIM_MODEM_CONFIGURATION_STATUS_UNKNOWN: Unknown * @MBIM_MODEM_CONFIGURATION_STATUS_STARTED: SIM is ready and configuration started. * @MBIM_MODEM_CONFIGURATION_STATUS_COMPLETED: SIM is ready and configuration completed. * * Modem configuration status. * * Since: 1.28 */ typedef enum {/*< since=1.28 >*/ MBIM_MODEM_CONFIGURATION_STATUS_UNKNOWN = 0, MBIM_MODEM_CONFIGURATION_STATUS_STARTED = 1, MBIM_MODEM_CONFIGURATION_STATUS_COMPLETED = 2 } MbimModemConfigurationStatus; /*****************************************************************************/ /* 'Packet service v2' enums */ /** * MbimFrequencyRange: * @MBIM_FREQUENCY_RANGE_UNKNOWN: Unknown. * @MBIM_FREQUENCY_RANGE_1: Frequency range 1 (FR1) in 3GPP TS 38.101-1 (Sub-6G). * @MBIM_FREQUENCY_RANGE_2: FR2 in 3GPP TS 38.101-2 (mmWave). * * Frequency Range. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_FREQUENCY_RANGE_UNKNOWN = 0, MBIM_FREQUENCY_RANGE_1 = 1 << 0, MBIM_FREQUENCY_RANGE_2 = 1 << 1 } MbimFrequencyRange; /*****************************************************************************/ /* 'Provisioned Context v2' enums */ /** * MbimContextRoamingControl: * @MBIM_CONTEXT_ROAMING_CONTROL_HOME_ONLY: Context allowed to be used in home network. * @MBIM_CONTEXT_ROAMING_CONTROL_PARTNER_ONLY: Context allowed to be used in partner network. * @MBIM_CONTEXT_ROAMING_CONTROL_NON_PARTNER_ONLY: Context allowed to be used in non-partner network. * @MBIM_CONTEXT_ROAMING_CONTROL_HOME_AND_PARTNER: Context allowed to be used in home and partner networks. * @MBIM_CONTEXT_ROAMING_CONTROL_HOME_AND_NON_PARTNER: Context allowed to be used in home and non-partner networks. * @MBIM_CONTEXT_ROAMING_CONTROL_PARTNER_AND_NON_PARTNER: Context allowed to be used in partner and non-partner networks. * @MBIM_CONTEXT_ROAMING_CONTROL_ALLOW_ALL: Context allowed to be used in any roaming condition. * * Type of roaming control. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_CONTEXT_ROAMING_CONTROL_HOME_ONLY = 0, MBIM_CONTEXT_ROAMING_CONTROL_PARTNER_ONLY = 1, MBIM_CONTEXT_ROAMING_CONTROL_NON_PARTNER_ONLY = 2, MBIM_CONTEXT_ROAMING_CONTROL_HOME_AND_PARTNER = 3, MBIM_CONTEXT_ROAMING_CONTROL_HOME_AND_NON_PARTNER = 4, MBIM_CONTEXT_ROAMING_CONTROL_PARTNER_AND_NON_PARTNER = 5, MBIM_CONTEXT_ROAMING_CONTROL_ALLOW_ALL = 6 } MbimContextRoamingControl; /** * MbimContextMediaType: * @MBIM_CONTEXT_MEDIA_TYPE_CELLULAR_ONLY: Context allowed to be used only wen registered over cellular. * @MBIM_CONTEXT_MEDIA_TYPE_WIFI_ONLY: Context allowed to be used only when registered over Wi-Fi. * @MBIM_CONTEXT_MEDIA_TYPE_ALL: Context allowed to be used when registered either over cellular or Wi-Fi. * * Media type, specifying whether the modem is used for cellular or * iWLAN (Wi-Fi offload). * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_CONTEXT_MEDIA_TYPE_CELLULAR_ONLY = 0, MBIM_CONTEXT_MEDIA_TYPE_WIFI_ONLY = 1, MBIM_CONTEXT_MEDIA_TYPE_ALL = 2 } MbimContextMediaType; /** * MbimContextState: * @MBIM_CONTEXT_STATE_DISABLED: Disabled. * @MBIM_CONTEXT_STATE_ENABLED: Enabled. * * Status of the context, specifying whether it's enabled or disabled. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_CONTEXT_STATE_DISABLED = 0, MBIM_CONTEXT_STATE_ENABLED = 1, } MbimContextState; /** * MbimContextOperation: * @MBIM_CONTEXT_OPERATION_DEFAULT: Adds or replaces an existing context. * @MBIM_CONTEXT_OPERATION_DELETE: Delete an existing context. * @MBIM_CONTEXT_OPERATION_RESTORE_FACTORY: Restore preconfigured contexts for the provider ID of the current SIM card. * * Command to run when updating context configuration. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_CONTEXT_OPERATION_DEFAULT = 0, MBIM_CONTEXT_OPERATION_DELETE = 1, MBIM_CONTEXT_OPERATION_RESTORE_FACTORY = 2, } MbimContextOperation; /*****************************************************************************/ /* 'Registration Parameters' enums */ /** * MbimMicoMode: * @MBIM_MICO_MODE_DISABLED: Disabled. * @MBIM_MICO_MODE_ENABLED: Enabled. * @MBIM_MICO_MODE_UNSUPPORTED: Device does not support MICO mode. * @MBIM_MICO_MODE_DEFAULT: Default. * * Mobile Initiated Connection Only (MICO) Mode state. * * The @MBIM_MICO_MODE_DEFAULT value should only be used in set operations, it * should never be returned by the module upon a query. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_MICO_MODE_DISABLED = 0, MBIM_MICO_MODE_ENABLED = 1, MBIM_MICO_MODE_UNSUPPORTED = 2, MBIM_MICO_MODE_DEFAULT = 3, } MbimMicoMode; /** * MbimDefaultPduActivationHint: * @MBIM_DEFAULT_PDU_ACTIVATION_HINT_UNLIKELY: Default PDU session activation is unlikely to happen soon. * @MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY: Default PDU session activation is likely to happen soon. * * Hint regarding the activation of the default PDU session. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_DEFAULT_PDU_ACTIVATION_HINT_UNLIKELY = 0, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY = 1, } MbimDefaultPduActivationHint; /** * MbimLadnInfo: * @MBIM_LADN_INFO_NOT_NEEDED: Information not needed. * @MBIM_LADN_INFO_REQUESTED: Information requested. * * Local Area Data Network (LADN) information state. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_LADN_INFO_NOT_NEEDED = 0, MBIM_LADN_INFO_REQUESTED = 1, } MbimLadnInfo; /** * MbimDrxCycle: * @MBIM_DRX_CYCLE_NOT_SPECIFIED: DRX cycle not specified. * @MBIM_DRX_CYCLE_NOT_SUPPORTED: DRX cycle setting not supported. * @MBIM_DRX_CYCLE_32: DRX cycle T=32. * @MBIM_DRX_CYCLE_64: DRX cycle T=64. * @MBIM_DRX_CYCLE_128: DRX cycle T=128. * @MBIM_DRX_CYCLE_256: DRX cycle T=256. * * DRX cycle settings. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_DRX_CYCLE_NOT_SPECIFIED = 0, MBIM_DRX_CYCLE_NOT_SUPPORTED = 1, MBIM_DRX_CYCLE_32 = 2, MBIM_DRX_CYCLE_64 = 3, MBIM_DRX_CYCLE_128 = 4, MBIM_DRX_CYCLE_256 = 5, } MbimDrxCycle; /*****************************************************************************/ /* 'Subscriber Ready Status v3' enums */ /** * MbimSubscriberReadyStatusFlag: * @MBIM_SUBSCRIBER_READY_STATUS_FLAG_NONE: None. * @MBIM_SUBSCRIBER_READY_STATUS_FLAG_ESIM: Whether the SIM is an eSIM or not. * @MBIM_SUBSCRIBER_READY_STATUS_FLAG_SIM_REMOVABILITY_KNOWN: Whether the SIM removability details are know or not. * @MBIM_SUBSCRIBER_READY_STATUS_FLAG_SIM_REMOVABLE: Whether the SIM is removable or not, valid only if @MBIM_SUBSCRIBER_READY_STATUS_FLAG_SIM_REMOVABLITY_KNOWN is also given. * * Flags specifying SIM related details. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_SUBSCRIBER_READY_STATUS_FLAG_NONE = 0, MBIM_SUBSCRIBER_READY_STATUS_FLAG_ESIM = 1 << 0, MBIM_SUBSCRIBER_READY_STATUS_FLAG_SIM_REMOVABILITY_KNOWN = 1 << 1, MBIM_SUBSCRIBER_READY_STATUS_FLAG_SIM_REMOVABLE = 1 << 2, } MbimSubscriberReadyStatusFlag; /*****************************************************************************/ /* 'Device Caps v3' and 'Base Stations Info v3' enums */ /** * MbimDataClassV3: * @MBIM_DATA_CLASS_V3_NONE: None. Since 1.30. * @MBIM_DATA_CLASS_V3_GPRS: GPRS. * @MBIM_DATA_CLASS_V3_EDGE: EDGE. * @MBIM_DATA_CLASS_V3_UMTS: UMTS. * @MBIM_DATA_CLASS_V3_HSDPA: HSDPA. * @MBIM_DATA_CLASS_V3_HSUPA: HSUPA. * @MBIM_DATA_CLASS_V3_LTE: LTE. * @MBIM_DATA_CLASS_V3_5G: 5G. * @MBIM_DATA_CLASS_V3_1XRTT: 1xRTT. * @MBIM_DATA_CLASS_V3_1XEVDO: 1xEV-DO. * @MBIM_DATA_CLASS_V3_1XEVDO_REVA: 1xEV-DO RevA * @MBIM_DATA_CLASS_V3_1XEVDV: 1xEV-DV. * @MBIM_DATA_CLASS_V3_3XRTT: 3xRTT. * @MBIM_DATA_CLASS_V3_1XEVDO_REVB: 1xEV-DO RevB. * @MBIM_DATA_CLASS_V3_UMB: UMB. * @MBIM_DATA_CLASS_V3_CUSTOM: Custom. * * Data class update in MBIMEx v3.0. * * There is now a single flag for 5G, and the new #MbimDataSubclass helps to * identify the specific 5G setup. * * This type should be considered incompatible with #MbimDataClass. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_DATA_CLASS_V3_NONE = 0, MBIM_DATA_CLASS_V3_GPRS = 1 << 0, MBIM_DATA_CLASS_V3_EDGE = 1 << 1, MBIM_DATA_CLASS_V3_UMTS = 1 << 2, MBIM_DATA_CLASS_V3_HSDPA = 1 << 3, MBIM_DATA_CLASS_V3_HSUPA = 1 << 4, MBIM_DATA_CLASS_V3_LTE = 1 << 5, MBIM_DATA_CLASS_V3_5G = 1 << 6, /* Bit 7 unused, bits 8 to 15 reserved for future 3GPP classes */ MBIM_DATA_CLASS_V3_1XRTT = 1 << 16, MBIM_DATA_CLASS_V3_1XEVDO = 1 << 17, MBIM_DATA_CLASS_V3_1XEVDO_REVA = 1 << 18, MBIM_DATA_CLASS_V3_1XEVDV = 1 << 19, MBIM_DATA_CLASS_V3_3XRTT = 1 << 20, MBIM_DATA_CLASS_V3_1XEVDO_REVB = 1 << 21, MBIM_DATA_CLASS_V3_UMB = 1 << 22, /* Bits 23 to 30 reserved for future 3GPP2 classes */ MBIM_DATA_CLASS_V3_CUSTOM = 1 << 31 } MbimDataClassV3; /** * MbimDataSubclass: * @MBIM_DATA_SUBCLASS_NONE: No data subclass. * @MBIM_DATA_SUBCLASS_5G_ENDC: EUTRAN and NR dual connectivity as in 5G option 3. * @MBIM_DATA_SUBCLASS_5G_NR: Standalone NR as in 5G option 2. * @MBIM_DATA_SUBCLASS_5G_NEDC: NR and EUTRAN dual connectivity as in 5G option 4. * @MBIM_DATA_SUBCLASS_5G_ELTE: eLTE as in 5G option 5. * @MBIM_DATA_SUBCLASS_5G_NGENDC: Next-gen eLTE and NR dual connectivity as in 5G option 7. * * Flags specifying the data subclass. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_DATA_SUBCLASS_NONE = 0, MBIM_DATA_SUBCLASS_5G_ENDC = 1 << 0, MBIM_DATA_SUBCLASS_5G_NR = 1 << 1, MBIM_DATA_SUBCLASS_5G_NEDC = 1 << 2, MBIM_DATA_SUBCLASS_5G_ELTE = 1 << 3, MBIM_DATA_SUBCLASS_5G_NGENDC = 1 << 4, } MbimDataSubclass; /*****************************************************************************/ /* 'Quectel Radio State' enums */ /** * MbimQuectelRadioSwitchState: * @MBIM_QUECTEL_RADIO_SWITCH_STATE_OFF: Radio is off. * @MBIM_QUECTEL_RADIO_SWITCH_STATE_ON: Radio is on. * @MBIM_QUECTEL_RADIO_SWITCH_STATE_FCC_LOCKED: Radio is FCC locked. * * Radio switch state. * * Since: 1.26.2 */ typedef enum { /*< since=1.26.2 >*/ MBIM_QUECTEL_RADIO_SWITCH_STATE_OFF = 0, MBIM_QUECTEL_RADIO_SWITCH_STATE_ON = 1, MBIM_QUECTEL_RADIO_SWITCH_STATE_FCC_LOCKED = 4, } MbimQuectelRadioSwitchState; /*****************************************************************************/ /* 'Serving Cell Information' */ /** * MbimIntelServingCellInfo: * @MBIM_INTEL_SERVING_CELL_INFO_PCELL: Primary cell. * @MBIM_INTEL_SERVING_CELL_INFO_SCELL: Secondary cell. * @MBIM_INTEL_SERVING_CELL_INFO_PSCELL: Primary cell in SCS. * @MBIM_INTEL_SERVING_CELL_INFO_SSCELL: Secondary cell in SCS. * @MBIM_INTEL_SERVING_CELL_INFO_RADIO_OFF: Radio state is off. * * Serving cell information. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_INTEL_SERVING_CELL_INFO_PCELL = 0, MBIM_INTEL_SERVING_CELL_INFO_SCELL = 1, MBIM_INTEL_SERVING_CELL_INFO_PSCELL = 2, MBIM_INTEL_SERVING_CELL_INFO_SSCELL = 3, MBIM_INTEL_SERVING_CELL_INFO_RADIO_OFF = 0xFFFFFFFF, } MbimIntelServingCellInfo; /*****************************************************************************/ /* 'Mbim Intel Boot Mode enums */ /** * MbimIntelBootMode: * @MBIM_INTEL_BOOT_MODE_NORMAL_MODE: Normal boot mode. * @MBIM_INTEL_BOOT_MODE_DOWNLOAD_MODE: Download boot mode. * @MBIM_INTEL_BOOT_MODE_POWER_OFF_DEVICE: Power off device. * @MBIM_INTEL_BOOT_MODE_NON_RESETABLE_REGISTER: Configure non-resetable register without reboot or power off. * @MBIM_INTEL_BOOT_MODE_WITHOUT_REBOOT_POWER_OFF: Configure without reboot power-off. * @MBIM_INTEL_BOOT_MODE_FAST_DOWNLOAD_MODE: Fast boot in download mode. * * Modem intel boot mode. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_INTEL_BOOT_MODE_NORMAL_MODE = 0, MBIM_INTEL_BOOT_MODE_DOWNLOAD_MODE = 1, MBIM_INTEL_BOOT_MODE_POWER_OFF_DEVICE = 2, MBIM_INTEL_BOOT_MODE_NON_RESETABLE_REGISTER = 3, MBIM_INTEL_BOOT_MODE_WITHOUT_REBOOT_POWER_OFF = 4, MBIM_INTEL_BOOT_MODE_FAST_DOWNLOAD_MODE = 5, } MbimIntelBootMode; /** * MbimUiccApplicationType: * @MBIM_UICC_APPLICATION_TYPE_UNKNOWN: Unknown. * @MBIM_UICC_APPLICATION_TYPE_MF: Legacy SIM directories rooted at the MF. * @MBIM_UICC_APPLICATION_TYPE_MF_SIM: Legacy SIM directories rooted at the DF_GSM. * @MBIM_UICC_APPLICATION_TYPE_MF_RUIM: Legacy SIM directories rooted at the DF_CDMA. * @MBIM_UICC_APPLICATION_TYPE_USIM: USIM application. * @MBIM_UICC_APPLICATION_TYPE_CSIM: CSIM application. * @MBIM_UICC_APPLICATION_TYPE_ISIM: ISIM application. * * Type of UICC application. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_UICC_APPLICATION_TYPE_UNKNOWN = 0, MBIM_UICC_APPLICATION_TYPE_MF = 1, MBIM_UICC_APPLICATION_TYPE_MF_SIM = 2, MBIM_UICC_APPLICATION_TYPE_MF_RUIM = 3, MBIM_UICC_APPLICATION_TYPE_USIM = 4, MBIM_UICC_APPLICATION_TYPE_CSIM = 5, MBIM_UICC_APPLICATION_TYPE_ISIM = 6, } MbimUiccApplicationType; /** * MbimUiccFileAccessibility: * @MBIM_UICC_FILE_ACCESSIBILITY_UNKNOWN: Unknown. * @MBIM_UICC_FILE_ACCESSIBILITY_NOT_SHAREABLE: Not shareable. * @MBIM_UICC_FILE_ACCESSIBILITY_SHAREABLE: Shareable. * * The UICC file accessibility. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_UICC_FILE_ACCESSIBILITY_UNKNOWN = 0, MBIM_UICC_FILE_ACCESSIBILITY_NOT_SHAREABLE = 1, MBIM_UICC_FILE_ACCESSIBILITY_SHAREABLE = 2, } MbimUiccFileAccessibility; /** * MbimUiccFileType: * @MBIM_UICC_FILE_TYPE_UNKNOWN: Unknown. * @MBIM_UICC_FILE_TYPE_WORKING_EF: Working EF. * @MBIM_UICC_FILE_TYPE_INTERNAL_EF: Internal EF. * @MBIM_UICC_FILE_TYPE_DF_OR_ADF: Dedicated file, DF or ADF. * * The UICC file type. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_UICC_FILE_TYPE_UNKNOWN = 0, MBIM_UICC_FILE_TYPE_WORKING_EF = 1, MBIM_UICC_FILE_TYPE_INTERNAL_EF = 2, MBIM_UICC_FILE_TYPE_DF_OR_ADF = 3, } MbimUiccFileType; /** * MbimUiccFileStructure: * @MBIM_UICC_FILE_STRUCTURE_UNKNOWN: Unknown. * @MBIM_UICC_FILE_STRUCTURE_TRANSPARENT: A single record of variable length. * @MBIM_UICC_FILE_STRUCTURE_CYCLIC: A cyclic set of records, each of the same length. * @MBIM_UICC_FILE_STRUCTURE_LINEAR: A linear set of records, each of the same length. * @MBIM_UICC_FILE_STRUCTURE_BER_TLV: A set of data values accessible by tag. * * The UICC file structure. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_UICC_FILE_STRUCTURE_UNKNOWN = 0, MBIM_UICC_FILE_STRUCTURE_TRANSPARENT = 1, MBIM_UICC_FILE_STRUCTURE_CYCLIC = 2, MBIM_UICC_FILE_STRUCTURE_LINEAR = 3, MBIM_UICC_FILE_STRUCTURE_BER_TLV = 4, } MbimUiccFileStructure; /** * MbimTraceCommand: * @MBIM_TRACE_COMMAND_MODE: Trace command mode value. * @MBIM_TRACE_COMMAND_LEVEL: Trace command level value. * @MBIM_TRACE_COMMAND_LOCATION: Trace command location information. * @MBIM_TRACE_COMMAND_FLASH_INTERVAL: Trace command flash interval information. * * The trace command value. * * Since: 1.30 */ typedef enum { /*< since=1.30 >*/ MBIM_TRACE_COMMAND_MODE = 0, MBIM_TRACE_COMMAND_LEVEL = 1, MBIM_TRACE_COMMAND_LOCATION = 2, MBIM_TRACE_COMMAND_FLASH_INTERVAL = 3, } MbimTraceCommand; /*****************************************************************************/ /* 'Google Carrier Lock' enums */ /** * MbimCarrierLockStatus: * @MBIM_CARRIER_LOCK_STATUS_NOT_APPLIED: Carrier lock not applied. * @MBIM_CARRIER_LOCK_STATUS_APPLIED: Carrier lock applied. * * Status of carrier lock. * * Since: 1.30 */ typedef enum { /*< since=1.30 >*/ MBIM_CARRIER_LOCK_STATUS_NOT_APPLIED = 0, MBIM_CARRIER_LOCK_STATUS_APPLIED = 1, } MbimCarrierLockStatus; /** * MbimCarrierLockModemState: * @MBIM_CARRIER_LOCK_MODEM_STATE_DEREGISTERED: Modem deregistered. * @MBIM_CARRIER_LOCK_MODEM_STATE_DEREGISTRATION_IN_PROGRESS: Modem de-registration in progress. * @MBIM_CARRIER_LOCK_MODEM_STATE_REGISTRATION_IN_PROGRESS: Modem registration state in progress. * @MBIM_CARRIER_LOCK_MODEM_STATE_REGISTERED: Modem registered. * * State of modem after a carrier lock state update. * * Since: 1.30 */ typedef enum { /*< since=1.30 >*/ MBIM_CARRIER_LOCK_MODEM_STATE_DEREGISTERED = 0, MBIM_CARRIER_LOCK_MODEM_STATE_DEREGISTRATION_IN_PROGRESS = 1, MBIM_CARRIER_LOCK_MODEM_STATE_REGISTRATION_IN_PROGRESS = 2, MBIM_CARRIER_LOCK_MODEM_STATE_REGISTERED = 3, } MbimCarrierLockModemState; /** * MbimCarrierLockCause: * @MBIM_CARRIER_LOCK_CAUSE_NOT_APPLICABLE: Cause not applicable. * @MBIM_CARRIER_LOCK_CAUSE_SIM_LOCK_POLICY_MISMATCH: Sim lock policy mismatch. * @MBIM_CARRIER_LOCK_CAUSE_SIM_LOCK_POLICY_MATCHED: Sim lock policy matched. * * Carrier lock cause. * * Since: 1.30 */ typedef enum { /*< since=1.30 >*/ MBIM_CARRIER_LOCK_CAUSE_NOT_APPLICABLE = 0, MBIM_CARRIER_LOCK_CAUSE_SIM_LOCK_POLICY_MISMATCH = 1, MBIM_CARRIER_LOCK_CAUSE_SIM_LOCK_POLICY_MATCHED = 2, } MbimCarrierLockCause; G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_ENUMS_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-errors.h000066400000000000000000000300031453630424100215070ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2022 Intel Corporation */ #ifndef _LIBMBIM_GLIB_MBIM_ERRORS_H_ #define _LIBMBIM_GLIB_MBIM_ERRORS_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif /** * SECTION: mbim-errors * @title: Errors * @short_description: Common error types. * * This section defines common error types used in the interface. */ /* Prefixes for errors registered in DBus */ #define MBIM_DBUS_ERROR_PREFIX "org.freedesktop.libmbim.Error" #define MBIM_CORE_ERROR_DBUS_PREFIX MBIM_DBUS_ERROR_PREFIX ".Core" #define MBIM_PROTOCOL_ERROR_DBUS_PREFIX MBIM_DBUS_ERROR_PREFIX ".Protocol" #define MBIM_STATUS_ERROR_DBUS_PREFIX MBIM_DBUS_ERROR_PREFIX ".Status" /** * MbimCoreError: * @MBIM_CORE_ERROR_FAILED: Operation failed. * @MBIM_CORE_ERROR_WRONG_STATE: Operation cannot be executed in the current state. * @MBIM_CORE_ERROR_TIMEOUT: Operation timed out. * @MBIM_CORE_ERROR_INVALID_ARGS: Invalid arguments given. * @MBIM_CORE_ERROR_INVALID_MESSAGE: MBIM message is invalid. * @MBIM_CORE_ERROR_UNSUPPORTED: Not supported. * @MBIM_CORE_ERROR_ABORTED: Operation aborted. * @MBIM_CORE_ERROR_UNKNOWN_STATE: State is unknown. Since 1.16. * @MBIM_CORE_ERROR_INCOMPLETE_MESSAGE: MBIM message is incomplete. Since 1.28. * * Common errors that may be reported by libmbim-glib. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CORE_ERROR_FAILED = 0, /*< nick=Failed >*/ MBIM_CORE_ERROR_WRONG_STATE = 1, /*< nick=WrongState >*/ MBIM_CORE_ERROR_TIMEOUT = 2, /*< nick=Timeout >*/ MBIM_CORE_ERROR_INVALID_ARGS = 3, /*< nick=InvalidArgs >*/ MBIM_CORE_ERROR_INVALID_MESSAGE = 4, /*< nick=InvalidMessage >*/ MBIM_CORE_ERROR_UNSUPPORTED = 5, /*< nick=Unsupported >*/ MBIM_CORE_ERROR_ABORTED = 6, /*< nick=Aborted >*/ MBIM_CORE_ERROR_UNKNOWN_STATE = 7, /*< nick=UnknownState >*/ MBIM_CORE_ERROR_INCOMPLETE_MESSAGE = 8, /*< nick=IncompleteMessage >*/ } MbimCoreError; /** * MbimProtocolError: * @MBIM_PROTOCOL_ERROR_INVALID: Invalid MBIM error. * @MBIM_PROTOCOL_ERROR_TIMEOUT_FRAGMENT: Timeout waiting for fragment. * @MBIM_PROTOCOL_ERROR_FRAGMENT_OUT_OF_SEQUENCE: Fragment received out of sequence. * @MBIM_PROTOCOL_ERROR_LENGTH_MISMATCH: Length mismatch. * @MBIM_PROTOCOL_ERROR_DUPLICATED_TID: Duplicated transaction ID. * @MBIM_PROTOCOL_ERROR_NOT_OPENED: Not opened. * @MBIM_PROTOCOL_ERROR_UNKNOWN: Unknown error. * @MBIM_PROTOCOL_ERROR_CANCEL: Cancel the operation. * @MBIM_PROTOCOL_ERROR_MAX_TRANSFER: Maximum control transfer not supported. * * MBIM protocol errors. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_PROTOCOL_ERROR_INVALID = 0, /*< nick=Invalid >*/ MBIM_PROTOCOL_ERROR_TIMEOUT_FRAGMENT = 1, /*< nick=TimeoutFragment >*/ MBIM_PROTOCOL_ERROR_FRAGMENT_OUT_OF_SEQUENCE = 2, /*< nick=FragmentOutOfSequence >*/ MBIM_PROTOCOL_ERROR_LENGTH_MISMATCH = 3, /*< nick=LengthMismatch >*/ MBIM_PROTOCOL_ERROR_DUPLICATED_TID = 4, /*< nick=DuplicatedTid >*/ MBIM_PROTOCOL_ERROR_NOT_OPENED = 5, /*< nick=NotOpened >*/ MBIM_PROTOCOL_ERROR_UNKNOWN = 6, /*< nick=Unknown >*/ MBIM_PROTOCOL_ERROR_CANCEL = 7, /*< nick=Cancel >*/ MBIM_PROTOCOL_ERROR_MAX_TRANSFER = 8 /*< nick=MaxTransfer >*/ } MbimProtocolError; /** * MbimStatusError: * @MBIM_STATUS_ERROR_NONE: Success, no error. * @MBIM_STATUS_ERROR_BUSY: Busy. * @MBIM_STATUS_ERROR_FAILURE: Failure. * @MBIM_STATUS_ERROR_SIM_NOT_INSERTED: SIM not inserted. * @MBIM_STATUS_ERROR_BAD_SIM: Bad SIM. * @MBIM_STATUS_ERROR_PIN_REQUIRED: PIN required. * @MBIM_STATUS_ERROR_PIN_DISABLED: PIN disabled. * @MBIM_STATUS_ERROR_NOT_REGISTERED: Not registered. * @MBIM_STATUS_ERROR_PROVIDERS_NOT_FOUND: Providers not found. * @MBIM_STATUS_ERROR_NO_DEVICE_SUPPORT: No device support. * @MBIM_STATUS_ERROR_PROVIDER_NOT_VISIBLE: Provider not visible. * @MBIM_STATUS_ERROR_DATA_CLASS_NOT_AVAILABLE: Data class not available. * @MBIM_STATUS_ERROR_PACKET_SERVICE_DETACHED: Packet service detached. * @MBIM_STATUS_ERROR_MAX_ACTIVATED_CONTEXTS: Max activated contexts. * @MBIM_STATUS_ERROR_NOT_INITIALIZED: Not initialized. * @MBIM_STATUS_ERROR_VOICE_CALL_IN_PROGRESS: Voice call in progress. * @MBIM_STATUS_ERROR_CONTEXT_NOT_ACTIVATED: Context not activated. * @MBIM_STATUS_ERROR_SERVICE_NOT_ACTIVATED: Service not activated. * @MBIM_STATUS_ERROR_INVALID_ACCESS_STRING: Invalid access string. * @MBIM_STATUS_ERROR_INVALID_USER_NAME_PWD: Invalid user name or password. * @MBIM_STATUS_ERROR_RADIO_POWER_OFF: Radio power off. * @MBIM_STATUS_ERROR_INVALID_PARAMETERS: Invalid parameters. * @MBIM_STATUS_ERROR_READ_FAILURE: Read failure. * @MBIM_STATUS_ERROR_WRITE_FAILURE: Write failure. * @MBIM_STATUS_ERROR_NO_PHONEBOOK: No phonebook. * @MBIM_STATUS_ERROR_PARAMETER_TOO_LONG: Parameter too long. * @MBIM_STATUS_ERROR_STK_BUSY: SIM toolkit busy. * @MBIM_STATUS_ERROR_OPERATION_NOT_ALLOWED: Operation not allowed. * @MBIM_STATUS_ERROR_MEMORY_FAILURE: Memory failure. * @MBIM_STATUS_ERROR_INVALID_MEMORY_INDEX: Invalid memory index. * @MBIM_STATUS_ERROR_MEMORY_FULL: Memory full. * @MBIM_STATUS_ERROR_FILTER_NOT_SUPPORTED: Filter not supported. * @MBIM_STATUS_ERROR_DSS_INSTANCE_LIMIT: DSS instance limit. * @MBIM_STATUS_ERROR_INVALID_DEVICE_SERVICE_OPERATION: Invalid device service operation. * @MBIM_STATUS_ERROR_AUTH_INCORRECT_AUTN: Incorrect AUTN when sending authentication. * @MBIM_STATUS_ERROR_AUTH_SYNC_FAILURE: Synchronization failure during the authentication. * @MBIM_STATUS_ERROR_AUTH_AMF_NOT_SET: AMF bit not set in the authentication. * @MBIM_STATUS_ERROR_CONTEXT_NOT_SUPPORTED: ContextType not supported by the operation. Since 1.16. * @MBIM_STATUS_ERROR_SMS_UNKNOWN_SMSC_ADDRESS: Unknown SMSC address. * @MBIM_STATUS_ERROR_SMS_NETWORK_TIMEOUT: Network timeout when sending SMS. * @MBIM_STATUS_ERROR_SMS_LANG_NOT_SUPPORTED: Language not supported in SMS. * @MBIM_STATUS_ERROR_SMS_ENCODING_NOT_SUPPORTED: Encoding not supported in SMS. * @MBIM_STATUS_ERROR_SMS_FORMAT_NOT_SUPPORTED: Format not supported in SMS. * @MBIM_STATUS_ERROR_INVALID_SIGNATURE: Invalid signature. Defined by Google for the carrier lock operation. Since 1.30. * @MBIM_STATUS_ERROR_INVALID_IMEI: Invalid IMEI. Defined by Google for the carrier lock operation. Since 1.30. * @MBIM_STATUS_ERROR_INVALID_TIMESTAMP: Invalid timestamp. Defined by Google for the carrier lock operation. Since 1.30. * @MBIM_STATUS_ERROR_NETWORK_LIST_TOO_LARGE: List of networks too large. Defined by Google for the carrier lock operation. Since 1.30. * @MBIM_STATUS_ERROR_SIGNATURE_ALGORITHM_NOT_SUPPORTED: Signature algorithm not supported. Defined by Google for the carrier lock operation. Since 1.30. * @MBIM_STATUS_ERROR_FEATURE_NOT_SUPPORTED: Feature not supported. Defined by Google for the carrier lock operation. Since 1.30. * @MBIM_STATUS_ERROR_DECODE_OR_PARSING_ERROR: Decode or parsing error. Defined by Google for the carrier lock operation. Since 1.30. * * Status of the MBIM request. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_STATUS_ERROR_NONE = 0, /*< nick=None >*/ MBIM_STATUS_ERROR_BUSY = 1, /*< nick=Busy >*/ MBIM_STATUS_ERROR_FAILURE = 2, /*< nick=Failure >*/ MBIM_STATUS_ERROR_SIM_NOT_INSERTED = 3, /*< nick=SimNotInserted >*/ MBIM_STATUS_ERROR_BAD_SIM = 4, /*< nick=BadSim >*/ MBIM_STATUS_ERROR_PIN_REQUIRED = 5, /*< nick=PinRequired >*/ MBIM_STATUS_ERROR_PIN_DISABLED = 6, /*< nick=PinDisabled >*/ MBIM_STATUS_ERROR_NOT_REGISTERED = 7, /*< nick=NotRegistered >*/ MBIM_STATUS_ERROR_PROVIDERS_NOT_FOUND = 8, /*< nick=ProvidersNotFound >*/ MBIM_STATUS_ERROR_NO_DEVICE_SUPPORT = 9, /*< nick=NoDeviceSupport >*/ MBIM_STATUS_ERROR_PROVIDER_NOT_VISIBLE = 10, /*< nick=ProviderNotVisible >*/ MBIM_STATUS_ERROR_DATA_CLASS_NOT_AVAILABLE = 11, /*< nick=DataClassNotAvailable >*/ MBIM_STATUS_ERROR_PACKET_SERVICE_DETACHED = 12, /*< nick=PacketServiceDetached >*/ MBIM_STATUS_ERROR_MAX_ACTIVATED_CONTEXTS = 13, /*< nick=MaxActivatedContexts >*/ MBIM_STATUS_ERROR_NOT_INITIALIZED = 14, /*< nick=NotInitialized >*/ MBIM_STATUS_ERROR_VOICE_CALL_IN_PROGRESS = 15, /*< nick=VoiceCallInProgress >*/ MBIM_STATUS_ERROR_CONTEXT_NOT_ACTIVATED = 16, /*< nick=ContextNotActivated >*/ MBIM_STATUS_ERROR_SERVICE_NOT_ACTIVATED = 17, /*< nick=ServiceNotActivated >*/ MBIM_STATUS_ERROR_INVALID_ACCESS_STRING = 18, /*< nick=InvalidAccessString >*/ MBIM_STATUS_ERROR_INVALID_USER_NAME_PWD = 19, /*< nick=InvalidUserNamePwd >*/ MBIM_STATUS_ERROR_RADIO_POWER_OFF = 20, /*< nick=RadioPowerOff >*/ MBIM_STATUS_ERROR_INVALID_PARAMETERS = 21, /*< nick=InvalidParameters >*/ MBIM_STATUS_ERROR_READ_FAILURE = 22, /*< nick=ReadFailure >*/ MBIM_STATUS_ERROR_WRITE_FAILURE = 23, /*< nick=WriteFailure >*/ /* 24 = reserved */ MBIM_STATUS_ERROR_NO_PHONEBOOK = 25, /*< nick=NoPhonebook >*/ MBIM_STATUS_ERROR_PARAMETER_TOO_LONG = 26, /*< nick=ParameterTooLong >*/ MBIM_STATUS_ERROR_STK_BUSY = 27, /*< nick=StkBusy >*/ MBIM_STATUS_ERROR_OPERATION_NOT_ALLOWED = 28, /*< nick=OperationNotAllowed >*/ MBIM_STATUS_ERROR_MEMORY_FAILURE = 29, /*< nick=MemoryFailure >*/ MBIM_STATUS_ERROR_INVALID_MEMORY_INDEX = 30, /*< nick=InvalidMemoryIndex >*/ MBIM_STATUS_ERROR_MEMORY_FULL = 31, /*< nick=MemoryFull >*/ MBIM_STATUS_ERROR_FILTER_NOT_SUPPORTED = 32, /*< nick=FilterNotSupported >*/ MBIM_STATUS_ERROR_DSS_INSTANCE_LIMIT = 33, /*< nick=DssInstanceLimit >*/ MBIM_STATUS_ERROR_INVALID_DEVICE_SERVICE_OPERATION = 34, /*< nick=InvalidDeviceServiceOperation >*/ MBIM_STATUS_ERROR_AUTH_INCORRECT_AUTN = 35, /*< nick=AuthIncorrectAuth >*/ MBIM_STATUS_ERROR_AUTH_SYNC_FAILURE = 36, /*< nick=AuthSyncFailure >*/ MBIM_STATUS_ERROR_AUTH_AMF_NOT_SET = 37, /*< nick=AuthAmfNotSet >*/ MBIM_STATUS_ERROR_CONTEXT_NOT_SUPPORTED = 38, /*< nick=ContextNotSupported >*/ MBIM_STATUS_ERROR_SMS_UNKNOWN_SMSC_ADDRESS = 100, /*< nick=SmsUnknownSmscAddress >*/ MBIM_STATUS_ERROR_SMS_NETWORK_TIMEOUT = 101, /*< nick=SmsNetworkTimeout >*/ MBIM_STATUS_ERROR_SMS_LANG_NOT_SUPPORTED = 102, /*< nick=SmsLangNotSupported >*/ MBIM_STATUS_ERROR_SMS_ENCODING_NOT_SUPPORTED = 103, /*< nick=SmsEncodingNotSupported >*/ MBIM_STATUS_ERROR_SMS_FORMAT_NOT_SUPPORTED = 104, /*< nick=SmsFormatNotSupported >*/ /* google defined error for carrier lock */ MBIM_STATUS_ERROR_INVALID_SIGNATURE = 0x91000001, /*< nick=InvalidSignature >*/ MBIM_STATUS_ERROR_INVALID_IMEI = 0x91000002, /*< nick=InvalidImei >*/ MBIM_STATUS_ERROR_INVALID_TIMESTAMP = 0x91000003, /*< nick=InvalidTimeStamp >*/ MBIM_STATUS_ERROR_NETWORK_LIST_TOO_LARGE = 0x91000004, /*< nick=NetworkListTooLarge >*/ MBIM_STATUS_ERROR_SIGNATURE_ALGORITHM_NOT_SUPPORTED = 0x91000005, /*< nick=SignatureAlgorithmNotSupported >*/ MBIM_STATUS_ERROR_FEATURE_NOT_SUPPORTED = 0x91000006, /*< nick=FeatureNotSupported >*/ MBIM_STATUS_ERROR_DECODE_OR_PARSING_ERROR = 0x91000007, /*< nick=DecodeOrParsingError >*/ } MbimStatusError; #endif /* _LIBMBIM_GLIB_MBIM_ERRORS_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-helpers-netlink.c000066400000000000000000000241511453630424100233010ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2022 Daniele Palmas * * Based on previous work: * Copyright (C) 2020-2021 Eric Caruso * Copyright (C) 2020-2021 Andrew Lassalle * Copyright (C) 2021 Aleksander Morgado */ #include #include #include /* This is a built-in file, not provided by the kernel headers, * used to add wwan symbols if not available */ #include #include #include "mbim-helpers-netlink.h" /*****************************************************************************/ /* * Netlink message construction functions */ NetlinkHeader * mbim_helpers_netlink_get_message_header (NetlinkMessage *msg) { #if defined(__clang__) || defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-align" #endif return (NetlinkHeader *) (msg->data); #if defined(__clang__) || defined(__GNUC__) # pragma GCC diagnostic pop #endif } guint mbim_helpers_netlink_get_pos_of_next_attr (NetlinkMessage *msg) { return NLMSG_ALIGN (msg->len); } static void append_netlink_attribute (NetlinkMessage *msg, gushort type, gconstpointer value, gushort len) { guint attr_len; guint old_len; guint next_attr_rel_pos; char *next_attr_abs_pos; struct rtattr new_attr; /* Expand the buffer to hold the new attribute */ attr_len = RTA_ALIGN (RTA_LENGTH (len)); old_len = msg->len; next_attr_rel_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg); g_byte_array_set_size (msg, next_attr_rel_pos + attr_len); /* fill new bytes with zero, since some padding is added between attributes. */ memset ((char *) msg->data + old_len, 0, msg->len - old_len); new_attr.rta_type = type; new_attr.rta_len = RTA_LENGTH (len); next_attr_abs_pos = (char *) msg->data + next_attr_rel_pos; memcpy (next_attr_abs_pos, &new_attr, sizeof (struct rtattr)); if (value) memcpy (RTA_DATA (next_attr_abs_pos), value, len); /* Update the total netlink message length */ mbim_helpers_netlink_get_message_header (msg)->msghdr.nlmsg_len = msg->len; } void mbim_helpers_netlink_append_attribute_nested (NetlinkMessage *msg, gushort type) { append_netlink_attribute (msg, type, NULL, 0); } void mbim_helpers_netlink_append_attribute_string (NetlinkMessage *msg, gushort type, const gchar *value) { append_netlink_attribute (msg, type, value, strlen (value)); } void mbim_helpers_netlink_append_attribute_string_null (NetlinkMessage *msg, gushort type, const gchar *value) { append_netlink_attribute (msg, type, value, strlen (value) + 1); } void mbim_helpers_netlink_append_attribute_uint16 (NetlinkMessage *msg, gushort type, guint16 value) { append_netlink_attribute (msg, type, &value, sizeof (value)); } void mbim_helpers_netlink_append_attribute_uint32 (NetlinkMessage *msg, gushort type, guint32 value) { append_netlink_attribute (msg, type, &value, sizeof (value)); } NetlinkMessage * mbim_helpers_netlink_message_new (guint16 type, guint16 extra_flags) { NetlinkMessage *msg; NetlinkHeader *hdr; int size = sizeof (NetlinkHeader); msg = g_byte_array_new (); g_byte_array_set_size (msg, size); memset ((char *) msg->data, 0, size); hdr = mbim_helpers_netlink_get_message_header (msg); hdr->msghdr.nlmsg_len = msg->len; hdr->msghdr.nlmsg_type = type; hdr->msghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | extra_flags; hdr->ifreq.ifi_family = AF_UNSPEC; return msg; } void mbim_helpers_netlink_message_free (NetlinkMessage *msg) { g_byte_array_unref (msg); } /*****************************************************************************/ /* * Transaction management functions */ static gboolean transaction_timed_out (NetlinkTransaction *tr, GHashTable *transactions) { GTask *task; guint32 sequence_id; task = g_steal_pointer (&tr->completion_task); sequence_id = tr->sequence_id; g_hash_table_remove (transactions, GUINT_TO_POINTER (tr->sequence_id)); g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "Netlink message with sequence ID %u timed out", sequence_id); g_object_unref (task); return G_SOURCE_REMOVE; } void mbim_helpers_netlink_transaction_complete_with_error (NetlinkTransaction *tr, GHashTable *transactions, GError *error) { GTask *task; task = g_steal_pointer (&tr->completion_task); g_hash_table_remove (transactions, GUINT_TO_POINTER (tr->sequence_id)); g_task_return_error (task, error); g_object_unref (task); } void mbim_helpers_netlink_transaction_complete (NetlinkTransaction *tr, GHashTable *transactions, gint saved_errno) { GTask *task; guint32 sequence_id; task = g_steal_pointer (&tr->completion_task); sequence_id = tr->sequence_id; g_hash_table_remove (transactions, GUINT_TO_POINTER (tr->sequence_id)); if (!saved_errno) { g_task_return_boolean (task, TRUE); } else { g_task_return_new_error (task, G_IO_ERROR, g_io_error_from_errno (saved_errno), "Netlink message with transaction %u failed: %s", sequence_id, g_strerror (saved_errno)); } g_object_unref (task); } void mbim_helpers_netlink_transaction_free (NetlinkTransaction *tr) { g_assert (tr->completion_task == NULL); g_source_destroy (tr->timeout_source); g_source_unref (tr->timeout_source); g_slice_free (NetlinkTransaction, tr); } NetlinkTransaction * mbim_helpers_netlink_transaction_new (guint *sequence_id, GHashTable *transactions, NetlinkMessage *msg, guint timeout, GTask *task) { NetlinkTransaction *tr; tr = g_slice_new0 (NetlinkTransaction); tr->sequence_id = ++(*sequence_id); mbim_helpers_netlink_get_message_header (msg)->msghdr.nlmsg_seq = tr->sequence_id; if (timeout) { tr->timeout_source = g_timeout_source_new_seconds (timeout); g_source_set_callback (tr->timeout_source, (GSourceFunc) transaction_timed_out, tr, NULL); g_source_attach (tr->timeout_source, g_main_context_get_thread_default ()); } tr->completion_task = g_object_ref (task); g_hash_table_insert (transactions, GUINT_TO_POINTER (tr->sequence_id), tr); return tr; } /*****************************************************************************/ static gboolean netlink_message_cb (GSocket *socket, GIOCondition condition, GHashTable *transactions) { GError *error = NULL; gchar buf[512]; int bytes_received; unsigned int buffer_len; struct nlmsghdr *hdr; if (condition & G_IO_HUP || condition & G_IO_ERR) { g_warning ("[netlink] socket connection closed."); return G_SOURCE_REMOVE; } bytes_received = g_socket_receive (socket, buf, sizeof (buf), NULL, &error); if (bytes_received < 0) { g_warning ("[netlink] socket i/o failure: %s", error->message); g_error_free (error); return G_SOURCE_REMOVE; } buffer_len = (unsigned int ) bytes_received; #if defined(__clang__) || defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-align" #endif for (hdr = (struct nlmsghdr *) buf; NLMSG_OK (hdr, buffer_len); NLMSG_NEXT (hdr, buffer_len)) { #if defined(__clang__) || defined(__GNUC__) # pragma GCC diagnostic pop #endif NetlinkTransaction *tr; struct nlmsgerr *err; if (hdr->nlmsg_type != NLMSG_ERROR) continue; tr = g_hash_table_lookup (transactions, GUINT_TO_POINTER (hdr->nlmsg_seq)); if (!tr) continue; err = NLMSG_DATA (buf); mbim_helpers_netlink_transaction_complete (tr, transactions, err->error); } return G_SOURCE_CONTINUE; } void mbim_helpers_netlink_set_callback (GSource **source, GSocket *socket, GHashTable *transactions) { *source = g_socket_create_source (socket, G_IO_IN | G_IO_ERR | G_IO_HUP, NULL); g_source_set_callback (*source, (GSourceFunc) netlink_message_cb, transactions, NULL); g_source_attach (*source, g_main_context_get_thread_default ()); } libmbim-1.31.2-dev/src/libmbim-glib/mbim-helpers-netlink.h000066400000000000000000000074131453630424100233100ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2022 Daniele Palmas * * Based on previous work: * Copyright (C) 2020-2021 Eric Caruso * Copyright (C) 2020-2021 Andrew Lassalle * Copyright (C) 2021 Aleksander Morgado */ #ifndef _LIBMBIM_GLIB_MBIM_HELPERS_NETLINK_H_ #define _LIBMBIM_GLIB_MBIM_HELPERS_NETLINK_H_ #if !defined (LIBMBIM_GLIB_COMPILATION) #error "This is a private header!!" #endif #include #include G_BEGIN_DECLS typedef GByteArray NetlinkMessage; typedef struct { struct nlmsghdr msghdr; struct ifinfomsg ifreq; } NetlinkHeader; G_GNUC_INTERNAL NetlinkHeader *mbim_helpers_netlink_get_message_header (NetlinkMessage *msg); G_GNUC_INTERNAL guint mbim_helpers_netlink_get_pos_of_next_attr (NetlinkMessage *msg); G_GNUC_INTERNAL void mbim_helpers_netlink_append_attribute_nested (NetlinkMessage *msg, gushort type); G_GNUC_INTERNAL void mbim_helpers_netlink_append_attribute_string (NetlinkMessage *msg, gushort type, const gchar *value); G_GNUC_INTERNAL void mbim_helpers_netlink_append_attribute_string_null (NetlinkMessage *msg, gushort type, const gchar *value); G_GNUC_INTERNAL void mbim_helpers_netlink_append_attribute_uint16 (NetlinkMessage *msg, gushort type, guint16 value); G_GNUC_INTERNAL void mbim_helpers_netlink_append_attribute_uint32 (NetlinkMessage *msg, gushort type, guint32 value); G_GNUC_INTERNAL NetlinkMessage *mbim_helpers_netlink_message_new (guint16 type, guint16 extra_flags); G_GNUC_INTERNAL void mbim_helpers_netlink_message_free (NetlinkMessage *msg); typedef struct { guint32 sequence_id; GSource *timeout_source; GTask *completion_task; } NetlinkTransaction; G_GNUC_INTERNAL void mbim_helpers_netlink_transaction_complete_with_error (NetlinkTransaction *tr, GHashTable *transactions, GError *error); G_GNUC_INTERNAL void mbim_helpers_netlink_transaction_complete (NetlinkTransaction *tr, GHashTable *transactions, gint saved_errno); G_GNUC_INTERNAL void mbim_helpers_netlink_transaction_free (NetlinkTransaction *tr); G_GNUC_INTERNAL NetlinkTransaction *mbim_helpers_netlink_transaction_new (guint *sequence_id, GHashTable *transactions, NetlinkMessage *msg, guint timeout, GTask *task); G_GNUC_INTERNAL void mbim_helpers_netlink_set_callback (GSource **source, GSocket *socket, GHashTable *transactions); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_HELPERS_NETLINK_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-helpers.c000066400000000000000000000167331453630424100216460ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2021 Aleksander Morgado */ #include #include #include #include #include #include #include #include #include "mbim-helpers.h" #include "mbim-error-types.h" /******************************************************************************/ guint16 mbim_helpers_read_unaligned_guint16 (const guint8 *buffer) { guint16 tmp; memcpy (&tmp, buffer, 2); return GUINT16_FROM_LE (tmp); } guint32 mbim_helpers_read_unaligned_guint32 (const guint8 *buffer) { guint32 tmp; memcpy (&tmp, buffer, 4); return GUINT32_FROM_LE (tmp); } guint32 mbim_helpers_read_unaligned_gint32 (const guint8 *buffer) { gint32 tmp; memcpy (&tmp, buffer, 4); return GINT32_FROM_LE (tmp); } guint64 mbim_helpers_read_unaligned_guint64 (const guint8 *buffer) { guint64 tmp; memcpy (&tmp, buffer, 8); return GUINT64_FROM_LE (tmp); } /*****************************************************************************/ gboolean mbim_helpers_check_user_allowed (uid_t uid, GError **error) { #ifndef MBIM_USERNAME_ENABLED if (uid == 0) return TRUE; #else # ifndef MBIM_USERNAME # error MBIM username not defined # endif struct passwd *expected_usr = NULL; /* Root user is always allowed, regardless of the specified MBIM_USERNAME */ if (uid == 0) return TRUE; expected_usr = getpwnam (MBIM_USERNAME); if (!expected_usr) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Not enough privileges (unknown username %s)", MBIM_USERNAME); return FALSE; } if (uid == expected_usr->pw_uid) return TRUE; #endif g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Not enough privileges"); return FALSE; } /*****************************************************************************/ gchar * mbim_helpers_get_devpath (const gchar *cdc_wdm_path, GError **error) { gchar *aux; if (!g_file_test (cdc_wdm_path, G_FILE_TEST_IS_SYMLINK)) return g_strdup (cdc_wdm_path); aux = realpath (cdc_wdm_path, NULL); if (!aux) { int saved_errno = errno; g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Couldn't get realpath: %s", g_strerror (saved_errno)); return NULL; } return aux; } /*****************************************************************************/ gchar * mbim_helpers_get_devname (const gchar *cdc_wdm_path, GError **error) { gchar *aux; gchar *devname = NULL; aux = mbim_helpers_get_devpath (cdc_wdm_path, error); if (aux) { devname = g_path_get_basename (aux); g_free (aux); } return devname; } /*****************************************************************************/ gboolean mbim_helpers_list_links_wdm (GFile *sysfs_file, GCancellable *cancellable, GPtrArray *previous_links, GPtrArray **out_links, GError **error) { g_autofree gchar *sysfs_path = NULL; g_autoptr(GFileEnumerator) direnum = NULL; g_autoptr(GPtrArray) links = NULL; direnum = g_file_enumerate_children (sysfs_file, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NONE, cancellable, error); if (!direnum) return FALSE; sysfs_path = g_file_get_path (sysfs_file); links = g_ptr_array_new_with_free_func (g_free); while (TRUE) { GFileInfo *info; g_autofree gchar *filename = NULL; g_autofree gchar *link_path = NULL; g_autofree gchar *real_path = NULL; g_autofree gchar *basename = NULL; if (!g_file_enumerator_iterate (direnum, &info, NULL, cancellable, error)) return FALSE; if (!info) break; filename = g_file_info_get_attribute_as_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME); if (!filename || !g_str_has_prefix (filename, "upper_")) continue; link_path = g_strdup_printf ("%s/%s", sysfs_path, filename); real_path = realpath (link_path, NULL); if (!real_path) continue; basename = g_path_get_basename (real_path); /* skip interface if it was already known */ if (previous_links && g_ptr_array_find_with_equal_func (previous_links, basename, g_str_equal, NULL)) continue; g_ptr_array_add (links, g_steal_pointer (&basename)); } if (!links || !links->len) { *out_links = NULL; return TRUE; } g_ptr_array_sort (links, (GCompareFunc) g_ascii_strcasecmp); *out_links = g_steal_pointer (&links); return TRUE; } /*****************************************************************************/ gboolean mbim_helpers_list_links_wwan (const gchar *base_ifname, GFile *sysfs_file, GCancellable *cancellable, GPtrArray *previous_links, GPtrArray **out_links, GError **error) { g_autofree gchar *sysfs_path = NULL; g_autoptr(GFileEnumerator) direnum = NULL; g_autoptr(GPtrArray) links = NULL; direnum = g_file_enumerate_children (sysfs_file, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NONE, cancellable, error); if (!direnum) return FALSE; sysfs_path = g_file_get_path (sysfs_file); links = g_ptr_array_new_with_free_func (g_free); while (TRUE) { GFileInfo *info; g_autofree gchar *filename = NULL; g_autofree gchar *link_path = NULL; g_autofree gchar *real_path = NULL; g_autofree gchar *basename = NULL; if (!g_file_enumerator_iterate (direnum, &info, NULL, cancellable, error)) return FALSE; if (!info) break; filename = g_file_info_get_attribute_as_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME); if (!g_strcmp0(base_ifname, filename)) continue; link_path = g_strdup_printf ("%s/%s", sysfs_path, filename); real_path = realpath (link_path, NULL); if (!real_path) continue; basename = g_path_get_basename (real_path); /* skip interface if it was already known */ if (previous_links && g_ptr_array_find_with_equal_func (previous_links, basename, g_str_equal, NULL)) continue; g_ptr_array_add (links, g_steal_pointer (&basename)); } if (!links || !links->len) { *out_links = NULL; return TRUE; } g_ptr_array_sort (links, (GCompareFunc) g_ascii_strcasecmp); *out_links = g_steal_pointer (&links); return TRUE; } libmbim-1.31.2-dev/src/libmbim-glib/mbim-helpers.h000066400000000000000000000045111453630424100216420ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2021 Aleksander Morgado */ #ifndef _LIBMBIM_GLIB_MBIM_HELPERS_H_ #define _LIBMBIM_GLIB_MBIM_HELPERS_H_ #if !defined (LIBMBIM_GLIB_COMPILATION) #error "This is a private header!!" #endif #include #include G_BEGIN_DECLS /******************************************************************************/ /* Helpers to read variables from a bytearray without assuming alignment. The * caller should ensure the buffer contains the required amount of bytes in each * case. */ G_GNUC_INTERNAL guint16 mbim_helpers_read_unaligned_guint16 (const guint8 *buffer); G_GNUC_INTERNAL guint32 mbim_helpers_read_unaligned_guint32 (const guint8 *buffer); G_GNUC_INTERNAL guint32 mbim_helpers_read_unaligned_gint32 (const guint8 *buffer); G_GNUC_INTERNAL guint64 mbim_helpers_read_unaligned_guint64 (const guint8 *buffer); /******************************************************************************/ G_GNUC_INTERNAL gboolean mbim_helpers_check_user_allowed (uid_t uid, GError **error); G_GNUC_INTERNAL gchar *mbim_helpers_get_devpath (const gchar *cdc_wdm_path, GError **error); G_GNUC_INTERNAL gchar *mbim_helpers_get_devname (const gchar *cdc_wdm_path, GError **error); G_GNUC_INTERNAL gboolean mbim_helpers_list_links_wdm (GFile *sysfs_file, GCancellable *cancellable, GPtrArray *previous_links, GPtrArray **out_links, GError **error); G_GNUC_INTERNAL gboolean mbim_helpers_list_links_wwan (const gchar *base_ifname, GFile *sysfs_file, GCancellable *cancellable, GPtrArray *previous_links, GPtrArray **out_links, GError **error); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_HELPERS_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-message-private.h000066400000000000000000000533571453630424100233100ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2019 Aleksander Morgado * * This is a private non-installed header */ #ifndef _LIBMBIM_GLIB_MBIM_MESSAGE_PRIVATE_H_ #define _LIBMBIM_GLIB_MBIM_MESSAGE_PRIVATE_H_ #if !defined (LIBMBIM_GLIB_COMPILATION) #error "This is a private header!!" #endif #include #include "mbim-message.h" #include "mbim-tlv.h" G_BEGIN_DECLS /*****************************************************************************/ /* The MbimMessage */ /* Defined in the same way as GByteArray */ struct _MbimMessage { guint8 *data; guint len; }; /*****************************************************************************/ /* Basic message types */ struct header { guint32 type; guint32 length; guint32 transaction_id; } __attribute__((packed)); #define MBIM_MESSAGE_GET_MESSAGE_TYPE(self) \ (MbimMessageType) GUINT32_FROM_LE (((struct header *)(self->data))->type) #define MBIM_MESSAGE_GET_MESSAGE_LENGTH(self) \ GUINT32_FROM_LE (((struct header *)(self->data))->length) #define MBIM_MESSAGE_GET_TRANSACTION_ID(self) \ GUINT32_FROM_LE (((struct header *)(self->data))->transaction_id) struct open_message { guint32 max_control_transfer; } __attribute__((packed)); struct open_done_message { guint32 status_code; } __attribute__((packed)); struct close_done_message { guint32 status_code; } __attribute__((packed)); struct error_message { guint32 error_status_code; } __attribute__((packed)); struct fragment_header { guint32 total; guint32 current; } __attribute__((packed)); struct fragment_message { struct fragment_header fragment_header; guint8 buffer[]; } __attribute__((packed)); struct command_message { struct fragment_header fragment_header; guint8 service_id[16]; guint32 command_id; guint32 command_type; guint32 buffer_length; guint8 buffer[]; } __attribute__((packed)); struct command_done_message { struct fragment_header fragment_header; guint8 service_id[16]; guint32 command_id; guint32 status_code; guint32 buffer_length; guint8 buffer[]; } __attribute__((packed)); struct indicate_status_message { struct fragment_header fragment_header; guint8 service_id[16]; guint32 command_id; guint32 buffer_length; guint8 buffer[]; } __attribute__((packed)); struct full_message { struct header header; union { struct open_message open; struct open_done_message open_done; /* nothing needed for close_message */ struct close_done_message close_done; struct error_message error; struct fragment_message fragment; struct command_message command; struct command_done_message command_done; struct indicate_status_message indicate_status; } message; } __attribute__((packed)); /*****************************************************************************/ /* Message creation */ GByteArray *_mbim_message_allocate (MbimMessageType message_type, guint32 transaction_id, guint32 additional_size); /*****************************************************************************/ /* Message validation */ gboolean _mbim_message_validate_internal (const MbimMessage *self, gboolean allow_fragment, GError **error); /*****************************************************************************/ /* Fragment interface */ gboolean _mbim_message_is_fragment (const MbimMessage *self); guint32 _mbim_message_fragment_get_total (const MbimMessage *self); guint32 _mbim_message_fragment_get_current (const MbimMessage *self); const guint8 *_mbim_message_fragment_get_payload (const MbimMessage *self, guint32 *length); /* Merge fragments into a message... */ MbimMessage *_mbim_message_fragment_collector_init (const MbimMessage *fragment, GError **error); gboolean _mbim_message_fragment_collector_add (MbimMessage *self, const MbimMessage *fragment, GError **error); gboolean _mbim_message_fragment_collector_complete (MbimMessage *self); /* Split message into fragments... */ struct fragment_info { struct header header; struct fragment_header fragment_header; guint32 data_length; const guint8 *data; } __attribute__((packed)); struct fragment_info *_mbim_message_split_fragments (const MbimMessage *self, guint32 max_fragment_size, guint *n_fragments); /*****************************************************************************/ /* Struct builder */ typedef struct { GByteArray *fixed_buffer; GByteArray *variable_buffer; GArray *offsets; } MbimStructBuilder; MbimStructBuilder *_mbim_struct_builder_new (void); GByteArray *_mbim_struct_builder_complete (MbimStructBuilder *builder); void _mbim_struct_builder_append_byte_array (MbimStructBuilder *builder, gboolean with_offset, gboolean with_length, gboolean pad_buffer, const guint8 *buffer, guint32 buffer_len, gboolean swapped_offset_length); void _mbim_struct_builder_append_uuid (MbimStructBuilder *builder, const MbimUuid *value); void _mbim_struct_builder_append_guint16 (MbimStructBuilder *builder, guint16 value); void _mbim_struct_builder_append_guint32 (MbimStructBuilder *builder, guint32 value); void _mbim_struct_builder_append_gint32 (MbimStructBuilder *builder, gint32 value); void _mbim_struct_builder_append_guint32_array (MbimStructBuilder *builder, const guint32 *values, guint32 n_values); void _mbim_struct_builder_append_guint64 (MbimStructBuilder *builder, guint64 value); void _mbim_struct_builder_append_string (MbimStructBuilder *builder, const gchar *value); void _mbim_struct_builder_append_string_array (MbimStructBuilder *builder, const gchar *const *values, guint32 n_values); void _mbim_struct_builder_append_ipv4 (MbimStructBuilder *builder, const MbimIPv4 *value, gboolean ref); void _mbim_struct_builder_append_ipv4_array (MbimStructBuilder *builder, const MbimIPv4 *values, guint32 n_values); void _mbim_struct_builder_append_ipv6 (MbimStructBuilder *builder, const MbimIPv6 *value, gboolean ref); void _mbim_struct_builder_append_ipv6_array (MbimStructBuilder *builder, const MbimIPv6 *values, guint32 n_values); void _mbim_struct_builder_append_string_tlv (MbimStructBuilder *builder, const gchar *values); /*****************************************************************************/ /* Message builder */ typedef struct { MbimMessage *message; MbimStructBuilder *contents_builder; } MbimMessageCommandBuilder; MbimMessageCommandBuilder *_mbim_message_command_builder_new (guint32 transaction_id, MbimService service, guint32 cid, MbimMessageCommandType command_type); MbimMessage *_mbim_message_command_builder_complete (MbimMessageCommandBuilder *builder); void _mbim_message_command_builder_append_byte_array (MbimMessageCommandBuilder *builder, gboolean with_offset, gboolean with_length, gboolean pad_buffer, const guint8 *buffer, guint32 buffer_len, gboolean swapped_offset_length); void _mbim_message_command_builder_append_uuid (MbimMessageCommandBuilder *builder, const MbimUuid *value); void _mbim_message_command_builder_append_guint16 (MbimMessageCommandBuilder *builder, guint16 value); void _mbim_message_command_builder_append_guint32 (MbimMessageCommandBuilder *builder, guint32 value); void _mbim_message_command_builder_append_guint32_array (MbimMessageCommandBuilder *builder, const guint32 *values, guint32 n_values); void _mbim_message_command_builder_append_guint64 (MbimMessageCommandBuilder *builder, guint64 value); void _mbim_message_command_builder_append_string (MbimMessageCommandBuilder *builder, const gchar *value); void _mbim_message_command_builder_append_string_array (MbimMessageCommandBuilder *builder, const gchar *const *values, guint32 n_values); void _mbim_message_command_builder_append_ipv4 (MbimMessageCommandBuilder *builder, const MbimIPv4 *value, gboolean ref); void _mbim_message_command_builder_append_ipv4_array (MbimMessageCommandBuilder *builder, const MbimIPv4 *values, guint32 n_values); void _mbim_message_command_builder_append_ipv6 (MbimMessageCommandBuilder *builder, const MbimIPv6 *value, gboolean ref); void _mbim_message_command_builder_append_ipv6_array (MbimMessageCommandBuilder *builder, const MbimIPv6 *values, guint32 n_values); void _mbim_message_command_builder_append_tlv (MbimMessageCommandBuilder *builder, const MbimTlv *tlv); void _mbim_message_command_builder_append_tlv_string (MbimMessageCommandBuilder *builder, const gchar *str); void _mbim_message_command_builder_append_tlv_list (MbimMessageCommandBuilder *builder, const GList *tlvs); /*****************************************************************************/ /* Message parser */ typedef enum { MBIM_STRING_ENCODING_UTF16, MBIM_STRING_ENCODING_UTF8, } MbimStringEncoding; gboolean _mbim_message_read_byte_array (const MbimMessage *self, guint32 struct_start_offset, guint32 relative_offset, gboolean has_offset, gboolean has_length, guint32 explicit_array_size, const guint8 **array, guint32 *array_size, GError **error, gboolean swapped_offset_length); gboolean _mbim_message_read_uuid (const MbimMessage *self, guint32 relative_offset, const MbimUuid **uuid_ptr, /* unsafe if unaligned */ MbimUuid *uuid_value, GError **error); gboolean _mbim_message_read_guint16 (const MbimMessage *self, guint32 relative_offset, guint16 *value, GError **error); gboolean _mbim_message_read_guint32 (const MbimMessage *self, guint32 relative_offset, guint32 *value, GError **error); gboolean _mbim_message_read_gint32 (const MbimMessage *self, guint32 relative_offset, gint32 *value, GError **error); gboolean _mbim_message_read_guint32_array (const MbimMessage *self, guint32 array_size, guint32 relative_offset_array_start, guint32 **array, GError **error); gboolean _mbim_message_read_guint64 (const MbimMessage *self, guint32 relative_offset, guint64 *value, GError **error); gboolean _mbim_message_read_string (const MbimMessage *self, guint32 struct_start_offset, guint32 relative_offset, MbimStringEncoding encoding, gchar **str, guint32 *bytes_read, GError **error); gboolean _mbim_message_read_string_array (const MbimMessage *self, guint32 array_size, guint32 struct_start_offset, guint32 relative_offset_array_start, MbimStringEncoding encoding, gchar ***array, GError **error); gboolean _mbim_message_read_ipv4 (const MbimMessage *self, guint32 relative_offset, gboolean ref, const MbimIPv4 **ipv4_ptr, /* unsafe if unaligned */ MbimIPv4 *ipv4_value, GError **error); gboolean _mbim_message_read_ipv4_array (const MbimMessage *self, guint32 array_size, guint32 relative_offset_array_start, MbimIPv4 **array, GError **error); gboolean _mbim_message_read_ipv6 (const MbimMessage *self, guint32 relative_offset, gboolean ref, const MbimIPv6 **ipv6_ptr, /* unsafe if unaligned */ MbimIPv6 *ipv6_value, GError **error); gboolean _mbim_message_read_ipv6_array (const MbimMessage *self, guint32 array_size, guint32 relative_offset_array_start, MbimIPv6 **array, GError **error); gboolean _mbim_message_read_tlv (const MbimMessage *self, guint32 relative_offset, MbimTlv **tlv, guint32 *bytes_read, GError **error); gboolean _mbim_message_read_tlv_string (const MbimMessage *self, guint32 relative_offset, gchar **str, guint32 *bytes_read, GError **error); gboolean _mbim_message_read_tlv_guint16_array (const MbimMessage *self, guint32 relative_offset, guint32 *array_size, guint16 **array, guint32 *bytes_read, GError **error); gboolean _mbim_message_read_tlv_list (const MbimMessage *self, guint32 relative_offset, GList **tlv, guint32 *bytes_read, GError **error); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_MESSAGE_PRIVATE_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-message.c000066400000000000000000003521231453630424100216240ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2022 Aleksander Morgado * Copyright (C) 2022 Google, Inc. * Copyright (C) 2022 Intel Corporation */ #include #include #include #include #include #include "mbim-message.h" #include "mbim-message-private.h" #include "mbim-error-types.h" #include "mbim-enum-types.h" #include "mbim-tlv-private.h" #include "mbim-helpers.h" #include "mbim-basic-connect.h" #include "mbim-auth.h" #include "mbim-dss.h" #include "mbim-phonebook.h" #include "mbim-sms.h" #include "mbim-stk.h" #include "mbim-ussd.h" #include "mbim-proxy-control.h" #include "mbim-qmi.h" #include "mbim-ms-firmware-id.h" #include "mbim-ms-host-shutdown.h" #include "mbim-ms-sar.h" #include "mbim-atds.h" #include "mbim-intel-firmware-update.h" #include "mbim-qdu.h" #include "mbim-ms-basic-connect-extensions.h" #include "mbim-ms-uicc-low-level-access.h" #include "mbim-quectel.h" #include "mbim-intel-thermal-rf.h" #include "mbim-ms-voice-extensions.h" #include "mbim-intel-mutual-authentication.h" #include "mbim-intel-tools.h" #include "mbim-google.h" #include "mbim-fibocom.h" /*****************************************************************************/ #define MBIM_MESSAGE_IS_FRAGMENT(self) \ (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND || \ MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND_DONE || \ MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_INDICATE_STATUS) #define MBIM_MESSAGE_FRAGMENT_GET_TOTAL(self) \ GUINT32_FROM_LE (((struct full_message *)(self->data))->message.fragment.fragment_header.total) #define MBIM_MESSAGE_FRAGMENT_GET_CURRENT(self) \ GUINT32_FROM_LE (((struct full_message *)(self->data))->message.fragment.fragment_header.current) static void bytearray_apply_padding (GByteArray *buffer, guint32 *len) { static const guint8 padding = 0; g_assert (buffer); g_assert (len); /* Apply padding to the requested length until multiple of 4 */ while (*len % 4 != 0) { g_byte_array_append (buffer, &padding, 1); (*len)++; } } static void set_error_from_status (GError **error, MbimStatusError status) { const gchar *error_string; error_string = mbim_status_error_get_string (status); if (error_string) g_set_error_literal (error, MBIM_STATUS_ERROR, status, error_string); else g_set_error (error, MBIM_STATUS_ERROR, status, "Unknown status 0x%08x", status); } /*****************************************************************************/ GType mbim_message_get_type (void) { static gsize g_define_type_id_initialized = 0; if (g_once_init_enter (&g_define_type_id_initialized)) { GType g_define_type_id = g_boxed_type_register_static (g_intern_static_string ("MbimMessage"), (GBoxedCopyFunc) mbim_message_ref, (GBoxedFreeFunc) mbim_message_unref); g_once_init_leave (&g_define_type_id_initialized, g_define_type_id); } return g_define_type_id_initialized; } /*****************************************************************************/ GByteArray * _mbim_message_allocate (MbimMessageType message_type, guint32 transaction_id, guint32 additional_size) { GByteArray *self; guint32 len; /* Compute size of the basic empty message and allocate heap for it */ len = sizeof (struct header) + additional_size; self = g_byte_array_sized_new (len); g_byte_array_set_size (self, len); /* Set MBIM header */ ((struct header *)(self->data))->type = GUINT32_TO_LE (message_type); ((struct header *)(self->data))->length = GUINT32_TO_LE (len); ((struct header *)(self->data))->transaction_id = GUINT32_TO_LE (transaction_id); return self; } /*****************************************************************************/ static gboolean _mbim_message_validate_generic_header (const MbimMessage *self, GError **error) { /* Validate that the generic header can be read before reading the message * type and length */ if (self->len < sizeof (struct header)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INCOMPLETE_MESSAGE, "Message is shorter than the minimum header (%u < %u)", self->len, (guint) sizeof (struct header)); return FALSE; } /* Validate that the size reported in the message header is available */ if (self->len < MBIM_MESSAGE_GET_MESSAGE_LENGTH (self)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INCOMPLETE_MESSAGE, "Message is incomplete (%u < %u)", self->len, MBIM_MESSAGE_GET_MESSAGE_LENGTH (self)); return FALSE; } return TRUE; } static gboolean _mbim_message_validate_type_header (const MbimMessage *self, GError **error) { gsize message_header_size = 0; if (!_mbim_message_validate_generic_header (self, error)) return FALSE; /* Validate message type and get additional minimum required size based on * message type. At this stage, we only check the fragment header validity for * Command, Command Done and Indication messages, because only the 'complete' * fragment will have the additional header contents specific to each message * type. */ switch (MBIM_MESSAGE_GET_MESSAGE_TYPE (self)) { case MBIM_MESSAGE_TYPE_OPEN: message_header_size = sizeof (struct header) + sizeof (struct open_message); break; case MBIM_MESSAGE_TYPE_CLOSE: /* ignore check */ break; case MBIM_MESSAGE_TYPE_COMMAND: message_header_size = sizeof (struct header) + sizeof (struct fragment_header); break; case MBIM_MESSAGE_TYPE_OPEN_DONE: message_header_size = sizeof (struct header) + sizeof (struct open_done_message); break; case MBIM_MESSAGE_TYPE_CLOSE_DONE: message_header_size = sizeof (struct header) + sizeof (struct close_done_message); break; case MBIM_MESSAGE_TYPE_COMMAND_DONE: message_header_size = sizeof (struct header) + sizeof (struct fragment_header); break; case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: case MBIM_MESSAGE_TYPE_HOST_ERROR: message_header_size = sizeof (struct header) + sizeof (struct error_message); break; case MBIM_MESSAGE_TYPE_INDICATE_STATUS: message_header_size = sizeof (struct header) + sizeof (struct fragment_header); break; default: case MBIM_MESSAGE_TYPE_INVALID: g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Message type unknown: 0x%08x", MBIM_MESSAGE_GET_MESSAGE_TYPE (self)); return FALSE; } /* Validate that the message type specific header can be read. */ if (message_header_size && (MBIM_MESSAGE_GET_MESSAGE_LENGTH (self) < message_header_size)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Invalid message size: message type header incomplete"); return FALSE; } return TRUE; } static gboolean _mbim_message_validate_partial_fragment (const MbimMessage *self, GError **error) { if (MBIM_MESSAGE_FRAGMENT_GET_CURRENT (self) >= MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Invalid message fragment (%u/%u)", MBIM_MESSAGE_FRAGMENT_GET_CURRENT (self), MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self)); return FALSE; } return TRUE; } static gboolean _mbim_message_validate_complete_fragment (const MbimMessage *self, GError **error) { gsize message_size = 0; gsize message_header_size = 0; if (MBIM_MESSAGE_FRAGMENT_GET_CURRENT (self) != 0) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Invalid current fragment in complete message"); return FALSE; } /* Before reading the information buffer length we must validate that the * message type header is readable. */ switch (MBIM_MESSAGE_GET_MESSAGE_TYPE (self)) { case MBIM_MESSAGE_TYPE_COMMAND: message_header_size = sizeof (struct header) + sizeof (struct command_message); break; case MBIM_MESSAGE_TYPE_COMMAND_DONE: message_header_size = sizeof (struct header) + sizeof (struct command_done_message); break; case MBIM_MESSAGE_TYPE_INDICATE_STATUS: message_header_size = sizeof (struct header) + sizeof (struct indicate_status_message); break; case MBIM_MESSAGE_TYPE_OPEN: case MBIM_MESSAGE_TYPE_CLOSE: case MBIM_MESSAGE_TYPE_HOST_ERROR: case MBIM_MESSAGE_TYPE_OPEN_DONE: case MBIM_MESSAGE_TYPE_CLOSE_DONE: case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: case MBIM_MESSAGE_TYPE_INVALID: default: g_assert_not_reached (); break; } /* Validate that the message type specific header can be read. */ if (message_header_size && (MBIM_MESSAGE_GET_MESSAGE_LENGTH (self) < message_header_size)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Invalid message size: fragment type header incomplete"); return FALSE; } /* Get information buffer size */ switch (MBIM_MESSAGE_GET_MESSAGE_TYPE (self)) { case MBIM_MESSAGE_TYPE_COMMAND: message_size = sizeof (struct header) + sizeof (struct command_message) + GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command.buffer_length); break; case MBIM_MESSAGE_TYPE_COMMAND_DONE: message_size = sizeof (struct header) + sizeof (struct command_done_message) + GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command_done.buffer_length); break; case MBIM_MESSAGE_TYPE_INDICATE_STATUS: message_size = sizeof (struct header) + sizeof (struct indicate_status_message) + GUINT32_FROM_LE (((struct full_message *)(self->data))->message.indicate_status.buffer_length); break; case MBIM_MESSAGE_TYPE_OPEN: case MBIM_MESSAGE_TYPE_CLOSE: case MBIM_MESSAGE_TYPE_HOST_ERROR: case MBIM_MESSAGE_TYPE_OPEN_DONE: case MBIM_MESSAGE_TYPE_CLOSE_DONE: case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: case MBIM_MESSAGE_TYPE_INVALID: default: g_assert_not_reached (); break; } /* The information buffer must fit within the message contents */ if (MBIM_MESSAGE_GET_MESSAGE_LENGTH (self) < message_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Invalid complete fragment size: type header or information buffer incomplete (%u < %" G_GSIZE_FORMAT ")", MBIM_MESSAGE_GET_MESSAGE_LENGTH (self), message_size); return FALSE; } return TRUE; } gboolean _mbim_message_validate_internal (const MbimMessage *self, gboolean allow_fragment, GError **error) { if (!_mbim_message_validate_type_header (self, error)) return FALSE; if (!MBIM_MESSAGE_IS_FRAGMENT (self)) return TRUE; if (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) > 1) { if (allow_fragment) return _mbim_message_validate_partial_fragment (self, error); g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Incomplete partial fragment message"); return FALSE; } if (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1) return _mbim_message_validate_complete_fragment (self, error); g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Invalid total fragment number"); return FALSE; } gboolean mbim_message_validate (const MbimMessage *self, GError **error) { /* No fragments allowed in the API message validation */ return _mbim_message_validate_internal (self, FALSE, error); } /*****************************************************************************/ static guint32 _mbim_message_get_information_buffer_offset (const MbimMessage *self) { g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND || MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND_DONE || MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_INDICATE_STATUS, 0); switch (MBIM_MESSAGE_GET_MESSAGE_TYPE (self)) { case MBIM_MESSAGE_TYPE_COMMAND: return (sizeof (struct header) + G_STRUCT_OFFSET (struct command_message, buffer)); case MBIM_MESSAGE_TYPE_COMMAND_DONE: return (sizeof (struct header) + G_STRUCT_OFFSET (struct command_done_message, buffer)); break; case MBIM_MESSAGE_TYPE_INDICATE_STATUS: return (sizeof (struct header) + G_STRUCT_OFFSET (struct indicate_status_message, buffer)); break; case MBIM_MESSAGE_TYPE_INVALID: case MBIM_MESSAGE_TYPE_OPEN: case MBIM_MESSAGE_TYPE_CLOSE: case MBIM_MESSAGE_TYPE_HOST_ERROR: case MBIM_MESSAGE_TYPE_OPEN_DONE: case MBIM_MESSAGE_TYPE_CLOSE_DONE: case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: default: g_assert_not_reached (); return 0; } } gboolean _mbim_message_read_guint16 (const MbimMessage *self, guint32 relative_offset, guint16 *value, GError **error) { guint64 required_size; guint32 information_buffer_offset; g_assert (value); information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 2; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read 16bit unsigned integer (2 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } *value = mbim_helpers_read_unaligned_guint16 (self->data + information_buffer_offset + relative_offset); return TRUE; } gboolean _mbim_message_read_guint32 (const MbimMessage *self, guint32 relative_offset, guint32 *value, GError **error) { guint64 required_size; guint32 information_buffer_offset; g_assert (value); information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read 32bit unsigned integer (4 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } *value = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); return TRUE; } gboolean _mbim_message_read_gint32 (const MbimMessage *self, guint32 relative_offset, gint32 *value, GError **error) { guint64 required_size; guint32 information_buffer_offset; g_assert (value); information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read 32bit signed integer (4 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } *value = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); return TRUE; } gboolean _mbim_message_read_guint32_array (const MbimMessage *self, guint32 array_size, guint32 relative_offset_array_start, guint32 **array, GError **error) { guint64 required_size; guint i; guint32 information_buffer_offset; g_assert (array != NULL); if (!array_size) { *array = NULL; return TRUE; } information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset_array_start + (4 * (guint64)array_size); if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read 32bit unsigned integer array (%" G_GUINT64_FORMAT " bytes) (%u < %" G_GUINT64_FORMAT ")", (4 * (guint64)array_size), self->len, (guint64)required_size); return FALSE; } *array = g_new (guint32, array_size + 1); for (i = 0; i < array_size; i++) (*array)[i] = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset_array_start + (4 * i)); (*array)[array_size] = 0; return TRUE; } gboolean _mbim_message_read_guint64 (const MbimMessage *self, guint32 relative_offset, guint64 *value, GError **error) { guint64 required_size; guint32 information_buffer_offset; g_assert (value != NULL); information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 8; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read 64bit unsigned integer (8 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } *value = mbim_helpers_read_unaligned_guint64 (self->data + information_buffer_offset + relative_offset); return TRUE; } gboolean _mbim_message_read_string (const MbimMessage *self, guint32 struct_start_offset, guint32 relative_offset, MbimStringEncoding encoding, gchar **str, guint32 *bytes_read, GError **error) { g_autofree gchar *tmp = NULL; guint64 required_size; guint32 offset; guint32 size; guint32 information_buffer_offset; information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 8; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read string offset and size (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } offset = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); size = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset + 4); if (!size) { *str = NULL; if (bytes_read) *bytes_read = 0; return TRUE; } if (bytes_read) *bytes_read = size; required_size = (guint64)information_buffer_offset + (guint64)struct_start_offset + (guint64)offset + (guint64)size; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read string data (%u bytes) (%u < %" G_GUINT64_FORMAT ")", size, self->len, required_size); return FALSE; } if (encoding == MBIM_STRING_ENCODING_UTF16) { g_autofree gunichar2 *utf16d = NULL; /* Always duplicate to avoid memory alignment issues */ utf16d = g_memdup (self->data + information_buffer_offset + struct_start_offset + offset, size); /* For BE systems, convert from LE to BE */ if (G_BYTE_ORDER == G_BIG_ENDIAN) { guint i; for (i = 0; i < (size / 2); i++) utf16d[i] = GUINT16_FROM_LE (utf16d[i]); } tmp = g_utf16_to_utf8 (utf16d, size / 2, NULL, NULL, error); if (!tmp) { g_prefix_error (error, "Error converting string to UTF-8: "); return FALSE; } size = strlen (tmp); } else if (encoding == MBIM_STRING_ENCODING_UTF8) { const gchar *utf8; utf8 = (const gchar *) (self->data + information_buffer_offset + struct_start_offset + offset); /* size may include the trailing NUL byte, skip it from the check */ while (size > 0 && utf8[size - 1] == '\0') size--; tmp = g_strndup (utf8, size); } else g_assert_not_reached (); if (!g_utf8_validate (tmp, size, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Error validating UTF-8 string"); return FALSE; } *str = g_steal_pointer (&tmp); return TRUE; } gboolean _mbim_message_read_string_array (const MbimMessage *self, guint32 array_size, guint32 struct_start_offset, guint32 relative_offset_array_start, MbimStringEncoding encoding, gchar ***out_array, GError **error) { guint32 offset; guint32 i; g_autoptr(GPtrArray) array = NULL; g_assert (out_array != NULL); if (!array_size) { *out_array = NULL; return TRUE; } array = g_ptr_array_new_with_free_func (g_free); for (i = 0, offset = relative_offset_array_start; i < array_size; offset += 8, i++) { gchar *str; /* Read next string in the OL pair list */ if (!_mbim_message_read_string (self, struct_start_offset, offset, encoding, &str, NULL, error)) return FALSE; /* When an empty string is given as part of the array, we don't want to * add the NULL pointer, we should be adding the empty string explicitly. * Otherwise, if more elements are added after that one, they will leak * once the GPtrArray is freed and its contents converted into a GStrv. */ if (!str) str = g_strdup (""); g_ptr_array_add (array, str); } g_ptr_array_add (array, NULL); *out_array = (gchar **) g_ptr_array_free (g_steal_pointer (&array), FALSE); return TRUE; } /* * Byte arrays may be given in very different ways: * - (a) Offset + Length pair in static buffer, data in variable buffer. * - (b) Just length in static buffer, data just afterwards. * - (c) Just offset in static buffer, length given in another variable, data in variable buffer. * - (d) Fixed-sized array directly in the static buffer. * - (e) Unsized array directly in the variable buffer, length is assumed until end of message. */ gboolean _mbim_message_read_byte_array (const MbimMessage *self, guint32 struct_start_offset, guint32 relative_offset, gboolean has_offset, gboolean has_length, guint32 explicit_array_size, const guint8 **array, guint32 *array_size, GError **error, gboolean swapped_offset_length) { guint32 information_buffer_offset; information_buffer_offset = _mbim_message_get_information_buffer_offset (self); /* (a) Offset + Length pair in static buffer, data in variable buffer. */ if (has_offset && has_length) { guint32 offset; guint64 required_size; g_assert (array_size != NULL); g_assert (explicit_array_size == 0); /* requires 8 bytes in relative offset */ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 8; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read byte array offset and size (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } if (!swapped_offset_length) { /* (b) Offset followed by length encoding format. */ offset = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); *array_size = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset + 4); } else { /* (b) length followed by offset encoding format. */ *array_size = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); offset = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset + 4); } /* requires array_size bytes in offset */ required_size = (guint64)information_buffer_offset + (guint64)struct_start_offset + (guint64)offset + (guint64)(*array_size); if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read byte array data (%u bytes) (%u < %" G_GUINT64_FORMAT ")", *array_size, self->len, required_size); return FALSE; } *array = self->data + information_buffer_offset + struct_start_offset + offset; return TRUE; } /* (b) Just length in static buffer, data just afterwards. */ if (!has_offset && has_length) { guint64 required_size; g_assert (array_size != NULL); g_assert (explicit_array_size == 0); /* requires 4 bytes in relative offset */ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read byte array size (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } *array_size = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); /* requires array_size bytes in after the array_size variable */ required_size += (guint64)(*array_size); if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read byte array data (%u bytes) (%u < %" G_GUINT64_FORMAT ")", *array_size, self->len, required_size); return FALSE; } *array = self->data + information_buffer_offset + relative_offset + 4; return TRUE; } /* (c) Just offset in static buffer, length given in another variable, data in variable buffer. */ if (has_offset && !has_length) { guint64 required_size; guint32 offset; g_assert (array_size == NULL); /* requires 4 bytes in relative offset */ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read byte array offset (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } offset = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); /* requires explicit_array_size bytes in offset */ required_size = (guint64)information_buffer_offset + (guint64)struct_start_offset + (guint64)offset + (guint64)explicit_array_size; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read byte array data (%u bytes) (%u < %" G_GUINT64_FORMAT ")", explicit_array_size, self->len, required_size); return FALSE; } *array = self->data + information_buffer_offset + struct_start_offset + offset; return TRUE; } /* (d) Fixed-sized array directly in the static buffer. * (e) Unsized array directly in the variable buffer, length is assumed until end of message. */ if (!has_offset && !has_length) { /* If array size is requested, it's case (e) */ if (array_size) { if ((guint64)self->len < (information_buffer_offset + relative_offset)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot compute byte array length: wrong offsets"); return FALSE; } *array_size = self->len - (information_buffer_offset + relative_offset); } else { guint64 required_size; /* requires explicit_array_size bytes in offset */ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + (guint64)explicit_array_size; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read byte array data (%u bytes) (%u < %" G_GUINT64_FORMAT ")", explicit_array_size, self->len, required_size); return FALSE; } } *array = self->data + information_buffer_offset + relative_offset; return TRUE; } g_assert_not_reached (); } gboolean _mbim_message_read_uuid (const MbimMessage *self, guint32 relative_offset, const MbimUuid **uuid_ptr, /* unsafe if unaligned */ MbimUuid *uuid_value, GError **error) { guint64 required_size; guint32 information_buffer_offset; g_assert (uuid_ptr || uuid_value); g_assert (!(uuid_ptr && uuid_value)); information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 16; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read UUID (16 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } /* This explicit cast to a MbimUuid may fail if the contents are not correctly aligned, * but so far in the currently supported MBIM messages where a MbimUuid is returned * the 32bit alignment is ensured: * - MBIM Basic Connect "Connect" response. * - MBIM Basic Connect "Connect" notification. * - MBIM MS Basic Connect v3 "Connect" response. * - MBIM MS Basic Connect v3 "Connect" notification. * - MBIM MS Firmware ID "Get" response. * * We keep this limitation instead of making it an alignment-safe read because otherwise * it would require new API/ABI compat methods. */ if (uuid_ptr) *uuid_ptr = (const MbimUuid *) (self->data + information_buffer_offset + relative_offset); if (uuid_value) memcpy (uuid_value, self->data + information_buffer_offset + relative_offset, 16); return TRUE; } gboolean _mbim_message_read_ipv4 (const MbimMessage *self, guint32 relative_offset, gboolean ref, const MbimIPv4 **ipv4_ptr, /* unsafe if unaligned */ MbimIPv4 *ipv4_value, GError **error) { guint64 required_size; guint32 information_buffer_offset; guint32 offset; g_assert (ipv4_ptr || ipv4_value); g_assert (!(ipv4_ptr && ipv4_value)); information_buffer_offset = _mbim_message_get_information_buffer_offset (self); if (ref) { /* Read operations with a reference are expected only on certain message * API methods, where the output is required to be a pointer as well, to * indicate whether the field exists or not. */ g_assert (ipv4_ptr); required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read IPv4 offset (4 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } offset = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); if (!offset) { *ipv4_ptr = NULL; return TRUE; } } else offset = relative_offset; required_size = (guint64)information_buffer_offset + (guint64)offset + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read IPv4 (4 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } /* This explicit cast to a MbimIPv4 may fail if the contents are not correctly aligned, * but so far in the currently supported MBIM messages where a MbimIPv4 is returned * the 32bit alignment is ensured: * - MBIM Basic Connect "IP Configuration" response. * - MBIM Basic Connect "IP Configuration" notification. * * We keep this limitation instead of making it an alignment-safe read because otherwise * it would require new API/ABI compat methods. */ if (ipv4_ptr) *ipv4_ptr = (const MbimIPv4 *) (self->data +information_buffer_offset + offset); if (ipv4_value) memcpy (ipv4_value, self->data +information_buffer_offset + offset, 4); return TRUE; } gboolean _mbim_message_read_ipv4_array (const MbimMessage *self, guint32 array_size, guint32 relative_offset_array_start, MbimIPv4 **array, GError **error) { guint64 required_size; guint32 offset; guint32 i; guint32 information_buffer_offset; g_assert (array != NULL); if (!array_size) { *array = NULL; return TRUE; } information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset_array_start + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read IPv4 array offset (4 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } offset = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset_array_start); required_size = (guint64)information_buffer_offset + (guint64)offset + (4 * (guint64)array_size); if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read IPv4 array data (%" G_GUINT64_FORMAT " bytes) (%u < %" G_GUINT64_FORMAT ")", (4 * (guint64)array_size), self->len, required_size); return FALSE; } *array = g_new (MbimIPv4, array_size); for (i = 0; i < array_size; i++, offset += 4) memcpy (&((*array)[i]), self->data + information_buffer_offset + offset, 4); return TRUE; } gboolean _mbim_message_read_ipv6 (const MbimMessage *self, guint32 relative_offset, gboolean ref, const MbimIPv6 **ipv6_ptr, /* unsafe if unaligned */ MbimIPv6 *ipv6_value, GError **error) { guint64 required_size; guint32 information_buffer_offset; guint32 offset; g_assert (ipv6_ptr || ipv6_value); g_assert (!(ipv6_ptr && ipv6_value)); information_buffer_offset = _mbim_message_get_information_buffer_offset (self); if (ref) { /* Read operations with a reference are expected only on certain message * API methods, where the output is required to be a pointer as well, to * indicate whether the field exists or not. */ g_assert (ipv6_ptr); required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read IPv6 offset (4 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } offset = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset); if (!offset) { *ipv6_ptr = NULL; return TRUE; } } else offset = relative_offset; required_size = (guint64)information_buffer_offset + (guint64)offset + 16; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read IPv6 (16 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } /* This explicit cast to a MbimIPv6 may fail if the contents are not correctly aligned, * but so far in the currently supported MBIM messages where a MbimIPv6 is returned * the 32bit alignment is ensured: * - MBIM Basic Connect "IP Configuration" response. * - MBIM Basic Connect "IP Configuration" notification. * * We keep this limitation instead of making it an alignment-safe read because otherwise * it would require new API/ABI compat methods. */ if (ipv6_ptr) *ipv6_ptr = (const MbimIPv6 *) (self->data +information_buffer_offset + offset); if (ipv6_value) memcpy (ipv6_value, self->data +information_buffer_offset + offset, 16); return TRUE; } gboolean _mbim_message_read_ipv6_array (const MbimMessage *self, guint32 array_size, guint32 relative_offset_array_start, MbimIPv6 **array, GError **error) { guint64 required_size; guint32 offset; guint32 i; guint32 information_buffer_offset; g_assert (array != NULL); if (!array_size) { *array = NULL; return TRUE; } information_buffer_offset = _mbim_message_get_information_buffer_offset (self); required_size = (guint64)information_buffer_offset + (guint64)relative_offset_array_start + 4; if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read IPv6 array offset (4 bytes) (%u < %" G_GUINT64_FORMAT ")", self->len, required_size); return FALSE; } offset = mbim_helpers_read_unaligned_guint32 (self->data + information_buffer_offset + relative_offset_array_start); required_size = (guint64)information_buffer_offset + (guint64)offset + (16 * (guint64)array_size); if ((guint64)self->len < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read IPv6 array data (%" G_GUINT64_FORMAT " bytes) (%u < %" G_GUINT64_FORMAT ")", (16 * (guint64)array_size), self->len, required_size); return FALSE; } *array = g_new (MbimIPv6, array_size); for (i = 0; i < array_size; i++, offset += 16) memcpy (&((*array)[i]), self->data + information_buffer_offset + offset, 16); return TRUE; } gboolean _mbim_message_read_tlv (const MbimMessage *self, guint32 relative_offset, MbimTlv **tlv, guint32 *bytes_read, GError **error) { guint32 information_buffer_offset; guint64 tlv_offset; const guint8 *tlv_raw; guint32 tlv_raw_size; information_buffer_offset = _mbim_message_get_information_buffer_offset (self); tlv_offset = (guint64)information_buffer_offset + (guint64)relative_offset; if ((guint64)self->len < tlv_offset) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "TLV has invalid offset %" G_GUINT64_FORMAT " and will exceed message bounds (%u)", tlv_offset, self->len); return FALSE; } tlv_raw_size = self->len - (guint32)tlv_offset; tlv_raw = self->data + tlv_offset; *tlv = _mbim_tlv_new_from_raw (tlv_raw, tlv_raw_size, bytes_read, error); return (*tlv) ? TRUE : FALSE; } gboolean _mbim_message_read_tlv_string (const MbimMessage *self, guint32 relative_offset, gchar **str, guint32 *bytes_read, GError **error) { g_autoptr(MbimTlv) tlv = NULL; guint32 tlv_bytes_read = 0; gchar *tlv_str; if (!_mbim_message_read_tlv (self, relative_offset, &tlv, &tlv_bytes_read, error)) return FALSE; tlv_str = mbim_tlv_string_get (tlv, error); if (!tlv_str) return FALSE; *str = tlv_str; *bytes_read = tlv_bytes_read; return TRUE; } gboolean _mbim_message_read_tlv_guint16_array (const MbimMessage *self, guint32 relative_offset, guint32 *array_size, guint16 **array, guint32 *bytes_read, GError **error) { g_autoptr(MbimTlv) tlv = NULL; guint32 tlv_bytes_read = 0; if (!_mbim_message_read_tlv (self, relative_offset, &tlv, &tlv_bytes_read, error)) return FALSE; if (!mbim_tlv_guint16_array_get (tlv, array_size, array, error)) return FALSE; *bytes_read = tlv_bytes_read; return TRUE; } gboolean _mbim_message_read_tlv_list (const MbimMessage *self, guint32 relative_offset, GList **tlv_list, guint32 *bytes_read, GError **error) { guint32 information_buffer_offset; guint64 tlv_list_offset; const guint8 *tlv_list_raw; guint32 tlv_list_raw_size; GList *list = NULL; guint32 total_bytes_read = 0; GError *inner_error = NULL; information_buffer_offset = _mbim_message_get_information_buffer_offset (self); tlv_list_offset = (guint64)information_buffer_offset + (guint64)relative_offset; /* TLV list always at the end of the message */ if ((guint64)self->len < tlv_list_offset) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "TLV list item has invalid offset %" G_GUINT64_FORMAT " and will exceed message bounds (%u)", tlv_list_offset, self->len); return FALSE; } tlv_list_raw_size = self->len - (guint32)tlv_list_offset; tlv_list_raw = self->data + tlv_list_offset; while ((tlv_list_raw_size > 0) && !inner_error) { MbimTlv *tlv; guint32 tlv_bytes_read; if (tlv_list_raw_size < sizeof (struct tlv)) { g_debug ("Ignored %u bytes unused after the TLV list", tlv_list_raw_size); break; } tlv = _mbim_tlv_new_from_raw (tlv_list_raw, tlv_list_raw_size, &tlv_bytes_read, &inner_error); if (!tlv) break; list = g_list_append (list, tlv); total_bytes_read += tlv_bytes_read; g_assert (tlv_list_raw_size >= tlv_bytes_read); tlv_list_raw += tlv_bytes_read; tlv_list_raw_size -= tlv_bytes_read; } if (inner_error) { g_propagate_error (error, inner_error); g_list_free_full (list, (GDestroyNotify)mbim_tlv_unref); return FALSE; } *bytes_read = total_bytes_read; *tlv_list = list; return TRUE; } /*****************************************************************************/ /* Struct builder interface * * Types like structs consist of a fixed sized prefix plus a variable length * data buffer. Items of variable size are usually given as an offset (with * respect to the start of the struct) plus a size field. */ MbimStructBuilder * _mbim_struct_builder_new (void) { MbimStructBuilder *builder; builder = g_slice_new (MbimStructBuilder); builder->fixed_buffer = g_byte_array_new (); builder->variable_buffer = g_byte_array_new (); builder->offsets = g_array_new (FALSE, FALSE, sizeof (guint32)); return builder; } GByteArray * _mbim_struct_builder_complete (MbimStructBuilder *builder) { GByteArray *out; guint i; /* Update offsets with the length of the information buffer, and store them * in LE. */ for (i = 0; i < builder->offsets->len; i++) { guint32 offset_offset; guint32 offset_value; offset_offset = g_array_index (builder->offsets, guint32, i); memcpy (&offset_value, &(builder->fixed_buffer->data[offset_offset]), sizeof (guint32)); offset_value = GUINT32_TO_LE (offset_value + builder->fixed_buffer->len); memcpy (&(builder->fixed_buffer->data[offset_offset]), &offset_value, sizeof (guint32)); } /* Merge both buffers */ g_byte_array_append (builder->fixed_buffer, (const guint8 *)builder->variable_buffer->data, (guint32)builder->variable_buffer->len); /* Steal the buffer to return */ out = builder->fixed_buffer; /* Dispose the builder */ g_array_unref (builder->offsets); g_byte_array_unref (builder->variable_buffer); g_slice_free (MbimStructBuilder, builder); return out; } /* * Byte arrays may be given in very different ways: * - (a) Offset + Length pair in static buffer, data in variable buffer. * - (b) Just length in static buffer, data just afterwards. * - (c) Just offset in static buffer, length given in another variable, data in variable buffer. * - (d) Fixed-sized array directly in the static buffer. * - (e) Unsized array directly in the variable buffer, length is assumed until end of message. */ void _mbim_struct_builder_append_byte_array (MbimStructBuilder *builder, gboolean with_offset, gboolean with_length, gboolean pad_buffer, const guint8 *buffer, guint32 buffer_len, gboolean swapped_offset_length) { /* * (d) Fixed-sized array directly in the static buffer. * (e) Unsized array directly in the variable buffer (here end of static buffer is also beginning of variable) */ if (!with_offset && !with_length) { g_byte_array_append (builder->fixed_buffer, buffer, buffer_len); if (pad_buffer) bytearray_apply_padding (builder->fixed_buffer, &buffer_len); return; } /* (a) Offset + Length pair in static buffer, data in variable buffer. * This case is the sum of cases b+c */ /* (b) Just length in static buffer, data just afterwards. */ if (swapped_offset_length && with_length) { guint32 length; /* Add the length value in beginning and offset in the end later*/ length = GUINT32_TO_LE (buffer_len); g_byte_array_append (builder->fixed_buffer, (guint8 *)&length, sizeof (length)); } /* (c) Just offset in static buffer, length given in another variable, data in variable buffer. */ if (with_offset) { guint32 offset; /* If string length is greater than 0, add the offset to fix, otherwise set * the offset to 0 and don't configure the update */ if (buffer_len == 0) { offset = 0; g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); } else { guint32 offset_offset; /* Offset of the offset */ offset_offset = builder->fixed_buffer->len; /* Length *not* in LE yet */ offset = builder->variable_buffer->len; /* Add the offset value */ g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); /* Configure the value to get updated */ g_array_append_val (builder->offsets, offset_offset); } } /* (b) Just length in static buffer, data just afterwards. */ if (!swapped_offset_length && with_length) { guint32 length; /* Add the length value */ length = GUINT32_TO_LE (buffer_len); g_byte_array_append (builder->fixed_buffer, (guint8 *)&length, sizeof (length)); } /* And finally, the bytearray itself to the variable buffer */ if (buffer_len) { g_byte_array_append (builder->variable_buffer, (const guint8 *)buffer, (guint)buffer_len); /* Note: adding zero padding causes trouble for QMI service */ if (pad_buffer) bytearray_apply_padding (builder->variable_buffer, &buffer_len); } } void _mbim_struct_builder_append_uuid (MbimStructBuilder *builder, const MbimUuid *value) { static const MbimUuid uuid_invalid = { .a = { 0x00, 0x00, 0x00, 0x00 }, .b = { 0x00, 0x00 }, .c = { 0x00, 0x00 }, .d = { 0x00, 0x00 }, .e = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; /* uuids are added in the static buffer only */ g_byte_array_append (builder->fixed_buffer, value ? (guint8 *)value : (guint8 *)&uuid_invalid, sizeof (MbimUuid)); } void _mbim_struct_builder_append_guint16 (MbimStructBuilder *builder, guint16 value) { guint16 tmp; /* guint16 values are added in the static buffer only */ tmp = GUINT16_TO_LE (value); g_byte_array_append (builder->fixed_buffer, (guint8 *)&tmp, sizeof (tmp)); } void _mbim_struct_builder_append_guint32 (MbimStructBuilder *builder, guint32 value) { guint32 tmp; /* guint32 values are added in the static buffer only */ tmp = GUINT32_TO_LE (value); g_byte_array_append (builder->fixed_buffer, (guint8 *)&tmp, sizeof (tmp)); } void _mbim_struct_builder_append_gint32 (MbimStructBuilder *builder, gint32 value) { gint32 tmp; /* gint32 values are added in the static buffer only */ tmp = GINT32_TO_LE (value); g_byte_array_append (builder->fixed_buffer, (guint8 *)&tmp, sizeof (tmp)); } void _mbim_struct_builder_append_guint32_array (MbimStructBuilder *builder, const guint32 *values, guint32 n_values) { guint i; /* guint32 array added directly in the static buffer */ for (i = 0; i < n_values; i++) _mbim_struct_builder_append_guint32 (builder, values[i]); } void _mbim_struct_builder_append_guint64 (MbimStructBuilder *builder, guint64 value) { guint64 tmp; /* guint64 values are added in the static buffer only */ tmp = GUINT64_TO_LE (value); g_byte_array_append (builder->fixed_buffer, (guint8 *)&tmp, sizeof (tmp)); } void _mbim_struct_builder_append_string (MbimStructBuilder *builder, const gchar *value) { guint32 offset; guint32 length; g_autofree gunichar2 *utf16 = NULL; guint32 utf16_bytes = 0; /* A string consists of Offset+Size in the static buffer, plus the * string itself in the variable buffer */ /* Convert the string from UTF-8 to UTF-16HE */ if (value && value[0]) { g_autoptr(GError) error = NULL; glong items_written = 0; utf16 = g_utf8_to_utf16 (value, -1, NULL, /* bytes */ &items_written, /* gunichar2 */ &error); if (!utf16) { g_warning ("Error converting string: %s", error->message); return; } utf16_bytes = items_written * 2; } /* If string length is greater than 0, add the offset to fix, otherwise set * the offset to 0 and don't configure the update */ if (utf16_bytes == 0) { offset = 0; g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); } else { guint32 offset_offset; /* Offset of the offset */ offset_offset = builder->fixed_buffer->len; /* Length *not* in LE yet */ offset = builder->variable_buffer->len; /* Add the offset value */ g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); /* Configure the value to get updated */ g_array_append_val (builder->offsets, offset_offset); } /* Add the length value */ length = GUINT32_TO_LE (utf16_bytes); g_byte_array_append (builder->fixed_buffer, (guint8 *)&length, sizeof (length)); /* And finally, the string itself to the variable buffer */ if (utf16_bytes) { /* For BE systems, convert from BE to LE */ if (G_BYTE_ORDER == G_BIG_ENDIAN) { guint i; for (i = 0; i < (utf16_bytes / 2); i++) utf16[i] = GUINT16_TO_LE (utf16[i]); } g_byte_array_append (builder->variable_buffer, (const guint8 *)utf16, (guint)utf16_bytes); bytearray_apply_padding (builder->variable_buffer, &utf16_bytes); } } void _mbim_struct_builder_append_string_tlv (MbimStructBuilder *builder, const gchar *value) { guint8 reserved = 0; guint8 padding = 0; guint32 length; gunichar2 *utf16 = NULL; guint32 utf16_bytes = 0; GError *error = NULL; /* Add the reserved value */ g_byte_array_append (builder->fixed_buffer, (guint8 *)&reserved, sizeof (reserved)); /* Convert the string from UTF-8 to UTF-16HE */ if (value && value[0]) { glong items_written = 0; utf16 = g_utf8_to_utf16 (value, -1, NULL, /* bytes */ &items_written, /* gunichar2 */ &error); if (!utf16) { g_warning ("Error converting string: %s", error->message); g_error_free (error); return; } utf16_bytes = items_written * 2; /* Add the padding length value */ padding = utf16_bytes % 4; g_byte_array_append (builder->fixed_buffer, (guint8 *)&padding, sizeof (padding)); } /* Add the length value */ length = GUINT32_TO_LE (utf16_bytes); g_byte_array_append (builder->fixed_buffer, (guint8 *)&length, sizeof (length)); /* And finally, the string itself to the variable buffer */ if (utf16_bytes) { /* For BE systems, convert from BE to LE */ if (G_BYTE_ORDER == G_BIG_ENDIAN) { guint i; for (i = 0; i < (utf16_bytes / 2); i++) utf16[i] = GUINT16_TO_LE (utf16[i]); } g_byte_array_append (builder->variable_buffer, (const guint8 *)utf16, (guint)utf16_bytes); bytearray_apply_padding (builder->variable_buffer, &utf16_bytes); } g_free (utf16); } void _mbim_struct_builder_append_string_array (MbimStructBuilder *builder, const gchar *const *values, guint32 n_values) { /* TODO */ g_warn_if_reached (); } void _mbim_struct_builder_append_ipv4 (MbimStructBuilder *builder, const MbimIPv4 *value, gboolean ref) { if (ref) _mbim_struct_builder_append_ipv4_array (builder, value, value ? 1 : 0); else g_byte_array_append (builder->fixed_buffer, (guint8 *)value, sizeof (MbimIPv4)); } void _mbim_struct_builder_append_ipv4_array (MbimStructBuilder *builder, const MbimIPv4 *values, guint32 n_values) { guint32 offset; if (!n_values) { offset = 0; g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); } else { guint32 offset_offset; /* Offset of the offset */ offset_offset = builder->fixed_buffer->len; /* Length *not* in LE yet */ offset = builder->variable_buffer->len; /* Add the offset value */ g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); /* Configure the value to get updated */ g_array_append_val (builder->offsets, offset_offset); /* NOTE: length of the array must be given in a separate variable */ /* And finally, the array of IPs itself to the variable buffer */ g_byte_array_append (builder->variable_buffer, (guint8 *)values, n_values * sizeof (MbimIPv4)); } } void _mbim_struct_builder_append_ipv6 (MbimStructBuilder *builder, const MbimIPv6 *value, gboolean ref) { if (ref) _mbim_struct_builder_append_ipv6_array (builder, value, value ? 1 : 0); else g_byte_array_append (builder->fixed_buffer, (guint8 *)value, sizeof (MbimIPv6)); } void _mbim_struct_builder_append_ipv6_array (MbimStructBuilder *builder, const MbimIPv6 *values, guint32 n_values) { guint32 offset; if (!n_values) { offset = 0; g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); } else { guint32 offset_offset; /* Offset of the offset */ offset_offset = builder->fixed_buffer->len; /* Length *not* in LE yet */ offset = builder->variable_buffer->len; /* Add the offset value */ g_byte_array_append (builder->fixed_buffer, (guint8 *)&offset, sizeof (offset)); /* Configure the value to get updated */ g_array_append_val (builder->offsets, offset_offset); /* NOTE: length of the array must be given in a separate variable */ /* And finally, the array of IPs itself to the variable buffer */ g_byte_array_append (builder->variable_buffer, (guint8 *)values, n_values * sizeof (MbimIPv6)); } } /*****************************************************************************/ /* Command message builder interface */ MbimMessageCommandBuilder * _mbim_message_command_builder_new (guint32 transaction_id, MbimService service, guint32 cid, MbimMessageCommandType command_type) { MbimMessageCommandBuilder *builder; builder = g_slice_new (MbimMessageCommandBuilder); builder->message = mbim_message_command_new (transaction_id, service, cid, command_type); builder->contents_builder = _mbim_struct_builder_new (); return builder; } MbimMessage * _mbim_message_command_builder_complete (MbimMessageCommandBuilder *builder) { MbimMessage *message; GByteArray *contents; /* Complete contents, which disposes the builder itself */ contents = _mbim_struct_builder_complete (builder->contents_builder); /* Merge both buffers */ mbim_message_command_append (builder->message, (const guint8 *)contents->data, (guint32)contents->len); g_byte_array_unref (contents); /* Steal the message to return */ message = builder->message; /* Dispose the remaining stuff from the message builder */ g_slice_free (MbimMessageCommandBuilder, builder); return message; } void _mbim_message_command_builder_append_byte_array (MbimMessageCommandBuilder *builder, gboolean with_offset, gboolean with_length, gboolean pad_buffer, const guint8 *buffer, guint32 buffer_len, gboolean swapped_offset_length) { _mbim_struct_builder_append_byte_array (builder->contents_builder, with_offset, with_length, pad_buffer, buffer, buffer_len, swapped_offset_length); } void _mbim_message_command_builder_append_uuid (MbimMessageCommandBuilder *builder, const MbimUuid *value) { _mbim_struct_builder_append_uuid (builder->contents_builder, value); } void _mbim_message_command_builder_append_guint32 (MbimMessageCommandBuilder *builder, guint32 value) { _mbim_struct_builder_append_guint32 (builder->contents_builder, value); } void _mbim_message_command_builder_append_guint16 (MbimMessageCommandBuilder *builder, guint16 value) { _mbim_struct_builder_append_guint16 (builder->contents_builder, value); } void _mbim_message_command_builder_append_guint32_array (MbimMessageCommandBuilder *builder, const guint32 *values, guint32 n_values) { _mbim_struct_builder_append_guint32_array (builder->contents_builder, values, n_values); } void _mbim_message_command_builder_append_guint64 (MbimMessageCommandBuilder *builder, guint64 value) { _mbim_struct_builder_append_guint64 (builder->contents_builder, value); } void _mbim_message_command_builder_append_string (MbimMessageCommandBuilder *builder, const gchar *value) { _mbim_struct_builder_append_string (builder->contents_builder, value); } void _mbim_message_command_builder_append_string_array (MbimMessageCommandBuilder *builder, const gchar *const *values, guint32 n_values) { _mbim_struct_builder_append_string_array (builder->contents_builder, values, n_values); } void _mbim_message_command_builder_append_ipv4 (MbimMessageCommandBuilder *builder, const MbimIPv4 *value, gboolean ref) { _mbim_struct_builder_append_ipv4 (builder->contents_builder, value, ref); } void _mbim_message_command_builder_append_ipv4_array (MbimMessageCommandBuilder *builder, const MbimIPv4 *values, guint32 n_values) { _mbim_struct_builder_append_ipv4_array (builder->contents_builder, values, n_values); } void _mbim_message_command_builder_append_ipv6 (MbimMessageCommandBuilder *builder, const MbimIPv6 *value, gboolean ref) { _mbim_struct_builder_append_ipv6 (builder->contents_builder, value, ref); } void _mbim_message_command_builder_append_ipv6_array (MbimMessageCommandBuilder *builder, const MbimIPv6 *values, guint32 n_values) { _mbim_struct_builder_append_ipv6_array (builder->contents_builder, values, n_values); } /*****************************************************************************/ /* TLVs only expected as primary message fields, not inside structs */ void _mbim_message_command_builder_append_tlv (MbimMessageCommandBuilder *builder, const MbimTlv *tlv) { const guint8 *raw_tlv; guint32 raw_tlv_size; raw_tlv = mbim_tlv_get_raw (tlv, &raw_tlv_size, NULL); _mbim_struct_builder_append_byte_array (builder->contents_builder, FALSE, FALSE, FALSE, raw_tlv, raw_tlv_size, FALSE); } void _mbim_message_command_builder_append_tlv_string (MbimMessageCommandBuilder *builder, const gchar *str) { g_autoptr(MbimTlv) tlv = NULL; g_autoptr(GError) error = NULL; tlv = mbim_tlv_string_new (str, &error); if (!tlv) g_warning ("Error appending TLV: %s", error->message); else _mbim_message_command_builder_append_tlv (builder, tlv); } void _mbim_message_command_builder_append_tlv_list (MbimMessageCommandBuilder *builder, const GList *tlvs) { const GList *l; for (l = tlvs; l; l = g_list_next (l)) _mbim_message_command_builder_append_tlv (builder, (MbimTlv *)(l->data)); } /*****************************************************************************/ /* Generic message interface */ MbimMessage * mbim_message_ref (MbimMessage *self) { g_return_val_if_fail (self != NULL, NULL); return (MbimMessage *) g_byte_array_ref ((GByteArray *)self); } void mbim_message_unref (MbimMessage *self) { g_return_if_fail (self != NULL); g_byte_array_unref ((GByteArray *)self); } MbimMessageType mbim_message_get_message_type (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_MESSAGE_TYPE_INVALID); g_return_val_if_fail (_mbim_message_validate_generic_header (self, NULL), MBIM_MESSAGE_TYPE_INVALID); return MBIM_MESSAGE_GET_MESSAGE_TYPE (self); } guint32 mbim_message_get_message_length (const MbimMessage *self) { g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (_mbim_message_validate_generic_header (self, NULL), 0); return MBIM_MESSAGE_GET_MESSAGE_LENGTH (self); } guint32 mbim_message_get_transaction_id (const MbimMessage *self) { g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (_mbim_message_validate_generic_header (self, NULL), 0); return MBIM_MESSAGE_GET_TRANSACTION_ID (self); } void mbim_message_set_transaction_id (MbimMessage *self, guint32 transaction_id) { g_return_if_fail (self != NULL); g_return_if_fail (_mbim_message_validate_generic_header (self, NULL)); ((struct header *)(self->data))->transaction_id = GUINT32_TO_LE (transaction_id); } MbimMessage * mbim_message_new (const guint8 *data, guint32 data_length) { GByteArray *out; /* Create output MbimMessage */ out = g_byte_array_sized_new (data_length); g_byte_array_append (out, data, data_length); return (MbimMessage *)out; } MbimMessage * mbim_message_dup (const MbimMessage *self) { g_return_val_if_fail (self != NULL, NULL); return mbim_message_new (((GByteArray *)self)->data, MBIM_MESSAGE_GET_MESSAGE_LENGTH (self)); } const guint8 * mbim_message_get_raw (const MbimMessage *self, guint32 *length, GError **error) { g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (length != NULL, NULL); if (!self->data || !self->len) { g_set_error_literal (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Message is empty"); return NULL; } *length = (guint32) self->len; return self->data; } gchar * mbim_message_get_printable (const MbimMessage *self, const gchar *line_prefix, gboolean headers_only) { return mbim_message_get_printable_full (self, 1, 0, line_prefix, headers_only, NULL); } gchar * mbim_message_get_printable_full (const MbimMessage *self, guint8 mbimex_version_major, guint8 mbimex_version_minor, const gchar *line_prefix, gboolean headers_only, GError **error) { GString *printable = NULL; MbimService service_read_fields = MBIM_SERVICE_INVALID; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (line_prefix != NULL, NULL); g_return_val_if_fail (_mbim_message_validate_internal (self, TRUE, NULL), NULL); if (mbimex_version_major > 3) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "MBIMEx version %x.%02x is unsupported", mbimex_version_major, mbimex_version_minor); return NULL; } if (!line_prefix) line_prefix = ""; printable = g_string_new (""); g_string_append_printf (printable, "%sHeader:\n" "%s length = %u\n" "%s type = %s (0x%08x)\n" "%s transaction = %u\n", line_prefix, line_prefix, MBIM_MESSAGE_GET_MESSAGE_LENGTH (self), line_prefix, mbim_message_type_get_string (MBIM_MESSAGE_GET_MESSAGE_TYPE (self)), MBIM_MESSAGE_GET_MESSAGE_TYPE (self), line_prefix, MBIM_MESSAGE_GET_TRANSACTION_ID (self)); switch (MBIM_MESSAGE_GET_MESSAGE_TYPE (self)) { case MBIM_MESSAGE_TYPE_INVALID: g_warn_if_reached (); break; case MBIM_MESSAGE_TYPE_OPEN: if (!headers_only) g_string_append_printf (printable, "%sContents:\n" "%s max control transfer = %u\n", line_prefix, line_prefix, mbim_message_open_get_max_control_transfer (self)); break; case MBIM_MESSAGE_TYPE_CLOSE: break; case MBIM_MESSAGE_TYPE_OPEN_DONE: if (!headers_only) { MbimStatusError status; status = mbim_message_open_done_get_status_code (self); g_string_append_printf (printable, "%sContents:\n" "%s status error = '%s' (0x%08x)\n", line_prefix, line_prefix, mbim_status_error_get_string (status), status); } break; case MBIM_MESSAGE_TYPE_CLOSE_DONE: if (!headers_only) { MbimStatusError status; status = mbim_message_close_done_get_status_code (self); g_string_append_printf (printable, "%sContents:\n" "%s status error = '%s' (0x%08x)\n", line_prefix, line_prefix, mbim_status_error_get_string (status), status); } break; case MBIM_MESSAGE_TYPE_HOST_ERROR: case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: if (!headers_only) { MbimProtocolError protocol_error; protocol_error = mbim_message_error_get_error_status_code (self); g_string_append_printf (printable, "%sContents:\n" "%s error = '%s' (0x%08x)\n", line_prefix, line_prefix, mbim_protocol_error_get_string (protocol_error), protocol_error); } break; case MBIM_MESSAGE_TYPE_COMMAND: g_string_append_printf (printable, "%sFragment header:\n" "%s total = %u\n" "%s current = %u\n", line_prefix, line_prefix, _mbim_message_fragment_get_total (self), line_prefix, _mbim_message_fragment_get_current (self)); if (!headers_only) { g_autofree gchar *uuid_printable = NULL; const gchar *cid_printable; service_read_fields = mbim_message_command_get_service (self); uuid_printable = mbim_uuid_get_printable (mbim_message_command_get_service_id (self)); cid_printable = mbim_cid_get_printable (mbim_message_command_get_service (self), mbim_message_command_get_cid (self)); g_string_append_printf (printable, "%sContents:\n" "%s service = '%s' (%s)\n" "%s cid = '%s' (0x%08x)\n" "%s type = '%s' (0x%08x)\n", line_prefix, line_prefix, mbim_service_lookup_name (mbim_message_command_get_service (self)), uuid_printable, line_prefix, cid_printable, mbim_message_command_get_cid (self), line_prefix, mbim_message_command_type_get_string (mbim_message_command_get_command_type (self)), mbim_message_command_get_command_type (self)); } break; case MBIM_MESSAGE_TYPE_COMMAND_DONE: g_string_append_printf (printable, "%sFragment header:\n" "%s total = %u\n" "%s current = %u\n", line_prefix, line_prefix, _mbim_message_fragment_get_total (self), line_prefix, _mbim_message_fragment_get_current (self)); if (!headers_only) { g_autofree gchar *uuid_printable = NULL; MbimStatusError status; const gchar *cid_printable; service_read_fields = mbim_message_command_done_get_service (self); status = mbim_message_command_done_get_status_code (self); uuid_printable = mbim_uuid_get_printable (mbim_message_command_done_get_service_id (self)); cid_printable = mbim_cid_get_printable (mbim_message_command_done_get_service (self), mbim_message_command_done_get_cid (self)); g_string_append_printf (printable, "%sContents:\n" "%s status error = '%s' (0x%08x)\n" "%s service = '%s' (%s)\n" "%s cid = '%s' (0x%08x)\n", line_prefix, line_prefix, mbim_status_error_get_string (status), status, line_prefix, mbim_service_lookup_name (mbim_message_command_done_get_service (self)), uuid_printable, line_prefix, cid_printable, mbim_message_command_done_get_cid (self)); } break; case MBIM_MESSAGE_TYPE_INDICATE_STATUS: g_string_append_printf (printable, "%sFragment header:\n" "%s total = %u\n" "%s current = %u\n", line_prefix, line_prefix, _mbim_message_fragment_get_total (self), line_prefix, _mbim_message_fragment_get_current (self)); if (!headers_only) { g_autofree gchar *uuid_printable = NULL; const gchar *cid_printable; service_read_fields = mbim_message_indicate_status_get_service (self); uuid_printable = mbim_uuid_get_printable (mbim_message_indicate_status_get_service_id (self)); cid_printable = mbim_cid_get_printable (mbim_message_indicate_status_get_service (self), mbim_message_indicate_status_get_cid (self)); g_string_append_printf (printable, "%sContents:\n" "%s service = '%s' (%s)\n" "%s cid = '%s' (0x%08x)\n", line_prefix, line_prefix, mbim_service_lookup_name (mbim_message_indicate_status_get_service (self)), uuid_printable, line_prefix, cid_printable, mbim_message_indicate_status_get_cid (self)); } break; default: g_assert_not_reached (); } if (service_read_fields != MBIM_SERVICE_INVALID) { g_autofree gchar *fields_printable = NULL; g_autoptr(GError) inner_error = NULL; switch (service_read_fields) { case MBIM_SERVICE_BASIC_CONNECT: if (mbimex_version_major < 2) fields_printable = __mbim_message_basic_connect_get_printable_fields (self, line_prefix, &inner_error); else if (mbimex_version_major == 2) { fields_printable = __mbim_message_ms_basic_connect_v2_get_printable_fields (self, line_prefix, &inner_error); /* attempt fallback to v1 printable */ if (g_error_matches (inner_error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNSUPPORTED)) { g_clear_error (&inner_error); fields_printable = __mbim_message_basic_connect_get_printable_fields (self, line_prefix, &inner_error); } } else if (mbimex_version_major == 3) { fields_printable = __mbim_message_ms_basic_connect_v3_get_printable_fields (self, line_prefix, &inner_error); /* attempt fallback to v2 printable */ if (g_error_matches (inner_error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNSUPPORTED)) { g_clear_error (&inner_error); fields_printable = __mbim_message_ms_basic_connect_v2_get_printable_fields (self, line_prefix, &inner_error); /* attempt fallback to v1 printable */ if (g_error_matches (inner_error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNSUPPORTED)) { g_clear_error (&inner_error); fields_printable = __mbim_message_basic_connect_get_printable_fields (self, line_prefix, &inner_error); } } } else g_assert_not_reached (); break; case MBIM_SERVICE_SMS: fields_printable = __mbim_message_sms_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_USSD: fields_printable = __mbim_message_ussd_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_PHONEBOOK: fields_printable = __mbim_message_phonebook_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_STK: fields_printable = __mbim_message_stk_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_AUTH: fields_printable = __mbim_message_auth_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_DSS: fields_printable = __mbim_message_dss_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_MS_FIRMWARE_ID: fields_printable = __mbim_message_ms_firmware_id_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_MS_HOST_SHUTDOWN: fields_printable = __mbim_message_ms_host_shutdown_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_MS_SAR: fields_printable = __mbim_message_ms_sar_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_PROXY_CONTROL: fields_printable = __mbim_message_proxy_control_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_QMI: fields_printable = __mbim_message_qmi_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_ATDS: fields_printable = __mbim_message_atds_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_INTEL_FIRMWARE_UPDATE: if (mbimex_version_major < 2) fields_printable = __mbim_message_intel_firmware_update_get_printable_fields (self, line_prefix, &inner_error); else if (mbimex_version_major >= 2) { fields_printable = __mbim_message_intel_firmware_update_v2_get_printable_fields (self, line_prefix, &inner_error); if (g_error_matches (inner_error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNSUPPORTED)) { g_clear_error (&inner_error); fields_printable = __mbim_message_intel_firmware_update_get_printable_fields (self, line_prefix, &inner_error); } } break; case MBIM_SERVICE_QDU: fields_printable = __mbim_message_qdu_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS: if (mbimex_version_major < 2) fields_printable = __mbim_message_ms_basic_connect_extensions_get_printable_fields (self, line_prefix, &inner_error); else if (mbimex_version_major == 2) { fields_printable = __mbim_message_ms_basic_connect_extensions_v2_get_printable_fields (self, line_prefix, &inner_error); /* attempt fallback to v1 printable */ if (g_error_matches (inner_error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNSUPPORTED)) { g_clear_error (&inner_error); fields_printable = __mbim_message_ms_basic_connect_extensions_get_printable_fields (self, line_prefix, &inner_error); } } else if (mbimex_version_major == 3) { fields_printable = __mbim_message_ms_basic_connect_extensions_v3_get_printable_fields (self, line_prefix, &inner_error); /* attempt fallback to v2 printable */ if (g_error_matches (inner_error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNSUPPORTED)) { g_clear_error (&inner_error); fields_printable = __mbim_message_ms_basic_connect_extensions_v2_get_printable_fields (self, line_prefix, &inner_error); /* attempt fallback to v1 printable */ if (g_error_matches (inner_error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNSUPPORTED)) { g_clear_error (&inner_error); fields_printable = __mbim_message_ms_basic_connect_extensions_get_printable_fields (self, line_prefix, &inner_error); } } } else g_assert_not_reached (); break; case MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS: fields_printable = __mbim_message_ms_uicc_low_level_access_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_QUECTEL: fields_printable = __mbim_message_quectel_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_INTEL_THERMAL_RF: fields_printable = __mbim_message_intel_thermal_rf_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_MS_VOICE_EXTENSIONS: fields_printable = __mbim_message_ms_voice_extensions_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: fields_printable = __mbim_message_intel_mutual_authentication_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_INTEL_TOOLS: fields_printable = __mbim_message_intel_tools_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_GOOGLE: fields_printable = __mbim_message_google_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_FIBOCOM: fields_printable = __mbim_message_fibocom_get_printable_fields (self, line_prefix, &inner_error); break; case MBIM_SERVICE_INVALID: case MBIM_SERVICE_LAST: g_assert_not_reached (); default: break; } if (inner_error) g_string_append_printf (printable, "%sFields: %s\n", line_prefix, inner_error->message); else if (fields_printable && fields_printable[0]) g_string_append_printf (printable, "%sFields:\n" "%s", line_prefix, fields_printable); } return g_string_free (printable, FALSE); } /*****************************************************************************/ /* Fragment interface */ gboolean _mbim_message_is_fragment (const MbimMessage *self) { return MBIM_MESSAGE_IS_FRAGMENT (self); } guint32 _mbim_message_fragment_get_total (const MbimMessage *self) { g_assert (MBIM_MESSAGE_IS_FRAGMENT (self)); return MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self); } guint32 _mbim_message_fragment_get_current (const MbimMessage *self) { g_assert (MBIM_MESSAGE_IS_FRAGMENT (self)); return MBIM_MESSAGE_FRAGMENT_GET_CURRENT (self); } const guint8 * _mbim_message_fragment_get_payload (const MbimMessage *self, guint32 *length) { g_assert (MBIM_MESSAGE_IS_FRAGMENT (self)); *length = (MBIM_MESSAGE_GET_MESSAGE_LENGTH (self) - \ sizeof (struct header) - \ sizeof (struct fragment_header)); return ((struct full_message *)(self->data))->message.fragment.buffer; } MbimMessage * _mbim_message_fragment_collector_init (const MbimMessage *fragment, GError **error) { g_assert (MBIM_MESSAGE_IS_FRAGMENT (fragment)); /* Collector must start with fragment #0 */ if (MBIM_MESSAGE_FRAGMENT_GET_CURRENT (fragment) != 0) { g_set_error (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_FRAGMENT_OUT_OF_SEQUENCE, "Expecting fragment '0/%u', got '%u/%u'", MBIM_MESSAGE_FRAGMENT_GET_TOTAL (fragment), MBIM_MESSAGE_FRAGMENT_GET_CURRENT (fragment), MBIM_MESSAGE_FRAGMENT_GET_TOTAL (fragment)); return NULL; } return mbim_message_dup (fragment); } gboolean _mbim_message_fragment_collector_add (MbimMessage *self, const MbimMessage *fragment, GError **error) { guint32 buffer_len; const guint8 *buffer; g_assert (MBIM_MESSAGE_IS_FRAGMENT (self)); g_assert (MBIM_MESSAGE_IS_FRAGMENT (fragment)); /* We can only add a fragment if it is the next one we're expecting. * Otherwise, we return an error. */ if (MBIM_MESSAGE_FRAGMENT_GET_CURRENT (self) != (MBIM_MESSAGE_FRAGMENT_GET_CURRENT (fragment) - 1)) { g_set_error (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_FRAGMENT_OUT_OF_SEQUENCE, "Expecting fragment '%u/%u', got '%u/%u'", MBIM_MESSAGE_FRAGMENT_GET_CURRENT (self) + 1, MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self), MBIM_MESSAGE_FRAGMENT_GET_CURRENT (fragment), MBIM_MESSAGE_FRAGMENT_GET_TOTAL (fragment)); return FALSE; } buffer = _mbim_message_fragment_get_payload (fragment, &buffer_len); if (buffer_len) { /* Concatenate information buffers */ g_byte_array_append ((GByteArray *)self, buffer, buffer_len); /* Update the whole message length */ ((struct header *)(self->data))->length = GUINT32_TO_LE (MBIM_MESSAGE_GET_MESSAGE_LENGTH (self) + buffer_len); } /* Update the current fragment info in the main message; skip endian changes */ ((struct full_message *)(self->data))->message.fragment.fragment_header.current = ((struct full_message *)(fragment->data))->message.fragment.fragment_header.current; return TRUE; } gboolean _mbim_message_fragment_collector_complete (MbimMessage *self) { g_assert (MBIM_MESSAGE_IS_FRAGMENT (self)); if (MBIM_MESSAGE_FRAGMENT_GET_CURRENT (self) != (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) - 1)) /* Not complete yet */ return FALSE; /* Reset current & total */ ((struct full_message *)(self->data))->message.fragment.fragment_header.current = 0; ((struct full_message *)(self->data))->message.fragment.fragment_header.total = GUINT32_TO_LE (1); return TRUE; } struct fragment_info * _mbim_message_split_fragments (const MbimMessage *self, guint32 max_fragment_size, guint *n_fragments) { GArray *array; guint32 total_message_length; guint32 total_payload_length; guint32 fragment_header_length; guint32 fragment_payload_length; guint32 total_fragments; guint i; const guint8 *data; guint32 data_length; /* A message which is longer than the maximum fragment size needs to be * split in different fragments before sending it. */ total_message_length = mbim_message_get_message_length (self); /* If a single fragment is enough, don't try to split */ if (total_message_length <= max_fragment_size) return NULL; /* Total payload length is the total length minus the headers of the * input message */ fragment_header_length = sizeof (struct header) + sizeof (struct fragment_header); total_payload_length = total_message_length - fragment_header_length; /* Fragment payload length is the maximum amount of data that can fit in a * single fragment */ fragment_payload_length = max_fragment_size - fragment_header_length; /* We can now compute the number of fragments that we'll get */ total_fragments = total_payload_length / fragment_payload_length; if (total_payload_length % fragment_payload_length) total_fragments++; array = g_array_sized_new (FALSE, FALSE, sizeof (struct fragment_info), total_fragments); /* Initialize data walkers */ data = ((struct full_message *)(((GByteArray *)self)->data))->message.fragment.buffer; data_length = total_payload_length; /* Create fragment infos */ for (i = 0; i < total_fragments; i++) { struct fragment_info info; /* Set data info */ info.data = data; info.data_length = (data_length > fragment_payload_length ? fragment_payload_length : data_length); /* Set header info */ info.header.type = GUINT32_TO_LE (MBIM_MESSAGE_GET_MESSAGE_TYPE (self)); info.header.length = GUINT32_TO_LE (fragment_header_length + info.data_length); info.header.transaction_id = GUINT32_TO_LE (MBIM_MESSAGE_GET_TRANSACTION_ID (self)); info.fragment_header.total = GUINT32_TO_LE (total_fragments); info.fragment_header.current = GUINT32_TO_LE (i); g_array_insert_val (array, i, info); /* Update walkers */ data = &data[info.data_length]; data_length -= info.data_length; } g_warn_if_fail (data_length == 0); *n_fragments = total_fragments; return (struct fragment_info *) g_array_free (array, FALSE); } /*****************************************************************************/ /* 'Open' message interface */ MbimMessage * mbim_message_open_new (guint32 transaction_id, guint32 max_control_transfer) { GByteArray *self; self = _mbim_message_allocate (MBIM_MESSAGE_TYPE_OPEN, transaction_id, sizeof (struct open_message)); /* Open header */ ((struct full_message *)(self->data))->message.open.max_control_transfer = GUINT32_TO_LE (max_control_transfer); return (MbimMessage *)self; } guint32 mbim_message_open_get_max_control_transfer (const MbimMessage *self) { g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), 0); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_OPEN, 0); return GUINT32_FROM_LE (((struct full_message *)(self->data))->message.open.max_control_transfer); } /*****************************************************************************/ /* 'Open Done' message interface */ MbimMessage * mbim_message_open_done_new (guint32 transaction_id, MbimStatusError error_status_code) { GByteArray *self; self = _mbim_message_allocate (MBIM_MESSAGE_TYPE_OPEN_DONE, transaction_id, sizeof (struct open_done_message)); /* Open header */ ((struct full_message *)(self->data))->message.open_done.status_code = GUINT32_TO_LE (error_status_code); return (MbimMessage *)self; } MbimStatusError mbim_message_open_done_get_status_code (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_STATUS_ERROR_FAILURE); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_STATUS_ERROR_FAILURE); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_OPEN_DONE, MBIM_STATUS_ERROR_FAILURE); return (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.open_done.status_code); } gboolean mbim_message_open_done_get_result (const MbimMessage *self, GError **error) { MbimStatusError status; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), FALSE); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_OPEN_DONE, FALSE); status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.open_done.status_code); if (status == MBIM_STATUS_ERROR_NONE) return TRUE; set_error_from_status (error, status); return FALSE; } /*****************************************************************************/ /* 'Close' message interface */ MbimMessage * mbim_message_close_new (guint32 transaction_id) { return (MbimMessage *) _mbim_message_allocate (MBIM_MESSAGE_TYPE_CLOSE, transaction_id, 0); } /*****************************************************************************/ /* 'Close Done' message interface */ MbimMessage * mbim_message_close_done_new (guint32 transaction_id, MbimStatusError error_status_code) { GByteArray *self; self = _mbim_message_allocate (MBIM_MESSAGE_TYPE_CLOSE_DONE, transaction_id, sizeof (struct close_done_message)); /* Open header */ ((struct full_message *)(self->data))->message.close_done.status_code = GUINT32_TO_LE (error_status_code); return (MbimMessage *)self; } MbimStatusError mbim_message_close_done_get_status_code (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_STATUS_ERROR_FAILURE); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_STATUS_ERROR_FAILURE); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_CLOSE_DONE, MBIM_STATUS_ERROR_FAILURE); return (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.close_done.status_code); } gboolean mbim_message_close_done_get_result (const MbimMessage *self, GError **error) { MbimStatusError status; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), FALSE); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_CLOSE_DONE, FALSE); status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.close_done.status_code); if (status == MBIM_STATUS_ERROR_NONE) return TRUE; set_error_from_status (error, status); return FALSE; } /*****************************************************************************/ /* 'Error' message interface */ MbimMessage * mbim_message_error_new (guint32 transaction_id, MbimProtocolError error_status_code) { GByteArray *self; self = _mbim_message_allocate (MBIM_MESSAGE_TYPE_HOST_ERROR, transaction_id, sizeof (struct error_message)); /* Open header */ ((struct full_message *)(self->data))->message.error.error_status_code = GUINT32_TO_LE (error_status_code); return (MbimMessage *)self; } MbimMessage * mbim_message_function_error_new (guint32 transaction_id, MbimProtocolError error_status_code) { GByteArray *self; self = _mbim_message_allocate (MBIM_MESSAGE_TYPE_FUNCTION_ERROR, transaction_id, sizeof (struct error_message)); /* Open header */ ((struct full_message *)(self->data))->message.error.error_status_code = GUINT32_TO_LE (error_status_code); return (MbimMessage *)self; } MbimProtocolError mbim_message_error_get_error_status_code (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_PROTOCOL_ERROR_INVALID); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_PROTOCOL_ERROR_INVALID); g_return_val_if_fail ((MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_HOST_ERROR || MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_FUNCTION_ERROR), MBIM_PROTOCOL_ERROR_INVALID); return (MbimProtocolError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.error.error_status_code); } GError * mbim_message_error_get_error (const MbimMessage *self) { MbimProtocolError error_status_code; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), NULL); g_return_val_if_fail ((MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_HOST_ERROR || MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_FUNCTION_ERROR), NULL); error_status_code = (MbimProtocolError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.error.error_status_code); return g_error_new (MBIM_PROTOCOL_ERROR, error_status_code, "MBIM protocol error: %s", mbim_protocol_error_get_string (error_status_code)); } /*****************************************************************************/ /* 'Command' message interface */ MbimMessage * mbim_message_command_new (guint32 transaction_id, MbimService service, guint32 cid, MbimMessageCommandType command_type) { GByteArray *self; const MbimUuid *service_id; /* Known service required */ service_id = mbim_uuid_from_service (service); g_return_val_if_fail (service_id != NULL, NULL); self = _mbim_message_allocate (MBIM_MESSAGE_TYPE_COMMAND, transaction_id, sizeof (struct command_message)); /* Fragment header */ ((struct full_message *)(self->data))->message.command.fragment_header.total = GUINT32_TO_LE (1); ((struct full_message *)(self->data))->message.command.fragment_header.current = 0; /* Command header */ memcpy (((struct full_message *)(self->data))->message.command.service_id, service_id, sizeof (*service_id)); ((struct full_message *)(self->data))->message.command.command_id = GUINT32_TO_LE (cid); ((struct full_message *)(self->data))->message.command.command_type = GUINT32_TO_LE (command_type); ((struct full_message *)(self->data))->message.command.buffer_length = 0; return (MbimMessage *)self; } void mbim_message_command_append (MbimMessage *self, const guint8 *buffer, guint32 buffer_size) { g_byte_array_append ((GByteArray *)self, buffer, buffer_size); /* Update message and buffer length */ ((struct header *)(self->data))->length = GUINT32_TO_LE (MBIM_MESSAGE_GET_MESSAGE_LENGTH (self) + buffer_size); ((struct full_message *)(self->data))->message.command.buffer_length = GUINT32_TO_LE (GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command.buffer_length) + buffer_size); } MbimService mbim_message_command_get_service (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_SERVICE_INVALID); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_SERVICE_INVALID); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND, MBIM_SERVICE_INVALID); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, MBIM_SERVICE_INVALID); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), MBIM_SERVICE_INVALID); return mbim_uuid_to_service ((const MbimUuid *)&(((struct full_message *)(self->data))->message.command.service_id)); } const MbimUuid * mbim_message_command_get_service_id (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_UUID_INVALID); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_UUID_INVALID); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND, MBIM_UUID_INVALID); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, MBIM_UUID_INVALID); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), MBIM_UUID_INVALID); return (const MbimUuid *)&(((struct full_message *)(self->data))->message.command.service_id); } guint32 mbim_message_command_get_cid (const MbimMessage *self) { g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), 0); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND, 0); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, 0); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), 0); return GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command.command_id); } MbimMessageCommandType mbim_message_command_get_command_type (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND, MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN); return (MbimMessageCommandType) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command.command_type); } const guint8 * mbim_message_command_get_raw_information_buffer (const MbimMessage *self, guint32 *out_length) { guint32 length; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), NULL); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND, NULL); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, NULL); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), NULL); length = GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command.buffer_length); if (out_length) *out_length = length; return (length > 0 ? ((struct full_message *)(self->data))->message.command.buffer : NULL); } /*****************************************************************************/ /* 'Command Done' message interface */ MbimService mbim_message_command_done_get_service (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_SERVICE_INVALID); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_SERVICE_INVALID); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND_DONE, MBIM_SERVICE_INVALID); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, MBIM_SERVICE_INVALID); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), MBIM_SERVICE_INVALID); return mbim_uuid_to_service ((const MbimUuid *)&(((struct full_message *)(self->data))->message.command_done.service_id)); } const MbimUuid * mbim_message_command_done_get_service_id (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_UUID_INVALID); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_UUID_INVALID); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND_DONE, MBIM_UUID_INVALID); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, MBIM_UUID_INVALID); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), MBIM_UUID_INVALID); return (const MbimUuid *)&(((struct full_message *)(self->data))->message.command_done.service_id); } guint32 mbim_message_command_done_get_cid (const MbimMessage *self) { g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), 0); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND_DONE, 0); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, 0); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), 0); return GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command_done.command_id); } MbimStatusError mbim_message_command_done_get_status_code (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_STATUS_ERROR_FAILURE); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_STATUS_ERROR_FAILURE); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND_DONE, MBIM_STATUS_ERROR_FAILURE); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, MBIM_STATUS_ERROR_FAILURE); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), MBIM_STATUS_ERROR_FAILURE); return (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command_done.status_code); } gboolean mbim_message_command_done_get_result (const MbimMessage *self, GError **error) { MbimStatusError status; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), FALSE); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND_DONE, FALSE); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, FALSE); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), FALSE); status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command_done.status_code); if (status == MBIM_STATUS_ERROR_NONE) return TRUE; set_error_from_status (error, status); return FALSE; } const guint8 * mbim_message_command_done_get_raw_information_buffer (const MbimMessage *self, guint32 *out_length) { guint32 length; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), NULL); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_COMMAND_DONE, NULL); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, NULL); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), NULL); length = GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command_done.buffer_length); if (out_length) *out_length = length; return (length > 0 ? ((struct full_message *)(self->data))->message.command_done.buffer : NULL); } /*****************************************************************************/ /* 'Indicate Status' message interface */ MbimService mbim_message_indicate_status_get_service (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_SERVICE_INVALID); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_SERVICE_INVALID); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_INDICATE_STATUS, MBIM_SERVICE_INVALID); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, MBIM_SERVICE_INVALID); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), MBIM_SERVICE_INVALID); return mbim_uuid_to_service ((const MbimUuid *)&(((struct full_message *)(self->data))->message.indicate_status.service_id)); } const MbimUuid * mbim_message_indicate_status_get_service_id (const MbimMessage *self) { g_return_val_if_fail (self != NULL, MBIM_UUID_INVALID); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), MBIM_UUID_INVALID); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_INDICATE_STATUS, MBIM_UUID_INVALID); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, MBIM_UUID_INVALID); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), MBIM_UUID_INVALID); return (const MbimUuid *)&(((struct full_message *)(self->data))->message.indicate_status.service_id); } guint32 mbim_message_indicate_status_get_cid (const MbimMessage *self) { g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), 0); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_INDICATE_STATUS, 0); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, 0); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), 0); return GUINT32_FROM_LE (((struct full_message *)(self->data))->message.indicate_status.command_id); } const guint8 * mbim_message_indicate_status_get_raw_information_buffer (const MbimMessage *self, guint32 *out_length) { guint32 length; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), NULL); g_return_val_if_fail (MBIM_MESSAGE_GET_MESSAGE_TYPE (self) == MBIM_MESSAGE_TYPE_INDICATE_STATUS, NULL); g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, NULL); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), NULL); length = GUINT32_FROM_LE (((struct full_message *)(self->data))->message.indicate_status.buffer_length); if (out_length) *out_length = length; return (length > 0 ? ((struct full_message *)(self->data))->message.indicate_status.buffer : NULL); } /*****************************************************************************/ /* Other helpers */ gboolean mbim_message_response_get_result (const MbimMessage *self, MbimMessageType expected, GError **error) { MbimStatusError status = MBIM_STATUS_ERROR_NONE; MbimMessageType type; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (expected == MBIM_MESSAGE_TYPE_OPEN_DONE || expected == MBIM_MESSAGE_TYPE_CLOSE_DONE || expected == MBIM_MESSAGE_TYPE_COMMAND_DONE, FALSE); g_return_val_if_fail (_mbim_message_validate_type_header (self, NULL), FALSE); type = MBIM_MESSAGE_GET_MESSAGE_TYPE (self); if (type != MBIM_MESSAGE_TYPE_FUNCTION_ERROR && type != expected) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Unexpected response message type: 0x%04X", (guint32) type); return FALSE; } switch (type) { case MBIM_MESSAGE_TYPE_OPEN_DONE: status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.open_done.status_code); break; case MBIM_MESSAGE_TYPE_CLOSE_DONE: status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.close_done.status_code); break; case MBIM_MESSAGE_TYPE_COMMAND_DONE: g_return_val_if_fail (MBIM_MESSAGE_FRAGMENT_GET_TOTAL (self) == 1, FALSE); g_return_val_if_fail (_mbim_message_validate_complete_fragment (self, NULL), FALSE); status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command_done.status_code); break; case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: if (error) *error = mbim_message_error_get_error (self); return FALSE; case MBIM_MESSAGE_TYPE_INVALID: case MBIM_MESSAGE_TYPE_OPEN: case MBIM_MESSAGE_TYPE_CLOSE: case MBIM_MESSAGE_TYPE_COMMAND: case MBIM_MESSAGE_TYPE_HOST_ERROR: case MBIM_MESSAGE_TYPE_INDICATE_STATUS: default: g_assert_not_reached (); } if (status == MBIM_STATUS_ERROR_NONE) return TRUE; /* Build error */ set_error_from_status (error, status); return FALSE; } libmbim-1.31.2-dev/src/libmbim-glib/mbim-message.h000066400000000000000000000541611453630424100216320ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2022 Aleksander Morgado * Copyright (C) 2022 Google, Inc. */ #ifndef _LIBMBIM_GLIB_MBIM_MESSAGE_H_ #define _LIBMBIM_GLIB_MBIM_MESSAGE_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif #include #include #include "mbim-uuid.h" #include "mbim-errors.h" G_BEGIN_DECLS /** * SECTION:mbim-message * @title: MbimMessage * @short_description: Generic MBIM message handling routines * * #MbimMessage is a generic type representing a MBIM message of any kind * (request, response, indication). **/ /** * MbimMessage: * * An opaque type representing a MBIM message. * * Since: 1.0 */ typedef struct _MbimMessage MbimMessage; GType mbim_message_get_type (void) G_GNUC_CONST; #define MBIM_TYPE_MESSAGE (mbim_message_get_type ()) /** * MbimIPv4: * @addr: 4 bytes specifying the IPv4 address. * * An IPv4 address. * * Since: 1.0 */ typedef struct _MbimIPv4 MbimIPv4; struct _MbimIPv4 { guint8 addr[4]; }; /** * MbimIPv6: * @addr: 16 bytes specifying the IPv6 address. * * An IPv6 address. * * Since: 1.0 */ typedef struct _MbimIPv6 MbimIPv6; struct _MbimIPv6 { guint8 addr[16]; }; /** * MbimMessageType: * @MBIM_MESSAGE_TYPE_INVALID: Invalid MBIM message. * @MBIM_MESSAGE_TYPE_OPEN: Initialization request. * @MBIM_MESSAGE_TYPE_CLOSE: Close request. * @MBIM_MESSAGE_TYPE_COMMAND: Command request. * @MBIM_MESSAGE_TYPE_HOST_ERROR: Host-reported error in the communication. * @MBIM_MESSAGE_TYPE_OPEN_DONE: Response to initialization request. * @MBIM_MESSAGE_TYPE_CLOSE_DONE: Response to close request. * @MBIM_MESSAGE_TYPE_COMMAND_DONE: Response to command request. * @MBIM_MESSAGE_TYPE_FUNCTION_ERROR: Function-reported error in the communication. * @MBIM_MESSAGE_TYPE_INDICATE_STATUS: Unsolicited message from the function. * * Type of MBIM messages. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_MESSAGE_TYPE_INVALID = 0x00000000, /* From Host to Function */ MBIM_MESSAGE_TYPE_OPEN = 0x00000001, MBIM_MESSAGE_TYPE_CLOSE = 0x00000002, MBIM_MESSAGE_TYPE_COMMAND = 0x00000003, MBIM_MESSAGE_TYPE_HOST_ERROR = 0x00000004, /* From Function to Host */ MBIM_MESSAGE_TYPE_OPEN_DONE = 0x80000001, MBIM_MESSAGE_TYPE_CLOSE_DONE = 0x80000002, MBIM_MESSAGE_TYPE_COMMAND_DONE = 0x80000003, MBIM_MESSAGE_TYPE_FUNCTION_ERROR = 0x80000004, MBIM_MESSAGE_TYPE_INDICATE_STATUS = 0x80000007 } MbimMessageType; /*****************************************************************************/ /* Generic message interface */ /** * mbim_message_new: * @data: contents of the message. * @data_length: length of the message. * * Create a #MbimMessage with the given contents. * * Returns: (transfer full): a newly created #MbimMessage, which should be freed with mbim_message_unref(). * * Since: 1.0 */ MbimMessage *mbim_message_new (const guint8 *data, guint32 data_length); /** * mbim_message_dup: * @self: a #MbimMessage to duplicate. * * Create a #MbimMessage with the same contents as @self. * * Returns: (transfer full): a newly created #MbimMessage, which should be freed with mbim_message_unref(). * * Since: 1.0 */ MbimMessage *mbim_message_dup (const MbimMessage *self); /** * mbim_message_ref: * @self: a #MbimMessage. * * Atomically increments the reference count of @self by one. * * Returns: (transfer full): the new reference to @self. * * Since: 1.0 */ MbimMessage *mbim_message_ref (MbimMessage *self); /** * mbim_message_unref: * @self: a #MbimMessage. * * Atomically decrements the reference count of @self by one. * If the reference count drops to 0, @self is completely disposed. * * Since: 1.0 */ void mbim_message_unref (MbimMessage *self); /** * mbim_message_get_printable: * @self: a #MbimMessage. * @line_prefix: prefix string to use in each new generated line. * @headers_only: %TRUE if only basic headers should be printed. * * Gets a printable string with the contents of the whole MBIM message. * * This method will not fail if the parsing of the message contents fails, * a fallback text with the error will be included in the generated printable * information instead. * * Returns: a newly allocated string, which should be freed with g_free(). * * Since: 1.0 */ gchar *mbim_message_get_printable (const MbimMessage *self, const gchar *line_prefix, gboolean headers_only); /** * mbim_message_get_printable_full: * @self: a #MbimMessage. * @mbimex_version_major: major version of the agreed MBIMEx support. * @mbimex_version_minor: minor version of the agreed MBIMEx support. * @line_prefix: prefix string to use in each new generated line. * @headers_only: %TRUE if only basic headers should be printed. * @error: return location for error or %NULL. * * Gets a printable string with the contents of the whole MBIM message. * * Unlike mbim_message_get_printable(), this method allows specifying the * MBIMEx version agreed between host and device, so that the correct * processing and parsing is done on messages in the newer MBIMEx versions. * * If @mbimex_version_major < 2, this method behaves exactly as * mbim_message_get_printable(). * * If the specified @mbimex_version_major is unsupported, an error will be * returned. * * This method will not fail if the parsing of the message contents fails, * a fallback text with the error will be included in the generated printable * information instead. * * Returns: a newly allocated string which should be freed with g_free(), or * #NULL if @error is set. * * Since: 1.28 */ gchar *mbim_message_get_printable_full (const MbimMessage *self, guint8 mbimex_version_major, guint8 mbimex_version_minor, const gchar *line_prefix, gboolean headers_only, GError **error); /** * mbim_message_get_raw: * @self: a #MbimMessage. * @length: (out): return location for the size of the output buffer. * @error: return location for error or %NULL. * * Gets the whole raw data buffer of the #MbimMessage. * * Returns: The raw data buffer, or #NULL if @error is set. * * Since: 1.0 */ const guint8 *mbim_message_get_raw (const MbimMessage *self, guint32 *length, GError **error); /** * mbim_message_get_message_type: * @self: a #MbimMessage. * * Gets the message type. * * Returns: a #MbimMessageType. * * Since: 1.0 */ MbimMessageType mbim_message_get_message_type (const MbimMessage *self); /** * mbim_message_get_message_length: * @self: a #MbimMessage. * * Gets the whole message length. * * Returns: the length of the message. * * Since: 1.0 */ guint32 mbim_message_get_message_length (const MbimMessage *self); /** * mbim_message_get_transaction_id: * @self: a #MbimMessage. * * Gets the transaction ID of the message. * * Returns: the transaction ID. * * Since: 1.0 */ guint32 mbim_message_get_transaction_id (const MbimMessage *self); /** * mbim_message_set_transaction_id: * @self: a #MbimMessage. * @transaction_id: the transaction id. * * Sets the transaction ID of the message. * * Since: 1.0 */ void mbim_message_set_transaction_id (MbimMessage *self, guint32 transaction_id); /** * mbim_message_validate: * @self: a #MbimMessage. * @error: return location for error or %NULL. * * Validates the contents of the headers in the MBIM message. * * This operation may be used to ensure that the message contains all bytes * it is expected to contain and that it is of a valid type. * * This operation also ensures the message is complete and not a partial * MBIM fragment. * * This operation does not validate that the specific contents of a given * message type are available, that is done by the methods retrieving those * specific contents. * * Returns: %TRUE if the message is valid, %FALSE if @error is set. * * Since: 1.28 */ gboolean mbim_message_validate (const MbimMessage *self, GError **error); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimMessage, mbim_message_unref) /*****************************************************************************/ /* 'Open' message interface */ /** * mbim_message_open_new: * @transaction_id: transaction ID. * @max_control_transfer: maximum control transfer. * * Create a new #MbimMessage of type %MBIM_MESSAGE_TYPE_OPEN with the specified * parameters. * * Returns: (transfer full): a newly created #MbimMessage. The returned value * should be freed with mbim_message_unref(). * * Since: 1.0 */ MbimMessage *mbim_message_open_new (guint32 transaction_id, guint32 max_control_transfer); /** * mbim_message_open_get_max_control_transfer: * @self: a #MbimMessage. * * Get the maximum control transfer set to be used in the #MbimMessage of type * %MBIM_MESSAGE_TYPE_OPEN. * * Returns: the maximum control transfer. * * Since: 1.0 */ guint32 mbim_message_open_get_max_control_transfer (const MbimMessage *self); /*****************************************************************************/ /* 'Open Done' message interface */ /** * mbim_message_open_done_new: * @transaction_id: transaction ID. * @error_status_code: a #MbimStatusError. * * Create a new #MbimMessage of type %MBIM_MESSAGE_TYPE_OPEN_DONE with the specified * parameters. * * Returns: (transfer full): a newly created #MbimMessage, which should be freed with mbim_message_unref(). * * Since: 1.10 */ MbimMessage *mbim_message_open_done_new (guint32 transaction_id, MbimStatusError error_status_code); /** * mbim_message_open_done_get_status_code: * @self: a #MbimMessage. * * Get status code from the %MBIM_MESSAGE_TYPE_OPEN_DONE message. * * Returns: a #MbimStatusError. * * Since: 1.0 */ MbimStatusError mbim_message_open_done_get_status_code (const MbimMessage *self); /** * mbim_message_open_done_get_result: * @self: a #MbimMessage. * @error: return location for error or %NULL. * * Gets the result of the 'Open' operation in the %MBIM_MESSAGE_TYPE_OPEN_DONE message. * * Returns: %TRUE if the operation succeeded, %FALSE if @error is set. * * Since: 1.0 */ gboolean mbim_message_open_done_get_result (const MbimMessage *self, GError **error); /*****************************************************************************/ /* 'Close' message interface */ /** * mbim_message_close_new: * @transaction_id: transaction ID. * * Create a new #MbimMessage of type %MBIM_MESSAGE_TYPE_CLOSE with the specified * parameters. * * Returns: (transfer full): a newly created #MbimMessage. The returned value * should be freed with mbim_message_unref(). * * Since: 1.0 */ MbimMessage *mbim_message_close_new (guint32 transaction_id); /*****************************************************************************/ /* 'Close Done' message interface */ /** * mbim_message_close_done_new: * @transaction_id: transaction ID. * @error_status_code: a #MbimStatusError. * * Create a new #MbimMessage of type %MBIM_MESSAGE_TYPE_CLOSE_DONE with the specified * parameters. * * Returns: (transfer full): a newly created #MbimMessage, which should be freed with mbim_message_unref(). * * Since: 1.10 */ MbimMessage *mbim_message_close_done_new (guint32 transaction_id, MbimStatusError error_status_code); /** * mbim_message_close_done_get_status_code: * @self: a #MbimMessage. * * Get status code from the %MBIM_MESSAGE_TYPE_CLOSE_DONE message. * * Returns: a #MbimStatusError. * * Since: 1.0 */ MbimStatusError mbim_message_close_done_get_status_code (const MbimMessage *self); /** * mbim_message_close_done_get_result: * @self: a #MbimMessage. * @error: return location for error or %NULL. * * Gets the result of the 'Close' operation in the %MBIM_MESSAGE_TYPE_CLOSE_DONE message. * * Returns: %TRUE if the operation succeeded, %FALSE if @error is set. * * Since: 1.0 */ gboolean mbim_message_close_done_get_result (const MbimMessage *self, GError **error); /*****************************************************************************/ /* 'Error' message interface */ /** * mbim_message_error_new: * @transaction_id: transaction ID. * @error_status_code: a #MbimProtocolError. * * Create a new #MbimMessage of type %MBIM_MESSAGE_TYPE_HOST_ERROR with the specified * parameters. * * Returns: (transfer full): a newly created #MbimMessage. The returned value * should be freed with mbim_message_unref(). * * Since: 1.0 */ MbimMessage *mbim_message_error_new (guint32 transaction_id, MbimProtocolError error_status_code); /** * mbim_message_function_error_new: * @transaction_id: transaction ID. * @error_status_code: a #MbimProtocolError. * * Create a new #MbimMessage of type %MBIM_MESSAGE_TYPE_FUNCTION_ERROR with the specified * parameters. * * Returns: (transfer full): a newly created #MbimMessage. The returned value * should be freed with mbim_message_unref(). * * Since: 1.12 */ MbimMessage *mbim_message_function_error_new (guint32 transaction_id, MbimProtocolError error_status_code); /** * mbim_message_error_get_error_status_code: * @self: a #MbimMessage. * * Get the error code in a %MBIM_MESSAGE_TYPE_HOST_ERROR or * %MBIM_MESSAGE_TYPE_FUNCTION_ERROR message. * * Returns: a #MbimProtocolError. * * Since: 1.0 */ MbimProtocolError mbim_message_error_get_error_status_code (const MbimMessage *self); /** * mbim_message_error_get_error: * @self: a #MbimMessage. * * Get the error in a %MBIM_MESSAGE_TYPE_HOST_ERROR or * %MBIM_MESSAGE_TYPE_FUNCTION_ERROR message. * * Returns: a newly allocated #GError, which should be freed with g_error_free(). * * Since: 1.0 */ GError *mbim_message_error_get_error (const MbimMessage *self); /*****************************************************************************/ /* 'Command' message interface */ /** * MbimMessageCommandType: * @MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN: Unknown type. * @MBIM_MESSAGE_COMMAND_TYPE_QUERY: Query command. * @MBIM_MESSAGE_COMMAND_TYPE_SET: Set command. * * Type of command message. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_MESSAGE_COMMAND_TYPE_UNKNOWN = -1, MBIM_MESSAGE_COMMAND_TYPE_QUERY = 0, MBIM_MESSAGE_COMMAND_TYPE_SET = 1 } MbimMessageCommandType; /** * mbim_message_command_new: * @transaction_id: transaction ID. * @service: a #MbimService. * @cid: the command ID. * @command_type: the command type. * * Create a new #MbimMessage of type %MBIM_MESSAGE_TYPE_COMMAND with the * specified parameters and an empty information buffer. * * Returns: (transfer full): a newly created #MbimMessage. The returned value * should be freed with mbim_message_unref(). * * Since: 1.0 */ MbimMessage *mbim_message_command_new (guint32 transaction_id, MbimService service, guint32 cid, MbimMessageCommandType command_type); /** * mbim_message_command_append: * @self: a #MbimMessage. * @buffer: raw buffer to append to the message. * @buffer_size: length of the data in @buffer. * * Appends the contents of @buffer to @self. * * Since: 1.0 */ void mbim_message_command_append (MbimMessage *self, const guint8 *buffer, guint32 buffer_size); /** * mbim_message_command_get_service: * @self: a #MbimMessage. * * Get the service of a %MBIM_MESSAGE_TYPE_COMMAND message. * * Returns: a #MbimService. * * Since: 1.0 */ MbimService mbim_message_command_get_service (const MbimMessage *self); /** * mbim_message_command_get_service_id: * @self: a #MbimMessage. * * Get the service UUID of a %MBIM_MESSAGE_TYPE_COMMAND message. * * Returns: a #MbimUuid. * * Since: 1.0 */ const MbimUuid *mbim_message_command_get_service_id (const MbimMessage *self); /** * mbim_message_command_get_cid: * @self: a #MbimMessage. * * Get the command id of a %MBIM_MESSAGE_TYPE_COMMAND message. * * Returns: a CID. * * Since: 1.0 */ guint32 mbim_message_command_get_cid (const MbimMessage *self); /** * mbim_message_command_get_command_type: * @self: a #MbimMessage. * * Get the command type of a %MBIM_MESSAGE_TYPE_COMMAND message. * * Returns: a #MbimMessageCommandType. * * Since: 1.0 */ MbimMessageCommandType mbim_message_command_get_command_type (const MbimMessage *self); /** * mbim_message_command_get_raw_information_buffer: * @self: a #MbimMessage. * @out_length: (out): return location for the size of the output buffer. * * Gets the information buffer of the %MBIM_MESSAGE_TYPE_COMMAND message. * * Returns: (transfer none): The raw data buffer, or #NULL if empty. * * Since: 1.0 */ const guint8 *mbim_message_command_get_raw_information_buffer (const MbimMessage *self, guint32 *out_length); /*****************************************************************************/ /* 'Command Done' message interface */ /** * mbim_message_command_done_get_service: * @self: a #MbimMessage. * * Get the service of a %MBIM_MESSAGE_TYPE_COMMAND_DONE message. * * Returns: a #MbimService. * * Since: 1.0 */ MbimService mbim_message_command_done_get_service (const MbimMessage *self); /** * mbim_message_command_done_get_service_id: * @self: a #MbimMessage. * * Get the service UUID of a %MBIM_MESSAGE_TYPE_COMMAND_DONE message. * * Returns: a #MbimUuid. * * Since: 1.0 */ const MbimUuid *mbim_message_command_done_get_service_id (const MbimMessage *self); /** * mbim_message_command_done_get_cid: * @self: a #MbimMessage. * * Get the command id of a %MBIM_MESSAGE_TYPE_COMMAND_DONE message. * * Returns: a CID. * * Since: 1.0 */ guint32 mbim_message_command_done_get_cid (const MbimMessage *self); /** * mbim_message_command_done_get_status_code: * @self: a #MbimMessage. * * Get status code from the %MBIM_MESSAGE_TYPE_COMMAND_DONE message. * * Returns: a #MbimStatusError. * * Since: 1.0 */ MbimStatusError mbim_message_command_done_get_status_code (const MbimMessage *self); /** * mbim_message_command_done_get_result: * @self: a #MbimMessage. * @error: return location for error or %NULL. * * Gets the result of the 'Command' operation in the %MBIM_MESSAGE_TYPE_COMMAND_DONE message. * * Returns: %TRUE if the operation succeeded, %FALSE if @error is set. * * Since: 1.0 */ gboolean mbim_message_command_done_get_result (const MbimMessage *self, GError **error); /** * mbim_message_command_done_get_raw_information_buffer: * @self: a #MbimMessage. * @out_length: (out): return location for the size of the output buffer. * * Gets the information buffer of the %MBIM_MESSAGE_TYPE_COMMAND_DONE message. * * Returns: (transfer none): The raw data buffer, or #NULL if empty. * * Since: 1.0 */ const guint8 *mbim_message_command_done_get_raw_information_buffer (const MbimMessage *self, guint32 *out_length); /*****************************************************************************/ /* 'Indicate Status' message interface */ /** * mbim_message_indicate_status_get_service: * @self: a #MbimMessage. * * Get the service of a %MBIM_MESSAGE_TYPE_INDICATE_STATUS message. * * Returns: a #MbimService. * * Since: 1.0 */ MbimService mbim_message_indicate_status_get_service (const MbimMessage *self); /** * mbim_message_indicate_status_get_service_id: * @self: a #MbimMessage. * * Get the service UUID of a %MBIM_MESSAGE_TYPE_INDICATE_STATUS message. * * Returns: a #MbimUuid. * * Since: 1.0 */ const MbimUuid *mbim_message_indicate_status_get_service_id (const MbimMessage *self); /** * mbim_message_indicate_status_get_cid: * @self: a #MbimMessage. * * Get the command id of a %MBIM_MESSAGE_TYPE_INDICATE_STATUS message. * * Returns: a CID. * * Since: 1.0 */ guint32 mbim_message_indicate_status_get_cid (const MbimMessage *self); /** * mbim_message_indicate_status_get_raw_information_buffer: * @self: a #MbimMessage. * @out_length: (out): return location for the size of the output buffer. * * Gets the information buffer of the %MBIM_MESSAGE_TYPE_INDICATE_STATUS message. * * Returns: (transfer none): The raw data buffer, or #NULL if empty. * * Since: 1.0 */ const guint8 *mbim_message_indicate_status_get_raw_information_buffer (const MbimMessage *self, guint32 *out_length); /*****************************************************************************/ /* Other helpers */ /** * mbim_message_response_get_result: * @self: a #MbimMessage response message. * @expected: expected #MbimMessageType if there isn't any error in the operation. * @error: return location for error or %NULL. * * Gets the result of the operation from the response message, which * can be either a %MBIM_MESSAGE_TYPE_FUNCTION_ERROR message or a message of the * specified @expected type. * * Returns: %TRUE if the operation succeeded, %FALSE if @error is set. * * Since: 1.12 */ gboolean mbim_message_response_get_result (const MbimMessage *self, MbimMessageType expected, GError **error); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_MESSAGE_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-net-port-manager-wdm.c000066400000000000000000000233531453630424100241450ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2022 Daniele Palmas * * Based on previous work: * Copyright (C) 2020-2021 Eric Caruso * Copyright (C) 2020-2021 Andrew Lassalle * Copyright (C) 2021 Aleksander Morgado */ #include #include #include #include #include #include #include #include #include "mbim-device.h" #include "mbim-helpers.h" #include "mbim-error-types.h" #include "mbim-net-port-manager.h" #include "mbim-net-port-manager-wdm.h" #include "mbim-helpers-netlink.h" G_DEFINE_TYPE (MbimNetPortManagerWdm, mbim_net_port_manager_wdm, MBIM_TYPE_NET_PORT_MANAGER) /* alternative VLAN for IP session 0 if not untagged */ #define MBIM_IPS0_VID 4094 #define VLAN_DATA_TYPE "vlan" /*****************************************************************************/ static guint session_id_to_vlan_id (guint session_id) { /* VLAN ID 4094 is an alternative mapping of MBIM session 0. If you create * a subinterface with this ID then it will take over the session 0 traffic * and no packets go untagged anymore. */ return (session_id == 0 ? MBIM_IPS0_VID : session_id); } /*****************************************************************************/ static NetlinkMessage * netlink_message_new_link (guint vlan_id, gchar *ifname, guint base_if_index) { NetlinkMessage *msg; guint linkinfo_pos, datainfo_pos; struct rtattr info; msg = mbim_helpers_netlink_message_new (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL); mbim_helpers_netlink_append_attribute_uint32 (msg, IFLA_LINK, base_if_index); mbim_helpers_netlink_append_attribute_string (msg, IFLA_IFNAME, ifname); /* Store the position of the next attribute to adjust its length later. */ linkinfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg); mbim_helpers_netlink_append_attribute_nested (msg, IFLA_LINKINFO); mbim_helpers_netlink_append_attribute_string (msg, IFLA_INFO_KIND, VLAN_DATA_TYPE); /* Store the position of the next attribute to adjust its length later. */ datainfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg); mbim_helpers_netlink_append_attribute_nested (msg, IFLA_INFO_DATA); mbim_helpers_netlink_append_attribute_uint16 (msg, IFLA_VLAN_ID, vlan_id); /* Use memcpy to preserve byte alignment */ memcpy (&info, (char *) msg->data + datainfo_pos, sizeof (struct rtattr)); info.rta_len = msg->len - datainfo_pos; memcpy ((char *) msg->data + datainfo_pos, &info, sizeof (struct rtattr)); memcpy (&info, (char *) msg->data + linkinfo_pos, sizeof (struct rtattr)); info.rta_len = msg->len - linkinfo_pos; memcpy ((char *) msg->data + linkinfo_pos, &info, sizeof (struct rtattr)); return msg; } /*****************************************************************************/ static gboolean mbim_net_port_manager_wdm_list_links (MbimNetPortManager *self, const gchar *base_ifname, GPtrArray **out_links, GError **error) { g_autoptr(GFile) sysfs_file = NULL; g_autofree gchar *sysfs_path = NULL; sysfs_path = g_strdup_printf ("/sys/class/net/%s", base_ifname); sysfs_file = g_file_new_for_path (sysfs_path); return mbim_helpers_list_links_wdm (sysfs_file, NULL, NULL, out_links, error); } /*****************************************************************************/ typedef struct { guint session_id; guint vlan_id; gchar *ifname; } AddLinkContext; static void add_link_context_free (AddLinkContext *ctx) { g_free (ctx->ifname); g_free (ctx); } static gchar * mbim_net_port_manager_wdm_add_link_finish (MbimNetPortManager *self, guint *session_id, GAsyncResult *res, GError **error) { AddLinkContext *ctx; ctx = g_task_get_task_data (G_TASK (res)); if (!g_task_propagate_boolean (G_TASK (res), error)) { g_prefix_error (error, "Failed to add link with session id %d: ", ctx->session_id); return NULL; } *session_id = ctx->session_id; return g_steal_pointer (&ctx->ifname); } static void mbim_net_port_manager_wdm_add_link (MbimNetPortManager *self, guint session_id, const gchar *base_ifname, const gchar *ifname_prefix, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { NetlinkMessage *msg; NetlinkTransaction *tr; GTask *task; GError *error = NULL; gssize bytes_sent; guint base_if_index; AddLinkContext *ctx; task = g_task_new (self, cancellable, callback, user_data); ctx = g_new0 (AddLinkContext, 1); ctx->session_id = session_id; g_task_set_task_data (task, ctx, (GDestroyNotify) add_link_context_free); if (ctx->session_id == MBIM_DEVICE_SESSION_ID_AUTOMATIC) { if (!mbim_net_port_manager_util_get_first_free_session_id (ifname_prefix, &ctx->session_id)) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to find an available session ID"); g_object_unref (task); return; } g_debug ("Using dynamic session ID %u", ctx->session_id); } else g_debug ("Using static session ID %u", ctx->session_id); /* validate interface to use */ if (g_strcmp0 (mbim_net_port_manager_peek_iface (self), base_ifname) != 0) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Invalid network interface %s: expected %s", base_ifname, mbim_net_port_manager_peek_iface (self)); g_object_unref (task); return; } base_if_index = if_nametoindex (base_ifname); if (!base_if_index) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "%s interface is not available", base_ifname); g_object_unref (task); return; } ctx->ifname = mbim_net_port_manager_util_session_id_to_ifname (ifname_prefix, ctx->session_id); ctx->vlan_id = session_id_to_vlan_id (ctx->session_id); g_debug ("Using ifname '%s' and vlan id %u", ctx->ifname, ctx->vlan_id); msg = netlink_message_new_link (ctx->vlan_id, ctx->ifname, base_if_index); /* The task ownership is transferred to the transaction. */ tr = mbim_helpers_netlink_transaction_new (mbim_net_port_manager_peek_current_sequence_id (MBIM_NET_PORT_MANAGER (self)), mbim_net_port_manager_peek_transactions (MBIM_NET_PORT_MANAGER (self)), msg, timeout, task); bytes_sent = g_socket_send (mbim_net_port_manager_peek_socket (MBIM_NET_PORT_MANAGER (self)), (const gchar *) msg->data, msg->len, cancellable, &error); mbim_helpers_netlink_message_free (msg); if (bytes_sent < 0) mbim_helpers_netlink_transaction_complete_with_error (tr, mbim_net_port_manager_peek_transactions (MBIM_NET_PORT_MANAGER (self)), error); g_object_unref (task); } /*****************************************************************************/ MbimNetPortManagerWdm * mbim_net_port_manager_wdm_new (const gchar *iface, GError **error) { MbimNetPortManagerWdm *self; gint socket_fd; GSocket *gsocket; GError *inner_error = NULL; socket_fd = socket (AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (socket_fd < 0) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to create netlink socket"); return NULL; } gsocket = g_socket_new_from_fd (socket_fd, &inner_error); if (inner_error) { g_debug ("Could not create socket: %s", inner_error->message); close (socket_fd); g_propagate_error (error, inner_error); return NULL; } self = g_object_new (MBIM_TYPE_NET_PORT_MANAGER_WDM, NULL); mbim_net_port_manager_common_setup (MBIM_NET_PORT_MANAGER (self), iface, gsocket); return self; } static void mbim_net_port_manager_wdm_init (MbimNetPortManagerWdm *self) { } static void mbim_net_port_manager_wdm_class_init (MbimNetPortManagerWdmClass *klass) { MbimNetPortManagerClass *net_port_manager_class = MBIM_NET_PORT_MANAGER_CLASS (klass); net_port_manager_class->list_links = mbim_net_port_manager_wdm_list_links; net_port_manager_class->add_link = mbim_net_port_manager_wdm_add_link; net_port_manager_class->add_link_finish = mbim_net_port_manager_wdm_add_link_finish; } libmbim-1.31.2-dev/src/libmbim-glib/mbim-net-port-manager-wdm.h000066400000000000000000000037551453630424100241560ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2022 Daniele Palmas * * Based on previous work: * Copyright (C) 2020-2021 Eric Caruso * Copyright (C) 2020-2021 Andrew Lassalle * Copyright (C) 2021 Aleksander Morgado */ #ifndef _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WDM_H_ #define _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WDM_H_ #include #include #define MBIM_TYPE_NET_PORT_MANAGER_WDM (mbim_net_port_manager_wdm_get_type ()) #define MBIM_NET_PORT_MANAGER_WDM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MBIM_TYPE_NET_PORT_MANAGER_WDM, MbimNetPortManagerWdm)) #define MBIM_NET_PORT_MANAGER_WDM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MBIM_TYPE_NET_PORT_MANAGER_WDM, MbimNetPortManagerWdmClass)) #define MBIM_IS_NET_PORT_MANAGER_WDM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MBIM_TYPE_NET_PORT_MANAGER_WDM)) #define MBIM_IS_NET_PORT_MANAGER_WDM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MBIM_TYPE_NET_PORT_MANAGER_WDM)) #define MBIM_NET_PORT_MANAGER_WDM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MBIM_TYPE_NET_PORT_MANAGER_WDM, MbimNetPortManagerWdmClass)) typedef struct _MbimNetPortManagerWdm MbimNetPortManagerWdm; typedef struct _MbimNetPortManagerWdmClass MbimNetPortManagerWdmClass; struct _MbimNetPortManagerWdm { MbimNetPortManager parent; }; struct _MbimNetPortManagerWdmClass { MbimNetPortManagerClass parent; }; GType mbim_net_port_manager_wdm_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimNetPortManagerWdm, g_object_unref) MbimNetPortManagerWdm *mbim_net_port_manager_wdm_new (const gchar *iface, GError **error); #endif /* _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WDM_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-net-port-manager-wwan.c000066400000000000000000000221111453630424100243210ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2022 Daniele Palmas * * Based on previous work: * Copyright (C) 2020-2021 Eric Caruso * Copyright (C) 2020-2021 Andrew Lassalle * Copyright (C) 2021 Aleksander Morgado */ #include #include #include /* These are built-in files, not provided by the kernel headers, * used to add wwan/link symbols if not available */ #include #include #include #include #include #include #include #include "mbim-device.h" #include "mbim-helpers.h" #include "mbim-error-types.h" #include "mbim-net-port-manager.h" #include "mbim-net-port-manager-wwan.h" #include "mbim-helpers-netlink.h" G_DEFINE_TYPE (MbimNetPortManagerWwan, mbim_net_port_manager_wwan, MBIM_TYPE_NET_PORT_MANAGER) #define WWAN_DATA_TYPE "wwan" /*****************************************************************************/ static NetlinkMessage * netlink_message_new_link (guint link_id, gchar *ifname, const gchar *base_if_name) { NetlinkMessage *msg; guint linkinfo_pos, datainfo_pos; struct rtattr info; msg = mbim_helpers_netlink_message_new (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL); /* IFLA_PARENT_DEV_NAME has type NLA_NUL_STRING */ mbim_helpers_netlink_append_attribute_string_null (msg, MBIM_IFLA_PARENT_DEV_NAME, base_if_name); mbim_helpers_netlink_append_attribute_string (msg, IFLA_IFNAME, ifname); /* Store the position of the next attribute to adjust its length later. */ linkinfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg); mbim_helpers_netlink_append_attribute_nested (msg, IFLA_LINKINFO); mbim_helpers_netlink_append_attribute_string (msg, IFLA_INFO_KIND, WWAN_DATA_TYPE); /* Store the position of the next attribute to adjust its length later. */ datainfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg); mbim_helpers_netlink_append_attribute_nested (msg, IFLA_INFO_DATA); mbim_helpers_netlink_append_attribute_uint32 (msg, MBIM_IFLA_WWAN_LINK_ID, link_id); /* Use memcpy to preserve byte alignment */ memcpy (&info, (char *) msg->data + datainfo_pos, sizeof (struct rtattr)); info.rta_len = msg->len - datainfo_pos; memcpy ((char *) msg->data + datainfo_pos, &info, sizeof (struct rtattr)); memcpy (&info, (char *) msg->data + linkinfo_pos, sizeof (struct rtattr)); info.rta_len = msg->len - linkinfo_pos; memcpy ((char *) msg->data + linkinfo_pos, &info, sizeof (struct rtattr)); return msg; } /*****************************************************************************/ static gboolean mbim_net_port_manager_wwan_list_links (MbimNetPortManager *self, const gchar *base_ifname, GPtrArray **out_links, GError **error) { g_autoptr(GFile) sysfs_file = NULL; g_autofree gchar *sysfs_path = NULL; sysfs_path = g_strdup_printf ("/sys/class/net/%s/device/net", base_ifname); sysfs_file = g_file_new_for_path (sysfs_path); return mbim_helpers_list_links_wwan (base_ifname, sysfs_file, NULL, NULL, out_links, error); } /*****************************************************************************/ typedef struct { guint session_id; guint link_id; gchar *ifname; } AddLinkContext; static void add_link_context_free (AddLinkContext *ctx) { g_free (ctx->ifname); g_free (ctx); } static gchar * mbim_net_port_manager_wwan_add_link_finish (MbimNetPortManager *self, guint *session_id, GAsyncResult *res, GError **error) { AddLinkContext *ctx; ctx = g_task_get_task_data (G_TASK (res)); if (!g_task_propagate_boolean (G_TASK (res), error)) { g_prefix_error (error, "Failed to add link with session id %d: ", ctx->session_id); return NULL; } *session_id = ctx->session_id; return g_steal_pointer (&ctx->ifname); } static void mbim_net_port_manager_wwan_add_link (MbimNetPortManager *self, guint session_id, const gchar *base_ifname, const gchar *ifname_prefix, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { NetlinkMessage *msg; NetlinkTransaction *tr; GTask *task; GError *error = NULL; gssize bytes_sent; guint base_if_index; AddLinkContext *ctx; task = g_task_new (self, cancellable, callback, user_data); ctx = g_new0 (AddLinkContext, 1); ctx->session_id = session_id; g_task_set_task_data (task, ctx, (GDestroyNotify) add_link_context_free); if (ctx->session_id == MBIM_DEVICE_SESSION_ID_AUTOMATIC) { if (!mbim_net_port_manager_util_get_first_free_session_id (ifname_prefix, &ctx->session_id)) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to find an available session ID"); g_object_unref (task); return; } g_debug ("Using dynamic session ID %u", ctx->session_id); } else g_debug ("Using static session ID %u", ctx->session_id); base_if_index = if_nametoindex (base_ifname); if (!base_if_index) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "%s interface is not available", base_ifname); g_object_unref (task); return; } ctx->ifname = mbim_net_port_manager_util_session_id_to_ifname (ifname_prefix, ctx->session_id); ctx->link_id = ctx->session_id; g_debug ("Using ifname '%s' and link id %u", ctx->ifname, ctx->link_id); msg = netlink_message_new_link (ctx->link_id, ctx->ifname, base_ifname); /* The task ownership is transferred to the transaction. */ tr = mbim_helpers_netlink_transaction_new (mbim_net_port_manager_peek_current_sequence_id (MBIM_NET_PORT_MANAGER (self)), mbim_net_port_manager_peek_transactions (MBIM_NET_PORT_MANAGER (self)), msg, timeout, task); bytes_sent = g_socket_send (mbim_net_port_manager_peek_socket (MBIM_NET_PORT_MANAGER (self)), (const gchar *) msg->data, msg->len, cancellable, &error); mbim_helpers_netlink_message_free (msg); if (bytes_sent < 0) mbim_helpers_netlink_transaction_complete_with_error (tr, mbim_net_port_manager_peek_transactions (MBIM_NET_PORT_MANAGER (self)), error); g_object_unref (task); } /*****************************************************************************/ MbimNetPortManagerWwan * mbim_net_port_manager_wwan_new (GError **error) { MbimNetPortManagerWwan *self; gint socket_fd; GSocket *gsocket; GError *inner_error = NULL; socket_fd = socket (AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (socket_fd < 0) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to create netlink socket"); return NULL; } gsocket = g_socket_new_from_fd (socket_fd, &inner_error); if (inner_error) { g_debug ("Could not create socket: %s", inner_error->message); close (socket_fd); g_propagate_error (error, inner_error); return NULL; } self = g_object_new (MBIM_TYPE_NET_PORT_MANAGER_WWAN, NULL); mbim_net_port_manager_common_setup (MBIM_NET_PORT_MANAGER (self), NULL, gsocket); return self; } static void mbim_net_port_manager_wwan_init (MbimNetPortManagerWwan *self) { } static void mbim_net_port_manager_wwan_class_init (MbimNetPortManagerWwanClass *klass) { MbimNetPortManagerClass *net_port_manager_class = MBIM_NET_PORT_MANAGER_CLASS (klass); net_port_manager_class->list_links = mbim_net_port_manager_wwan_list_links; net_port_manager_class->add_link = mbim_net_port_manager_wwan_add_link; net_port_manager_class->add_link_finish = mbim_net_port_manager_wwan_add_link_finish; } libmbim-1.31.2-dev/src/libmbim-glib/mbim-net-port-manager-wwan.h000066400000000000000000000036651453630424100243430ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2022 Daniele Palmas * * Based on previous work: * Copyright (C) 2020-2021 Eric Caruso * Copyright (C) 2020-2021 Andrew Lassalle * Copyright (C) 2021 Aleksander Morgado */ #ifndef _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WWAN_H_ #define _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WWAN_H_ #include #include #define MBIM_TYPE_NET_PORT_MANAGER_WWAN (mbim_net_port_manager_wwan_get_type ()) #define MBIM_NET_PORT_MANAGER_WWAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MBIM_TYPE_NET_PORT_MANAGER_WWAN, MbimNetPortManagerWwan)) #define MBIM_NET_PORT_MANAGER_WWAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MBIM_TYPE_NET_PORT_MANAGER_WWAN, MbimNetPortManagerWwanClass)) #define MBIM_IS_NET_PORT_MANAGER_WWAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MBIM_TYPE_NET_PORT_MANAGER_WWAN)) #define MBIM_IS_NET_PORT_MANAGER_WWAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MBIM_TYPE_NET_PORT_MANAGER_WWAN)) #define MBIM_NET_PORT_MANAGER_WWAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MBIM_TYPE_NET_PORT_MANAGER_WWAN, MbimNetPortManagerWwanClass)) typedef struct _MbimNetPortManagerWwan MbimNetPortManagerWwan; typedef struct _MbimNetPortManagerWwanClass MbimNetPortManagerWwanClass; struct _MbimNetPortManagerWwan { MbimNetPortManager parent; }; struct _MbimNetPortManagerWwanClass { MbimNetPortManagerClass parent; }; GType mbim_net_port_manager_wwan_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimNetPortManagerWwan, g_object_unref) MbimNetPortManagerWwan *mbim_net_port_manager_wwan_new (GError **error); #endif /* _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WWAN_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-net-port-manager.c000066400000000000000000000323331453630424100233560ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2021 Aleksander Morgado * * Based on the QmiNetPortManagerRmnet from libqmi: * Copyright (C) 2020-2021 Eric Caruso * Copyright (C) 2020-2021 Andrew Lassalle */ #include #include #include #include #include "mbim-device.h" #include "mbim-helpers.h" #include "mbim-error-types.h" #include "mbim-net-port-manager.h" #include "mbim-helpers-netlink.h" G_DEFINE_ABSTRACT_TYPE (MbimNetPortManager, mbim_net_port_manager, G_TYPE_OBJECT) struct _MbimNetPortManagerPrivate { gchar *iface; /* Netlink socket */ GSocket *socket; GSource *source; /* Netlink state */ guint current_sequence_id; GHashTable *transactions; }; /*****************************************************************************/ void mbim_net_port_manager_add_link (MbimNetPortManager *self, guint session_id, const gchar *base_ifname, const gchar *ifname_prefix, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { MBIM_NET_PORT_MANAGER_GET_CLASS (self)->add_link (self, session_id, base_ifname, ifname_prefix, timeout, cancellable, callback, user_data); } gchar * mbim_net_port_manager_add_link_finish (MbimNetPortManager *self, guint *session_id, GAsyncResult *res, GError **error) { return MBIM_NET_PORT_MANAGER_GET_CLASS (self)->add_link_finish (self, session_id, res, error); } void mbim_net_port_manager_del_link (MbimNetPortManager *self, const gchar *ifname, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { MBIM_NET_PORT_MANAGER_GET_CLASS (self)->del_link (self, ifname, timeout, cancellable, callback, user_data); } gboolean mbim_net_port_manager_del_link_finish (MbimNetPortManager *self, GAsyncResult *res, GError **error) { return MBIM_NET_PORT_MANAGER_GET_CLASS (self)->del_link_finish (self, res, error); } void mbim_net_port_manager_del_all_links (MbimNetPortManager *self, const gchar *base_ifname, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { MBIM_NET_PORT_MANAGER_GET_CLASS (self)->del_all_links (self, base_ifname, cancellable, callback, user_data); } gboolean mbim_net_port_manager_del_all_links_finish (MbimNetPortManager *self, GAsyncResult *res, GError **error) { return MBIM_NET_PORT_MANAGER_GET_CLASS (self)->del_all_links_finish (self, res, error); } gboolean mbim_net_port_manager_list_links (MbimNetPortManager *self, const gchar *base_ifname, GPtrArray **out_links, GError **error) { return MBIM_NET_PORT_MANAGER_GET_CLASS (self)->list_links (self, base_ifname, out_links, error); } /*****************************************************************************/ /* Default implementations */ static gboolean net_port_manager_del_link_finish (MbimNetPortManager *self, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static NetlinkMessage * netlink_message_del_link (guint ifindex) { NetlinkMessage *msg; g_assert (ifindex != 0); msg = mbim_helpers_netlink_message_new (RTM_DELLINK, 0); mbim_helpers_netlink_get_message_header (msg)->ifreq.ifi_index = ifindex; return msg; } static void net_port_manager_del_link (MbimNetPortManager *self, const gchar *ifname, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { guint ifindex; NetlinkMessage *msg; NetlinkTransaction *tr; GTask *task; GError *error = NULL; gssize bytes_sent; task = g_task_new (self, cancellable, callback, user_data); ifindex = if_nametoindex (ifname); if (ifindex == 0) { g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to retrieve interface index for interface %s", ifname); g_object_unref (task); return; } msg = netlink_message_del_link (ifindex); /* The task ownership is transferred to the transaction. */ tr = mbim_helpers_netlink_transaction_new (&self->priv->current_sequence_id, self->priv->transactions, msg, timeout, task); bytes_sent = g_socket_send (self->priv->socket, (const gchar *) msg->data, msg->len, cancellable, &error); mbim_helpers_netlink_message_free (msg); if (bytes_sent < 0) mbim_helpers_netlink_transaction_complete_with_error (tr, self->priv->transactions, error); g_object_unref (task); } typedef struct { GPtrArray *links; guint link_i; } DelAllLinksContext; static void del_all_links_context_free (DelAllLinksContext *ctx) { g_clear_pointer (&ctx->links, g_ptr_array_unref); g_slice_free (DelAllLinksContext, ctx); } static gboolean net_port_manager_del_all_links_finish (MbimNetPortManager *self, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void delete_next_link (GTask *task); static void port_manager_del_link_ready (MbimNetPortManager *self, GAsyncResult *res, GTask *task) { DelAllLinksContext *ctx; GError *error = NULL; ctx = g_task_get_task_data (task); if (!mbim_net_port_manager_del_link_finish (self, res, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } g_ptr_array_remove_index_fast (ctx->links, 0); delete_next_link (task); } static void delete_next_link (GTask *task) { MbimNetPortManager *self; DelAllLinksContext *ctx; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); if (!ctx->links || ctx->links->len == 0) { g_task_return_boolean (task, TRUE); g_object_unref (task); return; } mbim_net_port_manager_del_link (self, g_ptr_array_index (ctx->links, 0), 5, g_task_get_cancellable (task), (GAsyncReadyCallback) port_manager_del_link_ready, task); } static void net_port_manager_del_all_links (MbimNetPortManager *self, const gchar *base_ifname, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; DelAllLinksContext *ctx; GError *error = NULL; task = g_task_new (self, cancellable, callback, user_data); ctx = g_slice_new0 (DelAllLinksContext); g_task_set_task_data (task, ctx, (GDestroyNotify)del_all_links_context_free); if (!mbim_net_port_manager_list_links (self, base_ifname, &ctx->links, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } delete_next_link (task); } /*****************************************************************************/ GHashTable * mbim_net_port_manager_peek_transactions (MbimNetPortManager *self) { return self->priv->transactions; } gchar * mbim_net_port_manager_peek_iface (MbimNetPortManager *self) { return self->priv->iface; } guint * mbim_net_port_manager_peek_current_sequence_id (MbimNetPortManager *self) { return &self->priv->current_sequence_id; } GSocket * mbim_net_port_manager_peek_socket (MbimNetPortManager *self) { return self->priv->socket; } void mbim_net_port_manager_common_setup (MbimNetPortManager *self, const gchar *iface, GSocket *gsocket) { self->priv->iface = g_strdup (iface); self->priv->socket = gsocket; self->priv->current_sequence_id = 0; self->priv->transactions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) mbim_helpers_netlink_transaction_free); mbim_helpers_netlink_set_callback (&self->priv->source, self->priv->socket, self->priv->transactions); } gchar * mbim_net_port_manager_util_session_id_to_ifname (const gchar *ifname_prefix, guint session_id) { /* Link names are in the form . */ return g_strdup_printf ("%s%u", ifname_prefix, session_id); } gboolean mbim_net_port_manager_util_get_first_free_session_id (const gchar *ifname_prefix, guint *session_id) { guint i; /* The minimum session id is really 0 (MBIM_DEVICE_SESSION_ID_MIN), but * when we have to automatically allocate a new session id we'll start at * 1, because 0 is also used by the non-muxed setup. */ for (i = 1; i <= MBIM_DEVICE_SESSION_ID_MAX; i++) { g_autofree gchar *ifname = NULL; ifname = mbim_net_port_manager_util_session_id_to_ifname (ifname_prefix, i); if (!if_nametoindex (ifname)) { *session_id = i; return TRUE; } } return FALSE; } /*****************************************************************************/ static void mbim_net_port_manager_init (MbimNetPortManager *self) { /* Initialize private data */ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MBIM_TYPE_NET_PORT_MANAGER, MbimNetPortManagerPrivate); } static void finalize (GObject *object) { MbimNetPortManager *self = MBIM_NET_PORT_MANAGER (object); g_assert (g_hash_table_size (self->priv->transactions) == 0); g_hash_table_unref (self->priv->transactions); g_free (self->priv->iface); G_OBJECT_CLASS (mbim_net_port_manager_parent_class)->finalize (object); } static void mbim_net_port_manager_class_init (MbimNetPortManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (MbimNetPortManagerPrivate)); object_class->finalize = finalize; klass->del_link = net_port_manager_del_link; klass->del_link_finish = net_port_manager_del_link_finish; klass->del_all_links = net_port_manager_del_all_links; klass->del_all_links_finish = net_port_manager_del_all_links_finish; } libmbim-1.31.2-dev/src/libmbim-glib/mbim-net-port-manager.h000066400000000000000000000165761453630424100233760ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2021 Aleksander Morgado * * Based on the QmiNetPortManagerRmnet from libqmi: * Copyright (C) 2020-2021 Eric Caruso * Copyright (C) 2020-2021 Andrew Lassalle */ #ifndef _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_H_ #define _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_H_ #include #include #define MBIM_TYPE_NET_PORT_MANAGER (mbim_net_port_manager_get_type ()) #define MBIM_NET_PORT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MBIM_TYPE_NET_PORT_MANAGER, MbimNetPortManager)) #define MBIM_NET_PORT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MBIM_TYPE_NET_PORT_MANAGER, MbimNetPortManagerClass)) #define MBIM_IS_NET_PORT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MBIM_TYPE_NET_PORT_MANAGER)) #define MBIM_IS_NET_PORT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MBIM_TYPE_NET_PORT_MANAGER)) #define MBIM_NET_PORT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MBIM_TYPE_NET_PORT_MANAGER, MbimNetPortManagerClass)) typedef struct _MbimNetPortManager MbimNetPortManager; typedef struct _MbimNetPortManagerClass MbimNetPortManagerClass; typedef struct _MbimNetPortManagerPrivate MbimNetPortManagerPrivate; struct _MbimNetPortManager { GObject parent; MbimNetPortManagerPrivate *priv; }; struct _MbimNetPortManagerClass { GObjectClass parent; gboolean (* list_links) (MbimNetPortManager *self, const gchar *base_ifname, GPtrArray **out_links, GError **error); void (* add_link) (MbimNetPortManager *self, guint session_id, const gchar *base_ifname, const gchar *ifname_prefix, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gchar * (* add_link_finish) (MbimNetPortManager *self, guint *session_id, GAsyncResult *res, GError **error); void (* del_link) (MbimNetPortManager *self, const gchar *ifname, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean (* del_link_finish) (MbimNetPortManager *self, GAsyncResult *res, GError **error); void (* del_all_links) (MbimNetPortManager *self, const gchar *base_ifname, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean (* del_all_links_finish) (MbimNetPortManager *self, GAsyncResult *res, GError **error); }; GType mbim_net_port_manager_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimNetPortManager, g_object_unref) gboolean mbim_net_port_manager_list_links (MbimNetPortManager *self, const gchar *base_ifname, GPtrArray **out_links, GError **error); void mbim_net_port_manager_add_link (MbimNetPortManager *self, guint session_id, const gchar *base_ifname, const gchar *ifname_prefix, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gchar *mbim_net_port_manager_add_link_finish (MbimNetPortManager *self, guint *session_id, GAsyncResult *res, GError **error); void mbim_net_port_manager_del_link (MbimNetPortManager *self, const gchar *ifname, guint timeout, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean mbim_net_port_manager_del_link_finish (MbimNetPortManager *self, GAsyncResult *res, GError **error); void mbim_net_port_manager_del_all_links (MbimNetPortManager *self, const gchar *base_ifname, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean mbim_net_port_manager_del_all_links_finish (MbimNetPortManager *self, GAsyncResult *res, GError **error); GHashTable *mbim_net_port_manager_peek_transactions (MbimNetPortManager *self); gchar *mbim_net_port_manager_peek_iface (MbimNetPortManager *self); guint *mbim_net_port_manager_peek_current_sequence_id (MbimNetPortManager *self); GSocket *mbim_net_port_manager_peek_socket (MbimNetPortManager *self); void mbim_net_port_manager_common_setup (MbimNetPortManager *self, const gchar *iface, GSocket *gsocket); gchar *mbim_net_port_manager_util_session_id_to_ifname (const gchar *ifname_prefix, guint session_id); gboolean mbim_net_port_manager_util_get_first_free_session_id (const gchar *ifname_prefix, guint *session_id); #endif /* _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-proxy-helpers.c000066400000000000000000000320061453630424100230140ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2014 Aleksander Morgado * Copyright (C) 2014 Smith Micro Software, Inc. */ #include #include "mbim-proxy-helpers.h" #include "mbim-message-private.h" #include "mbim-message.h" #include "mbim-error-types.h" #include "mbim-cid.h" #include "mbim-uuid.h" /*****************************************************************************/ static gboolean cmp_event_entry_contents (const MbimEventEntry *in, const MbimEventEntry *out) { guint i, o; g_assert (mbim_uuid_cmp (&(in->device_service_id), &(out->device_service_id))); /* First, compare number of cids in the array */ if (in->cids_count != out->cids_count) return FALSE; if (in->cids_count == 0) g_assert (in->cids == NULL); if (out->cids_count == 0) g_assert (out->cids == NULL); for (i = 0; i < in->cids_count; i++) { for (o = 0; o < out->cids_count; o++) { if (in->cids[i] == out->cids[o]) break; } if (o == out->cids_count) return FALSE; } return TRUE; } gboolean _mbim_proxy_helper_service_subscribe_list_cmp (const MbimEventEntry * const *a, gsize a_size, const MbimEventEntry * const *b, gsize b_size) { gsize i, o; /* First, compare number of entries a the array */ if (a_size != b_size) return FALSE; /* Now compare each service one by one */ for (i = 0; i < a_size; i++) { /* Look for this same service a the other array */ for (o = 0; o < b_size; o++) { /* When service found, compare contents */ if (mbim_uuid_cmp (&(a[i]->device_service_id), &(b[o]->device_service_id))) { if (!cmp_event_entry_contents (a[i], b[o])) return FALSE; break; } } /* Service not found! */ if (!b[o]) return FALSE; } return TRUE; } /*****************************************************************************/ void _mbim_proxy_helper_service_subscribe_list_debug (const MbimEventEntry * const *list, gsize list_size) { gsize i; for (i = 0; i < list_size; i++) { const MbimEventEntry *entry = list[i]; MbimService service; gchar *str; service = mbim_uuid_to_service (&entry->device_service_id); str = mbim_uuid_get_printable (&entry->device_service_id); g_debug ("[service %u] %s (%s)", (guint)i, str, mbim_service_lookup_name (service)); g_free (str); if (entry->cids_count == 0) g_debug ("[service %u] No CIDs explicitly enabled", (guint)i); else { guint j; g_debug ("[service %u] %u CIDs enabled", (guint)i, entry->cids_count); for (j = 0; j < entry->cids_count; j++) { const gchar *cid_str; cid_str = mbim_cid_get_printable (service, entry->cids[j]); g_debug ("[service %u] [cid %u] %u (%s)", (guint)i, j, entry->cids[j], cid_str ? cid_str : "unknown"); } } } } /*****************************************************************************/ MbimEventEntry ** _mbim_proxy_helper_service_subscribe_request_parse (MbimMessage *message, gsize *out_size, GError **error) { MbimEventEntry **array = NULL; guint32 i; guint32 element_count; guint32 offset = 0; guint32 array_offset; GError *inner_error = NULL; g_assert (message != NULL); g_assert (out_size != NULL); if (mbim_message_get_message_type (message) != MBIM_MESSAGE_TYPE_COMMAND) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Message is not a request"); return FALSE; } if (!mbim_message_command_get_raw_information_buffer (message, NULL)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Message does not have information buffer"); return FALSE; } if (!_mbim_message_read_guint32 (message, offset, &element_count, error)) return NULL; if (element_count) { array = g_new0 (MbimEventEntry *, element_count + 1); offset += 4; for (i = 0; i < element_count; i++) { MbimUuid uuid; if (!_mbim_message_read_guint32 (message, offset, &array_offset, &inner_error)) break; if (!_mbim_message_read_uuid (message, array_offset, NULL, &uuid, &inner_error)) break; array[i] = g_new0 (MbimEventEntry, 1); memcpy (&(array[i]->device_service_id), &uuid, 16); array_offset += 16; if (!_mbim_message_read_guint32 (message, array_offset, &(array[i])->cids_count, &inner_error)) break; array_offset += 4; if (array[i]->cids_count && !_mbim_message_read_guint32_array (message, array[i]->cids_count, array_offset, &array[i]->cids, &inner_error)) break; offset += 8; } } if (inner_error) { mbim_event_entry_array_free (array); g_propagate_error (error, inner_error); return NULL; } *out_size = element_count; return array; } /*****************************************************************************/ MbimEventEntry ** _mbim_proxy_helper_service_subscribe_list_merge (MbimEventEntry **in, gsize in_size, MbimEventEntry **merge, gsize merge_size, gsize *out_size) { gsize m; g_assert (out_size != NULL); *out_size = in_size; if (!merge || !merge_size) return in; for (m = 0; m < merge_size; m++) { MbimEventEntry *entry = NULL; MbimService id; /* ignore all merge additions for standard services */ id = mbim_uuid_to_service (&merge[m]->device_service_id); if (id >= MBIM_SERVICE_BASIC_CONNECT && id <= MBIM_SERVICE_DSS) continue; /* look for matching uuid */ if (in && in_size) { gsize i; for (i = 0; i < in_size; i++) { if (mbim_uuid_cmp (&merge[m]->device_service_id, &in[i]->device_service_id)) { entry = in[i]; break; } } } /* matching uuid not found in merge array, add it */ if (!entry) { gsize o; /* Index of the new element to add... */ o = *out_size; /* Increase number of events in the output array */ (*out_size)++; in = g_realloc (in, sizeof (MbimEventEntry *) * (*out_size + 1)); in[o] = g_memdup (merge[m], sizeof (MbimEventEntry)); if (merge[m]->cids_count) in[o]->cids = g_memdup (merge[m]->cids, sizeof (guint32) * merge[m]->cids_count); else in[o]->cids = NULL; in[*out_size] = NULL; } else { gsize cm, co; /* matching uuid found, add cids */ if (!entry->cids_count) /* all cids already enabled for uuid */ continue; /* If we're adding all enabled cids, directly apply that */ if (merge[m]->cids_count == 0) { g_free (entry->cids); entry->cids = NULL; entry->cids_count = 0; } for (cm = 0; cm < merge[m]->cids_count; cm++) { for (co = 0; co < entry->cids_count; co++) { if (merge[m]->cids[cm] == entry->cids[co]) { break; } } if (co == entry->cids_count) { /* cid not found in merge array, add it */ entry->cids = g_realloc (entry->cids, sizeof (guint32) * (++entry->cids_count)); entry->cids[co] = merge[m]->cids[cm]; } } } } return in; } /*****************************************************************************/ MbimEventEntry ** _mbim_proxy_helper_service_subscribe_list_dup (MbimEventEntry **in, gsize in_size, gsize *out_size) { MbimEventEntry **out; guint i; g_assert (out_size != NULL); out = g_new0 (MbimEventEntry *, in_size + 1); for (i = 0; i < in_size; i++) { MbimEventEntry *entry_in; MbimEventEntry *entry_out; entry_in = in[i]; entry_out = g_new (MbimEventEntry, 1); memcpy (&entry_out->device_service_id, &entry_in->device_service_id, sizeof (MbimUuid)); entry_out->cids_count = entry_in->cids_count; entry_out->cids = g_new (guint32, entry_out->cids_count); memcpy (entry_out->cids, entry_in->cids, sizeof (guint32) * entry_out->cids_count); out[i] = entry_out; } *out_size = in_size; return out; } /*****************************************************************************/ MbimEventEntry ** _mbim_proxy_helper_service_subscribe_list_new_standard (gsize *out_size) { MbimEventEntry **out; guint i = 0; MbimEventEntry *entry; g_assert (out_size != NULL); #define STANDARD_SERVICES_LIST_SIZE 5 out = g_new0 (MbimEventEntry *, STANDARD_SERVICES_LIST_SIZE + 1); /* Basic connect service */ { static const guint32 notify_cids[] = { MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS, MBIM_CID_BASIC_CONNECT_RADIO_STATE, MBIM_CID_BASIC_CONNECT_PREFERRED_PROVIDERS, MBIM_CID_BASIC_CONNECT_REGISTER_STATE, MBIM_CID_BASIC_CONNECT_PACKET_SERVICE, MBIM_CID_BASIC_CONNECT_SIGNAL_STATE, MBIM_CID_BASIC_CONNECT_CONNECT, MBIM_CID_BASIC_CONNECT_PROVISIONED_CONTEXTS, MBIM_CID_BASIC_CONNECT_IP_CONFIGURATION, MBIM_CID_BASIC_CONNECT_EMERGENCY_MODE, MBIM_CID_BASIC_CONNECT_MULTICARRIER_PROVIDERS, }; entry = g_new (MbimEventEntry, 1); memcpy (&entry->device_service_id, mbim_uuid_from_service (MBIM_SERVICE_BASIC_CONNECT), sizeof (MbimUuid)); entry->cids_count = G_N_ELEMENTS (notify_cids); entry->cids = g_memdup (notify_cids, sizeof (guint32) * entry->cids_count); out[i++] = entry; } /* SMS service */ { static const guint32 notify_cids[] = { MBIM_CID_SMS_CONFIGURATION, MBIM_CID_SMS_READ, MBIM_CID_SMS_MESSAGE_STORE_STATUS, }; entry = g_new (MbimEventEntry, 1); memcpy (&entry->device_service_id, mbim_uuid_from_service (MBIM_SERVICE_SMS), sizeof (MbimUuid)); entry->cids_count = G_N_ELEMENTS (notify_cids); entry->cids = g_memdup (notify_cids, sizeof (guint32) * entry->cids_count); out[i++] = entry; } /* USSD service */ { static const guint32 notify_cids[] = { MBIM_CID_USSD, }; entry = g_new (MbimEventEntry, 1); memcpy (&entry->device_service_id, mbim_uuid_from_service (MBIM_SERVICE_USSD), sizeof (MbimUuid)); entry->cids_count = G_N_ELEMENTS (notify_cids); entry->cids = g_memdup (notify_cids, sizeof (guint32) * entry->cids_count); out[i++] = entry; } /* Phonebook service */ { static const guint32 notify_cids[] = { MBIM_CID_PHONEBOOK_CONFIGURATION, }; entry = g_new (MbimEventEntry, 1); memcpy (&entry->device_service_id, mbim_uuid_from_service (MBIM_SERVICE_PHONEBOOK), sizeof (MbimUuid)); entry->cids_count = G_N_ELEMENTS (notify_cids); entry->cids = g_memdup (notify_cids, sizeof (guint32) * entry->cids_count); out[i++] = entry; } /* STK service */ { static const guint32 notify_cids[] = { MBIM_CID_STK_PAC, }; entry = g_new (MbimEventEntry, 1); memcpy (&entry->device_service_id, mbim_uuid_from_service (MBIM_SERVICE_STK), sizeof (MbimUuid)); entry->cids_count = G_N_ELEMENTS (notify_cids); entry->cids = g_memdup (notify_cids, sizeof (guint32) * entry->cids_count); out[i++] = entry; } g_assert_cmpuint (i, ==, STANDARD_SERVICES_LIST_SIZE); *out_size = i; return out; } libmbim-1.31.2-dev/src/libmbim-glib/mbim-proxy-helpers.h000066400000000000000000000047511453630424100230270ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2014 Aleksander Morgado * Copyright (C) 2014 Smith Micro Software, Inc. * * This is a private non-installed header */ #ifndef _LIBMBIM_GLIB_MBIM_PROXY_HELPERS_H_ #define _LIBMBIM_GLIB_MBIM_PROXY_HELPERS_H_ #if !defined (LIBMBIM_GLIB_COMPILATION) #error "This is a private header!!" #endif #include #include "mbim-basic-connect.h" G_BEGIN_DECLS gboolean _mbim_proxy_helper_service_subscribe_list_cmp (const MbimEventEntry * const *a, gsize a_size, const MbimEventEntry * const *b, gsize b_size); void _mbim_proxy_helper_service_subscribe_list_debug (const MbimEventEntry * const *list, gsize list_size); MbimEventEntry **_mbim_proxy_helper_service_subscribe_request_parse (MbimMessage *message, gsize *out_size, GError **error); MbimEventEntry **_mbim_proxy_helper_service_subscribe_list_merge (MbimEventEntry **original, gsize original_size, MbimEventEntry **merge, gsize merge_size, gsize *out_size); MbimEventEntry **_mbim_proxy_helper_service_subscribe_list_dup (MbimEventEntry **original, gsize original_size, gsize *out_size); MbimEventEntry **_mbim_proxy_helper_service_subscribe_list_new_standard (gsize *out_size); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_PROXY_HELPERS_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-proxy.c000066400000000000000000001706431453630424100213660ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2014 Aleksander Morgado * Copyright (C) 2014 Smith Micro Software, Inc. */ #include #include #include #include #include #include #include #include #include "config.h" #include "mbim-device.h" #include "mbim-utils.h" #include "mbim-helpers.h" #include "mbim-proxy.h" #include "mbim-message-private.h" #include "mbim-cid.h" #include "mbim-enum-types.h" #include "mbim-error-types.h" #include "mbim-basic-connect.h" #include "mbim-ms-basic-connect-extensions.h" #include "mbim-proxy-helpers.h" /* The mbim-proxy may be used for bulk data transfer, such as modem * firmware upgrade, and the BUFFER_SIZE should be at least equal * to MAX_CONTROL_TRANSFER which defined in mbim-device.c, which * will bring better performance in such case. */ #define BUFFER_SIZE 4096 /* The proxy control "Version" indication reporting the last agreed * MBIMEx version, if any */ #define MBIM_DEVICE_PROXY_CONTROL_VERSION "mbim-device-proxy-control-version" G_DEFINE_TYPE (MbimProxy, mbim_proxy, G_TYPE_OBJECT) enum { PROP_0, PROP_N_CLIENTS, PROP_N_DEVICES, PROP_LAST }; static GParamSpec *properties[PROP_LAST]; struct _MbimProxyPrivate { /* Unix socket service */ GSocketService *socket_service; /* Clients */ GList *clients; /* Devices */ GList *devices; GList *opening_devices; }; static void track_device (MbimProxy *self, MbimDevice *device); static void untrack_device (MbimProxy *self, MbimDevice *device); static MbimDevice *peek_device_for_path (MbimProxy *self, const gchar *path); /*****************************************************************************/ guint mbim_proxy_get_n_clients (MbimProxy *self) { g_return_val_if_fail (MBIM_IS_PROXY (self), 0); return g_list_length (self->priv->clients); } guint mbim_proxy_get_n_devices (MbimProxy *self) { g_return_val_if_fail (MBIM_IS_PROXY (self), 0); return g_list_length (self->priv->devices); } /*****************************************************************************/ /* Client info */ typedef struct { volatile gint ref_count; gulong id; MbimProxy *self; /* not full ref */ GSocketConnection *connection; GSource *connection_readable_source; GByteArray *buffer; /* Only one proxy config allowed at a time */ gboolean config_ongoing; MbimDevice *device; guint indication_id; MbimEventEntry **mbim_event_entry_array; gsize mbim_event_entry_array_size; } Client; static gboolean connection_readable_cb (GSocket *socket, GIOCondition condition, Client *client); static void track_client (MbimProxy *self, Client *client); static void untrack_client (MbimProxy *self, Client *client); static void client_disconnect (Client *client) { g_clear_pointer (&client->mbim_event_entry_array, mbim_event_entry_array_free); client->mbim_event_entry_array_size = 0; if (client->connection_readable_source) { g_source_destroy (client->connection_readable_source); g_source_unref (client->connection_readable_source); client->connection_readable_source = 0; } if (client->connection) { g_debug ("[client %lu] connection closed", client->id); g_output_stream_close (g_io_stream_get_output_stream (G_IO_STREAM (client->connection)), NULL, NULL); g_object_unref (client->connection); client->connection = NULL; } } static void client_indication_cb (MbimDevice *device, MbimMessage *message, Client *client); static void client_set_device (Client *client, MbimDevice *device) { if (client->device) { if (g_signal_handler_is_connected (client->device, client->indication_id)) g_signal_handler_disconnect (client->device, client->indication_id); g_object_unref (client->device); } if (device) { client->device = g_object_ref (device); client->indication_id = g_signal_connect (client->device, MBIM_DEVICE_SIGNAL_INDICATE_STATUS, G_CALLBACK (client_indication_cb), client); } else { client->device = NULL; client->indication_id = 0; } } static void client_unref (Client *client) { if (g_atomic_int_dec_and_test (&client->ref_count)) { /* Ensure disconnected */ client_disconnect (client); /* Reset device */ client_set_device (client, NULL); if (client->buffer) g_byte_array_unref (client->buffer); if (client->mbim_event_entry_array) mbim_event_entry_array_free (client->mbim_event_entry_array); g_slice_free (Client, client); } } G_DEFINE_AUTOPTR_CLEANUP_FUNC (Client, client_unref) static Client * client_ref (Client *client) { g_atomic_int_inc (&client->ref_count); return client; } static gboolean client_send_message (Client *client, MbimMessage *message, GError **error) { if (!client->connection) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE, "Cannot send message: not connected"); return FALSE; } if (!g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (client->connection)), message->data, message->len, NULL, /* bytes_written */ NULL, /* cancellable */ error)) { g_prefix_error (error, "Cannot send message to client: "); return FALSE; } return TRUE; } /*****************************************************************************/ /* Track/untrack clients */ static void track_client (MbimProxy *self, Client *client) { self->priv->clients = g_list_append (self->priv->clients, client_ref (client)); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_CLIENTS]); } static void untrack_client (MbimProxy *self, Client *client) { /* Disconnect the client explicitly when untracking */ client_disconnect (client); if (g_list_find (self->priv->clients, client)) { self->priv->clients = g_list_remove (self->priv->clients, client); client_unref (client); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_CLIENTS]); } } /*****************************************************************************/ /* Client indications */ static void forward_indication (Client *client, MbimMessage *message) { g_autoptr(GError) error = NULL; if (!client_send_message (client, message, &error)) g_warning ("[client %lu] couldn't forward indication: %s", client->id, error->message); } static void client_indication_cb (MbimDevice *device, MbimMessage *message, Client *client) { MbimEventEntry *entry; guint i; /* if client doesn't have a subscribe list, we're done. */ if (!client->mbim_event_entry_array) return; /* Look for the event list associated to the service */ entry = NULL; for (i = 0; i < client->mbim_event_entry_array_size; i++) { if (mbim_uuid_cmp (mbim_message_indicate_status_get_service_id (message), &client->mbim_event_entry_array[i]->device_service_id)) { entry = client->mbim_event_entry_array[i]; break; } } /* if client didn't subscribe to anything in this service, we're done */ if (!entry) return; /* if client subscribed using the wildcard, no need to match specific cid */ if (entry->cids_count == 0) { forward_indication (client, message); return; } /* Look for the specific cid in the event list */ for (i = 0; i < entry->cids_count; i++) { if (mbim_message_indicate_status_get_cid (message) == entry->cids[i]) { /* exact match in the subscription */ forward_indication (client, message); return; } } } /*****************************************************************************/ /* Request info */ typedef struct { MbimProxy *self; Client *client; MbimMessage *message; MbimMessage *response; guint32 original_transaction_id; /* Only used in proxy config */ guint32 timeout_secs; } Request; static void request_complete_and_free (Request *request) { if (request->response) { g_autoptr(GError) error = NULL; /* Try to send response to client; if it fails, always assume we have * to close the connection */ if (!client_send_message (request->client, request->response, &error)) { g_warning ("[client %lu,0x%08x] couldn't send response back to client: %s", request->client->id, request->original_transaction_id, error->message); /* Disconnect and untrack client */ untrack_client (request->self, request->client); } mbim_message_unref (request->response); } if (request->message) mbim_message_unref (request->message); client_unref (request->client); g_object_unref (request->self); g_slice_free (Request, request); } static Request * request_new (MbimProxy *self, Client *client, MbimMessage *message) { Request *request; request = g_slice_new0 (Request); request->self = g_object_ref (self); request->client = client_ref (client); request->message = mbim_message_ref (message); request->original_transaction_id = mbim_message_get_transaction_id (message); return request; } /*****************************************************************************/ /* Internal proxy device opening operation */ static MbimEventEntry **merge_client_service_subscribe_lists (MbimProxy *self, MbimDevice *device, gsize *out_size); static void reset_client_service_subscribe_lists (MbimProxy *self, MbimDevice *device); typedef struct { MbimDevice *device; guint32 timeout_secs; } InternalDeviceOpenContext; static void internal_device_open_context_free (InternalDeviceOpenContext *ctx) { g_object_unref (ctx->device); g_slice_free (InternalDeviceOpenContext, ctx); } static gboolean internal_device_open_finish (MbimProxy *self, GAsyncResult *res, GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } typedef struct { MbimDevice *device; GList *pending; } OpeningDevice; static void opening_device_complete_and_free (OpeningDevice *info, const GError *error) { GList *l; /* Complete all pending open tasks */ for (l = info->pending; l; l = g_list_next (l)) { GTask *task = (GTask *)(l->data); if (error) g_task_return_error (task, g_error_copy (error)); else g_task_return_boolean (task, TRUE); g_object_unref (task); } g_list_free (info->pending); g_object_unref (info->device); g_slice_free (OpeningDevice, info); } static OpeningDevice * peek_opening_device_info (MbimProxy *self, MbimDevice *device) { GList *l; /* If already being opened, queue it up */ for (l = self->priv->opening_devices; l; l = g_list_next (l)) { OpeningDevice *info; info = (OpeningDevice *)(l->data); if (device == info->device) return info; } return NULL; } static void complete_opening_device (MbimProxy *self, MbimDevice *device, const GError *error) { OpeningDevice *info; info = peek_opening_device_info (self, device); if (!info) return; self->priv->opening_devices = g_list_remove (self->priv->opening_devices, info); opening_device_complete_and_free (info, error); } static void cancel_opening_device (MbimProxy *self, MbimDevice *device) { OpeningDevice *info; GError *error; info = peek_opening_device_info (self, device); if (!info) return; error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_ABORTED, "Device is gone"); complete_opening_device (self, device, error); g_error_free (error); } static void device_open_ready (MbimDevice *device, GAsyncResult *res, MbimProxy *self) { GError *error = NULL; mbim_device_open_finish (device, res, &error); /* Complete all pending open actions */ complete_opening_device (self, device, error); if (error) { /* Fully untrack the device as it wasn't correctly open */ untrack_device (self, device); g_error_free (error); } } static void internal_open (GTask *task) { MbimProxy *self; InternalDeviceOpenContext *ctx; OpeningDevice *info; self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); /* If already being opened, queue it up */ info = peek_opening_device_info (self, ctx->device); if (info) { info->pending = g_list_append (info->pending, task); return; } /* First time opening */ info = g_slice_new0 (OpeningDevice); info->device = g_object_ref (ctx->device); info->pending = g_list_append (info->pending, task); self->priv->opening_devices = g_list_prepend (self->priv->opening_devices, info); /* Note: for now, only the first timeout request is taken into account */ /* Need to open the device; and we must make sure the proxy only does this once, even * when multiple clients request it */ mbim_device_open (ctx->device, ctx->timeout_secs, NULL, (GAsyncReadyCallback)device_open_ready, g_object_ref (self)); } static void internal_device_open_caps_query_ready (MbimDevice *device, GAsyncResult *res, GTask *task) { MbimProxy *self; g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; self = g_task_get_source_object (task); response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { /* If we get a not-opened error, well, force closing right away and reopen */ if (g_error_matches (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_NOT_OPENED)) { g_debug ("[%s] device not-opened error reported, reopening", mbim_device_get_path (device)); reset_client_service_subscribe_lists (self, device); mbim_device_close_force (device, NULL); internal_open (task); return; } /* Warn other (unlikely!) errors, but keep on anyway */ g_warning ("[%s] device caps query during internal open failed: %s", mbim_device_get_path (device), error->message); } g_debug ("[%s] device caps query during internal open succeeded", mbim_device_get_path (device)); g_task_return_boolean (task, TRUE); g_object_unref (task); } static void internal_device_open (MbimProxy *self, MbimDevice *device, guint32 timeout_secs, GAsyncReadyCallback callback, gpointer user_data) { InternalDeviceOpenContext *ctx; GTask *task; task = g_task_new (self, NULL, callback, user_data); ctx = g_slice_new0 (InternalDeviceOpenContext); ctx->device = g_object_ref (device); ctx->timeout_secs = timeout_secs; g_task_set_task_data (task, ctx, (GDestroyNotify) internal_device_open_context_free); /* If the device is flagged as already open, we still want to check * whether that's totally true, and we do that with a standard command * (loading caps in this case). */ if (mbim_device_is_open (device)) { MbimMessage *message; g_debug ("[%s] checking device caps during client device open...", mbim_device_get_path (device)); message = mbim_message_device_caps_query_new (NULL); mbim_device_command (device, message, 5, NULL, (GAsyncReadyCallback)internal_device_open_caps_query_ready, task); mbim_message_unref (message); return; } internal_open (task); } /*****************************************************************************/ /* Proxy open */ static gboolean process_internal_proxy_open (MbimProxy *self, Client *client, MbimMessage *message) { Request *request; MbimStatusError status = MBIM_STATUS_ERROR_FAILURE; /* create request holder */ request = request_new (self, client, message); if (!client->device) g_warning ("[client %lu] cannot process MBIM open: device not set", client->id); else if (!mbim_device_is_open (client->device)) g_warning ("[client %lu] cannot process MBIM open: device not opened by proxy", client->id); else { g_debug ("[client %lu] connection to MBIM device '%s' established", client->id, mbim_device_get_path (client->device)); status = MBIM_STATUS_ERROR_NONE; } request->response = mbim_message_open_done_new (mbim_message_get_transaction_id (request->message), status); request_complete_and_free (request); return TRUE; } /*****************************************************************************/ /* Proxy close */ static gboolean process_internal_proxy_close (MbimProxy *self, Client *client, MbimMessage *message) { Request *request; guint32 original_transaction_id; original_transaction_id = mbim_message_get_transaction_id (message); g_debug ("[client %lu,0x%08x] requested explicit MBIM channel close", client->id, original_transaction_id); request = request_new (self, client, message); request->response = mbim_message_close_done_new (original_transaction_id, MBIM_STATUS_ERROR_NONE); request_complete_and_free (request); return TRUE; } /*****************************************************************************/ /* Proxy config */ static MbimMessage * build_proxy_control_command_done (MbimMessage *message, MbimStatusError status) { MbimMessage *response; struct command_done_message *command_done; response = (MbimMessage *) _mbim_message_allocate (MBIM_MESSAGE_TYPE_COMMAND_DONE, mbim_message_get_transaction_id (message), sizeof (struct command_done_message)); command_done = &(((struct full_message *)(response->data))->message.command_done); command_done->fragment_header.total = GUINT32_TO_LE (1); command_done->fragment_header.current = 0; memcpy (command_done->service_id, MBIM_UUID_PROXY_CONTROL, sizeof (MbimUuid)); command_done->command_id = GUINT32_TO_LE (mbim_message_command_get_cid (message)); command_done->status_code = GUINT32_TO_LE (status); command_done->buffer_length = 0; return response; } static void proxy_config_internal_device_open_ready (MbimProxy *self, GAsyncResult *res, Request *request) { g_autoptr(GError) error = NULL; MbimMessage *indication; if (!internal_device_open_finish (self, res, &error)) { g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't open MBIM device: %s", request->client->id, request->original_transaction_id, error->message); /* Untrack client and complete without response */ untrack_client (request->self, request->client); request_complete_and_free (request); return; } g_debug ("[client %lu,0x%08x] proxy configured", request->client->id, request->original_transaction_id); /* notify the client about the MBIMEx version */ indication = (MbimMessage *) g_object_get_data (G_OBJECT (request->client->device), MBIM_DEVICE_PROXY_CONTROL_VERSION); if (indication) { if (!client_send_message (request->client, indication, &error)) g_warning ("[client %lu] couldn't report MBIMEx version update: %s", request->client->id, error->message); else g_debug ("[client %lu] reported MBIMEx version update", request->client->id); } if (request->client->config_ongoing == TRUE) request->client->config_ongoing = FALSE; request->response = build_proxy_control_command_done (request->message, MBIM_STATUS_ERROR_NONE); request_complete_and_free (request); } static void device_new_ready (GObject *source, GAsyncResult *res, Request *request) { g_autoptr(GError) error = NULL; MbimDevice *existing; MbimDevice *device; device = mbim_device_new_finish (res, &error); if (!device) { g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't create MBIM device: %s", request->client->id, request->original_transaction_id, error->message); /* Untrack client and complete without response */ untrack_client (request->self, request->client); request_complete_and_free (request); return; } /* Store device in the proxy independently */ existing = peek_device_for_path (request->self, mbim_device_get_path (device)); if (existing) { /* Race condition, we created two MbimDevices for the same port, just skip ours, no big deal */ client_set_device (request->client, existing); } else { /* Keep the newly added device in the proxy */ track_device (request->self, device); /* Also keep track of the device in the client */ client_set_device (request->client, device); } g_object_unref (device); internal_device_open (request->self, request->client->device, request->timeout_secs, (GAsyncReadyCallback)proxy_config_internal_device_open_ready, request); } static gboolean process_internal_proxy_config (MbimProxy *self, Client *client, MbimMessage *message) { Request *request; MbimDevice *device; g_autofree gchar *incoming_path = NULL; g_autofree gchar *path = NULL; g_autoptr(GFile) file = NULL; g_autoptr(GError) error = NULL; /* create request holder */ request = request_new (self, client, message); g_debug ("[client %lu,0x%08x] request to configure proxy", request->client->id, request->original_transaction_id); /* Error out if there is already a proxy config ongoing */ if (client->config_ongoing) { g_warning ("[client %lu,0x%08x] cannot configure proxy: another request already ongoing", request->client->id, request->original_transaction_id); request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_BUSY); request_complete_and_free (request); return TRUE; } /* Only allow SET command */ if (mbim_message_command_get_command_type (message) != MBIM_MESSAGE_COMMAND_TYPE_SET) { g_warning ("[client %lu,0x%08x] cannot configure proxy: invalid request type", request->client->id, request->original_transaction_id); request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_INVALID_PARAMETERS); request_complete_and_free (request); return TRUE; } /* Retrieve path from request */ if (!_mbim_message_read_string (message, 0, 0, MBIM_STRING_ENCODING_UTF16, &incoming_path, NULL, &error)) { g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't read device path from request: %s", request->client->id, request->original_transaction_id, error->message); request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_INVALID_PARAMETERS); request_complete_and_free (request); return TRUE; } /* The incoming path may be a symlink. In the proxy, we always use the real path of the * device, so that clients using different symlinks for the same file don't collide with * each other. */ path = mbim_helpers_get_devpath (incoming_path, &error); if (!path) { g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't lookup real device path: %s", request->client->id, request->original_transaction_id, error->message); request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_INVALID_PARAMETERS); request_complete_and_free (request); return TRUE; } /* Only allow subsequent requests with the same path */ if (client->device) { if (g_str_equal (path, mbim_device_get_path (client->device))) { g_debug ("[client %lu,0x%08x] proxy re-configured", request->client->id, request->original_transaction_id); request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_NONE); } else { g_warning ("[client %lu,0x%08x] cannot configure proxy: different device path given", request->client->id, request->original_transaction_id); request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_FAILURE); } request_complete_and_free (request); return TRUE; } /* Read requested timeout value */ if (!_mbim_message_read_guint32 (message, 8, &request->timeout_secs, &error)) { g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't read timeout from request: %s", request->client->id, request->original_transaction_id, error->message); request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_INVALID_PARAMETERS); request_complete_and_free (request); return TRUE; } /* Check if some other client already handled the same device */ device = peek_device_for_path (self, path); if (device) { /* Keep reference and continue */ client_set_device (client, device); internal_device_open (self, device, request->timeout_secs, (GAsyncReadyCallback)proxy_config_internal_device_open_ready, request); return TRUE; } /* Flag as ongoing */ client->config_ongoing = TRUE; /* Create new MBIM device */ file = g_file_new_for_path (path); mbim_device_new (file, NULL, (GAsyncReadyCallback)device_new_ready, request); return TRUE; } /*****************************************************************************/ /* Subscriber list */ static void track_service_subscribe_list (Client *client, MbimMessage *message) { g_autoptr(GError) error = NULL; g_autoptr(MbimEventEntryArray) mbim_event_entry_array = NULL; gsize mbim_event_entry_array_size; mbim_event_entry_array = _mbim_proxy_helper_service_subscribe_request_parse (message, &mbim_event_entry_array_size, &error); if (error) { g_warning ("[client %lu] invalid subscribe request message: %s", client->id, error->message); return; } /* On each new request from the client, it should provide the FULL list of * events it's subscribed to, so we can safely recreate the whole array each * time. */ g_clear_pointer (&client->mbim_event_entry_array, mbim_event_entry_array_free); client->mbim_event_entry_array = g_steal_pointer (&mbim_event_entry_array); client->mbim_event_entry_array_size = mbim_event_entry_array_size; if (mbim_utils_get_traces_enabled ()) { g_debug ("[client %lu] service subscribe list built", client->id); _mbim_proxy_helper_service_subscribe_list_debug ((const MbimEventEntry * const *)client->mbim_event_entry_array, client->mbim_event_entry_array_size); } } static void device_service_subscribe_list_set_complete (Request *request, MbimStatusError status) { struct command_done_message *command_done; guint32 raw_len; const guint8 *raw_data; /* The raw message data to send back as response to client */ raw_data = mbim_message_command_get_raw_information_buffer (request->message, &raw_len); request->response = (MbimMessage *)_mbim_message_allocate (MBIM_MESSAGE_TYPE_COMMAND_DONE, mbim_message_get_transaction_id (request->message), sizeof (struct command_done_message) + raw_len); command_done = &(((struct full_message *)(request->response->data))->message.command_done); command_done->fragment_header.total = GUINT32_TO_LE (1); command_done->fragment_header.current = 0; memcpy (command_done->service_id, MBIM_UUID_BASIC_CONNECT, sizeof (MbimUuid)); command_done->command_id = GUINT32_TO_LE (MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBE_LIST); command_done->status_code = GUINT32_TO_LE (status); command_done->buffer_length = GUINT32_TO_LE (raw_len); memcpy (&command_done->buffer[0], raw_data, raw_len); request_complete_and_free (request); } static void device_service_subscribe_list_set_ready (MbimDevice *device, GAsyncResult *res, Request *request) { g_autoptr(MbimMessage) tmp_response = NULL; g_autoptr(GError) error = NULL; MbimStatusError error_status_code; tmp_response = mbim_device_command_finish (device, res, &error); if (!tmp_response) { /* Translate a MbimDevice wrong state error into a Not-Opened function error. */ if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE)) { g_debug ("[client %lu,0x%08x] sending request to device failed: wrong state", request->client->id, request->original_transaction_id); request->response = mbim_message_function_error_new (mbim_message_get_transaction_id (request->message), MBIM_PROTOCOL_ERROR_NOT_OPENED); request_complete_and_free (request); return; } /* Don't disconnect client, just let the request timeout in its side */ g_debug ("[client %lu,0x%08x] sending request to device failed: %s", request->client->id, request->original_transaction_id, error->message); request_complete_and_free (request); return; } g_debug ("[client %lu,0x%08x] response from device received", request->client->id, request->original_transaction_id); error_status_code = GUINT32_FROM_LE (((struct full_message *)(tmp_response->data))->message.command_done.status_code); device_service_subscribe_list_set_complete (request, error_status_code); } static gboolean process_device_service_subscribe_list (MbimProxy *self, Client *client, MbimMessage *message) { MbimEventEntry **updated; gsize updated_size = 0; Request *request; g_autoptr(MbimMessage) request_message = NULL; /* create request holder */ request = request_new (self, client, message); g_debug ("[client %lu,0x%08x] request to update service subscribe list received", request->client->id, request->original_transaction_id); /* trace the service subscribe list for the client */ track_service_subscribe_list (client, message); /* merge all service subscribe list for all clients to set on device */ updated = merge_client_service_subscribe_lists (self, client->device, &updated_size); if (!updated) { g_debug ("[client %lu,0x%08x] service subscribe list update in device not needed", request->client->id, request->original_transaction_id); device_service_subscribe_list_set_complete (request, MBIM_STATUS_ERROR_NONE); return TRUE; } /* the 'updated' array was given to us as transfer-none!!!! */ request_message = mbim_message_device_service_subscribe_list_set_new (updated_size, (const MbimEventEntry *const *)updated, NULL); mbim_message_set_transaction_id (request_message, mbim_device_get_next_transaction_id (client->device)); g_debug ("[client %lu,0x%08x] updating service subscribe list in device...", request->client->id, request->original_transaction_id); mbim_device_command (client->device, request_message, 300, NULL, (GAsyncReadyCallback)device_service_subscribe_list_set_ready, request); return TRUE; } /*****************************************************************************/ /* MBIMEx version detection */ static MbimMessage * build_proxy_control_version_notification (guint16 mbim_version, guint16 ms_mbimex_version) { MbimMessage *message; struct indicate_status_message *indicate_status; guint16 tmp; guint buffer_i = 0; gsize buffer_length = 0; buffer_length = sizeof (mbim_version) + sizeof (ms_mbimex_version); message = (MbimMessage *) _mbim_message_allocate (MBIM_MESSAGE_TYPE_INDICATE_STATUS, 0, sizeof (struct indicate_status_message) + buffer_length); indicate_status = &(((struct full_message *)(message->data))->message.indicate_status); indicate_status->fragment_header.total = GUINT32_TO_LE (1); indicate_status->fragment_header.current = 0; memcpy (indicate_status->service_id, MBIM_UUID_PROXY_CONTROL, sizeof (MbimUuid)); indicate_status->command_id = GUINT32_TO_LE (MBIM_CID_PROXY_CONTROL_VERSION); indicate_status->buffer_length = GUINT32_TO_LE (buffer_length); tmp = GUINT16_TO_LE (mbim_version); memcpy (&indicate_status->buffer[buffer_i], &tmp, sizeof (tmp)); buffer_i += sizeof (tmp); tmp = GUINT16_TO_LE (ms_mbimex_version); memcpy (&indicate_status->buffer[buffer_i], &tmp, sizeof (tmp)); buffer_i += sizeof (tmp); g_assert (buffer_i == buffer_length); return message; } static void monitor_ms_basic_connect_extensions_version_response (MbimProxy *self, MbimDevice *device, MbimMessage *response) { g_autoptr(MbimMessage) indication = NULL; guint16 mbim_version; guint16 ms_mbimex_version; guint8 ms_mbimex_version_major; guint8 ms_mbimex_version_minor; GList *l; /* monitor the MBIMEx version agreed between the clients and the device */ if (!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, NULL) || (mbim_message_command_done_get_service (response) != MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS) || (mbim_message_command_done_get_cid (response) != MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_VERSION) || !mbim_message_ms_basic_connect_extensions_v2_version_response_parse (response, &mbim_version, &ms_mbimex_version, NULL)) return; ms_mbimex_version_major = ms_mbimex_version >> 8; ms_mbimex_version_minor = ms_mbimex_version & 0xFF; g_message ("Proxy monitoring detected MBIMEx version agreed with device: %x.%02x", ms_mbimex_version_major, ms_mbimex_version_minor); mbim_device_set_ms_mbimex_version (device, ms_mbimex_version_major, ms_mbimex_version_minor, NULL); /* notify to all clients about the MBIMEx version update */ indication = build_proxy_control_version_notification (mbim_version, ms_mbimex_version); for (l = self->priv->clients; l; l = g_list_next (l)) { g_autoptr(GError) error = NULL; Client *client; client = l->data; if (client->device != device) continue; if (!client_send_message (client, indication, &error)) g_warning ("[client %lu] couldn't report MBIMEx version update to %x.%02x: %s", client->id, ms_mbimex_version_major, ms_mbimex_version_minor, error->message); else g_debug ("[client %lu] reported MBIMEx version update to %x.%02x", client->id, ms_mbimex_version_major, ms_mbimex_version_minor); } /* the indication is stored as data associated to the device, so that it can * be reused any time new clients attempt an open */ g_object_set_data_full (G_OBJECT (device), MBIM_DEVICE_PROXY_CONTROL_VERSION, mbim_message_ref (indication), (GDestroyNotify)mbim_message_unref); } /*****************************************************************************/ /* Standard command */ static void device_command_ready (MbimDevice *device, GAsyncResult *res, Request *request) { g_autoptr(GError) error = NULL; request->response = mbim_device_command_finish (device, res, &error); if (!request->response) { /* Translate a MbimDevice wrong state error into a Not-Opened function error. */ if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE)) { g_debug ("[client %lu,0x%08x] sending request to device failed: wrong state", request->client->id, request->original_transaction_id); request->response = mbim_message_function_error_new (request->original_transaction_id, MBIM_PROTOCOL_ERROR_NOT_OPENED); request_complete_and_free (request); return; } /* Don't disconnect client, just let the request timeout in its side */ g_debug ("[client %lu,0x%08x] sending request to device failed: %s", request->client->id, request->original_transaction_id, error->message); request_complete_and_free (request); return; } /* replace reponse transaction id with the requested transaction id */ g_debug ("[client %lu,0x%08x] response from device received", request->client->id, request->original_transaction_id); /* try to match the MBIMEx version exchange */ monitor_ms_basic_connect_extensions_version_response (request->self, device, request->response); mbim_message_set_transaction_id (request->response, request->original_transaction_id); request_complete_and_free (request); } static gboolean process_command (MbimProxy *self, Client *client, MbimMessage *message) { Request *request; const gchar *command; const gchar *command_type; const gchar *service; command = mbim_cid_get_printable (mbim_message_command_get_service (message), mbim_message_command_get_cid (message)); command_type = mbim_message_command_type_get_string (mbim_message_command_get_command_type (message)); service = mbim_service_get_string (mbim_message_command_get_service (message)); /* create request holder */ request = request_new (self, client, message); g_debug ("[client %lu,0x%08x] forwarding request to device: %s, %s, %s", client->id, request->original_transaction_id, service ? service : "unknown service", command_type ? command_type : "unknown command type", command ? command : "unknown command"); if (_mbim_message_fragment_get_current (message) == _mbim_message_fragment_get_total (message) - 1) /* replace command transaction id with internal proxy transaction id to avoid collision */ mbim_message_set_transaction_id (message, mbim_device_get_next_transaction_id (client->device)); else /* avoid incrementing transaction until the last fragment is processed */ mbim_message_set_transaction_id (message, mbim_device_get_transaction_id (client->device)); /* The timeout needs to be big enough for any kind of transaction to * complete, otherwise the remote clients will lose the reply if they * configured a timeout bigger than this internal one. We should likely * make this value configurable per-client, instead of a hardcoded value. */ mbim_device_command (client->device, message, 300, NULL, (GAsyncReadyCallback)device_command_ready, request); return TRUE; } /*****************************************************************************/ static gboolean process_message (MbimProxy *self, Client *client, MbimMessage *message) { /* Filter by message type */ switch (mbim_message_get_message_type (message)) { case MBIM_MESSAGE_TYPE_OPEN: return process_internal_proxy_open (self, client, message); case MBIM_MESSAGE_TYPE_CLOSE: return process_internal_proxy_close (self, client, message); case MBIM_MESSAGE_TYPE_COMMAND: /* Proxy control message? */ if (mbim_message_command_get_service (message) == MBIM_SERVICE_PROXY_CONTROL && mbim_message_command_get_cid (message) == MBIM_CID_PROXY_CONTROL_CONFIGURATION) return process_internal_proxy_config (self, client, message); /* device service subscribe list message? */ if (mbim_message_command_get_service (message) == MBIM_SERVICE_BASIC_CONNECT && mbim_message_command_get_cid (message) == MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBE_LIST) return process_device_service_subscribe_list (self, client, message); /* Otherwise, standard command to forward */ return process_command (self, client, message); case MBIM_MESSAGE_TYPE_INVALID: case MBIM_MESSAGE_TYPE_COMMAND_DONE: case MBIM_MESSAGE_TYPE_INDICATE_STATUS: case MBIM_MESSAGE_TYPE_HOST_ERROR: case MBIM_MESSAGE_TYPE_OPEN_DONE: case MBIM_MESSAGE_TYPE_CLOSE_DONE: case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: default: g_debug ("[client %lu] invalid message: not a command", client->id); return FALSE; } g_assert_not_reached (); } static void parse_request (MbimProxy *self, Client *client) { do { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; /* Invalid message? */ if (!_mbim_message_validate_internal ((const MbimMessage *)client->buffer, TRUE, &error)) { /* No full message yet */ if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INCOMPLETE_MESSAGE)) return; /* Invalid message */ g_byte_array_remove_range (client->buffer, 0, client->buffer->len); return; } message = mbim_message_dup ((const MbimMessage *)client->buffer); g_assert (message); g_byte_array_remove_range (client->buffer, 0, mbim_message_get_message_length (message)); process_message (self, client, message); } while (client->buffer->len > 0); } static gboolean connection_readable_cb (GSocket *socket, GIOCondition condition, Client *_client) { g_autoptr(Client) client = NULL; MbimProxy *self; guint8 buffer[BUFFER_SIZE]; g_autoptr(GError) error = NULL; gssize r; /* Recover proxy pointer soon */ client = client_ref (_client); self = client->self; if (condition & G_IO_HUP || condition & G_IO_ERR) { untrack_client (self, client); return FALSE; } if (!(condition & G_IO_IN || condition & G_IO_PRI)) return TRUE; r = g_input_stream_read (g_io_stream_get_input_stream (G_IO_STREAM (client->connection)), buffer, BUFFER_SIZE, NULL, &error); if (r < 0) { g_warning ("[client %lu] error reading from istream: %s", client->id, error ? error->message : "unknown"); /* Close the device */ untrack_client (self, client); return FALSE; } if (r == 0) return TRUE; /* else, r > 0 */ if (!G_UNLIKELY (client->buffer)) client->buffer = g_byte_array_sized_new (r); g_byte_array_append (client->buffer, buffer, r); /* Try to parse input messages */ parse_request (self, client); return TRUE; } static void incoming_cb (GSocketService *service, GSocketConnection *connection, GObject *unused, MbimProxy *self) { static gulong client_id = 0; Client *client; g_autoptr(GCredentials) credentials = NULL; g_autoptr(GError) error = NULL; uid_t uid; /* Each new incoming request updates the client id, even if the request is * not accepted */ client_id++; g_debug ("[client %lu] connection open...", client_id); credentials = g_socket_get_credentials (g_socket_connection_get_socket (connection), &error); if (!credentials) { g_warning ("[client %lu] not allowed: error getting socket credentials: %s", client_id, error->message); return; } uid = g_credentials_get_unix_user (credentials, &error); if (error) { g_warning ("[client %lu] not allowed: error getting unix user id: %s", client_id, error->message); return; } if (!mbim_helpers_check_user_allowed (uid, &error)) { g_warning ("[client %lu] not allowed: %s", client_id, error->message); return; } /* Create client */ client = g_slice_new0 (Client); client->self = self; client->ref_count = 1; client->id = client_id; client->connection = g_object_ref (connection); /* By default, a new client has all the standard services enabled for indications */ client->mbim_event_entry_array = _mbim_proxy_helper_service_subscribe_list_new_standard (&client->mbim_event_entry_array_size); client->connection_readable_source = g_socket_create_source (g_socket_connection_get_socket (client->connection), G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, NULL); g_source_set_callback (client->connection_readable_source, (GSourceFunc)connection_readable_cb, client, NULL); g_source_attach (client->connection_readable_source, g_main_context_get_thread_default ()); /* Keep the client info around */ track_client (self, client); client_unref (client); } static gboolean setup_socket_service (MbimProxy *self, GError **error) { g_autoptr(GSocketAddress) socket_address = NULL; g_autoptr(GSocket) socket = NULL; socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error); if (!socket) return FALSE; /* Bind to address */ socket_address = (g_unix_socket_address_new_with_type ( MBIM_PROXY_SOCKET_PATH, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT)); if (!g_socket_bind (socket, socket_address, TRUE, error)) return FALSE; g_debug ("creating UNIX socket service..."); /* Listen */ if (!g_socket_listen (socket, error)) return FALSE; /* Create socket service */ self->priv->socket_service = g_socket_service_new (); g_signal_connect (self->priv->socket_service, "incoming", G_CALLBACK (incoming_cb), self); if (!g_socket_listener_add_socket (G_SOCKET_LISTENER (self->priv->socket_service), socket, NULL, /* don't pass an object, will take a reference */ error)) { g_prefix_error (error, "Error adding socket at '%s' to socket service: ", MBIM_PROXY_SOCKET_PATH); return FALSE; } g_debug ("starting UNIX socket service at '%s'...", MBIM_PROXY_SOCKET_PATH); g_socket_service_start (self->priv->socket_service); return TRUE; } /*****************************************************************************/ /* Device tracking */ #define DEVICE_CONTEXT_TAG "device-context-tag" static GQuark device_context_quark; typedef struct { /* Combined events array */ MbimEventEntry **mbim_event_entry_array; gsize mbim_event_entry_array_size; } DeviceContext; static void device_context_free (DeviceContext *ctx) { mbim_event_entry_array_free (ctx->mbim_event_entry_array); g_slice_free (DeviceContext, ctx); } static DeviceContext * device_context_get (MbimDevice *device) { DeviceContext *ctx; if (G_UNLIKELY (!device_context_quark)) device_context_quark = g_quark_from_static_string (DEVICE_CONTEXT_TAG); ctx = g_object_get_qdata (G_OBJECT (device), device_context_quark); if (!ctx) { ctx = g_slice_new0 (DeviceContext); ctx->mbim_event_entry_array = _mbim_proxy_helper_service_subscribe_list_new_standard (&ctx->mbim_event_entry_array_size); g_debug ("[%s] initial device subscribe list...", mbim_device_get_path (device)); _mbim_proxy_helper_service_subscribe_list_debug ((const MbimEventEntry * const *)ctx->mbim_event_entry_array, ctx->mbim_event_entry_array_size); g_object_set_qdata_full (G_OBJECT (device), device_context_quark, ctx, (GDestroyNotify)device_context_free); } return ctx; } static MbimEventEntry ** merge_client_service_subscribe_lists (MbimProxy *self, MbimDevice *device, gsize *out_size) { GList *l; g_autoptr(MbimEventEntryArray) updated = NULL; gsize updated_size = 0; DeviceContext *ctx; g_debug ("[%s] merging client service subscribe lists...", mbim_device_get_path (device)); ctx = device_context_get (device); g_assert (ctx); g_assert (out_size != NULL); /* Init default list */ updated = _mbim_proxy_helper_service_subscribe_list_new_standard (&updated_size); /* Lookup all clients with this device */ for (l = self->priv->clients; l; l = g_list_next (l)) { Client *client; client = l->data; if (!client->mbim_event_entry_array) continue; /* Add per-client list */ if (client->device == device) updated = _mbim_proxy_helper_service_subscribe_list_merge (updated, updated_size, client->mbim_event_entry_array, client->mbim_event_entry_array_size, &updated_size); } /* If lists are equal, ignore re-setting them up */ if (_mbim_proxy_helper_service_subscribe_list_cmp ( (const MbimEventEntry *const *)updated, updated_size, (const MbimEventEntry *const *)ctx->mbim_event_entry_array, ctx->mbim_event_entry_array_size)) { g_debug ("[%s] merged service subscribe list not updated", mbim_device_get_path (device)); return NULL; } /* Lists are different, update stored one */ g_clear_pointer (&ctx->mbim_event_entry_array, mbim_event_entry_array_free); ctx->mbim_event_entry_array = g_steal_pointer (&updated); ctx->mbim_event_entry_array_size = updated_size; if (mbim_utils_get_traces_enabled ()) { g_debug ("[%s] merged service subscribe list built", mbim_device_get_path (device)); _mbim_proxy_helper_service_subscribe_list_debug ((const MbimEventEntry * const *)ctx->mbim_event_entry_array, ctx->mbim_event_entry_array_size); } *out_size = ctx->mbim_event_entry_array_size; return ctx->mbim_event_entry_array; } static void reset_client_service_subscribe_lists (MbimProxy *self, MbimDevice *device) { DeviceContext *ctx; GList *l; g_debug ("[%s] reseting client service subscribe lists...", mbim_device_get_path (device)); ctx = device_context_get (device); g_assert (ctx); /* make sure that all clients of this device don't track any event registered */ for (l = self->priv->clients; l; l = g_list_next (l)) { Client *client; client = l->data; if (!client->mbim_event_entry_array) continue; if (client->device == device) { g_clear_pointer (&client->mbim_event_entry_array, mbim_event_entry_array_free); client->mbim_event_entry_array = _mbim_proxy_helper_service_subscribe_list_new_standard (&client->mbim_event_entry_array_size); } } /* And reset the device-specific merged list */ g_clear_pointer (&ctx->mbim_event_entry_array, mbim_event_entry_array_free); ctx->mbim_event_entry_array = _mbim_proxy_helper_service_subscribe_list_new_standard (&ctx->mbim_event_entry_array_size); } static void proxy_device_error_cb (MbimDevice *device, GError *error, MbimProxy *self) { if (g_error_matches (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_NOT_OPENED)) { g_debug ("[%s] reports as being closed...", mbim_device_get_path (device)); reset_client_service_subscribe_lists (self, device); mbim_device_close_force (device, NULL); } } static MbimDevice * peek_device_for_path (MbimProxy *self, const gchar *path) { GList *l; for (l = self->priv->devices; l; l = g_list_next (l)) { /* Return if found */ if (g_str_equal (mbim_device_get_path ((MbimDevice *)l->data), path)) return (MbimDevice *)l->data; } return NULL; } static void proxy_device_removed_cb (MbimDevice *device, MbimProxy *self) { untrack_device (self, device); } static void untrack_device (MbimProxy *self, MbimDevice *device) { GList *l; GList *to_remove = NULL; g_debug ("[%s] untracking device...", mbim_device_get_path (device)); if (!g_list_find (self->priv->devices, device)) return; /* Disconnect right away */ g_signal_handlers_disconnect_by_func (device, proxy_device_error_cb, self); g_signal_handlers_disconnect_by_func (device, proxy_device_removed_cb, self); /* If pending openings ongoing, complete them with error */ cancel_opening_device (self, device); /* Lookup all clients with this device */ for (l = self->priv->clients; l; l = g_list_next (l)) { if (((Client *)(l->data))->device == device) to_remove = g_list_append (to_remove, l->data); } /* Remove all these clients */ for (l = to_remove; l; l = g_list_next (l)) untrack_client (self, (Client *)(l->data)); g_list_free (to_remove); /* And finally, remove the device */ self->priv->devices = g_list_remove (self->priv->devices, device); g_object_unref (device); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_DEVICES]); } static void track_device (MbimProxy *self, MbimDevice *device) { g_signal_connect (device, MBIM_DEVICE_SIGNAL_REMOVED, G_CALLBACK (proxy_device_removed_cb), self); g_signal_connect (device, MBIM_DEVICE_SIGNAL_ERROR, G_CALLBACK (proxy_device_error_cb), self); self->priv->devices = g_list_append (self->priv->devices, g_object_ref (device)); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_DEVICES]); } /*****************************************************************************/ MbimProxy * mbim_proxy_new (GError **error) { g_autoptr(MbimProxy) self = NULL; if (!mbim_helpers_check_user_allowed (getuid(), error)) return NULL; self = g_object_new (MBIM_TYPE_PROXY, NULL); if (!setup_socket_service (self, error)) return NULL; return g_steal_pointer (&self); } static void mbim_proxy_init (MbimProxy *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MBIM_TYPE_PROXY, MbimProxyPrivate); } static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { MbimProxy *self = MBIM_PROXY (object); switch (prop_id) { case PROP_N_CLIENTS: g_value_set_uint (value, g_list_length (self->priv->clients)); break; case PROP_N_DEVICES: g_value_set_uint (value, g_list_length (self->priv->devices)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void dispose (GObject *object) { MbimProxyPrivate *priv = MBIM_PROXY (object)->priv; /* This list should always be empty when disposing */ g_assert (priv->opening_devices == NULL); if (priv->clients) { g_list_free_full (priv->clients, (GDestroyNotify) client_unref); priv->clients = NULL; } if (priv->devices) { g_list_free_full (priv->devices, g_object_unref); priv->devices = NULL; } if (priv->socket_service) { if (g_socket_service_is_active (priv->socket_service)) g_socket_service_stop (priv->socket_service); g_clear_object (&priv->socket_service); g_unlink (MBIM_PROXY_SOCKET_PATH); g_debug ("UNIX socket service at '%s' stopped", MBIM_PROXY_SOCKET_PATH); } G_OBJECT_CLASS (mbim_proxy_parent_class)->dispose (object); } static void mbim_proxy_class_init (MbimProxyClass *proxy_class) { GObjectClass *object_class = G_OBJECT_CLASS (proxy_class); g_type_class_add_private (object_class, sizeof (MbimProxyPrivate)); /* Virtual methods */ object_class->get_property = get_property; object_class->dispose = dispose; /** * MbimProxy:mbim-proxy-n-clients * * Since: 1.10 */ properties[PROP_N_CLIENTS] = g_param_spec_uint (MBIM_PROXY_N_CLIENTS, "Number of clients", "Number of clients currently connected to the proxy", 0, G_MAXUINT, 0, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_N_CLIENTS, properties[PROP_N_CLIENTS]); /** * MbimProxy:mbim-proxy-n-devices * * Since: 1.10 */ properties[PROP_N_DEVICES] = g_param_spec_uint (MBIM_PROXY_N_DEVICES, "Number of devices", "Number of devices currently managed by the proxy", 0, G_MAXUINT, 0, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_N_DEVICES, properties[PROP_N_DEVICES]); } libmbim-1.31.2-dev/src/libmbim-glib/mbim-proxy.h000066400000000000000000000064741453630424100213730ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2014 Aleksander Morgado * Copyright (C) 2014 Smith Micro Software, Inc. */ #ifndef MBIM_PROXY_H #define MBIM_PROXY_H #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif #include #include G_BEGIN_DECLS /** * SECTION:mbim-proxy * @title: MbimProxy * @short_description: MBIM proxy handling routines * * The #MbimProxy will setup an abstract socket listening on a predefined * address, and will take care of synchronizing the access to a set of shared * MBIM ports. * * Multiple #MbimDevice objects may be connected to the #MbimProxy at any given * time. The #MbimProxy acts as a stateful proxy (all remote #MbimDevice objects * will need to share the same message sequence). */ #define MBIM_TYPE_PROXY (mbim_proxy_get_type ()) #define MBIM_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MBIM_TYPE_PROXY, MbimProxy)) #define MBIM_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MBIM_TYPE_PROXY, MbimProxyClass)) #define MBIM_IS_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MBIM_TYPE_PROXY)) #define MBIM_IS_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), MBIM_TYPE_PROXY)) #define MBIM_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MBIM_TYPE_PROXY, MbimProxyClass)) typedef struct _MbimProxy MbimProxy; typedef struct _MbimProxyClass MbimProxyClass; typedef struct _MbimProxyPrivate MbimProxyPrivate; /** * MBIM_PROXY_SOCKET_PATH: * * Symbol defining the default abstract socket name where the #MbimProxy will listen. * * Since: 1.10 */ #define MBIM_PROXY_SOCKET_PATH "mbim-proxy" /** * MBIM_PROXY_N_CLIENTS: * * Symbol defining the #MbimProxy:mbim-proxy-n-clients property. * * Since: 1.10 */ #define MBIM_PROXY_N_CLIENTS "mbim-proxy-n-clients" /** * MBIM_PROXY_N_DEVICES: * * Symbol defining the #MbimProxy:mbim-proxy-n-devices property. * * Since: 1.10 */ #define MBIM_PROXY_N_DEVICES "mbim-proxy-n-devices" /** * MbimProxy: * * The #MbimProxy structure contains private data and should only be accessed * using the provided API. * * Since: 1.10 */ struct _MbimProxy { GObject parent; MbimProxyPrivate *priv; }; struct _MbimProxyClass { GObjectClass parent; }; GType mbim_proxy_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimProxy, g_object_unref) /** * mbim_proxy_new: * @error: Return location for error or %NULL. * * Creates a #MbimProxy object. * * Returns: (transfer full): a newly created #MbimProxy, or #NULL if @error is set. * * Since: 1.10 */ MbimProxy *mbim_proxy_new (GError **error); /** * mbim_proxy_get_n_clients: (skip) * @self: a #MbimProxy. * * Get the number of clients currently connected to the proxy. * * Returns: a #guint. * * Since: 1.10 */ guint mbim_proxy_get_n_clients (MbimProxy *self); /** * mbim_proxy_get_n_devices: (skip) * @self: a #MbimProxy. * * Get the number of devices currently connected to the proxy. * * Returns: a #guint. * * Since: 1.10 */ guint mbim_proxy_get_n_devices (MbimProxy *self); G_END_DECLS #endif /* MBIM_PROXY_H */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-tlv-private.h000066400000000000000000000042071453630424100224570ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2021 Aleksander Morgado * Copyright (C) 2021 Intel Corporation * * This is a private non-installed header */ #ifndef _LIBMBIM_GLIB_MBIM_TLV_PRIVATE_H_ #define _LIBMBIM_GLIB_MBIM_TLV_PRIVATE_H_ #if !defined (LIBMBIM_GLIB_COMPILATION) #error "This is a private header!!" #endif #include #include "mbim-tlv.h" G_BEGIN_DECLS /*****************************************************************************/ /* The MbimTlv */ /* Defined in the same way as GByteArray */ struct _MbimTlv { /*< private >*/ guint8 *data; guint len; }; struct tlv { guint16 type; guint8 reserved; guint8 padding_length; guint32 data_length; guint8 data[]; } __attribute__((packed)); #define MBIM_TLV_HEADER(self) ((struct tlv *)(((MbimTlv *)self)->data)) #define MBIM_TLV_FIELD_TYPE(self) MBIM_TLV_HEADER (self)->type #define MBIM_TLV_FIELD_RESERVED(self) MBIM_TLV_HEADER (self)->reserved #define MBIM_TLV_FIELD_PADDING_LENGTH(self) MBIM_TLV_HEADER (self)->padding_length #define MBIM_TLV_FIELD_DATA_LENGTH(self) MBIM_TLV_HEADER (self)->data_length #define MBIM_TLV_FIELD_DATA(self) MBIM_TLV_HEADER (self)->data #define MBIM_TLV_GET_TLV_TYPE(self) (MbimTlvType) GUINT16_FROM_LE (MBIM_TLV_FIELD_TYPE (self)) #define MBIM_TLV_GET_DATA_LENGTH(self) GUINT32_FROM_LE (MBIM_TLV_FIELD_DATA_LENGTH (self)) /*****************************************************************************/ /* Print support */ gchar *_mbim_tlv_print (const MbimTlv *tlv, const gchar *line_prefix); /*****************************************************************************/ /* Parsing support */ MbimTlv *_mbim_tlv_new_from_raw (const guint8 *raw, guint32 raw_length, guint32 *bytes_read, GError **error); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_TLV_PRIVATE_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-tlv.c000066400000000000000000000400761453630424100210060ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2021 Aleksander Morgado * Copyright (C) 2021 Intel Corporation */ #include #include #include #include #include #include "mbim-tlv.h" #include "mbim-tlv-private.h" #include "mbim-error-types.h" #include "mbim-enum-types.h" #include "mbim-common.h" /*****************************************************************************/ GType mbim_tlv_get_type (void) { static gsize g_define_type_id_initialized = 0; if (g_once_init_enter (&g_define_type_id_initialized)) { GType g_define_type_id = g_boxed_type_register_static (g_intern_static_string ("MbimTlv"), (GBoxedCopyFunc) mbim_tlv_ref, (GBoxedFreeFunc) mbim_tlv_unref); g_once_init_leave (&g_define_type_id_initialized, g_define_type_id); } return g_define_type_id_initialized; } /*****************************************************************************/ gchar * _mbim_tlv_print (const MbimTlv *tlv, const gchar *line_prefix) { GString *str; MbimTlvType tlv_type; const gchar *tlv_type_str; const guint8 *tlv_data; guint32 tlv_data_size; g_autofree gchar *tlv_data_str = NULL; tlv_type = mbim_tlv_get_tlv_type (tlv); tlv_type_str = mbim_tlv_type_get_string (tlv_type); str = g_string_new (""); g_string_append_printf (str, "{\n"); g_string_append_printf (str, "%s tlv type = %s (0x%04x)\n", line_prefix, tlv_type_str ? tlv_type_str : "unknown", tlv_type); tlv_data = mbim_tlv_get_tlv_data (tlv, &tlv_data_size); tlv_data_str = mbim_common_str_hex (tlv_data, tlv_data_size, ':'); g_string_append_printf (str, "%s tlv data = %s\n", line_prefix, tlv_data_str ? tlv_data_str : ""); if (tlv_type == MBIM_TLV_TYPE_WCHAR_STR) { g_autoptr(GError) error = NULL; g_autofree gchar *tlv_data_string_str = NULL; tlv_data_string_str = mbim_tlv_string_get (tlv, &error); if (!tlv_data_string_str) tlv_data_string_str = g_strdup_printf ("*** error: %s", error->message); g_string_append_printf (str, "%s tlv string = %s\n", line_prefix, tlv_data_string_str ? tlv_data_string_str : ""); } else if (tlv_type == MBIM_TLV_TYPE_UINT16_TBL) { g_autoptr(GError) error = NULL; guint32 array_size = 0; g_autofree guint16 *array = NULL; g_autofree gchar *tlv_data_string_str = NULL; if (!mbim_tlv_guint16_array_get (tlv, &array_size, &array, &error)) tlv_data_string_str = g_strdup_printf ("*** error: %s", error->message); else { GString *aux; guint32 i; aux = g_string_new ("["); for (i = 0; i < array_size; i++) g_string_append_printf (aux, "%s%" G_GUINT16_FORMAT, (i == 0) ? "" : ",", array[i]); g_string_append (aux, "]"); tlv_data_string_str = g_string_free (aux, FALSE); } g_string_append_printf (str, "%s tlv uint16 array = %s\n", line_prefix, tlv_data_string_str ? tlv_data_string_str : ""); } g_string_append_printf (str, "%s}", line_prefix); return g_string_free (str, FALSE); } /*****************************************************************************/ MbimTlv * mbim_tlv_new (MbimTlvType tlv_type, const guint8 *tlv_data, guint32 tlv_data_length) { GByteArray *self; guint32 tlv_size; guint32 padding_size; g_return_val_if_fail (tlv_type != MBIM_TLV_TYPE_INVALID, NULL); /* Compute size of the TLV and allocate heap for it */ padding_size = (tlv_data_length % 4) ? (4 - (tlv_data_length % 4)) : 0; tlv_size = sizeof (struct tlv) + tlv_data_length + padding_size; self = g_byte_array_sized_new (tlv_size); g_byte_array_set_size (self, tlv_size); /* Set TLV header */ MBIM_TLV_FIELD_TYPE (self) = GUINT16_TO_LE (tlv_type); MBIM_TLV_FIELD_RESERVED (self) = 0; MBIM_TLV_FIELD_PADDING_LENGTH (self) = padding_size; MBIM_TLV_FIELD_DATA_LENGTH (self) = GUINT32_TO_LE (tlv_data_length); if (tlv_data && tlv_data_length) { memcpy (MBIM_TLV_FIELD_DATA (self), tlv_data, tlv_data_length); if (padding_size) memset (MBIM_TLV_FIELD_DATA (self) + tlv_data_length, 0, padding_size); } return (MbimTlv *)self; } MbimTlv * _mbim_tlv_new_from_raw (const guint8 *raw, guint32 raw_length, guint32 *bytes_read, GError **error) { guint64 tlv_size; struct tlv tlv_header; if (raw_length < sizeof (struct tlv)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Cannot read TLV header: (%u < %" G_GSIZE_FORMAT ")", raw_length, sizeof (struct tlv)); return NULL; } /* intermediate variable to ensure the data_length value is properly aligned */ memcpy (&tlv_header, raw, sizeof (struct tlv)); tlv_size = ((guint64)sizeof (struct tlv) + (guint64)GUINT32_FROM_LE (tlv_header.data_length) + (guint64)tlv_header.padding_length); if ((guint64)raw_length < tlv_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Cannot read full TLV data (%u > %" G_GUINT64_FORMAT ")", raw_length, tlv_size); return NULL; } if (tlv_size > (guint64) G_MAXUINT32) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "Unsupported TLV size (%" G_GUINT64_FORMAT " > %u)", tlv_size, G_MAXUINT32); return NULL; } *bytes_read = (guint32)tlv_size; return (MbimTlv *) g_byte_array_append (g_byte_array_sized_new (tlv_size), raw, tlv_size); } MbimTlv * mbim_tlv_dup (const MbimTlv *self) { g_return_val_if_fail (self != NULL, NULL); return mbim_tlv_new (MBIM_TLV_GET_TLV_TYPE (self), MBIM_TLV_FIELD_DATA (self), MBIM_TLV_GET_DATA_LENGTH (self)); } MbimTlv * mbim_tlv_ref (MbimTlv *self) { g_return_val_if_fail (self != NULL, NULL); return (MbimTlv *) g_byte_array_ref ((GByteArray *)self); } void mbim_tlv_unref (MbimTlv *self) { g_return_if_fail (self != NULL); g_byte_array_unref ((GByteArray *)self); } MbimTlvType mbim_tlv_get_tlv_type (const MbimTlv *self) { g_return_val_if_fail (self != NULL, MBIM_TLV_TYPE_INVALID); return MBIM_TLV_GET_TLV_TYPE (self); } const guint8 * mbim_tlv_get_tlv_data (const MbimTlv *self, guint32 *out_length) { g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (out_length != NULL, NULL); *out_length = MBIM_TLV_GET_DATA_LENGTH (self); return MBIM_TLV_FIELD_DATA (self); } const guint8 * mbim_tlv_get_raw (const MbimTlv *self, guint32 *length, GError **error) { g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (length != NULL, NULL); if (!self->data || !self->len) { g_set_error_literal (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "TLV is invalid"); return NULL; } *length = (guint32) self->len; return self->data; } /*****************************************************************************/ MbimTlv * mbim_tlv_string_new (const gchar *str, GError **error) { g_autofree gunichar2 *utf16 = NULL; guint32 utf16_bytes = 0; /* Convert the string from UTF-8 to UTF-16HE */ if (str && str[0]) { glong items_written = 0; utf16 = g_utf8_to_utf16 (str, -1, NULL, /* bytes */ &items_written, /* gunichar2 */ error); if (!utf16) return NULL; utf16_bytes = items_written * 2; /* For BE systems, convert from BE to LE */ if (G_BYTE_ORDER == G_BIG_ENDIAN) { guint i; for (i = 0; i < items_written; i++) utf16[i] = GUINT16_TO_LE (utf16[i]); } } return mbim_tlv_new (MBIM_TLV_TYPE_WCHAR_STR, (const guint8 *)utf16, utf16_bytes); } gchar * mbim_tlv_string_get (const MbimTlv *self, GError **error) { g_autofree gunichar2 *tmp = NULL; guint32 size; g_return_val_if_fail (self != NULL, NULL); if (MBIM_TLV_GET_TLV_TYPE (self) != MBIM_TLV_TYPE_WCHAR_STR) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "TLV is not a WCHAR string"); return NULL; } /* Duplicate array unconditionally to avoid alignment issues as we don't * know if the 16bit array is aligned properly or not in the TLV */ size = MBIM_TLV_GET_DATA_LENGTH (self); /* If size == 0, an empty string is returned since 0-length strings are allowed */ if (!size) return g_strdup (""); tmp = (gunichar2 *) g_memdup ((gconstpointer) MBIM_TLV_FIELD_DATA (self), size); /* For BE systems, convert from LE to BE */ if (G_BYTE_ORDER == G_BIG_ENDIAN) { guint i; for (i = 0; i < (size / 2); i++) tmp[i] = GUINT16_FROM_LE (tmp[i]); } return g_utf16_to_utf8 (tmp, size / 2, NULL, NULL, error); } /*****************************************************************************/ gboolean mbim_tlv_guint16_array_get (const MbimTlv *self, guint32 *array_size, guint16 **array, GError **error) { guint32 size; g_autofree guint16 *tmp = NULL; g_return_val_if_fail (self != NULL, FALSE); if (MBIM_TLV_GET_TLV_TYPE (self) != MBIM_TLV_TYPE_UINT16_TBL) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "TLV is not a UINT16 array"); return FALSE; } size = MBIM_TLV_GET_DATA_LENGTH (self); if (size % 2 != 0) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "Invalid TLV data length, must be multiple of 2: %u", size); return FALSE; } if (size) { tmp = (guint16 *) g_memdup ((gconstpointer) MBIM_TLV_FIELD_DATA (self), size); /* For BE systems, convert from LE to BE */ if (G_BYTE_ORDER == G_BIG_ENDIAN) { guint i; for (i = 0; i < (size / 2); i++) tmp[i] = GUINT16_FROM_LE (tmp[i]); } } if (array_size) *array_size = size / 2; if (array) *array = g_steal_pointer (&tmp); return TRUE; } /*****************************************************************************/ gboolean mbim_tlv_wake_command_get (const MbimTlv *self, const MbimUuid **service, guint32 *cid, guint32 *payload_size, guint8 **payload, GError **error) { const guint8 *tlv_data; guint32 tlv_data_size; guint32 buffer_offset; guint32 buffer_size; guint32 offset = 0; guint64 required_size; g_return_val_if_fail (self != NULL, FALSE); if (MBIM_TLV_GET_TLV_TYPE (self) != MBIM_TLV_TYPE_WAKE_COMMAND) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "TLV is not a wake command"); return FALSE; } tlv_data = mbim_tlv_get_tlv_data (self, &tlv_data_size); tlv_data_size = MBIM_TLV_GET_DATA_LENGTH (self); required_size = 28; if (tlv_data_size < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read wake command TLV (%u < %" G_GUINT64_FORMAT ")", tlv_data_size, required_size); return FALSE; } if (service) *service = (const MbimUuid *) G_STRUCT_MEMBER_P (tlv_data, offset); offset += 16; if (cid) *cid = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); offset += 4; buffer_offset = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); offset += 4; buffer_size = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); offset += 4; if (buffer_size > 0) { if (buffer_offset != required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read wake command TLV: invalid payload offset (%u)", buffer_offset); return FALSE; } required_size += buffer_size; if (tlv_data_size < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read wake command TLV payload (%u bytes) (%u < %" G_GUINT64_FORMAT ")", buffer_size, tlv_data_size, required_size); return FALSE; } } if (payload_size) *payload_size = buffer_size; if (payload) *payload = (buffer_size ? g_memdup (&tlv_data[offset], buffer_size) : NULL); return TRUE; } /*****************************************************************************/ gboolean mbim_tlv_wake_packet_get (const MbimTlv *self, guint32 *filter_id, guint32 *original_packet_size, guint32 *packet_size, guint8 **packet, GError **error) { const guint8 *tlv_data; guint32 tlv_data_size; guint32 buffer_offset; guint32 buffer_size; guint32 offset = 0; guint64 required_size; g_return_val_if_fail (self != NULL, FALSE); if (MBIM_TLV_GET_TLV_TYPE (self) != MBIM_TLV_TYPE_WAKE_PACKET) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "TLV is not a wake packet"); return FALSE; } tlv_data = mbim_tlv_get_tlv_data (self, &tlv_data_size); tlv_data_size = MBIM_TLV_GET_DATA_LENGTH (self); required_size = 16; if (tlv_data_size < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read wake packet TLV (%u < %" G_GUINT64_FORMAT ")", tlv_data_size, required_size); return FALSE; } if (filter_id) *filter_id = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); offset += 4; if (original_packet_size) *original_packet_size = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); offset += 4; buffer_offset = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); offset += 4; buffer_size = GUINT32_FROM_LE (G_STRUCT_MEMBER (guint32, tlv_data, offset)); offset += 4; if (buffer_size > 0) { if (buffer_offset != offset) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read wake packet TLV: invalid saved packet offset (%u)", buffer_offset); return FALSE; } required_size += buffer_size; if (tlv_data_size < required_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE, "cannot read wake packet TLV payload (%u bytes) (%u < %" G_GUINT64_FORMAT ")", buffer_size, tlv_data_size, required_size); return FALSE; } } if (packet_size) *packet_size = buffer_size; if (packet) *packet = (buffer_size ? g_memdup (&tlv_data[offset], buffer_size) : NULL); return TRUE; } libmbim-1.31.2-dev/src/libmbim-glib/mbim-tlv.h000066400000000000000000000245731453630424100210170ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2021 Aleksander Morgado * Copyright (C) 2021 Intel Corporation */ #ifndef _LIBMBIM_GLIB_MBIM_TLV_H_ #define _LIBMBIM_GLIB_MBIM_TLV_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif #include #include #include "mbim-uuid.h" G_BEGIN_DECLS /** * SECTION:mbim-tlv * @title: MbimTlv * @short_description: A variable-sized data structure specified in Microsoft * MBIM extension v3.0. * * The #MbimTlv structure is capable of exchanging a wide range of information * between an MBIM host and an MBIM device. * * CID payloads for requests, responses, and/or notifications may contain zero * or more unnamed and optional Information Elements (IE) encoded as #MbimTlv * fields. */ /** * MbimTlv: * * An opaque type representing a MBIM TLV. * * Since: 1.28 */ typedef struct _MbimTlv MbimTlv; GType mbim_tlv_get_type (void) G_GNUC_CONST; #define MBIM_TYPE_TLV (mbim_tlv_get_type ()) /*****************************************************************************/ /* Generic TLV interface */ /** * MbimTlvType: * @MBIM_TLV_TYPE_INVALID: Invalid TLV type. * @MBIM_TLV_TYPE_UE_POLICITES: UE policies. * @MBIM_TLV_TYPE_SINGLE_NSSAI: Single NSSAI. * @MBIM_TLV_TYPE_ALLOWED_NSSAI: Allowed NSSAI. * @MBIM_TLV_TYPE_CFG_NSSAI: Configured NSSAI. * @MBIM_TLV_TYPE_DFLT_CFG_NSSAI: Default configured NSSAI. * @MBIM_TLV_TYPE_PRECFG_DFLT_CFG_NSSAI: Preconfigured default configured NSSAI. * @MBIM_TLV_TYPE_REJ_NSSAI: Rejected NSSAI. * @MBIM_TLV_TYPE_LADN: Local Area Data Network (LADN). * @MBIM_TLV_TYPE_TAI: Tracking Area Identity (TAI). * @MBIM_TLV_TYPE_WCHAR_STR: WCHAR string. * @MBIM_TLV_TYPE_UINT16_TBL: Array of 1 or more @guint16 entries. * @MBIM_TLV_TYPE_EAP_PACKET: Extensible Authentication Protocol packet. * @MBIM_TLV_TYPE_PCO: Protocol Configuration Option (PCO). * @MBIM_TLV_TYPE_ROUTE_SELECTION_DESCRIPTORS: One or more route selection descriptors. * @MBIM_TLV_TYPE_TRAFFIC_PARAMETERS: A traffic parameters record. * @MBIM_TLV_TYPE_WAKE_COMMAND: Wake command. * @MBIM_TLV_TYPE_WAKE_PACKET: Wake packet. * * Type of the MBIM TLV. * * Since: 1.28 */ typedef enum { /*< since=1.28 >*/ MBIM_TLV_TYPE_INVALID = 0, MBIM_TLV_TYPE_UE_POLICITES = 1, MBIM_TLV_TYPE_SINGLE_NSSAI = 2, MBIM_TLV_TYPE_ALLOWED_NSSAI = 3, MBIM_TLV_TYPE_CFG_NSSAI = 4, MBIM_TLV_TYPE_DFLT_CFG_NSSAI = 5, MBIM_TLV_TYPE_PRECFG_DFLT_CFG_NSSAI = 6, MBIM_TLV_TYPE_REJ_NSSAI = 7, MBIM_TLV_TYPE_LADN = 8, MBIM_TLV_TYPE_TAI = 9, MBIM_TLV_TYPE_WCHAR_STR = 10, MBIM_TLV_TYPE_UINT16_TBL = 11, MBIM_TLV_TYPE_EAP_PACKET = 12, MBIM_TLV_TYPE_PCO = 13, MBIM_TLV_TYPE_ROUTE_SELECTION_DESCRIPTORS = 14, MBIM_TLV_TYPE_TRAFFIC_PARAMETERS = 15, MBIM_TLV_TYPE_WAKE_COMMAND = 16, MBIM_TLV_TYPE_WAKE_PACKET = 17, } MbimTlvType; /** * mbim_tlv_new: * @type: a #MbimTlvType. * @data: contents of the TLV. * @data_length: length of the message. * * Create a #MbimTlv with the given contents. * * Returns: (transfer full): a newly created #MbimTlv, which should be freed with mbim_tlv_unref(). * * Since: 1.28 */ MbimTlv *mbim_tlv_new (MbimTlvType type, const guint8 *data, guint32 data_length); /** * mbim_tlv_dup: * @self: a #MbimTlv to duplicate. * * Create a #MbimTlv with the same contents as @self. * * Returns: (transfer full): a newly created #MbimTlv, which should be freed with mbim_tlv_unref(). * * Since: 1.28 */ MbimTlv *mbim_tlv_dup (const MbimTlv *self); /** * mbim_tlv_ref: * @self: a #MbimTlv. * * Atomically increments the reference count of @self by one. * * Returns: (transfer full): the new reference to @self. * * Since: 1.28 */ MbimTlv *mbim_tlv_ref (MbimTlv *self); /** * mbim_tlv_unref: * @self: a #MbimTlv. * * Atomically decrements the reference count of @self by one. * If the reference count drops to 0, @self is completely disposed. * * Since: 1.28 */ void mbim_tlv_unref (MbimTlv *self); /** * mbim_tlv_get_raw: * @self: a #MbimTlv. * @length: (out): return location for the size of the output buffer. * @error: return location for error or %NULL. * * Gets the whole raw data buffer of the #MbimTlv. * * Returns: The raw data buffer, or #NULL if @error is set. * * Since: 1.28 */ const guint8 *mbim_tlv_get_raw (const MbimTlv *self, guint32 *length, GError **error); /** * mbim_tlv_get_tlv_type: * @self: a #MbimTlv. * * Gets the message type. * * Returns: a #MbimTlvType. * * Since: 1.28 */ MbimTlvType mbim_tlv_get_tlv_type (const MbimTlv *self); /** * mbim_tlv_get_tlv_data: * @self: a #MbimTlv. * @out_length: (out): return location for the size of the output buffer. * * Gets the TLV raw data. * * Returns: (transfer none): The raw data buffer, or #NULL if empty. * * Since: 1.28 */ const guint8 *mbim_tlv_get_tlv_data (const MbimTlv *self, guint32 *out_length); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimTlv, mbim_tlv_unref) /*****************************************************************************/ /* String TLV type helpers */ /** * mbim_tlv_string_new: * @str: a string. * @error: return location for error or %NULL. * * Create a #MbimTlv of type %MBIM_TLV_TYPE_WCHAR_STR with the given contents. * * Returns: (transfer full): a newly created #MbimTlv which should be freed with mbim_tlv_unref(), or %NULL if @error is set. * * Since: 1.28 */ MbimTlv *mbim_tlv_string_new (const gchar *str, GError **error); /** * mbim_tlv_string_get: * @self: a #MbimTlv of type %MBIM_TLV_TYPE_WCHAR_STR. * @error: return location for error or %NULL. * * Get a string with the contents in the #MbimTlv. * * Returns: (transfer full): a newly created string, which should be freed with g_free(), or %NULL if @error is set. * * Since: 1.28 */ gchar *mbim_tlv_string_get (const MbimTlv *self, GError **error); /*****************************************************************************/ /* guint16 array type helpers */ /** * mbim_tlv_guint16_array_get: * @self: a #MbimTlv of type %MBIM_TLV_TYPE_UINT16_TBL. * @array_size: (out)(optional)(transfer none): return location for a #guint32, * or %NULL if the field is not needed. * @array: (out)(optional)(transfer full)(type guint16): return location for a * newly allocated array of #guint16 values, or %NULL if the field is not * needed. Free the returned value with g_free(). * @error: return location for error or %NULL. * * Get an array of #guint16 values with the contents in the #MbimTlv. * * The method may return a successful return even with on empty arrays (i.e. * with @array_size set to 0 and @array set to %NULL). * * Returns: %TRUE if on success, %FALSE if @error is set. * * Since: 1.28 */ gboolean mbim_tlv_guint16_array_get (const MbimTlv *self, guint32 *array_size, guint16 **array, GError **error); /*****************************************************************************/ /* wake command type helpers */ /** * mbim_tlv_wake_command_get: * @self: a #MbimTlv of type %MBIM_TLV_TYPE_WAKE_COMMAND. * @service: (out)(optional)(transfer none): return location for a #MbimUuid * specifying the service that triggered the wake. * @cid: (out)(optional)(transfer none): return location for the command id that * triggered the wake. * @payload_size: (out)(optional)(transfer none): return location for a #guint32, * or %NULL if the field is not needed. * @payload: (out)(optional)(transfer full)(type guint8): return location for a * newly allocated array of #guint8 values, or %NULL if the field is not * needed. Free the returned value with g_free(). * @error: return location for error or %NULL. * * Get the contents of a wake command TLV. * * The method may return a successful return even with on empty payload (i.e. * with @payload_size set to 0 and @payload set to %NULL). * * Returns: %TRUE if on success, %FALSE if @error is set. * * Since: 1.28 */ gboolean mbim_tlv_wake_command_get (const MbimTlv *self, const MbimUuid **service, guint32 *cid, guint32 *payload_size, guint8 **payload, GError **error); /*****************************************************************************/ /* wake packet type helpers */ /** * mbim_tlv_wake_packet_get: * @self: a #MbimTlv of type %MBIM_TLV_TYPE_WAKE_PACKET. * @filter_id: (out)(optional)(transfer none): return location for a #guint32 * specifying the filter id. * @original_packet_size: (out)(optional)(transfer none): return location for a * #guint32, or %NULL if the field is not needed. * @packet_size: (out)(optional)(transfer none): return location for a #guint32, * or %NULL if the field is not needed. * @packet: (out)(optional)(transfer full)(type guint8): return location for a * newly allocated array of #guint8 values, or %NULL if the field is not * needed. Free the returned value with g_free(). * @error: return location for error or %NULL. * * Get the contents of a wake packet TLV. * * Returns: %TRUE if on success, %FALSE if @error is set. * * Since: 1.28 */ gboolean mbim_tlv_wake_packet_get (const MbimTlv *self, guint32 *filter_id, guint32 *original_packet_size, guint32 *packet_size, guint8 **packet, GError **error); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_TLV_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-utils.c000066400000000000000000000021421453630424100213310ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2019 Aleksander Morgado */ #include "mbim-utils.h" /** * SECTION:mbim-utils * @title: Common utilities * @short_description: Common utilities in the libmbim-glib library. * * This section exposes a set of common utilities that may be used to work * with the libmbim-glib library. */ static volatile gint __traces_enabled = FALSE; static volatile gint __hide_personal_info = FALSE; gboolean mbim_utils_get_traces_enabled (void) { return (gboolean) g_atomic_int_get (&__traces_enabled); } void mbim_utils_set_traces_enabled (gboolean enabled) { g_atomic_int_set (&__traces_enabled, enabled); } void mbim_utils_set_show_personal_info (gboolean hide_personal_info) { g_atomic_int_set (&__hide_personal_info, hide_personal_info); } gboolean mbim_utils_get_show_personal_info (void) { return (gboolean) g_atomic_int_get (&__hide_personal_info); } libmbim-1.31.2-dev/src/libmbim-glib/mbim-utils.h000066400000000000000000000031501453630424100213360ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado */ #ifndef _LIBMBIM_GLIB_MBIM_UTILS_H_ #define _LIBMBIM_GLIB_MBIM_UTILS_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS /* Enabling/Disabling traces */ /** * mbim_utils_get_traces_enabled: * * Checks whether MBIM message traces are currently enabled. * * Returns: %TRUE if traces are enabled, %FALSE otherwise. * * Since: 1.0 */ gboolean mbim_utils_get_traces_enabled (void); /** * mbim_utils_set_traces_enabled: * @enabled: %TRUE to enable traces, %FALSE to disable them. * * Sets whether MBIM message traces are enabled or disabled. * * Since: 1.0 */ void mbim_utils_set_traces_enabled (gboolean enabled); /** * mbim_utils_set_show_personal_info: * @show_personal_info: %TRUE to show personal info in traces, %FALSE otherwise. * * Sets whether personal info is printed when traces are enabled. * * Since: 1.28 */ void mbim_utils_set_show_personal_info (gboolean show_personal_info); /** * mbim_utils_get_show_personal_info: * * Checks whether personal info should be hidden when traces are enabled. * * Returns: %TRUE to show personal info in trace, %FALSE otherwise. * * Since: 1.28 */ gboolean mbim_utils_get_show_personal_info (void); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_UTILS_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-uuid.c000066400000000000000000000500271453630424100211440ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2014 NVDIA Corporation * Copyright (C) 2014 Smith Micro Software, Inc. * Copyright (C) 2022 Intel Corporation */ #include #include #include #include "mbim-uuid.h" #include "generated/mbim-enum-types.h" /*****************************************************************************/ gboolean mbim_uuid_cmp (const MbimUuid *a, const MbimUuid *b) { return (memcmp (a, b, sizeof (*a)) == 0); } gchar * mbim_uuid_get_printable (const MbimUuid *uuid) { return (g_strdup_printf ( "%02x%02x%02x%02x-" "%02x%02x-" "%02x%02x-" "%02x%02x-" "%02x%02x%02x%02x%02x%02x", uuid->a[0], uuid->a[1], uuid->a[2], uuid->a[3], uuid->b[0], uuid->b[1], uuid->c[0], uuid->c[1], uuid->d[0], uuid->d[1], uuid->e[0], uuid->e[1], uuid->e[2], uuid->e[3], uuid->e[4], uuid->e[5])); } gboolean mbim_uuid_from_printable (const gchar *str, MbimUuid *uuid) { guint8 tmp[16]; guint i; guint k; gint d0; gint d1; g_return_val_if_fail (str != NULL, FALSE); g_return_val_if_fail (uuid != NULL, FALSE); if (strlen (str) != 36) return FALSE; for (i = 0, k = 0, d0 = -1, d1 = -1; str[i]; i++) { /* Accept dashes in expected positions */ if (str[i] == '-') { if (i == 8 || i == 13 || i == 18 || i == 23) continue; return FALSE; } /* Read first digit in the hex pair */ else if (d0 == -1) { d0 = g_ascii_xdigit_value (str[i]); if (d0 == -1) return FALSE; } /* Read second digit in the hex pair */ else { d1 = g_ascii_xdigit_value (str[i]); if (d1 == -1) return FALSE; tmp[k++] = (d0 << 4) | d1; d0 = d1 = -1; } } memcpy (uuid, tmp, sizeof (tmp)); return TRUE; } /*****************************************************************************/ static const MbimUuid uuid_invalid = { .a = { 0x00, 0x00, 0x00, 0x00 }, .b = { 0x00, 0x00 }, .c = { 0x00, 0x00 }, .d = { 0x00, 0x00 }, .e = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static const MbimUuid uuid_basic_connect = { .a = { 0xa2, 0x89, 0xcc, 0x33 }, .b = { 0xbc, 0xbb }, .c = { 0x8b, 0x4f }, .d = { 0xb6, 0xb0 }, .e = { 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf } }; static const MbimUuid uuid_sms = { .a = { 0x53, 0x3f, 0xbe, 0xeb }, .b = { 0x14, 0xfe }, .c = { 0x44, 0x67 }, .d = { 0x9f, 0x90 }, .e = { 0x33, 0xa2, 0x23, 0xe5, 0x6c, 0x3f } }; static const MbimUuid uuid_ussd = { .a = { 0xe5, 0x50, 0xa0, 0xc8 }, .b = { 0x5e, 0x82 }, .c = { 0x47, 0x9e }, .d = { 0x82, 0xf7 }, .e = { 0x10, 0xab, 0xf4, 0xc3, 0x35, 0x1f } }; static const MbimUuid uuid_phonebook = { .a = { 0x4b, 0xf3, 0x84, 0x76 }, .b = { 0x1e, 0x6a }, .c = { 0x41, 0xdb }, .d = { 0xb1, 0xd8 }, .e = { 0xbe, 0xd2, 0x89, 0xc2, 0x5b, 0xdb } }; static const MbimUuid uuid_stk = { .a = { 0xd8, 0xf2, 0x01, 0x31 }, .b = { 0xfc, 0xb5 }, .c = { 0x4e, 0x17 }, .d = { 0x86, 0x02 }, .e = { 0xd6, 0xed, 0x38, 0x16, 0x16, 0x4c } }; static const MbimUuid uuid_auth = { .a = { 0x1d, 0x2b, 0x5f, 0xf7 }, .b = { 0x0a, 0xa1 }, .c = { 0x48, 0xb2 }, .d = { 0xaa, 0x52 }, .e = { 0x50, 0xf1, 0x57, 0x67, 0x17, 0x4e } }; static const MbimUuid uuid_dss = { .a = { 0xc0, 0x8a, 0x26, 0xdd }, .b = { 0x77, 0x18 }, .c = { 0x43, 0x82 }, .d = { 0x84, 0x82 }, .e = { 0x6e, 0x0d, 0x58, 0x3c, 0x4d, 0x0e } }; static const MbimUuid uuid_ms_firmware_id = { .a = { 0xe9, 0xf7, 0xde, 0xa2 }, .b = { 0xfe, 0xaf }, .c = { 0x40, 0x09 }, .d = { 0x93, 0xce }, .e = { 0x90, 0xa3, 0x69, 0x41, 0x03, 0xb6 } }; static const MbimUuid uuid_ms_host_shutdown = { .a = { 0x88, 0x3b, 0x7c, 0x26 }, .b = { 0x98, 0x5f }, .c = { 0x43, 0xfa }, .d = { 0x98, 0x04 }, .e = { 0x27, 0xd7, 0xfb, 0x80, 0x95, 0x9c } }; static const MbimUuid uuid_ms_sar = { .a = { 0x68, 0x22, 0x3d, 0x04 }, .b = { 0x9f, 0x6c }, .c = { 0x4e, 0x0f }, .d = { 0x82, 0x2d }, .e = { 0x28, 0x44, 0x1f, 0xb7, 0x23, 0x40 } }; static const MbimUuid uuid_proxy_control = { .a = { 0x83, 0x8c, 0xf7, 0xfb }, .b = { 0x8d, 0x0d }, .c = { 0x4d, 0x7f }, .d = { 0x87, 0x1e }, .e = { 0xd7, 0x1d , 0xbe, 0xfb, 0xb3, 0x9b } }; /* Note: this UUID is likely to work only for Sierra modems */ static const MbimUuid uuid_qmi = { .a = { 0xd1, 0xa3, 0x0b, 0xc2 }, .b = { 0xf9, 0x7a }, .c = { 0x6e, 0x43 }, .d = { 0xbf, 0x65 }, .e = { 0xc7, 0xe2 , 0x4f, 0xb0, 0xf0, 0xd3 } }; static const MbimUuid uuid_atds = { .a = { 0x59, 0x67, 0xbd, 0xcc }, .b = { 0x7f, 0xd2 }, .c = { 0x49, 0xa2 }, .d = { 0x9f, 0x5c }, .e = { 0xb2, 0xe7, 0x0e, 0x52, 0x7d, 0xb3 } }; static const MbimUuid uuid_intel_firmware_update = { .a = { 0x0e, 0xd3, 0x74, 0xcb }, .b = { 0xf8, 0x35 }, .c = { 0x44, 0x74 }, .d = { 0xbc, 0x11 }, .e = { 0x3b, 0x3f, 0xd7, 0x6f, 0x56, 0x41 } }; static const MbimUuid uuid_qdu = { .a = { 0x64, 0x27, 0x01, 0x5f }, .b = { 0x57, 0x9d }, .c = { 0x48, 0xf5 }, .d = { 0x8c, 0x54 }, .e = { 0xf4, 0x3e, 0xd1, 0xe7, 0x6f, 0x83 } }; static const MbimUuid uuid_ms_basic_connect_extensions = { .a = { 0x3d, 0x01, 0xdc, 0xc5 }, .b = { 0xfe, 0xf5 }, .c = { 0x4d, 0x05 }, .d = { 0x0d, 0x3a }, .e = { 0xbe, 0xf7, 0x05, 0x8e, 0x9a, 0xaf } }; static const MbimUuid uuid_ms_uicc_low_level_access = { .a = { 0xc2, 0xf6, 0x58, 0x8e }, .b = { 0xf0, 0x37 }, .c = { 0x4b, 0xc9 }, .d = { 0x86, 0x65 }, .e = { 0xf4, 0xd4, 0x4b, 0xd0, 0x93, 0x67 } }; static const MbimUuid uuid_quectel = { .a = { 0x11, 0x22, 0x33, 0x44 }, .b = { 0x55, 0x66 }, .c = { 0x77, 0x88 }, .d = { 0x99, 0xaa }, .e = { 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11 } }; static const MbimUuid uuid_intel_thermal_rf = { .a = { 0xfd, 0xc2, 0x2a, 0xf2 }, .b = { 0xf4, 0x41 }, .c = { 0x4d, 0x46 }, .d = { 0xaf, 0x8d }, .e = { 0x25, 0x9f, 0xcd, 0xde, 0x46, 0x35 } }; static const MbimUuid uuid_ms_voice_extensions = { .a = { 0x8d, 0x8b, 0x9e, 0xba }, .b = { 0x37, 0xbe }, .c = { 0x44, 0x9b }, .d = { 0x8f, 0x1e }, .e = { 0x61, 0xcb, 0x03, 0x4a, 0x70, 0x2e } }; static const MbimUuid uuid_intel_mutual_authentication = { .a = { 0xf8, 0x5d, 0x46, 0xef }, .b = { 0xab, 0x26 }, .c = { 0x40, 0x81 }, .d = { 0x98, 0x68 }, .e = { 0x4d, 0x18, 0x3c, 0x0a, 0x3a, 0xec } }; static const MbimUuid uuid_intel_tools = { .a = { 0x4a, 0xda, 0x49, 0x62 }, .b = { 0xb9, 0x88 }, .c = { 0x46, 0xc3 }, .d = { 0x87, 0xa7 }, .e = { 0x97, 0xf2, 0x0f, 0x99, 0x4a, 0xbb } }; static const MbimUuid uuid_google = { .a = { 0x3e, 0x1e, 0x92, 0xcf }, .b = { 0xc5, 0x3d }, .c = { 0x4f, 0x14 }, .d = { 0x85, 0xd0 }, .e = { 0xa8, 0x6a, 0xd9, 0xe1, 0x22, 0x45 } }; static const MbimUuid uuid_fibocom = { .a = { 0xff, 0xff, 0xff, 0xff }, .b = { 0xab, 0xca }, .c = { 0x4b, 0x11 }, .d = { 0xa4, 0xe2 }, .e = { 0xf2, 0xfc, 0x87, 0xf9, 0x44, 0x88 } }; static GList *mbim_custom_service_list = NULL; typedef struct { guint service_id; MbimUuid uuid; gchar *nickname; } MbimCustomService; guint mbim_register_custom_service (const MbimUuid *uuid, const gchar *nickname) { MbimCustomService *s; GList *l; guint service_id = 100; for (l = mbim_custom_service_list; l != NULL; l = l->next) { s = (MbimCustomService *)l->data; if (mbim_uuid_cmp (&s->uuid, uuid)) return s->service_id; else service_id = MAX (service_id, s->service_id); } /* create a new custom service */ s = g_slice_new (MbimCustomService); s->service_id = service_id + 1; memcpy (&s->uuid, uuid, sizeof (MbimUuid)); s->nickname = g_strdup (nickname); mbim_custom_service_list = g_list_append (mbim_custom_service_list, s); return s->service_id; } gboolean mbim_unregister_custom_service (const guint id) { MbimCustomService *s; GList *l; for (l = mbim_custom_service_list; l != NULL; l = l->next) { s = (MbimCustomService *)l->data; if (s->service_id == id) { g_free (s->nickname); g_slice_free (MbimCustomService, s); mbim_custom_service_list = \ g_list_delete_link (mbim_custom_service_list, l); return TRUE; } } return FALSE; } gboolean mbim_service_id_is_custom (const guint id) { GList *l; if (id < MBIM_SERVICE_LAST) return FALSE; for (l = mbim_custom_service_list; l != NULL; l = l->next) { if (((MbimCustomService *)l->data)->service_id == id) return TRUE; } return FALSE; } const gchar * mbim_service_lookup_name (guint service) { GList *l; if (service < MBIM_SERVICE_LAST) return mbim_service_get_string (service); for (l = mbim_custom_service_list; l != NULL; l = l->next) { if (service == ((MbimCustomService *)l->data)->service_id) return ((MbimCustomService *)l->data)->nickname; } return NULL; } const MbimUuid * mbim_uuid_from_service (MbimService service) { GList *l; g_return_val_if_fail (service < MBIM_SERVICE_LAST || mbim_service_id_is_custom (service), &uuid_invalid); switch (service) { case MBIM_SERVICE_INVALID: return &uuid_invalid; case MBIM_SERVICE_BASIC_CONNECT: return &uuid_basic_connect; case MBIM_SERVICE_SMS: return &uuid_sms; case MBIM_SERVICE_USSD: return &uuid_ussd; case MBIM_SERVICE_PHONEBOOK: return &uuid_phonebook; case MBIM_SERVICE_STK: return &uuid_stk; case MBIM_SERVICE_AUTH: return &uuid_auth; case MBIM_SERVICE_DSS: return &uuid_dss; case MBIM_SERVICE_MS_FIRMWARE_ID: return &uuid_ms_firmware_id; case MBIM_SERVICE_MS_HOST_SHUTDOWN: return &uuid_ms_host_shutdown; case MBIM_SERVICE_MS_SAR: return &uuid_ms_sar; case MBIM_SERVICE_PROXY_CONTROL: return &uuid_proxy_control; case MBIM_SERVICE_QMI: return &uuid_qmi; case MBIM_SERVICE_ATDS: return &uuid_atds; case MBIM_SERVICE_QDU: return &uuid_qdu; case MBIM_SERVICE_INTEL_FIRMWARE_UPDATE: return &uuid_intel_firmware_update; case MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS: return &uuid_ms_basic_connect_extensions; case MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS: return &uuid_ms_uicc_low_level_access; case MBIM_SERVICE_QUECTEL: return &uuid_quectel; case MBIM_SERVICE_INTEL_THERMAL_RF: return &uuid_intel_thermal_rf; case MBIM_SERVICE_MS_VOICE_EXTENSIONS: return &uuid_ms_voice_extensions; case MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: return &uuid_intel_mutual_authentication; case MBIM_SERVICE_INTEL_TOOLS: return &uuid_intel_tools; case MBIM_SERVICE_GOOGLE: return &uuid_google; case MBIM_SERVICE_FIBOCOM: return &uuid_fibocom; case MBIM_SERVICE_LAST: g_assert_not_reached (); default: for (l = mbim_custom_service_list; l != NULL; l = l->next) { if (service == ((MbimCustomService *)l->data)->service_id) return &((MbimCustomService *)l->data)->uuid; } g_return_val_if_reached (NULL); } } MbimService mbim_uuid_to_service (const MbimUuid *uuid) { GList *l; if (mbim_uuid_cmp (uuid, &uuid_basic_connect)) return MBIM_SERVICE_BASIC_CONNECT; if (mbim_uuid_cmp (uuid, &uuid_sms)) return MBIM_SERVICE_SMS; if (mbim_uuid_cmp (uuid, &uuid_ussd)) return MBIM_SERVICE_USSD; if (mbim_uuid_cmp (uuid, &uuid_phonebook)) return MBIM_SERVICE_PHONEBOOK; if (mbim_uuid_cmp (uuid, &uuid_stk)) return MBIM_SERVICE_STK; if (mbim_uuid_cmp (uuid, &uuid_auth)) return MBIM_SERVICE_AUTH; if (mbim_uuid_cmp (uuid, &uuid_dss)) return MBIM_SERVICE_DSS; if (mbim_uuid_cmp (uuid, &uuid_ms_firmware_id)) return MBIM_SERVICE_MS_FIRMWARE_ID; if (mbim_uuid_cmp (uuid, &uuid_ms_host_shutdown)) return MBIM_SERVICE_MS_HOST_SHUTDOWN; if (mbim_uuid_cmp (uuid, &uuid_ms_sar)) return MBIM_SERVICE_MS_SAR; if (mbim_uuid_cmp (uuid, &uuid_proxy_control)) return MBIM_SERVICE_PROXY_CONTROL; if (mbim_uuid_cmp (uuid, &uuid_qmi)) return MBIM_SERVICE_QMI; if (mbim_uuid_cmp (uuid, &uuid_atds)) return MBIM_SERVICE_ATDS; if (mbim_uuid_cmp (uuid, &uuid_intel_firmware_update)) return MBIM_SERVICE_INTEL_FIRMWARE_UPDATE; if (mbim_uuid_cmp (uuid, &uuid_qdu)) return MBIM_SERVICE_QDU; if (mbim_uuid_cmp (uuid, &uuid_ms_basic_connect_extensions)) return MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS; if (mbim_uuid_cmp (uuid, &uuid_ms_uicc_low_level_access)) return MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS; if (mbim_uuid_cmp (uuid, &uuid_quectel)) return MBIM_SERVICE_QUECTEL; if (mbim_uuid_cmp (uuid, &uuid_intel_thermal_rf)) return MBIM_SERVICE_INTEL_THERMAL_RF; if (mbim_uuid_cmp (uuid, &uuid_ms_voice_extensions)) return MBIM_SERVICE_MS_VOICE_EXTENSIONS; if (mbim_uuid_cmp (uuid, &uuid_intel_mutual_authentication)) return MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION; if (mbim_uuid_cmp (uuid, &uuid_intel_tools)) return MBIM_SERVICE_INTEL_TOOLS; if (mbim_uuid_cmp (uuid, &uuid_google)) return MBIM_SERVICE_GOOGLE; if (mbim_uuid_cmp (uuid, &uuid_fibocom)) return MBIM_SERVICE_FIBOCOM; for (l = mbim_custom_service_list; l != NULL; l = l->next) { if (mbim_uuid_cmp (&((MbimCustomService *)l->data)->uuid, uuid)) return ((MbimCustomService *)l->data)->service_id; } return MBIM_SERVICE_INVALID; } /*****************************************************************************/ static const MbimUuid uuid_context_type_none = { .a = { 0xB4, 0x3F, 0x75, 0x8C }, .b = { 0xA5, 0x60 }, .c = { 0x4B, 0x46 }, .d = { 0xB3, 0x5E }, .e = { 0xC5, 0x86, 0x96, 0x41, 0xFB, 0x54 } }; static const MbimUuid uuid_context_type_internet = { .a = { 0x7E, 0x5E, 0x2A, 0x7E }, .b = { 0x4E, 0x6F }, .c = { 0x72, 0x72 }, .d = { 0x73, 0x6B }, .e = { 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E } }; static const MbimUuid uuid_context_type_vpn = { .a = { 0x9B, 0x9F, 0x7B, 0xBE }, .b = { 0x89, 0x52 }, .c = { 0x44, 0xB7 }, .d = { 0x83, 0xAC }, .e = { 0xCA, 0x41, 0x31, 0x8D, 0xF7, 0xA0 } }; static const MbimUuid uuid_context_type_voice = { .a = { 0x88, 0x91, 0x82, 0x94 }, .b = { 0x0E, 0xF4 }, .c = { 0x43, 0x96 }, .d = { 0x8C, 0xCA }, .e = { 0xA8, 0x58, 0x8F, 0xBC, 0x02, 0xB2 } }; static const MbimUuid uuid_context_type_video_share = { .a = { 0x05, 0xA2, 0xA7, 0x16 }, .b = { 0x7C, 0x34 }, .c = { 0x4B, 0x4D }, .d = { 0x9A, 0x91 }, .e = { 0xC5, 0xEF, 0x0C, 0x7A, 0xAA, 0xCC } }; static const MbimUuid uuid_context_type_purchase = { .a = { 0xB3, 0x27, 0x24, 0x96 }, .b = { 0xAC, 0x6C }, .c = { 0x42, 0x2B }, .d = { 0xA8, 0xC0 }, .e = { 0xAC, 0xF6, 0x87, 0xA2, 0x72, 0x17 } }; static const MbimUuid uuid_context_type_ims = { .a = { 0x21, 0x61, 0x0D, 0x01 }, .b = { 0x30, 0x74 }, .c = { 0x4B, 0xCE }, .d = { 0x94, 0x25 }, .e = { 0xB5, 0x3A, 0x07, 0xD6, 0x97, 0xD6 } }; static const MbimUuid uuid_context_type_mms = { .a = { 0x46, 0x72, 0x66, 0x64 }, .b = { 0x72, 0x69 }, .c = { 0x6B, 0xC6 }, .d = { 0x96, 0x24 }, .e = { 0xD1, 0xD3, 0x53, 0x89, 0xAC, 0xA9 } }; static const MbimUuid uuid_context_type_local = { .a = { 0xA5, 0x7A, 0x9A, 0xFC }, .b = { 0xB0, 0x9F }, .c = { 0x45, 0xD7 }, .d = { 0xBB, 0x40 }, .e = { 0x03, 0x3C, 0x39, 0xF6, 0x0D, 0xB9 } }; static const MbimUuid uuid_context_type_admin = { .a = { 0x5F, 0x7E, 0x4C, 0x2E }, .b = { 0xE8, 0x0B }, .c = { 0x40, 0xA9 }, .d = { 0xA2, 0x39 }, .e = { 0xF0, 0xAB, 0xCF, 0xD1, 0x1F, 0x4B } }; static const MbimUuid uuid_context_type_app = { .a = { 0x74, 0xD8, 0x8A, 0x3D }, .b = { 0xDF, 0xBD }, .c = { 0x47, 0x99 }, .d = { 0x9A, 0x8C }, .e = { 0x73, 0x10, 0xA3, 0x7B, 0xB2, 0xEE } }; static const MbimUuid uuid_context_type_xcap = { .a = { 0x50, 0xD3, 0x78, 0xA7 }, .b = { 0xBA, 0xA5 }, .c = { 0x4A, 0x50 }, .d = { 0xB8, 0x72 }, .e = { 0x3F, 0xE5, 0xBB, 0x46, 0x34, 0x11 } }; static const MbimUuid uuid_context_type_tethering = { .a = { 0x5E, 0x4E, 0x06, 0x01 }, .b = { 0x48, 0xDC }, .c = { 0x4E, 0x2B }, .d = { 0xAC, 0xB8 }, .e = { 0x08, 0xB4, 0x01, 0x6B, 0xBA, 0xAC } }; static const MbimUuid uuid_context_type_emergency_calling = { .a = { 0x5F, 0x41, 0xAD, 0xB8 }, .b = { 0x20, 0x4E }, .c = { 0x4D, 0x31 }, .d = { 0x9D, 0xA8 }, .e = { 0xB3, 0xC9, 0x70, 0xE3, 0x60, 0xF2 } }; const MbimUuid * mbim_uuid_from_context_type (MbimContextType context_type) { g_return_val_if_fail (context_type <= MBIM_CONTEXT_TYPE_EMERGENCY_CALLING, &uuid_invalid); switch (context_type) { case MBIM_CONTEXT_TYPE_INVALID: return &uuid_invalid; case MBIM_CONTEXT_TYPE_NONE: return &uuid_context_type_none; case MBIM_CONTEXT_TYPE_INTERNET: return &uuid_context_type_internet; case MBIM_CONTEXT_TYPE_VPN: return &uuid_context_type_vpn; case MBIM_CONTEXT_TYPE_VOICE: return &uuid_context_type_none; case MBIM_CONTEXT_TYPE_VIDEO_SHARE: return &uuid_context_type_video_share; case MBIM_CONTEXT_TYPE_PURCHASE: return &uuid_context_type_purchase; case MBIM_CONTEXT_TYPE_IMS: return &uuid_context_type_ims; case MBIM_CONTEXT_TYPE_MMS: return &uuid_context_type_mms; case MBIM_CONTEXT_TYPE_LOCAL: return &uuid_context_type_local; case MBIM_CONTEXT_TYPE_ADMIN: return &uuid_context_type_admin; case MBIM_CONTEXT_TYPE_APP: return &uuid_context_type_app; case MBIM_CONTEXT_TYPE_XCAP: return &uuid_context_type_xcap; case MBIM_CONTEXT_TYPE_TETHERING: return &uuid_context_type_tethering; case MBIM_CONTEXT_TYPE_EMERGENCY_CALLING: return &uuid_context_type_emergency_calling; default: g_assert_not_reached (); } } MbimContextType mbim_uuid_to_context_type (const MbimUuid *uuid) { if (mbim_uuid_cmp (uuid, &uuid_context_type_none)) return MBIM_CONTEXT_TYPE_NONE; if (mbim_uuid_cmp (uuid, &uuid_context_type_internet)) return MBIM_CONTEXT_TYPE_INTERNET; if (mbim_uuid_cmp (uuid, &uuid_context_type_vpn)) return MBIM_CONTEXT_TYPE_VPN; if (mbim_uuid_cmp (uuid, &uuid_context_type_voice)) return MBIM_CONTEXT_TYPE_VOICE; if (mbim_uuid_cmp (uuid, &uuid_context_type_video_share)) return MBIM_CONTEXT_TYPE_VIDEO_SHARE; if (mbim_uuid_cmp (uuid, &uuid_context_type_purchase)) return MBIM_CONTEXT_TYPE_PURCHASE; if (mbim_uuid_cmp (uuid, &uuid_context_type_ims)) return MBIM_CONTEXT_TYPE_IMS; if (mbim_uuid_cmp (uuid, &uuid_context_type_mms)) return MBIM_CONTEXT_TYPE_MMS; if (mbim_uuid_cmp (uuid, &uuid_context_type_local)) return MBIM_CONTEXT_TYPE_LOCAL; if (mbim_uuid_cmp (uuid, &uuid_context_type_admin)) return MBIM_CONTEXT_TYPE_ADMIN; if (mbim_uuid_cmp (uuid, &uuid_context_type_app)) return MBIM_CONTEXT_TYPE_APP; if (mbim_uuid_cmp (uuid, &uuid_context_type_xcap)) return MBIM_CONTEXT_TYPE_XCAP; if (mbim_uuid_cmp (uuid, &uuid_context_type_tethering)) return MBIM_CONTEXT_TYPE_TETHERING; if (mbim_uuid_cmp (uuid, &uuid_context_type_emergency_calling)) return MBIM_CONTEXT_TYPE_EMERGENCY_CALLING; return MBIM_CONTEXT_TYPE_INVALID; } libmbim-1.31.2-dev/src/libmbim-glib/mbim-uuid.h000066400000000000000000000374731453630424100211630ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * libmbim-glib -- GLib/GIO based library to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2022 Intel Corporation */ #ifndef _LIBMBIM_GLIB_MBIM_UUID_H_ #define _LIBMBIM_GLIB_MBIM_UUID_H_ #if !defined (__LIBMBIM_GLIB_H_INSIDE__) && !defined (LIBMBIM_GLIB_COMPILATION) #error "Only can be included directly." #endif #include G_BEGIN_DECLS /** * SECTION: mbim-uuid * @title: UUIDs * @short_description: Generic UUID handling routines. * * This section defines the data type for unique identifiers. */ /*****************************************************************************/ /** * MbimUuid: * * A UUID as defined in MBIM. * * Since: 1.0 */ typedef struct _MbimUuid MbimUuid; #define MBIM_PACKED __attribute__((__packed__)) struct MBIM_PACKED _MbimUuid { guint8 a[4]; guint8 b[2]; guint8 c[2]; guint8 d[2]; guint8 e[6]; }; #undef MBIM_PACKED /** * mbim_uuid_cmp: * @a: a #MbimUuid. * @b: a #MbimUuid. * * Compare two %MbimUuid values. * * Returns: %TRUE if @a and @b are equal, %FALSE otherwise. * * Since: 1.0 */ gboolean mbim_uuid_cmp (const MbimUuid *a, const MbimUuid *b); /** * mbim_uuid_get_printable: * @uuid: a #MbimUuid. * * Get a string with the UUID. * * Returns: (transfer full): a newly allocated string, which should be freed with g_free(). * * Since: 1.0 */ gchar *mbim_uuid_get_printable (const MbimUuid *uuid); /** * mbim_uuid_from_printable: * @str: a MBIM UUID. * @uuid: pointer to the target #MbimUuid. * * Fills in @uuid from the printable representation give in @str. * * Only ccepts @str written with dashes separating items, e.g.: * a289cc33-bcbb-8b4f-b6b0-133ec2aae6df * * Returns: %TRUE if @uuid was correctly set, %FALSE otherwise. * * Since: 1.8 */ gboolean mbim_uuid_from_printable (const gchar *str, MbimUuid *uuid); /*****************************************************************************/ /** * MbimService: * @MBIM_SERVICE_INVALID: Invalid service. * @MBIM_SERVICE_BASIC_CONNECT: Basic connectivity service. * @MBIM_SERVICE_SMS: SMS messaging service. * @MBIM_SERVICE_USSD: USSD service. * @MBIM_SERVICE_PHONEBOOK: Phonebook service. * @MBIM_SERVICE_STK: SIM toolkit service. * @MBIM_SERVICE_AUTH: Authentication service. * @MBIM_SERVICE_DSS: Device Service Stream service. * @MBIM_SERVICE_MS_FIRMWARE_ID: Microsoft Firmware ID service. Since 1.8. * @MBIM_SERVICE_MS_HOST_SHUTDOWN: Microsoft Host Shutdown service. Since 1.8. * @MBIM_SERVICE_PROXY_CONTROL: Proxy Control service. Since 1.10. * @MBIM_SERVICE_QMI: QMI-over-MBIM service. Since 1.14. * @MBIM_SERVICE_ATDS: ATT Device service. Since 1.16. * @MBIM_SERVICE_INTEL_FIRMWARE_UPDATE: Intel firmware update service. Since 1.16. * @MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS: Microsoft basic connectivity extensions service. Since 1.18. * @MBIM_SERVICE_MS_SAR: Microsoft SAR service. Since 1.26. * @MBIM_SERVICE_QDU: QDU firmware update service. Since 1.26. * @MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS: Microsoft UICC Low Level Access service. Since 1.26. * @MBIM_SERVICE_QUECTEL: Quectel specific operations. Since 1.26.2. * @MBIM_SERVICE_INTEL_THERMAL_RF: Intel thermal rf related commands. Since 1.28 * @MBIM_SERVICE_MS_VOICE_EXTENSIONS: Microsoft Voice extensions service. Since 1.28. * @MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: Intel mutual authentication commands. Since 1.30. * @MBIM_SERVICE_INTEL_TOOLS: Intel tools service. Since 1.30. * @MBIM_SERVICE_GOOGLE: Google specific service. Since 1.30 * @MBIM_SERVICE_FIBOCOM: Fibocom specific service. Since 1.32. * @MBIM_SERVICE_LAST: Internal value. * * Enumeration of the generic MBIM services. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_SERVICE_INVALID = 0, MBIM_SERVICE_BASIC_CONNECT = 1, MBIM_SERVICE_SMS = 2, MBIM_SERVICE_USSD = 3, MBIM_SERVICE_PHONEBOOK = 4, MBIM_SERVICE_STK = 5, MBIM_SERVICE_AUTH = 6, MBIM_SERVICE_DSS = 7, MBIM_SERVICE_MS_FIRMWARE_ID = 8, MBIM_SERVICE_MS_HOST_SHUTDOWN = 9, MBIM_SERVICE_PROXY_CONTROL = 10, MBIM_SERVICE_QMI = 11, MBIM_SERVICE_ATDS = 12, MBIM_SERVICE_INTEL_FIRMWARE_UPDATE = 13, MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS = 14, MBIM_SERVICE_MS_SAR = 15, MBIM_SERVICE_QDU = 16, MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS = 17, MBIM_SERVICE_QUECTEL = 18, MBIM_SERVICE_INTEL_THERMAL_RF = 19, MBIM_SERVICE_MS_VOICE_EXTENSIONS = 20, MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION = 21, MBIM_SERVICE_INTEL_TOOLS = 22, MBIM_SERVICE_GOOGLE = 23, MBIM_SERVICE_FIBOCOM = 24, #if defined LIBMBIM_GLIB_COMPILATION MBIM_SERVICE_LAST /*< skip >*/ #endif } MbimService; /** * MBIM_UUID_INVALID: * * Get the UUID of the %MBIM_SERVICE_INVALID service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ #define MBIM_UUID_INVALID mbim_uuid_from_service (MBIM_SERVICE_INVALID) /** * MBIM_UUID_BASIC_CONNECT: * * Get the UUID of the %MBIM_SERVICE_BASIC_CONNECT service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ #define MBIM_UUID_BASIC_CONNECT mbim_uuid_from_service (MBIM_SERVICE_BASIC_CONNECT) /** * MBIM_UUID_SMS: * * Get the UUID of the %MBIM_SERVICE_SMS service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ #define MBIM_UUID_SMS mbim_uuid_from_service (MBIM_SERVICE_SMS) /** * MBIM_UUID_USSD: * * Get the UUID of the %MBIM_SERVICE_USSD service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ #define MBIM_UUID_USSD mbim_uuid_from_service (MBIM_SERVICE_USSD) /** * MBIM_UUID_PHONEBOOK: * * Get the UUID of the %MBIM_SERVICE_PHONEBOOK service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ #define MBIM_UUID_PHONEBOOK mbim_uuid_from_service (MBIM_SERVICE_PHONEBOOK) /** * MBIM_UUID_STK: * * Get the UUID of the %MBIM_SERVICE_STK service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ #define MBIM_UUID_STK mbim_uuid_from_service (MBIM_SERVICE_STK) /** * MBIM_UUID_AUTH: * * Get the UUID of the %MBIM_SERVICE_AUTH service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ #define MBIM_UUID_AUTH mbim_uuid_from_service (MBIM_SERVICE_AUTH) /** * MBIM_UUID_DSS: * * Get the UUID of the %MBIM_SERVICE_DSS service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ #define MBIM_UUID_DSS mbim_uuid_from_service (MBIM_SERVICE_DSS) /** * MBIM_UUID_MS_FIRMWARE_ID: * * Get the UUID of the %MBIM_SERVICE_MS_FIRMWARE_ID service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.8 */ #define MBIM_UUID_MS_FIRMWARE_ID mbim_uuid_from_service (MBIM_SERVICE_MS_FIRMWARE_ID) /** * MBIM_UUID_MS_HOST_SHUTDOWN: * * Get the UUID of the %MBIM_SERVICE_MS_HOST_SHUTDOWN service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.8 */ #define MBIM_UUID_MS_HOST_SHUTDOWN mbim_uuid_from_service (MBIM_SERVICE_MS_HOST_SHUTDOWN) /** * MBIM_UUID_MS_SAR: * * Get the UUID of the %MBIM_SERVICE_MS_SAR service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.26 */ #define MBIM_UUID_MS_SAR mbim_uuid_from_service (MBIM_SERVICE_MS_SAR) /** * MBIM_UUID_PROXY_CONTROL: * * Get the UUID of the %MBIM_SERVICE_PROXY_CONTROL service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.10 */ #define MBIM_UUID_PROXY_CONTROL mbim_uuid_from_service (MBIM_SERVICE_PROXY_CONTROL) /** * MBIM_UUID_QMI: * * Get the UUID of the %MBIM_SERVICE_QMI service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.14 */ #define MBIM_UUID_QMI mbim_uuid_from_service (MBIM_SERVICE_QMI) /** * MBIM_UUID_ATDS: * * Get the UUID of the %MBIM_SERVICE_ATDS service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.16 */ #define MBIM_UUID_ATDS mbim_uuid_from_service (MBIM_SERVICE_ATDS) /** * MBIM_UUID_INTEL_FIRMWARE_UPDATE: * * Get the UUID of the %MBIM_SERVICE_INTEL_FIRMWARE_UPDATE service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.16 */ #define MBIM_UUID_INTEL_FIRMWARE_UPDATE mbim_uuid_from_service (MBIM_SERVICE_INTEL_FIRMWARE_UPDATE) /** * MBIM_UUID_QDU: * * Get the UUID of the %MBIM_SERVICE_QDU service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.26 */ #define MBIM_UUID_QDU mbim_uuid_from_service (MBIM_SERVICE_QDU) /** * MBIM_UUID_MS_BASIC_CONNECT_EXTENSIONS: * * Get the UUID of the %MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.18 */ #define MBIM_UUID_MS_BASIC_CONNECT_EXTENSIONS mbim_uuid_from_service (MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS) /** * MBIM_UUID_MS_UICC_LOW_LEVEL_ACCESS: * * Get the UUID of the %MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.26 */ #define MBIM_UUID_MS_UICC_LOW_LEVEL_ACCESS mbim_uuid_from_service (MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS) /** * MBIM_UUID_QUECTEL: * * Get the UUID of the %MBIM_SERVICE_QUECTEL service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.26.2 */ #define MBIM_UUID_QUECTEL mbim_uuid_from_service (MBIM_SERVICE_QUECTEL) /** * MBIM_UUID_INTEL_THERMAL_RF: * * Get the UUID of the %MBIM_SERVICE_INTEL_THERMAL_RF service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.28 */ #define MBIM_UUID_INTEL_THERMAL_RF mbim_uuid_from_service (MBIM_SERVICE_INTEL_THERMAL_RF) /** * MBIM_UUID_MS_VOICE_EXTENSIONS: * * Get the UUID of the %MBIM_SERVICE_MS_VOICE_EXTENSIONS service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.28 */ #define MBIM_UUID_MS_VOICE_EXTENSIONS mbim_uuid_from_service (MBIM_SERVICE_MS_VOICE_EXTENSIONS) /** * MBIM_UUID_INTEL_MUTUAL_AUTHENTICATION: * * Get the UUID of the %MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.30 */ #define MBIM_UUID_INTEL_MUTUAL_AUTHENTICATION mbim_uuid_from_service (MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION) /** * MBIM_UUID_INTEL_TOOLS: * * Get the UUID of the %MBIM_SERVICE_INTEL_TOOLS service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.30 */ #define MBIM_UUID_INTEL_TOOLS mbim_uuid_from_service (MBIM_SERVICE_INTEL_TOOLS) /** * MBIM_UUID_GOOGLE: * * Get the UUID of the %MBIM_SERVICE_GOOGLE service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.30 */ #define MBIM_UUID_GOOGLE mbim_uuid_from_service (MBIM_SERVICE_GOOGLE) /** * MBIM_UUID_FIBOCOM: * * Get the UUID of the %MBIM_SERVICE_FIBOCOM service. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.32 */ #define MBIM_UUID_FIBOCOM mbim_uuid_from_service (MBIM_SERVICE_FIBOCOM) /** * mbim_service_lookup_name: * @service: a MbimService or custom service. * * Gets the nickname string for the @service. * * As opposed to mbim_service_get_string(), this methods takes into account * custom services that may have been registered by the user. * * Returns: (transfer none): a string with the nickname, or %NULL if not found. Do not free the returned value. * * Since: 1.10 */ const gchar *mbim_service_lookup_name (guint service); /** * mbim_register_custom_service: * @uuid: MbimUuid structure corresponding to service * @nickname: a printable name for service * * Register a custom service * * Returns: TRUE if service has been registered, FALSE otherwise. * * Since: 1.10 */ guint mbim_register_custom_service (const MbimUuid *uuid, const gchar *nickname); /** * mbim_unregister_custom_service: * @id: ID of the service to unregister.MbimUuid structure corresponding to service * * Unregister a custom service. * * Returns: TRUE if service has been unregistered, FALSE otherwise. * * Since: 1.10 */ gboolean mbim_unregister_custom_service (const guint id); /** * mbim_service_id_is_custom: * @id: ID of the service * * Checks whether @id is a custom or standard service. * * Returns: TRUE if service is custom, FALSE otherwise. * * Since: 1.10 */ gboolean mbim_service_id_is_custom (const guint id); /** * mbim_uuid_from_service: * @service: a #MbimService. * * Get the UUID corresponding to @service. * * The @service needs to be either a generic one (including #MBIM_SERVICE_INVALID) * or a custom registered one. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ const MbimUuid *mbim_uuid_from_service (MbimService service); /** * mbim_uuid_to_service: * @uuid: a #MbimUuid. * * Get the service corresponding to @uuid. * * Returns: a #MbimService. * * Since: 1.0 */ MbimService mbim_uuid_to_service (const MbimUuid *uuid); /*****************************************************************************/ /** * MbimContextType: * @MBIM_CONTEXT_TYPE_INVALID: Invalid context type. * @MBIM_CONTEXT_TYPE_NONE: Context not yet provisioned. * @MBIM_CONTEXT_TYPE_INTERNET: Context representing a connection to the * Internet. * @MBIM_CONTEXT_TYPE_VPN: Context representing a connection to a a private * network (e.g. VPN to a corporate network). * @MBIM_CONTEXT_TYPE_VOICE: Context representing a connection to a VoIP service. * @MBIM_CONTEXT_TYPE_VIDEO_SHARE: Context representing a connection to a video * sharing service. * @MBIM_CONTEXT_TYPE_PURCHASE: Context representing a connection to an * OTA (over-the-air) activation site. * @MBIM_CONTEXT_TYPE_IMS: Context representing a connection to IMS. * @MBIM_CONTEXT_TYPE_MMS: Context representing a connection to MMS. * @MBIM_CONTEXT_TYPE_LOCAL: Context representing a connection which is * terminated at the device. No IP traffic sent over the air. * @MBIM_CONTEXT_TYPE_ADMIN: Context used for administrative purposes, such as * device management (MS MBIMEx). Since 1.28. * @MBIM_CONTEXT_TYPE_APP: Context used for certain applications allowed by * mobile operators (MS MBIMEx). Since 1.28. * @MBIM_CONTEXT_TYPE_XCAP: Context used for XCAP provisioning on IMS services * (MS MBIMEx). Since 1.28. * @MBIM_CONTEXT_TYPE_TETHERING: Context used for mobile hotspot tethering * (MS MBIMEx). Since 1.28. * @MBIM_CONTEXT_TYPE_EMERGENCY_CALLING: Context used for IMS emergency calling * (MS MBIMEx). Since 1.28. * * Enumeration of the generic MBIM context types. * * Since: 1.0 */ typedef enum { /*< since=1.0 >*/ MBIM_CONTEXT_TYPE_INVALID = 0, MBIM_CONTEXT_TYPE_NONE = 1, MBIM_CONTEXT_TYPE_INTERNET = 2, MBIM_CONTEXT_TYPE_VPN = 3, MBIM_CONTEXT_TYPE_VOICE = 4, MBIM_CONTEXT_TYPE_VIDEO_SHARE = 5, MBIM_CONTEXT_TYPE_PURCHASE = 6, MBIM_CONTEXT_TYPE_IMS = 7, MBIM_CONTEXT_TYPE_MMS = 8, MBIM_CONTEXT_TYPE_LOCAL = 9, MBIM_CONTEXT_TYPE_ADMIN = 10, MBIM_CONTEXT_TYPE_APP = 11, MBIM_CONTEXT_TYPE_XCAP = 12, MBIM_CONTEXT_TYPE_TETHERING = 13, MBIM_CONTEXT_TYPE_EMERGENCY_CALLING = 14, } MbimContextType; /** * mbim_uuid_from_context_type: * @context_type: a #MbimContextType. * * Get the UUID corresponding to @context_type. * * Returns: (transfer none): a #MbimUuid. * * Since: 1.0 */ const MbimUuid *mbim_uuid_from_context_type (MbimContextType context_type); /** * mbim_uuid_to_context_type: * @uuid: a #MbimUuid. * * Get the context type corresponding to @uuid. * * Returns: a #MbimContextType. * * Since: 1.0 */ MbimContextType mbim_uuid_to_context_type (const MbimUuid *uuid); G_END_DECLS #endif /* _LIBMBIM_GLIB_MBIM_UUID_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/mbim-version.h.in000066400000000000000000000034361453630424100222770ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2013 Lanedo GmbH * Copyright (C) 2013 - 2014 Aleksander Morgado */ #ifndef _MBIM_VERSION_H_ #define _MBIM_VERSION_H_ /** * SECTION:mbim-version * @short_description: Version information in the API. * * This section defines types that are used to identify the libmbim-glib version. **/ /** * MBIM_MAJOR_VERSION: * * Evaluates to the major version number of libmbim-glib which this source * is compiled against. * * Since: 1.2 */ #define MBIM_MAJOR_VERSION (@MBIM_MAJOR_VERSION@) /** * MBIM_MINOR_VERSION: * * Evaluates to the minor version number of libmbim-glib which this source * is compiled against. * * Since: 1.2 */ #define MBIM_MINOR_VERSION (@MBIM_MINOR_VERSION@) /** * MBIM_MICRO_VERSION: * * Evaluates to the micro version number of libmbim-glib which this source * compiled against. * * Since: 1.2 */ #define MBIM_MICRO_VERSION (@MBIM_MICRO_VERSION@) /** * MBIM_CHECK_VERSION: * @major: major version (e.g. 1 for version 1.2.5) * @minor: minor version (e.g. 2 for version 1.2.5) * @micro: micro version (e.g. 5 for version 1.2.5) * * Checks the version of the library that is being compiled against. * * Returns: %TRUE if the version of the libmbim-glib header files * is the same as or newer than the passed-in version. * * Since: 1.2 */ #define MBIM_CHECK_VERSION(major,minor,micro) \ (MBIM_MAJOR_VERSION > (major) || \ (MBIM_MAJOR_VERSION == (major) && MBIM_MINOR_VERSION > (minor)) || \ (MBIM_MAJOR_VERSION == (major) && MBIM_MINOR_VERSION == (minor) && MBIM_MICRO_VERSION >= (micro))) #endif /* _MBIM_VERSION_H_ */ libmbim-1.31.2-dev/src/libmbim-glib/meson.build000066400000000000000000000065731453630424100212610ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez libmbim_glib_inc = include_directories('.') mbim_errors_header = files('mbim-errors.h') mbim_enums_headers = files( 'mbim-cid.h', 'mbim-enums.h', 'mbim-message.h', 'mbim-uuid.h', 'mbim-tlv.h', ) subdir('generated') headers = mbim_errors_header + mbim_enums_headers + files( 'libmbim-glib.h', 'mbim-compat.h', 'mbim-device.h', 'mbim-proxy.h', 'mbim-utils.h', ) install_headers( headers, install_dir: mbim_glib_pkgincludedir, ) common_c_flags = [ '-DLIBMBIM_GLIB_COMPILATION', '-DG_LOG_DOMAIN="Mbim"', '-DLIBEXEC_PATH="@0@"'.format(mbim_prefix / mbim_libexecdir), ] sources = files( 'mbim-cid.c', 'mbim-compat.c', 'mbim-device.c', 'mbim-helpers.c', 'mbim-helpers-netlink.c', 'mbim-message.c', 'mbim-net-port-manager.c', 'mbim-net-port-manager-wdm.c', 'mbim-net-port-manager-wwan.c', 'mbim-proxy.c', 'mbim-proxy-helpers.c', 'mbim-utils.c', 'mbim-uuid.c', 'mbim-tlv.c', ) deps = [ generated_dep, libmbim_common_dep, ] libmbim_glib_core = static_library( 'mbim-glib-core', sources: sources, include_directories: top_inc, dependencies: deps + [gio_unix_dep], c_args: common_c_flags, link_whole: libmbim_glib_generated, ) libmbim_glib_core_dep = declare_dependency( include_directories: libmbim_glib_inc, dependencies: deps, link_with: libmbim_glib_core, ) libname = 'mbim-glib' version_header = configure_file( input: 'mbim-version.h.in', output: '@BASENAME@', configuration: version_conf, install_dir: mbim_glib_pkgincludedir, ) symbol_map = meson.current_source_dir() / 'symbol.map' ldflags = cc.get_supported_link_arguments('-Wl,--version-script,@0@'.format(symbol_map)) libmbim_glib = library( libname, version: mbim_glib_version, sources: version_header, include_directories: top_inc, dependencies: generated_dep, link_args: ldflags, link_depends: symbol_map, link_whole: libmbim_glib_core, install: true, ) libmbim_glib_dep = declare_dependency( sources: [gen_headers, version_header], include_directories: [libmbim_glib_inc, generated_inc], dependencies: glib_deps, link_with: libmbim_glib, ) pkg.generate( libraries: libmbim_glib, version: mbim_version, name: libname, description: 'Library to communicate with MBIM-powered modems', subdirs: mbim_glib_include_subdir, # FIXME: produced by the inhability of meson to use internal dependencies requires: ['glib-2.0', 'gobject-2.0', 'gio-2.0'], variables: 'exec_prefix=${prefix}', ) # Introspection if enable_gir and get_option('default_library') != 'static' incs = [ 'Gio-2.0', 'GLib-2.0', 'GObject-2.0', ] ns = 'Mbim' libmbim_glib_gir = gnome.generate_gir( libmbim_glib, sources: headers + [version_header] + gen_sources + gen_headers, includes: incs, dependencies: libmbim_glib_dep, namespace: ns, nsversion: mbim_gir_version, identifier_prefix: ns, symbol_prefix: ns.to_lower() + '_', extra_args: common_c_flags + ['--identifier-prefix=' + ns.to_upper()], header: 'libmbim-glib.h', export_packages: libname, install: true, ) endif if enable_mbim_username configure_file( input: '76-mbim-device-ownership.rules.in', output: '@BASENAME@', configuration: {'MBIM_USERNAME': mbim_username}, install_dir: udev_udevdir / 'rules.d', ) endif subdir('test') libmbim-1.31.2-dev/src/libmbim-glib/symbol.map000066400000000000000000000000431453630424100211050ustar00rootroot00000000000000{ global: mbim_*; local: *; }; libmbim-1.31.2-dev/src/libmbim-glib/test/000077500000000000000000000000001453630424100200635ustar00rootroot00000000000000libmbim-1.31.2-dev/src/libmbim-glib/test/meson.build000066400000000000000000000020171453630424100222250ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez test_units = [ 'uuid', 'cid', 'message', 'fragment', 'message-fuzzer-samples', 'message-parser', 'message-builder', 'proxy-helpers', ] test_env = { 'G_DEBUG': 'gc-friendly', 'MALLOC_CHECK_': '2', 'G_TEST_SRCDIR': meson.current_source_dir(), 'G_TEST_BUILDDIR': meson.current_build_dir(), } foreach test_unit: test_units test_name = 'test-' + test_unit exe = executable( test_name, sources: test_name + '.c', include_directories: top_inc, dependencies: libmbim_glib_core_dep, c_args: '-DLIBMBIM_GLIB_COMPILATION', ) test( test_unit, exe, env: test_env, ) endforeach if get_option('fuzzer') fuzzer_name = 'test-message-fuzzer' exe = executable( fuzzer_name, sources: fuzzer_name + '.c', include_directories: top_inc, dependencies: libmbim_glib_core_dep, c_args: '-DLIBMBIM_GLIB_COMPILATION', link_args : '-fsanitize=fuzzer', ) endif libmbim-1.31.2-dev/src/libmbim-glib/test/test-cid.c000066400000000000000000000072451453630424100217530ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2014 Aleksander Morgado */ #include #include "mbim-cid.h" static void test_common (MbimService service, guint cid, gboolean can_set, gboolean can_query, gboolean can_notify) { g_assert (mbim_cid_can_set (service, cid) == can_set); g_assert (mbim_cid_can_query (service, cid) == can_query); g_assert (mbim_cid_can_notify (service, cid) == can_notify); } static void test_cid_basic_connect (void) { test_common (MBIM_SERVICE_BASIC_CONNECT, MBIM_CID_BASIC_CONNECT_DEVICE_CAPS, FALSE, TRUE, FALSE); test_common (MBIM_SERVICE_BASIC_CONNECT, MBIM_CID_BASIC_CONNECT_MULTICARRIER_PROVIDERS, TRUE, TRUE, TRUE); } static void test_cid_sms (void) { test_common (MBIM_SERVICE_SMS, MBIM_CID_SMS_CONFIGURATION, TRUE, TRUE, TRUE); test_common (MBIM_SERVICE_SMS, MBIM_CID_SMS_MESSAGE_STORE_STATUS, FALSE, TRUE, TRUE); } static void test_cid_ussd (void) { test_common (MBIM_SERVICE_USSD, MBIM_CID_USSD, TRUE, FALSE, TRUE); } static void test_cid_phonebook (void) { test_common (MBIM_SERVICE_PHONEBOOK, MBIM_CID_PHONEBOOK_CONFIGURATION, FALSE, TRUE, TRUE); test_common (MBIM_SERVICE_PHONEBOOK, MBIM_CID_PHONEBOOK_WRITE, TRUE, FALSE, FALSE); } static void test_cid_stk (void) { test_common (MBIM_SERVICE_STK, MBIM_CID_STK_PAC, TRUE, TRUE, TRUE); test_common (MBIM_SERVICE_STK, MBIM_CID_STK_ENVELOPE, TRUE, TRUE, FALSE); } static void test_cid_auth (void) { test_common (MBIM_SERVICE_AUTH, MBIM_CID_AUTH_AKA, FALSE, TRUE, FALSE); test_common (MBIM_SERVICE_AUTH, MBIM_CID_AUTH_SIM, FALSE, TRUE, FALSE); } static void test_cid_dss (void) { test_common (MBIM_SERVICE_DSS, MBIM_CID_DSS_CONNECT, TRUE, FALSE, FALSE); } static void test_cid_ms_firmware_id (void) { test_common (MBIM_SERVICE_MS_FIRMWARE_ID, MBIM_CID_MS_FIRMWARE_ID_GET, FALSE, TRUE, FALSE); } static void test_cid_ms_host_shutdown (void) { test_common (MBIM_SERVICE_MS_HOST_SHUTDOWN, MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY, TRUE, FALSE, FALSE); } static void test_cid_ms_sar (void) { test_common (MBIM_SERVICE_MS_SAR, MBIM_CID_MS_SAR_CONFIG, TRUE, TRUE, TRUE); } int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/libmbim-glib/cid/basic-connect", test_cid_basic_connect); g_test_add_func ("/libmbim-glib/cid/sms", test_cid_sms); g_test_add_func ("/libmbim-glib/cid/ussd", test_cid_ussd); g_test_add_func ("/libmbim-glib/cid/phonebook", test_cid_phonebook); g_test_add_func ("/libmbim-glib/cid/stk", test_cid_stk); g_test_add_func ("/libmbim-glib/cid/auth", test_cid_auth); g_test_add_func ("/libmbim-glib/cid/dss", test_cid_dss); g_test_add_func ("/libmbim-glib/cid/ms-firmware-id", test_cid_ms_firmware_id); g_test_add_func ("/libmbim-glib/cid/ms-host-shutdown", test_cid_ms_host_shutdown); g_test_add_func ("/libmbim-glib/cid/ms-sar", test_cid_ms_sar); return g_test_run (); } libmbim-1.31.2-dev/src/libmbim-glib/test/test-fragment.c000066400000000000000000000353611453630424100230170ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2014 Aleksander Morgado */ #include #include #include "mbim-message.h" #include "mbim-message-private.h" static void test_fragment_receive_single (void) { GError *error = NULL; g_autoptr(MbimMessage) message = NULL; const guint8 *fragment_information_buffer; guint32 fragment_information_buffer_length; /* This buffer contains a single message composed of a single fragment. * We don't really care about the actual data included within the fragment. */ const guint8 buffer [] = { 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x2C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x01, 0x00, 0x00, 0x00, /* total fragments */ 0x00, 0x00, 0x00, 0x00, /* current fragment */ 0x01, 0x02, 0x03, 0x04, /* fragment data (at least 24 bytes for an indication) */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x00, 0x00, 0x00, 0x00, /* buffer length 0! */ }; const guint8 data [] = { 0x01, 0x02, 0x03, 0x04, /* same data as in the fragment */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x00, 0x00, 0x00, 0x00, }; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (_mbim_message_is_fragment (message)); g_assert_cmpuint (_mbim_message_fragment_get_total (message), ==, 1); g_assert_cmpuint (_mbim_message_fragment_get_current (message), ==, 0); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); fragment_information_buffer = (_mbim_message_fragment_get_payload ( message, &fragment_information_buffer_length)); g_assert_cmpuint (fragment_information_buffer_length, ==, sizeof (data)); g_assert (memcmp (fragment_information_buffer, data, fragment_information_buffer_length) == 0); } static void test_fragment_receive_multiple (void) { g_autoptr(GByteArray) bytearray = NULL; g_autoptr(MbimMessage) message = NULL; GError *error = NULL; const guint8 *fragment_information_buffer; guint32 fragment_information_buffer_length; /* This buffer contains several fragments of a single message. * We don't really care about the actual data included within the fragments. */ const guint8 buffer [] = { /* First fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x04, 0x00, 0x00, 0x00, /* total fragments */ 0x00, 0x00, 0x00, 0x00, /* current fragment */ 0x00, 0x01, 0x02, 0x03, /* frament data */ 0x04, 0x05, 0x06, 0x07, /* Second fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x04, 0x00, 0x00, 0x00, /* total fragments */ 0x01, 0x00, 0x00, 0x00, /* current fragment */ 0x08, 0x09, 0x0A, 0x0B, /* frament data */ 0x0C, 0x0D, 0x0E, 0x0F, /* Third fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x04, 0x00, 0x00, 0x00, /* total fragments */ 0x02, 0x00, 0x00, 0x00, /* current fragment */ 0x10, 0x11, 0x12, 0x13, /* frament data */ 0x04, 0x00, 0x00, 0x00, /* Fourth fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x18, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x04, 0x00, 0x00, 0x00, /* total fragments */ 0x03, 0x00, 0x00, 0x00, /* current fragment */ 0x18, 0x19, 0x1A, 0x1B /* frament data */ }; const guint8 data [] = { 0x00, 0x01, 0x02, 0x03, /* same data as in the fragments */ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x04, 0x00, 0x00, 0x00, 0x18, 0x19, 0x1A, 0x1B }; bytearray = g_byte_array_new (); g_byte_array_append (bytearray, buffer, sizeof (buffer)); g_assert (_mbim_message_validate_internal ((const MbimMessage *)bytearray, TRUE, &error)); g_assert_no_error (error); /* First fragment creates the message */ message = _mbim_message_fragment_collector_init ((const MbimMessage *)bytearray, &error); g_assert_no_error (error); g_assert_cmpuint (_mbim_message_fragment_get_total (message), ==, 4); g_assert_cmpuint (_mbim_message_fragment_get_current (message), ==, 0); g_assert (_mbim_message_fragment_collector_complete (message) == FALSE); g_byte_array_remove_range (bytearray, 0, mbim_message_get_message_length ((const MbimMessage *)bytearray)); g_assert (_mbim_message_validate_internal ((const MbimMessage *)bytearray, TRUE, &error)); g_assert_no_error (error); /* Add second fragment */ g_assert (_mbim_message_fragment_collector_add (message, (const MbimMessage *)bytearray, &error)); g_assert_no_error (error); g_assert_cmpuint (_mbim_message_fragment_get_total (message), ==, 4); g_assert_cmpuint (_mbim_message_fragment_get_current (message), ==, 1); g_assert (_mbim_message_fragment_collector_complete (message) == FALSE); g_byte_array_remove_range (bytearray, 0, mbim_message_get_message_length ((const MbimMessage *)bytearray)); g_assert (_mbim_message_validate_internal ((const MbimMessage *)bytearray, TRUE, &error)); g_assert_no_error (error); /* Add third fragment */ g_assert (_mbim_message_fragment_collector_add (message, (const MbimMessage *)bytearray, &error)); g_assert_no_error (error); g_assert_cmpuint (_mbim_message_fragment_get_total (message), ==, 4); g_assert_cmpuint (_mbim_message_fragment_get_current (message), ==, 2); g_assert (_mbim_message_fragment_collector_complete (message) == FALSE); g_byte_array_remove_range (bytearray, 0, mbim_message_get_message_length ((const MbimMessage *)bytearray)); g_assert (_mbim_message_validate_internal ((const MbimMessage *)bytearray, TRUE, &error)); g_assert_no_error (error); /* Add fourth fragment */ g_assert (_mbim_message_fragment_collector_add (message, (const MbimMessage *)bytearray, &error)); g_assert_no_error (error); g_assert_cmpuint (_mbim_message_fragment_get_total (message), ==, 4); g_assert_cmpuint (_mbim_message_fragment_get_current (message), ==, 3); g_assert (_mbim_message_fragment_collector_complete (message) == TRUE); g_assert_cmpuint (_mbim_message_fragment_get_total (message), ==, 1); g_assert_cmpuint (_mbim_message_fragment_get_current (message), ==, 0); g_byte_array_remove_range (bytearray, 0, mbim_message_get_message_length ((const MbimMessage *)bytearray)); /* Validate all compiled data */ g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); fragment_information_buffer = (_mbim_message_fragment_get_payload ( message, &fragment_information_buffer_length)); g_assert_cmpuint (fragment_information_buffer_length, ==, sizeof (data)); g_assert (memcmp (fragment_information_buffer, data, fragment_information_buffer_length) == 0); } static void test_fragment_send_multiple_common (guint32 max_fragment_size, const guint8 *buffer, gsize buffer_length, const guint8 *expected_buffer, gsize expected_buffer_length) { GByteArray *bytearray; struct fragment_info *fragments; guint n_fragments; guint i; GByteArray *output_bytearray; /* Setup message and split it into fragments */ bytearray = g_byte_array_new (); g_byte_array_append (bytearray, buffer, buffer_length); fragments = _mbim_message_split_fragments ((const MbimMessage *)bytearray, max_fragment_size, &n_fragments); g_assert (fragments != NULL); /* Simulate that we write the fragments */ output_bytearray = g_byte_array_new (); for (i = 0; i < n_fragments; i++) { /* Header */ g_byte_array_append (output_bytearray, (guint8 *)&fragments[i].header, sizeof (fragments[i].header)); /* Fragment header */ g_byte_array_append (output_bytearray, (guint8 *)&fragments[i].fragment_header, sizeof (fragments[i].fragment_header)); /* Data */ g_byte_array_append (output_bytearray, fragments[i].data, fragments[i].data_length); } g_free (fragments); /* Compare with the expected buffer */ g_assert_cmpuint (expected_buffer_length, == , output_bytearray->len); g_assert (memcmp (output_bytearray->data, expected_buffer, output_bytearray->len) == 0); g_byte_array_unref (output_bytearray); } static void test_fragment_send_multiple_1 (void) { const guint8 buffer [] = { 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x30, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x01, 0x00, 0x00, 0x00, /* total fragments */ 0x00, 0x00, 0x00, 0x00, /* current fragment */ 0x00, 0x01, 0x02, 0x03, /* same data as in the fragments */ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B }; /* This buffer contains several fragments of a single message. * We don't really care about the actual data included within the fragments. */ const guint8 expected_buffer [] = { /* First fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x04, 0x00, 0x00, 0x00, /* total fragments */ 0x00, 0x00, 0x00, 0x00, /* current fragment */ 0x00, 0x01, 0x02, 0x03, /* frament data */ 0x04, 0x05, 0x06, 0x07, /* Second fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x04, 0x00, 0x00, 0x00, /* total fragments */ 0x01, 0x00, 0x00, 0x00, /* current fragment */ 0x08, 0x09, 0x0A, 0x0B, /* frament data */ 0x0C, 0x0D, 0x0E, 0x0F, /* Third fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x04, 0x00, 0x00, 0x00, /* total fragments */ 0x02, 0x00, 0x00, 0x00, /* current fragment */ 0x10, 0x11, 0x12, 0x13, /* frament data */ 0x14, 0x15, 0x16, 0x17, /* Fourth fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x18, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x04, 0x00, 0x00, 0x00, /* total fragments */ 0x03, 0x00, 0x00, 0x00, /* current fragment */ 0x18, 0x19, 0x1A, 0x1B /* frament data */ }; test_fragment_send_multiple_common ( 28, buffer, sizeof (buffer), expected_buffer, sizeof (expected_buffer)); } static void test_fragment_send_multiple_2 (void) { const guint8 buffer [] = { 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x2C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x01, 0x00, 0x00, 0x00, /* total fragments */ 0x00, 0x00, 0x00, 0x00, /* current fragment */ 0x00, 0x01, 0x02, 0x03, /* same data as in the fragments */ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; /* This buffer contains several fragments of a single message. * We don't really care about the actual data included within the fragments. */ const guint8 expected_buffer [] = { /* First fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x03, 0x00, 0x00, 0x00, /* total fragments */ 0x00, 0x00, 0x00, 0x00, /* current fragment */ 0x00, 0x01, 0x02, 0x03, /* frament data */ 0x04, 0x05, 0x06, 0x07, /* Second fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x03, 0x00, 0x00, 0x00, /* total fragments */ 0x01, 0x00, 0x00, 0x00, /* current fragment */ 0x08, 0x09, 0x0A, 0x0B, /* frament data */ 0x0C, 0x0D, 0x0E, 0x0F, /* Third fragment */ 0x07, 0x00, 0x00, 0x80, /* indications have fragments */ 0x1C, 0x00, 0x00, 0x00, /* length of this fragment */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ 0x03, 0x00, 0x00, 0x00, /* total fragments */ 0x02, 0x00, 0x00, 0x00, /* current fragment */ 0x10, 0x11, 0x12, 0x13, /* frament data */ 0x14, 0x15, 0x16, 0x17 }; test_fragment_send_multiple_common ( 28, buffer, sizeof (buffer), expected_buffer, sizeof (expected_buffer)); } int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/libmbim-glib/fragment/receive/single", test_fragment_receive_single); g_test_add_func ("/libmbim-glib/fragment/receive/multiple", test_fragment_receive_multiple); g_test_add_func ("/libmbim-glib/fragment/send/multiple-1", test_fragment_send_multiple_1); g_test_add_func ("/libmbim-glib/fragment/send/multiple-2", test_fragment_send_multiple_2); return g_test_run (); } libmbim-1.31.2-dev/src/libmbim-glib/test/test-message-builder.c000066400000000000000000002357451453630424100242740ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2023 Intel Corporation */ #include #include #include "mbim-message.h" #include "mbim-message-private.h" #include "mbim-cid.h" #include "mbim-enums.h" #include "mbim-common.h" #include "mbim-basic-connect.h" #include "mbim-ussd.h" #include "mbim-auth.h" #include "mbim-stk.h" #include "mbim-dss.h" #include "mbim-ms-host-shutdown.h" #include "mbim-ms-basic-connect-extensions.h" #include "mbim-ms-uicc-low-level-access.h" #include "mbim-google.h" static void test_message_trace (const guint8 *computed, guint32 computed_size, const guint8 *expected, guint32 expected_size) { gchar *message_str; gchar *expected_str; message_str = mbim_common_str_hex (computed, computed_size, ':'); expected_str = mbim_common_str_hex (expected, expected_size, ':'); /* Dump all message contents */ g_print ("\n" "Message str:\n" "'%s'\n" "Expected str:\n" "'%s'\n", message_str, expected_str); /* If they are different, tell which are the different bytes */ if (computed_size != expected_size || memcmp (computed, expected, expected_size)) { guint32 i; for (i = 0; i < MIN (computed_size, expected_size); i++) { if (computed[i] != expected[i]) g_print ("Byte [%u] is different (computed: 0x%02X vs expected: 0x%02x)\n", i, computed[i], expected[i]); } } g_free (message_str); g_free (expected_str); } static void test_message_printable (MbimMessage *message, guint8 mbimex_version_major, guint8 mbimex_version_minor) { g_autofree gchar *printable = NULL; printable = mbim_message_get_printable_full (message, mbimex_version_major, mbimex_version_minor, "---- ", FALSE, NULL); g_print ("\n" "Message printable:\n" "%s\n", printable); } static void test_basic_connect_pin_set_raw (void) { GError *error = NULL; MbimMessage *message; MbimMessageCommandBuilder *builder; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x50, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xa2, 0x89, 0xcc, 0x33, /* service id */ 0xbc, 0xbb, 0x8b, 0x4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf, 0x04, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x20, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x02, 0x00, 0x00, 0x00, /* pin type */ 0x00, 0x00, 0x00, 0x00, /* pin operation */ 0x18, 0x00, 0x00, 0x00, /* pin offset */ 0x08, 0x00, 0x00, 0x00, /* pin size */ 0x00, 0x00, 0x00, 0x00, /* new pin offset */ 0x00, 0x00, 0x00, 0x00, /* new pin size */ 0x31, 0x00, 0x31, 0x00, /* pin string */ 0x31, 0x00, 0x31, 0x00 }; /* PIN set message */ builder = _mbim_message_command_builder_new (1, MBIM_SERVICE_BASIC_CONNECT, MBIM_CID_BASIC_CONNECT_PIN, MBIM_MESSAGE_COMMAND_TYPE_SET); _mbim_message_command_builder_append_guint32 (builder, (guint32)MBIM_PIN_TYPE_PIN1); _mbim_message_command_builder_append_guint32 (builder, (guint32)MBIM_PIN_OPERATION_ENTER); _mbim_message_command_builder_append_string (builder, "1111"); _mbim_message_command_builder_append_string (builder, ""); message = _mbim_message_command_builder_complete (builder); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_PIN); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_basic_connect_pin_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x50, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xa2, 0x89, 0xcc, 0x33, /* service id */ 0xbc, 0xbb, 0x8b, 0x4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf, 0x04, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x20, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x02, 0x00, 0x00, 0x00, /* pin type */ 0x00, 0x00, 0x00, 0x00, /* pin operation */ 0x18, 0x00, 0x00, 0x00, /* pin offset */ 0x08, 0x00, 0x00, 0x00, /* pin size */ 0x00, 0x00, 0x00, 0x00, /* new pin offset */ 0x00, 0x00, 0x00, 0x00, /* new pin size */ 0x31, 0x00, 0x31, 0x00, /* pin string */ 0x31, 0x00, 0x31, 0x00 }; /* PIN set message */ message = mbim_message_pin_set_new (MBIM_PIN_TYPE_PIN1, MBIM_PIN_OPERATION_ENTER, "1111", "", &error); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_PIN); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_basic_connect_connect_set_raw (void) { GError *error = NULL; MbimMessage *message; MbimMessageCommandBuilder *builder; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x7C, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0C, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x4C, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* session id */ 0x01, 0x00, 0x00, 0x00, /* activation command */ 0x3C, 0x00, 0x00, 0x00, /* access string offset */ 0x10, 0x00, 0x00, 0x00, /* access string size */ 0x00, 0x00, 0x00, 0x00, /* username offset */ 0x00, 0x00, 0x00, 0x00, /* username size */ 0x00, 0x00, 0x00, 0x00, /* password offset */ 0x00, 0x00, 0x00, 0x00, /* password size */ 0x00, 0x00, 0x00, 0x00, /* compression */ 0x01, 0x00, 0x00, 0x00, /* auth protocol */ 0x01, 0x00, 0x00, 0x00, /* ip type */ 0x7E, 0x5E, 0x2A, 0x7E, /* context type */ 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E, /* data buffer */ 0x69, 0x00, 0x6E, 0x00, /* access string */ 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x74, 0x00 }; /* CONNECT set message */ builder = _mbim_message_command_builder_new (1, MBIM_SERVICE_BASIC_CONNECT, MBIM_CID_BASIC_CONNECT_CONNECT, MBIM_MESSAGE_COMMAND_TYPE_SET); _mbim_message_command_builder_append_guint32 (builder, 0x01); _mbim_message_command_builder_append_guint32 (builder, (guint32)MBIM_ACTIVATION_COMMAND_ACTIVATE); _mbim_message_command_builder_append_string (builder, "internet"); _mbim_message_command_builder_append_string (builder, ""); _mbim_message_command_builder_append_string (builder, ""); _mbim_message_command_builder_append_guint32 (builder, (guint32)MBIM_COMPRESSION_NONE); _mbim_message_command_builder_append_guint32 (builder, (guint32)MBIM_AUTH_PROTOCOL_PAP); _mbim_message_command_builder_append_guint32 (builder, (guint32)MBIM_CONTEXT_IP_TYPE_IPV4); _mbim_message_command_builder_append_uuid (builder, mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET)); message = _mbim_message_command_builder_complete (builder); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_CONNECT); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_basic_connect_connect_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x7C, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0C, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x4C, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* session id */ 0x01, 0x00, 0x00, 0x00, /* activation command */ 0x3C, 0x00, 0x00, 0x00, /* access string offset */ 0x10, 0x00, 0x00, 0x00, /* access string size */ 0x00, 0x00, 0x00, 0x00, /* username offset */ 0x00, 0x00, 0x00, 0x00, /* username size */ 0x00, 0x00, 0x00, 0x00, /* password offset */ 0x00, 0x00, 0x00, 0x00, /* password size */ 0x00, 0x00, 0x00, 0x00, /* compression */ 0x01, 0x00, 0x00, 0x00, /* auth protocol */ 0x01, 0x00, 0x00, 0x00, /* ip type */ 0x7E, 0x5E, 0x2A, 0x7E, /* context type */ 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E, /* data buffer */ 0x69, 0x00, 0x6E, 0x00, /* access string */ 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x74, 0x00 }; /* CONNECT set message */ message = (mbim_message_connect_set_new ( 0x01, MBIM_ACTIVATION_COMMAND_ACTIVATE, "internet", "", "", MBIM_COMPRESSION_NONE, MBIM_AUTH_PROTOCOL_PAP, MBIM_CONTEXT_IP_TYPE_IPV4, mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET), &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_CONNECT); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_basic_connect_service_activation_set (void) { GError *error = NULL; MbimMessage *message; const guint8 buffer [] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x38, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0E, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x08, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; /* CONNECT set message */ message = (mbim_message_service_activation_set_new ( sizeof (buffer), buffer, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_SERVICE_ACTIVATION); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_basic_connect_device_service_subscribe_list_set (void) { GError *error = NULL; MbimEventEntry **entries; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x78, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x13, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x48, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x02, 0x00, 0x00, 0x00, /* 0x00 Events count */ 0x14, 0x00, 0x00, 0x00, /* 0x04 Event 1 offset */ 0x1C, 0x00, 0x00, 0x00, /* 0x08 Event 1 length */ 0x30, 0x00, 0x00, 0x00, /* 0x0C Event 2 offset */ 0x18, 0x00, 0x00, 0x00, /* 0x10 Event 2 length */ /* data buffer, event 1 */ 0xA2, 0x89, 0xCC, 0x33, /* 0x14 Event 1, service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x02, 0x00, 0x00, 0x00, /* 0x24 Event 1, cid count */ 0x0B, 0x00, 0x00, 0x00, /* 0x28 Event 1, cid 1 */ 0x09, 0x00, 0x00, 0x00, /* 0x2C Event 1, cid 2 */ /* data buffer, event 2 */ 0x53, 0x3F, 0xBE, 0xEB, /* 0x30 Event 1, service id */ 0x14, 0xFE, 0x44, 0x67, 0x9F, 0x90, 0x33, 0xA2, 0x23, 0xE5, 0x6C, 0x3F, 0x01, 0x00, 0x00, 0x00, /* 0x40 Event 2, cid count */ 0x02, 0x00, 0x00, 0x00, /* 0x44 Event 2, cid 1 */ }; /* Device Service Subscribe List set message */ entries = g_new0 (MbimEventEntry *, 3); entries[0] = g_new (MbimEventEntry, 1); memcpy (&(entries[0]->device_service_id), MBIM_UUID_BASIC_CONNECT, sizeof (MbimUuid)); entries[0]->cids_count = 2; entries[0]->cids = g_new0 (guint32, 2); entries[0]->cids[0] = MBIM_CID_BASIC_CONNECT_SIGNAL_STATE; entries[0]->cids[1] = MBIM_CID_BASIC_CONNECT_REGISTER_STATE; entries[1] = g_new (MbimEventEntry, 1); memcpy (&(entries[1]->device_service_id), MBIM_UUID_SMS, sizeof (MbimUuid)); entries[1]->cids_count = 1; entries[1]->cids = g_new0 (guint32, 1); entries[1]->cids[0] = MBIM_CID_SMS_READ; message = (mbim_message_device_service_subscribe_list_set_new ( 2, (const MbimEventEntry *const *)entries, &error)); mbim_event_entry_array_free (entries); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_DEVICE_SERVICE_SUBSCRIBE_LIST); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_ussd_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x50, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xE5, 0x50, 0xA0, 0xC8, /* service id */ 0x5E, 0x82, 0x47, 0x9E, 0x82, 0xF7, 0x10, 0xAB, 0xF4, 0xC3, 0x35, 0x1F, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x20, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* 0x00 Action */ 0x01, 0x00, 0x00, 0x00, /* 0x04 Data coding scheme */ 0x10, 0x00, 0x00, 0x00, /* 0x08 Payload offset */ 0x10, 0x00, 0x00, 0x00, /* 0x0C Payload length */ /* data buffer, payload */ 0x01, 0x02, 0x03, 0x04, /* 0x10 Payload */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 }; const guint8 payload [] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 }; /* USSD set message */ message = (mbim_message_ussd_set_new ( MBIM_USSD_ACTION_CONTINUE, 1, /* dcs */ sizeof (payload), payload, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_USSD); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_USSD); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_auth_akap_query (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x60, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0x1D, 0x2B, 0x5F, 0xF7, /* service id */ 0x0A, 0xA1, 0x48, 0xB2, 0xAA, 0x52, 0x50, 0xF1, 0x57, 0x67, 0x17, 0x4E, 0x02, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* command_type */ 0x30, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x00, 0x01, 0x02, 0x03, /* 0x00 Rand */ 0x04, 0x05, 0x06, 0x07, /* 0x04 */ 0x08, 0x09, 0x0A, 0x0B, /* 0x08 */ 0x0C, 0x0D, 0x0E, 0x0F, /* 0x0C */ 0xFF, 0xFE, 0xFD, 0xFC, /* 0x10 Autn */ 0xFB, 0xFA, 0xF9, 0xF8, /* 0x14 */ 0xF7, 0xF6, 0xF5, 0xF4, /* 0x18 */ 0xF3, 0xF2, 0xF1, 0xF0, /* 0x1C */ 0x28, 0x00, 0x00, 0x00, /* 0x20 Network name (offset) */ 0x08, 0x00, 0x00, 0x00, /* 0x24 Network name (length) */ /* data buffer */ 0x31, 0x00, 0x31, 0x00, /* 0x28 Network name */ 0x31, 0x00, 0x31, 0x00 }; const guint8 rand [] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; const guint8 autn [] = { 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0 }; /* AKAP Auth message */ message = (mbim_message_auth_akap_query_new ( rand, autn, "1111", &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_AUTH); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_AUTH_AKAP); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_QUERY); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_stk_pac_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x50, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xD8, 0xF2, 0x01, 0x31, /* service id */ 0xFC, 0xB5, 0x4E, 0x17, 0x86, 0x02, 0xD6, 0xED, 0x38, 0x16, 0x16, 0x4C, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x20, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0 }; const guint8 pac_host_control [] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0 }; /* STK PAC set message */ message = (mbim_message_stk_pac_set_new ( pac_host_control, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_STK); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_STK_PAC); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_stk_terminal_response_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x50, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xD8, 0xF2, 0x01, 0x31, /* service id */ 0xFC, 0xB5, 0x4E, 0x17, 0x86, 0x02, 0xD6, 0xED, 0x38, 0x16, 0x16, 0x4C, 0x02, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x20, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x1C, 0x00, 0x00, 0x00, /* 0x00 Response length */ 0x04, 0x05, 0x06, 0x07, /* 0x04 Response */ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0 }; const guint8 response [] = { 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0 }; /* STK Terminal Response set message */ message = (mbim_message_stk_terminal_response_set_new ( sizeof (response), response, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_STK); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_STK_TERMINAL_RESPONSE); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_stk_envelope_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x58, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xD8, 0xF2, 0x01, 0x31, /* service id */ 0xFC, 0xB5, 0x4E, 0x17, 0x86, 0x02, 0xD6, 0xED, 0x38, 0x16, 0x16, 0x4C, 0x03, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x28, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x1C, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8 }; const guint8 databuffer [] = { 0x1C, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8 }; /* STK Envelop set message */ message = (mbim_message_stk_envelope_set_new ( sizeof (databuffer), databuffer, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_STK); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_STK_ENVELOPE); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_basic_connect_ip_packet_filters_set_none (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x38, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x17, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x08, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* 0x00 session id */ 0x00, 0x00, 0x00, 0x00 /* 0x04 packet filters count */ }; /* IP packet filters set message */ message = mbim_message_ip_packet_filters_set_new (1, 0, NULL, &error); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_IP_PACKET_FILTERS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_basic_connect_ip_packet_filters_set_one (void) { GError *error = NULL; MbimMessage *message; MbimPacketFilter **filters; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x5C, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x17, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x2C, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* 0x00 session id */ 0x01, 0x00, 0x00, 0x00, /* 0x04 packet filters count */ 0x10, 0x00, 0x00, 0x00, /* 0x08 packet filter 1 offset */ 0x1C, 0x00, 0x00, 0x00, /* 0x0C packet filter 1 length */ /* databuffer, packet filter 1 */ 0x07, 0x00, 0x00, 0x00, /* 0x10 0x00 filter size */ 0x0C, 0x00, 0x00, 0x00, /* 0x14 0x04 filter offset (from beginning of struct) */ 0x14, 0x00, 0x00, 0x00, /* 0x18 0x08 mask offset (from beginning of struct) */ 0x01, 0x02, 0x03, 0x04, /* 0x1C 0x0C filter (padding 1) */ 0x05, 0x06, 0x07, 0x00, 0xF1, 0xF2, 0xF3, 0xF4, /* 0x24 0x14 mask (padding 1) */ 0xF5, 0xF6, 0xF7, 0x00, }; const guint8 filter[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, }; const guint8 mask[] = { 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, }; filters = g_new0 (MbimPacketFilter *, 2); filters[0] = g_new (MbimPacketFilter, 1); filters[0]->filter_size = 7; filters[0]->packet_filter = g_new (guint8, 7); memcpy (filters[0]->packet_filter, filter, 7); filters[0]->packet_mask = g_new (guint8, 7); memcpy (filters[0]->packet_mask, mask, 7); /* IP packet filters set message */ message = (mbim_message_ip_packet_filters_set_new ( 1, 1, (const MbimPacketFilter * const*)filters, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_IP_PACKET_FILTERS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); mbim_packet_filter_array_free (filters); } static void test_basic_connect_ip_packet_filters_set_two (void) { GError *error = NULL; MbimMessage *message; MbimPacketFilter **filters; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x88, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x17, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x58, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* 0x00 session id */ 0x02, 0x00, 0x00, 0x00, /* 0x04 packet filters count */ 0x18, 0x00, 0x00, 0x00, /* 0x08 packet filter 1 offset */ 0x1C, 0x00, 0x00, 0x00, /* 0x0C packet filter 1 length */ 0x34, 0x00, 0x00, 0x00, /* 0x10 packet filter 2 offset */ 0x24, 0x00, 0x00, 0x00, /* 0x14 packet filter 2 length */ /* databuffer, packet filter 2 */ 0x08, 0x00, 0x00, 0x00, /* 0x18 0x00 filter size */ 0x0C, 0x00, 0x00, 0x00, /* 0x1C 0x04 filter offset (from beginning of struct) */ 0x14, 0x00, 0x00, 0x00, /* 0x20 0x08 mask offset (from beginning of struct) */ 0x01, 0x02, 0x03, 0x04, /* 0x24 0x0C filter */ 0x05, 0x06, 0x07, 0x08, 0xF1, 0xF2, 0xF3, 0xF4, /* 0x2C 0x14 mask */ 0xF5, 0xF6, 0xF7, 0xF8, /* databuffer, packet filter 2 */ 0x0C, 0x00, 0x00, 0x00, /* 0x34 0x00 filter size */ 0x0C, 0x00, 0x00, 0x00, /* 0x38 0x04 filter offset (from beginning of struct) */ 0x18, 0x00, 0x00, 0x00, /* 0x3C 0x08 mask offset (from beginning of struct) */ 0x01, 0x02, 0x03, 0x04, /* 0x40 0x0C filter */ 0x05, 0x06, 0x07, 0x08, 0x05, 0x06, 0x07, 0x08, 0xF1, 0xF2, 0xF3, 0xF4, /* 0x4C 0x18 mask */ 0xF5, 0xF6, 0xF7, 0xF8, 0xF5, 0xF6, 0xF7, 0xF8, }; const guint8 filter1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }; const guint8 mask1[] = { 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, }; const guint8 filter2[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x05, 0x06, 0x07, 0x08, }; const guint8 mask2[] = { 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF5, 0xF6, 0xF7, 0xF8, }; filters = g_new0 (MbimPacketFilter *, 3); filters[0] = g_new (MbimPacketFilter, 1); filters[0]->filter_size = 8; filters[0]->packet_filter = g_new (guint8, 8); memcpy (filters[0]->packet_filter, filter1, 8); filters[0]->packet_mask = g_new (guint8, 8); memcpy (filters[0]->packet_mask, mask1, 8); filters[1] = g_new (MbimPacketFilter, 1); filters[1]->filter_size = 12; filters[1]->packet_filter = g_new (guint8, 12); memcpy (filters[1]->packet_filter, filter2, 12); filters[1]->packet_mask = g_new (guint8, 12); memcpy (filters[1]->packet_mask, mask2, 12); /* IP packet filters set message */ message = (mbim_message_ip_packet_filters_set_new ( 1, 2, (const MbimPacketFilter * const*)filters, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_IP_PACKET_FILTERS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); mbim_packet_filter_array_free (filters); } static void test_dss_connect_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x48, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xC0, 0x8A, 0x26, 0xDD, /* service id */ 0x77, 0x18, 0x43, 0x82, 0x84, 0x82, 0x6E, 0x0D, 0x58, 0x3C, 0x4D, 0x0E, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x18, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x02, 0x03, 0x04, /* service id */ 0xFF, 0xFF, 0xBB, 0xBB, 0xFF, 0xCC, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xFF, 0x00, 0x00, 0x00, /* dss session id */ 0x01, 0x00, 0x00, 0x00 /* dss link state */ }; static const MbimUuid another_uuid = { .a = { 0x01, 0x02, 0x03, 0x04 }, .b = { 0xFF, 0xFF }, .c = { 0xBB, 0xBB }, .d = { 0xFF, 0xCC }, .e = { 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5 } }; /* IP packet filters set message */ message = (mbim_message_dss_connect_set_new ( &another_uuid, 255, MBIM_DSS_LINK_STATE_ACTIVATE, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_DSS); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_DSS_CONNECT); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_basic_connect_multicarrier_providers_set (void) { GError *error = NULL; MbimMessage *message; MbimProvider **providers; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0xB4, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x18, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x84, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x02, 0x00, 0x00, 0x00, /* 0x00 providers count */ 0x14, 0x00, 0x00, 0x00, /* 0x04 provider 0 offset */ 0x38, 0x00, 0x00, 0x00, /* 0x08 provider 0 length */ 0x4C, 0x00, 0x00, 0x00, /* 0x0C provider 1 offset */ 0x38, 0x00, 0x00, 0x00, /* 0x10 provider 1 length */ /* data buffer... struct provider 0 */ 0x20, 0x00, 0x00, 0x00, /* 0x14 [0x00] id offset */ 0x0A, 0x00, 0x00, 0x00, /* 0x18 [0x04] id length */ 0x08, 0x00, 0x00, 0x00, /* 0x1C [0x08] state */ 0x2C, 0x00, 0x00, 0x00, /* 0x20 [0x0C] name offset */ 0x0C, 0x00, 0x00, 0x00, /* 0x24 [0x10] name length */ 0x01, 0x00, 0x00, 0x00, /* 0x28 [0x14] cellular class */ 0x0B, 0x00, 0x00, 0x00, /* 0x2C [0x18] rssi */ 0x00, 0x00, 0x00, 0x00, /* 0x30 [0x1C] error rate */ 0x32, 0x00, 0x31, 0x00, /* 0x34 [0x20] id string (10 bytes) */ 0x34, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x72, 0x00, /* 0x40 [0x2C] name string (12 bytes) */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, /* data buffer... struct provider 1 */ 0x20, 0x00, 0x00, 0x00, /* 0x4C [0x00] id offset */ 0x0A, 0x00, 0x00, 0x00, /* 0x50 [0x04] id length */ 0x19, 0x00, 0x00, 0x00, /* 0x51 [0x08] state */ 0x2C, 0x00, 0x00, 0x00, /* 0x54 [0x0C] name offset */ 0x0C, 0x00, 0x00, 0x00, /* 0x58 [0x10] name length */ 0x01, 0x00, 0x00, 0x00, /* 0x5C [0x14] cellular class */ 0x0B, 0x00, 0x00, 0x00, /* 0x60 [0x18] rssi */ 0x00, 0x00, 0x00, 0x00, /* 0x64 [0x1C] error rate */ 0x32, 0x00, 0x31, 0x00, /* 0x68 [0x20] id string (10 bytes) */ 0x34, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x72, 0x00, /* 0x74 [0x2C] name string (12 bytes) */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00 }; providers = g_new0 (MbimProvider *, 3); providers[0] = g_new0 (MbimProvider, 1); providers[0]->provider_id = g_strdup ("21403"); providers[0]->provider_name = g_strdup ("Orange"); providers[0]->provider_state = MBIM_PROVIDER_STATE_VISIBLE; providers[0]->cellular_class = MBIM_CELLULAR_CLASS_GSM; providers[0]->rssi = 11; providers[0]->error_rate = 0; providers[1] = g_new0 (MbimProvider, 1); providers[1]->provider_id = g_strdup ("21403"); providers[1]->provider_name = g_strdup ("Orange"); providers[1]->provider_state = (MBIM_PROVIDER_STATE_HOME | MBIM_PROVIDER_STATE_VISIBLE | MBIM_PROVIDER_STATE_REGISTERED); providers[1]->cellular_class = MBIM_CELLULAR_CLASS_GSM; providers[1]->rssi = 11; providers[1]->error_rate = 0; /* Multicarrier providers set message */ message = (mbim_message_multicarrier_providers_set_new ( 2, (const MbimProvider *const *)providers, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_MULTICARRIER_PROVIDERS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); mbim_provider_array_free (providers); } static void test_ms_host_shutdown_notify_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x30, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0x88, 0x3B, 0x7C, 0x26, /* service id */ 0x98, 0x5F, 0x43, 0xFA, 0x98, 0x04, 0x27, 0xD7, 0xFB, 0x80, 0x95, 0x9C, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x00, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ }; /* MS Host Shutdown set message */ message = mbim_message_ms_host_shutdown_notify_set_new (&error); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_MS_HOST_SHUTDOWN); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); mbim_message_unref (message); } static void test_ms_basic_connect_extensions_registration_parameters_set_0_unnamed_tlvs (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) message = NULL; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x44, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x11, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x14, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* mico mode */ 0x00, 0x00, 0x00, 0x00, /* drx cycle */ 0x00, 0x00, 0x00, 0x00, /* ladn info */ 0x01, 0x00, 0x00, 0x00, /* pdu hint */ 0x01, 0x00, 0x00, 0x00, /* re register if needed */ /* no unnamed TLVs */ }; message = (mbim_message_ms_basic_connect_extensions_v3_registration_parameters_set_new ( MBIM_MICO_MODE_DISABLED, MBIM_DRX_CYCLE_NOT_SPECIFIED, MBIM_LADN_INFO_NOT_NEEDED, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY, TRUE, NULL, /* 0 unnamed ies */ &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 3, 0); } static void test_ms_basic_connect_extensions_registration_parameters_set_1_unnamed_tlv (void) { MbimTlv *tlv; GList *tlv_list = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) message = NULL; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x58, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x11, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x28, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* mico mode */ 0x00, 0x00, 0x00, 0x00, /* drx cycle */ 0x00, 0x00, 0x00, 0x00, /* ladn info */ 0x01, 0x00, 0x00, 0x00, /* pdu hint */ 0x01, 0x00, 0x00, 0x00, /* re register if needed */ /* First unnamed TLV */ 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, }; tlv = mbim_tlv_string_new ("Orange", &error); g_assert_no_error (error); g_assert (tlv); tlv_list = g_list_append (tlv_list, tlv); message = (mbim_message_ms_basic_connect_extensions_v3_registration_parameters_set_new ( MBIM_MICO_MODE_DISABLED, MBIM_DRX_CYCLE_NOT_SPECIFIED, MBIM_LADN_INFO_NOT_NEEDED, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY, TRUE, tlv_list, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); g_list_free_full (tlv_list, (GDestroyNotify)mbim_tlv_unref); test_message_printable (message, 3, 0); } static void test_ms_basic_connect_extensions_registration_parameters_set_3_unnamed_tlvs (void) { MbimTlv *tlv; GList *tlv_list = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) message = NULL; const guint8 pco[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B }; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x80, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x11, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x50, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* mico mode */ 0x00, 0x00, 0x00, 0x00, /* drx cycle */ 0x00, 0x00, 0x00, 0x00, /* ladn info */ 0x01, 0x00, 0x00, 0x00, /* pdu hint */ 0x01, 0x00, 0x00, 0x00, /* re register if needed */ /* First unnamed TLV */ 0x0A, 0x00, 0x00, 0x02, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, padding 2 */ 0x0A, 0x00, 0x00, 0x00, /* TLV data length */ 0x61, 0x00, 0x62, 0x00, /* TLV data string */ 0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x00, 0x00, /* Second unnamed TLV */ 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, /* Third unnamed TLV */ 0x0D, 0x00, 0x00, 0x01, /* TLV type MBIM_TLV_TYPE_PCO, padding 1 */ 0x0B, 0x00, 0x00, 0x00, /* TLV data length */ 0x01, 0x02, 0x03, 0x04, /* TLV data bytes */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x00, }; tlv = mbim_tlv_string_new ("abcde", &error); g_assert_no_error (error); g_assert (tlv); tlv_list = g_list_append (tlv_list, tlv); tlv = mbim_tlv_string_new ("Orange", &error); g_assert_no_error (error); g_assert (tlv); tlv_list = g_list_append (tlv_list, tlv); tlv = mbim_tlv_new (MBIM_TLV_TYPE_PCO, pco, sizeof (pco)); g_assert (tlv); tlv_list = g_list_append (tlv_list, tlv); message = (mbim_message_ms_basic_connect_extensions_v3_registration_parameters_set_new ( MBIM_MICO_MODE_DISABLED, MBIM_DRX_CYCLE_NOT_SPECIFIED, MBIM_LADN_INFO_NOT_NEEDED, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY, TRUE, tlv_list, &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); g_list_free_full (tlv_list, (GDestroyNotify)mbim_tlv_unref); test_message_printable (message, 3, 0); } static void test_ms_basic_connect_v3_connect_set (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x80, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0C, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x50, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* session id */ 0x01, 0x00, 0x00, 0x00, /* activation command */ 0x00, 0x00, 0x00, 0x00, /* compression */ 0x01, 0x00, 0x00, 0x00, /* auth protocol */ 0x01, 0x00, 0x00, 0x00, /* ip type */ 0x7E, 0x5E, 0x2A, 0x7E, /* context type */ 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E, 0x01, 0x00, 0x00, 0x00, /* media preference */ 0x0A, 0x00, 0x00, 0x00, /* access string */ 0x10, 0x00, 0x00, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x74, 0x00, 0x0A, 0x00, 0x00, 0x00, /* username */ 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, /* password */ 0x00, 0x00, 0x00, 0x00, /* no unnamed TLVs */ }; /* CONNECT set message */ message = (mbim_message_ms_basic_connect_v3_connect_set_new ( 0x01, MBIM_ACTIVATION_COMMAND_ACTIVATE, MBIM_COMPRESSION_NONE, MBIM_AUTH_PROTOCOL_PAP, MBIM_CONTEXT_IP_TYPE_IPV4, mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET), MBIM_ACCESS_MEDIA_TYPE_3GPP, "internet", "", "", NULL, /* no unnamed ies */ &error)); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_CONNECT); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 3, 0); mbim_message_unref (message); } static void test_ms_uicc_low_level_access_terminal_capability (void) { GError *error = NULL; MbimMessage *message; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x50, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xC2, 0xF6, 0x58, 0x8E, /* service id */ 0xF0, 0x37, 0x4B, 0xC9, 0x86, 0x65, 0xF4, 0xD4, 0x4B, 0xD0, 0x93, 0x67, 0x05, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command_type */ 0x20, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x02, 0x00, 0x00, 0x00, /* terminal capability count */ 0x14, 0x00, 0x00, 0x00, /* terminal capability 1 offset */ 0x05, 0x00, 0x00, 0x00, /* terminal capability 1 length */ 0x1C, 0x00, 0x00, 0x00, /* terminal capability 2 offset */ 0x03, 0x00, 0x00, 0x00, /* terminal capability 2 length */ 0x0A, 0x0B, 0x0C, 0x0D, /* terminal capability data 1 */ 0x0A, 0x00, 0x00, 0x00, /* struct padding */ 0xA0, 0xB0, 0xC0, /* terminal capability data 2 */ 0x00 /* struct padding */ }; const guint8 terminal_capability_data_1[] = { 0x0A, 0x0B, 0x0C, 0x0D, 0x0A, }; const guint8 terminal_capability_data_2[] = { 0xA0, 0xB0, 0xC0 }; MbimTerminalCapabilityInfo *terminal_capability_infos[2]; terminal_capability_infos[0] = g_new0 (MbimTerminalCapabilityInfo, 1); terminal_capability_infos[0]->terminal_capability_data_size = sizeof (terminal_capability_data_1); terminal_capability_infos[0]->terminal_capability_data = g_memdup (terminal_capability_data_1, sizeof (terminal_capability_data_1)); terminal_capability_infos[1] = g_new0 (MbimTerminalCapabilityInfo, 1); terminal_capability_infos[1]->terminal_capability_data_size = sizeof (terminal_capability_data_2); terminal_capability_infos[1]->terminal_capability_data = g_memdup (terminal_capability_data_2, sizeof (terminal_capability_data_2)); message = mbim_message_ms_uicc_low_level_access_terminal_capability_set_new ( G_N_ELEMENTS (terminal_capability_infos), (const MbimTerminalCapabilityInfo *const *)terminal_capability_infos, &error); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_TERMINAL_CAPABILITY); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); g_free (terminal_capability_infos[0]->terminal_capability_data); g_free (terminal_capability_infos[0]); g_free (terminal_capability_infos[1]->terminal_capability_data); g_free (terminal_capability_infos[1]); } static void test_google_carrier_lock_set (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) message = NULL; const guint8 expected_message [] = { /* header */ 0x03, 0x00, 0x00, 0x00, /* type */ 0x40, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0x3E, 0x1E, 0x92, 0xCF, /* service id */ 0xC5, 0x3D, 0x4F, 0x14, 0x85, 0xD0, 0xA8, 0x6A, 0xD9, 0xE1, 0x22, 0x45, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x01, 0x00, 0x00, 0x00, /* command type */ 0x10, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x0A, 0x00, 0x00, 0x00, /* data buffer */ 0x56, 0x24, 0x46, 0x95, 0xAB, 0xCD, 0x25, 0x59, 0x14, 0x35, 0x00, 0x00, }; const guint8 data [] = { 0x56, 0x24, 0x46, 0x95, 0xAB, 0xCD, 0x25, 0x59, 0x14, 0x35, }; message = mbim_message_google_carrier_lock_set_new ( sizeof (data), data, &error); g_assert_no_error (error); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); mbim_message_set_transaction_id (message, 1); test_message_trace ((const guint8 *)((GByteArray *)message)->data, ((GByteArray *)message)->len, expected_message, sizeof (expected_message)); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, sizeof (expected_message)); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_GOOGLE); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_GOOGLE_CARRIER_LOCK); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_SET); g_assert_cmpuint (((GByteArray *)message)->len, ==, sizeof (expected_message)); g_assert (memcmp (((GByteArray *)message)->data, expected_message, sizeof (expected_message)) == 0); test_message_printable (message, 1, 0); } int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); #define PREFIX "/libmbim-glib/message/builder" g_test_add_func (PREFIX "/basic-connect/pin/set/raw", test_basic_connect_pin_set_raw); g_test_add_func (PREFIX "/basic-connect/pin/set", test_basic_connect_pin_set); g_test_add_func (PREFIX "/basic-connect/connect/set/raw", test_basic_connect_connect_set_raw); g_test_add_func (PREFIX "/basic-connect/connect/set", test_basic_connect_connect_set); g_test_add_func (PREFIX "/basic-connect/service-activation/set", test_basic_connect_service_activation_set); g_test_add_func (PREFIX "/basic-connect/device-service-subscribe-list/set", test_basic_connect_device_service_subscribe_list_set); g_test_add_func (PREFIX "/ussd/set", test_ussd_set); g_test_add_func (PREFIX "/auth/akap/query", test_auth_akap_query); g_test_add_func (PREFIX "/stk/pac/set", test_stk_pac_set); g_test_add_func (PREFIX "/stk/terminal-response/set", test_stk_terminal_response_set); g_test_add_func (PREFIX "/stk/envelope/set", test_stk_envelope_set); g_test_add_func (PREFIX "/basic-connect/ip-packet-filters/set/none", test_basic_connect_ip_packet_filters_set_none); g_test_add_func (PREFIX "/basic-connect/ip-packet-filters/set/one", test_basic_connect_ip_packet_filters_set_one); g_test_add_func (PREFIX "/basic-connect/ip-packet-filters/set/two", test_basic_connect_ip_packet_filters_set_two); g_test_add_func (PREFIX "/dss/connect/set", test_dss_connect_set); g_test_add_func (PREFIX "/basic-connect/multicarrier-providers/set", test_basic_connect_multicarrier_providers_set); g_test_add_func (PREFIX "/ms-host-shutdown/notify/set", test_ms_host_shutdown_notify_set); g_test_add_func (PREFIX "/ms-basic-connect-extensions/registration-parameters/set/0-unnamed-tlvs", test_ms_basic_connect_extensions_registration_parameters_set_0_unnamed_tlvs); g_test_add_func (PREFIX "/ms-basic-connect-extensions/registration-parameters/set/1-unnamed-tlv", test_ms_basic_connect_extensions_registration_parameters_set_1_unnamed_tlv); g_test_add_func (PREFIX "/ms-basic-connect-extensions/registration-parameters/set/3-unnamed-tlvs", test_ms_basic_connect_extensions_registration_parameters_set_3_unnamed_tlvs); g_test_add_func (PREFIX "/ms-basic-connect-v3/connect/set", test_ms_basic_connect_v3_connect_set); g_test_add_func (PREFIX "/ms-uicc-low-level-access/terminal-capability", test_ms_uicc_low_level_access_terminal_capability); g_test_add_func (PREFIX "/google/carrier-lock/set", test_google_carrier_lock_set); #undef PREFIX return g_test_run (); } libmbim-1.31.2-dev/src/libmbim-glib/test/test-message-fuzzer-samples.c000066400000000000000000000105011453630424100256120ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2023 Google, Inc. */ #include #include #include #include /* Include the whole fuzzer test file */ int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size); #include "test-message-fuzzer.c" static void test_fuzzer_sample_basic (void) { const guint8 data[] = { 0x3 }; g_assert_cmpuint (LLVMFuzzerTestOneInput (data, G_N_ELEMENTS (data)), ==, 0); } static void test_fuzzer_sample_invalid_array_size (void) { const guint8 data[] = { 0x3,0x0,0x0,0x80,0x46,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x68,0x22,0x3d,0x4,0x9f, 0x6c,0x4e,0xf,0x82,0x2d,0x28,0x44,0x1f,0xb7,0x23,0x40, 0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x5,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2e,0xb7,0x23, 0x40,0x59,0x67,0xbd,0xcc,0x7f,0xd2,0x49,0xa2,0x9f,0x5c, 0xb2,0xe7,0xe,0x52,0x7d,0xb3,0x1,0x0,0x0,0x0,0x23,0x40, 0x1,0x0,0x0,0x0,0x0,0x3,0x0,0x0,0x9 }; g_assert_cmpuint (LLVMFuzzerTestOneInput (data, G_N_ELEMENTS (data)), ==, 0); } static void test_fuzzer_sample_invalid_offset_unbound_bytearray (void) { const guint8 data[] = { 0x3,0x0,0x0,0x80,0x31,0x0,0x0,0x0,0x0,0x4c,0x0,0x0,0x1, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc2,0xf6,0x58,0x8e,0xf0,0x37, 0x4b,0xc9,0x86,0x65,0xf4,0xd4,0x4b,0xd0,0x93,0x67,0x5,0x0, 0x0,0x0,0x4c,0x0,0x5d,0x0,0x1,0x0,0x0,0x0,0x0,0x4,0x0,0x0, 0x80,0x0,0x0,0x0,0xa0,0x0,0x0,0x1,0x0,0x80,0x32 }; g_assert_cmpuint (LLVMFuzzerTestOneInput (data, G_N_ELEMENTS (data)), ==, 0); } static void test_fuzzer_sample_ms_struct_array_with_string (void) { const guint8 data[] = { 0x3,0x0,0x0,0x80,0x54,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x3d,0x1,0xdc,0xc5,0xfe,0xf5,0x4d, 0x5,0xd,0x3a,0xbe,0xf7,0x5,0x8e,0x9a,0xaf,0xb,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x40,0x0,0x7a,0x1d,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x12,0x0, 0x0,0x0,0x0,0x0,0x0,0x7a,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0xa2,0x89,0xcc,0x33,0xbc,0xbb,0x8b,0x4f, 0xb6,0xb0,0x13,0x3e,0xc2,0xaa,0xe6,0xdf,0x1,0x0,0x0,0x0,0x0, 0x0,0x2,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xa4,0xa4,0x3, 0x0,0x0,0x0,0x24,0x0,0x0,0xfe,0xf5,0x4d,0x5,0xd,0x3a,0xbe, 0xf7,0x5,0x8e,0x9a,0xaf,0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1, 0x0,0x0,0x0,0x0,0x40,0x0,0x7a,0x1d,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x12,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x15,0x0,0x0,0x0,0x80,0xad,0xa4,0x9b,0x9b,0x9b,0xbd, 0xbd }; g_assert_cmpuint (LLVMFuzzerTestOneInput (data, G_N_ELEMENTS (data)), ==, 0); } static void test_fuzzer_sample_ref_struct_array_with_unsized_bytearrays (void) { const guint8 data[] = { 0x3,0x0,0x0,0x80,0x33,0x0,0x0,0x0,0x0,0x0,0x55,0x8,0x1,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0xc2,0xf6,0x58,0x8e,0xf0,0x37,0x4b,0xc9,0x86, 0x65,0xf4,0xd4,0x4b,0xd0,0x93,0x67,0x5,0x0,0x0,0x0,0x32,0x0,0x0, 0x0,0x1,0x0,0x0,0x0,0x0,0x1,0x0,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0xb0,0x13,0x12,0x0,0xca,0xca,0xca,0x0,0x0,0xe8 }; g_assert_cmpuint (LLVMFuzzerTestOneInput (data, G_N_ELEMENTS (data)), ==, 0); } int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); #define PREFIX "/libmbim-glib/message/fuzzer-samples/" g_test_add_func (PREFIX "basic", test_fuzzer_sample_basic); g_test_add_func (PREFIX "invalid-arraysize", test_fuzzer_sample_invalid_array_size); g_test_add_func (PREFIX "invalid-offset-unbound-bytearray", test_fuzzer_sample_invalid_offset_unbound_bytearray); g_test_add_func (PREFIX "ms-struct-array-with-string", test_fuzzer_sample_ms_struct_array_with_string); g_test_add_func (PREFIX "ref-struct-array-with-unsized-bytearrays", test_fuzzer_sample_ref_struct_array_with_unsized_bytearrays); #undef PREFIX return g_test_run (); } libmbim-1.31.2-dev/src/libmbim-glib/test/test-message-fuzzer.c000066400000000000000000000023061453630424100241540ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2022 Google, Inc. */ #include #include #include #include #include "mbim-message.h" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; guint mbimex_version_major; if (!size) return 0; message = mbim_message_new (data, size); if (!mbim_message_validate (message, &error)) { g_printerr ("error: %s\n", error->message); return 0; } /* We support printing as MBIMEx 1, 2 and 3 */ for (mbimex_version_major = 1; mbimex_version_major <= 3; mbimex_version_major++) { g_autofree gchar *printable = NULL; g_autoptr(GError) inner_error = NULL; printable = mbim_message_get_printable_full (message, mbimex_version_major, 0, "---- ", FALSE, &inner_error); if (!printable) g_printerr ("error: %s\n", inner_error->message); else g_print ("%s\n", printable); } return 0; } libmbim-1.31.2-dev/src/libmbim-glib/test/test-message-parser.c000066400000000000000000004240661453630424100241360ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2014 Aleksander Morgado */ #include #include #include "mbim-basic-connect.h" #include "mbim-sms.h" #include "mbim-ussd.h" #include "mbim-auth.h" #include "mbim-stk.h" #include "mbim-ms-firmware-id.h" #include "mbim-ms-basic-connect-extensions.h" #include "mbim-ms-uicc-low-level-access.h" #include "mbim-google.h" #include "mbim-message.h" #include "mbim-tlv.h" #include "mbim-cid.h" #include "mbim-common.h" #include "mbim-error-types.h" static void test_message_trace (const guint8 *computed, guint32 computed_size, const guint8 *expected, guint32 expected_size) { g_autofree gchar *message_str = NULL; g_autofree gchar *expected_str = NULL; message_str = mbim_common_str_hex (computed, computed_size, ':'); expected_str = mbim_common_str_hex (expected, expected_size, ':'); /* Dump all message contents */ g_print ("\n" "Message str:\n" "'%s'\n" "Expected str:\n" "'%s'\n", message_str, expected_str); /* If they are different, tell which are the different bytes */ if (computed_size != expected_size || memcmp (computed, expected, expected_size)) { guint32 i; for (i = 0; i < MIN (computed_size, expected_size); i++) { if (computed[i] != expected[i]) g_print ("Byte [%u] is different (computed: 0x%02X vs expected: 0x%02x)\n", i, computed[i], expected[i]); } } } static void test_message_printable (MbimMessage *message, guint8 mbimex_version_major, guint8 mbimex_version_minor) { g_autofree gchar *printable = NULL; printable = mbim_message_get_printable_full (message, mbimex_version_major, mbimex_version_minor, "---- ", FALSE, NULL); g_print ("\n" "Message printable:\n" "%s\n", printable); } static void test_basic_connect_visible_providers (void) { guint32 n_providers; g_autoptr(GError) error = NULL; g_autoptr(MbimProviderArray) providers = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0xB4, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x08, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x84, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x02, 0x00, 0x00, 0x00, /* 0x00 providers count */ 0x14, 0x00, 0x00, 0x00, /* 0x04 provider 0 offset */ 0x38, 0x00, 0x00, 0x00, /* 0x08 provider 0 length */ 0x4C, 0x00, 0x00, 0x00, /* 0x0C provider 1 offset */ 0x38, 0x00, 0x00, 0x00, /* 0x10 provider 1 length */ /* data buffer... struct provider 0 */ 0x20, 0x00, 0x00, 0x00, /* 0x14 [0x00] id offset */ 0x0A, 0x00, 0x00, 0x00, /* 0x18 [0x04] id length */ 0x08, 0x00, 0x00, 0x00, /* 0x1C [0x08] state */ 0x2C, 0x00, 0x00, 0x00, /* 0x20 [0x0C] name offset */ 0x0C, 0x00, 0x00, 0x00, /* 0x24 [0x10] name length */ 0x01, 0x00, 0x00, 0x00, /* 0x28 [0x14] cellular class */ 0x0B, 0x00, 0x00, 0x00, /* 0x2C [0x18] rssi */ 0x00, 0x00, 0x00, 0x00, /* 0x30 [0x1C] error rate */ 0x32, 0x00, 0x31, 0x00, /* 0x34 [0x20] id string (10 bytes) */ 0x34, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x72, 0x00, /* 0x40 [0x2C] name string (12 bytes) */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, /* data buffer... struct provider 1 */ 0x20, 0x00, 0x00, 0x00, /* 0x4C [0x00] id offset */ 0x0A, 0x00, 0x00, 0x00, /* 0x50 [0x04] id length */ 0x19, 0x00, 0x00, 0x00, /* 0x51 [0x08] state */ 0x2C, 0x00, 0x00, 0x00, /* 0x54 [0x0C] name offset */ 0x0C, 0x00, 0x00, 0x00, /* 0x58 [0x10] name length */ 0x01, 0x00, 0x00, 0x00, /* 0x5C [0x14] cellular class */ 0x0B, 0x00, 0x00, 0x00, /* 0x60 [0x18] rssi */ 0x00, 0x00, 0x00, 0x00, /* 0x64 [0x1C] error rate */ 0x32, 0x00, 0x31, 0x00, /* 0x68 [0x20] id string (10 bytes) */ 0x34, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x72, 0x00, /* 0x74 [0x2C] name string (12 bytes) */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_visible_providers_response_parse ( response, &n_providers, &providers, &error)); g_assert_no_error (error); g_assert_cmpuint (n_providers, ==, 2); /* Provider [0] * Provider ID: '21403' * Provider Name: 'Orange' * State: 'visible' * Cellular class: 'gsm' * RSSI: '11' * Error rate: '0' */ g_assert_cmpstr (providers[0]->provider_id, ==, "21403"); g_assert_cmpstr (providers[0]->provider_name, ==, "Orange"); g_assert_cmpuint (providers[0]->provider_state, ==, MBIM_PROVIDER_STATE_VISIBLE); g_assert_cmpuint (providers[0]->cellular_class, ==, MBIM_CELLULAR_CLASS_GSM); g_assert_cmpuint (providers[0]->rssi, ==, 11); g_assert_cmpuint (providers[0]->error_rate, ==, 0); /* Provider [1]: * Provider ID: '21403' * Provider Name: 'Orange' * State: 'home, visible, registered' * Cellular class: 'gsm' * RSSI: '11' * Error rate: '0' */ g_assert_cmpstr (providers[1]->provider_id, ==, "21403"); g_assert_cmpstr (providers[1]->provider_name, ==, "Orange"); g_assert_cmpuint (providers[1]->provider_state, ==, (MBIM_PROVIDER_STATE_HOME | MBIM_PROVIDER_STATE_VISIBLE | MBIM_PROVIDER_STATE_REGISTERED)); g_assert_cmpuint (providers[1]->cellular_class, ==, MBIM_CELLULAR_CLASS_GSM); g_assert_cmpuint (providers[1]->rssi, ==, 11); g_assert_cmpuint (providers[1]->error_rate, ==, 0); } static void test_basic_connect_subscriber_ready_status (void) { MbimSubscriberReadyState ready_state; MbimReadyInfoFlag ready_info; guint32 telephone_numbers_count; g_autofree gchar *subscriber_id = NULL; g_autofree gchar *sim_iccid = NULL; g_auto(GStrv) telephone_numbers = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0xB4, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x02, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x84, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* 0x00 ready state */ 0x5C, 0x00, 0x00, 0x00, /* 0x04 subscriber id (offset) */ 0x1E, 0x00, 0x00, 0x00, /* 0x08 subscriber id (size) */ 0x7C, 0x00, 0x00, 0x00, /* 0x0C sim iccid (offset) */ 0x28, 0x00, 0x00, 0x00, /* 0x10 sim iccid (size) */ 0x00, 0x00, 0x00, 0x00, /* 0x14 ready info */ 0x02, 0x00, 0x00, 0x00, /* 0x18 telephone numbers count */ 0x2C, 0x00, 0x00, 0x00, /* 0x1C telephone number #1 (offset) */ 0x16, 0x00, 0x00, 0x00, /* 0x20 telephone number #1 (size) */ 0x44, 0x00, 0x00, 0x00, /* 0x24 telephone number #2 (offset) */ 0x16, 0x00, 0x00, 0x00, /* 0x28 telephone number #2 (size) */ /* data buffer */ 0x31, 0x00, 0x31, 0x00, /* 0x2C telephone number #1 (data) */ 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x00, 0x00, /* last 2 bytes are padding */ 0x30, 0x00, 0x30, 0x00, /* 0x44 telephone number #2 (data) */ 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, /* last 2 bytes are padding */ 0x33, 0x00, 0x31, 0x00, /* 0x5C subscriber id (data) */ 0x30, 0x00, 0x34, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x31, 0x00, 0x31, 0x00, 0x30, 0x00, 0x37, 0x00, 0x36, 0x00, 0x31, 0x00, 0x00, 0x00, /* last 2 bytes are padding */ 0x38, 0x00, 0x39, 0x00, /* 0x7C sim iccid (data) */ 0x30, 0x00, 0x31, 0x00, 0x30, 0x00, 0x31, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x35, 0x00, 0x34, 0x00, 0x36, 0x00, 0x30, 0x00, 0x31, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x36, 0x00, 0x31, 0x00, 0x32, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_subscriber_ready_status_response_parse ( response, &ready_state, &subscriber_id, &sim_iccid, &ready_info, &telephone_numbers_count, &telephone_numbers, &error)); g_assert_no_error (error); g_assert_cmpuint (ready_state, ==, MBIM_SUBSCRIBER_READY_STATE_INITIALIZED); g_assert_cmpstr (subscriber_id, ==, "310410000110761"); g_assert_cmpstr (sim_iccid, ==, "89010104054601100612"); g_assert_cmpuint (ready_info, ==, 0); g_assert_cmpuint (telephone_numbers_count, ==, 2); g_assert_cmpstr (telephone_numbers[0], ==, "11111111111"); g_assert_cmpstr (telephone_numbers[1], ==, "00000000000"); g_assert (telephone_numbers[2] == NULL); } static void test_basic_connect_device_caps (void) { MbimDeviceType device_type; MbimCellularClass cellular_class; MbimVoiceClass voice_class; MbimSimClass sim_class; MbimDataClass data_class; MbimSmsCaps sms_caps; MbimCtrlCaps ctrl_caps; guint32 max_sessions; g_autofree gchar *custom_data_class = NULL; g_autofree gchar *device_id = NULL; g_autofree gchar *firmware_info = NULL; g_autofree gchar *hardware_info = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { 0x03, 0x00, 0x00, 0x80, 0xD0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x89, 0xCC, 0x33, 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x48, 0x00, 0x53, 0x00, 0x50, 0x00, 0x41, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x33, 0x00, 0x35, 0x00, 0x33, 0x00, 0x36, 0x00, 0x31, 0x00, 0x33, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x38, 0x00, 0x30, 0x00, 0x34, 0x00, 0x36, 0x00, 0x32, 0x00, 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x38, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x39, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x43, 0x00, 0x50, 0x00, 0x31, 0x00, 0x45, 0x00, 0x33, 0x00, 0x36, 0x00, 0x37, 0x00, 0x55, 0x00, 0x4D, 0x00, 0x00, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_device_caps_response_parse ( response, &device_type, &cellular_class, &voice_class, &sim_class, &data_class, &sms_caps, &ctrl_caps, &max_sessions, &custom_data_class, &device_id, &firmware_info, &hardware_info, &error)); g_assert_no_error (error); g_assert_cmpuint (device_type, ==, MBIM_DEVICE_TYPE_REMOVABLE); g_assert_cmpuint (cellular_class, ==, MBIM_CELLULAR_CLASS_GSM); g_assert_cmpuint (sim_class, ==, MBIM_SIM_CLASS_REMOVABLE); g_assert_cmpuint (data_class, ==, (MBIM_DATA_CLASS_GPRS | MBIM_DATA_CLASS_EDGE | MBIM_DATA_CLASS_UMTS | MBIM_DATA_CLASS_HSDPA | MBIM_DATA_CLASS_HSUPA | MBIM_DATA_CLASS_CUSTOM)); g_assert_cmpuint (sms_caps, ==, (MBIM_SMS_CAPS_PDU_RECEIVE | MBIM_SMS_CAPS_PDU_SEND)); g_assert_cmpuint (ctrl_caps, ==, MBIM_CTRL_CAPS_REG_MANUAL); g_assert_cmpuint (max_sessions, ==, 1); g_assert_cmpstr (custom_data_class, ==, "HSPA+"); g_assert_cmpstr (device_id, ==, "353613048804622"); g_assert_cmpstr (firmware_info, ==, "11.810.09.00.00"); g_assert_cmpstr (hardware_info, ==, "CP1E367UM"); } static void test_basic_connect_ip_configuration (void) { guint32 session_id; MbimIPConfigurationAvailableFlag ipv4configurationavailable; MbimIPConfigurationAvailableFlag ipv6configurationavailable; guint32 ipv4addresscount; guint32 ipv6addresscount; const MbimIPv4 *ipv4gateway; const MbimIPv6 *ipv6gateway; guint32 ipv4dnsservercount; guint32 ipv6dnsservercount; guint32 ipv4mtu; guint32 ipv6mtu; g_autofree MbimIPv4 *ipv4dnsserver = NULL; g_autofree MbimIPv6 *ipv6dnsserver = NULL; g_autoptr(MbimIPv4ElementArray) ipv4address = NULL; g_autoptr(MbimIPv6ElementArray) ipv6address = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x80, 0x00, 0x00, 0x00, /* length */ 0x1A, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0F, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x50, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* session id */ 0x0F, 0x00, 0x00, 0x00, /* IPv4ConfigurationAvailable */ 0x00, 0x00, 0x00, 0x00, /* IPv6ConfigurationAvailable */ 0x01, 0x00, 0x00, 0x00, /* IPv4 element count */ 0x3C, 0x00, 0x00, 0x00, /* IPv4 element offset */ 0x00, 0x00, 0x00, 0x00, /* IPv6 element count */ 0x00, 0x00, 0x00, 0x00, /* IPv6 element offset */ 0x44, 0x00, 0x00, 0x00, /* IPv4 gateway offset */ 0x00, 0x00, 0x00, 0x00, /* IPv6 gateway offset */ 0x02, 0x00, 0x00, 0x00, /* IPv4 DNS count */ 0x48, 0x00, 0x00, 0x00, /* IPv4 DNS offset */ 0x00, 0x00, 0x00, 0x00, /* IPv6 DNS count */ 0x00, 0x00, 0x00, 0x00, /* IPv6 DNS offset */ 0xDC, 0x05, 0x00, 0x00, /* IPv4 MTU */ 0x00, 0x00, 0x00, 0x00, /* IPv6 MTU */ /* data buffer */ 0x1C, 0x00, 0x00, 0x00, /* IPv4 element (netmask) */ 0xD4, 0x49, 0x22, 0xF8, /* IPv4 element (address) */ 0xD4, 0x49, 0x22, 0xF1, /* IPv4 gateway */ 0xD4, 0xA6, 0xD2, 0x50, /* IPv4 DNS1 */ 0xD4, 0x49, 0x20, 0x43 /* IPv4 DNS2 */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_ip_configuration_response_parse ( response, &session_id, &ipv4configurationavailable, &ipv6configurationavailable, &ipv4addresscount, &ipv4address, &ipv6addresscount, &ipv6address, &ipv4gateway, &ipv6gateway, &ipv4dnsservercount, &ipv4dnsserver, &ipv6dnsservercount, &ipv6dnsserver, &ipv4mtu, &ipv6mtu, &error)); /* * IPv4 configuration available: 'address, gateway, dns, mtu' * IP addresses (1) * IP [0]: '212.166.228.25/28' * Gateway: '212.166.228.26' * DNS addresses (2) * DNS [0]: '212.166.210.80' * DNS [1]: '212.73.32.67' * MTU: '1500' */ g_assert_cmpuint (session_id, ==, 0); g_assert_cmpuint (ipv4configurationavailable, ==, (MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)); g_assert_cmpuint (ipv6configurationavailable, ==, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE); { MbimIPv4 addr = { .addr = { 0xD4, 0x49, 0x22, 0xF8 } }; g_assert_cmpuint (ipv4addresscount, ==, 1); g_assert_cmpuint (ipv4address[0]->on_link_prefix_length, ==, 28); g_assert (memcmp (&addr, &(ipv4address[0]->ipv4_address), 4) == 0); } { MbimIPv4 gateway_addr = { .addr = { 0xD4, 0x49, 0x22, 0xF1 } }; g_assert (memcmp (&gateway_addr, ipv4gateway, 4) == 0); } { MbimIPv4 dns_addr_1 = { .addr = { 0xD4, 0xA6, 0xD2, 0x50 } }; MbimIPv4 dns_addr_2 = { .addr = { 0xD4, 0x49, 0x20, 0x43 } }; g_assert_cmpuint (ipv4dnsservercount, ==, 2); g_assert (memcmp (&dns_addr_1, &ipv4dnsserver[0], 4) == 0); g_assert (memcmp (&dns_addr_2, &ipv4dnsserver[1], 4) == 0); } g_assert_cmpuint (ipv4mtu, ==, 1500); g_assert_cmpuint (ipv6addresscount, ==, 0); g_assert (ipv6address == NULL); g_assert (ipv6gateway == NULL); g_assert_cmpuint (ipv6dnsservercount, ==, 0); g_assert (ipv6dnsserver == NULL); } static void test_basic_connect_ip_configuration_2 (void) { guint32 session_id; MbimIPConfigurationAvailableFlag ipv4configurationavailable; MbimIPConfigurationAvailableFlag ipv6configurationavailable; guint32 ipv4addresscount; guint32 ipv6addresscount; const MbimIPv4 *ipv4gateway; const MbimIPv6 *ipv6gateway; guint32 ipv4dnsservercount; guint32 ipv6dnsservercount; guint32 ipv4mtu; guint32 ipv6mtu; g_autofree MbimIPv4 *ipv4dnsserver = NULL; g_autofree MbimIPv6 *ipv6dnsserver = NULL; g_autoptr(MbimIPv4ElementArray) ipv4address = NULL; g_autoptr(MbimIPv6ElementArray) ipv6address = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0xC4, 0x00, 0x00, 0x00, /* length */ 0x24, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0F, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x94, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* session id */ 0x0F, 0x00, 0x00, 0x00, /* IPv4ConfigurationAvailable */ 0x0F, 0x00, 0x00, 0x00, /* IPv6ConfigurationAvailable */ 0x01, 0x00, 0x00, 0x00, /* IPv4 element count */ 0x3C, 0x00, 0x00, 0x00, /* IPv4 element offset */ 0x01, 0x00, 0x00, 0x00, /* IPv6 element count */ 0x50, 0x00, 0x00, 0x00, /* IPv6 element offset */ 0x44, 0x00, 0x00, 0x00, /* IPv4 gateway offset */ 0x64, 0x00, 0x00, 0x00, /* IPv6 gateway offset */ 0x02, 0x00, 0x00, 0x00, /* IPv4 DNS count */ 0x48, 0x00, 0x00, 0x00, /* IPv4 DNS offset */ 0x02, 0x00, 0x00, 0x00, /* IPv6 DNS count */ 0x74, 0x00, 0x00, 0x00, /* IPv6 DNS offset */ 0xDC, 0x05, 0x00, 0x00, /* IPv4 MTU */ 0xDC, 0x05, 0x00, 0x00, /* IPv6 MTU */ /* data buffer */ 0x1D, 0x00, 0x00, 0x00, /* IPv4 element (netmask) */ 0x1C, 0xF6, 0xC9, 0xDB, /* IPv4 element (address) */ 0x1C, 0xF6, 0xC9, 0xDC, /* IPv4 gateway */ 0x0A, 0xB1, 0x00, 0x22, /* IPv4 DNS1 */ 0x0A, 0xB1, 0x00, 0xD2, /* IPv4 DNS2 */ 0x40, 0x00, 0x00, 0x00, /* IPv6 element (netmask) */ 0x26, 0x07, 0xFB, 0x90, /* IPv6 element (address) */ 0x64, 0x3B, 0x28, 0x1F, 0x1D, 0xFF, 0xBF, 0x3D, 0xC5, 0xC8, 0x48, 0xAD, 0x26, 0x07, 0xFB, 0x90, /* IPv6 gateway */ 0x64, 0x3B, 0x28, 0x1F, 0xFD, 0xF7, 0x80, 0xF4, 0xE3, 0x99, 0x98, 0x4A, 0xFD, 0x00, 0x97, 0x6A, /* IPv6 DNS1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFD, 0x00, 0x97, 0x6A, /* IPv6 DNS2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_ip_configuration_response_parse ( response, &session_id, &ipv4configurationavailable, &ipv6configurationavailable, &ipv4addresscount, &ipv4address, &ipv6addresscount, &ipv6address, &ipv4gateway, &ipv6gateway, &ipv4dnsservercount, &ipv4dnsserver, &ipv6dnsservercount, &ipv6dnsserver, &ipv4mtu, &ipv6mtu, &error)); /* * IPv4 configuration available: 'address, gateway, dns, mtu' * IP addresses (1) * IP [0]: '28.246.201.219/29' * gateway: '28.246.201.220' * DNS addresses (2) * DNS [0]: '10.177.0.34' * DNS [1]: '10.177.0.210' * MTU: '1500' * IPv6 configuration available: 'address, gateway, dns, mtu' * IP addresses (1) * IP [0]: '2607:fb90:643b:281f:1dff:bf3d:c5c8:48ad/64' * gateway: '2607:fb90:643b:281f:fdf7:80f4:e399:984a' * DNS addresses (2) * DNS [0]: 'fd00:976a::9' */ g_assert_cmpuint (session_id, ==, 0); g_assert_cmpuint (ipv4configurationavailable, ==, (MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU)); g_assert_cmpuint (ipv6configurationavailable, ==, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS | MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU); { MbimIPv4 addr = { .addr = { 0x1C, 0xF6, 0xC9, 0xDB } }; g_assert_cmpuint (ipv4addresscount, ==, 1); g_assert_cmpuint (ipv4address[0]->on_link_prefix_length, ==, 29); g_assert (memcmp (&addr, &(ipv4address[0]->ipv4_address), 4) == 0); } { MbimIPv4 gateway_addr = { .addr = { 0x1C, 0xF6, 0xC9, 0xDC } }; g_assert (memcmp (&gateway_addr, ipv4gateway, 4) == 0); } { MbimIPv4 dns_addr_1 = { .addr = { 0x0A, 0xB1, 0x00, 0x22 } }; MbimIPv4 dns_addr_2 = { .addr = { 0x0A, 0xB1, 0x00, 0xD2 } }; g_assert_cmpuint (ipv4dnsservercount, ==, 2); g_assert (memcmp (&dns_addr_1, &ipv4dnsserver[0], 4) == 0); g_assert (memcmp (&dns_addr_2, &ipv4dnsserver[1], 4) == 0); } g_assert_cmpuint (ipv4mtu, ==, 1500); { MbimIPv6 addr = { .addr = { 0x26, 0x07, 0xFB, 0x90, 0x64, 0x3B, 0x28, 0x1F, 0x1D, 0xFF, 0xBF, 0x3D, 0xC5, 0xC8, 0x48, 0xAD } }; g_assert_cmpuint (ipv6addresscount, ==, 1); g_assert_cmpuint (ipv6address[0]->on_link_prefix_length, ==, 64); g_assert (memcmp (&addr, &(ipv6address[0]->ipv6_address), 16) == 0); } { MbimIPv6 dns_addr_1 = { .addr = { 0xFD, 0x00, 0x97, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 } }; MbimIPv6 dns_addr_2 = { .addr = { 0xFD, 0x00, 0x97, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } }; g_assert_cmpuint (ipv6dnsservercount, ==, 2); g_assert (memcmp (&dns_addr_1, &ipv6dnsserver[0], 16) == 0); g_assert (memcmp (&dns_addr_2, &ipv6dnsserver[1], 16) == 0); } } static void test_basic_connect_service_activation (void) { guint32 nw_error; const guint8 *databuffer; guint32 databuffer_size; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 expected_databuffer [] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x3C, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0E, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x0C, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x06, 0x00, 0x00, 0x00, /* nw error */ 0x01, 0x02, 0x03, 0x04, /* buffer */ 0x05, 0x06, 0x07, 0x08 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_service_activation_response_parse ( response, &nw_error, &databuffer_size, &databuffer, &error)); g_assert_no_error (error); g_assert_cmpuint (nw_error, ==, MBIM_NW_ERROR_ILLEGAL_ME); g_assert_cmpuint (databuffer_size, ==, sizeof (expected_databuffer)); g_assert (memcmp (databuffer, expected_databuffer, databuffer_size) == 0); } static void test_basic_connect_register_state (void) { MbimNwError nw_error; MbimRegisterState register_state; MbimRegisterMode register_mode; MbimDataClass available_data_classes; MbimCellularClass current_cellular_class; MbimRegistrationFlag registration_flag; g_autofree gchar *provider_id; g_autofree gchar *provider_name; g_autofree gchar *roaming_text; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x6C, 0x00, 0x00, 0x00, /* length */ 0x12, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x09, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x3C, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* nw error */ 0x03, 0x00, 0x00, 0x00, /* register state */ 0x01, 0x00, 0x00, 0x00, /* register mode */ 0x1C, 0x00, 0x00, 0x00, /* available data classes */ 0x01, 0x00, 0x00, 0x00, /* current cellular class */ 0x30, 0x00, 0x00, 0x00, /* provider id offset */ 0x0A, 0x00, 0x00, 0x00, /* provider id size */ 0x00, 0x00, 0x00, 0x00, /* provider name offset */ 0x00, 0x00, 0x00, 0x00, /* provider name size */ 0x00, 0x00, 0x00, 0x00, /* roaming text offset */ 0x00, 0x00, 0x00, 0x00, /* roaming text size */ 0x02, 0x00, 0x00, 0x00, /* registration flag */ /* data buffer */ 0x32, 0x00, 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x36, 0x00, 0x00, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_register_state_response_parse ( response, &nw_error, ®ister_state, ®ister_mode, &available_data_classes, ¤t_cellular_class, &provider_id, &provider_name, &roaming_text, ®istration_flag, &error)); g_assert_no_error (error); g_assert_cmpuint (nw_error, ==, MBIM_NW_ERROR_NONE); g_assert_cmpuint (register_state, ==, MBIM_REGISTER_STATE_HOME); g_assert_cmpuint (register_mode, ==, MBIM_REGISTER_MODE_AUTOMATIC); g_assert_cmpuint (available_data_classes, ==, (MBIM_DATA_CLASS_UMTS | MBIM_DATA_CLASS_HSDPA | MBIM_DATA_CLASS_HSUPA)); g_assert_cmpuint (current_cellular_class, ==, MBIM_CELLULAR_CLASS_GSM); g_assert_cmpstr (provider_id, ==, "26006"); g_assert (provider_name == NULL); g_assert (roaming_text == NULL); g_assert_cmpuint (registration_flag, ==, MBIM_REGISTRATION_FLAG_PACKET_SERVICE_AUTOMATIC_ATTACH); } static void test_provisioned_contexts (void) { guint32 provisioned_contexts_count = 0; g_autoptr(MbimProvisionedContextElementArray) provisioned_contexts = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x30, 0x00, 0x00, 0x00, /* length */ 0x1C, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* length */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0D, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x00, 0x00, 0x00, 0x00 /* buffer length */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (!mbim_message_provisioned_contexts_response_parse ( response, &provisioned_contexts_count, &provisioned_contexts, &error)); g_assert_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE); } static void test_sms_read_zero_pdu (void) { MbimSmsFormat format; guint32 messages_count; g_autoptr(MbimSmsPduReadRecordArray) pdu_messages = NULL; g_autoptr(MbimSmsCdmaReadRecordArray) cdma_messages = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x38, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x53, 0x3F, 0xBE, 0xEB, /* service id */ 0x14, 0xFE, 0x44, 0x67, 0x9F, 0x90, 0x33, 0xA2, 0x23, 0xE5, 0x6C, 0x3F, 0x02, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x08, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* 0x00 format */ 0x00, 0x00, 0x00, 0x00, /* 0x04 messages count */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_sms_read_response_parse ( response, &format, &messages_count, &pdu_messages, &cdma_messages, &error)); g_assert_no_error (error); g_assert_cmpuint (format, ==, MBIM_SMS_FORMAT_PDU); g_assert_cmpuint (messages_count, ==, 0); g_assert (pdu_messages == NULL); g_assert (cdma_messages == NULL); } static void test_sms_read_single_pdu (void) { MbimSmsFormat format; guint32 messages_count; g_autoptr(MbimSmsPduReadRecordArray) pdu_messages = NULL; g_autoptr(MbimSmsCdmaReadRecordArray) cdma_messages = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x60, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x53, 0x3F, 0xBE, 0xEB, /* service id */ 0x14, 0xFE, 0x44, 0x67, 0x9F, 0x90, 0x33, 0xA2, 0x23, 0xE5, 0x6C, 0x3F, 0x02, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x30, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* 0x00 format */ 0x01, 0x00, 0x00, 0x00, /* 0x04 messages count */ 0x10, 0x00, 0x00, 0x00, /* 0x08 message 1 offset */ 0x20, 0x00, 0x00, 0x00, /* 0x0C message 1 length */ /* data buffer... message 1 */ 0x07, 0x00, 0x00, 0x00, /* 0x10 0x00 message index */ 0x03, 0x00, 0x00, 0x00, /* 0x14 0x04 message status */ 0x10, 0x00, 0x00, 0x00, /* 0x18 0x08 pdu data offset (w.r.t. pdu start */ 0x10, 0x00, 0x00, 0x00, /* 0x1C 0x0C pdu data length */ /* pdu data... */ 0x01, 0x02, 0x03, 0x04, /* 0x20 0x10 */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 }; const guint8 expected_pdu [] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_sms_read_response_parse ( response, &format, &messages_count, &pdu_messages, &cdma_messages, &error)); g_assert_no_error (error); g_assert_cmpuint (format, ==, MBIM_SMS_FORMAT_PDU); g_assert_cmpuint (messages_count, ==, 1); g_assert (pdu_messages != NULL); g_assert (cdma_messages == NULL); g_assert_cmpuint (pdu_messages[0]->message_index, ==, 7); g_assert_cmpuint (pdu_messages[0]->message_status, ==, MBIM_SMS_STATUS_SENT); test_message_trace (pdu_messages[0]->pdu_data, pdu_messages[0]->pdu_data_size, expected_pdu, sizeof (expected_pdu)); g_assert_cmpuint (pdu_messages[0]->pdu_data_size, ==, sizeof (expected_pdu)); g_assert (memcmp (pdu_messages[0]->pdu_data, expected_pdu, sizeof (expected_pdu)) == 0); } static void test_sms_read_multiple_pdu (void) { guint32 idx; MbimSmsFormat format; guint32 messages_count; g_autoptr(MbimSmsPduReadRecordArray) pdu_messages = NULL; g_autoptr(MbimSmsCdmaReadRecordArray) cdma_messages = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x88, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x53, 0x3F, 0xBE, 0xEB, /* service id */ 0x14, 0xFE, 0x44, 0x67, 0x9F, 0x90, 0x33, 0xA2, 0x23, 0xE5, 0x6C, 0x3F, 0x02, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x58, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* 0x00 format */ 0x02, 0x00, 0x00, 0x00, /* 0x04 messages count */ 0x18, 0x00, 0x00, 0x00, /* 0x08 message 1 offset */ 0x20, 0x00, 0x00, 0x00, /* 0x0C message 1 length */ 0x38, 0x00, 0x00, 0x00, /* 0x10 message 2 offset */ 0x24, 0x00, 0x00, 0x00, /* 0x14 message 2 length */ /* data buffer... message 1 */ 0x06, 0x00, 0x00, 0x00, /* 0x18 0x00 message index */ 0x03, 0x00, 0x00, 0x00, /* 0x1C 0x04 message status */ 0x10, 0x00, 0x00, 0x00, /* 0x20 0x08 pdu data offset (w.r.t. pdu start */ 0x10, 0x00, 0x00, 0x00, /* 0x24 0x0C pdu data length */ /* pdu data... */ 0x01, 0x02, 0x03, 0x04, /* 0x28 0x10 */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, /* data buffer... message 2 */ 0x07, 0x00, 0x00, 0x00, /* 0x38 0x00 message index */ 0x03, 0x00, 0x00, 0x00, /* 0x3C 0x04 message status */ 0x10, 0x00, 0x00, 0x00, /* 0x40 0x08 pdu data offset (w.r.t. pdu start */ 0x10, 0x00, 0x00, 0x00, /* 0x44 0x0C pdu data length */ /* pdu data... */ 0x00, 0x01, 0x02, 0x03, /* 0x48 0x10 */ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; const guint8 expected_pdu_idx6 [] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 }; const guint8 expected_pdu_idx7 [] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_sms_read_response_parse ( response, &format, &messages_count, &pdu_messages, &cdma_messages, &error)); g_assert_no_error (error); g_assert_cmpuint (format, ==, MBIM_SMS_FORMAT_PDU); g_assert_cmpuint (messages_count, ==, 2); g_assert (pdu_messages != NULL); g_assert (cdma_messages == NULL); /* First message with index 6 */ if (pdu_messages[0]->message_index == 6) idx = 0; else if (pdu_messages[1]->message_index == 6) idx = 1; else g_assert_not_reached (); g_assert_cmpuint (pdu_messages[idx]->message_index, ==, 6); g_assert_cmpuint (pdu_messages[idx]->message_status, ==, MBIM_SMS_STATUS_SENT); test_message_trace (pdu_messages[idx]->pdu_data, pdu_messages[idx]->pdu_data_size, expected_pdu_idx6, sizeof (expected_pdu_idx6)); g_assert_cmpuint (pdu_messages[idx]->pdu_data_size, ==, sizeof (expected_pdu_idx6)); g_assert (memcmp (pdu_messages[idx]->pdu_data, expected_pdu_idx6, sizeof (expected_pdu_idx6)) == 0); /* Second message with index 7 */ if (pdu_messages[0]->message_index == 7) idx = 0; else if (pdu_messages[1]->message_index == 7) idx = 1; else g_assert_not_reached (); g_assert_cmpuint (pdu_messages[idx]->message_index, ==, 7); g_assert_cmpuint (pdu_messages[idx]->message_status, ==, MBIM_SMS_STATUS_SENT); test_message_trace (pdu_messages[idx]->pdu_data, pdu_messages[idx]->pdu_data_size, expected_pdu_idx7, sizeof (expected_pdu_idx7)); g_assert_cmpuint (pdu_messages[idx]->pdu_data_size, ==, sizeof (expected_pdu_idx7)); g_assert (memcmp (pdu_messages[idx]->pdu_data, expected_pdu_idx7, sizeof (expected_pdu_idx7)) == 0); } static void test_ussd (void) { MbimUssdResponse ussd_response; MbimUssdSessionState ussd_session_state; const guint8 *ussd_payload; guint32 ussd_payload_size; guint32 ussd_dcs; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x54, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xE5, 0x50, 0xA0, 0xC8, /* service id */ 0x5E, 0x82, 0x47, 0x9E, 0x82, 0xF7, 0x10, 0xAB, 0xF4, 0xC3, 0x35, 0x1F, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x24, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x05, 0x00, 0x00, 0x00, /* 0x00 response */ 0x01, 0x00, 0x00, 0x00, /* 0x04 sesstion state */ 0x01, 0x00, 0x00, 0x00, /* 0x08 coding scheme */ 0x14, 0x00, 0x00, 0x00, /* 0x0C payload offset */ 0x10, 0x00, 0x00, 0x00, /* 0x10 payload length */ /* data buffer... payload */ 0x01, 0x02, 0x03, 0x04, /* 0x14 payload */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 }; const guint8 expected_payload [] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_ussd_response_parse ( response, &ussd_response, &ussd_session_state, &ussd_dcs, &ussd_payload_size, &ussd_payload, &error)); g_assert_no_error (error); g_assert_cmpuint (ussd_response, ==, MBIM_USSD_RESPONSE_NETWORK_TIMEOUT); g_assert_cmpuint (ussd_session_state, ==, MBIM_USSD_SESSION_STATE_EXISTING_SESSION); g_assert_cmpuint (ussd_dcs, ==, 0x01); test_message_trace (ussd_payload, ussd_payload_size, expected_payload, sizeof (expected_payload)); g_assert_cmpuint (ussd_payload_size, ==, sizeof (expected_payload)); g_assert (memcmp (ussd_payload, expected_payload, sizeof (expected_payload)) == 0); } static void test_auth_akap (void) { const guint8 *res; guint32 res_len; const guint8 *ik; const guint8 *ck; const guint8 *auts; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x74, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x1D, 0x2B, 0x5F, 0xF7, /* service id */ 0x0A, 0xA1, 0x48, 0xB2, 0xAA, 0x52, 0x50, 0xF1, 0x57, 0x67, 0x17, 0x4E, 0x02, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x44, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x01, 0x02, 0x03, /* 0x00 Res */ 0x04, 0x05, 0x06, 0x07, /* 0x04 */ 0x08, 0x09, 0x0A, 0x0B, /* 0x08 */ 0x0C, 0x0D, 0x0E, 0x0F, /* 0x0C */ 0x05, 0x00, 0x00, 0x00, /* 0x10 Reslen */ 0xFF, 0xFE, 0xFD, 0xFC, /* 0x14 IK */ 0xFB, 0xFA, 0xF9, 0xF8, /* 0x18 */ 0xF7, 0xF6, 0xF5, 0xF4, /* 0x1C */ 0xF3, 0xF2, 0xF1, 0xF0, /* 0x20 */ 0xAF, 0xAE, 0xAD, 0xAC, /* 0x24 CK */ 0xAB, 0xAA, 0xA9, 0xA8, /* 0x28 */ 0xA7, 0xA6, 0xA5, 0xA4, /* 0x2C */ 0xA3, 0xA2, 0xA1, 0xA0, /* 0x30 */ 0x7F, 0x7E, 0x7D, 0x7C, /* 0x34 Auts */ 0x7B, 0x7A, 0x79, 0x78, /* 0x38 */ 0x77, 0x76, 0x75, 0x74, /* 0x3C */ 0x73, 0x72, 0x00, 0x00, /* 0x40 */ }; const guint8 expected_res [] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, }; const guint8 expected_ik [] = { 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0, }; const guint8 expected_ck [] = { 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, }; const guint8 expected_auts [] = { 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_auth_akap_response_parse ( response, &res, &res_len, &ik, &ck, &auts, &error)); g_assert_no_error (error); test_message_trace (res, sizeof (expected_res), expected_res, sizeof (expected_res)); g_assert (memcmp (res, expected_res, sizeof (expected_res)) == 0); g_assert_cmpuint (res_len, ==, 5); test_message_trace (ik, sizeof (expected_ik), expected_ik, sizeof (expected_ik)); g_assert (memcmp (ik, expected_ik, sizeof (expected_ik)) == 0); test_message_trace (ck, sizeof (expected_ck), expected_ck, sizeof (expected_ck)); g_assert (memcmp (ck, expected_ck, sizeof (expected_ck)) == 0); test_message_trace (auts, sizeof (expected_auts), expected_auts, sizeof (expected_auts)); g_assert (memcmp (auts, expected_auts, sizeof (expected_auts)) == 0); } static void test_stk_pac_notification (void) { const guint8 *databuffer; guint32 databuffer_len; guint32 pac_type; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x07, 0x00, 0x00, 0x80, /* type */ 0x54, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* indicate_status_message */ 0xD8, 0xF2, 0x01, 0x31, /* service id */ 0xFC, 0xB5, 0x4E, 0x17, 0x86, 0x02, 0xD6, 0xED, 0x38, 0x16, 0x16, 0x4C, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x28, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* 0x00 Pac Type */ 0x04, 0x05, 0x06, 0x07, /* 0x04 Data buffer */ 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00 }; const guint8 expected_databuffer [] = { 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_stk_pac_notification_parse ( response, &pac_type, &databuffer_len, &databuffer, &error)); g_assert_no_error (error); g_assert_cmpuint (pac_type, ==, MBIM_STK_PAC_TYPE_NOTIFICATION); test_message_trace (databuffer, sizeof (databuffer_len), expected_databuffer, sizeof (expected_databuffer)); g_assert_cmpuint (databuffer_len, ==, sizeof (expected_databuffer)); g_assert (memcmp (databuffer, expected_databuffer, sizeof (expected_databuffer)) == 0); } static void test_stk_pac_response (void) { const guint8 *databuffer; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x30, 0x01, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* indicate_status_message */ 0xD8, 0xF2, 0x01, 0x31, /* service id */ 0xFC, 0xB5, 0x4E, 0x17, 0x86, 0x02, 0xD6, 0xED, 0x38, 0x16, 0x16, 0x4C, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x00, 0x01, 0x00, 0x00, /* buffer length (256) */ /* information buffer */ 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, }; const guint8 expected_databuffer [256] = { 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, }; response = mbim_message_new (buffer, sizeof (buffer)); mbim_message_validate (response, &error); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_stk_pac_response_parse ( response, &databuffer, &error)); g_assert_no_error (error); test_message_trace (databuffer, sizeof (expected_databuffer), expected_databuffer, sizeof (expected_databuffer)); g_assert (memcmp (databuffer, expected_databuffer, sizeof (expected_databuffer)) == 0); } static void test_stk_terminal_response (void) { const guint8 *databuffer; guint32 databuffer_len; guint32 status_words; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x48, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* indicate_status_message */ 0xD8, 0xF2, 0x01, 0x31, /* service id */ 0xFC, 0xB5, 0x4E, 0x17, 0x86, 0x02, 0xD6, 0xED, 0x38, 0x16, 0x16, 0x4C, 0x02, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x18, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x0C, 0x00, 0x00, 0x00, /* 0x00 ResultData offset */ 0x0C, 0x00, 0x00, 0x00, /* 0x04 ResultData length */ 0xCC, 0x00, 0x00, 0x00, /* 0x08 StatusWords */ /* databuffer */ 0x00, 0x00, 0x00, 0x00, /* 0x0C ResultData */ 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC }; const guint8 expected_databuffer [] = { 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0xAF, 0xAE, 0xAD, 0xAC }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_stk_terminal_response_response_parse ( response, &databuffer_len, &databuffer, &status_words, &error)); g_assert_no_error (error); g_assert_cmpuint (status_words, ==, 204); test_message_trace (databuffer, databuffer_len, expected_databuffer, sizeof (expected_databuffer)); g_assert_cmpuint (databuffer_len, ==, sizeof (expected_databuffer)); g_assert (memcmp (databuffer, expected_databuffer, sizeof (expected_databuffer)) == 0); } static void test_stk_envelope_response (void) { const guint8 *databuffer; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x50, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* indicate_status_message */ 0xD8, 0xF2, 0x01, 0x31, /* service id */ 0xFC, 0xB5, 0x4E, 0x17, 0x86, 0x02, 0xD6, 0xED, 0x38, 0x16, 0x16, 0x4C, 0x03, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x20, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const guint8 expected_databuffer [] = { 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_stk_envelope_response_parse ( response, &databuffer, &error)); g_assert_no_error (error); test_message_trace (databuffer, sizeof (expected_databuffer), expected_databuffer, sizeof (expected_databuffer)); g_assert (memcmp (databuffer, expected_databuffer, sizeof (expected_databuffer)) == 0); } static void test_basic_connect_ip_packet_filters_none (void) { guint32 n_filters; guint32 session_id; g_autoptr(MbimPacketFilterArray) filters = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x38, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* indicate_status_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x17, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x08, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* session id */ 0x00, 0x00, 0x00, 0x00 /* packet filters count */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_ip_packet_filters_response_parse ( response, &session_id, &n_filters, &filters, &error)); g_assert_no_error (error); g_assert_cmpuint (session_id, ==, 1); g_assert_cmpuint (n_filters, ==, 0); g_assert (filters == NULL); } static void test_basic_connect_ip_packet_filters_one (void) { guint32 n_filters; guint32 session_id; g_autoptr(MbimPacketFilterArray) filters = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x5C, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* indicate_status_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x17, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x2C, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* 0x00 session id */ 0x01, 0x00, 0x00, 0x00, /* 0x04 packet filters count */ 0x10, 0x00, 0x00, 0x00, /* 0x08 packet filter 1 offset */ 0x1C, 0x00, 0x00, 0x00, /* 0x0C packet filter 1 length */ /* databuffer, packet filter 1 */ 0x08, 0x00, 0x00, 0x00, /* 0x10 0x00 filter size */ 0x0C, 0x00, 0x00, 0x00, /* 0x14 0x04 filter offset (from beginning of struct) */ 0x14, 0x00, 0x00, 0x00, /* 0x18 0x08 mask offset (from beginning of struct) */ 0x01, 0x02, 0x03, 0x04, /* 0x1C 0x0C filter */ 0x05, 0x06, 0x07, 0x08, 0xF1, 0xF2, 0xF3, 0xF4, /* 0x24 0x14 mask */ 0xF5, 0xF6, 0xF7, 0xF8, }; const guint8 expected_filter[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }; const guint8 expected_mask[] = { 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_ip_packet_filters_response_parse ( response, &session_id, &n_filters, &filters, &error)); g_assert_no_error (error); g_assert_cmpuint (session_id, ==, 1); g_assert_cmpuint (n_filters, ==, 1); g_assert (filters != NULL); g_assert_cmpuint (filters[0]->filter_size, ==, 8); test_message_trace (filters[0]->packet_filter, 8, expected_filter, sizeof (expected_filter)); g_assert (memcmp (filters[0]->packet_filter, expected_filter, sizeof (expected_filter)) == 0); test_message_trace (filters[0]->packet_mask, 8, expected_mask, sizeof (expected_mask)); g_assert (memcmp (filters[0]->packet_mask, expected_mask, sizeof (expected_mask)) == 0); } static void test_basic_connect_ip_packet_filters_two (void) { guint32 n_filters; guint32 session_id; g_autoptr(MbimPacketFilterArray) filters = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x88, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* indicate_status_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x17, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x58, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* 0x00 session id */ 0x02, 0x00, 0x00, 0x00, /* 0x04 packet filters count */ 0x18, 0x00, 0x00, 0x00, /* 0x08 packet filter 1 offset */ 0x1C, 0x00, 0x00, 0x00, /* 0x0C packet filter 1 length */ 0x34, 0x00, 0x00, 0x00, /* 0x10 packet filter 2 offset */ 0x24, 0x00, 0x00, 0x00, /* 0x14 packet filter 2 length */ /* databuffer, packet filter 2 */ 0x08, 0x00, 0x00, 0x00, /* 0x18 0x00 filter size */ 0x0C, 0x00, 0x00, 0x00, /* 0x1C 0x04 filter offset (from beginning of struct) */ 0x14, 0x00, 0x00, 0x00, /* 0x20 0x08 mask offset (from beginning of struct) */ 0x01, 0x02, 0x03, 0x04, /* 0x24 0x0C filter */ 0x05, 0x06, 0x07, 0x08, 0xF1, 0xF2, 0xF3, 0xF4, /* 0x2C 0x14 mask */ 0xF5, 0xF6, 0xF7, 0xF8, /* databuffer, packet filter 2 */ 0x0C, 0x00, 0x00, 0x00, /* 0x34 0x00 filter size */ 0x0C, 0x00, 0x00, 0x00, /* 0x38 0x04 filter offset (from beginning of struct) */ 0x18, 0x00, 0x00, 0x00, /* 0x3C 0x08 mask offset (from beginning of struct) */ 0x01, 0x02, 0x03, 0x04, /* 0x40 0x0C filter */ 0x05, 0x06, 0x07, 0x08, 0x05, 0x06, 0x07, 0x08, 0xF1, 0xF2, 0xF3, 0xF4, /* 0x4C 0x18 mask */ 0xF5, 0xF6, 0xF7, 0xF8, 0xF5, 0xF6, 0xF7, 0xF8, }; const guint8 expected_filter1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }; const guint8 expected_mask1[] = { 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, }; const guint8 expected_filter2[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x05, 0x06, 0x07, 0x08, }; const guint8 expected_mask2[] = { 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF5, 0xF6, 0xF7, 0xF8, }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_ip_packet_filters_response_parse ( response, &session_id, &n_filters, &filters, &error)); g_assert_no_error (error); g_assert_cmpuint (session_id, ==, 1); g_assert_cmpuint (n_filters, ==, 2); g_assert (filters != NULL); g_assert_cmpuint (filters[0]->filter_size, ==, 8); test_message_trace (filters[0]->packet_filter, 8, expected_filter1, sizeof (expected_filter1)); g_assert (memcmp (filters[0]->packet_filter, expected_filter1, sizeof (expected_filter1)) == 0); test_message_trace (filters[0]->packet_mask, 8, expected_mask1, sizeof (expected_mask1)); g_assert (memcmp (filters[0]->packet_mask, expected_mask1, sizeof (expected_mask1)) == 0); g_assert_cmpuint (filters[1]->filter_size, ==, 12); test_message_trace (filters[1]->packet_filter, 12, expected_filter2, sizeof (expected_filter2)); g_assert (memcmp (filters[1]->packet_filter, expected_filter2, sizeof (expected_filter2)) == 0); test_message_trace (filters[1]->packet_mask, 12, expected_mask2, sizeof (expected_mask2)); g_assert (memcmp (filters[1]->packet_mask, expected_mask2, sizeof (expected_mask2)) == 0); } static void test_ms_firmware_id_get (void) { const MbimUuid *firmware_id; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x40, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xE9, 0xF7, 0xDE, 0xA2, /* service id */ 0xFE, 0xAF, 0x40, 0x09, 0x93, 0xCE, 0x90, 0xA3, 0x69, 0x41, 0x03, 0xB6, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x10, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x11, 0x22, 0x33, /* firmware id */ 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; const MbimUuid expected_firmware_id = { .a = { 0x00, 0x11, 0x22, 0x33 }, .b = { 0x44, 0x55 }, .c = { 0x66, 0x77 }, .d = { 0x88, 0x99 }, .e = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); g_assert (mbim_message_ms_firmware_id_get_response_parse ( response, &firmware_id, &error)); g_assert_no_error (error); g_assert (mbim_uuid_cmp (firmware_id, &expected_firmware_id)); } static void test_basic_connect_connect_short (void) { guint32 session_id; MbimActivationState activation_state; MbimVoiceCallState voice_call_state; MbimContextIpType ip_type; const MbimUuid *context_type; guint32 nw_error; g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x30, 0x00, 0x00, 0x00, /* length */ 0x1A, 0x0D, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, /* command id */ 0x0C, 0x00, 0x00, 0x00, /* status code */ 0x02, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); /* generic validation passes because the MBIM message format is fine */ g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); /* should fail! */ g_assert (!mbim_message_connect_response_parse ( response, &session_id, &activation_state, &voice_call_state, &ip_type, &context_type, &nw_error, &error)); g_assert (error != NULL); } static void test_basic_connect_visible_providers_overflow (void) { guint32 n_providers; g_autoptr(GError) error = NULL; g_autoptr(MbimProviderArray) providers = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0xB4, 0x00, 0x00, 0x00, /* length */ 0x02, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x08, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x84, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x02, 0x00, 0x00, 0x00, /* 0x00 providers count */ 0x14, 0x00, 0x00, 0x00, /* 0x04 provider 0 offset */ 0x38, 0x00, 0x00, 0x00, /* 0x08 provider 0 length */ 0x4C, 0x00, 0x00, 0x00, /* 0x0C provider 1 offset */ 0x38, 0x00, 0x00, 0x00, /* 0x10 provider 1 length */ /* data buffer... struct provider 0 */ 0x20, 0x00, 0x00, 0x80, /* 0x14 [0x00] id offset */ /* OFFSET WRONG (0x80 instead of 0x00) */ 0x0A, 0x00, 0x00, 0x80, /* 0x18 [0x04] id length */ /* LENGTH WRONG (0x80 instead of 0x00) */ 0x08, 0x00, 0x00, 0x00, /* 0x1C [0x08] state */ 0x2C, 0x00, 0x00, 0x00, /* 0x20 [0x0C] name offset */ 0x0C, 0x00, 0x00, 0x00, /* 0x24 [0x10] name length */ 0x01, 0x00, 0x00, 0x00, /* 0x28 [0x14] cellular class */ 0x0B, 0x00, 0x00, 0x00, /* 0x2C [0x18] rssi */ 0x00, 0x00, 0x00, 0x00, /* 0x30 [0x1C] error rate */ 0x32, 0x00, 0x31, 0x00, /* 0x34 [0x20] id string (10 bytes) */ 0x34, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x72, 0x00, /* 0x40 [0x2C] name string (12 bytes) */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, /* data buffer... struct provider 1 */ 0x20, 0x00, 0x00, 0x00, /* 0x4C [0x00] id offset */ 0x0A, 0x00, 0x00, 0x00, /* 0x50 [0x04] id length */ 0x19, 0x00, 0x00, 0x00, /* 0x51 [0x08] state */ 0x2C, 0x00, 0x00, 0x00, /* 0x54 [0x0C] name offset */ 0x0C, 0x00, 0x00, 0x00, /* 0x58 [0x10] name length */ 0x01, 0x00, 0x00, 0x00, /* 0x5C [0x14] cellular class */ 0x0B, 0x00, 0x00, 0x00, /* 0x60 [0x18] rssi */ 0x00, 0x00, 0x00, 0x00, /* 0x64 [0x1C] error rate */ 0x32, 0x00, 0x31, 0x00, /* 0x68 [0x20] id string (10 bytes) */ 0x34, 0x00, 0x30, 0x00, 0x33, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x72, 0x00, /* 0x74 [0x2C] name string (12 bytes) */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); result = mbim_message_visible_providers_response_parse (response, &n_providers, &providers, &error); g_assert (error != NULL); g_assert (!result); } static void test_ms_basic_connect_extensions_base_stations (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimDataClass system_type; g_autoptr(MbimCellInfoServingGsm) gsm_serving_cell = NULL; g_autoptr(MbimCellInfoServingUmts) umts_serving_cell = NULL; g_autoptr(MbimCellInfoServingTdscdma) tdscdma_serving_cell = NULL; g_autoptr(MbimCellInfoServingLte) lte_serving_cell = NULL; guint32 gsm_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringGsmArray) gsm_neighboring_cells = NULL; guint32 umts_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringUmtsArray) umts_neighboring_cells = NULL; guint32 tdscdma_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringTdscdmaArray) tdscdma_neighboring_cells = NULL; guint32 lte_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringLteArray) lte_neighboring_cells = NULL; guint32 cdma_cells_count; g_autoptr(MbimCellInfoCdmaArray) cdma_cells = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0xD8, 0x00, 0x00, 0x00, /* length */ 0x03, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x0B, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0xA8, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x60, 0x00, 0x00, 0x00, /* system type */ 0x00, 0x00, 0x00, 0x00, /* gsm serving cell offset */ 0x00, 0x00, 0x00, 0x00, /* gsm serving cell size */ 0x00, 0x00, 0x00, 0x00, /* umts serving cell offset */ 0x00, 0x00, 0x00, 0x00, /* umts serving cell size */ 0x00, 0x00, 0x00, 0x00, /* tdscdma serving cell offset */ 0x00, 0x00, 0x00, 0x00, /* tdscdma serving cell size */ 0x4C, 0x00, 0x00, 0x00, /* lte serving cell offset*/ 0x2E, 0x00, 0x00, 0x00, /* lte serving cell size*/ 0xA0, 0x00, 0x00, 0x00, /* gsm network measurement report offset */ 0x04, 0x00, 0x00, 0x00, /* gsm network measurement report size */ 0xA4, 0x00, 0x00, 0x00, /* umts network measurement report offset */ 0x04, 0x00, 0x00, 0x00, /* umts network measurement report size */ 0x00, 0x00, 0x00, 0x00, /* tdscdma network measurement report offset */ 0x00, 0x00, 0x00, 0x00, /* tdscdma network measurement report size */ 0x7C, 0x00, 0x00, 0x00, /* lte network measurement report offset */ 0x24, 0x00, 0x00, 0x00, /* lte network measurement report size */ 0x00, 0x00, 0x00, 0x00, /* cdma network measurement report offset */ 0x00, 0x00, 0x00, 0x00, /* cdma network measurement report size */ /* lte serving cell */ /*4C*/ 0x24, 0x00, 0x00, 0x00, /* provider id offset */ 0x0A, 0x00, 0x00, 0x00, /* provider id size */ 0x1F, 0xCD, 0x65, 0x04, /* cell id */ 0x00, 0x19, 0x00, 0x00, /* earfcn */ 0x36, 0x01, 0x00, 0x00, /* physical cell id */ 0xFE, 0x6F, 0x00, 0x00, /* tac */ 0x99, 0xFF, 0xFF, 0xFF, /* rsrp */ 0xF4, 0xFF, 0xFF, 0xFF, /* rsrq */ 0xFF, 0xFF, 0xFF, 0xFF, /* timing advance */ 0x32, 0x00, 0x31, 0x00, /* provider id string */ 0x34, 0x00, 0x30, 0x00, 0x37, 0x00, 0x00, 0x00, /* lte network measurement report */ /*7C*/ 0x01, 0x00, 0x00, 0x00, /* element count */ 0x00, 0x00, 0x00, 0x00, /* provider id offset */ 0x00, 0x00, 0x00, 0x00, /* provider id size */ 0xFF, 0xFF, 0xFF, 0xFF, /* cell id */ 0xFF, 0xFF, 0xFF, 0xFF, /* earfcn */ 0x36, 0x01, 0x00, 0x00, /* physical cell id */ 0xFF, 0xFF, 0xFF, 0xFF, /* tac */ 0x99, 0xFF, 0xFF, 0xFF, /* rsrp */ 0xF4, 0xFF, 0xFF, 0xFF, /* rsrq */ /* gsm network measurement report */ /*A0*/ 0x00, 0x00, 0x00, 0x00, /* umts network measurement report */ /*A4*/ 0x00, 0x00, 0x00, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); result = (mbim_message_ms_basic_connect_extensions_base_stations_info_response_parse ( response, &system_type, &gsm_serving_cell, &umts_serving_cell, &tdscdma_serving_cell, <e_serving_cell, &gsm_neighboring_cells_count, &gsm_neighboring_cells, &umts_neighboring_cells_count, &umts_neighboring_cells, &tdscdma_neighboring_cells_count, &tdscdma_neighboring_cells, <e_neighboring_cells_count, <e_neighboring_cells, &cdma_cells_count, &cdma_cells, &error)); g_assert_no_error (error); g_assert (result); g_assert_null (gsm_serving_cell); g_assert_null (umts_serving_cell); g_assert_null (tdscdma_serving_cell); g_assert_nonnull (lte_serving_cell); g_assert_cmpuint (gsm_neighboring_cells_count, ==, 0); g_assert_null (gsm_neighboring_cells); g_assert_cmpuint (umts_neighboring_cells_count, ==, 0); g_assert_null (umts_neighboring_cells); g_assert_cmpuint (tdscdma_neighboring_cells_count, ==, 0); g_assert_null (tdscdma_neighboring_cells); g_assert_cmpuint (lte_neighboring_cells_count, ==, 1); g_assert_nonnull (lte_neighboring_cells); g_assert_cmpuint (cdma_cells_count, ==, 0); g_assert_null (cdma_cells); } static void test_ms_basic_connect_extensions_registration_parameters_0_unnamed_tlvs (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimMicoMode mico_mode; MbimDrxCycle drx_cycle; MbimLadnInfo ladn_info; MbimDefaultPduActivationHint pdu_hint; gboolean re_register_if_needed; GList *unnamed_ies = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x44, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x11, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x14, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* mico mode */ 0x00, 0x00, 0x00, 0x00, /* drx cycle */ 0x00, 0x00, 0x00, 0x00, /* ladn info */ 0x01, 0x00, 0x00, 0x00, /* pdu hint */ 0x01, 0x00, 0x00, 0x00, /* re register if needed */ /* no unnamed TLVs */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_extensions_v3_registration_parameters_response_parse ( response, &mico_mode, &drx_cycle, &ladn_info, &pdu_hint, &re_register_if_needed, &unnamed_ies, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (mico_mode, ==, MBIM_MICO_MODE_DISABLED); g_assert_cmpuint (drx_cycle, ==, MBIM_DRX_CYCLE_NOT_SPECIFIED); g_assert_cmpuint (ladn_info, ==, MBIM_LADN_INFO_NOT_NEEDED); g_assert_cmpuint (pdu_hint, ==, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY); g_assert_cmpuint (re_register_if_needed, ==, TRUE); g_assert_cmpuint (g_list_length (unnamed_ies), ==, 0); } static void test_ms_basic_connect_extensions_registration_parameters_1_unnamed_tlv (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimMicoMode mico_mode; MbimDrxCycle drx_cycle; MbimLadnInfo ladn_info; MbimDefaultPduActivationHint pdu_hint; gboolean re_register_if_needed; GList *unnamed_ies = NULL; MbimTlv *tlv; g_autofree gchar *tlv_str = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x58, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x11, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x28, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* mico mode */ 0x00, 0x00, 0x00, 0x00, /* drx cycle */ 0x00, 0x00, 0x00, 0x00, /* ladn info */ 0x01, 0x00, 0x00, 0x00, /* pdu hint */ 0x01, 0x00, 0x00, 0x00, /* re register if needed */ /* First unnamed TLV */ 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_extensions_v3_registration_parameters_response_parse ( response, &mico_mode, &drx_cycle, &ladn_info, &pdu_hint, &re_register_if_needed, &unnamed_ies, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (mico_mode, ==, MBIM_MICO_MODE_DISABLED); g_assert_cmpuint (drx_cycle, ==, MBIM_DRX_CYCLE_NOT_SPECIFIED); g_assert_cmpuint (ladn_info, ==, MBIM_LADN_INFO_NOT_NEEDED); g_assert_cmpuint (pdu_hint, ==, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY); g_assert_cmpuint (re_register_if_needed, ==, TRUE); g_assert_cmpuint (g_list_length (unnamed_ies), ==, 1); tlv = (MbimTlv *)(unnamed_ies->data); g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); tlv_str = mbim_tlv_string_get (tlv, &error); g_assert_no_error (error); g_assert_cmpstr (tlv_str, ==, "Orange"); g_list_free_full (unnamed_ies, (GDestroyNotify)mbim_tlv_unref); } static void test_ms_basic_connect_extensions_registration_parameters_3_unnamed_tlvs (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimMicoMode mico_mode; MbimDrxCycle drx_cycle; MbimLadnInfo ladn_info; MbimDefaultPduActivationHint pdu_hint; gboolean re_register_if_needed; GList *unnamed_ies = NULL; GList *iter; MbimTlv *tlv; g_autofree gchar *tlv_str_1 = NULL; const gchar *expected_tlv_str_1 = "abcde"; g_autofree gchar *tlv_str_2 = NULL; const gchar *expected_tlv_str_2 = "Orange"; const guint8 *pco_3 = NULL; guint32 pco_3_size = 0; const guint8 expected_pco[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B }; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x80, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x11, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x50, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* mico mode */ 0x00, 0x00, 0x00, 0x00, /* drx cycle */ 0x00, 0x00, 0x00, 0x00, /* ladn info */ 0x01, 0x00, 0x00, 0x00, /* pdu hint */ 0x01, 0x00, 0x00, 0x00, /* re register if needed */ /* First unnamed TLV */ 0x0A, 0x00, 0x00, 0x02, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, padding 2 */ 0x0A, 0x00, 0x00, 0x00, /* TLV data length */ 0x61, 0x00, 0x62, 0x00, /* TLV data string */ 0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x00, 0x00, /* Second unnamed TLV */ 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, /* Third unnamed TLV */ 0x0D, 0x00, 0x00, 0x01, /* TLV type MBIM_TLV_TYPE_PCO, padding 1 */ 0x0B, 0x00, 0x00, 0x00, /* TLV data length */ 0x01, 0x02, 0x03, 0x04, /* TLV data bytes */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x00, }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_extensions_v3_registration_parameters_response_parse ( response, &mico_mode, &drx_cycle, &ladn_info, &pdu_hint, &re_register_if_needed, &unnamed_ies, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (mico_mode, ==, MBIM_MICO_MODE_DISABLED); g_assert_cmpuint (drx_cycle, ==, MBIM_DRX_CYCLE_NOT_SPECIFIED); g_assert_cmpuint (ladn_info, ==, MBIM_LADN_INFO_NOT_NEEDED); g_assert_cmpuint (pdu_hint, ==, MBIM_DEFAULT_PDU_ACTIVATION_HINT_LIKELY); g_assert_cmpuint (re_register_if_needed, ==, TRUE); g_assert_cmpuint (g_list_length (unnamed_ies), ==, 3); iter = unnamed_ies; tlv = (MbimTlv *)(iter->data); g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); tlv_str_1 = mbim_tlv_string_get (tlv, &error); g_assert_no_error (error); g_assert_cmpstr (tlv_str_1, ==, expected_tlv_str_1); iter = g_list_next (iter); tlv = (MbimTlv *)(iter->data); g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); tlv_str_2 = mbim_tlv_string_get (tlv, &error); g_assert_no_error (error); g_assert_cmpstr (tlv_str_2, ==, expected_tlv_str_2); iter = g_list_next (iter); tlv = (MbimTlv *)(iter->data); g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_PCO); pco_3 = mbim_tlv_get_tlv_data (tlv, &pco_3_size); g_assert_cmpuint (pco_3_size, ==, sizeof (expected_pco)); g_assert (memcmp (pco_3, expected_pco, sizeof (expected_pco)) == 0); g_list_free_full (unnamed_ies, (GDestroyNotify)mbim_tlv_unref); } static void test_ms_basic_connect_v3_connect_0_unnamed_tlvs (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; GList *unnamed_ies = NULL; guint32 session_id; MbimActivationState activation_state; MbimVoiceCallState voice_call_state; MbimContextIpType ip_type; MbimAccessMediaType media_type = MBIM_ACCESS_MEDIA_TYPE_UNKNOWN; g_autofree gchar *access_string = NULL; const MbimUuid *context_type; guint32 nw_error; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x6C, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0C, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x3C, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* session id */ 0x01, 0x00, 0x00, 0x00, /* activation state */ 0x00, 0x00, 0x00, 0x00, /* voice call state */ 0x01, 0x00, 0x00, 0x00, /* ip type */ 0x7E, 0x5E, 0x2A, 0x7E, /* context type */ 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E, 0x00, 0x00, 0x00, 0x00, /* nw error */ 0x01, 0x00, 0x00, 0x00, /* media type */ 0x0A, 0x00, 0x00, 0x00, /* access string */ 0x10, 0x00, 0x00, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x74, 0x00, /* no unnamed TLVs */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_v3_connect_response_parse ( response, &session_id, &activation_state, &voice_call_state, &ip_type, &context_type, &nw_error, &media_type, &access_string, &unnamed_ies, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (session_id, ==, 1); g_assert_cmpuint (activation_state, ==, MBIM_ACTIVATION_STATE_ACTIVATED); g_assert_cmpuint (voice_call_state, ==, MBIM_VOICE_CALL_STATE_NONE); g_assert_cmpuint (ip_type, ==, MBIM_CONTEXT_IP_TYPE_IPV4); g_assert_cmpuint (mbim_uuid_to_context_type (context_type), ==, MBIM_CONTEXT_TYPE_INTERNET); g_assert_cmpuint (media_type, ==, MBIM_ACCESS_MEDIA_TYPE_3GPP); g_assert_cmpstr (access_string, ==, "internet"); g_assert_cmpuint (g_list_length (unnamed_ies), ==, 0); } static void test_ms_basic_connect_v3_connect_0_unnamed_tlvs_empty_access_string (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; GList *unnamed_ies = NULL; guint32 session_id; MbimActivationState activation_state; MbimVoiceCallState voice_call_state; MbimContextIpType ip_type; MbimAccessMediaType media_type = MBIM_ACCESS_MEDIA_TYPE_UNKNOWN; g_autofree gchar *access_string = NULL; const MbimUuid *context_type; guint32 nw_error; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x60, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0C, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x30, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* session id */ 0x01, 0x00, 0x00, 0x00, /* activation state */ 0x00, 0x00, 0x00, 0x00, /* voice call state */ 0x01, 0x00, 0x00, 0x00, /* ip type */ 0x7E, 0x5E, 0x2A, 0x7E, /* context type */ 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E, 0x00, 0x00, 0x00, 0x00, /* nw error */ 0x01, 0x00, 0x00, 0x00, /* media type */ 0x0A, 0x00, 0x00, 0x00, /* access string empty */ 0x00, 0x00, 0x00, 0x00, /* no unnamed TLVs */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_v3_connect_response_parse ( response, &session_id, &activation_state, &voice_call_state, &ip_type, &context_type, &nw_error, &media_type, &access_string, &unnamed_ies, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (session_id, ==, 1); g_assert_cmpuint (activation_state, ==, MBIM_ACTIVATION_STATE_ACTIVATED); g_assert_cmpuint (voice_call_state, ==, MBIM_VOICE_CALL_STATE_NONE); g_assert_cmpuint (ip_type, ==, MBIM_CONTEXT_IP_TYPE_IPV4); g_assert_cmpuint (mbim_uuid_to_context_type (context_type), ==, MBIM_CONTEXT_TYPE_INTERNET); g_assert_cmpuint (media_type, ==, MBIM_ACCESS_MEDIA_TYPE_3GPP); g_assert_cmpstr (access_string, ==, ""); g_assert_cmpuint (g_list_length (unnamed_ies), ==, 0); } static void test_ms_basic_connect_v3_connect_1_unnamed_tlv (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; GList *unnamed_ies = NULL; guint32 session_id; MbimActivationState activation_state; MbimVoiceCallState voice_call_state; MbimContextIpType ip_type; MbimAccessMediaType media_type = MBIM_ACCESS_MEDIA_TYPE_UNKNOWN; g_autofree gchar *access_string = NULL; const MbimUuid *context_type; guint32 nw_error; MbimTlv *tlv; g_autofree gchar *tlv_str = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x82, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0C, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x52, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* session id */ 0x01, 0x00, 0x00, 0x00, /* activation state */ 0x00, 0x00, 0x00, 0x00, /* voice call state */ 0x01, 0x00, 0x00, 0x00, /* ip type */ 0x7E, 0x5E, 0x2A, 0x7E, /* context type */ 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E, 0x00, 0x00, 0x00, 0x00, /* nw error */ 0x01, 0x00, 0x00, 0x00, /* media type */ 0x0A, 0x00, 0x00, 0x00, /* access string */ 0x10, 0x00, 0x00, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x74, 0x00, /* First unnamed TLV */ 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_v3_connect_response_parse ( response, &session_id, &activation_state, &voice_call_state, &ip_type, &context_type, &nw_error, &media_type, &access_string, &unnamed_ies, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (session_id, ==, 1); g_assert_cmpuint (activation_state, ==, MBIM_ACTIVATION_STATE_ACTIVATED); g_assert_cmpuint (voice_call_state, ==, MBIM_VOICE_CALL_STATE_NONE); g_assert_cmpuint (ip_type, ==, MBIM_CONTEXT_IP_TYPE_IPV4); g_assert_cmpuint (mbim_uuid_to_context_type (context_type), ==, MBIM_CONTEXT_TYPE_INTERNET); g_assert_cmpuint (media_type, ==, MBIM_ACCESS_MEDIA_TYPE_3GPP); g_assert_cmpstr (access_string, ==, "internet"); g_assert_cmpuint (g_list_length (unnamed_ies), ==, 1); tlv = (MbimTlv *)(unnamed_ies->data); g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); tlv_str = mbim_tlv_string_get (tlv, &error); g_assert_no_error (error); g_assert_cmpstr (tlv_str, ==, "Orange"); g_list_free_full (unnamed_ies, (GDestroyNotify)mbim_tlv_unref); } static void test_ms_basic_connect_v3_connect_3_unnamed_tlvs (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; GList *unnamed_ies = NULL; guint32 session_id; MbimActivationState activation_state; MbimVoiceCallState voice_call_state; MbimContextIpType ip_type; MbimAccessMediaType media_type = MBIM_ACCESS_MEDIA_TYPE_UNKNOWN; g_autofree gchar *access_string = NULL; const MbimUuid *context_type; guint32 nw_error; GList *iter; MbimTlv *tlv; g_autofree gchar *tlv_str_1 = NULL; const gchar *expected_tlv_str_1 = "abcde"; g_autofree gchar *tlv_str_2 = NULL; const gchar *expected_tlv_str_2 = "Orange"; const guint8 *pco_3 = NULL; guint32 pco_3_size = 0; const guint8 expected_pco[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B }; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0xAA, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0xA2, 0x89, 0xCC, 0x33, /* service id */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0C, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x7A, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* session id */ 0x01, 0x00, 0x00, 0x00, /* activation state */ 0x00, 0x00, 0x00, 0x00, /* voice call state */ 0x01, 0x00, 0x00, 0x00, /* ip type */ 0x7E, 0x5E, 0x2A, 0x7E, /* context type */ 0x4E, 0x6F, 0x72, 0x72, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E, 0x00, 0x00, 0x00, 0x00, /* nw error */ 0x01, 0x00, 0x00, 0x00, /* media type */ 0x0A, 0x00, 0x00, 0x00, /* access string */ 0x10, 0x00, 0x00, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x74, 0x00, /* First unnamed TLV */ 0x0A, 0x00, 0x00, 0x02, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, padding 2 */ 0x0A, 0x00, 0x00, 0x00, /* TLV data length */ 0x61, 0x00, 0x62, 0x00, /* TLV data string */ 0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x00, 0x00, /* Second unnamed TLV */ 0x0A, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WCHAR_STR, no padding */ 0x0C, 0x00, 0x00, 0x00, /* TLV data length */ 0x4F, 0x00, 0x72, 0x00, /* TLV data string */ 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65, 0x00, /* Third unnamed TLV */ 0x0D, 0x00, 0x00, 0x01, /* TLV type MBIM_TLV_TYPE_PCO, padding 1 */ 0x0B, 0x00, 0x00, 0x00, /* TLV data length */ 0x01, 0x02, 0x03, 0x04, /* TLV data bytes */ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x00, }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_v3_connect_response_parse ( response, &session_id, &activation_state, &voice_call_state, &ip_type, &context_type, &nw_error, &media_type, &access_string, &unnamed_ies, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (session_id, ==, 1); g_assert_cmpuint (activation_state, ==, MBIM_ACTIVATION_STATE_ACTIVATED); g_assert_cmpuint (voice_call_state, ==, MBIM_VOICE_CALL_STATE_NONE); g_assert_cmpuint (ip_type, ==, MBIM_CONTEXT_IP_TYPE_IPV4); g_assert_cmpuint (mbim_uuid_to_context_type (context_type), ==, MBIM_CONTEXT_TYPE_INTERNET); g_assert_cmpuint (media_type, ==, MBIM_ACCESS_MEDIA_TYPE_3GPP); g_assert_cmpstr (access_string, ==, "internet"); g_assert_cmpuint (g_list_length (unnamed_ies), ==, 3); iter = unnamed_ies; tlv = (MbimTlv *)(iter->data); g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); tlv_str_1 = mbim_tlv_string_get (tlv, &error); g_assert_no_error (error); g_assert_cmpstr (tlv_str_1, ==, expected_tlv_str_1); iter = g_list_next (iter); tlv = (MbimTlv *)(iter->data); g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_WCHAR_STR); tlv_str_2 = mbim_tlv_string_get (tlv, &error); g_assert_no_error (error); g_assert_cmpstr (tlv_str_2, ==, expected_tlv_str_2); iter = g_list_next (iter); tlv = (MbimTlv *)(iter->data); g_assert_cmpuint (mbim_tlv_get_tlv_type (tlv), ==, MBIM_TLV_TYPE_PCO); pco_3 = mbim_tlv_get_tlv_data (tlv, &pco_3_size); g_assert_cmpuint (pco_3_size, ==, sizeof (expected_pco)); g_assert (memcmp (pco_3, expected_pco, sizeof (expected_pco)) == 0); g_list_free_full (unnamed_ies, (GDestroyNotify)mbim_tlv_unref); } static void test_ms_basic_connect_extensions_device_caps_v3 (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimDeviceType device_type; MbimVoiceClass voice_class; MbimCellularClass cellular_class; MbimSimClass sim_class; MbimDataClassV3 data_class; MbimDataSubclass data_subclass; MbimSmsCaps sms_caps; MbimCtrlCaps ctrl_caps; guint32 max_sessions; guint32 wcdma_band_class = 0; guint32 lte_band_class_array_size = 0; g_autofree guint16 *lte_band_class_array = NULL; guint32 nr_band_class_array_size = 0; g_autofree guint16 *nr_band_class_array = NULL; g_autofree gchar *custom_data_class = NULL; g_autofree gchar *device_id = NULL; g_autofree gchar *firmware_info = NULL; g_autofree gchar *hardware_info = NULL; guint32 executor_index; static const guint16 expected_lte_band_class_array[] = { 1, 2, 3, 4, 5, 7, 8, 12, 13, 14, 17, 18, 19, 20, 25, 26, 28, 29, 30, 32, 34, 38, 39, 40, 41, 42, 43, 46, 48 }; static const guint16 expected_nr_band_class_array[] = { 1, 2, 3, 5, 7, 8, 20, 25, 28, 30, 38, 40, 41, 48, 66, 71, 77, 78, 79 }; const guint8 buffer [] = { 0x03, 0x00, 0x00, 0x80, 0x68, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x01, 0xDC, 0xC5, 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x02, 0x3A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x20, 0x00, 0x22, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x02, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x05, 0x00, 0x07, 0x00, 0x08, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1C, 0x00, 0x1E, 0x00, 0x26, 0x00, 0x28, 0x00, 0x29, 0x00, 0x30, 0x00, 0x42, 0x00, 0x47, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x00, 0x48, 0x00, 0x53, 0x00, 0x50, 0x00, 0x41, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x00, 0x38, 0x00, 0x36, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, 0x30, 0x00, 0x35, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x34, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x31, 0x00, 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x39, 0x00, 0x39, 0x00, 0x2E, 0x00, 0x32, 0x00, 0x39, 0x00, 0x2E, 0x00, 0x31, 0x00, 0x37, 0x00, 0x2E, 0x00, 0x31, 0x00, 0x39, 0x00, 0x5F, 0x00, 0x47, 0x00, 0x43, 0x00, 0x0D, 0x00, 0x0A, 0x00, 0x42, 0x00, 0x39, 0x00, 0x30, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x56, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x36, 0x00 }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_extensions_v3_device_caps_response_parse ( response, &device_type, &cellular_class, &voice_class, &sim_class, &data_class, &sms_caps, &ctrl_caps, &data_subclass, &max_sessions, &executor_index, &wcdma_band_class, <e_band_class_array_size, <e_band_class_array, &nr_band_class_array_size, &nr_band_class_array, &custom_data_class, &device_id, &firmware_info, &hardware_info, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (device_type, ==, MBIM_DEVICE_TYPE_EMBEDDED); g_assert_cmpuint (cellular_class, ==, MBIM_CELLULAR_CLASS_GSM); g_assert_cmpuint (voice_class, ==, MBIM_VOICE_CLASS_NO_VOICE); g_assert_cmpuint (sim_class, ==, MBIM_SIM_CLASS_REMOVABLE); g_assert_cmpuint (data_class, ==, (MBIM_DATA_CLASS_V3_UMTS | MBIM_DATA_CLASS_V3_HSDPA | MBIM_DATA_CLASS_V3_HSUPA | MBIM_DATA_CLASS_V3_LTE | MBIM_DATA_CLASS_V3_5G | MBIM_DATA_CLASS_V3_CUSTOM)); g_assert_cmpuint (sms_caps, ==, (MBIM_SMS_CAPS_PDU_RECEIVE | MBIM_SMS_CAPS_PDU_SEND)); g_assert_cmpuint (ctrl_caps, ==, (MBIM_CTRL_CAPS_REG_MANUAL | MBIM_CTRL_CAPS_HW_RADIO_SWITCH | MBIM_CTRL_CAPS_ESIM | MBIM_CTRL_CAPS_SIM_HOT_SWAP_CAPABLE)); g_assert_cmpuint (data_subclass, ==, (MBIM_DATA_SUBCLASS_5G_ENDC | MBIM_DATA_SUBCLASS_5G_NR)); g_assert_cmpuint (max_sessions, ==, 2); g_assert_cmpuint (executor_index, ==, 0); g_assert_cmpuint (wcdma_band_class, ==, (1 << (1 - 1) | 1 << (2 - 1) | 1 << (4 - 1) | 1 << (5 - 1) | 1 << (8 - 1))); g_assert_cmpuint (G_N_ELEMENTS (expected_lte_band_class_array), ==, lte_band_class_array_size); g_assert (memcmp (lte_band_class_array, expected_lte_band_class_array, lte_band_class_array_size * sizeof (guint16)) == 0); g_assert_cmpuint (G_N_ELEMENTS (expected_nr_band_class_array), ==, nr_band_class_array_size); g_assert (memcmp (nr_band_class_array, expected_nr_band_class_array, nr_band_class_array_size * sizeof (guint16)) == 0); g_assert_cmpstr (custom_data_class, ==, "HSPA+"); g_assert_cmpstr (device_id, ==, "862146050084555"); g_assert_cmpstr (firmware_info, ==, "81600.0000.99.29.17.19_GC\r\nB90"); g_assert_cmpstr (hardware_info, ==, "V1.0.6"); } static void test_ms_basic_connect_extensions_wake_reason_command (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimWakeType wake_type; guint32 session_id; g_autoptr(MbimTlv) wake_tlv = NULL; const MbimUuid *service = NULL; guint32 cid = 0; guint32 payload_size = 0; g_autofree guint8 *payload = NULL; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x5C, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x13, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x2C, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* wake type: cid indication */ 0x02, 0x00, 0x00, 0x00, /* session id */ /* TLV */ 0x10, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WAKE_COMMAND, padding 0 */ 0x1C, 0x00, 0x00, 0x00, /* TLV data length */ 0xA2, 0x89, 0xCC, 0x33, /* service id: basic connect */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0B, 0x00, 0x00, 0x00, /* command id: signal state */ 0x00, 0x00, 0x00, 0x00, /* payload offset: none */ 0x00, 0x00, 0x00, 0x00, /* payload size: none */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_extensions_v3_wake_reason_response_parse ( response, &wake_type, &session_id, &wake_tlv, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (wake_type, ==, MBIM_WAKE_TYPE_CID_INDICATION); g_assert_cmpuint (session_id, ==, 2); g_assert_nonnull (wake_tlv); g_assert_cmpuint (mbim_tlv_get_tlv_type (wake_tlv), ==, MBIM_TLV_TYPE_WAKE_COMMAND); result = (mbim_tlv_wake_command_get (wake_tlv, &service, &cid, &payload_size, &payload, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (mbim_uuid_to_service (service), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (cid, ==, MBIM_CID_BASIC_CONNECT_SIGNAL_STATE); g_assert_cmpuint (payload_size, ==, 0); g_assert_null (payload); } static void test_ms_basic_connect_extensions_wake_reason_command_payload (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimWakeType wake_type; guint32 session_id; g_autoptr(MbimTlv) wake_tlv = NULL; const MbimUuid *service = NULL; guint32 cid = 0; guint32 payload_size = 0; g_autofree guint8 *payload = NULL; guint32 payload_uint; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x60, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x13, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x30, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x00, 0x00, 0x00, 0x00, /* wake type: cid response */ 0x02, 0x00, 0x00, 0x00, /* session id */ /* TLV */ 0x10, 0x00, 0x00, 0x00, /* TLV type MBIM_TLV_TYPE_WAKE_COMMAND, padding 0 */ 0x20, 0x00, 0x00, 0x00, /* TLV data length */ 0xA2, 0x89, 0xCC, 0x33, /* service id: basic connect */ 0xBC, 0xBB, 0x8B, 0x4F, 0xB6, 0xB0, 0x13, 0x3E, 0xC2, 0xAA, 0xE6, 0xDF, 0x0C, 0x00, 0x00, 0x00, /* command id: connect */ 0x1C, 0x00, 0x00, 0x00, /* payload offset: 28 */ 0x04, 0x00, 0x00, 0x00, /* payload size: 4 */ 0x01, 0x00, 0x00, 0x00, /* payload: a guint32 */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_extensions_v3_wake_reason_response_parse ( response, &wake_type, &session_id, &wake_tlv, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (wake_type, ==, MBIM_WAKE_TYPE_CID_RESPONSE); g_assert_cmpuint (session_id, ==, 2); g_assert_nonnull (wake_tlv); g_assert_cmpuint (mbim_tlv_get_tlv_type (wake_tlv), ==, MBIM_TLV_TYPE_WAKE_COMMAND); result = (mbim_tlv_wake_command_get (wake_tlv, &service, &cid, &payload_size, &payload, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (mbim_uuid_to_service (service), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (cid, ==, MBIM_CID_BASIC_CONNECT_CONNECT); g_assert_cmpuint (payload_size, ==, 4); g_assert_nonnull (payload); memcpy (&payload_uint, payload, payload_size); payload_uint = GUINT32_FROM_LE (payload_uint); g_assert_cmpuint (payload_uint, ==, 1); } static void test_ms_basic_connect_extensions_wake_reason_packet (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimWakeType wake_type; guint32 session_id; g_autoptr(MbimTlv) wake_tlv = NULL; guint32 filter_id = 0; guint32 original_packet_size = 0; guint32 packet_size = 0; g_autofree guint8 *packet = NULL; const guint8 expected_packet[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A }; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x5C, 0x00, 0x00, 0x00, /* length */ 0x04, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done_message */ 0x3D, 0x01, 0xDC, 0xC5, /* service id */ 0xFE, 0xF5, 0x4D, 0x05, 0x0D, 0x3A, 0xBE, 0xF7, 0x05, 0x8E, 0x9A, 0xAF, 0x13, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x2C, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x02, 0x00, 0x00, 0x00, /* wake type: packet */ 0x02, 0x00, 0x00, 0x00, /* session id */ /* TLV */ 0x11, 0x00, 0x00, 0x02, /* TLV type MBIM_TLV_TYPE_WAKE_PACKET, padding 2 */ 0x1A, 0x00, 0x00, 0x00, /* TLV data length */ 0x0B, 0x00, 0x00, 0x00, /* filter id */ 0x0C, 0x00, 0x00, 0x00, /* original packet size: 12 */ 0x10, 0x00, 0x00, 0x00, /* packet offset: 16 */ 0x0A, 0x00, 0x00, 0x00, /* packet size: 10 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x00, 0x00, /* last 2 bytes padding */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 3, 0); result = (mbim_message_ms_basic_connect_extensions_v3_wake_reason_response_parse ( response, &wake_type, &session_id, &wake_tlv, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (wake_type, ==, MBIM_WAKE_TYPE_PACKET); g_assert_cmpuint (session_id, ==, 2); g_assert_nonnull (wake_tlv); g_assert_cmpuint (mbim_tlv_get_tlv_type (wake_tlv), ==, MBIM_TLV_TYPE_WAKE_PACKET); result = (mbim_tlv_wake_packet_get (wake_tlv, &filter_id, &original_packet_size, &packet_size, &packet, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (filter_id, ==, 0x0B); g_assert_cmpuint (original_packet_size, ==, 12); g_assert_cmpuint (packet_size, ==, sizeof (expected_packet)); g_assert_nonnull (packet); g_assert (memcmp (packet, expected_packet, sizeof (expected_packet)) == 0); } static void test_ms_uicc_low_level_access_application_list (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; guint32 version; guint32 application_count; guint32 active_application_index; guint32 application_list_size_bytes; g_autoptr(MbimUiccApplicationArray) applications = NULL; const guint8 expected_application_id[] = { 0xA0, 0x00, 0x00, 0x00, 0x87, 0x10, 0x02, 0xFF, 0x34, 0xFF, 0x07, 0x89, 0x31, 0x2E, 0x30, 0xFF }; const gchar *expected_application_name = "Movistar"; const guint8 expected_pin_key_references[] = { 0x01, 0x81 }; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x84, 0x00, 0x00, 0x00, /* length */ 0x03, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done message */ 0xC2, 0xF6, 0x58, 0x8E, /* service id */ 0xF0, 0x37, 0x4B, 0xC9, 0x86, 0x65, 0xF4, 0xD4, 0x4B, 0xD0, 0x93, 0x67, 0x07, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x54, 0x00, 0x00, 0x00, /* buffer_length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* version: 1 */ 0x01, 0x00, 0x00, 0x00, /* app count: 1 */ 0x00, 0x00, 0x00, 0x00, /* active app index: 0 */ 0x3C, 0x00, 0x00, 0x00, /* app list size bytes: 60 */ 0x18, 0x00, 0x00, 0x00, /* application 0 offset: 24 bytes */ 0x3C, 0x00, 0x00, 0x00, /* application 0 length: 60 bytes */ /* application 0 */ 0x04, 0x00, 0x00, 0x00, /* application type: usim */ 0x20, 0x00, 0x00, 0x00, /* application id offset: 32 bytes */ 0x10, 0x00, 0x00, 0x00, /* application id length: 16 bytes */ 0x30, 0x00, 0x00, 0x00, /* application name offset: 48 bytes */ 0x08, 0x00, 0x00, 0x00, /* application name length: 8 bytes */ 0x02, 0x00, 0x00, 0x00, /* num pin key refs: 2 */ 0x38, 0x00, 0x00, 0x00, /* pin key refs offset: 56 bytes */ 0x02, 0x00, 0x00, 0x00, /* pin key refs length: 2 bytes */ /* application 0 databuffer */ 0xA0, 0x00, 0x00, 0x00, /* application id */ 0x87, 0x10, 0x02, 0xFF, 0x34, 0xFF, 0x07, 0x89, 0x31, 0x2E, 0x30, 0xFF, 0x4D, 0x6F, 0x76, 0x69, /* application name */ 0x73, 0x74, 0x61, 0x72, 0x01, 0x81, 0x00, 0x00, /* pin key refs plus 2 padding bytes */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); result = (mbim_message_ms_uicc_low_level_access_application_list_response_parse ( response, &version, &application_count, &active_application_index, &application_list_size_bytes, &applications, &error)); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (version, ==, 1); g_assert_cmpuint (application_count, ==, 1); g_assert_cmpuint (active_application_index, ==, 0); g_assert_cmpuint (application_list_size_bytes, ==, 60); g_assert_cmpuint (applications[0]->application_id_size, ==, sizeof (expected_application_id)); g_assert (memcmp (applications[0]->application_id, expected_application_id, sizeof (expected_application_id)) == 0); g_assert (g_strcmp0 (applications[0]->application_name, expected_application_name) == 0); g_assert_cmpuint (applications[0]->pin_key_reference_count, ==, 2); g_assert_cmpuint (applications[0]->pin_key_references_size, ==, sizeof (expected_pin_key_references)); g_assert (memcmp (applications[0]->pin_key_references, expected_pin_key_references, sizeof (expected_pin_key_references)) == 0); } static void test_google_carrier_lock (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimCarrierLockStatus carrier_lock_status; MbimCarrierLockModemState modem_state; MbimCarrierLockCause carrier_lock_cause; const guint8 buffer [] = { /* header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x3C, 0x00, 0x00, 0x00, /* length */ 0x03, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done message */ 0x3E, 0x1E, 0x92, 0xCF, /* service id */ 0xC5, 0x3D, 0x4F, 0x14, 0x85, 0xD0, 0xA8, 0x6A, 0xD9, 0xE1, 0x22, 0x45, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x0C, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* carrier lock status*/ 0x00, 0x00, 0x00, 0x00, /* modem state */ 0x00, 0x00, 0x00, 0x00, /* carrier lock cause */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); result = mbim_message_google_carrier_lock_response_parse ( response, &carrier_lock_status, &modem_state, &carrier_lock_cause, &error); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (carrier_lock_status, ==, MBIM_CARRIER_LOCK_STATUS_APPLIED); g_assert_cmpuint (modem_state, ==, MBIM_CARRIER_LOCK_MODEM_STATE_DEREGISTERED); g_assert_cmpuint (carrier_lock_cause, ==, MBIM_CARRIER_LOCK_CAUSE_NOT_APPLICABLE); } static void test_google_carrier_lock_notification (void) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response = NULL; gboolean result; MbimCarrierLockStatus carrier_lock_status; MbimCarrierLockModemState modem_state; MbimCarrierLockCause carrier_lock_cause; const guint8 buffer [] = { /* header */ 0x07, 0x00, 0x00, 0x80, /* type */ 0x38, 0x00, 0x00, 0x00, /* length */ 0x03, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command_done message */ 0x3E, 0x1E, 0x92, 0xCF, /* service id */ 0xC5, 0x3D, 0x4F, 0x14, 0x85, 0xD0, 0xA8, 0x6A, 0xD9, 0xE1, 0x22, 0x45, 0x01, 0x00, 0x00, 0x00, /* command id */ 0x0C, 0x00, 0x00, 0x00, /* buffer length */ /* information buffer */ 0x01, 0x00, 0x00, 0x00, /* carrier lock status */ 0x00, 0x00, 0x00, 0x00, /* modem state */ 0x00, 0x00, 0x00, 0x00, /* carrier lock cause */ }; response = mbim_message_new (buffer, sizeof (buffer)); g_assert (mbim_message_validate (response, &error)); g_assert_no_error (error); test_message_printable (response, 1, 0); result = mbim_message_google_carrier_lock_notification_parse ( response, &carrier_lock_status, &modem_state, &carrier_lock_cause, &error); g_assert_no_error (error); g_assert (result); g_assert_cmpuint (carrier_lock_status, ==, MBIM_CARRIER_LOCK_STATUS_APPLIED); g_assert_cmpuint (modem_state, ==, MBIM_CARRIER_LOCK_MODEM_STATE_DEREGISTERED); g_assert_cmpuint (carrier_lock_cause, ==, MBIM_CARRIER_LOCK_CAUSE_NOT_APPLICABLE); } int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); #define PREFIX "/libmbim-glib/message/parser" g_test_add_func (PREFIX "/basic-connect/visible-providers", test_basic_connect_visible_providers); g_test_add_func (PREFIX "/basic-connect/subscriber-ready-status", test_basic_connect_subscriber_ready_status); g_test_add_func (PREFIX "/basic-connect/device-caps", test_basic_connect_device_caps); g_test_add_func (PREFIX "/basic-connect/ip-configuration/1", test_basic_connect_ip_configuration); g_test_add_func (PREFIX "/basic-connect/ip-configuration/2", test_basic_connect_ip_configuration_2); g_test_add_func (PREFIX "/basic-connect/service-activation", test_basic_connect_service_activation); g_test_add_func (PREFIX "/basic-connect/register-state", test_basic_connect_register_state); g_test_add_func (PREFIX "/basic-connect/provisioned-contexts", test_provisioned_contexts); g_test_add_func (PREFIX "/sms/read/zero-pdu", test_sms_read_zero_pdu); g_test_add_func (PREFIX "/sms/read/single-pdu", test_sms_read_single_pdu); g_test_add_func (PREFIX "/sms/read/multiple-pdu", test_sms_read_multiple_pdu); g_test_add_func (PREFIX "/ussd", test_ussd); g_test_add_func (PREFIX "/auth/akap", test_auth_akap); g_test_add_func (PREFIX "/stk/pac/notification", test_stk_pac_notification); g_test_add_func (PREFIX "/stk/pac/response", test_stk_pac_response); g_test_add_func (PREFIX "/stk/terminal/response", test_stk_terminal_response); g_test_add_func (PREFIX "/stk/envelope/response", test_stk_envelope_response); g_test_add_func (PREFIX "/basic-connect/ip-packet-filters/none", test_basic_connect_ip_packet_filters_none); g_test_add_func (PREFIX "/basic-connect/ip-packet-filters/one", test_basic_connect_ip_packet_filters_one); g_test_add_func (PREFIX "/basic-connect/ip-packet-filters/two", test_basic_connect_ip_packet_filters_two); g_test_add_func (PREFIX "/ms-firmware-id/get", test_ms_firmware_id_get); g_test_add_func (PREFIX "/basic-connect/connect/short", test_basic_connect_connect_short); g_test_add_func (PREFIX "/basic-connect/visible-providers/overflow", test_basic_connect_visible_providers_overflow); g_test_add_func (PREFIX "/basic-connect-extensions/base-stations", test_ms_basic_connect_extensions_base_stations); g_test_add_func (PREFIX "/basic-connect-extensions/registration-parameters/0-unnamed-tlvs", test_ms_basic_connect_extensions_registration_parameters_0_unnamed_tlvs); g_test_add_func (PREFIX "/basic-connect-extensions/registration-parameters/1-unnamed-tlv", test_ms_basic_connect_extensions_registration_parameters_1_unnamed_tlv); g_test_add_func (PREFIX "/basic-connect-extensions/registration-parameters/3-unnamed-tlvs", test_ms_basic_connect_extensions_registration_parameters_3_unnamed_tlvs); g_test_add_func (PREFIX "/basic-connect-v3/connect/0-unnamed-tlvs", test_ms_basic_connect_v3_connect_0_unnamed_tlvs); g_test_add_func (PREFIX "/basic-connect-v3/connect/0-unnamed-tlvs-empty-access-string", test_ms_basic_connect_v3_connect_0_unnamed_tlvs_empty_access_string); g_test_add_func (PREFIX "/basic-connect-v3/connect/1-unnamed-tlv", test_ms_basic_connect_v3_connect_1_unnamed_tlv); g_test_add_func (PREFIX "/basic-connect-v3/connect/3-unnamed-tlvs", test_ms_basic_connect_v3_connect_3_unnamed_tlvs); g_test_add_func (PREFIX "/basic-connect-extensions/device-caps-v3", test_ms_basic_connect_extensions_device_caps_v3); g_test_add_func (PREFIX "/basic-connect-extensions/wake-reason/command", test_ms_basic_connect_extensions_wake_reason_command); g_test_add_func (PREFIX "/basic-connect-extensions/wake-reason/command/payload", test_ms_basic_connect_extensions_wake_reason_command_payload); g_test_add_func (PREFIX "/basic-connect-extensions/wake-reason/packet", test_ms_basic_connect_extensions_wake_reason_packet); g_test_add_func (PREFIX "/ms-uicc-low-level-access/application-list", test_ms_uicc_low_level_access_application_list); g_test_add_func (PREFIX "/google/carrier-lock-response", test_google_carrier_lock); g_test_add_func (PREFIX "/google/carrier-lock-notify", test_google_carrier_lock_notification); #undef PREFIX return g_test_run (); } libmbim-1.31.2-dev/src/libmbim-glib/test/test-message.c000066400000000000000000000473461453630424100226460ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2014 Aleksander Morgado */ #include #include #include "mbim-message.h" #include "mbim-cid.h" #include "mbim-error-types.h" static void test_message_open (void) { MbimMessage *message; GError *error = NULL; message = mbim_message_open_new (12345, 4096); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 12345); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_OPEN); g_assert_cmpuint (mbim_message_get_message_length (message), ==, 16); g_assert_cmpuint (mbim_message_open_get_max_control_transfer (message), ==, 4096); mbim_message_unref (message); } static void test_message_open_done (void) { MbimMessage *message; GError *error = NULL; const guint8 buffer [] = { 0x01, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_OPEN_DONE); g_assert_cmpuint (mbim_message_get_message_length (message), ==, 16); g_assert_cmpuint (mbim_message_open_done_get_status_code (message), ==, MBIM_STATUS_ERROR_NONE); mbim_message_unref (message); } static void test_message_close (void) { MbimMessage *message; GError *error = NULL; message = mbim_message_close_new (12345); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 12345); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_CLOSE); g_assert_cmpuint (mbim_message_get_message_length (message), ==, 12); mbim_message_unref (message); } static void test_message_close_done (void) { MbimMessage *message; GError *error = NULL; const guint8 buffer [] = { 0x02, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_CLOSE_DONE); g_assert_cmpuint (mbim_message_get_message_length (message), ==, 16); g_assert_cmpuint (mbim_message_close_done_get_status_code (message), ==, MBIM_STATUS_ERROR_NONE); mbim_message_unref (message); } static void test_message_command_empty (void) { MbimMessage *message; GError *error = NULL; guint32 len; message = mbim_message_command_new (12345, MBIM_SERVICE_BASIC_CONNECT, MBIM_CID_BASIC_CONNECT_DEVICE_CAPS, MBIM_MESSAGE_COMMAND_TYPE_QUERY); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 12345); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, 48); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_DEVICE_CAPS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_QUERY); g_assert (mbim_message_command_get_raw_information_buffer (message, &len) == NULL); g_assert_cmpuint (len, ==, 0); mbim_message_unref (message); } static void test_message_command_not_empty (void) { MbimMessage *message; const guint8 *buffer; guint32 len; GError *error = NULL; const guint8 information_buffer [] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; message = mbim_message_command_new (12345, MBIM_SERVICE_BASIC_CONNECT, MBIM_CID_BASIC_CONNECT_DEVICE_CAPS, MBIM_MESSAGE_COMMAND_TYPE_QUERY); g_assert (message != NULL); mbim_message_command_append (message, information_buffer, sizeof (information_buffer)); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 12345); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND); g_assert_cmpuint (mbim_message_get_message_length (message), ==, 56); g_assert_cmpuint (mbim_message_command_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_DEVICE_CAPS); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_QUERY); buffer = mbim_message_command_get_raw_information_buffer (message, &len); g_assert (buffer != NULL); g_assert_cmpuint (len, ==, sizeof (information_buffer)); g_assert (memcmp (&information_buffer, buffer, sizeof (information_buffer)) == 0); mbim_message_unref (message); } static void test_message_command_custom_service (void) { static const gchar *nick = "My custom service"; static const MbimUuid uuid_custom = { .a = { 0x11, 0x22, 0x33, 0x44 }, .b = { 0x11, 0x11 }, .c = { 0x22, 0x22 }, .d = { 0x33, 0x33 }, .e = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; guint service; MbimMessage *message; GError *error = NULL; service = mbim_register_custom_service (&uuid_custom, nick); g_assert (mbim_service_id_is_custom (service)); message = mbim_message_command_new (0x01, service, 0x11223344, MBIM_MESSAGE_COMMAND_TYPE_QUERY); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); g_assert_cmpuint (mbim_message_command_get_service (message), ==, service); g_assert (mbim_uuid_cmp (mbim_message_command_get_service_id (message), &uuid_custom)); g_assert_cmpuint (mbim_message_command_get_cid (message), ==, 0x11223344); g_assert_cmpuint (mbim_message_command_get_command_type (message), ==, MBIM_MESSAGE_COMMAND_TYPE_QUERY); mbim_message_unref (message); } static void test_message_command_done (void) { MbimMessage *message; GError *error = NULL; const guint8 buffer [] = { 0x03, 0x00, 0x00, 0x80, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x89, 0xcc, 0x33, 0xbc, 0xbb, 0x8b, 0x4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const guint8 expected_information_buffer [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const guint8 *out_information_buffer; guint32 len; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (message != NULL); g_assert (mbim_message_validate (message, &error)); g_assert_no_error (error); g_assert_cmpuint (mbim_message_get_transaction_id (message), ==, 1); g_assert_cmpuint (mbim_message_get_message_type (message), ==, MBIM_MESSAGE_TYPE_COMMAND_DONE); g_assert_cmpuint (mbim_message_get_message_length (message), ==, 60); g_assert_cmpuint (mbim_message_command_done_get_service (message), ==, MBIM_SERVICE_BASIC_CONNECT); g_assert_cmpuint (mbim_message_command_done_get_cid (message), ==, MBIM_CID_BASIC_CONNECT_PIN); g_assert_cmpuint (mbim_message_command_done_get_status_code (message), ==, MBIM_STATUS_ERROR_NONE); out_information_buffer = mbim_message_command_done_get_raw_information_buffer (message, &len); g_assert (buffer != NULL); g_assert_cmpuint (len, ==, sizeof (expected_information_buffer)); g_assert (memcmp (&expected_information_buffer, out_information_buffer, sizeof (expected_information_buffer)) == 0); mbim_message_unref (message); } static void test_message_command_done_short (void) { gsize len; const guint8 buffer [] = { 0x03, 0x00, 0x00, 0x80, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x89, 0xcc, 0x33, 0xbc, 0xbb, 0x8b, 0x4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* If no full message received, always return INCOMPLETE_MESSAGE, which is * the indication given to the reader in MbimDevice or MbimProxy to keep on * reading without discarding the already read data. */ for (len = 0; len < sizeof (buffer); len++) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; message = mbim_message_new (buffer, len); g_assert (message != NULL); g_assert (!mbim_message_validate (message, &error)); g_assert_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INCOMPLETE_MESSAGE); } } static void test_message_command_done_invalid_type_header (void) { /* This message will be invalid because the size of the message must be at least * 48 bytes for a command-done message type. */ guint8 buffer [] = { /* generic mbim header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x00, 0x00, 0x00, 0x00, /* length -- this will be modified in the test*/ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command done header */ 0xa2, 0x89, 0xcc, 0x33, /* service id */ 0xbc, 0xbb, 0x8b, 0x4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf, 0x04, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x00, 0x00, 0x00, 0x00, /* buffer length */ /* no buffer */ }; guint len; /* If no full message received, always return INCOMPLETE_MESSAGE, which is * the indication given to the reader in MbimDevice or MbimProxy to keep on * reading without discarding the already read data. */ for (len = 12; len < sizeof (buffer); len++) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; /* all our lengths are < 0xFF so we only have to modify 1 byte */ buffer[4] = len; message = mbim_message_new (buffer, len); g_assert (message != NULL); g_assert (!mbim_message_validate (message, &error)); g_assert_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE); } } static void test_message_command_done_invalid_buffer_length (void) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; /* This message will be invalid because the buffer length would span out of the bounds * imposed by the full message length */ const guint8 buffer [] = { /* generic mbim header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x30, 0x00, 0x00, 0x00, /* length 40 bytes, expects 0 bytes in the information buffer */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command done header */ 0xa2, 0x89, 0xcc, 0x33, /* service id */ 0xbc, 0xbb, 0x8b, 0x4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf, 0x04, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x04, 0x00, 0x00, 0x00, /* buffer length: 4 bytes, which is 4 more than expected */ /* simple buffer buffer */ 0x00, 0x00, 0x00, 0x00 }; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (message != NULL); g_assert (!mbim_message_validate (message, &error)); g_assert_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE); } static void test_message_command_done_invalid_fragment_total (void) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; guint8 buffer [] = { /* generic mbim header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x30, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x00, 0x00, 0x00, 0x00, /* total cannot be 0! */ 0x00, 0x00, 0x00, 0x00, /* current */ /* command done header */ 0xa2, 0x89, 0xcc, 0x33, /* service id */ 0xbc, 0xbb, 0x8b, 0x4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf, 0x04, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x00, 0x00, 0x00, 0x00, /* no buffer */ }; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (message != NULL); g_assert (!mbim_message_validate (message, &error)); g_assert_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE); } static void test_message_command_done_invalid_complate_fragment_current (void) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; guint8 buffer [] = { /* generic mbim header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x30, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x01, 0x00, 0x00, 0x00, /* total */ 0x01, 0x00, 0x00, 0x00, /* current must be 0! */ /* command done header */ 0xa2, 0x89, 0xcc, 0x33, /* service id */ 0xbc, 0xbb, 0x8b, 0x4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf, 0x04, 0x00, 0x00, 0x00, /* command id */ 0x00, 0x00, 0x00, 0x00, /* status code */ 0x00, 0x00, 0x00, 0x00, /* no buffer */ }; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (message != NULL); g_assert (!mbim_message_validate (message, &error)); g_assert_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE); } static void test_message_command_done_invalid_partial_fragment_current (void) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; guint8 buffer [] = { /* generic mbim header */ 0x03, 0x00, 0x00, 0x80, /* type */ 0x30, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ /* fragment header */ 0x02, 0x00, 0x00, 0x00, /* total */ 0x05, 0x00, 0x00, 0x00, /* current must be < total! */ /* fragment data */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (message != NULL); g_assert (!mbim_message_validate (message, &error)); g_assert_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE); } static void test_message_invalid_type (void) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; const guint8 buffer [] = { /* generic mbim header */ 0x03, 0xAB, 0xCD, 0x80, /* unknown type */ 0x0C, 0x00, 0x00, 0x00, /* length */ 0x01, 0x00, 0x00, 0x00, /* transaction id */ }; message = mbim_message_new (buffer, sizeof (buffer)); g_assert (message != NULL); g_assert (!mbim_message_validate (message, &error)); g_assert_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE); } int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/libmbim-glib/message/open", test_message_open); g_test_add_func ("/libmbim-glib/message/open-done", test_message_open_done); g_test_add_func ("/libmbim-glib/message/close", test_message_close); g_test_add_func ("/libmbim-glib/message/close-done", test_message_close_done); g_test_add_func ("/libmbim-glib/message/command/empty", test_message_command_empty); g_test_add_func ("/libmbim-glib/message/command/not-empty", test_message_command_not_empty); g_test_add_func ("/libmbim-glib/message/command/custom-service", test_message_command_custom_service); g_test_add_func ("/libmbim-glib/message/command-done", test_message_command_done); g_test_add_func ("/libmbim-glib/message/command-done/short", test_message_command_done_short); g_test_add_func ("/libmbim-glib/message/command-done/invalid-type-header", test_message_command_done_invalid_type_header); g_test_add_func ("/libmbim-glib/message/command-done/invalid-buffer-length", test_message_command_done_invalid_buffer_length); g_test_add_func ("/libmbim-glib/message/command-done/invalid-fragment-total", test_message_command_done_invalid_fragment_total); g_test_add_func ("/libmbim-glib/message/command-done/invalid-complete-fragment-current", test_message_command_done_invalid_complate_fragment_current); g_test_add_func ("/libmbim-glib/message/command-done/invalid-partial-fragment-current", test_message_command_done_invalid_partial_fragment_current); g_test_add_func ("/libmbim-glib/message/invalid-type", test_message_invalid_type); return g_test_run (); } libmbim-1.31.2-dev/src/libmbim-glib/test/test-proxy-helpers.c000066400000000000000000000406321453630424100240320ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Aleksander Morgado */ #include #include #include "mbim-cid.h" #include "mbim-uuid.h" #include "mbim-basic-connect.h" #include "mbim-proxy-helpers.h" /*****************************************************************************/ static void test_parse_single_service_0_cids (void) { MbimMessage *message; MbimEventEntry **in; MbimEventEntry **out; GError *error = NULL; gsize out_size = 0; in = g_new0 (MbimEventEntry *, 2); in[0] = g_new0 (MbimEventEntry, 1); memcpy (&in[0]->device_service_id, MBIM_UUID_BASIC_CONNECT, sizeof (MbimUuid)); in[0]->cids_count = 0; in[0]->cids = NULL; message = mbim_message_device_service_subscribe_list_set_new (1, (const MbimEventEntry *const *)in, &error); g_assert_no_error (error); g_assert (message != NULL); out = _mbim_proxy_helper_service_subscribe_request_parse (message, &out_size, &error); g_assert_no_error (error); g_assert (out != NULL); g_assert (_mbim_proxy_helper_service_subscribe_list_cmp ((const MbimEventEntry * const *)in, 1, (const MbimEventEntry * const *)out, out_size)); g_assert_cmpuint (out_size, ==, 1); mbim_message_unref (message); mbim_event_entry_array_free (in); mbim_event_entry_array_free (out); } static void test_parse_single_service_1_cids (void) { MbimMessage *message; MbimEventEntry **in; MbimEventEntry **out; GError *error = NULL; gsize out_size = 0; in = g_new0 (MbimEventEntry *, 2); in[0] = g_new0 (MbimEventEntry, 1); memcpy (&in[0]->device_service_id, MBIM_UUID_BASIC_CONNECT, sizeof (MbimUuid)); in[0]->cids_count = 1; in[0]->cids = g_new0 (guint32, in[0]->cids_count); in[0]->cids[0] = MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS; message = mbim_message_device_service_subscribe_list_set_new (1, (const MbimEventEntry *const *)in, &error); g_assert_no_error (error); g_assert (message != NULL); out = _mbim_proxy_helper_service_subscribe_request_parse (message, &out_size, &error); g_assert_no_error (error); g_assert (out != NULL); g_assert (_mbim_proxy_helper_service_subscribe_list_cmp ((const MbimEventEntry * const *)in, 1, (const MbimEventEntry * const *)out, out_size)); g_assert_cmpuint (out_size, ==, 1); mbim_message_unref (message); mbim_event_entry_array_free (in); mbim_event_entry_array_free (out); } static void test_parse_single_service_5_cids (void) { MbimMessage *message; MbimEventEntry **in; MbimEventEntry **out; GError *error = NULL; gsize out_size = 0; in = g_new0 (MbimEventEntry *, 2); in[0] = g_new0 (MbimEventEntry, 1); memcpy (&in[0]->device_service_id, MBIM_UUID_BASIC_CONNECT, sizeof (MbimUuid)); in[0]->cids_count = 5; in[0]->cids = g_new0 (guint32, in[0]->cids_count); in[0]->cids[0] = MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS; in[0]->cids[1] = MBIM_CID_BASIC_CONNECT_RADIO_STATE; in[0]->cids[2] = MBIM_CID_BASIC_CONNECT_SIGNAL_STATE; in[0]->cids[3] = MBIM_CID_BASIC_CONNECT_IP_CONFIGURATION; in[0]->cids[4] = MBIM_CID_BASIC_CONNECT_NETWORK_IDLE_HINT; message = mbim_message_device_service_subscribe_list_set_new (1, (const MbimEventEntry *const *)in, &error); g_assert_no_error (error); g_assert (message != NULL); out = _mbim_proxy_helper_service_subscribe_request_parse (message, &out_size, &error); g_assert_no_error (error); g_assert (out != NULL); g_assert (_mbim_proxy_helper_service_subscribe_list_cmp ((const MbimEventEntry * const *)in, 1, (const MbimEventEntry * const *)out, out_size)); g_assert_cmpuint (out_size, ==, 1); mbim_message_unref (message); mbim_event_entry_array_free (in); mbim_event_entry_array_free (out); } /*****************************************************************************/ static void test_merge_none (void) { MbimEventEntry **list = NULL; gsize list_size = 0; gsize out_size = 0; /* merge */ list = _mbim_proxy_helper_service_subscribe_list_merge (list, list_size, NULL, 0, &out_size); g_assert (list == NULL); g_assert_cmpuint (out_size, ==, 0); } static void test_merge_standard_services (void) { MbimEventEntry **list = NULL; gsize list_size = 0; MbimEventEntry **addition; gsize addition_size; gsize out_size = 0; /* setup a new list with a subset of standard services */ addition_size = 2; addition = g_new0 (MbimEventEntry *, addition_size + 1); addition[0] = g_new0 (MbimEventEntry, 1); memcpy (&addition[0]->device_service_id, MBIM_UUID_BASIC_CONNECT, sizeof (MbimUuid)); addition[0]->cids_count = 5; addition[0]->cids = g_new0 (guint32, addition[0]->cids_count); addition[0]->cids[0] = MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS; addition[0]->cids[1] = MBIM_CID_BASIC_CONNECT_RADIO_STATE; addition[0]->cids[2] = MBIM_CID_BASIC_CONNECT_SIGNAL_STATE; addition[0]->cids[3] = MBIM_CID_BASIC_CONNECT_IP_CONFIGURATION; addition[0]->cids[4] = MBIM_CID_BASIC_CONNECT_NETWORK_IDLE_HINT; addition[1] = g_new0 (MbimEventEntry, 1); memcpy (&addition[1]->device_service_id, MBIM_UUID_SMS, sizeof (MbimUuid)); addition[1]->cids_count = 2; addition[1]->cids = g_new0 (guint32, addition[1]->cids_count); addition[1]->cids[0] = MBIM_CID_SMS_READ; addition[1]->cids[1] = MBIM_CID_SMS_SEND; /* merge */ list = _mbim_proxy_helper_service_subscribe_list_merge (list, list_size, addition, addition_size, &out_size); /* The new list should be empty, as standard services are ignored */ g_assert (list == NULL); g_assert_cmpuint (out_size, ==, 0); mbim_event_entry_array_free (addition); } static void test_merge_other_services (void) { MbimEventEntry **list = NULL; gsize list_size = 0; MbimEventEntry **addition; gsize addition_size; gsize out_size = 0; /* setup a new list with a subset of other services */ addition_size = 2; addition = g_new0 (MbimEventEntry *, addition_size + 1); addition[0] = g_new0 (MbimEventEntry, 1); memcpy (&addition[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); addition[0]->cids_count = 5; addition[0]->cids = g_new0 (guint32, addition[0]->cids_count); addition[0]->cids[0] = MBIM_CID_ATDS_SIGNAL; addition[0]->cids[1] = MBIM_CID_ATDS_LOCATION; addition[0]->cids[2] = MBIM_CID_ATDS_OPERATORS; addition[0]->cids[3] = MBIM_CID_ATDS_RAT; addition[0]->cids[4] = MBIM_CID_ATDS_REGISTER_STATE; addition[1] = g_new0 (MbimEventEntry, 1); memcpy (&addition[1]->device_service_id, MBIM_UUID_QMI, sizeof (MbimUuid)); addition[1]->cids_count = 1; addition[1]->cids = g_new0 (guint32, addition[1]->cids_count); addition[1]->cids[0] = MBIM_CID_QMI_MSG; /* merge */ list = _mbim_proxy_helper_service_subscribe_list_merge (list, list_size, addition, addition_size, &out_size); /* The new list should be totally equal to the addition, as the original list was empty. */ g_assert (_mbim_proxy_helper_service_subscribe_list_cmp ((const MbimEventEntry * const *)list, out_size, (const MbimEventEntry * const *)addition, addition_size)); mbim_event_entry_array_free (list); mbim_event_entry_array_free (addition); } static void test_merge_list_same_service (void) { MbimEventEntry **list; gsize list_size; MbimEventEntry **addition; gsize addition_size; MbimEventEntry **expected; gsize expected_size; gsize out_size = 0; /* setup a new list with a subset of non-standard services */ list_size = 1; list = g_new0 (MbimEventEntry *, list_size + 1); list[0] = g_new0 (MbimEventEntry, 1); memcpy (&list[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); list[0]->cids_count = 2; list[0]->cids = g_new0 (guint32, list[0]->cids_count); list[0]->cids[0] = MBIM_CID_ATDS_SIGNAL; list[0]->cids[1] = MBIM_CID_ATDS_LOCATION; /* setup a new list with a subset of non-standard services */ addition_size = 1; addition = g_new0 (MbimEventEntry *, addition_size + 1); addition[0] = g_new0 (MbimEventEntry, 1); memcpy (&addition[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); addition[0]->cids_count = 3; addition[0]->cids = g_new0 (guint32, addition[0]->cids_count); addition[0]->cids[0] = MBIM_CID_ATDS_OPERATORS; addition[0]->cids[1] = MBIM_CID_ATDS_RAT; addition[0]->cids[2] = MBIM_CID_ATDS_REGISTER_STATE; /* merge */ list = _mbim_proxy_helper_service_subscribe_list_merge (list, list_size, addition, addition_size, &out_size); /* setup the expected list */ expected_size = 1; expected = g_new0 (MbimEventEntry *, expected_size + 1); expected[0] = g_new0 (MbimEventEntry, 1); memcpy (&expected[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); expected[0]->cids_count = 5; expected[0]->cids = g_new0 (guint32, expected[0]->cids_count); expected[0]->cids[0] = MBIM_CID_ATDS_SIGNAL; expected[0]->cids[1] = MBIM_CID_ATDS_LOCATION; expected[0]->cids[2] = MBIM_CID_ATDS_OPERATORS; expected[0]->cids[3] = MBIM_CID_ATDS_RAT; expected[0]->cids[4] = MBIM_CID_ATDS_REGISTER_STATE; /* Compare */ g_assert (_mbim_proxy_helper_service_subscribe_list_cmp ((const MbimEventEntry * const *)list, out_size, (const MbimEventEntry * const *)expected, expected_size)); mbim_event_entry_array_free (list); mbim_event_entry_array_free (addition); mbim_event_entry_array_free (expected); } static void test_merge_list_different_services (void) { MbimEventEntry **list; gsize list_size; MbimEventEntry **addition; gsize addition_size; MbimEventEntry **expected; gsize expected_size; gsize out_size = 0; /* setup a new list with a subset of non-standard services */ list_size = 1; list = g_new0 (MbimEventEntry *, list_size + 1); list[0] = g_new0 (MbimEventEntry, 1); memcpy (&list[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); list[0]->cids_count = 2; list[0]->cids = g_new0 (guint32, list[0]->cids_count); list[0]->cids[0] = MBIM_CID_ATDS_SIGNAL; list[0]->cids[1] = MBIM_CID_ATDS_LOCATION; /* setup a new list with a subset of non-standard services */ addition_size = 1; addition = g_new0 (MbimEventEntry *, addition_size + 1); addition[0] = g_new0 (MbimEventEntry, 1); memcpy (&addition[0]->device_service_id, MBIM_UUID_QMI, sizeof (MbimUuid)); addition[0]->cids_count = 1; addition[0]->cids = g_new0 (guint32, addition[0]->cids_count); addition[0]->cids[0] = MBIM_CID_QMI_MSG; /* merge */ list = _mbim_proxy_helper_service_subscribe_list_merge (list, list_size, addition, addition_size, &out_size); /* setup the expected list */ expected_size = 2; expected = g_new0 (MbimEventEntry *, expected_size + 1); expected[0] = g_new0 (MbimEventEntry, 1); memcpy (&expected[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); expected[0]->cids_count = 2; expected[0]->cids = g_new0 (guint32, expected[0]->cids_count); expected[0]->cids[0] = MBIM_CID_ATDS_SIGNAL; expected[0]->cids[1] = MBIM_CID_ATDS_LOCATION; expected[1] = g_new0 (MbimEventEntry, 1); memcpy (&expected[1]->device_service_id, MBIM_UUID_QMI, sizeof (MbimUuid)); expected[1]->cids_count = 1; expected[1]->cids = g_new0 (guint32, expected[1]->cids_count); expected[1]->cids[0] = MBIM_CID_QMI_MSG; /* Compare */ g_assert (_mbim_proxy_helper_service_subscribe_list_cmp ((const MbimEventEntry * const *)list, out_size, (const MbimEventEntry * const *)expected, expected_size)); mbim_event_entry_array_free (list); mbim_event_entry_array_free (addition); mbim_event_entry_array_free (expected); } static void test_merge_list_merged_services (void) { MbimEventEntry **list; gsize list_size; MbimEventEntry **addition; gsize addition_size; MbimEventEntry **expected; gsize expected_size; gsize out_size = 0; /* setup a new list with a subset of non-standard services */ list_size = 2; list = g_new0 (MbimEventEntry *, list_size + 1); list[0] = g_new0 (MbimEventEntry, 1); memcpy (&list[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); list[0]->cids_count = 3; list[0]->cids = g_new0 (guint32, list[0]->cids_count); list[0]->cids[0] = MBIM_CID_ATDS_SIGNAL; list[0]->cids[1] = MBIM_CID_ATDS_LOCATION; list[0]->cids[2] = MBIM_CID_ATDS_OPERATORS; list[1] = g_new0 (MbimEventEntry, 1); memcpy (&list[1]->device_service_id, MBIM_UUID_QMI, sizeof (MbimUuid)); list[1]->cids_count = 1; list[1]->cids = g_new0 (guint32, list[1]->cids_count); list[1]->cids[0] = MBIM_CID_QMI_MSG; /* setup a new list with a subset of standard and non-standard services */ addition_size = 2; addition = g_new0 (MbimEventEntry *, addition_size + 1); addition[0] = g_new0 (MbimEventEntry, 1); memcpy (&addition[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); addition[0]->cids_count = 1; addition[0]->cids = g_new0 (guint32, addition[0]->cids_count); addition[0]->cids[0] = MBIM_CID_ATDS_RAT; addition[1] = g_new0 (MbimEventEntry, 1); memcpy (&addition[1]->device_service_id, MBIM_UUID_MS_HOST_SHUTDOWN, sizeof (MbimUuid)); addition[1]->cids_count = 1; addition[1]->cids = g_new0 (guint32, addition[1]->cids_count); addition[1]->cids[0] = MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY; /* merge */ list = _mbim_proxy_helper_service_subscribe_list_merge (list, list_size, addition, addition_size, &out_size); /* setup the expected list */ expected_size = 3; expected = g_new0 (MbimEventEntry *, expected_size + 1); expected[0] = g_new0 (MbimEventEntry, 1); memcpy (&expected[0]->device_service_id, MBIM_UUID_ATDS, sizeof (MbimUuid)); expected[0]->cids_count = 4; expected[0]->cids = g_new0 (guint32, expected[0]->cids_count); expected[0]->cids[0] = MBIM_CID_ATDS_SIGNAL; expected[0]->cids[1] = MBIM_CID_ATDS_LOCATION; expected[0]->cids[2] = MBIM_CID_ATDS_OPERATORS; expected[0]->cids[3] = MBIM_CID_ATDS_RAT; expected[1] = g_new0 (MbimEventEntry, 1); memcpy (&expected[1]->device_service_id, MBIM_UUID_QMI, sizeof (MbimUuid)); expected[1]->cids_count = 1; expected[1]->cids = g_new0 (guint32, expected[1]->cids_count); expected[1]->cids[0] = MBIM_CID_QMI_MSG; expected[2] = g_new0 (MbimEventEntry, 1); memcpy (&expected[2]->device_service_id, MBIM_UUID_MS_HOST_SHUTDOWN, sizeof (MbimUuid)); expected[2]->cids_count = 1; expected[2]->cids = g_new0 (guint32, expected[2]->cids_count); expected[2]->cids[0] = MBIM_CID_MS_HOST_SHUTDOWN_NOTIFY; /* Compare */ g_assert (_mbim_proxy_helper_service_subscribe_list_cmp ((const MbimEventEntry * const *)list, out_size, (const MbimEventEntry * const *)expected, expected_size)); mbim_event_entry_array_free (list); mbim_event_entry_array_free (addition); mbim_event_entry_array_free (expected); } /*****************************************************************************/ int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/libmbim-glib/proxy/parse/single-service/0", test_parse_single_service_0_cids); g_test_add_func ("/libmbim-glib/proxy/parse/single-service/1", test_parse_single_service_1_cids); g_test_add_func ("/libmbim-glib/proxy/parse/single-service/5", test_parse_single_service_5_cids); g_test_add_func ("/libmbim-glib/proxy/merge/none", test_merge_none); g_test_add_func ("/libmbim-glib/proxy/merge/standard", test_merge_standard_services); g_test_add_func ("/libmbim-glib/proxy/merge/other", test_merge_other_services); g_test_add_func ("/libmbim-glib/proxy/merge/same-service", test_merge_list_same_service); g_test_add_func ("/libmbim-glib/proxy/merge/different-services", test_merge_list_different_services); g_test_add_func ("/libmbim-glib/proxy/merge/merged-services", test_merge_list_merged_services); return g_test_run (); } libmbim-1.31.2-dev/src/libmbim-glib/test/test-uuid.c000066400000000000000000000155261453630424100221630ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2014 Aleksander Morgado */ #include #include "mbim-uuid.h" static void compare_uuid_strings (const MbimUuid *uuid, const gchar *other_uuid_str) { gchar *uuid_str; uuid_str = mbim_uuid_get_printable (uuid); g_assert_cmpstr (uuid_str, ==, other_uuid_str); g_free (uuid_str); } static void test_uuid_basic_connect (void) { compare_uuid_strings (MBIM_UUID_BASIC_CONNECT, "a289cc33-bcbb-8b4f-b6b0-133ec2aae6df"); } static void test_uuid_sms (void) { compare_uuid_strings (MBIM_UUID_SMS, "533fbeeb-14fe-4467-9f90-33a223e56c3f"); } static void test_uuid_ussd (void) { compare_uuid_strings (MBIM_UUID_USSD, "e550a0c8-5e82-479e-82f7-10abf4c3351f"); } static void test_uuid_phonebook (void) { compare_uuid_strings (MBIM_UUID_PHONEBOOK, "4bf38476-1e6a-41db-b1d8-bed289c25bdb"); } static void test_uuid_stk (void) { compare_uuid_strings (MBIM_UUID_STK, "d8f20131-fcb5-4e17-8602-d6ed3816164c"); } static void test_uuid_auth (void) { compare_uuid_strings (MBIM_UUID_AUTH, "1d2b5ff7-0aa1-48b2-aa52-50f15767174e"); } static void test_uuid_dss (void) { compare_uuid_strings (MBIM_UUID_DSS, "c08a26dd-7718-4382-8482-6e0d583c4d0e"); } static void test_uuid_ms_firmware_id (void) { compare_uuid_strings (MBIM_UUID_MS_FIRMWARE_ID, "e9f7dea2-feaf-4009-93ce-90a3694103b6"); } static void test_uuid_ms_host_shutdown (void) { compare_uuid_strings (MBIM_UUID_MS_HOST_SHUTDOWN, "883b7c26-985f-43fa-9804-27d7fb80959c"); } static void test_uuid_ms_sar (void) { compare_uuid_strings (MBIM_UUID_MS_SAR, "68223d04-9f6c-4e0f-822d-28441fb72340"); } static void test_uuid_intel_firmware_update (void) { compare_uuid_strings (MBIM_UUID_INTEL_FIRMWARE_UPDATE, "0ed374cb-f835-4474-bc11-3b3fd76f5641"); } static void test_uuid_ms_basic_connect_extensions (void) { compare_uuid_strings (MBIM_UUID_MS_BASIC_CONNECT_EXTENSIONS, "3d01dcc5-fef5-4d05-0d3a-bef7058e9aaf"); } static void test_uuid_quectel (void) { compare_uuid_strings (MBIM_UUID_QUECTEL, "11223344-5566-7788-99aa-bbccddeeff11"); } /*****************************************************************************/ static void compare_uuid_types (const gchar *uuid_str, const MbimUuid *other_uuid) { MbimUuid uuid; g_assert (mbim_uuid_from_printable (uuid_str, &uuid)); g_assert (mbim_uuid_cmp (&uuid, other_uuid)); } static void invalid_uuid_str (const gchar *uuid_str) { MbimUuid uuid; g_assert (mbim_uuid_from_printable (uuid_str, &uuid) == FALSE); } static void test_uuid_valid (void) { compare_uuid_types ("a289cc33-bcbb-8b4f-b6b0-133ec2aae6df", MBIM_UUID_BASIC_CONNECT); } static void test_uuid_valid_camelcase (void) { compare_uuid_types ("A289cC33-BcBb-8B4f-B6b0-133Ec2Aae6Df", MBIM_UUID_BASIC_CONNECT); } static void test_uuid_invalid_empty (void) { invalid_uuid_str (""); } static void test_uuid_invalid_short (void) { invalid_uuid_str ("a289cc33-bcbb-8b4f-b6b0-"); } static void test_uuid_invalid_long (void) { invalid_uuid_str ("a289cc33-bcbb-8b4f-b6b0-133ec2aae6dfaaa"); } static void test_uuid_invalid_dashes (void) { /* Dashes one too early */ invalid_uuid_str ("289cc33-bcbb-8b4f-b6b0-133ec2aae6dfa"); } static void test_uuid_invalid_no_hex (void) { invalid_uuid_str ("hello wo-rld -8b4f-b6b0-133ec2aae6df"); } /*****************************************************************************/ static void test_uuid_custom (void) { static const gchar *nick = "register_custom"; static const MbimUuid uuid_custom = { .a = { 0x52, 0x65, 0x67, 0x69 }, .b = { 0x73, 0x74 }, .c = { 0x65, 0x72 }, .d = { 0x20, 0x63 }, .e = { 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x21 } }; guint service; /* SERVICE_AUTH is not a custom service */ g_assert (!mbim_service_id_is_custom (MBIM_SERVICE_AUTH)); service = mbim_register_custom_service (&uuid_custom, nick); g_assert (mbim_service_id_is_custom (service)); g_assert (g_strcmp0 (mbim_service_lookup_name (service), nick) == 0); g_assert (mbim_uuid_cmp (mbim_uuid_from_service (service), &uuid_custom)); g_assert (mbim_uuid_to_service (&uuid_custom) == service); g_assert (mbim_unregister_custom_service (service)); /* once removed service is not custom */ g_assert (!mbim_service_id_is_custom (service)); } /*****************************************************************************/ int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/libmbim-glib/uuid/basic-connect", test_uuid_basic_connect); g_test_add_func ("/libmbim-glib/uuid/sms", test_uuid_sms); g_test_add_func ("/libmbim-glib/uuid/ussd", test_uuid_ussd); g_test_add_func ("/libmbim-glib/uuid/phonebook", test_uuid_phonebook); g_test_add_func ("/libmbim-glib/uuid/stk", test_uuid_stk); g_test_add_func ("/libmbim-glib/uuid/auth", test_uuid_auth); g_test_add_func ("/libmbim-glib/uuid/dss", test_uuid_dss); g_test_add_func ("/libmbim-glib/uuid/ms-firmware-id", test_uuid_ms_firmware_id); g_test_add_func ("/libmbim-glib/uuid/ms-host-shutdown", test_uuid_ms_host_shutdown); g_test_add_func ("/libmbim-glib/uuid/ms-sar", test_uuid_ms_sar); g_test_add_func ("/libmbim-glib/uuid/intel-firmware-update", test_uuid_intel_firmware_update); g_test_add_func ("/libmbim-glib/uuid/ms-basic-connect-extensions", test_uuid_ms_basic_connect_extensions); g_test_add_func ("/libmbim-glib/uuid/quectel", test_uuid_quectel); g_test_add_func ("/libmbim-glib/uuid/valid", test_uuid_valid); g_test_add_func ("/libmbim-glib/uuid/valid/camelcase", test_uuid_valid_camelcase); g_test_add_func ("/libmbim-glib/uuid/invalid/empty", test_uuid_invalid_empty); g_test_add_func ("/libmbim-glib/uuid/invalid/short", test_uuid_invalid_short); g_test_add_func ("/libmbim-glib/uuid/invalid/long", test_uuid_invalid_long); g_test_add_func ("/libmbim-glib/uuid/invalid/dashes", test_uuid_invalid_dashes); g_test_add_func ("/libmbim-glib/uuid/invalid/no-hex", test_uuid_invalid_no_hex); g_test_add_func ("/libmbim-glib/uuid/custom", test_uuid_custom); return g_test_run (); } libmbim-1.31.2-dev/src/mbim-proxy/000077500000000000000000000000001453630424100166615ustar00rootroot00000000000000libmbim-1.31.2-dev/src/mbim-proxy/mbim-proxy.c000066400000000000000000000171501453630424100211340ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbim-proxy -- A proxy to communicate with MBIM ports * * Copyright (C) 2014-2023 Aleksander Morgado * Copyright (C) 2014 Smith Micro Software, Inc. */ #include "config.h" #include #include #include #include #include #include #include #include #include #define PROGRAM_NAME "mbim-proxy" #define PROGRAM_VERSION PACKAGE_VERSION #define EMPTY_TIMEOUT_DEFAULT 300 /* Globals */ static GMainLoop *loop; static MbimProxy *proxy; static guint timeout_id; static guint client_connected_once = FALSE; /* Main options */ static gboolean verbose_flag; static gboolean verbose_full_flag; static gboolean version_flag; static gboolean no_exit_flag; static gint empty_timeout = -1; static GOptionEntry main_entries[] = { { "no-exit", 0, 0, G_OPTION_ARG_NONE, &no_exit_flag, "Don't exit after being idle without clients/devices", NULL }, { "empty-timeout", 0, 0, G_OPTION_ARG_INT, &empty_timeout, "If no clients/devices, exit after this timeout. If set to 0, equivalent to --no-exit.", "[SECS]" }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose_flag, "Run action with verbose logs, including the debug ones", NULL }, { "verbose-full", 'v', 0, G_OPTION_ARG_NONE, &verbose_full_flag, "Run action with verbose logs, including the debug ones and personal info", NULL }, { "version", 'V', 0, G_OPTION_ARG_NONE, &version_flag, "Print version", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; static gboolean quit_cb (gpointer user_data) { if (loop) { g_warning ("Caught signal, stopping the loop..."); g_idle_add ((GSourceFunc) g_main_loop_quit, loop); } return FALSE; } static void log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { const gchar *log_level_str; time_t now; gchar time_str[64]; struct tm *local_time; gboolean err = FALSE; switch (log_level) { case G_LOG_LEVEL_WARNING: log_level_str = "-Warning **"; err = TRUE; break; case G_LOG_LEVEL_CRITICAL: case G_LOG_FLAG_FATAL: case G_LOG_LEVEL_ERROR: log_level_str = "-Error **"; err = TRUE; break; case G_LOG_LEVEL_DEBUG: log_level_str = "[Debug]"; break; case G_LOG_LEVEL_MESSAGE: case G_LOG_LEVEL_INFO: log_level_str = ""; break; case G_LOG_LEVEL_MASK: case G_LOG_FLAG_RECURSION: default: g_assert_not_reached (); } if (!verbose_flag && !verbose_full_flag && !err) return; now = time ((time_t *) NULL); local_time = localtime (&now); strftime (time_str, 64, "%d %b %Y, %H:%M:%S", local_time); g_fprintf (err ? stderr : stdout, "[%s] %s %s\n", time_str, log_level_str, message); } G_GNUC_NORETURN static void print_version_and_exit (void) { g_print ("\n" PROGRAM_NAME " " PROGRAM_VERSION "\n" "Copyright (C) 2013-2023 Aleksander Morgado\n" "Copyright (C) 2014-2018 Greg Suarez\n" "License GPLv2+: GNU GPL version 2 or later \n" "This is free software: you are free to change and redistribute it.\n" "There is NO WARRANTY, to the extent permitted by law.\n" "\n"); exit (EXIT_SUCCESS); } /*****************************************************************************/ static gboolean stop_loop_cb (void) { timeout_id = 0; if (loop) g_main_loop_quit (loop); return FALSE; } static void proxy_n_clients_changed (MbimProxy *_proxy) { /* once a client has connected only exit if there are no devices */ if (client_connected_once) return; if (mbim_proxy_get_n_clients (proxy) == 0) { g_assert (timeout_id == 0); g_assert (empty_timeout > 0); timeout_id = g_timeout_add_seconds (empty_timeout, (GSourceFunc)stop_loop_cb, NULL); return; } /* At least one client, remove timeout if any */ if (timeout_id) { g_source_remove (timeout_id); timeout_id = 0; } client_connected_once = TRUE; } static void proxy_n_devices_changed (MbimProxy *_proxy) { if (mbim_proxy_get_n_devices (proxy) == 0) { g_assert (timeout_id == 0); g_assert (empty_timeout > 0); timeout_id = g_timeout_add_seconds (empty_timeout, (GSourceFunc)stop_loop_cb, NULL); return; } /* At least one device, remove timeout if any */ if (timeout_id) { g_source_remove (timeout_id); timeout_id = 0; } } /*****************************************************************************/ int main (int argc, char **argv) { g_autoptr(GError) error = NULL; g_autoptr(GOptionContext) context = NULL; setlocale (LC_ALL, ""); /* Setup option context, process it and destroy it */ context = g_option_context_new ("- Proxy for MBIM devices"); g_option_context_add_main_entries (context, main_entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("error: %s\n", error->message); exit (EXIT_FAILURE); } if (version_flag) print_version_and_exit (); g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, NULL); g_log_set_handler ("Mbim", G_LOG_LEVEL_MASK, log_handler, NULL); if (verbose_flag && verbose_full_flag) { g_printerr ("error: cannot specify --verbose and --verbose-full at the same time\n"); exit (EXIT_FAILURE); } else if (verbose_flag) { mbim_utils_set_traces_enabled (TRUE); mbim_utils_set_show_personal_info (FALSE); } else if (verbose_full_flag) { mbim_utils_set_traces_enabled (TRUE); mbim_utils_set_show_personal_info (TRUE); } /* Setup signals */ g_unix_signal_add (SIGINT, quit_cb, NULL); g_unix_signal_add (SIGHUP, quit_cb, NULL); g_unix_signal_add (SIGTERM, quit_cb, NULL); /* Setup empty timeout */ if (empty_timeout < 0) empty_timeout = EMPTY_TIMEOUT_DEFAULT; /* Setup proxy */ proxy = mbim_proxy_new (&error); if (!proxy) { g_printerr ("error: %s\n", error->message); exit (EXIT_FAILURE); } /* Don't exit the proxy when no clients/devices are found */ if (!no_exit_flag && empty_timeout != 0) { g_debug ("proxy will exit after %d secs if unused", empty_timeout); proxy_n_clients_changed (proxy); g_signal_connect (proxy, "notify::" MBIM_PROXY_N_CLIENTS, G_CALLBACK (proxy_n_clients_changed), NULL); g_signal_connect (proxy, "notify::" MBIM_PROXY_N_DEVICES, G_CALLBACK (proxy_n_devices_changed), NULL); } else g_debug ("proxy will remain running if unused"); /* Loop */ loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); g_main_loop_unref (loop); /* Cleanup; releases socket and such */ g_object_unref (proxy); g_debug ("exiting 'mbim-proxy'..."); return EXIT_SUCCESS; } libmbim-1.31.2-dev/src/mbim-proxy/meson.build000066400000000000000000000004421453630424100210230ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez name = 'mbim-proxy' executable( name, sources: name + '.c', include_directories: top_inc, dependencies: libmbim_glib_dep, install: true, install_dir: mbim_libexecdir, ) libmbim-1.31.2-dev/src/mbimcli/000077500000000000000000000000001453630424100161725ustar00rootroot00000000000000libmbim-1.31.2-dev/src/mbimcli/mbimcli000066400000000000000000000051331453630424100175330ustar00rootroot00000000000000# mbimcli(1) completion -*- shell-script -*- # SPDX-License-Identifier: GPL-2.0-or-later # # Copyright (C) 2015 Aleksander Morgado _mbimcli() { local cur prev words cword split _init_completion -s || return case $prev in '-d'|'--device') _filedir return 0 ;; '--no-open') COMPREPLY=( $(compgen -W "[Transaction-ID]" -- $cur) ) return 0 ;; '--set-radio-state') COMPREPLY=( $(compgen -W "[(on|off)]" -- $cur) ) return 0 ;; '--enter-pin') COMPREPLY=( $(compgen -W "[current-PIN]" -- $cur) ) return 0 ;; '--change-pin') COMPREPLY=( $(compgen -W "[(current-PIN),(new-PIN)]" -- $cur) ) return 0 ;; '--enable-pin') COMPREPLY=( $(compgen -W "[current-PIN]" -- $cur) ) return 0 ;; '--disable-pin') COMPREPLY=( $(compgen -W "[current-PIN]" -- $cur) ) return 0 ;; '--enter-puk') COMPREPLY=( $(compgen -W "[(PUK),(new-PIN)]" -- $cur) ) return 0 ;; '--connect') COMPREPLY=( $(compgen -W "[(APN),(PAP|CHAP|MSCHAPV2),(Username),(Password)]" -- $cur) ) return 0 ;; '--phonebook-read') COMPREPLY=( $(compgen -W "[(Phonebook-index)]" -- $cur) ) return 0 ;; '--phonebook-write') COMPREPLY=( $(compgen -W "[(Name),(Number)[,(Index)]]" -- $cur) ) return 0 ;; '--phonebook-delete') COMPREPLY=( $(compgen -W "[(Phonebook-index)]" -- $cur) ) return 0 ;; '--dss-connect') COMPREPLY=( $(compgen -W "[(UUID),(Session-ID)]" -- $cur) ) return 0 ;; '--dss-disconnect') COMPREPLY=( $(compgen -W "[(UUID),(Session-ID)]" -- $cur) ) return 0 ;; '-V'|'--version') return 0 ;; '-h'|'--help'|'--help-all'|'--help-basic-connect'|'--help-phonebook'|'--help-dss'|'--help-ms-firmware-id'|'--help-ms-host-shutdown'|'--help-ms-sar') return 0 ;; esac $split && return 0 if [[ $cur == -* ]]; then COMPREPLY=( $( compgen -W '$( _parse_help "$1" --help-all )' -- "$cur" ) ) [[ $COMPREPLY == *= ]] && compopt -o nospace return 0 fi } && complete -F _mbimcli mbimcli # ex: ts=4 sw=4 et filetype=sh libmbim-1.31.2-dev/src/mbimcli/mbimcli-atds.c000066400000000000000000000207111453630424100207040ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2017 Red Hat, Inc. */ #include "config.h" #include #include #include #include #include #include #include #include "mbimcli.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean query_signal_flag; static gboolean query_location_flag; static GOptionEntry entries[] = { { "atds-query-signal", 0, 0, G_OPTION_ARG_NONE, &query_signal_flag, "Query signal info", NULL }, { "atds-query-location", 0, 0, G_OPTION_ARG_NONE, &query_location_flag, "Query cell location", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_atds_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("atds", "AT&T Device Service options:", "Show AT&T Device Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_atds_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (query_signal_flag + query_location_flag); if (n_actions > 1) { g_printerr ("error: too many AT&T Device Service actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void query_signal_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autofree gchar *rssi_str = NULL; g_autofree gchar *error_rate_str = NULL; g_autofree gchar *rscp_str = NULL; g_autofree gchar *ecno_str = NULL; g_autofree gchar *rsrq_str = NULL; g_autofree gchar *rsrp_str = NULL; g_autofree gchar *rssnr_str = NULL; guint32 rssi = 0, error_rate = 0, rscp = 0, ecno = 0, rsrq = 0, rsrp = 0, rssnr = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_atds_signal_response_parse ( response, &rssi, &error_rate, &rscp, &ecno, &rsrq, &rsrp, &rssnr, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } if (rssi <= 31) rssi_str = g_strdup_printf ("%d dBm", -113 + (2 * rssi)); switch (error_rate) { case 0: error_rate_str = g_strdup_printf ("< 0.2%%"); break; case 1: error_rate_str = g_strdup_printf ("0.2%% - 0.39%%"); break; case 2: error_rate_str = g_strdup_printf ("0.4%% - 0.79%%"); break; case 3: error_rate_str = g_strdup_printf ("0.8%% - 1.59%%"); break; case 4: error_rate_str = g_strdup_printf ("1.6%% - 3.19%%"); break; case 5: error_rate_str = g_strdup_printf ("3.2%% - 6.39%%"); break; case 6: error_rate_str = g_strdup_printf ("6.4%% - 12.79%%"); break; case 7: error_rate_str = g_strdup_printf ("> 12.8%%"); break; default: error_rate_str = g_strdup_printf ("unknown (%u)", error_rate); break; } if (rscp == 0) rscp_str = g_strdup_printf ("< -120 dBm"); else if (rscp < 96) rscp_str = g_strdup_printf ("%d dBm", -120 + rscp); else if (rscp == 96) rscp_str = g_strdup_printf (">= -24 dBm"); if (ecno == 0) ecno_str = g_strdup_printf ("< -24 dBm"); else if (ecno < 49) ecno_str = g_strdup_printf ("%.2lf dBm", -24.0 + ((gdouble)ecno / 2)); else if (ecno == 49) ecno_str = g_strdup_printf (">= 0.5 dBm"); if (rsrq == 0) rsrq_str = g_strdup_printf ("< -19.5 dBm"); else if (rsrq < 34) rsrq_str = g_strdup_printf ("%.2lf dBm", -19.5 + ((gdouble)rsrq / 2)); else if (rsrq == 34) rsrq_str = g_strdup_printf (">= -2.5 dBm"); if (rsrp == 0) rsrp_str = g_strdup_printf ("< -140 dBm"); else if (rsrp < 97) rsrp_str = g_strdup_printf ("%d dBm", -140 + rsrp); else if (rsrp == 97) rsrp_str = g_strdup_printf (">= -43 dBm"); if (rssnr == 0) rssnr_str = g_strdup_printf ("< -5 dB"); else if (rssnr < 35) rssnr_str = g_strdup_printf ("%d dB", -5 + rssnr); else if (rssnr == 35) rssnr_str = g_strdup_printf (">= 30 dB"); g_print ("[%s] Signal info retrieved:\n" "\t RSSI: %s\n" "\t BER: %s\n" "\t RSCP: %s\n" "\t Ec/No: %s\n" "\t RSRQ: %s\n" "\t RSRP: %s\n" "\t RSSNR: %s\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (rssi_str), VALIDATE_UNKNOWN (error_rate_str), VALIDATE_UNKNOWN (rscp_str), VALIDATE_UNKNOWN (ecno_str), VALIDATE_UNKNOWN (rsrq_str), VALIDATE_UNKNOWN (rsrp_str), VALIDATE_UNKNOWN (rssnr_str)); shutdown (TRUE); } static void query_location_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 lac = 0, tac = 0, cellid = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_atds_location_response_parse ( response, &lac, &tac, &cellid, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Cell location retrieved:\n" "\t LAC: %04x\n" "\t TAC: %04x\n" "\t Cell ID: %04x\n", mbim_device_get_path_display (device), lac, tac, cellid); shutdown (TRUE); } void mbimcli_atds_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to get signal info? */ if (query_signal_flag) { g_debug ("Asynchronously querying signal info..."); request = (mbim_message_atds_signal_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_signal_ready, NULL); return; } /* Request to get cell location? */ if (query_location_flag) { g_debug ("Asynchronously querying cell location..."); request = (mbim_message_atds_location_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_location_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-basic-connect.c000066400000000000000000003613321453630424100224700ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbim-common.h" #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean query_device_caps_flag; static gboolean query_subscriber_ready_status_flag; static gboolean query_radio_state_flag; static gchar *set_radio_state_str; static gboolean query_device_services_flag; static gboolean query_pin_flag; static gchar *set_pin_enter_str; static gchar *set_pin_change_str; static gchar *set_pin_enable_str; static gchar *set_pin_disable_str; static gchar *set_pin_enter_puk_str; static gboolean query_pin_list_flag; static gboolean query_home_provider_flag; static gboolean query_preferred_providers_flag; static gboolean query_visible_providers_flag; static gboolean query_register_state_flag; static gboolean set_register_state_automatic_flag; static gboolean query_signal_state_flag; static gboolean query_packet_service_flag; static gboolean set_packet_service_attach_flag; static gboolean set_packet_service_detach_flag; static gchar *query_connect_str; static gchar *set_connect_activate_str; static gchar *query_ip_configuration_str; static gchar *set_connect_deactivate_str; static gboolean query_packet_statistics_flag; static gchar *query_ip_packet_filters_str; static gchar *set_ip_packet_filters_str; static gboolean query_provisioned_contexts_flag; static gchar *set_provisioned_contexts_str; static gchar *set_signal_state_str; static gchar *set_network_idle_hint_str; static gboolean query_network_idle_hint_flag; static gchar *set_emergency_mode_str; static gboolean query_emergency_mode_flag; static gchar *set_service_activation_str; static gboolean query_connection_state_arg_parse (const char *option_name, const char *value, gpointer user_data, GError **error); static gboolean query_ip_configuration_arg_parse (const char *option_name, const char *value, gpointer user_data, GError **error); static gboolean disconnect_arg_parse (const char *option_name, const char *value, gpointer user_data, GError **error); static gboolean query_ip_packet_filters_arg_parse (const char *option_name, const char *value, gpointer user_data, GError **error); static GOptionEntry entries[] = { { "query-device-caps", 0, 0, G_OPTION_ARG_NONE, &query_device_caps_flag, "Query device capabilities", NULL }, { "query-subscriber-ready-status", 0, 0, G_OPTION_ARG_NONE, &query_subscriber_ready_status_flag, "Query subscriber ready status", NULL }, { "query-radio-state", 0, 0, G_OPTION_ARG_NONE, &query_radio_state_flag, "Query radio state", NULL }, { "set-radio-state", 0, 0, G_OPTION_ARG_STRING, &set_radio_state_str, "Set radio state", "[(on|off)]" }, { "query-device-services", 0, 0, G_OPTION_ARG_NONE, &query_device_services_flag, "Query device services", NULL }, { "query-pin-state", 0, 0, G_OPTION_ARG_NONE, &query_pin_flag, "Query PIN state", NULL }, { "enter-pin", 0, 0, G_OPTION_ARG_STRING, &set_pin_enter_str, "Enter PIN (PIN type is optional, defaults to PIN1, allowed options: " "(pin1,network-pin,network-subset-pin,service-provider-pin,corporate-pin)", "[(PIN type),(current PIN)]" }, { "change-pin", 0, 0, G_OPTION_ARG_STRING, &set_pin_change_str, "Change PIN", "[(current PIN),(new PIN)]" }, { "enable-pin", 0, 0, G_OPTION_ARG_STRING, &set_pin_enable_str, "Enable PIN", "[(current PIN)]" }, { "disable-pin", 0, 0, G_OPTION_ARG_STRING, &set_pin_disable_str, "Disable PIN (PIN type is optional, see enter-pin for details)", "[(PIN type),(current PIN)]" }, { "enter-puk", 0, 0, G_OPTION_ARG_STRING, &set_pin_enter_puk_str, "Enter PUK (PUK type is optional, defaults to PUK1, allowed options: " "(puk1,network-puk,network-subset-puk,service-provider-puk,corporate-puk)", "[(PUK type),(PUK),(new PIN)]" }, { "query-pin-list", 0, 0, G_OPTION_ARG_NONE, &query_pin_list_flag, "Query PIN list", NULL }, { "query-home-provider", 0, 0, G_OPTION_ARG_NONE, &query_home_provider_flag, "Query home provider", NULL }, { "query-preferred-providers", 0, 0, G_OPTION_ARG_NONE, &query_preferred_providers_flag, "Query preferred providers", NULL }, { "query-visible-providers", 0, 0, G_OPTION_ARG_NONE, &query_visible_providers_flag, "Query visible providers", NULL }, { "query-registration-state", 0, 0, G_OPTION_ARG_NONE, &query_register_state_flag, "Query registration state", NULL }, { "register-automatic", 0, 0, G_OPTION_ARG_NONE, &set_register_state_automatic_flag, "Launch automatic registration", NULL }, { "query-signal-state", 0, 0, G_OPTION_ARG_NONE, &query_signal_state_flag, "Query signal state", NULL }, { "query-packet-service-state", 0, 0, G_OPTION_ARG_NONE, &query_packet_service_flag, "Query packet service state", NULL }, { "attach-packet-service", 0, 0, G_OPTION_ARG_NONE, &set_packet_service_attach_flag, "Attach to the packet service", NULL }, { "detach-packet-service", 0, 0, G_OPTION_ARG_NONE, &set_packet_service_detach_flag, "Detach from the packet service", NULL }, { "query-connection-state", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, G_CALLBACK (query_connection_state_arg_parse), "Query connection state (SessionID is optional, defaults to 0)", "[SessionID]" }, { "connect", 0, 0, G_OPTION_ARG_STRING, &set_connect_activate_str, "Connect (allowed keys: session-id, access-string, ip-type, auth, username, password, compression, context-type)", "[\"key=value,...\"]" }, { "query-ip-configuration", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, G_CALLBACK (query_ip_configuration_arg_parse), "Query IP configuration (SessionID is optional, defaults to 0)", "[SessionID]" }, { "disconnect", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, G_CALLBACK (disconnect_arg_parse), "Disconnect (SessionID is optional, defaults to 0)", "[SessionID]" }, { "query-packet-statistics", 0, 0, G_OPTION_ARG_NONE, &query_packet_statistics_flag, "Query packet statistics", NULL }, { "query-ip-packet-filters", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, G_CALLBACK (query_ip_packet_filters_arg_parse), "Query IP packet filters (SessionID is optional, defaults to 0)", "[SessionID]" }, { "set-ip-packet-filters", 0, 0, G_OPTION_ARG_STRING, &set_ip_packet_filters_str, "Set IP packet filters (allowed keys: session-id, packet-filter, packet-mask, filter-id)", "[\"key=value,...\"]" }, { "query-provisioned-contexts", 0, 0, G_OPTION_ARG_NONE, &query_provisioned_contexts_flag, "Query provisioned contexts", NULL }, { "set-provisioned-contexts", 0, 0, G_OPTION_ARG_STRING, &set_provisioned_contexts_str, "Set provisioned contexts (allowed keys: context-id, context-type, auth, compression, username, password, access-string, provider-id)", "[\"key=value,...\"]" }, { "set-signal-state", 0, 0, G_OPTION_ARG_STRING, &set_signal_state_str, "Set signal state (allowed keys: signal-strength-interval, rssi-threshold, error-rate-threshold)", "[\"key=value,...\"]" }, { "set-network-idle-hint", 0, 0, G_OPTION_ARG_STRING, &set_network_idle_hint_str, "Set network idle hint", "[(enabled|disabled)]" }, { "query-network-idle-hint", 0, 0, G_OPTION_ARG_NONE, &query_network_idle_hint_flag, "Query network idle hint", NULL }, { "set-emergency-mode", 0, 0, G_OPTION_ARG_STRING, &set_emergency_mode_str, "Set emergency mode", "[(on|off)]" }, { "query-emergency-mode", 0, 0, G_OPTION_ARG_NONE, &query_emergency_mode_flag, "Query emergency mode", NULL }, { "set-service-activation", 0, 0, G_OPTION_ARG_STRING, &set_service_activation_str, "Set service activation", "[Data]" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_basic_connect_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("basic-connect", "Basic Connect options:", "Show Basic Connect Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } static gboolean query_connection_state_arg_parse (const char *option_name, const char *value, gpointer user_data, GError **error) { query_connect_str = g_strdup (value ? value : "0"); return TRUE; } static gboolean query_ip_configuration_arg_parse (const char *option_name, const char *value, gpointer user_data, GError **error) { query_ip_configuration_str = g_strdup (value ? value : "0"); return TRUE; } static gboolean disconnect_arg_parse (const char *option_name, const char *value, gpointer user_data, GError **error) { set_connect_deactivate_str = g_strdup (value ? value : "0"); return TRUE; } static gboolean query_ip_packet_filters_arg_parse (const char *option_name, const char *value, gpointer user_data, GError **error) { query_ip_packet_filters_str = g_strdup (value ? value : "0"); return TRUE; } gboolean mbimcli_basic_connect_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (query_device_caps_flag + query_subscriber_ready_status_flag + query_radio_state_flag + !!set_radio_state_str + query_device_services_flag + query_pin_flag + !!set_pin_enter_str + !!set_pin_change_str + !!set_pin_enable_str + !!set_pin_disable_str + !!set_pin_enter_puk_str + query_pin_list_flag + query_register_state_flag + query_home_provider_flag + query_preferred_providers_flag + query_visible_providers_flag + set_register_state_automatic_flag + query_signal_state_flag + query_packet_service_flag + set_packet_service_attach_flag + set_packet_service_detach_flag + !!query_connect_str + !!set_connect_activate_str + !!query_ip_configuration_str + !!set_connect_deactivate_str + query_packet_statistics_flag + !!query_ip_packet_filters_str + !!set_ip_packet_filters_str + query_provisioned_contexts_flag + !!set_provisioned_contexts_str + !!set_signal_state_str + !!set_network_idle_hint_str + query_network_idle_hint_flag + !!set_emergency_mode_str + query_emergency_mode_flag + !!set_service_activation_str); if (n_actions > 1) { g_printerr ("error: too many Basic Connect actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void query_device_caps_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimDeviceType device_type; const gchar *device_type_str; MbimVoiceClass voice_class; const gchar *voice_class_str; MbimCellularClass cellular_class; g_autofree gchar *cellular_class_str = NULL; MbimSimClass sim_class; g_autofree gchar *sim_class_str = NULL; MbimDataClass data_class; g_autofree gchar *data_class_str = NULL; MbimSmsCaps sms_caps; g_autofree gchar *sms_caps_str = NULL; MbimCtrlCaps ctrl_caps; g_autofree gchar *ctrl_caps_str = NULL; guint32 max_sessions; g_autofree gchar *custom_data_class = NULL; g_autofree gchar *device_id = NULL; g_autofree gchar *firmware_info = NULL; g_autofree gchar *hardware_info = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_device_caps_response_parse ( response, &device_type, &cellular_class, &voice_class, &sim_class, &data_class, &sms_caps, &ctrl_caps, &max_sessions, &custom_data_class, &device_id, &firmware_info, &hardware_info, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } device_type_str = mbim_device_type_get_string (device_type); cellular_class_str = mbim_cellular_class_build_string_from_mask (cellular_class); voice_class_str = mbim_voice_class_get_string (voice_class); sim_class_str = mbim_sim_class_build_string_from_mask (sim_class); data_class_str = mbim_data_class_build_string_from_mask (data_class); sms_caps_str = mbim_sms_caps_build_string_from_mask (sms_caps); ctrl_caps_str = mbim_ctrl_caps_build_string_from_mask (ctrl_caps); g_print ("[%s] Device capabilities retrieved:\n" "\t Device type: '%s'\n" "\t Cellular class: '%s'\n" "\t Voice class: '%s'\n" "\t SIM class: '%s'\n" "\t Data class: '%s'\n" "\t SMS caps: '%s'\n" "\t Ctrl caps: '%s'\n" "\t Max sessions: '%u'\n" "\tCustom data class: '%s'\n" "\t Device ID: '%s'\n" "\t Firmware info: '%s'\n" "\t Hardware info: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (device_type_str), VALIDATE_UNKNOWN (cellular_class_str), VALIDATE_UNKNOWN (voice_class_str), VALIDATE_UNKNOWN (sim_class_str), VALIDATE_UNKNOWN (data_class_str), VALIDATE_UNKNOWN (sms_caps_str), VALIDATE_UNKNOWN (ctrl_caps_str), max_sessions, VALIDATE_UNKNOWN (custom_data_class), VALIDATE_UNKNOWN (device_id), VALIDATE_UNKNOWN (firmware_info), VALIDATE_UNKNOWN (hardware_info)); shutdown (TRUE); } static void query_subscriber_ready_status_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr (MbimMessage) response = NULL; g_autoptr (GError) error = NULL; MbimSubscriberReadyState ready_state; const gchar *ready_state_str; g_autofree gchar *subscriber_id = NULL; g_autofree gchar *sim_iccid = NULL; MbimReadyInfoFlag ready_info; g_autofree gchar *ready_info_str = NULL; guint32 telephone_numbers_count; g_auto(GStrv) telephone_numbers = NULL; g_autofree gchar *telephone_numbers_str = NULL; MbimSubscriberReadyStatusFlag flags; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } /* MBIMEx 3.0 support */ if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { if (!mbim_message_ms_basic_connect_v3_subscriber_ready_status_response_parse (response, &ready_state, &flags, &subscriber_id, &sim_iccid, &ready_info, &telephone_numbers_count, &telephone_numbers, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIMEx 3.0 Subscriber State"); } /* MBIM 1.0 support */ else { if (!mbim_message_subscriber_ready_status_response_parse (response, &ready_state, &subscriber_id, &sim_iccid, &ready_info, &telephone_numbers_count, &telephone_numbers, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIM 1.0 Subscriber State"); } telephone_numbers_str = (telephone_numbers ? g_strjoinv (", ", telephone_numbers) : NULL); ready_state_str = mbim_subscriber_ready_state_get_string (ready_state); ready_info_str = mbim_ready_info_flag_build_string_from_mask (ready_info); g_print ("[%s] Subscriber ready status retrieved:\n" "\t Ready state: '%s'\n" "\t Subscriber ID: '%s'\n" "\t SIM ICCID: '%s'\n" "\t Ready info: '%s'\n" "\tTelephone numbers: (%u) '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (ready_state_str), VALIDATE_UNKNOWN (subscriber_id), VALIDATE_UNKNOWN (sim_iccid), VALIDATE_UNKNOWN (ready_info_str), telephone_numbers_count, VALIDATE_UNKNOWN (telephone_numbers_str)); if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { g_autofree gchar *flags_str = NULL; flags_str = mbim_subscriber_ready_status_flag_build_string_from_mask (flags); g_print ("\t Flags: '%s'\n", VALIDATE_UNKNOWN (flags_str)); } shutdown (TRUE); } static void query_radio_state_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimRadioSwitchState hardware_radio_state; const gchar *hardware_radio_state_str; MbimRadioSwitchState software_radio_state; const gchar *software_radio_state_str; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_radio_state_response_parse ( response, &hardware_radio_state, &software_radio_state, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } hardware_radio_state_str = mbim_radio_switch_state_get_string (hardware_radio_state); software_radio_state_str = mbim_radio_switch_state_get_string (software_radio_state); g_print ("[%s] Radio state retrieved:\n" "\t Hardware radio state: '%s'\n" "\t Software radio state: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (hardware_radio_state_str), VALIDATE_UNKNOWN (software_radio_state_str)); shutdown (TRUE); } static void query_device_services_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimDeviceServiceElementArray) device_services = NULL; guint32 device_services_count; guint32 max_dss_sessions; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_device_services_response_parse ( response, &device_services_count, &max_dss_sessions, &device_services, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); return; } g_print ("[%s] Device services retrieved:\n" "\tMax DSS sessions: '%u'\n", mbim_device_get_path_display (device), max_dss_sessions); if (device_services_count == 0) g_print ("\t Services: None\n"); else { guint32 i; g_print ("\t Services: (%u)\n", device_services_count); for (i = 0; i < device_services_count; i++) { MbimService service; g_autofree gchar *uuid_str = NULL; g_autoptr(GString) cids = NULL; guint32 j; service = mbim_uuid_to_service (&device_services[i]->device_service_id); uuid_str = mbim_uuid_get_printable (&device_services[i]->device_service_id); cids = g_string_new (""); for (j = 0; j < device_services[i]->cids_count; j++) { if (service == MBIM_SERVICE_INVALID) { g_string_append_printf (cids, "%u", device_services[i]->cids[j]); if (j < device_services[i]->cids_count - 1) g_string_append (cids, ", "); } else { g_string_append_printf (cids, "%s%s (%u)", j == 0 ? "" : "\t\t ", VALIDATE_UNKNOWN (mbim_cid_get_printable (service, device_services[i]->cids[j])), device_services[i]->cids[j]); if (j < device_services[i]->cids_count - 1) g_string_append (cids, ",\n"); } } g_print ("\n" "\t\t Service: '%s'\n" "\t\t UUID: [%s]:\n" "\t\t DSS payload: %u\n" "\t\tMax DSS instances: %u\n" "\t\t CIDs: %s\n", service == MBIM_SERVICE_INVALID ? "unknown" : mbim_service_get_string (service), uuid_str, device_services[i]->dss_payload, device_services[i]->max_dss_instances, cids->str); } } shutdown (TRUE); } static void pin_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimPinType pin_type; MbimPinState pin_state; const gchar *pin_state_str; guint32 remaining_attempts; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_pin_response_parse ( response, &pin_type, &pin_state, &remaining_attempts, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } if (GPOINTER_TO_UINT (user_data)) g_print ("[%s] PIN operation successful\n\n", mbim_device_get_path_display (device)); pin_state_str = mbim_pin_state_get_string (pin_state); g_print ("[%s] PIN info:\n" "\t PIN state: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (pin_state_str)); if (pin_type != MBIM_PIN_TYPE_UNKNOWN) { const gchar *pin_type_str; pin_type_str = mbim_pin_type_get_string (pin_type); g_print ("\t PIN type: '%s'\n" "\tRemaining attempts: '%u'\n", VALIDATE_UNKNOWN (pin_type_str), remaining_attempts); } shutdown (TRUE); } static gboolean set_pin_input_parse (const gchar *str, gchar **pin, gchar **new_pin, MbimPinType *pin_type) { g_auto(GStrv) split = NULL; guint n_min, n_max, n = 0; MbimPinType new_pin_type; g_assert (pin != NULL); n_min = (new_pin ? 2 : 1); n_max = n_min + (pin_type ? 1 : 0); /* Format of the string is: * "[(current PIN)]" * or: * "[(PIN name),(current PIN)]" * or: * "[(current PIN),(new PIN)]" * or: * "[(PUK name),(PUK),(new PIN)]" */ split = g_strsplit (str, ",", -1); if (g_strv_length (split) > n_max) { g_printerr ("error: couldn't parse input string, too many arguments\n"); return FALSE; } if (g_strv_length (split) < n_min) { g_printerr ("error: couldn't parse input string, missing arguments\n"); return FALSE; } if (pin_type && (g_strv_length (split) == n_max)) { const gchar *pin_type_str; pin_type_str = split[n++]; if (!mbimcli_read_pin_type_from_string (pin_type_str, &new_pin_type)) { g_printerr ("error: couldn't parse input pin-type: %s\n", pin_type_str); return FALSE; } if (new_pin_type == MBIM_PIN_TYPE_UNKNOWN || (*pin_type == MBIM_PIN_TYPE_PIN1 && new_pin_type >= MBIM_PIN_TYPE_PUK1) || (*pin_type == MBIM_PIN_TYPE_PUK1 && new_pin_type < MBIM_PIN_TYPE_PUK1)) { g_printerr ("error: couldn't parse input string, invalid PIN type\n"); return FALSE; } *pin_type = new_pin_type; } *pin = g_strdup (split[n++]); if (new_pin) *new_pin = g_strdup (split[n]); return TRUE; } enum { CONNECTION_STATUS, CONNECT, DISCONNECT }; static void print_pin_desc (const gchar *pin_name, const MbimPinDesc *pin_desc) { g_print ("\t%s:\n" "\t\t Mode: '%s'\n" "\t\t Format: '%s'\n" "\t\tMin length: '%d'\n" "\t\tMax length: '%d'\n" "\n", pin_name, VALIDATE_UNKNOWN (mbim_pin_mode_get_string (pin_desc->pin_mode)), VALIDATE_UNKNOWN (mbim_pin_format_get_string (pin_desc->pin_format)), pin_desc->pin_length_min, pin_desc->pin_length_max); } static void pin_list_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimPinDesc) pin_desc_pin1 = NULL; g_autoptr(MbimPinDesc) pin_desc_pin2 = NULL; g_autoptr(MbimPinDesc) pin_desc_device_sim_pin = NULL; g_autoptr(MbimPinDesc) pin_desc_device_first_sim_pin = NULL; g_autoptr(MbimPinDesc) pin_desc_network_pin = NULL; g_autoptr(MbimPinDesc) pin_desc_network_subset_pin = NULL; g_autoptr(MbimPinDesc) pin_desc_service_provider_pin = NULL; g_autoptr(MbimPinDesc) pin_desc_corporate_pin = NULL; g_autoptr(MbimPinDesc) pin_desc_subsidy_lock = NULL; g_autoptr(MbimPinDesc) pin_desc_custom = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_pin_list_response_parse ( response, &pin_desc_pin1, &pin_desc_pin2, &pin_desc_device_sim_pin, &pin_desc_device_first_sim_pin, &pin_desc_network_pin, &pin_desc_network_subset_pin, &pin_desc_service_provider_pin, &pin_desc_corporate_pin, &pin_desc_subsidy_lock, &pin_desc_custom, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] PIN list:\n\n", mbim_device_get_path_display (device)); print_pin_desc ("PIN1", pin_desc_pin1); print_pin_desc ("PIN2", pin_desc_pin2); print_pin_desc ("Device SIM PIN", pin_desc_device_sim_pin); print_pin_desc ("Device first SIM PIN", pin_desc_device_first_sim_pin); print_pin_desc ("Network PIN", pin_desc_network_pin); print_pin_desc ("Network subset PIN", pin_desc_network_subset_pin); print_pin_desc ("Service provider PIN", pin_desc_service_provider_pin); print_pin_desc ("Corporate PIN", pin_desc_corporate_pin); print_pin_desc ("Subsidy lock", pin_desc_subsidy_lock); print_pin_desc ("Custom", pin_desc_custom); shutdown (TRUE); } static void ip_configuration_query_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(GError) error = NULL; g_autoptr(MbimMessage) response; gboolean success = FALSE; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: couldn't get IP configuration response message: %s\n", error->message); } else { success = mbimcli_print_ip_config (device, response, &error); if (!success) g_printerr ("error: couldn't parse IP configuration response message: %s\n", error->message); } shutdown (success); } static void ip_configuration_query (MbimDevice *device, GCancellable *cancellable, guint32 session_id) { g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; message = (mbim_message_ip_configuration_query_new ( session_id, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE, /* ipv4configurationavailable */ MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE, /* ipv6configurationavailable */ 0, /* ipv4addresscount */ NULL, /* ipv4address */ 0, /* ipv6addresscount */ NULL, /* ipv6address */ NULL, /* ipv4gateway */ NULL, /* ipv6gateway */ 0, /* ipv4dnsservercount */ NULL, /* ipv4dnsserver */ 0, /* ipv6dnsservercount */ NULL, /* ipv6dnsserver */ 0, /* ipv4mtu */ 0, /* ipv6mtu */ &error)); if (!message) { g_printerr ("error: couldn't create IP config request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (device, message, 60, cancellable, (GAsyncReadyCallback)ip_configuration_query_ready, NULL); } static void connect_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 session_id; MbimActivationState activation_state; MbimVoiceCallState voice_call_state; MbimContextIpType ip_type; MbimAccessMediaType media_type = MBIM_ACCESS_MEDIA_TYPE_UNKNOWN; g_autofree gchar *access_string = NULL; const MbimUuid *context_type; guint32 nw_error; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { if (!mbim_message_ms_basic_connect_v3_connect_response_parse ( response, &session_id, &activation_state, &voice_call_state, &ip_type, &context_type, &nw_error, &media_type, &access_string, NULL, /* unnamed IEs ignored */ &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } } else { if (!mbim_message_connect_response_parse ( response, &session_id, &activation_state, &voice_call_state, &ip_type, &context_type, &nw_error, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } } switch (GPOINTER_TO_UINT (user_data)) { case CONNECT: g_print ("[%s] Successfully connected\n\n", mbim_device_get_path_display (device)); break; case DISCONNECT: g_print ("[%s] Successfully disconnected\n\n", mbim_device_get_path_display (device)); break; default: break; } g_print ("[%s] Connection status:\n" "\t Session ID: '%u'\n" "\tActivation state: '%s'\n" "\tVoice call state: '%s'\n" "\t IP type: '%s'\n" "\t Context type: '%s'\n" "\t Network error: '%s'\n", mbim_device_get_path_display (device), session_id, VALIDATE_UNKNOWN (mbim_activation_state_get_string (activation_state)), VALIDATE_UNKNOWN (mbim_voice_call_state_get_string (voice_call_state)), VALIDATE_UNKNOWN (mbim_context_ip_type_get_string (ip_type)), VALIDATE_UNKNOWN (mbim_context_type_get_string (mbim_uuid_to_context_type (context_type))), VALIDATE_UNKNOWN (mbim_nw_error_get_string (nw_error))); if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { g_print ("\tAccess media type: '%s'\n" "\t Access string: '%s'\n", VALIDATE_UNKNOWN (mbim_access_media_type_get_string (media_type)), access_string); } if (GPOINTER_TO_UINT (user_data) == CONNECT) { ip_configuration_query (device, NULL, session_id); return; } shutdown (TRUE); } static void ip_packet_filters_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimPacketFilterArray) filters = NULL; g_autoptr(MbimPacketFilterV3Array) filters_v3 = NULL; guint32 filters_count; guint32 i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } /* MBIMEx 3.0 support */ if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { if (!mbim_message_ms_basic_connect_v3_ip_packet_filters_response_parse ( response, NULL, /* sessionid */ &filters_count, &filters_v3, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIMEx 3.0 IP Packet Filters"); } /* MBIM 1.0 support */ else { if (!mbim_message_ip_packet_filters_response_parse ( response, NULL, /* sessionid */ &filters_count, &filters, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIM 1.0 IP Packet Filters"); } g_print ("[%s] IP packet filters: (%u)\n", mbim_device_get_path_display (device), filters_count); for (i = 0; i < filters_count; i++) { g_autofree gchar *packet_filter = NULL; g_autofree gchar *packet_mask = NULL; guint32 filter_size = 0; if (filters_v3) { filter_size = filters_v3[i]->filter_size; packet_filter = mbim_common_str_hex (filters_v3[i]->packet_filter, filter_size, ' '); packet_mask = mbim_common_str_hex (filters_v3[i]->packet_mask, filter_size, ' '); } else if (filters) { filter_size = filters[i]->filter_size; packet_filter = mbim_common_str_hex (filters[i]->packet_filter, filter_size, ' '); packet_mask = mbim_common_str_hex (filters[i]->packet_mask, filter_size, ' '); } else g_assert_not_reached (); g_print ("Filter %u:\n", i); g_print ("\tFilter size : %u\n", filter_size); g_print ("\tPacket filter : %s\n", VALIDATE_UNKNOWN (packet_filter)); g_print ("\tPacket mask : %s\n", VALIDATE_UNKNOWN (packet_mask)); if (filters_v3) g_print ("\tFilter ID : %u\n", filters_v3[i]->filter_id); } shutdown (TRUE); } static gboolean connect_session_id_parse (const gchar *str, gboolean allow_empty, guint32 *session_id, GError **error) { gchar *endptr = NULL; gint64 n; g_assert (str != NULL); g_assert (session_id != NULL); if (!str[0]) { if (allow_empty) { *session_id = 0; return TRUE; } g_set_error_literal (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "missing session ID (must be 0 - 255)"); return FALSE; } errno = 0; n = g_ascii_strtoll (str, &endptr, 10); if (errno || n < 0 || n > 255 || ((size_t)(endptr - str) < strlen (str))) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "couldn't parse session ID '%s' (must be 0 - 255)", str); return FALSE; } *session_id = (guint32) n; return TRUE; } typedef struct { gboolean v3; guint32 session_id; GPtrArray *array; gchar *tmp_packet_filter; gchar *tmp_packet_mask; gchar *tmp_filter_id; } SetIpPacketFiltersProperties; static void mbim_packet_filter_v3_free (MbimPacketFilterV3 *var) { if (!var) return; g_free (var->packet_filter); g_free (var->packet_mask); g_free (var); } static void mbim_packet_filter_free (MbimPacketFilter *var) { if (!var) return; g_free (var->packet_filter); g_free (var->packet_mask); g_free (var); } static void set_ip_packet_filters_properties_clear (SetIpPacketFiltersProperties *props) { g_free (props->tmp_packet_filter); g_free (props->tmp_packet_mask); g_free (props->tmp_filter_id); g_ptr_array_unref (props->array); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(SetIpPacketFiltersProperties, set_ip_packet_filters_properties_clear); static gboolean check_filter_add (SetIpPacketFiltersProperties *props, GError **error) { g_autofree guint8 *packet_filter = NULL; gsize packet_filter_size = 0; g_autofree guint8 *packet_mask = NULL; gsize packet_mask_size = 0; if (!props->tmp_packet_filter) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'packet-filter' is missing"); return FALSE; } if (!props->tmp_packet_mask) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'packet-mask' is missing"); return FALSE; } if (!props->v3 && props->tmp_filter_id) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'filter-id' is specific to MBIMEx v3.0"); return FALSE; } if (props->v3 && !props->tmp_filter_id) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'filter-id' is missing"); return FALSE; } packet_filter = mbimcli_read_buffer_from_string (props->tmp_packet_filter, -1, &packet_filter_size, error); if (!packet_filter) return FALSE; packet_mask = mbimcli_read_buffer_from_string (props->tmp_packet_mask, -1, &packet_mask_size, error); if (!packet_mask) return FALSE; if (packet_filter_size != packet_mask_size) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'packet-filter' and 'packet-mask' must have same size"); return FALSE; } if (props->v3) { MbimPacketFilterV3 *filter; guint filter_id; if (!mbimcli_read_uint_from_string (props->tmp_filter_id, &filter_id)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse 'filter-id' field as an integer"); return FALSE; } filter = g_new0 (MbimPacketFilterV3, 1); filter->filter_size = packet_filter_size; filter->packet_filter = g_steal_pointer (&packet_filter); filter->packet_mask = g_steal_pointer (&packet_mask); filter->filter_id = filter_id; g_ptr_array_add (props->array, filter); } else { MbimPacketFilter *filter; filter = g_new0 (MbimPacketFilter, 1); filter->filter_size = packet_filter_size; filter->packet_filter = g_steal_pointer (&packet_filter); filter->packet_mask = g_steal_pointer (&packet_mask); g_ptr_array_add (props->array, filter); } g_clear_pointer (&props->tmp_filter_id, g_free); g_clear_pointer (&props->tmp_packet_filter, g_free); g_clear_pointer (&props->tmp_packet_mask, g_free); return TRUE; } static gboolean set_ip_packet_filters_properties_handle (const gchar *key, const gchar *value, GError **error, gpointer user_data) { SetIpPacketFiltersProperties *props = user_data; if (g_ascii_strcasecmp (key, "session-id") == 0) { if (!connect_session_id_parse (value, FALSE, &props->session_id, error)) return FALSE; } else if (g_ascii_strcasecmp (key, "packet-filter") == 0) { if (props->tmp_packet_filter) { if (!check_filter_add (props, error)) return FALSE; g_clear_pointer (&props->tmp_packet_filter, g_free); } props->tmp_packet_filter = g_strdup (value); } else if (g_ascii_strcasecmp (key, "packet-mask") == 0) { if (props->tmp_packet_mask) { if (!check_filter_add (props, error)) return FALSE; g_clear_pointer (&props->tmp_packet_mask, g_free); } props->tmp_packet_mask = g_strdup (value); } else if (g_ascii_strcasecmp (key, "filter-id") == 0) { if (props->tmp_filter_id) { if (!check_filter_add (props, error)) return FALSE; g_clear_pointer (&props->tmp_filter_id, g_free); } props->tmp_filter_id = g_strdup (value); } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static gboolean set_ip_packet_filters_parse (const gchar *str, SetIpPacketFiltersProperties *props, MbimDevice *device) { g_autoptr(GError) error = NULL; if (!mbimcli_parse_key_value_string (str, &error, set_ip_packet_filters_properties_handle, props)) { g_printerr ("error: couldn't parse input string: %s\n", error->message); return FALSE; } if ((props->tmp_packet_filter || props->tmp_packet_mask) && !check_filter_add (props, &error)) { g_printerr ("error: failed to add last packet filter item: %s\n", error->message); return FALSE; } return TRUE; } typedef struct { guint32 session_id; gchar *access_string; MbimAuthProtocol auth_protocol; gchar *username; gchar *password; MbimContextIpType ip_type; MbimCompression compression; MbimContextType context_type; MbimAccessMediaType media_type; } ConnectActivateProperties; static void connect_activate_properties_clear (ConnectActivateProperties *props) { g_free (props->access_string); g_free (props->username); g_free (props->password); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ConnectActivateProperties, connect_activate_properties_clear); static gboolean connect_activate_properties_handle (const gchar *key, const gchar *value, GError **error, gpointer user_data) { ConnectActivateProperties *props = user_data; /* access-string/apn may be empty */ if ((g_ascii_strcasecmp (key, "access-string") != 0) && (g_ascii_strcasecmp (key, "apn") != 0) && (!value || !value[0])) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "key '%s' required a value", key); return FALSE; } if (g_ascii_strcasecmp (key, "session-id") == 0) { if (!connect_session_id_parse (value, FALSE, &props->session_id, error)) return FALSE; } else if (g_ascii_strcasecmp (key, "apn") == 0) { g_printerr ("warning: key 'apn' is deprecated, use 'access-string' instead\n"); g_free (props->access_string); props->access_string = g_strdup (value); } else if (g_ascii_strcasecmp (key, "access-string") == 0) { g_free (props->access_string); props->access_string = g_strdup (value); } else if (g_ascii_strcasecmp (key, "auth") == 0) { if (!mbimcli_read_auth_protocol_from_string (value, &props->auth_protocol)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown auth: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "username") == 0) { g_free (props->username); props->username = g_strdup (value); } else if (g_ascii_strcasecmp (key, "password") == 0) { g_free (props->password); props->password = g_strdup (value); } else if (g_ascii_strcasecmp (key, "ip-type") == 0) { if (!mbimcli_read_context_ip_type_from_string (value, &props->ip_type)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown ip-type: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "compression") == 0) { if (!mbimcli_read_compression_from_string (value, &props->compression)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown compression: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "context-type") == 0) { if (!mbimcli_read_context_type_from_string (value, &props->context_type)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown context-type: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "media-type") == 0) { if (!mbimcli_read_access_media_type_from_string (value, &props->media_type)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown media-type: '%s'", value); return FALSE; } } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static gboolean set_connect_activate_parse (const gchar *str, ConnectActivateProperties *props, MbimDevice *device) { g_auto(GStrv) split = NULL; g_autoptr(GError) error = NULL; if (strchr (str, '=')) { /* New key=value format */ if (!mbimcli_parse_key_value_string (str, &error, connect_activate_properties_handle, props)) { g_printerr ("error: couldn't parse input string: %s\n", error->message); return FALSE; } } else { /* Old non key=value format, like this: * "[(APN),(PAP|CHAP|MSCHAPV2),(Username),(Password)]" */ g_printerr ("warning: positional input arguments format is deprecated, use key-value format instead\n"); split = g_strsplit (str, ",", -1); if (g_strv_length (split) > 4) { g_printerr ("error: couldn't parse input string, too many arguments\n"); return FALSE; } if (g_strv_length (split) > 0) { /* APN */ props->access_string = g_strdup (split[0]); /* Use authentication method */ if (split[1]) { if (!mbimcli_read_auth_protocol_from_string (split[1], &props->auth_protocol)) { g_printerr ("error: couldn't parse input string, unknown auth protocol '%s'\n", split[1]); return FALSE; } /* Username */ if (split[2]) { props->username = g_strdup (split[2]); /* Password */ props->password = g_strdup (split[3]); } } } if (props->auth_protocol == MBIM_AUTH_PROTOCOL_NONE) { if (props->username || props->password) { g_printerr ("error: username or password requires an auth protocol\n"); return FALSE; } } else { if (!props->username) { g_printerr ("error: auth protocol requires a username\n"); return FALSE; } } } return TRUE; } static void home_provider_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimProvider) provider = NULL; g_autofree gchar *provider_state_str = NULL; g_autofree gchar *cellular_class_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_home_provider_response_parse (response, &provider, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } provider_state_str = mbim_provider_state_build_string_from_mask (provider->provider_state); cellular_class_str = mbim_cellular_class_build_string_from_mask (provider->cellular_class); g_print ("[%s] Home provider:\n" "\t Provider ID: '%s'\n" "\t Provider name: '%s'\n" "\t State: '%s'\n" "\tCellular class: '%s'\n" "\t RSSI: '%u'\n" "\t Error rate: '%u'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (provider->provider_id), VALIDATE_UNKNOWN (provider->provider_name), VALIDATE_UNKNOWN (provider_state_str), VALIDATE_UNKNOWN (cellular_class_str), provider->rssi, provider->error_rate); shutdown (TRUE); } static void preferred_providers_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimProviderArray) providers = NULL; guint n_providers; guint i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_preferred_providers_response_parse (response, &n_providers, &providers, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } if (!n_providers) g_print ("[%s] No preferred providers given\n", mbim_device_get_path_display (device)); else g_print ("[%s] Preferred providers (%u):\n", mbim_device_get_path_display (device), n_providers); for (i = 0; i < n_providers; i++) { g_autofree gchar *provider_state_str = NULL; g_autofree gchar *cellular_class_str = NULL; provider_state_str = mbim_provider_state_build_string_from_mask (providers[i]->provider_state); cellular_class_str = mbim_cellular_class_build_string_from_mask (providers[i]->cellular_class); g_print ("\tProvider [%u]:\n" "\t\t Provider ID: '%s'\n" "\t\t Provider name: '%s'\n" "\t\t State: '%s'\n" "\t\t Cellular class: '%s'\n" "\t\t RSSI: '%u'\n" "\t\t Error rate: '%u'\n", i, VALIDATE_UNKNOWN (providers[i]->provider_id), VALIDATE_UNKNOWN (providers[i]->provider_name), VALIDATE_UNKNOWN (provider_state_str), VALIDATE_UNKNOWN (cellular_class_str), providers[i]->rssi, providers[i]->error_rate); } shutdown (TRUE); } static void visible_providers_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimProviderArray) providers = NULL; guint n_providers; guint i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_visible_providers_response_parse (response, &n_providers, &providers, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } if (!n_providers) g_print ("[%s] No visible providers given\n", mbim_device_get_path_display (device)); else g_print ("[%s] Visible providers (%u):\n", mbim_device_get_path_display (device), n_providers); for (i = 0; i < n_providers; i++) { g_autofree gchar *provider_state_str = NULL; g_autofree gchar *cellular_class_str = NULL; provider_state_str = mbim_provider_state_build_string_from_mask (providers[i]->provider_state); cellular_class_str = mbim_cellular_class_build_string_from_mask (providers[i]->cellular_class); g_print ("\tProvider [%u]:\n" "\t\t Provider ID: '%s'\n" "\t\t Provider name: '%s'\n" "\t\t State: '%s'\n" "\t\t Cellular class: '%s'\n" "\t\t RSSI: '%u'\n" "\t\t Error rate: '%u'\n", i, VALIDATE_UNKNOWN (providers[i]->provider_id), VALIDATE_UNKNOWN (providers[i]->provider_name), VALIDATE_UNKNOWN (provider_state_str), VALIDATE_UNKNOWN (cellular_class_str), providers[i]->rssi, providers[i]->error_rate); } shutdown (TRUE); } static void register_state_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimNwError nw_error; MbimRegisterState register_state; MbimRegisterMode register_mode; MbimDataClass available_data_classes; g_autofree gchar *available_data_classes_str = NULL; MbimCellularClass cellular_class; g_autofree gchar *cellular_class_str = NULL; g_autofree gchar *provider_id = NULL; g_autofree gchar *provider_name = NULL; g_autofree gchar *roaming_text = NULL; MbimRegistrationFlag registration_flag; g_autofree gchar *registration_flag_str = NULL; MbimDataClass preferred_data_classes; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } /* MBIMEx 2.0 support */ if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { if (!mbim_message_ms_basic_connect_v2_register_state_response_parse (response, &nw_error, ®ister_state, ®ister_mode, &available_data_classes, &cellular_class, &provider_id, &provider_name, &roaming_text, ®istration_flag, &preferred_data_classes, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIMEx 2.0 Register State"); } /* MBIM 1.0 support */ else { if (!mbim_message_register_state_response_parse (response, &nw_error, ®ister_state, ®ister_mode, &available_data_classes, &cellular_class, &provider_id, &provider_name, &roaming_text, ®istration_flag, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIM 1.0 Register State"); } if (GPOINTER_TO_UINT (user_data)) g_print ("[%s] Successfully launched automatic registration\n\n", mbim_device_get_path_display (device)); available_data_classes_str = mbim_data_class_build_string_from_mask (available_data_classes); cellular_class_str = mbim_cellular_class_build_string_from_mask (cellular_class); registration_flag_str = mbim_registration_flag_build_string_from_mask (registration_flag); g_print ("[%s] Registration status:\n" "\t Network error: '%s'\n" "\t Register state: '%s'\n" "\t Register mode: '%s'\n" "\tAvailable data classes: '%s'\n" "\tCurrent cellular class: '%s'\n" "\t Provider ID: '%s'\n" "\t Provider name: '%s'\n" "\t Roaming text: '%s'\n" "\t Registration flags: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (mbim_nw_error_get_string (nw_error)), VALIDATE_UNKNOWN (mbim_register_state_get_string (register_state)), VALIDATE_UNKNOWN (mbim_register_mode_get_string (register_mode)), VALIDATE_UNKNOWN (available_data_classes_str), VALIDATE_UNKNOWN (cellular_class_str), VALIDATE_UNKNOWN (provider_id), VALIDATE_UNKNOWN (provider_name), VALIDATE_UNKNOWN (roaming_text), VALIDATE_UNKNOWN (registration_flag_str)); if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { g_autofree gchar *preferred_data_classes_str = NULL; preferred_data_classes_str = mbim_data_class_build_string_from_mask (preferred_data_classes); g_print ("\tPreferred data classes: '%s'\n", VALIDATE_UNKNOWN (preferred_data_classes_str)); } shutdown (TRUE); } static void signal_state_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 rssi; guint32 error_rate; guint32 signal_strength_interval; guint32 rssi_threshold; guint32 error_rate_threshold; guint32 rsrp_snr_count; g_autoptr(MbimRsrpSnrInfoArray) rsrp_snr = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } /* MBIMEx 2.0 support */ if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { if (!mbim_message_ms_basic_connect_v2_signal_state_response_parse (response, &rssi, &error_rate, &signal_strength_interval, &rssi_threshold, &error_rate_threshold, &rsrp_snr_count, &rsrp_snr, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } } /* MBIM 1.0 support */ else { if (!mbim_message_signal_state_response_parse (response, &rssi, &error_rate, &signal_strength_interval, &rssi_threshold, &error_rate_threshold, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } } g_print ("[%s] Signal state:\n" "\t RSSI [0-31,99]: '%u'\n" "\t Error rate [0-7,99]: '%u'\n" "\tSignal strength interval: '%u'\n" "\t RSSI threshold: '%u'\n", mbim_device_get_path_display (device), rssi, error_rate, signal_strength_interval, rssi_threshold); if (error_rate_threshold == 0xFFFFFFFF) g_print ("\t Error rate threshold: 'unspecified'\n"); else g_print ("\t Error rate threshold: '%u'\n", error_rate_threshold); if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { g_print ("\n"); if (rsrp_snr_count == 0) { g_print ("[%s] RSRP/SNR info: 'n/a'\n", mbim_device_get_path_display (device)); } else { guint i; for (i = 0; i < rsrp_snr_count; i++) { g_autofree gchar *system_type_str = NULL; MbimRsrpSnrInfo *info; info = rsrp_snr[i]; system_type_str = mbim_data_class_build_string_from_mask (info->system_type); g_print ("[%s] RSRP/SNR info: '%s'\n", mbim_device_get_path_display (device), system_type_str); if (info->rsrp >= 127) g_print ("\t RSRP: 'unknown'\n"); else g_print ("\t RSRP: '%d dBm'\n", -157 + info->rsrp); if (info->snr >= 128) g_print ("\t SNR: 'unknown'\n"); else g_print ("\t SNR: '%.1lf dB'\n", -23.5 + (info->snr * 0.5)); if (info->rsrp_threshold == 0) g_print ("\t RSRP threshold: 'default'\n"); else if (info->rsrp_threshold == 0xFFFFFFFF) g_print ("\t RSRP threshold: 'unspecified'\n"); else g_print ("\t RSRP threshold: '%u'\n", info->rsrp_threshold); if (info->snr_threshold == 0) g_print ("\t SNR threshold: 'default'\n"); else if (info->snr_threshold == 0xFFFFFFFF) g_print ("\t SNR threshold: 'unspecified'\n"); else g_print ("\t SNR threshold: '%u'\n", info->snr_threshold); g_print ("\n"); } } } shutdown (TRUE); } enum { PACKET_SERVICE_STATUS, PACKET_SERVICE_ATTACH, PACKET_SERVICE_DETACH }; static void packet_service_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 nw_error; MbimPacketServiceState packet_service_state; MbimDataClass highest_available_data_class; MbimDataClassV3 highest_available_data_class_v3; g_autofree gchar *highest_available_data_class_str = NULL; guint64 uplink_speed; guint64 downlink_speed; MbimFrequencyRange frequency_range; MbimDataSubclass data_subclass; g_autoptr(MbimTai) tai = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } /* MBIMEx 3.0 support */ if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { if (!mbim_message_ms_basic_connect_v3_packet_service_response_parse (response, &nw_error, &packet_service_state, &highest_available_data_class_v3, &uplink_speed, &downlink_speed, &frequency_range, &data_subclass, &tai, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIM 3.0 Packet Service"); } /* MBIMEx 2.0 support */ else if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { if (!mbim_message_ms_basic_connect_v2_packet_service_response_parse (response, &nw_error, &packet_service_state, &highest_available_data_class, &uplink_speed, &downlink_speed, &frequency_range, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIM 2.0 Packet Service"); } /* MBIM 1.0 support */ else { if (!mbim_message_packet_service_response_parse (response, &nw_error, &packet_service_state, &highest_available_data_class, &uplink_speed, &downlink_speed, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIM 1.0 Packet Service"); } switch (GPOINTER_TO_UINT (user_data)) { case PACKET_SERVICE_ATTACH: g_print ("[%s] Successfully attached to packet service\n\n", mbim_device_get_path_display (device)); break; case PACKET_SERVICE_DETACH: g_print ("[%s] Successfully detached from packet service\n\n", mbim_device_get_path_display (device)); break; default: break; } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) highest_available_data_class_str = mbim_data_class_v3_build_string_from_mask (highest_available_data_class_v3); else highest_available_data_class_str = mbim_data_class_build_string_from_mask (highest_available_data_class); g_print ("[%s] Packet service status:\n" "\t Network error: '%s'\n" "\t Packet service state: '%s'\n" "\tAvailable data classes: '%s'\n" "\t Uplink speed: '%" G_GUINT64_FORMAT " bps'\n" "\t Downlink speed: '%" G_GUINT64_FORMAT " bps'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (mbim_nw_error_get_string (nw_error)), VALIDATE_UNKNOWN (mbim_packet_service_state_get_string (packet_service_state)), VALIDATE_UNKNOWN (highest_available_data_class_str), uplink_speed, downlink_speed); if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { g_autofree gchar *frequency_range_str = NULL; frequency_range_str = mbim_frequency_range_build_string_from_mask (frequency_range); g_print ("\t Frequency range: '%s'\n", VALIDATE_UNKNOWN (frequency_range_str)); } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { g_autofree gchar *data_subclass_str = NULL; g_autofree gchar *tai_plmn_mcc_str = NULL; g_autofree gchar *tai_plmn_mnc_str = NULL; /* Mobile Country Code of 3 decimal digits; The * least significant 12 bits contains BCD-encoded * 3 decimal digits sequentially for the MCC, with * the last digit of the MCC in the least significant * 4 bits. The unused bits in the UINT16 integer * must be zeros. */ tai_plmn_mcc_str = g_strdup_printf ("%03x", tai->plmn_mcc & 0x0FFF); /* Mobile Network Code of either 3 or 2 decimal * digits; The most significant bit indicates * whether the MNC has 2 decimal digits or 3 * decimal digits. If this bit has 1, the MNC has 2 * decimal digits and the least significant 8 bits * contains them in BCD-encoded form * sequentially, with the last digit of the MNC in * the least significant 4 bits. If the most * significant bit has 0, the MNC has 3 decimal * digits and the least significant 12 bits contains * them in BCD-encoded form sequentially, with * the last digit of the MNC in the least * esignificant 4 bits. The unused bits in the * UINT16 integer must be zeros. */ if (tai->plmn_mnc & 0x8000) tai_plmn_mnc_str = g_strdup_printf ("%02x", tai->plmn_mnc & 0x00FF); else tai_plmn_mnc_str = g_strdup_printf ("%03x", tai->plmn_mnc & 0x0FFF); data_subclass_str = mbim_data_subclass_build_string_from_mask (data_subclass); g_print ("\t Data sub class: '%s'\n" "\t TAI PLMN MCC: '%s'\n" "\t TAI PLMN MNC: '%s'\n" "\t TAI TAC: '%u'\n", VALIDATE_UNKNOWN (data_subclass_str), tai_plmn_mcc_str, tai_plmn_mnc_str, tai->tac); } shutdown (TRUE); } static void packet_statistics_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 in_discards; guint32 in_errors; guint64 in_octets; guint64 in_packets; guint64 out_octets; guint64 out_packets; guint32 out_errors; guint32 out_discards; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_packet_statistics_response_parse (response, &in_discards, &in_errors, &in_octets, &in_packets, &out_octets, &out_packets, &out_errors, &out_discards, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Packet statistics:\n" "\t Octets (in): '%" G_GUINT64_FORMAT "'\n" "\t Packets (in): '%" G_GUINT64_FORMAT "'\n" "\t Discards (in): '%u'\n" "\t Errors (in): '%u'\n" "\t Octets (out): '%" G_GUINT64_FORMAT "'\n" "\t Packets (out): '%" G_GUINT64_FORMAT "'\n" "\tDiscards (out): '%u'\n" "\t Errors (out): '%u'\n", mbim_device_get_path_display (device), in_octets, in_packets, in_discards, in_errors, out_octets, out_packets, out_discards, out_errors); shutdown (TRUE); } static void provisioned_contexts_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(MbimProvisionedContextElementArray) provisioned_contexts = NULL; g_autoptr(GError) error = NULL; guint32 provisioned_contexts_count; guint i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_provisioned_contexts_response_parse ( response, &provisioned_contexts_count, &provisioned_contexts, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Provisioned contexts (%u):\n", mbim_device_get_path_display (device), provisioned_contexts_count); for (i = 0; i < provisioned_contexts_count; i++) { g_print ("\tContext ID %u:\n" "\t Context type: '%s'\n" "\t Access string: '%s'\n" "\t Username: '%s'\n" "\t Password: '%s'\n" "\t Compression: '%s'\n" "\t Auth protocol: '%s'\n", provisioned_contexts[i]->context_id, VALIDATE_UNKNOWN (mbim_context_type_get_string ( mbim_uuid_to_context_type (&provisioned_contexts[i]->context_type))), VALIDATE_UNKNOWN (provisioned_contexts[i]->access_string), VALIDATE_UNKNOWN (provisioned_contexts[i]->user_name), VALIDATE_UNKNOWN (provisioned_contexts[i]->password), VALIDATE_UNKNOWN (mbim_compression_get_string ( provisioned_contexts[i]->compression)), VALIDATE_UNKNOWN (mbim_auth_protocol_get_string ( provisioned_contexts[i]->auth_protocol))); } shutdown (TRUE); } typedef struct { guint context_id; MbimCompression compression; MbimAuthProtocol auth_protocol; MbimContextType context_type; gchar *access_string; gchar *username; gchar *password; gchar *provider_id; } ProvisionedContextProperties; static void provisioned_context_properties_clear (ProvisionedContextProperties *props) { g_free (props->access_string); g_free (props->username); g_free (props->password); g_free (props->provider_id); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ProvisionedContextProperties, provisioned_context_properties_clear) static gboolean set_provisioned_contexts_foreach_cb (const gchar *key, const gchar *value, GError **error, ProvisionedContextProperties *props) { if (g_ascii_strcasecmp (key, "context-id") == 0) { if (!mbimcli_read_uint_from_string (value, &props->context_id)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "Couldn't parse context-id as integer : '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "context-type") == 0) { if (!mbimcli_read_context_type_from_string (value, &props->context_type)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown context-type: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "auth") == 0) { if (!mbimcli_read_auth_protocol_from_string (value, &props->auth_protocol)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown auth: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "compression") == 0) { if (!mbimcli_read_compression_from_string (value, &props->compression)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown compression: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "username") == 0) { g_free (props->username); props->username = g_strdup (value); } else if (g_ascii_strcasecmp (key, "password") == 0) { g_free (props->password); props->password = g_strdup (value); } else if (g_ascii_strcasecmp (key, "access-string") == 0) { g_free (props->access_string); props->access_string = g_strdup (value); } else if (g_ascii_strcasecmp (key, "provider-id") == 0) { g_free (props->provider_id); props->provider_id = g_strdup (value); } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } typedef struct { guint32 signal_strength; guint32 rssi; guint32 error_rate; } SignalStateProperties; static gboolean set_signal_state_foreach_cb (const gchar *key, const gchar *value, GError **error, SignalStateProperties *props) { if (g_ascii_strcasecmp (key, "signal-strength-interval") == 0) { if (!mbimcli_read_uint_from_string (value, &props->signal_strength)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "Couldn't parse signal-strength as integer : '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "rssi-threshold") == 0) { if (!mbimcli_read_uint_from_string (value, &props->rssi)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "Couldn't parse rssi as integer : '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "error-rate-threshold") == 0) { if (!mbimcli_read_uint_from_string (value, &props->error_rate)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "Couldn't parse error-rate as integer : '%s'", value); return FALSE; } } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static void network_idle_hint_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimNetworkIdleHintState network_state; const gchar *network_state_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_network_idle_hint_response_parse ( response, &network_state, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } network_state_str = mbim_network_idle_hint_state_get_string (network_state); g_print ("[%s] Network idle hint state: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (network_state_str)); shutdown (TRUE); } static void emergency_mode_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimEmergencyModeState emergency_state; const gchar *emergency_state_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_emergency_mode_response_parse ( response, &emergency_state, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } emergency_state_str = mbim_emergency_mode_state_get_string (emergency_state); g_print ("[%s] Emergency mode: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (emergency_state_str)); shutdown (TRUE); } static void set_service_activation_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimNwError nw_error; guint32 result_data_size; const guint8 *result_data = NULL; g_autofree gchar *result_data_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_service_activation_response_parse (response, &nw_error, &result_data_size, &result_data, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } result_data_str = mbim_common_str_hex (result_data, result_data_size, ':'); g_print ("[%s] Service activation response received successfully:\n" "\t Network error: '%s'\n" "\t Data: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (mbim_nw_error_get_string (nw_error)), result_data_str); shutdown (TRUE); } void mbimcli_basic_connect_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; g_autoptr(GError) error = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to get capabilities? */ if (query_device_caps_flag) { g_debug ("Asynchronously querying device capabilities..."); request = (mbim_message_device_caps_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_device_caps_ready, NULL); return; } /* Request to get subscriber ready status? */ if (query_subscriber_ready_status_flag) { g_debug ("Asynchronously querying subscriber ready status..."); request = (mbim_message_subscriber_ready_status_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_subscriber_ready_status_ready, NULL); return; } /* Request to get radio state? */ if (query_radio_state_flag) { g_debug ("Asynchronously querying radio state..."); request = (mbim_message_radio_state_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_radio_state_ready, NULL); return; } /* Request to set radio state? */ if (set_radio_state_str) { MbimRadioSwitchState radio_state; if (g_ascii_strcasecmp (set_radio_state_str, "on") == 0) { radio_state = MBIM_RADIO_SWITCH_STATE_ON; } else if (g_ascii_strcasecmp (set_radio_state_str, "off") == 0) { radio_state = MBIM_RADIO_SWITCH_STATE_OFF; } else { g_printerr ("error: invalid radio state: '%s'\n", set_radio_state_str); shutdown (FALSE); return; } g_debug ("Asynchronously setting radio state to %s...", radio_state == MBIM_RADIO_SWITCH_STATE_ON ? "on" : "off"); request = mbim_message_radio_state_set_new (radio_state, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_radio_state_ready, NULL); return; } /* Request to query device services? */ if (query_device_services_flag) { g_debug ("Asynchronously querying device services..."); request = (mbim_message_device_services_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_device_services_ready, NULL); return; } /* Query PIN state? */ if (query_pin_flag) { g_debug ("Asynchronously querying PIN state..."); request = (mbim_message_pin_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)pin_ready, GUINT_TO_POINTER (FALSE)); return; } /* Set PIN? */ if (set_pin_enter_str || set_pin_change_str || set_pin_enable_str || set_pin_disable_str || set_pin_enter_puk_str) { MbimPinType pin_type; MbimPinOperation pin_operation; g_autofree gchar *pin = NULL; g_autofree gchar *new_pin = NULL; if (set_pin_enter_puk_str) { g_debug ("Asynchronously entering PUK..."); pin_type = MBIM_PIN_TYPE_PUK1; pin_operation = MBIM_PIN_OPERATION_ENTER; set_pin_input_parse (set_pin_enter_puk_str, &pin, &new_pin, &pin_type); } else { pin_type = MBIM_PIN_TYPE_PIN1; if (set_pin_change_str) { g_debug ("Asynchronously changing PIN..."); pin_operation = MBIM_PIN_OPERATION_CHANGE; set_pin_input_parse (set_pin_change_str, &pin, &new_pin, NULL); } else if (set_pin_enable_str) { g_debug ("Asynchronously enabling PIN..."); pin_operation = MBIM_PIN_OPERATION_ENABLE; set_pin_input_parse (set_pin_enable_str, &pin, NULL, NULL); } else if (set_pin_disable_str) { g_debug ("Asynchronously disabling PIN..."); pin_operation = MBIM_PIN_OPERATION_DISABLE; set_pin_input_parse (set_pin_disable_str, &pin, NULL, &pin_type); } else if (set_pin_enter_str) { g_debug ("Asynchronously entering PIN..."); pin_operation = MBIM_PIN_OPERATION_ENTER; set_pin_input_parse (set_pin_enter_str, &pin, NULL, &pin_type); } else g_assert_not_reached (); } if (!pin || pin_type == MBIM_PIN_TYPE_UNKNOWN) { shutdown (FALSE); return; } request = (mbim_message_pin_set_new (pin_type, pin_operation, pin, new_pin, &error)); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)pin_ready, GUINT_TO_POINTER (TRUE)); return; } /* Query PIN list? */ if (query_pin_list_flag) { g_debug ("Asynchronously querying PIN list..."); request = (mbim_message_pin_list_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)pin_list_ready, GUINT_TO_POINTER (FALSE)); return; } /* Query home provider? */ if (query_home_provider_flag) { request = mbim_message_home_provider_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)home_provider_ready, NULL); return; } /* Query preferred providers? */ if (query_preferred_providers_flag) { request = mbim_message_preferred_providers_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)preferred_providers_ready, NULL); return; } /* Query visible providers? */ if (query_visible_providers_flag) { request = mbim_message_visible_providers_query_new (MBIM_VISIBLE_PROVIDERS_ACTION_FULL_SCAN, NULL); mbim_device_command (ctx->device, request, 120, /* longer timeout, needs to scan */ ctx->cancellable, (GAsyncReadyCallback)visible_providers_ready, NULL); return; } /* Query registration status? */ if (query_register_state_flag) { request = mbim_message_register_state_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)register_state_ready, GUINT_TO_POINTER (FALSE)); return; } /* Launch automatic registration? */ if (set_register_state_automatic_flag) { request = mbim_message_register_state_set_new (NULL, MBIM_REGISTER_ACTION_AUTOMATIC, 0, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 120, /* longer timeout, needs to look for the home network */ ctx->cancellable, (GAsyncReadyCallback)register_state_ready, GUINT_TO_POINTER (TRUE)); return; } /* Query signal status? */ if (query_signal_state_flag) { request = mbim_message_signal_state_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)signal_state_ready, NULL); return; } /* Query packet service status? */ if (query_packet_service_flag) { request = mbim_message_packet_service_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)packet_service_ready, GUINT_TO_POINTER (PACKET_SERVICE_STATUS)); return; } /* Launch packet attach or detach? */ if (set_packet_service_attach_flag || set_packet_service_detach_flag) { MbimPacketServiceAction action; if (set_packet_service_attach_flag) action = MBIM_PACKET_SERVICE_ACTION_ATTACH; else if (set_packet_service_detach_flag) action = MBIM_PACKET_SERVICE_ACTION_DETACH; else g_assert_not_reached (); request = mbim_message_packet_service_set_new (action, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 120, ctx->cancellable, (GAsyncReadyCallback)packet_service_ready, GUINT_TO_POINTER (set_packet_service_attach_flag ? PACKET_SERVICE_ATTACH : PACKET_SERVICE_DETACH)); return; } /* Query connection status? */ if (query_connect_str) { guint32 session_id = 0; if (!connect_session_id_parse (query_connect_str, TRUE, &session_id, &error)) { g_printerr ("error: couldn't parse session ID: %s\n", error->message); shutdown (FALSE); return; } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { request = mbim_message_ms_basic_connect_v3_connect_query_new (session_id, &error); } else { request = mbim_message_connect_query_new (session_id, MBIM_ACTIVATION_STATE_UNKNOWN, MBIM_VOICE_CALL_STATE_NONE, MBIM_CONTEXT_IP_TYPE_DEFAULT, mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET), 0, &error); } if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)connect_ready, GUINT_TO_POINTER (CONNECTION_STATUS)); return; } /* Connect? */ if (set_connect_activate_str) { g_auto(ConnectActivateProperties) props = { .session_id = 0, .access_string = NULL, .auth_protocol = MBIM_AUTH_PROTOCOL_NONE, .username = NULL, .password = NULL, .ip_type = MBIM_CONTEXT_IP_TYPE_DEFAULT, .compression = MBIM_COMPRESSION_NONE, .context_type = MBIM_CONTEXT_TYPE_INTERNET, .media_type = MBIM_ACCESS_MEDIA_TYPE_UNKNOWN, }; if (!set_connect_activate_parse (set_connect_activate_str, &props, device)) { shutdown (FALSE); return; } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { request = mbim_message_ms_basic_connect_v3_connect_set_new (props.session_id, MBIM_ACTIVATION_COMMAND_ACTIVATE, props.compression, props.auth_protocol, props.ip_type, mbim_uuid_from_context_type (props.context_type), props.media_type, props.access_string, props.username, props.password, NULL, /* unnamed IEs */ &error); } else { request = mbim_message_connect_set_new (props.session_id, MBIM_ACTIVATION_COMMAND_ACTIVATE, props.access_string, props.username, props.password, props.compression, props.auth_protocol, props.ip_type, mbim_uuid_from_context_type (props.context_type), &error); } if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 120, ctx->cancellable, (GAsyncReadyCallback)connect_ready, GUINT_TO_POINTER (CONNECT)); return; } /* Query IP configuration? */ if (query_ip_configuration_str) { guint32 session_id = 0; if (!connect_session_id_parse (query_ip_configuration_str, TRUE, &session_id, &error)) { g_printerr ("error: couldn't parse session ID: %s\n", error->message); shutdown (FALSE); return; } ip_configuration_query (ctx->device, ctx->cancellable, session_id); return; } /* Disconnect? */ if (set_connect_deactivate_str) { guint32 session_id = 0; if (!connect_session_id_parse (set_connect_deactivate_str, TRUE, &session_id, &error)) { g_printerr ("error: couldn't parse session ID: %s\n", error->message); shutdown (FALSE); return; } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { request = mbim_message_ms_basic_connect_v3_connect_set_new (session_id, MBIM_ACTIVATION_COMMAND_DEACTIVATE, MBIM_COMPRESSION_NONE, MBIM_AUTH_PROTOCOL_NONE, MBIM_CONTEXT_IP_TYPE_DEFAULT, mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET), MBIM_ACCESS_MEDIA_TYPE_UNKNOWN, NULL, NULL, NULL, NULL, &error); } else { request = mbim_message_connect_set_new (session_id, MBIM_ACTIVATION_COMMAND_DEACTIVATE, NULL, NULL, NULL, MBIM_COMPRESSION_NONE, MBIM_AUTH_PROTOCOL_NONE, MBIM_CONTEXT_IP_TYPE_DEFAULT, mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET), &error); } if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 60, ctx->cancellable, (GAsyncReadyCallback)connect_ready, GUINT_TO_POINTER (DISCONNECT)); return; } /* Packet statistics? */ if (query_packet_statistics_flag) { request = mbim_message_packet_statistics_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)packet_statistics_ready, NULL); return; } /* Query IP packet filters? */ if (query_ip_packet_filters_str) { guint32 session_id = 0; if (!connect_session_id_parse (query_ip_packet_filters_str, TRUE, &session_id, &error)) { g_printerr ("error: couldn't parse session ID: %s\n", error->message); shutdown (FALSE); return; } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { g_debug ("Asychronously querying v3.0 IP packet filter......"); request = mbim_message_ms_basic_connect_v3_ip_packet_filters_query_new (session_id, 0, NULL, &error); } else { g_debug ("Asychronously querying v1.0 IP packet filter......"); request = mbim_message_ip_packet_filters_query_new (session_id, 0, NULL, &error); } if (!request) { g_printerr ("error: couldn't create IP packet filters request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)ip_packet_filters_ready, NULL); return; } /* Set IP packet filters? */ if (set_ip_packet_filters_str) { g_auto(SetIpPacketFiltersProperties) props = { .v3 = FALSE, .session_id = 0, .array = NULL, }; props.v3 = mbim_device_check_ms_mbimex_version (device, 3, 0); if (props.v3) props.array = g_ptr_array_new_with_free_func ((GDestroyNotify)mbim_packet_filter_v3_free); else props.array = g_ptr_array_new_with_free_func ((GDestroyNotify)mbim_packet_filter_free); if (!set_ip_packet_filters_parse (set_ip_packet_filters_str, &props, device)) { shutdown (FALSE); return; } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { g_debug ("Asychronously set v3.0 IP packet filter......"); request = mbim_message_ms_basic_connect_v3_ip_packet_filters_set_new (props.session_id, props.array->len, (const MbimPacketFilterV3 *const *)props.array->pdata, &error); } else { g_debug ("Asychronously set v1.0 IP packet filter......"); request = mbim_message_ip_packet_filters_set_new (props.session_id, props.array->len, (const MbimPacketFilter *const *)props.array->pdata, &error); } if (!request) { g_printerr ("error: couldn't create IP packet filters request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)ip_packet_filters_ready, NULL); return; } /* Provisioned contexts? */ if (query_provisioned_contexts_flag) { request = mbim_message_provisioned_contexts_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)provisioned_contexts_ready, NULL); return; } /* Set provisioned context */ if (set_provisioned_contexts_str) { g_auto(ProvisionedContextProperties) props = { .access_string = NULL, .context_id = 0, .auth_protocol = MBIM_AUTH_PROTOCOL_NONE, .username = NULL, .password = NULL, .compression = MBIM_COMPRESSION_NONE, .context_type = MBIM_CONTEXT_TYPE_INVALID, .provider_id = NULL }; if (!mbimcli_parse_key_value_string (set_provisioned_contexts_str, &error, (MbimParseKeyValueForeachFn)set_provisioned_contexts_foreach_cb, &props)) { g_printerr ("error: couldn't parse input string: %s\n", error->message); shutdown (FALSE); return; } request = mbim_message_provisioned_contexts_set_new ((guint32)props.context_id, mbim_uuid_from_context_type (props.context_type), props.access_string, props.username, props.password, props.compression, props.auth_protocol, props.provider_id, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 60, ctx->cancellable, (GAsyncReadyCallback)provisioned_contexts_ready, NULL); return; } /* Set signal state */ if (set_signal_state_str) { SignalStateProperties props = { .signal_strength = 0, .rssi = 0, .error_rate = 0 }; if (!mbimcli_parse_key_value_string (set_signal_state_str, &error, (MbimParseKeyValueForeachFn)set_signal_state_foreach_cb, &props)) { g_printerr ("error: couldn't parse input string: %s\n", error->message); shutdown (FALSE); return; } request = mbim_message_signal_state_set_new (props.signal_strength, props.rssi, props.error_rate, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 60, ctx->cancellable, (GAsyncReadyCallback)signal_state_ready, NULL); return; } /* Set network idle hint state */ if (set_network_idle_hint_str) { MbimNetworkIdleHintState network_state; if (!mbimcli_read_network_idle_hint_state_from_string (set_network_idle_hint_str, &network_state)) { shutdown (FALSE); return; } request = mbim_message_network_idle_hint_set_new (network_state, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)network_idle_hint_ready, NULL); return; } /* Get network idle hint state */ if (query_network_idle_hint_flag) { request = mbim_message_network_idle_hint_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)network_idle_hint_ready, NULL); return; } /* Set emergency mode state */ if (set_emergency_mode_str) { MbimEmergencyModeState emergency_state; if (!mbimcli_read_emergency_mode_state_from_string (set_emergency_mode_str, &emergency_state)) { shutdown (FALSE); return; } request = mbim_message_emergency_mode_set_new (emergency_state, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)emergency_mode_ready, NULL); return; } /* Query emergency mode state */ if (query_emergency_mode_flag) { request = mbim_message_emergency_mode_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)emergency_mode_ready, NULL); return; } /* Request to set service activation */ if (set_service_activation_str) { guint8 *data = NULL; gsize data_size = 0; data = mbimcli_read_buffer_from_string (set_service_activation_str, -1, &data_size, &error); if (!data) { g_printerr ("error: couldn't parse the input: %s\n", error->message); shutdown (FALSE); return; } request = mbim_message_service_activation_set_new (data_size, data, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_service_activation_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-dss.c000066400000000000000000000207671453630424100205550ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2014 NVIDIA CORPORATION * Copyright (C) 2014 Aleksander Morgado */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; guint32 session_id; } Context; static Context *ctx; /* Options */ static gchar *connect_str; static gchar *disconnect_str; static GOptionEntry entries[] = { { "dss-connect", 0, 0, G_OPTION_ARG_STRING, &connect_str, "Connect DSS session", "[(UUID),(Session ID)]" }, { "dss-disconnect", 0, 0, G_OPTION_ARG_STRING, &disconnect_str, "Disconnect DSS session", "[(UUID),(Session ID)]" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_dss_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("dss", "Device Service Stream options:", "Show Device Service Stream options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_dss_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (!!connect_str + !!disconnect_str ); if (n_actions > 1) { g_printerr ("error: too many DSS actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } enum { CONNECT, DISCONNECT }; static void ip_configuration_query_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; gboolean success = FALSE; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: couldn't get IP configuration response message: %s\n", error->message); } else { success = mbimcli_print_ip_config (device, response, &error); if (!success) g_printerr ("error: couldn't parse IP configuration response message: %s\n", error->message); } shutdown (success); } static void set_dss_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_dss_connect_response_parse (response, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } if (GPOINTER_TO_UINT (user_data) == DISCONNECT) { g_print ("[%s] Successfully disconnected\n", mbim_device_get_path_display (device)); shutdown (TRUE); return; } g_assert (GPOINTER_TO_UINT (user_data) == CONNECT); g_print ("[%s] Successfully connected\n", mbim_device_get_path_display (device)); message = (mbim_message_ip_configuration_query_new ( ctx->session_id, MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE, /* ipv4configurationavailable */ MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_NONE, /* ipv6configurationavailable */ 0, /* ipv4addresscount */ NULL, /* ipv4address */ 0, /* ipv6addresscount */ NULL, /* ipv6address */ NULL, /* ipv4gateway */ NULL, /* ipv6gateway */ 0, /* ipv4dnsservercount */ NULL, /* ipv4dnsserver */ 0, /* ipv6dnsservercount */ NULL, /* ipv6dnsserver */ 0, /* ipv4mtu */ 0, /* ipv6mtu */ &error)); if (!message) { g_printerr ("error: couldn't create IP config request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (device, message, 60, NULL, (GAsyncReadyCallback)ip_configuration_query_ready, NULL); } static gboolean common_parse (const gchar *str, MbimUuid *dsid, guint32 *ssid) { g_auto(GStrv) split = NULL; gboolean status = FALSE; g_assert (dsid != NULL); g_assert (ssid != NULL); /* Format of the string is: * [(UUID),(Session ID)] */ split = g_strsplit (str, ",", -1); if (g_strv_length (split) > 2) g_printerr ("error: couldn't parse input string, too many arguments\n"); else if (g_strv_length (split) < 1) g_printerr ("error: couldn't parse input string, missing arguments\n"); else if (!mbim_uuid_from_printable (split[0], dsid)) g_printerr ("error: couldn't parse UUID, should be xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); else if (!mbimcli_read_uint_from_string (split[1], ssid)) g_printerr ("error: couldn't parse Session ID, should be a number\n"); else status = TRUE; return status; } void mbimcli_dss_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; g_autoptr(GError) error = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Connect? */ if (connect_str) { MbimUuid service_id; if (!common_parse (connect_str, &service_id, &ctx->session_id)) { shutdown (FALSE); return; } request = mbim_message_dss_connect_set_new (&service_id, ctx->session_id, MBIM_DSS_LINK_STATE_ACTIVATE, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_dss_ready, GUINT_TO_POINTER (CONNECT)); return; } /* Disconnect? */ if (disconnect_str) { MbimUuid service_id; guint32 session_id; if (!common_parse (disconnect_str, &service_id, &session_id)) { shutdown (FALSE); return; } request = mbim_message_dss_connect_set_new (&service_id, session_id, MBIM_DSS_LINK_STATE_DEACTIVATE, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_dss_ready, GUINT_TO_POINTER (DISCONNECT)); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-fibocom.c000066400000000000000000000076351453630424100214010ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2023 chenhaotian */ #include "config.h" #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gchar *set_at_command_str; static GOptionEntry entries[] = { { "fibocom-set-at-command", 0, 0, G_OPTION_ARG_STRING, &set_at_command_str, "send AT command to modem, and receive AT response", "\"\"" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_fibocom_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("fibocom", "FIbocom options:", "Show Fibocom Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_fibocom_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = !!set_at_command_str; if (n_actions > 1) { g_printerr ("error: too many fibocom actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void fibocom_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(GError) error = NULL; guint32 ret_size = 0; const guint8 *ret_str = NULL; g_autoptr(MbimMessage) response = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_fibocom_at_command_response_parse ( response, &ret_size, &ret_str, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("%.*s\n", ret_size, ret_str); shutdown (TRUE); } void mbimcli_fibocom_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; g_autofree gchar *req_str = NULL; guint32 req_size = 0; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to send AT command */ if (set_at_command_str) { req_str = g_strdup_printf ("%s\r\n", set_at_command_str); req_size = strlen (req_str); request = mbim_message_fibocom_at_command_set_new (req_size, (const guint8 *)req_str, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)fibocom_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-google.c000066400000000000000000000152471453630424100212350ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2023 Intel Corporation */ #include "config.h" #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gchar *set_carrier_lock_str; static gboolean query_carrier_lock_flag; static GOptionEntry entries[] = { { "google-set-carrier-lock", 0, 0, G_OPTION_ARG_STRING, &set_carrier_lock_str, "Set Google Carrier Lock", "[(Data)]" }, { "google-query-carrier-lock", 0, 0, G_OPTION_ARG_NONE, &query_carrier_lock_flag, "Query Google Carrier Lock", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_google_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("google", "Google options:", "Show Google Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_google_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (!!set_carrier_lock_str + query_carrier_lock_flag); if (n_actions > 1) { g_printerr ("error: too many google actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void set_carrier_lock_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully set carrier lock: \n", mbim_device_get_path_display (device)); shutdown (TRUE); } static void query_carrier_lock_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; const gchar *carrier_lock_status_str; const gchar *carrier_lock_modem_state_str; const gchar *carrier_lock_cause_str; MbimCarrierLockStatus carrier_lock_status; MbimCarrierLockModemState carrier_lock_modem_state; MbimCarrierLockCause carrier_lock_cause; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_google_carrier_lock_response_parse ( response, &carrier_lock_status, &carrier_lock_modem_state, &carrier_lock_cause, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); return; } carrier_lock_status_str = mbim_carrier_lock_status_get_string (carrier_lock_status); carrier_lock_modem_state_str = mbim_carrier_lock_modem_state_get_string (carrier_lock_modem_state); carrier_lock_cause_str = mbim_carrier_lock_cause_get_string (carrier_lock_cause); g_print ("[%s] Successfully queried carrier lock: \n" "\t Carrier lock status: '%s'\n" "\tCarrier lock modem state: '%s'\n" "\t Carrier lock cause: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (carrier_lock_status_str), VALIDATE_UNKNOWN (carrier_lock_modem_state_str), VALIDATE_UNKNOWN (carrier_lock_cause_str)); shutdown (TRUE); } void mbimcli_google_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; g_autoptr(GError) error = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to set carrier lock */ if (set_carrier_lock_str) { gsize data_size = 0; g_autofree guint8 *data = NULL; data = mbimcli_read_buffer_from_string (set_carrier_lock_str, -1, &data_size, &error); if (!data) { g_printerr ("Failed to read data: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Asynchronously setting carrier lock..."); request = mbim_message_google_carrier_lock_set_new ((guint32)data_size, data, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_carrier_lock_ready, NULL); return; } /* Query carrier lock information */ if (query_carrier_lock_flag) { request = mbim_message_google_carrier_lock_query_new (&error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_carrier_lock_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-helpers.c000066400000000000000000000423021453630424100214130ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2014 Aleksander Morgado */ #include #include #include #include #include "mbimcli-helpers.h" gboolean mbimcli_read_uint_from_string (const gchar *str, guint *out) { gulong num; if (!str || !str[0]) return FALSE; for (num = 0; str[num]; num++) { if (!g_ascii_isdigit (str[num])) return FALSE; } errno = 0; num = strtoul (str, NULL, 10); if (!errno && num <= G_MAXUINT) { *out = (guint)num; return TRUE; } return FALSE; } gboolean mbimcli_read_uint_from_bcd_string (const gchar *str, guint *out) { gulong num; if (!str || !str[0]) return FALSE; /* in bcd, only numeric values (0-9) */ for (num = 0; str[num]; num++) { if (!g_ascii_isdigit (str[num])) return FALSE; } /* for the numeric values of str, we can just read the string as hex * (base 16) and it will be valid bcd */ errno = 0; num = strtoul (str, NULL, 16); if (!errno && num <= G_MAXUINT) { *out = (guint)num; return TRUE; } return FALSE; } gboolean mbimcli_read_uint8_from_bcd_string (const gchar *str, guint8 *out) { guint num; if (!mbimcli_read_uint_from_bcd_string (str, &num) || (num > G_MAXUINT8)) return FALSE; *out = (guint8)num; return TRUE; } gboolean mbimcli_read_boolean_from_string (const gchar *value, gboolean *out) { if (!g_ascii_strcasecmp (value, "true") || g_str_equal (value, "1") || !g_ascii_strcasecmp (value, "yes")) { *out = TRUE; return TRUE; } if (!g_ascii_strcasecmp (value, "false") || g_str_equal (value, "0") || !g_ascii_strcasecmp (value, "no")) { *out = FALSE; return TRUE; } return FALSE; } /* Based on ModemManager's mm_utils_hexstr2bin() */ static gint hex2num (gchar c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } static gint hex2byte (const gchar *hex) { gint a, b; a = hex2num (*hex++); if (a < 0) return -1; b = hex2num (*hex++); if (b < 0) return -1; return (a << 4) | b; } guint8 * mbimcli_read_buffer_from_string (const gchar *hex, gssize len, gsize *out_len, GError **error) { const gchar *ipos = hex; g_autofree guint8 *buf = NULL; gssize i; gint a; guint8 *opos; if (len < 0) len = strlen (hex); if (len == 0) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Hex conversion failed: empty string"); return NULL; } /* Length must be a multiple of 2 */ if ((len % 2) != 0) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Hex conversion failed: invalid input length"); return NULL; } opos = buf = g_malloc0 (len / 2); for (i = 0; i < len; i += 2) { a = hex2byte (ipos); if (a < 0) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Hex byte conversion from '%c%c' failed", ipos[0], ipos[1]); return NULL; } *opos++ = (guint8)a; ipos += 2; } *out_len = len / 2; return g_steal_pointer (&buf); } gboolean mbimcli_print_ip_config (MbimDevice *device, MbimMessage *response, GError **error) { MbimIPConfigurationAvailableFlag ipv4configurationavailable; g_autofree gchar *ipv4configurationavailable_str = NULL; MbimIPConfigurationAvailableFlag ipv6configurationavailable; g_autofree gchar *ipv6configurationavailable_str = NULL; guint32 ipv4addresscount; g_autoptr(MbimIPv4ElementArray) ipv4address = NULL; guint32 ipv6addresscount; g_autoptr(MbimIPv6ElementArray) ipv6address = NULL; const MbimIPv4 *ipv4gateway; const MbimIPv6 *ipv6gateway; guint32 ipv4dnsservercount; g_autofree MbimIPv4 *ipv4dnsserver = NULL; guint32 ipv6dnsservercount; g_autofree MbimIPv6 *ipv6dnsserver = NULL; guint32 ipv4mtu; guint32 ipv6mtu; if (!mbim_message_ip_configuration_response_parse ( response, NULL, /* sessionid */ &ipv4configurationavailable, &ipv6configurationavailable, &ipv4addresscount, &ipv4address, &ipv6addresscount, &ipv6address, &ipv4gateway, &ipv6gateway, &ipv4dnsservercount, &ipv4dnsserver, &ipv6dnsservercount, &ipv6dnsserver, &ipv4mtu, &ipv6mtu, error)) return FALSE; /* IPv4 info */ ipv4configurationavailable_str = mbim_ip_configuration_available_flag_build_string_from_mask (ipv4configurationavailable); g_print ("\n[%s] IPv4 configuration available: '%s'\n", mbim_device_get_path_display (device), ipv4configurationavailable_str); if (ipv4configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS) { guint i; for (i = 0; i < ipv4addresscount; i++) { g_autoptr(GInetAddress) addr = NULL; g_autofree gchar *addr_str = NULL; addr = g_inet_address_new_from_bytes ((guint8 *)&ipv4address[i]->ipv4_address, G_SOCKET_FAMILY_IPV4); addr_str = g_inet_address_to_string (addr); g_print (" IP [%u]: '%s/%u'\n", i, addr_str, ipv4address[i]->on_link_prefix_length); } } if (ipv4configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY) { g_autoptr(GInetAddress) addr = NULL; g_autofree gchar *addr_str = NULL; addr = g_inet_address_new_from_bytes ((guint8 *)ipv4gateway, G_SOCKET_FAMILY_IPV4); addr_str = g_inet_address_to_string (addr); g_print (" Gateway: '%s'\n", addr_str); } if (ipv4configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS) { guint i; for (i = 0; i < ipv4dnsservercount; i++) { g_autoptr(GInetAddress) addr = NULL; addr = g_inet_address_new_from_bytes ((guint8 *)&ipv4dnsserver[i], G_SOCKET_FAMILY_IPV4); if (!g_inet_address_get_is_any (addr)) { g_autofree gchar *addr_str = NULL; addr_str = g_inet_address_to_string (addr); g_print (" DNS [%u]: '%s'\n", i, addr_str); } } } if (ipv4configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU) g_print (" MTU: '%u'\n", ipv4mtu); /* IPv6 info */ ipv6configurationavailable_str = mbim_ip_configuration_available_flag_build_string_from_mask (ipv6configurationavailable); g_print ("\n[%s] IPv6 configuration available: '%s'\n", mbim_device_get_path_display (device), ipv6configurationavailable_str); if (ipv6configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_ADDRESS) { guint i; for (i = 0; i < ipv6addresscount; i++) { g_autoptr(GInetAddress) addr = NULL; g_autofree gchar *addr_str = NULL; addr = g_inet_address_new_from_bytes ((guint8 *)&ipv6address[i]->ipv6_address, G_SOCKET_FAMILY_IPV6); addr_str = g_inet_address_to_string (addr); g_print (" IP [%u]: '%s/%u'\n", i, addr_str, ipv6address[i]->on_link_prefix_length); } } if (ipv6configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_GATEWAY) { g_autoptr(GInetAddress) addr = NULL; g_autofree gchar *addr_str = NULL; addr = g_inet_address_new_from_bytes ((guint8 *)ipv6gateway, G_SOCKET_FAMILY_IPV6); addr_str = g_inet_address_to_string (addr); g_print (" Gateway: '%s'\n", addr_str); } if (ipv6configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_DNS) { guint i; for (i = 0; i < ipv6dnsservercount; i++) { g_autoptr(GInetAddress) addr = NULL; addr = g_inet_address_new_from_bytes ((guint8 *)&ipv6dnsserver[i], G_SOCKET_FAMILY_IPV6); if (!g_inet_address_get_is_any (addr)) { g_autofree gchar *addr_str = NULL; addr_str = g_inet_address_to_string (addr); g_print (" DNS [%u]: '%s'\n", i, addr_str); } } } if (ipv6configurationavailable & MBIM_IP_CONFIGURATION_AVAILABLE_FLAG_MTU) g_print (" MTU: '%u'\n", ipv6mtu); return TRUE; } /* Expecting input as: * key1=string,key2=true,key3=false... * Strings may also be passed enclosed between double or single quotes, like: * key1="this is a string", key2='and so is this' */ gboolean mbimcli_parse_key_value_string (const gchar *str, GError **error, MbimParseKeyValueForeachFn callback, gpointer user_data) { GError *inner_error = NULL; g_autofree gchar *dupstr = NULL; gchar *p, *key, *key_end, *value, *value_end, quote; g_return_val_if_fail (callback != NULL, FALSE); g_return_val_if_fail (str != NULL, FALSE); /* Allow empty strings, we'll just return with success */ while (g_ascii_isspace (*str)) str++; if (!str[0]) return TRUE; dupstr = g_strdup (str); p = dupstr; while (TRUE) { gboolean keep_iteration = FALSE; /* Skip leading spaces */ while (g_ascii_isspace (*p)) p++; /* Key start */ key = p; if (!g_ascii_isalnum (*key)) { inner_error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Key must start with alpha/num, starts with '%c'", *key); break; } /* Key end */ while (g_ascii_isalnum (*p) || (*p == '-') || (*p == '_')) p++; key_end = p; if (key_end == key) { inner_error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Couldn't find a proper key"); break; } /* Skip whitespaces, if any */ while (g_ascii_isspace (*p)) p++; /* Equal sign must be here */ if (*p != '=') { inner_error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Couldn't find equal sign separator"); break; } /* Skip the equal */ p++; /* Skip whitespaces, if any */ while (g_ascii_isspace (*p)) p++; /* Do we have a quote-enclosed string? */ if (*p == '\"' || *p == '\'') { quote = *p; /* Skip the quote */ p++; /* Value start */ value = p; /* Find the closing quote */ p = strchr (p, quote); if (!p) { inner_error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Unmatched quotes in string value"); break; } /* Value end */ value_end = p; /* Skip the quote */ p++; } else { /* Value start */ value = p; /* Value end */ while ((*p != ',') && (*p != '\0') && !g_ascii_isspace (*p)) p++; value_end = p; } /* Note that we allow value == value_end here */ /* Skip whitespaces, if any */ while (g_ascii_isspace (*p)) p++; /* If a comma is found, we should keep the iteration */ if (*p == ',') { /* skip the comma */ p++; keep_iteration = TRUE; } /* Got key and value, prepare them and run the callback */ *value_end = '\0'; *key_end = '\0'; if (!callback (key, value, &inner_error, user_data)) { /* We were told to abort */ break; } g_assert (!inner_error); if (keep_iteration) continue; /* Check if no more key/value pairs expected */ if (*p == '\0') break; inner_error = g_error_new (MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Unexpected content (%s) after value", p); break; } if (inner_error) { g_propagate_error (error, inner_error); return FALSE; } return TRUE; } gboolean mbimcli_parse_sar_config_state_array (const gchar *str, GPtrArray **out) { g_autoptr(GPtrArray) config_state_array = NULL; g_autoptr(GRegex) regex = NULL; g_autoptr(GMatchInfo) match_info = NULL; g_autoptr(GError) inner_error = NULL; config_state_array = g_ptr_array_new_with_free_func (g_free); if (!str || !str[0]) { *out = NULL; return TRUE; } regex = g_regex_new ("\\s*{\\s*(\\d+|all)\\s*,\\s*(\\d+)\\s*}(?:\\s*,)?", G_REGEX_RAW, 0, NULL); g_assert (regex); g_regex_match_full (regex, str, strlen (str), 0, 0, &match_info, &inner_error); while (!inner_error && g_match_info_matches (match_info)) { g_autofree MbimSarConfigState *config_state = NULL; g_autofree gchar *antenna_index_str = NULL; g_autofree gchar *backoff_index_str = NULL; config_state = g_new (MbimSarConfigState, 1); antenna_index_str = g_match_info_fetch (match_info, 1); backoff_index_str = g_match_info_fetch (match_info, 2); if (g_ascii_strcasecmp (antenna_index_str, "all") == 0) config_state->antenna_index = 0xFFFFFFFF; else if (!mbimcli_read_uint_from_string (antenna_index_str, &config_state->antenna_index)) { g_printerr ("error: invalid antenna index: '%s'\n", antenna_index_str); return FALSE; } if (!mbimcli_read_uint_from_string (backoff_index_str, &config_state->backoff_index)) { g_printerr ("error: invalid backoff index: '%s'\n", backoff_index_str); return FALSE; } g_ptr_array_add (config_state_array, g_steal_pointer (&config_state)); g_match_info_next (match_info, &inner_error); } if (inner_error) { g_printerr ("error: couldn't match config state array: %s\n", inner_error->message); return FALSE; } if (config_state_array->len == 0) { g_printerr ("error: no elements found in the array\n"); return FALSE; } *out = (config_state_array->len > 0) ? g_steal_pointer (&config_state_array) : NULL; return TRUE; } #define MBIMCLI_ENUM_LIST_ITEM(TYPE,TYPE_UNDERSCORE,DESCR) \ gboolean \ mbimcli_read_## TYPE_UNDERSCORE ##_from_string (const gchar *str, \ TYPE *out) \ { \ GType type; \ GEnumClass *enum_class; \ GEnumValue *enum_value; \ \ type = mbim_## TYPE_UNDERSCORE ##_get_type (); \ enum_class = G_ENUM_CLASS (g_type_class_ref (type)); \ enum_value = g_enum_get_value_by_nick (enum_class, str); \ \ if (enum_value) \ *out = (TYPE)enum_value->value; \ else \ g_printerr ("error: invalid " DESCR " value given: '%s'\n", str); \ \ g_type_class_unref (enum_class); \ return !!enum_value; \ } MBIMCLI_ENUM_LIST #undef MBIMCLI_ENUM_LIST_ITEM libmbim-1.31.2-dev/src/mbimcli/mbimcli-helpers.h000066400000000000000000000123321453630424100214200ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control QMI devices * * Copyright (C) 2014 Aleksander Morgado */ #include #include #ifndef __MBIMCLI_HELPERS_H__ #define __MBIMCLI_HELPERS_H__ gboolean mbimcli_read_uint_from_string (const gchar *str, guint *out); gboolean mbimcli_read_uint_from_bcd_string (const gchar *str, guint *out); gboolean mbimcli_read_uint8_from_bcd_string (const gchar *str, guint8 *out); gboolean mbimcli_read_boolean_from_string (const gchar *value, gboolean *out); guint8 *mbimcli_read_buffer_from_string (const gchar *hex, gssize len, gsize *out_len, GError **error); gboolean mbimcli_print_ip_config (MbimDevice *device, MbimMessage *response, GError **error); typedef gboolean (*MbimParseKeyValueForeachFn) (const gchar *key, const gchar *value, GError **error, gpointer user_data); gboolean mbimcli_parse_key_value_string (const gchar *str, GError **error, MbimParseKeyValueForeachFn callback, gpointer user_data); gboolean mbimcli_parse_sar_config_state_array (const gchar *str, GPtrArray **out); /* Common helpers to read enums from strings */ #define MBIMCLI_ENUM_LIST \ MBIMCLI_ENUM_LIST_ITEM (MbimPinType, pin_type, "pin type") \ MBIMCLI_ENUM_LIST_ITEM (MbimContextType, context_type, "context type") \ MBIMCLI_ENUM_LIST_ITEM (MbimContextIpType, context_ip_type, "context ip type") \ MBIMCLI_ENUM_LIST_ITEM (MbimContextState, context_state, "context state") \ MBIMCLI_ENUM_LIST_ITEM (MbimContextRoamingControl, context_roaming_control, "context roaming control") \ MBIMCLI_ENUM_LIST_ITEM (MbimContextMediaType, context_media_type, "context media type") \ MBIMCLI_ENUM_LIST_ITEM (MbimContextSource, context_source, "context source") \ MBIMCLI_ENUM_LIST_ITEM (MbimContextOperation, context_operation, "context operation") \ MBIMCLI_ENUM_LIST_ITEM (MbimAuthProtocol, auth_protocol, "auth protocol") \ MBIMCLI_ENUM_LIST_ITEM (MbimCompression, compression, "compression") \ MBIMCLI_ENUM_LIST_ITEM (MbimSarControlMode, sar_control_mode, "sar control mode") \ MBIMCLI_ENUM_LIST_ITEM (MbimSarBackoffState, sar_backoff_state, "sar backoff state") \ MBIMCLI_ENUM_LIST_ITEM (MbimMicoMode, mico_mode, "mico mode") \ MBIMCLI_ENUM_LIST_ITEM (MbimDrxCycle, drx_cycle, "drx cycle") \ MBIMCLI_ENUM_LIST_ITEM (MbimLadnInfo, ladn_info, "ladn info") \ MBIMCLI_ENUM_LIST_ITEM (MbimDefaultPduActivationHint, default_pdu_activation_hint, "default pdu activation hint") \ MBIMCLI_ENUM_LIST_ITEM (MbimAccessMediaType, access_media_type, "access media type") \ MBIMCLI_ENUM_LIST_ITEM (MbimNetworkIdleHintState, network_idle_hint_state, "network idle hint state") \ MBIMCLI_ENUM_LIST_ITEM (MbimEmergencyModeState, emergency_mode_state, "emergency mode state") \ MBIMCLI_ENUM_LIST_ITEM (MbimUiccSecureMessaging, uicc_secure_messaging, "uicc secure messaging") \ MBIMCLI_ENUM_LIST_ITEM (MbimUiccClassByteType, uicc_class_byte_type, "uicc class byte type") \ MBIMCLI_ENUM_LIST_ITEM (MbimUiccPassThroughAction, uicc_pass_through_action, "uicc pass through action") \ MBIMCLI_ENUM_LIST_ITEM (MbimIntelBootMode, intel_boot_mode, "intel boot mode") \ MBIMCLI_ENUM_LIST_ITEM (MbimTraceCommand, trace_command, "trace command") \ MBIMCLI_ENUM_LIST_ITEM (MbimSmsFlag, sms_flag, "sms flag") #define MBIMCLI_ENUM_LIST_ITEM(TYPE,TYPE_UNDERSCORE,DESCR) \ gboolean mbimcli_read_## TYPE_UNDERSCORE ##_from_string (const gchar *str, TYPE *out); MBIMCLI_ENUM_LIST #undef MBIMCLI_ENUM_LIST_ITEM #endif /* __MBIMCLI_H__ */ libmbim-1.31.2-dev/src/mbimcli/mbimcli-intel-firmware-update.c000066400000000000000000000140051453630424100241550ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright 2018 Google LLC */ #include "config.h" #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean modem_reboot_set; static gchar *modem_reboot_str; static gboolean modem_reboot_arg_parse (const gchar *option_name, const gchar *value, gpointer user_data, GError **error); static GOptionEntry entries[] = { { "intel-modem-reboot", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, G_CALLBACK (modem_reboot_arg_parse), "Reboot modem. Boot mode and timeout arguments only required if MBIMEx >= 2.0.", "[(Boot Mode),(Timeout)]" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_intel_firmware_update_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("intel-firmware-update", "Intel Firmware Update Service options:", "Show Intel Firmware Update Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } static gboolean modem_reboot_arg_parse (const gchar *option_name, const gchar *value, gpointer user_data, GError **error) { modem_reboot_set = TRUE; modem_reboot_str = g_strdup (value); return TRUE; } gboolean mbimcli_intel_firmware_update_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = modem_reboot_set; if (n_actions > 1) { g_printerr ("error: too many Intel Firmware Update Service actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void modem_reboot_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully requested modem to reboot for firmware update\n\n", mbim_device_get_path_display (device)); shutdown (TRUE); } static gboolean modem_reboot_v2_input_parse (const gchar *str, MbimIntelBootMode *out_boot_mode, guint32 *out_timeout) { g_auto(GStrv) split = NULL; split = g_strsplit (modem_reboot_str, ",", -1); if (g_strv_length (split) > 2) { g_printerr ("error: couldn't parse input string, too many arguments\n"); return FALSE; } if (g_strv_length (split) < 2) { g_printerr ("error: couldn't parse input string, missing arguments\n"); return FALSE; } if (!mbimcli_read_intel_boot_mode_from_string (split[0], out_boot_mode)) { g_printerr ("error: couldn't read boot mode, wrong value given as input\n"); return FALSE; } if (!mbimcli_read_uint_from_string (split[1], out_timeout)) { g_printerr ("error: couldn't read timeout value\n"); return FALSE; } return TRUE; } void mbimcli_intel_firmware_update_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to reboot modem? */ if (modem_reboot_set) { if (mbim_device_check_ms_mbimex_version (device, 2, 0)) { MbimIntelBootMode boot_mode = MBIM_INTEL_BOOT_MODE_NORMAL_MODE; guint32 timeout = 0; if (!modem_reboot_v2_input_parse (modem_reboot_str, &boot_mode, &timeout)) { g_printerr ("error: couldn't parse input arguments\n"); g_printerr ("error: device in MBIMEx >= 2.0 requires boot mode and timeout arguments.\n"); shutdown (FALSE); return; } request = mbim_message_intel_firmware_update_v2_modem_reboot_set_new (boot_mode, timeout, NULL); } else { if (modem_reboot_str) { g_printerr ("error: arguments are not expected in MBIMEx < 2.0\n"); shutdown (FALSE); return; } g_debug ("Asynchronously rebooting modem..."); request = mbim_message_intel_firmware_update_modem_reboot_set_new (NULL); } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)modem_reboot_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-intel-mutual-authentication.c000066400000000000000000000137001453630424100254060ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2022 Intel Corporation */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbim-common.h" #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean query_fcc_lock_flag; static gchar *set_fcc_lock_str; static GOptionEntry entries[] = { { "intel-query-fcc-lock", 0, 0, G_OPTION_ARG_NONE, &query_fcc_lock_flag, "Query FCC lock information", NULL }, { "intel-set-fcc-lock", 0, 0, G_OPTION_ARG_STRING, &set_fcc_lock_str, "Set FCC lock information", "[(ResponsePresent),(Response)]" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_intel_mutual_authentication_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("intel-mutual-authentication", "Intel mutual authentication Service options:", "Show Intel mutual authentication Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_intel_mutual_authentication_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (query_fcc_lock_flag + !!set_fcc_lock_str); if (n_actions > 1) { g_printerr ("error: too many Intel mutual Authentication actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void query_fcc_lock_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { MbimMessage *response = NULL; GError *error = NULL; gboolean challenge_present = FALSE; guint32 challenge = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_intel_mutual_authentication_fcc_lock_response_parse (response, &challenge_present, &challenge, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("FCC lock status: %s\n", challenge_present ? "locked" : "unlocked"); if (challenge_present) g_print ("\tChallenge: %u\n", challenge); shutdown (TRUE); } void mbimcli_intel_mutual_authentication_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Query FCC lock information */ if (query_fcc_lock_flag) { g_debug ("Asynchronously querying FCC lock information..."); request = mbim_message_intel_mutual_authentication_fcc_lock_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_fcc_lock_ready, NULL); return; } /* Set FCC lock information */ if (set_fcc_lock_str) { gboolean response_present = FALSE; guint32 response = 0; g_auto(GStrv) split = NULL; split = g_strsplit (set_fcc_lock_str, ",", -1); if (g_strv_length (split) < 2) { g_printerr ("error: couldn't parse input arguments, missing arguments\n"); shutdown (FALSE); return; } if (g_strv_length (split) > 2) { g_printerr ("error: couldn't parse input arguments, too many arguments\n"); shutdown (FALSE); return; } if (!mbimcli_read_boolean_from_string (split[0], &response_present)) { g_printerr ("error: couldn't parse input, wrong value given\n"); shutdown (FALSE); return; } if (!mbimcli_read_uint_from_string (split[1], &response)) { g_printerr ("error: couldn't parse input, wrong value given\n"); shutdown (FALSE); return; } request = mbim_message_intel_mutual_authentication_fcc_lock_set_new (response_present, response, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_fcc_lock_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-intel-thermal-rf.c000066400000000000000000000216021453630424100231230ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * mbimcli -- Command line interface to control MBIM devices * * 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, see . * * Copyright (C) 2022 Intel Corporation */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbim-common.h" #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean query_rfim_flag; static gchar *set_rfim_str; static GOptionEntry entries[] = { { "intel-query-rfim", 0, 0, G_OPTION_ARG_NONE, &query_rfim_flag, "Query RFIM frequency information", NULL }, { "intel-set-rfim", 0, 0, G_OPTION_ARG_STRING, &set_rfim_str, "Enable or disable RFIM (disabled by default)", "[(on|off)]" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_intel_thermal_rf_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("intel-thermal-rf", "Intel Thermal RF Service options:", "Show Intel Thermal RF Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_intel_thermal_rf_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (query_rfim_flag + !!set_rfim_str); if (n_actions > 1) { g_printerr ("error: too many Intel Thermal RF actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void query_rfim_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { guint32 i = 0; g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 element_count; MbimIntelRfimFrequencyValueArray *rfim_frequency; g_autofree gchar *rssi_str = NULL; g_autofree gchar *sinr_str = NULL; g_autofree gchar *rsrq_str = NULL; g_autofree gchar *rsrp_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_intel_thermal_rf_rfim_response_parse (response, &element_count, &rfim_frequency, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] RFIM frequency values (%u):\n", mbim_device_get_path_display (device), element_count); for (i = 0; i < element_count; i++) { if (rfim_frequency[i]->rssi <= 31) rssi_str = g_strdup_printf ("%d dBm", -113 + (2 * rfim_frequency[i]->rssi)); else rssi_str = g_strdup_printf ("n/a"); if (rfim_frequency[i]->rsrq == 0) rsrq_str = g_strdup_printf ("< -19.5 dB"); else if (rfim_frequency[i]->rsrq < 34) rsrq_str = g_strdup_printf ("%.2lf dB", -19.5 + ((gdouble)rfim_frequency[i]->rsrq / 2)); else if (rfim_frequency[i]->rsrq == 34) rsrq_str = g_strdup_printf (">= -2.5 dB"); else rsrq_str = g_strdup_printf ("n/a"); if (rfim_frequency[i]->rsrp == 0) rsrp_str = g_strdup_printf ("< -140 dBm"); else if (rfim_frequency[i]->rsrp < 97) rsrp_str = g_strdup_printf ("%d dBm", -140 + rfim_frequency[i]->rsrp); else if (rfim_frequency[i]->rsrp == 97) rsrp_str = g_strdup_printf (">= -43 dBm"); else rsrp_str = g_strdup_printf ("n/a"); if (rfim_frequency[i]->sinr == 0) sinr_str = g_strdup_printf ("< -23 dB"); else if (rfim_frequency[i]->sinr < 97) sinr_str = g_strdup_printf ("%.21f dB", -23 + ((gdouble)rfim_frequency[i]->sinr / 2)); else if (rfim_frequency[i]->sinr == 97) sinr_str = g_strdup_printf (">= 40 dB"); else sinr_str = g_strdup_printf ("n/a"); g_print ("\tElement Number: %u\n" "\t Serving cell info: %s\n" "\t Center frequency: %" G_GUINT64_FORMAT " Hz\n" "\t Bandwidth: %u Hz\n" "\t RSRP: %s\n" "\t RSRQ: %s\n" "\t SINR: %s\n" "\t RSSI: %s\n" "\t Connected: %s\n", i + 1, mbim_intel_serving_cell_info_get_string (rfim_frequency[i]->serving_cell_info), rfim_frequency[i]->center_frequency, rfim_frequency[i]->bandwidth, rsrp_str, rsrq_str, sinr_str, rssi_str, rfim_frequency[i]->connection_status ? "yes" : "no"); } shutdown(TRUE); } static void set_rfim_state_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully requested modem to set RFIM state\n", mbim_device_get_path_display (device)); shutdown (TRUE); } void mbimcli_intel_thermal_rf_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Query RFIM Frequency information*/ if (query_rfim_flag) { g_debug ("Asynchronously querying RFIM frequency information..."); request = mbim_message_intel_thermal_rf_rfim_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_rfim_ready, NULL); return; } /* Request to set rfim activation state */ if (set_rfim_str) { gboolean activation_state; g_debug ("Asynchronously setting RFIM activation state..."); if (g_ascii_strcasecmp (set_rfim_str, "on") == 0) activation_state = TRUE; else if (g_ascii_strcasecmp (set_rfim_str, "off") == 0) activation_state = FALSE; else { g_printerr ("error: invalid RFIM state: '%s'\n", set_rfim_str); shutdown (FALSE); return; } request = mbim_message_intel_thermal_rf_rfim_set_new (activation_state, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_rfim_state_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-intel-tools.c000066400000000000000000000167571453630424100222410ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * mbimcli -- Command line interface to control MBIM devices * * 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, see . * * Copyright (C) 2022 Intel Corporation */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbim-common.h" #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static char *set_trace_config_str; static char *query_trace_config_str; static GOptionEntry entries[] = { { "intel-set-trace-config", 0, 0, G_OPTION_ARG_STRING, &set_trace_config_str, "Set trace configuration", "[(TraceCmd)|(TraceValue)]" }, { "intel-query-trace-config", 0, 0, G_OPTION_ARG_STRING, &query_trace_config_str, "Query trace configuration", "[(TraceCmd)]" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_intel_tools_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("intel-tools", "Intel 5G tools options", "Show Intel 5G tools options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_intel_tools_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions =(!!set_trace_config_str + !!query_trace_config_str); if (n_actions > 1) { g_printerr ("error: too many intel tools actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void query_trace_config_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimTraceCommand trace_cmd; const gchar *trace_cmd_str; guint32 trace_result; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully retrieved trace configuration\n", mbim_device_get_path_display (device)); if (!mbim_message_intel_tools_trace_config_response_parse ( response, &trace_cmd, &trace_result, &error)) { g_printerr ("error: couldn't parse response messages: %s\n", error->message); shutdown (FALSE); return; } trace_cmd_str = mbim_trace_command_get_string (trace_cmd); g_print ("[%s] Trace configuration retrieved:\n" "\t Trace Command: '%s'\n" "\t Trace Result: '%u'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN(trace_cmd_str), trace_result); shutdown (TRUE); } static void set_trace_config_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully retrieved trace configuration\n", mbim_device_get_path_display (device)); shutdown (TRUE); } void mbimcli_intel_tools_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to set trace config? */ if (set_trace_config_str) { g_auto(GStrv) split = NULL; MbimTraceCommand trace_command; guint32 trace_value = 0; split = g_strsplit (set_trace_config_str, ",", -1); if (g_strv_length (split) > 2) { g_printerr ("error: couldn't parse input string, too many arguments\n"); return; } if (g_strv_length (split) < 2) { g_printerr ("error: couldn't parse input string, missing arguments\n"); return; } if (split[0]) { if (!mbimcli_read_trace_command_from_string (split[0], &trace_command)) { g_printerr ("error: couldn't parse input string, invalid trace command '%s'\n", split[0]); return; } } if (split[1]) { if (!mbimcli_read_uint_from_string (split[1], &trace_value)) { g_printerr ("error: couldn't parse input string, invalid trace value '%s'\n", split[1]); return; } } g_debug ("Asynchronously setting trace info..."); request = mbim_message_intel_tools_trace_config_set_new (trace_command, trace_value, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_trace_config_ready, NULL); return; } /* Request to get trace config? */ if (query_trace_config_str) { MbimTraceCommand trace_command; if (!mbimcli_read_trace_command_from_string (query_trace_config_str, &trace_command)) { g_printerr ("error: couldn't parse input string, invalid trace command '%d'\n", trace_command); return; } g_debug ("Asynchronously querying trace info..."); request = mbim_message_intel_tools_trace_config_query_new (trace_command, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_trace_config_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-link-management.c000066400000000000000000000214251453630424100230230ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2021 Aleksander Morgado */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Options */ static gchar *link_list_str; static gchar *link_add_str; static gchar *link_delete_str; static gchar *link_delete_all_str; static GOptionEntry entries[] = { { "link-list", 0, 0, G_OPTION_ARG_STRING, &link_list_str, "List links created from a given interface", "[IFACE]" }, { "link-add", 0, 0, G_OPTION_ARG_STRING, &link_add_str, "Create new network interface link", "[iface=IFACE,prefix=PREFIX[,session-id=N]]" }, { "link-delete", 0, 0, G_OPTION_ARG_STRING, &link_delete_str, "Delete a given network interface link", "IFACE" }, { "link-delete-all", 0, 0, G_OPTION_ARG_STRING, &link_delete_all_str, "Delete all network interface links from the given interface", "[IFACE]" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_link_management_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("link-management", "Link management options:", "Show link management specific options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_link_management_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (!!link_list_str + !!link_add_str + !!link_delete_str + !!link_delete_all_str); if (n_actions > 1) { g_printerr ("error: too many link management actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } /******************************************************************************/ static void link_delete_all_ready (MbimDevice *dev, GAsyncResult *res) { g_autoptr(GError) error = NULL; if (!mbim_device_delete_all_links_finish (dev, res, &error)) g_printerr ("error: couldn't delete all links: %s\n", error->message); else g_print ("[%s] all links successfully deleted\n", mbim_device_get_path_display (dev)); mbimcli_async_operation_done (!error); } static void device_link_delete_all (MbimDevice *dev, GCancellable *cancellable, const gchar *iface) { mbim_device_delete_all_links (dev, iface, cancellable, (GAsyncReadyCallback)link_delete_all_ready, NULL); } /******************************************************************************/ static void link_delete_ready (MbimDevice *dev, GAsyncResult *res) { g_autoptr(GError) error = NULL; if (!mbim_device_delete_link_finish (dev, res, &error)) g_printerr ("error: couldn't delete link: %s\n", error->message); else g_print ("[%s] link successfully deleted\n", mbim_device_get_path_display (dev)); mbimcli_async_operation_done (!error); } static void device_link_delete (MbimDevice *dev, GCancellable *cancellable, const gchar *link_iface) { mbim_device_delete_link (dev, link_iface, cancellable, (GAsyncReadyCallback)link_delete_ready, NULL); } typedef struct { guint session_id; gchar *iface; gchar *prefix; } AddLinkProperties; static void link_add_ready (MbimDevice *dev, GAsyncResult *res) { g_autoptr(GError) error = NULL; g_autofree gchar *link_iface = NULL; guint session_id; link_iface = mbim_device_add_link_finish (dev, res, &session_id, &error); if (!link_iface) g_printerr ("error: couldn't add link: %s\n", error->message); else g_print ("[%s] link successfully added:\n" " iface name: %s\n" " session id: %u\n", mbim_device_get_path_display (dev), link_iface, session_id); mbimcli_async_operation_done (!error); } static gboolean add_link_properties_handle (const gchar *key, const gchar *value, GError **error, AddLinkProperties *props) { if (g_ascii_strcasecmp (key, "session-id") == 0 && props->session_id == MBIM_DEVICE_SESSION_ID_AUTOMATIC) { if (!mbimcli_read_uint_from_string (value, &props->session_id)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "invalid session-id given: '%s'", value); return FALSE; } return TRUE; } if (g_ascii_strcasecmp (key, "iface") == 0 && !props->iface) { props->iface = g_strdup (value); return TRUE; } if (g_ascii_strcasecmp (key, "prefix") == 0 && !props->prefix) { props->prefix = g_strdup (value); return TRUE; } g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized or duplicate option '%s'", key); return FALSE; } static void device_link_add (MbimDevice *dev, GCancellable *cancellable, const gchar *add_settings) { g_autoptr(GError) error = NULL; AddLinkProperties props = { .session_id = MBIM_DEVICE_SESSION_ID_AUTOMATIC, .iface = NULL, .prefix = NULL, }; if (!mbimcli_parse_key_value_string (add_settings, &error, (MbimParseKeyValueForeachFn)add_link_properties_handle, &props)) { g_printerr ("error: couldn't parse input add link settings: %s\n", error->message); mbimcli_async_operation_done (FALSE); return; } if (!props.iface) { g_printerr ("error: missing mandatory 'iface' setting\n"); mbimcli_async_operation_done (FALSE); return; } if (!props.prefix) props.prefix = g_strdup_printf ("%s.", props.iface); if ((props.session_id != MBIM_DEVICE_SESSION_ID_AUTOMATIC) && (props.session_id > MBIM_DEVICE_SESSION_ID_MAX)) { g_printerr ("error: session id %u out of range [%u,%u]\n", props.session_id, MBIM_DEVICE_SESSION_ID_MIN, MBIM_DEVICE_SESSION_ID_MAX); mbimcli_async_operation_done (FALSE); return; } mbim_device_add_link (dev, props.session_id, props.iface, props.prefix, cancellable, (GAsyncReadyCallback)link_add_ready, NULL); g_free (props.iface); g_free (props.prefix); } static void device_link_list (MbimDevice *dev, GCancellable *cancellable, const gchar *iface) { g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) links = NULL; if (!mbim_device_list_links (dev, iface, &links, &error)) g_printerr ("error: couldn't list links: %s\n", error->message); else { guint i; guint n_links; n_links = (links ? links->len : 0); g_print ("[%s] found %u links%s\n", mbim_device_get_path_display (dev), n_links, n_links > 0 ? ":" : ""); for (i = 0; i < n_links; i++) g_print (" [%u] %s\n", i, (const gchar *) g_ptr_array_index (links, i)); } mbimcli_async_operation_done (!error); } /******************************************************************************/ /* Common */ void mbimcli_link_management_run (MbimDevice *dev, GCancellable *cancellable) { if (link_list_str) device_link_list (dev, cancellable, link_list_str); else if (link_add_str) device_link_add (dev, cancellable, link_add_str); else if (link_delete_str) device_link_delete (dev, cancellable, link_delete_str); else if (link_delete_all_str) device_link_delete_all (dev, cancellable, link_delete_all_str); else g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-ms-basic-connect-extensions.c000066400000000000000000002545431453630424100253070ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2018 Google LLC * Copyright (C) 2018 Aleksander Morgado */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbim-common.h" #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gchar *query_pco_str; static gboolean query_lte_attach_configuration_flag; static gboolean query_lte_attach_status_flag; /* support for the deprecated name */ static gboolean query_lte_attach_info_flag; static gboolean query_sys_caps_flag; static gboolean query_device_caps_flag; static gchar *query_slot_info_status_str; static gboolean query_device_slot_mappings_flag; static gchar *set_device_slot_mappings_str; static gboolean query_location_info_status_flag; static gboolean query_provisioned_contexts_flag; static gchar *set_provisioned_contexts_str; static gboolean query_base_stations_flag; static gchar *query_version_str; static gboolean query_registration_parameters_flag; static gchar *set_registration_parameters_str; static gboolean query_modem_configuration_flag; static gboolean query_wake_reason_flag; static gboolean device_reset_flag; static gboolean query_pco_arg_parse (const gchar *option_name, const gchar *value, gpointer user_data, GError **error); static GOptionEntry entries[] = { { "ms-query-pco", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, G_CALLBACK (query_pco_arg_parse), "Query PCO value (SessionID is optional, defaults to 0)", "[SessionID]" }, { "ms-query-lte-attach-configuration", 0, 0, G_OPTION_ARG_NONE, &query_lte_attach_configuration_flag, "Query LTE attach configuration", NULL }, { "ms-query-lte-attach-status", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &query_lte_attach_status_flag, NULL, NULL }, { "ms-query-lte-attach-info", 0, 0, G_OPTION_ARG_NONE, &query_lte_attach_info_flag, "Query LTE attach status information", NULL }, { "ms-query-sys-caps", 0, 0, G_OPTION_ARG_NONE, &query_sys_caps_flag, "Query system capabilities", NULL }, { "ms-query-device-caps", 0,0, G_OPTION_ARG_NONE, &query_device_caps_flag, "Query device capabilities", NULL }, { "ms-query-slot-info-status", 0, 0, G_OPTION_ARG_STRING, &query_slot_info_status_str, "Query slot information status", "[SlotIndex]" }, { "ms-set-device-slot-mappings", 0, 0, G_OPTION_ARG_STRING, &set_device_slot_mappings_str, "Set device slot mappings for each executor", "[(SlotIndex)[,(SlotIndex)[,...]]]" }, { "ms-query-device-slot-mappings", 0, 0, G_OPTION_ARG_NONE, &query_device_slot_mappings_flag, "Query device slot mappings", NULL }, { "ms-query-location-info-status", 0, 0, G_OPTION_ARG_NONE, &query_location_info_status_flag, "Query location info status", NULL }, { "ms-set-provisioned-contexts", 0, 0, G_OPTION_ARG_STRING, &set_provisioned_contexts_str, "Set provisioned contexts (allowed keys: operation, context-type, ip-type, state, roaming-control, media-type, source, auth, compression, username, password, access-string)", "[\"key=value,...\"]" }, { "ms-query-provisioned-contexts", 0, 0, G_OPTION_ARG_NONE, &query_provisioned_contexts_flag, "Query provisioned contexts", NULL }, { "ms-query-base-stations-info", 0, 0, G_OPTION_ARG_NONE, &query_base_stations_flag, "Query base stations info", NULL }, { "ms-device-reset", 0, 0, G_OPTION_ARG_NONE, &device_reset_flag, "Reset device", NULL }, { "ms-query-version", 0, 0,G_OPTION_ARG_STRING , &query_version_str, "Exchange supported version information. Since MBIMEx v2.0.", "[(MBIM version),(MBIM extended version)]" }, { "ms-query-registration-parameters", 0, 0, G_OPTION_ARG_NONE, &query_registration_parameters_flag, "Query registration parameters. Since MBIMEx v3.0.", NULL }, { "ms-set-registration-parameters", 0, 0,G_OPTION_ARG_STRING , &set_registration_parameters_str, "Set registration parameters (required keys: mico-mode, drx-cycle, ladn-info, default-pdu-activation-hint, re-register-if-needed). Since MBIMEx v3.0.", "[\"key=value,...\"]" }, { "ms-query-modem-configuration", 0, 0, G_OPTION_ARG_NONE, &query_modem_configuration_flag, "Query modem configuration. Since MBIMEx v3.0.", NULL }, { "ms-query-wake-reason", 0, 0, G_OPTION_ARG_NONE, &query_wake_reason_flag, "Query wake reason. Since MBIMEx v3.0.", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; static gboolean query_pco_arg_parse (const gchar *option_name, const gchar *value, gpointer user_data, GError **error) { query_pco_str = g_strdup (value ? value : "0"); return TRUE; } GOptionGroup * mbimcli_ms_basic_connect_extensions_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("ms-basic-connect-extensions", "Microsoft Basic Connect Extensions options:", "Show Microsoft Basic Connect Extensions Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } static gboolean session_id_parse (const gchar *str, guint32 *session_id, GError **error) { gchar *endptr = NULL; gint64 n; g_assert (str != NULL); g_assert (session_id != NULL); if (!str[0]) { *session_id = 0; return TRUE; } errno = 0; n = g_ascii_strtoll (str, &endptr, 10); if (errno || n < 0 || n > 255 || ((size_t)(endptr - str) < strlen (str))) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "couldn't parse session ID '%s' (must be 0 - 255)", str); return FALSE; } *session_id = (guint32) n; return TRUE; } gboolean mbimcli_ms_basic_connect_extensions_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (!!query_pco_str + query_lte_attach_configuration_flag + (query_lte_attach_status_flag || query_lte_attach_info_flag) + query_sys_caps_flag + query_device_caps_flag + !!query_slot_info_status_str + !!set_device_slot_mappings_str + query_device_slot_mappings_flag + query_location_info_status_flag + query_provisioned_contexts_flag + !!set_provisioned_contexts_str + query_base_stations_flag + !!query_version_str + device_reset_flag + query_registration_parameters_flag + !!set_registration_parameters_str + query_modem_configuration_flag + query_wake_reason_flag); if (n_actions > 1) { g_printerr ("error: too many Microsoft Basic Connect Extensions Service actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void query_pco_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimPcoValue) pco_value = NULL; g_autofree gchar *pco_data = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully queried PCO\n", mbim_device_get_path_display (device)); if (!mbim_message_ms_basic_connect_extensions_pco_response_parse ( response, &pco_value, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } pco_data = mbim_common_str_hex (pco_value->pco_data_buffer, pco_value->pco_data_size, ' '); g_print ("[%s] PCO:\n" "\t Session ID: '%u'\n" "\tPCO data type: '%s'\n" "\tPCO data size: '%u'\n" "\t PCO data: '%s'\n", mbim_device_get_path_display (device), pco_value->session_id, VALIDATE_UNKNOWN (mbim_pco_type_get_string (pco_value->pco_data_type)), pco_value->pco_data_size, pco_data); shutdown (TRUE); } static void query_lte_attach_configuration_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimLteAttachConfigurationArray) configurations = NULL; guint32 configuration_count = 0; guint i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully queried LTE attach configuration\n", mbim_device_get_path_display (device)); if (!mbim_message_ms_basic_connect_extensions_lte_attach_configuration_response_parse ( response, &configuration_count, &configurations, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } #define VALIDATE_NA(str) (str ? str : "n/a") for (i = 0; i < configuration_count; i++) { g_print ("Configuration %u:\n", i); g_print (" IP type: %s\n", mbim_context_ip_type_get_string (configurations[i]->ip_type)); g_print (" Roaming: %s\n", mbim_lte_attach_context_roaming_control_get_string (configurations[i]->roaming)); g_print (" Source: %s\n", mbim_context_source_get_string (configurations[i]->source)); g_print (" Access string: %s\n", VALIDATE_NA (configurations[i]->access_string)); g_print (" Username: %s\n", VALIDATE_NA (configurations[i]->user_name)); g_print (" Password: %s\n", VALIDATE_NA (configurations[i]->password)); g_print (" Compression: %s\n", mbim_compression_get_string (configurations[i]->compression)); g_print (" Auth protocol: %s\n", mbim_auth_protocol_get_string (configurations[i]->auth_protocol)); } #undef VALIDATE_NA shutdown (TRUE); } static void query_lte_attach_info_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 lte_attach_state; guint32 ip_type; g_autofree gchar *access_string = NULL; g_autofree gchar *user_name = NULL; g_autofree gchar *password = NULL; guint32 compression; guint32 auth_protocol; MbimNwError nw_error = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } /* MBIMEx 3.0 support */ if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { if (!mbim_message_ms_basic_connect_extensions_v3_lte_attach_info_response_parse ( response, <e_attach_state, &nw_error, &ip_type, &access_string, &user_name, &password, &compression, &auth_protocol, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully received v3.0 LTE attach info\n", mbim_device_get_path_display (device)); } /* MBIM 1.0 support */ else { if (!mbim_message_ms_basic_connect_extensions_lte_attach_info_response_parse ( response, <e_attach_state, &ip_type, &access_string, &user_name, &password, &compression, &auth_protocol, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully received v1.0 LTE attach info\n", mbim_device_get_path_display (device)); } #define VALIDATE_NA(str) (str ? str : "n/a") g_print (" Attach state: %s\n", mbim_lte_attach_state_get_string (lte_attach_state)); g_print (" IP type: %s\n", mbim_context_ip_type_get_string (ip_type)); g_print (" Access string: %s\n", VALIDATE_NA (access_string)); g_print (" Username: %s\n", VALIDATE_NA (user_name)); g_print (" Password: %s\n", VALIDATE_NA (password)); g_print (" Compression: %s\n", mbim_compression_get_string (compression)); g_print (" Auth protocol: %s\n", mbim_auth_protocol_get_string (auth_protocol)); if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { if (nw_error == 0) g_print (" Network error: none\n"); else if (nw_error == 0xFFFFFFFF) g_print (" Network error: unknown\n"); else { const gchar *nw_error_str; nw_error_str = mbim_nw_error_get_string (nw_error); if (nw_error_str) g_print (" Network error: %s\n", nw_error_str); else g_print (" Network error: unknown (0x%08x)\n", nw_error); } } #undef VALIDATE_NA shutdown (TRUE); } static void query_sys_caps_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 number_executors; guint32 number_slots; guint32 concurrency; guint64 modem_id; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully queried sys caps\n", mbim_device_get_path_display (device)); if (!mbim_message_ms_basic_connect_extensions_sys_caps_response_parse ( response, &number_executors, &number_slots, &concurrency, &modem_id, &error)) { g_printerr ("error: couldn't parse response messages: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] System capabilities retrieved:\n" "\t Number of executors: '%u'\n" "\t Number of slots: '%u'\n" "\t Concurrency: '%u'\n" "\t Modem ID: '%" G_GUINT64_FORMAT "'\n", mbim_device_get_path_display (device), number_executors, number_slots, concurrency, modem_id); shutdown (TRUE); } static void query_device_caps_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimDeviceType device_type = MBIM_DEVICE_TYPE_UNKNOWN; const gchar *device_type_str = NULL; MbimVoiceClass voice_class = MBIM_VOICE_CLASS_UNKNOWN; const gchar *voice_class_str = NULL; MbimCellularClass cellular_class = MBIM_CELLULAR_CLASS_NONE; g_autofree gchar *cellular_class_str = NULL; MbimSimClass sim_class = MBIM_SIM_CLASS_NONE; g_autofree gchar *sim_class_str = NULL; MbimDataClass data_class = MBIM_DATA_CLASS_NONE; MbimDataClassV3 data_class_v3 = MBIM_DATA_CLASS_V3_NONE; g_autofree gchar *data_class_str = NULL; MbimDataSubclass data_subclass = MBIM_DATA_SUBCLASS_NONE; MbimSmsCaps sms_caps = MBIM_SMS_CAPS_NONE; g_autofree gchar *sms_caps_str = NULL; MbimCtrlCaps ctrl_caps = MBIM_CTRL_CAPS_NONE; g_autofree gchar *ctrl_caps_str = NULL; guint32 max_sessions = 0; guint32 wcdma_band_class = 0; guint32 lte_band_class_array_size = 0; g_autofree guint16 *lte_band_class_array = NULL; guint32 nr_band_class_array_size = 0; g_autofree guint16 *nr_band_class_array = NULL; g_autofree gchar *custom_data_class = NULL; g_autofree gchar *device_id = NULL; g_autofree gchar *firmware_info = NULL; g_autofree gchar *hardware_info = NULL; guint32 executor_index = 0; response = mbim_device_command_finish(device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { if (!mbim_message_ms_basic_connect_extensions_v3_device_caps_response_parse ( response, &device_type, &cellular_class, &voice_class, &sim_class, &data_class_v3, &sms_caps, &ctrl_caps, &data_subclass, &max_sessions, &executor_index, &wcdma_band_class, <e_band_class_array_size, <e_band_class_array, &nr_band_class_array_size, &nr_band_class_array, &custom_data_class, &device_id, &firmware_info, &hardware_info, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIMEx 3.0 Device Caps"); } else { if (!mbim_message_ms_basic_connect_extensions_device_caps_response_parse ( response, &device_type, &cellular_class, &voice_class, &sim_class, &data_class, &sms_caps, &ctrl_caps, &max_sessions, &custom_data_class, &device_id, &firmware_info, &hardware_info, &executor_index, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIMEx 1.0 Device Caps"); } if (mbim_device_check_ms_mbimex_version (device, 3, 0)) data_class_str = mbim_data_class_v3_build_string_from_mask (data_class_v3); else data_class_str = mbim_data_class_build_string_from_mask (data_class); device_type_str = mbim_device_type_get_string (device_type); cellular_class_str = mbim_cellular_class_build_string_from_mask (cellular_class); voice_class_str = mbim_voice_class_get_string (voice_class); sim_class_str = mbim_sim_class_build_string_from_mask (sim_class); sms_caps_str = mbim_sms_caps_build_string_from_mask (sms_caps); ctrl_caps_str = mbim_ctrl_caps_build_string_from_mask (ctrl_caps); g_print ("[%s] Device capabilities retrieved:\n" "\t Device type: '%s'\n" "\t Cellular class: '%s'\n" "\t Voice class: '%s'\n" "\t SIM class: '%s'\n" "\t Data class: '%s'\n" "\t SMS caps: '%s'\n" "\t Ctrl caps: '%s'\n" "\t Max sessions: '%u'\n" "\tCustom data class: '%s'\n" "\t Device ID: '%s'\n" "\t Firmware info: '%s'\n" "\t Hardware info: '%s'\n" "\t Executor Index: '%u'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (device_type_str), VALIDATE_UNKNOWN (cellular_class_str), VALIDATE_UNKNOWN (voice_class_str), VALIDATE_UNKNOWN (sim_class_str), VALIDATE_UNKNOWN (data_class_str), VALIDATE_UNKNOWN (sms_caps_str), VALIDATE_UNKNOWN (ctrl_caps_str), max_sessions, VALIDATE_UNKNOWN (custom_data_class), VALIDATE_UNKNOWN (device_id), VALIDATE_UNKNOWN (firmware_info), VALIDATE_UNKNOWN (hardware_info), executor_index); if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { g_autofree gchar *data_subclass_str = NULL; guint i; gboolean n_printed; data_subclass_str = mbim_data_subclass_build_string_from_mask (data_subclass); g_print ("\t Data subclass: '%s'\n", data_subclass_str); g_print ("\t WCDMA band class: '"); for (n_printed = 0, i = 0; i < 31; i++) { if (wcdma_band_class & (1 << i)) { g_print ("%s%u", n_printed > 0 ? ", " : "", i + 1); n_printed++; } } g_print ("'\n"); g_print ("\t LTE band class: '"); for (i = 0; i < lte_band_class_array_size; i++) g_print ("%s%" G_GUINT16_FORMAT, i > 0 ? ", " : "", lte_band_class_array[i]); g_print ("'\n"); g_print ("\t NR band class: '"); for (i = 0; i < nr_band_class_array_size; i++) g_print ("%s%" G_GUINT16_FORMAT, i > 0 ? ", " : "", nr_band_class_array[i]); g_print ("'\n"); } shutdown (TRUE); } static gboolean query_slot_information_status_slot_index_parse (const gchar *str, guint32 *slot_index, GError **error) { gchar *endptr = NULL; gint64 n; g_assert (str != NULL); g_assert (slot_index != NULL); if (!str[0]) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "slot index not given"); return FALSE; } errno = 0; n = g_ascii_strtoll (str, &endptr, 10); if (errno || ((size_t)(endptr - str) < strlen (str))) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "couldn't parse slot index '%s'", str); return FALSE; } *slot_index = (guint32) n; return TRUE; } static void query_slot_information_status_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 slot_index; MbimUiccSlotState slot_state; const gchar *slot_state_str; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_basic_connect_extensions_slot_info_status_response_parse ( response, &slot_index, &slot_state, &error)) { g_printerr ("error: conldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } slot_state_str = mbim_uicc_slot_state_get_string (slot_state); g_print ("[%s] Slot info status retrieved:\n" "\t Slot '%u': '%s'\n", mbim_device_get_path_display (device), slot_index, VALIDATE_UNKNOWN (slot_state_str)); shutdown (TRUE); } static gboolean set_device_slot_mappings_input_parse (const gchar *str, GPtrArray **slot_array, GError **error) { g_auto(GStrv) split = NULL; gchar *endptr = NULL; gint64 n; MbimSlot *slot_index; guint32 i = 0; g_assert (slot_array != NULL); split = g_strsplit (str, ",", 0); if (g_strv_length (split) < 1) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "missing arguments"); return FALSE; } *slot_array = g_ptr_array_new_with_free_func (g_free); while (split[i] != NULL) { errno = 0; n = g_ascii_strtoll (split[i], &endptr, 10); if (errno || n < 0 || n > G_MAXUINT32 || ((size_t)(endptr - split[i]) < strlen (split[i]))) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "couldn't parse device slot index '%s'", split[i]); return FALSE; } slot_index = g_new (MbimSlot, 1); slot_index->slot = (guint32) n; g_ptr_array_add (*slot_array, slot_index); i++; } return TRUE; } static void query_device_slot_mappings_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 map_count = 0; g_autoptr(MbimSlotArray) slot_mappings = NULL; guint i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_basic_connect_extensions_device_slot_mappings_response_parse ( response, &map_count, &slot_mappings, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } if (set_device_slot_mappings_str) { g_print ("[%s] Updated slot mappings retrieved:\n", mbim_device_get_path_display (device)); } else { g_print ("[%s] Slot mappings retrieved:\n", mbim_device_get_path_display (device)); } for (i = 0; i < map_count; i++) { g_print ("\t Executor '%u': slot '%u'\n", i, slot_mappings[i]->slot); } shutdown (TRUE); } static void query_location_info_status_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 location_area_code = 0; guint32 tracking_area_code = 0; guint32 cell_id = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully queried location info status\n", mbim_device_get_path_display (device)); if (!mbim_message_ms_basic_connect_extensions_location_info_status_response_parse ( response, &location_area_code, &tracking_area_code, &cell_id, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print (" Location area code: %04X\n", location_area_code); g_print (" Tracking area code: %06X\n", tracking_area_code); g_print (" Cell ID: %08X\n", cell_id); shutdown (TRUE); } typedef struct { MbimContextOperation operation; MbimContextIpType ip_type; MbimContextState state; MbimContextRoamingControl roaming_control; MbimContextMediaType media_type; MbimContextSource source; gchar *access_string; gchar *username; gchar *password; MbimCompression compression; MbimAuthProtocol auth_protocol; MbimContextType context_type; } ProvisionedContextProperties; static void provisioned_context_properties_clear (ProvisionedContextProperties *props) { g_free (props->access_string); g_free (props->username); g_free (props->password); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ProvisionedContextProperties, provisioned_context_properties_clear) static gboolean set_provisioned_contexts_foreach_cb (const gchar *key, const gchar *value, GError **error, ProvisionedContextProperties *props) { if (g_ascii_strcasecmp (key, "operation") == 0) { if (!mbimcli_read_context_operation_from_string (value, &props->operation)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown operation: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "context-type") == 0) { if (!mbimcli_read_context_type_from_string (value, &props->context_type)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown context-type: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "ip-type") == 0) { if (!mbimcli_read_context_ip_type_from_string (value, &props->ip_type)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown ip-type: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "state") == 0) { if (!mbimcli_read_context_state_from_string (value, &props->state)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown state: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "roaming-control") == 0) { if (!mbimcli_read_context_roaming_control_from_string (value, &props->roaming_control)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown roaming-control: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "media-type") == 0) { if (!mbimcli_read_context_media_type_from_string (value, &props->media_type)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown media-type: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "source") == 0) { if (!mbimcli_read_context_source_from_string (value, &props->source)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown source: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "auth") == 0) { if (!mbimcli_read_auth_protocol_from_string (value, &props->auth_protocol)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown auth: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "compression") == 0) { if (!mbimcli_read_compression_from_string (value, &props->compression)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown compression: '%s'", value); return FALSE; } } else if (g_ascii_strcasecmp (key, "username") == 0) { g_free (props->username); props->username = g_strdup (value); } else if (g_ascii_strcasecmp (key, "password") == 0) { g_free (props->password); props->password = g_strdup (value); } else if (g_ascii_strcasecmp (key, "access-string") == 0) { g_free (props->access_string); props->access_string = g_strdup (value); } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static void provisioned_contexts_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(MbimProvisionedContextElementV2Array) provisioned_contexts = NULL; g_autoptr(GError) error = NULL; guint32 provisioned_contexts_count; guint32 i = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_basic_connect_extensions_provisioned_contexts_response_parse ( response, &provisioned_contexts_count, &provisioned_contexts, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Provisioned contexts (%u):\n", mbim_device_get_path_display (device), provisioned_contexts_count); for (i = 0; i < provisioned_contexts_count; i++) { g_print ("\tContext ID %u:\n" "\t Context type: '%s'\n" "\t IP type: '%s'\n" "\t State: '%s'\n" "\tRoaming control: '%s'\n" "\t Media type: '%s'\n" "\t Source: '%s'\n" "\t Access string: '%s'\n" "\t Username: '%s'\n" "\t Password: '%s'\n" "\t Compression: '%s'\n" "\t Auth protocol: '%s'\n", provisioned_contexts[i]->context_id, VALIDATE_UNKNOWN (mbim_context_type_get_string ( mbim_uuid_to_context_type (&provisioned_contexts[i]->context_type))), VALIDATE_UNKNOWN (mbim_context_ip_type_get_string ( provisioned_contexts[i]->ip_type)), VALIDATE_UNKNOWN (mbim_context_state_get_string ( provisioned_contexts[i]->state)), VALIDATE_UNKNOWN (mbim_context_roaming_control_get_string ( provisioned_contexts[i]->roaming)), VALIDATE_UNKNOWN (mbim_context_media_type_get_string ( provisioned_contexts[i]->media_type)), VALIDATE_UNKNOWN (mbim_context_source_get_string ( provisioned_contexts[i]->source)), VALIDATE_UNKNOWN (provisioned_contexts[i]->access_string), VALIDATE_UNKNOWN (provisioned_contexts[i]->user_name), VALIDATE_UNKNOWN (provisioned_contexts[i]->password), VALIDATE_UNKNOWN (mbim_compression_get_string ( provisioned_contexts[i]->compression)), VALIDATE_UNKNOWN (mbim_auth_protocol_get_string ( provisioned_contexts[i]->auth_protocol))); } shutdown (TRUE); } static void query_base_stations_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimDataClass system_type; MbimDataClassV3 system_type_v3; MbimDataSubclass system_subtype; g_autoptr(MbimCellInfoServingGsm) gsm_serving_cell = NULL; g_autoptr(MbimCellInfoServingUmts) umts_serving_cell = NULL; g_autoptr(MbimCellInfoServingTdscdma) tdscdma_serving_cell = NULL; g_autoptr(MbimCellInfoServingLte) lte_serving_cell = NULL; guint32 gsm_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringGsmArray) gsm_neighboring_cells = NULL; guint32 umts_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringUmtsArray) umts_neighboring_cells = NULL; guint32 tdscdma_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringTdscdmaArray) tdscdma_neighboring_cells = NULL; guint32 lte_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringLteArray) lte_neighboring_cells = NULL; guint32 cdma_cells_count; g_autoptr(MbimCellInfoCdmaArray) cdma_cells = NULL; guint32 nr_serving_cells_count; g_autoptr(MbimCellInfoServingNrArray) nr_serving_cells = NULL; guint32 nr_neighboring_cells_count; g_autoptr(MbimCellInfoNeighboringNrArray) nr_neighboring_cells = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } /* MBIMEx 3.0 support */ if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { if (!mbim_message_ms_basic_connect_extensions_v3_base_stations_info_response_parse ( response, &system_type_v3, &system_subtype, &gsm_serving_cell, &umts_serving_cell, &tdscdma_serving_cell, <e_serving_cell, &gsm_neighboring_cells_count, &gsm_neighboring_cells, &umts_neighboring_cells_count, &umts_neighboring_cells, &tdscdma_neighboring_cells_count, &tdscdma_neighboring_cells, <e_neighboring_cells_count, <e_neighboring_cells, &cdma_cells_count, &cdma_cells, &nr_serving_cells_count, &nr_serving_cells, &nr_neighboring_cells_count, &nr_neighboring_cells, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIMEx 3.0 Base Stations Info"); } /* MBIMEx 1.0 support */ else { if (!mbim_message_ms_basic_connect_extensions_base_stations_info_response_parse ( response, &system_type, &gsm_serving_cell, &umts_serving_cell, &tdscdma_serving_cell, <e_serving_cell, &gsm_neighboring_cells_count, &gsm_neighboring_cells, &umts_neighboring_cells_count, &umts_neighboring_cells, &tdscdma_neighboring_cells_count, &tdscdma_neighboring_cells, <e_neighboring_cells_count, <e_neighboring_cells, &cdma_cells_count, &cdma_cells, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully parsed response as MBIMEx 1.0 Base Stations Info"); } #define PRINT_VALIDATED_UINT(number, invalid, format, units) do { \ if (number == invalid) \ g_print ("%s: unknown\n", format); \ else \ g_print ("%s: %u%s\n", format, number, units ? units : ""); \ } while (0) #define PRINT_VALIDATED_UINT64(number, invalid, format, units) do { \ if (number == invalid) \ g_print ("%s: unknown\n", format); \ else \ g_print ("%s: %" G_GUINT64_FORMAT "%s\n", format, number, units ? units : ""); \ } while (0) #define PRINT_VALIDATED_INT(number, invalid, format, units) do { \ if (number == (gint32)invalid) \ g_print ("%s: unknown\n", format); \ else \ g_print ("%s: %d%s\n", format, number, units ? units : ""); \ } while (0) #define PRINT_VALIDATED_SCALED_UINT(number, invalid, scale, format, units) do { \ if (number == 0xFFFFFFFF) \ g_print ("%s: unknown\n", format); \ else \ g_print ("%s: %d%s\n", format, ((gint32)number) + scale, units ? units : ""); \ } while (0) if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { g_autofree gchar *system_type_str = NULL; g_autofree gchar *system_subtype_str = NULL; system_type_str = mbim_data_class_v3_build_string_from_mask (system_type_v3); g_print ("System type: %s\n", system_type_str); system_subtype_str = mbim_data_subclass_build_string_from_mask (system_subtype); g_print ("System subtype: %s\n", VALIDATE_UNKNOWN (system_subtype_str)); } else { g_autofree gchar *system_type_str = NULL; system_type_str = mbim_data_class_build_string_from_mask (system_type); g_print ("System type: %s\n", system_type_str); } if (gsm_serving_cell) { g_print ("GSM serving cell:\n" "\t Provider id: %s\n", VALIDATE_UNKNOWN (gsm_serving_cell->provider_id)); PRINT_VALIDATED_UINT (gsm_serving_cell->location_area_code, 0xFFFFFFFF, "\t LAC", NULL); PRINT_VALIDATED_UINT (gsm_serving_cell->cell_id, 0xFFFFFFFF, "\t Cell ID", NULL); PRINT_VALIDATED_UINT (gsm_serving_cell->timing_advance, 0xFFFFFFFF, "\t Timing advance", " bit periods"); PRINT_VALIDATED_UINT (gsm_serving_cell->arfcn, 0xFFFFFFFF, "\t ARFCN", NULL); PRINT_VALIDATED_UINT (gsm_serving_cell->base_station_id, 0xFFFFFFFF, "\tBase station ID", NULL); PRINT_VALIDATED_SCALED_UINT (gsm_serving_cell->rx_level, 0xFFFFFFFF, -110, "\t Rx level", " dBm"); } else g_print ("GSM serving cell: n/a\n"); if (gsm_neighboring_cells_count && gsm_neighboring_cells) { guint i; g_print ("Neighboring GSM cells: %d\n", gsm_neighboring_cells_count); for (i = 0; i < gsm_neighboring_cells_count; i++) { g_print ("\tNeighboring cell [%u]:\n" "\t\t Provider id: %s\n", i + 1, VALIDATE_UNKNOWN (gsm_neighboring_cells[i]->provider_id)); PRINT_VALIDATED_UINT (gsm_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "\t\t LAC", NULL); PRINT_VALIDATED_UINT (gsm_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "\t\t Cell ID", NULL); PRINT_VALIDATED_UINT (gsm_neighboring_cells[i]->arfcn, 0xFFFFFFFF, "\t\t ARFCN", NULL); PRINT_VALIDATED_UINT (gsm_neighboring_cells[i]->base_station_id, 0xFFFFFFFF, "\t\tBase station ID", NULL); PRINT_VALIDATED_SCALED_UINT (gsm_neighboring_cells[i]->rx_level, 0xFFFFFFFF, -110, "\t\t Rx level", " dBm"); } } else g_print ("Neighboring GSM cells: n/a\n"); if (umts_serving_cell) { g_print ("UMTS Serving cell:\n" "\t Provider id: %s\n", VALIDATE_UNKNOWN (umts_serving_cell->provider_id)); PRINT_VALIDATED_UINT (umts_serving_cell->location_area_code, 0xFFFFFFFF, "\t LAC", NULL); PRINT_VALIDATED_UINT (umts_serving_cell->cell_id, 0xFFFFFFFF, "\t Cell id", NULL); PRINT_VALIDATED_UINT (umts_serving_cell->frequency_info_ul, 0xFFFFFFFF, "\t Frequency info uplink", NULL); PRINT_VALIDATED_UINT (umts_serving_cell->frequency_info_dl, 0xFFFFFFFF, "\tFrequency info downlink", NULL); PRINT_VALIDATED_UINT (umts_serving_cell->frequency_info_nt, 0xFFFFFFFF, "\t Frequency info TDD", NULL); PRINT_VALIDATED_UINT (umts_serving_cell->uarfcn, 0xFFFFFFFF, "\t UARFCN", NULL); PRINT_VALIDATED_UINT (umts_serving_cell->primary_scrambling_code, 0xFFFFFFFF, "\tPrimary Scrambling Code", NULL); PRINT_VALIDATED_INT (umts_serving_cell->rscp, 0, "\t RSCP", " dBm"); PRINT_VALIDATED_INT (umts_serving_cell->ecno, 1, "\t ECNO", " dBm"); PRINT_VALIDATED_UINT (umts_serving_cell->path_loss, 0xFFFFFFFF, "\t Path loss", NULL); } else g_print ("UMTS serving cell: n/a\n"); if (umts_neighboring_cells_count && umts_neighboring_cells) { guint i; g_print ("Neighboring UMTS cells: %d\n", umts_neighboring_cells_count); for (i = 0; i < umts_neighboring_cells_count; i++) { g_print ("\tNeighboring cell [%u]:\n" "\t\t Provider id: %s\n", i + 1, VALIDATE_UNKNOWN (umts_neighboring_cells[i]->provider_id)); PRINT_VALIDATED_UINT (umts_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "\t\t LAC", NULL); PRINT_VALIDATED_UINT (umts_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "\t\t Cell id", NULL); PRINT_VALIDATED_UINT (umts_neighboring_cells[i]->uarfcn, 0xFFFFFFFF, "\t\t UARFCN", NULL); PRINT_VALIDATED_UINT (umts_neighboring_cells[i]->primary_scrambling_code, 0xFFFFFFFF, "\t\tPrimary Scrambling Code", NULL); PRINT_VALIDATED_INT (umts_neighboring_cells[i]->rscp, 0, "\t\t RSCP", " dBm"); PRINT_VALIDATED_INT (umts_neighboring_cells[i]->ecno, 1, "\t\t ECNO", " dBm"); PRINT_VALIDATED_UINT (umts_neighboring_cells[i]->path_loss, 0xFFFFFFFF, "\t\t Path loss", NULL); } } else g_print ("Neighboring UMTS cells: n/a\n"); if (tdscdma_serving_cell) { g_print ("TDSCDMA Serving cell:\n" "\t Provider id: %s\n", VALIDATE_UNKNOWN (tdscdma_serving_cell->provider_id)); PRINT_VALIDATED_UINT (tdscdma_serving_cell->location_area_code, 0xFFFFFFFF, "\t LAC", NULL); PRINT_VALIDATED_UINT (tdscdma_serving_cell->cell_id, 0xFFFFFFFF, "\t Cell id", NULL); PRINT_VALIDATED_UINT (tdscdma_serving_cell->uarfcn, 0xFFFFFFFF, "\t UARFCN", NULL); PRINT_VALIDATED_UINT (tdscdma_serving_cell->cell_parameter_id, 0xFFFFFFFF, "\tCell parameter id", NULL); PRINT_VALIDATED_UINT (tdscdma_serving_cell->timing_advance, 0xFFFFFFFF, "\t Timing advance", NULL); PRINT_VALIDATED_INT (tdscdma_serving_cell->rscp, 0xFFFFFFFF, "\t RSCP", " dBm"); PRINT_VALIDATED_UINT (tdscdma_serving_cell->path_loss, 0xFFFFFFFF, "\t Path loss", NULL); } else g_print ("TDSCDMA serving cell: n/a\n"); if (tdscdma_neighboring_cells_count && tdscdma_neighboring_cells) { guint i; g_print ("Neighboring TDSCDMA cells: %d\n", tdscdma_neighboring_cells_count); for (i = 0; i < tdscdma_neighboring_cells_count; i++) { g_print ("\tNeighboring cell [%u]:\n" "\t\t Provider id: %s\n", i + 1, VALIDATE_UNKNOWN (tdscdma_neighboring_cells[i]->provider_id)); PRINT_VALIDATED_UINT (tdscdma_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "\t\t LAC", NULL); PRINT_VALIDATED_UINT (tdscdma_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "\t\t Cell id", NULL); PRINT_VALIDATED_UINT (tdscdma_neighboring_cells[i]->uarfcn, 0xFFFFFFFF, "\t\t UARFCN", NULL); PRINT_VALIDATED_UINT (tdscdma_neighboring_cells[i]->cell_parameter_id, 0xFFFFFFFF, "\t\tCell parameter id", NULL); PRINT_VALIDATED_UINT (tdscdma_neighboring_cells[i]->timing_advance, 0xFFFFFFFF, "\t\t Timing advance", NULL); PRINT_VALIDATED_INT (tdscdma_neighboring_cells[i]->rscp, 0xFFFFFFFF, "\t\t RSCP", " dBm"); PRINT_VALIDATED_UINT (tdscdma_neighboring_cells[i]->path_loss, 0xFFFFFFFF, "\t\t Path Loss", NULL); } } else g_print ("Neighboring TDSCDMA cells: n/a\n"); if (lte_serving_cell) { g_print ("LTE Serving cell:\n" "\t Provider id: %s\n", VALIDATE_UNKNOWN (lte_serving_cell->provider_id)); PRINT_VALIDATED_UINT (lte_serving_cell->cell_id, 0xFFFFFFFF, "\t Cell id", NULL); PRINT_VALIDATED_UINT (lte_serving_cell->earfcn, 0xFFFFFFFF, "\t EARFCN", NULL); PRINT_VALIDATED_UINT (lte_serving_cell->physical_cell_id, 0xFFFFFFFF, "\t Physical cell id", NULL); PRINT_VALIDATED_UINT (lte_serving_cell->tac, 0xFFFFFFFF, "\t TAC", NULL); PRINT_VALIDATED_INT (lte_serving_cell->rsrp, 0xFFFFFFFF, "\t RSRP", " dBm"); PRINT_VALIDATED_INT (lte_serving_cell->rsrq, 0xFFFFFFFF, "\t RSRQ", " dBm"); PRINT_VALIDATED_UINT (lte_serving_cell->timing_advance, 0xFFFFFFFF, "\t Timing advance", NULL); } else g_print ("LTE serving cell: n/a\n"); if (lte_neighboring_cells_count && lte_neighboring_cells) { guint i; g_print ("Neighboring LTE cells: %d\n", lte_neighboring_cells_count); for (i = 0; i < lte_neighboring_cells_count; i++) { g_print ("\tNeighboring cell [%u]:\n" "\t\t Provider id: %s\n", i + 1, VALIDATE_UNKNOWN (lte_neighboring_cells[i]->provider_id)); PRINT_VALIDATED_UINT (lte_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "\t\t Cell id", NULL); PRINT_VALIDATED_UINT (lte_neighboring_cells[i]->earfcn, 0xFFFFFFFF, "\t\t EARFCN", NULL); PRINT_VALIDATED_UINT (lte_neighboring_cells[i]->physical_cell_id, 0xFFFFFFFF, "\t\t Physical cell id", NULL); PRINT_VALIDATED_UINT (lte_neighboring_cells[i]->tac, 0xFFFFFFFF, "\t\t TAC", NULL); PRINT_VALIDATED_INT (lte_neighboring_cells[i]->rsrp, 0xFFFFFFFF, "\t\t RSRP", " dBm"); PRINT_VALIDATED_INT (lte_neighboring_cells[i]->rsrq, 0xFFFFFFFF, "\t\t RSRQ", " dBm"); } } else g_print ("Neighboring LTE cells: n/a\n"); if (cdma_cells_count && cdma_cells) { guint i; g_print ("CDMA cells: %d\n", cdma_cells_count); for (i = 0; i < cdma_cells_count; i++) g_print ("Cell [%u]:\n" "\t Serving: %s\n", i + 1, cdma_cells[i]->serving_cell_flag ? "yes" : "no"); PRINT_VALIDATED_UINT (cdma_cells[i]->nid, 0xFFFFFFFF, "\t NID", NULL); PRINT_VALIDATED_UINT (cdma_cells[i]->sid, 0xFFFFFFFF, "\t SID", NULL); PRINT_VALIDATED_UINT (cdma_cells[i]->base_station_id, 0xFFFFFFFF, "\tBase station id", NULL); /* TODO: The Base Station Latitude (0-4194303). This is encoded in units of 0.25 seconds, expressed * in two’s complement representation within the low 22 bits of the DWORD. As a signed value, * North latitudes are positive. Use 0xFFFFFFFF when this information is not available. */ PRINT_VALIDATED_UINT (cdma_cells[i]->base_latitude, 0xFFFFFFFF, "\t Base latitude", NULL); /* TODO: The Base Station Longitude (0-8388607). This is encoded in units of 0.25 seconds, expressed * in two’s complement representation within the low 23 bits of the DWORD. As a signed value, East * longitudes are positive. Use 0xFFFFFFFF when this information is not available. */ PRINT_VALIDATED_UINT (cdma_cells[i]->base_longitude, 0xFFFFFFFF, "\t Base longitude", NULL); PRINT_VALIDATED_UINT (cdma_cells[i]->ref_pn, 0xFFFFFFFF, "\t RefPN", NULL); PRINT_VALIDATED_UINT (cdma_cells[i]->gps_seconds, 0xFFFFFFFF, "\t GPS seconds", " seconds"); PRINT_VALIDATED_UINT (cdma_cells[i]->pilot_strength, 0xFFFFFFFF, "\t Pilot strength", NULL); } else g_print ("CDMA cells: n/a\n"); if (nr_serving_cells_count && nr_serving_cells) { guint i; g_print ("Serving NR cells: %d\n", nr_serving_cells_count); for (i = 0; i < nr_serving_cells_count; i++) { g_print ("\tServing cell [%u]:\n" "\t\t Provider id: %s\n", i + 1, VALIDATE_UNKNOWN (nr_serving_cells[i]->provider_id)); PRINT_VALIDATED_UINT64 (nr_serving_cells[i]->nci, 0xFFFFFFFFFFFFFFFF, "\t\t NCI", NULL); PRINT_VALIDATED_UINT (nr_serving_cells[i]->physical_cell_id, 0xFFFFFFFF, "\t\tPhysical cell id", NULL); PRINT_VALIDATED_UINT (nr_serving_cells[i]->nrarfcn, 0xFFFFFFFF, "\t\t NRARFCN", NULL); PRINT_VALIDATED_UINT (nr_serving_cells[i]->tac, 0xFFFFFFFF, "\t\t TAC", NULL); PRINT_VALIDATED_SCALED_UINT (nr_serving_cells[i]->rsrp, 0xFFFFFFFF, -156, "\t\t RSRP", " dBm"); PRINT_VALIDATED_SCALED_UINT (nr_serving_cells[i]->rsrq, 0xFFFFFFFF, -43, "\t\t RSRQ", " dB"); PRINT_VALIDATED_SCALED_UINT (nr_serving_cells[i]->sinr, 0xFFFFFFFF, -23, "\t\t SINR", " dB"); PRINT_VALIDATED_UINT64 (nr_serving_cells[i]->timing_advance, 0xFFFFFFFFFFFFFFFF, "\t\t Timing advance", " us"); } } else g_print ("Serving NR cells: n/a\n"); if (nr_neighboring_cells_count && nr_neighboring_cells) { guint i; g_print ("Neighboring NR cells: %d\n", nr_neighboring_cells_count); for (i = 0; i < nr_neighboring_cells_count; i++) { g_autofree gchar *system_subtype_str = NULL; system_subtype_str = mbim_data_subclass_build_string_from_mask (nr_neighboring_cells[i]->system_sub_type); g_print ("\tNeighboring cell [%u]:\n" "\t\t System subtype: %s\n" "\t\t Provider id: %s\n" "\t\t Cell id: %s\n", i + 1, VALIDATE_UNKNOWN (system_subtype_str), VALIDATE_UNKNOWN (nr_neighboring_cells[i]->provider_id), VALIDATE_UNKNOWN (nr_neighboring_cells[i]->cell_id)); PRINT_VALIDATED_UINT (nr_neighboring_cells[i]->physical_cell_id, 0xFFFFFFFF, "\t\tPhysical cell id", NULL); PRINT_VALIDATED_UINT (nr_neighboring_cells[i]->tac, 0xFFFFFFFF, "\t\t TAC", NULL); PRINT_VALIDATED_SCALED_UINT (nr_neighboring_cells[i]->rsrp, 0xFFFFFFFF, -156, "\t\t RSRP", " dBm"); PRINT_VALIDATED_SCALED_UINT (nr_neighboring_cells[i]->rsrq, 0xFFFFFFFF, -43, "\t\t RSRQ", " dB"); PRINT_VALIDATED_SCALED_UINT (nr_neighboring_cells[i]->sinr, 0xFFFFFFFF, -23, "\t\t SINR", " dB"); } } else g_print ("Neighboring NR cells: n/a\n"); #undef PRINT_VALIDATED_SCALED_UINT #undef PRINT_VALIDATED_UINT64 #undef PRINT_VALIDATED_UINT #undef PRINT_VALIDATED_INT shutdown (TRUE); } static void query_version_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint16 mbim_version; guint16 mbim_ext_version; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully exchanged version information\n", mbim_device_get_path_display (device)); if (!mbim_message_ms_basic_connect_extensions_v2_version_response_parse ( response, &mbim_version, &mbim_ext_version, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print (" MBIM version : %x.%02x\n", mbim_version >> 8, mbim_version & 0xFF); g_print (" MBIM extended version : %x.%02x\n", mbim_ext_version >> 8, mbim_ext_version & 0xFF); shutdown (TRUE); return; } typedef struct { MbimMicoMode mico_mode; gboolean mico_mode_set; MbimDrxCycle drx_cycle; gboolean drx_cycle_set; MbimLadnInfo ladn_info; gboolean ladn_info_set; MbimDefaultPduActivationHint pdu_hint; gboolean pdu_hint_set; gboolean re_register_if_needed; gboolean re_register_if_needed_set; } RegistrationParameters; static gboolean set_registration_parameters_foreach_cb (const gchar *key, const gchar *value, GError **error, RegistrationParameters *params) { if (g_ascii_strcasecmp (key, "mico-mode") == 0) { if (!mbimcli_read_mico_mode_from_string (value, ¶ms->mico_mode)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown mico-mode: '%s'", value); return FALSE; } params->mico_mode_set = TRUE; } else if (g_ascii_strcasecmp (key, "drx-cycle") == 0) { if (!mbimcli_read_drx_cycle_from_string (value, ¶ms->drx_cycle)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown drx-cycle: '%s'", value); return FALSE; } params->drx_cycle_set = TRUE; } else if (g_ascii_strcasecmp (key, "ladn-info") == 0) { if (!mbimcli_read_ladn_info_from_string (value, ¶ms->ladn_info)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown ladn-info: '%s'", value); return FALSE; } params->ladn_info_set = TRUE; } else if (g_ascii_strcasecmp (key, "default-pdu-activation-hint") == 0) { if (!mbimcli_read_default_pdu_activation_hint_from_string (value, ¶ms->pdu_hint)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown default-pdu-activation-hint: '%s'", value); return FALSE; } params->pdu_hint_set = TRUE; } else if (g_ascii_strcasecmp (key, "re-register-if-needed") == 0) { if (!mbimcli_read_boolean_from_string (value, ¶ms->re_register_if_needed)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_ARGS, "unknown re-register-if-needed: '%s'", value); return FALSE; } params->re_register_if_needed_set = TRUE; } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static void registration_parameters_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimMicoMode mico_mode; MbimDrxCycle drx_cycle; MbimLadnInfo ladn_info; MbimDefaultPduActivationHint pdu_hint; gboolean re_register_if_nedeed; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully received registration parameters information\n", mbim_device_get_path_display (device)); if (!mbim_message_ms_basic_connect_extensions_v3_registration_parameters_response_parse ( response, &mico_mode, &drx_cycle, &ladn_info, &pdu_hint, &re_register_if_nedeed, NULL, /* ignore unnamed IEs for now */ &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("\t MICO mode: %s\n", mbim_mico_mode_get_string (mico_mode)); g_print ("\t DRX cycle: %s\n", mbim_drx_cycle_get_string (drx_cycle)); g_print ("\t LADN information: %s\n", mbim_ladn_info_get_string (ladn_info)); g_print ("\tDefault PDU activation: %s\n", mbim_default_pdu_activation_hint_get_string (pdu_hint)); g_print ("\t Re-register if needed: %s\n", re_register_if_nedeed ? "yes" : "no"); shutdown (TRUE); } static void query_modem_configuration_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimModemConfigurationStatus configuration_status; g_autofree gchar *configuration_name = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_basic_connect_extensions_v3_modem_configuration_response_parse ( response, &configuration_status, &configuration_name, NULL, /* ignore unnamed IEs for now */ &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Modem configuration retrieved: \n", mbim_device_get_path_display (device)); g_print ("\tStatus: '%s'\n" "\t Name: '%s'\n", VALIDATE_UNKNOWN (mbim_modem_configuration_status_get_string (configuration_status)), VALIDATE_UNKNOWN (configuration_name)); shutdown (TRUE); } static void query_wake_reason_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimWakeType wake_type; guint32 session_id; MbimTlv *wake_tlv = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_basic_connect_extensions_v3_wake_reason_response_parse ( response, &wake_type, &session_id, &wake_tlv, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully queried wake reason\n", mbim_device_get_path_display (device)); g_print ("\t Wake type: '%s'\n", mbim_wake_type_get_string (wake_type)); g_print ("\tSession ID: '%u'\n", session_id); if ((wake_type == MBIM_WAKE_TYPE_CID_RESPONSE) || (wake_type == MBIM_WAKE_TYPE_CID_INDICATION)) { const MbimUuid *service = NULL; g_autofree gchar *service_str = NULL; guint32 cid = 0; guint32 payload_size = 0; g_autofree guint8 *payload = NULL; g_autofree gchar *payload_str = NULL; if (!mbim_tlv_wake_command_get (wake_tlv, &service, &cid, &payload_size, &payload, &error)) { g_printerr ("error: couldn't parse wake command TLV: %s\n", error->message); shutdown (FALSE); return; } /* Known payload defined right now only for the Connect CID */ if ((mbim_uuid_to_service (service) == MBIM_SERVICE_BASIC_CONNECT) && (cid == MBIM_CID_BASIC_CONNECT_CONNECT) && (payload_size == 4)) { guint32 activate; memcpy (&activate, payload, payload_size); activate = GUINT32_FROM_LE (activate); if (activate == 0x00000001 || activate == 0x00000000) payload_str = g_strdup (activate ? "activate" : "deactivate"); } if (!payload_str) payload_str = mbim_common_str_hex (payload, payload_size, ':'); service_str = mbim_uuid_get_printable (service); g_print ("\t Service: '%s'\n", service_str); g_print ("\t CID: '0x%08x'\n", cid); g_print ("\t Payload: '%s'\n", payload_str); shutdown (TRUE); return; } if (wake_type == MBIM_WAKE_TYPE_PACKET) { guint32 filter_id = 0; guint32 original_packet_size = 0; guint32 packet_size = 0; g_autofree guint8 *packet = NULL; g_autofree gchar *packet_str = NULL; if (!mbim_tlv_wake_packet_get (wake_tlv, &filter_id, &original_packet_size, &packet_size, &packet, &error)) { g_printerr ("error: couldn't parse wake packet TLV: %s\n", error->message); shutdown (FALSE); return; } packet_str = mbim_common_str_hex (packet, packet_size, ':'); g_print ("\t Filter ID: '%u'\n", filter_id); g_print ("\tOriginal size: '%u'\n", original_packet_size); g_print ("\t Saved size: '%u'\n", packet_size); g_print ("\t Packet: '%s'\n", packet_str); shutdown (TRUE); return; } g_printerr ("error: unknown wake type: 0x%08x\n", wake_type); shutdown (FALSE); } static void device_reset_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_basic_connect_extensions_device_reset_response_parse (response, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully requested device reset\n", mbim_device_get_path_display (device)); shutdown (TRUE); } void mbimcli_ms_basic_connect_extensions_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; g_autoptr(GError) error = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to get PCO? */ if (query_pco_str) { MbimPcoValue pco_value; if (!session_id_parse (query_pco_str, &pco_value.session_id, &error)) { g_printerr ("error: couldn't parse session ID: %s\n", error->message); shutdown (FALSE); return; } pco_value.pco_data_size = 0; pco_value.pco_data_type = MBIM_PCO_TYPE_COMPLETE; pco_value.pco_data_buffer = NULL; g_debug ("Asynchronously querying PCO..."); request = mbim_message_ms_basic_connect_extensions_pco_query_new (&pco_value, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_pco_ready, NULL); return; } if (query_lte_attach_configuration_flag) { g_debug ("Asynchronously querying LTE attach configuration..."); request = mbim_message_ms_basic_connect_extensions_lte_attach_configuration_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_lte_attach_configuration_ready, NULL); return; } if (query_lte_attach_status_flag || query_lte_attach_info_flag) { g_debug ("Asynchronously querying LTE attach info..."); request = mbim_message_ms_basic_connect_extensions_lte_attach_info_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_lte_attach_info_ready, NULL); return; } if (query_sys_caps_flag) { g_debug ("Asynchronously querying system capabilities..."); request = mbim_message_ms_basic_connect_extensions_sys_caps_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_sys_caps_ready, NULL); return; } if (query_device_caps_flag) { g_debug ("Asynchronously querying device capabilities..."); request = mbim_message_ms_basic_connect_extensions_device_caps_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_device_caps_ready, NULL); return; } if (query_slot_info_status_str) { guint32 slot_index; if (!query_slot_information_status_slot_index_parse (query_slot_info_status_str, &slot_index, &error)) { g_printerr ("error: couldn't parse slot index: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Asynchronously querying slot information status..."); request = mbim_message_ms_basic_connect_extensions_slot_info_status_query_new (slot_index, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_slot_information_status_ready, NULL); return; } if (set_device_slot_mappings_str) { g_autoptr(GPtrArray) slot_array = NULL; g_print ("Asynchronously set device slot mappings\n"); if (!set_device_slot_mappings_input_parse (set_device_slot_mappings_str, &slot_array, &error)) { g_printerr ("error: couldn't parse setting argument: %s\n", error->message); shutdown (FALSE); return; } request = mbim_message_ms_basic_connect_extensions_device_slot_mappings_set_new (slot_array->len, (const MbimSlot **)slot_array->pdata, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_device_slot_mappings_ready, NULL); return; } if (query_device_slot_mappings_flag) { g_debug ("Asynchronously querying device slot mappings..."); request = mbim_message_ms_basic_connect_extensions_device_slot_mappings_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_device_slot_mappings_ready, NULL); return; } if (query_location_info_status_flag) { g_debug ("Asynchronously querying location info status..."); request = mbim_message_ms_basic_connect_extensions_location_info_status_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_location_info_status_ready, NULL); return; } if (set_provisioned_contexts_str) { g_auto(ProvisionedContextProperties) props = { .access_string = NULL, .operation = MBIM_CONTEXT_OPERATION_DELETE, .auth_protocol = MBIM_AUTH_PROTOCOL_NONE, .username = NULL, .password = NULL, .ip_type = MBIM_CONTEXT_IP_TYPE_DEFAULT, .state = MBIM_CONTEXT_STATE_DISABLED, .roaming_control = MBIM_CONTEXT_ROAMING_CONTROL_HOME_ONLY, .media_type = MBIM_CONTEXT_MEDIA_TYPE_CELLULAR_ONLY, .source = MBIM_CONTEXT_SOURCE_ADMIN, .compression = MBIM_COMPRESSION_NONE, .context_type = MBIM_CONTEXT_TYPE_INVALID }; if (!mbimcli_parse_key_value_string (set_provisioned_contexts_str, &error, (MbimParseKeyValueForeachFn)set_provisioned_contexts_foreach_cb, &props)) { g_printerr ("error: couldn't parse input string: %s\n", error->message); shutdown (FALSE); return; } request = mbim_message_ms_basic_connect_extensions_provisioned_contexts_set_new ( props.operation, mbim_uuid_from_context_type (props.context_type), props.ip_type, props.state, props.roaming_control, props.media_type, props.source, props.access_string, props.username, props.password, props.compression, props.auth_protocol, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 60, ctx->cancellable, (GAsyncReadyCallback)provisioned_contexts_ready, NULL); return; } /* Request to query Provisioned contexts? */ if (query_provisioned_contexts_flag) { g_debug ("Asynchronously query provisioned contexts..."); request = mbim_message_ms_basic_connect_extensions_provisioned_contexts_query_new (NULL); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)provisioned_contexts_ready, NULL); return; } if (query_base_stations_flag) { g_debug ("Asynchronously querying base stations..."); /* default capacity is 15, so use that value when querying */ if (mbim_device_check_ms_mbimex_version (ctx->device, 3, 0)) request = mbim_message_ms_basic_connect_extensions_v3_base_stations_info_query_new (15, 15, 15, 15, 15, 15, NULL); else request = mbim_message_ms_basic_connect_extensions_base_stations_info_query_new (15, 15, 15, 15, 15, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_base_stations_ready, NULL); return; } if (query_version_str) { guint16 bcd_mbim_version = 0; guint16 bcd_mbim_extended_version = 0; guint8 mbim_version_major = 0; guint8 mbim_version_minor = 0; guint8 mbim_extended_version_major = 0; guint8 mbim_extended_version_minor = 0; g_auto(GStrv) split = NULL; g_auto(GStrv) mbim_version = NULL; g_auto(GStrv) mbim_extended_version = NULL; split = g_strsplit (query_version_str, ",", -1); if (g_strv_length (split) > 2) { g_printerr ("error: couldn't parse input string, too many arguments\n"); return; } if (g_strv_length (split) < 2) { g_printerr ("error: couldn't parse input string, missing arguments\n"); return; } mbim_version = g_strsplit (split[0], ".", -1); if (!mbimcli_read_uint8_from_bcd_string (mbim_version[0], &mbim_version_major) || !mbimcli_read_uint8_from_bcd_string (mbim_version[1], &mbim_version_minor)) { g_printerr ("error: couldn't parse version string\n"); return; } bcd_mbim_version = mbim_version_major << 8 | mbim_version_minor; g_debug ("BCD version built: 0x%x", bcd_mbim_version); mbim_extended_version = g_strsplit (split[1], ".", -1); if (!mbimcli_read_uint8_from_bcd_string (mbim_extended_version[0], &mbim_extended_version_major) || !mbimcli_read_uint8_from_bcd_string (mbim_extended_version[1], &mbim_extended_version_minor)) { g_printerr ("error: couldn't parse extended version string\n"); return; } bcd_mbim_extended_version = mbim_extended_version_major << 8 | mbim_extended_version_minor; g_debug ("BCD extended version built: 0x%x", bcd_mbim_extended_version); g_debug ("Asynchronously querying Version..."); request = mbim_message_ms_basic_connect_extensions_v2_version_query_new (bcd_mbim_version, bcd_mbim_extended_version, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_version_ready, NULL); return; } if (query_registration_parameters_flag) { g_debug (" Asynchronously querying registration parameters..."); request = mbim_message_ms_basic_connect_extensions_v3_registration_parameters_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)registration_parameters_ready, NULL); return; } if (device_reset_flag) { request = mbim_message_ms_basic_connect_extensions_device_reset_set_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)device_reset_ready, NULL); return; } if (set_registration_parameters_str) { RegistrationParameters params = { 0 }; if (!mbimcli_parse_key_value_string (set_registration_parameters_str, &error, (MbimParseKeyValueForeachFn)set_registration_parameters_foreach_cb, ¶ms)) { g_printerr ("error: couldn't parse input string: %s\n", error->message); shutdown (FALSE); return; } if (!params.mico_mode_set || !params.drx_cycle_set || !params.ladn_info_set || !params.pdu_hint_set || !params.re_register_if_needed_set) { g_printerr ("error: missing required keys\n"); if (!params.mico_mode_set) g_printerr ("error: key 'mico-mode' is missing\n"); if (!params.drx_cycle_set) g_printerr ("error: key 'drx-cycle' is missing\n"); if (!params.ladn_info_set) g_printerr ("error: key 'ladn-info' is missing\n"); if (!params.pdu_hint_set) g_printerr ("error: key 'default-pdu-activation-hint' is missing\n"); if (!params.re_register_if_needed_set) g_printerr ("error: key 're-register-is-needed' is missing\n"); shutdown (FALSE); return; } g_debug ("Asynchronously set registration parameters\n"); request = (mbim_message_ms_basic_connect_extensions_v3_registration_parameters_set_new ( params.mico_mode, params.drx_cycle, params.ladn_info, params.pdu_hint, params.re_register_if_needed, NULL, /* ignore unnamed IEs for now */ NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)registration_parameters_ready, NULL); return; } /* Request to query modem configuration? */ if (query_modem_configuration_flag) { g_debug ("Asynchronously query modem configuration\n"); request = mbim_message_ms_basic_connect_extensions_v3_modem_configuration_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_modem_configuration_ready, NULL); return; } /* Request to query Wake Reason? */ if (query_wake_reason_flag) { g_debug ("Asynchronously querying wake reason..."); request = mbim_message_ms_basic_connect_extensions_v3_wake_reason_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_wake_reason_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-ms-firmware-id.c000066400000000000000000000076411453630424100226030ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2014 Google, Inc. */ #include "config.h" #include #include #include #include #include #include #include #include "mbimcli.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean query_firmware_id_flag; static GOptionEntry entries[] = { { "ms-query-firmware-id", 0, 0, G_OPTION_ARG_NONE, &query_firmware_id_flag, "Query firmware ID", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_ms_firmware_id_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("ms-firmware-id", "Microsoft Firmware ID options:", "Show Microsoft Firmware ID Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_ms_firmware_id_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = query_firmware_id_flag; if (n_actions > 1) { g_printerr ("error: too many Microsoft Firmware ID actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void query_firmware_id_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; const MbimUuid *firmware_id; g_autofree gchar *firmware_id_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_firmware_id_get_response_parse (response, &firmware_id, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } firmware_id_str = firmware_id ? mbim_uuid_get_printable (firmware_id) : NULL; g_print ("[%s] Firmware ID retrieved: '%s'\n\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (firmware_id_str)); shutdown (TRUE); } void mbimcli_ms_firmware_id_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to get firmware ID? */ if (query_firmware_id_flag) { g_debug ("Asynchronously querying firmware ID..."); request = (mbim_message_ms_firmware_id_get_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_firmware_id_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-ms-host-shutdown.c000066400000000000000000000070741453630424100232230ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2014 Google, Inc. */ #include "config.h" #include #include #include #include #include #include #include #include "mbimcli.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean notify_host_shutdown_flag; static GOptionEntry entries[] = { { "ms-notify-host-shutdown", 0, 0, G_OPTION_ARG_NONE, ¬ify_host_shutdown_flag, "Notify that host is shutting down", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_ms_host_shutdown_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("ms-host-shutdown", "Microsoft Host Shutdown options:", "Show Microsoft Host Shutdown Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_ms_host_shutdown_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = notify_host_shutdown_flag; if (n_actions > 1) { g_printerr ("error: too many Microsoft Host Shutdown actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void ms_host_shutdown_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] Successfully notified that host is shutting down\n\n", mbim_device_get_path_display (device)); shutdown (TRUE); } void mbimcli_ms_host_shutdown_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to notify that host is shutting down */ if (notify_host_shutdown_flag) { g_debug ("Asynchronously notifying host is shutting down..."); request = (mbim_message_ms_host_shutdown_notify_set_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)ms_host_shutdown_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-ms-sar.c000066400000000000000000000332131453630424100211540ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2020 Aleksander Morgado */ #include "config.h" #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gchar *set_sar_config_str; static gboolean query_sar_config_flag; static gchar *set_transmission_status_str; static gboolean query_transmission_status_flag; static GOptionEntry entries[] = { { "ms-set-sar-config", 0, 0, G_OPTION_ARG_STRING, &set_sar_config_str, "Set SAR config", "[(device|os),(enabled|disabled)[,[{antenna_index,backoff_index}...]]]" }, { "ms-query-sar-config", 0, 0, G_OPTION_ARG_NONE, &query_sar_config_flag, "Query SAR config", NULL }, { "ms-set-transmission-status", 0, 0, G_OPTION_ARG_STRING, &set_transmission_status_str, "Set transmission status and hysteresis timer (in seconds)", "[(enabled|disabled),(timer)]" }, { "ms-query-transmission-status", 0, 0, G_OPTION_ARG_NONE, &query_transmission_status_flag, "Query transmission status", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_ms_sar_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("ms-sar", "Microsoft SAR options:", "Show Microsoft SAR Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_ms_sar_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = !!set_sar_config_str + query_sar_config_flag + !!set_transmission_status_str + query_transmission_status_flag; if (n_actions > 1) { g_printerr ("error: too many Microsoft SAR actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void ms_sar_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimSarControlMode mode; const gchar *mode_str; MbimSarBackoffState backoff_state; const gchar *backoff_state_str; MbimSarWifiHardwareState wifi_integration; const gchar *wifi_integration_str; guint32 config_states_count; g_autoptr(MbimSarConfigStateArray) config_states = NULL; guint32 i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_sar_config_response_parse ( response, &mode, &backoff_state, &wifi_integration, &config_states_count, &config_states, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } mode_str = mbim_sar_control_mode_get_string (mode); backoff_state_str = mbim_sar_backoff_state_get_string (backoff_state); wifi_integration_str = mbim_sar_wifi_hardware_state_get_string (wifi_integration); g_print ("[%s] SAR config:\n" "\t Mode: %s\n" "\t Backoff state: %s\n" "\tWi-Fi hardware state: %s\n" "\t Config states: %u\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (mode_str), VALIDATE_UNKNOWN (backoff_state_str), VALIDATE_UNKNOWN (wifi_integration_str), config_states_count); for (i = 0; i < config_states_count; i++) { g_print ("\t\t[%u]\n", i); if (config_states[i]->antenna_index == 0xFFFFFFFF) g_print ("\t\t Antenna index: all\n"); else g_print ("\t\t Antenna index: %u\n", config_states[i]->antenna_index); g_print ("\t\t Backoff index: %u\n", config_states[i]->backoff_index); } shutdown (TRUE); } static void modem_transmission_status_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimTransmissionNotificationStatus channel_notification; const gchar *channel_notification_str; MbimTransmissionState transmission_status; const gchar *transmission_status_str; guint32 hysteresis_timer; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_sar_transmission_status_response_parse ( response, &channel_notification, &transmission_status, &hysteresis_timer, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } channel_notification_str = mbim_transmission_notification_status_get_string (channel_notification); transmission_status_str = mbim_transmission_state_get_string (transmission_status); g_print ("[%s] Transmission status:\n" "\t notification: %s\n" "\t status: %s\n" "\t hysteresis timer: (%u)\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (channel_notification_str), VALIDATE_UNKNOWN (transmission_status_str), hysteresis_timer); shutdown (TRUE); } static gboolean sar_config_input_parse (const gchar *str, MbimSarControlMode *mode, MbimSarBackoffState *state, GPtrArray **states_array) { g_auto(GStrv) split = NULL; g_assert (mode != NULL); g_assert (state != NULL); g_assert (states_array!= NULL); /* Format of the string is: * "(mode:device or os),(state: enabled or disabled)[,[{antenna_index,backoff_index}...]]" * i.e. array of {antenna_index,backoff_index} is optional */ split = g_strsplit (str, ",", 3); if (g_strv_length (split) < 2) { g_printerr ("error: couldn't parse input string, missing arguments\n"); return FALSE; } if (!mbimcli_read_sar_control_mode_from_string (split[0], mode)) { g_printerr ("error: invalid mode: '%s'\n", split[0]); return FALSE; } if (!mbimcli_read_sar_backoff_state_from_string (split[1], state)) { g_printerr ("error: invalid state: '%s'\n", split[1]); return FALSE; } /* Check whether we have the optional item array: [{antenna_index,backoff_index}...] */ if (split[2]) { const gchar *array_begin; const gchar *array_end; g_autofree gchar *array_str = NULL; array_begin = strchr (split[2], '['); array_end = strchr (split[2], ']'); if (!array_begin || !array_end || (array_begin > array_end)) { g_printerr ("error: invalid SAR config state array: '%s'\n", split[2]); return FALSE; } array_str = g_strndup (&array_begin[1], array_end - array_begin - 1); if (!mbimcli_parse_sar_config_state_array (array_str, states_array)) { g_printerr ("error: failure parsing the SAR config state array contents: '%s'\n", array_str); return FALSE; } } else *states_array = NULL; return TRUE; } static gboolean transmission_status_input_parse (const gchar *str, MbimTransmissionNotificationStatus *notification, guint *hysteresis_timer) { g_auto(GStrv) split = NULL; g_assert (notification != NULL); g_assert (hysteresis_timer != NULL); /* Format of the string is: * "(notification: enabled or disabled),(seconds: 1~5)" */ split = g_strsplit (str, ",", -1); if (g_strv_length (split) < 2) { g_printerr ("error: couldn't parse input string, missing arguments\n"); return FALSE; } if (g_ascii_strcasecmp (split[0], "disabled") == 0) { *notification = MBIM_TRANSMISSION_NOTIFICATION_STATUS_DISABLED; } else if (g_ascii_strcasecmp (split[0], "enabled") == 0) { *notification = MBIM_TRANSMISSION_NOTIFICATION_STATUS_ENABLED; } else { g_printerr ("error: invalid state: '%s', it must be enabled or disabled\n", split[0]); return FALSE; } if (!mbimcli_read_uint_from_string (split[1], hysteresis_timer)) { g_printerr ("error: couldn't parse input string, invalid seconds '%s'\n", split[1]); return FALSE; } if (*hysteresis_timer < 1 || *hysteresis_timer > 5) { g_printerr ("error: the seconds of hysteresis_timer is %u, it must in range [1,5]\n", *hysteresis_timer); return FALSE; } return TRUE; } void mbimcli_ms_sar_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to set SAR config */ if (set_sar_config_str) { g_autoptr(GPtrArray) states_array = NULL; MbimSarControlMode mode; MbimSarBackoffState state; g_debug ("Asynchronously setting SAR config"); if (!sar_config_input_parse (set_sar_config_str, &mode, &state, &states_array)) { shutdown (FALSE); return; } request = mbim_message_ms_sar_config_set_new (mode, state, states_array ? states_array->len : 0, states_array ? (const MbimSarConfigState **)states_array->pdata : NULL, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)ms_sar_ready, NULL); return; } /* Request to querying SAR config */ if (query_sar_config_flag) { g_debug ("Asynchronously querying SAR config..."); request = (mbim_message_ms_sar_config_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)ms_sar_ready, NULL); return; } /* Request to set transmission status */ if (set_transmission_status_str) { MbimTransmissionNotificationStatus notification = MBIM_TRANSMISSION_NOTIFICATION_STATUS_DISABLED; guint32 hysteresis_timer = 0; g_debug ("Asynchronously set transmission status"); if (!transmission_status_input_parse (set_transmission_status_str, ¬ification, &hysteresis_timer)) { shutdown (FALSE); return; } request = mbim_message_ms_sar_transmission_status_set_new (notification, hysteresis_timer, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)modem_transmission_status_ready, NULL); return; } /* Request to query transmission status */ if (query_transmission_status_flag) { g_debug ("Asynchronously query transmission status"); request = mbim_message_ms_sar_transmission_status_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)modem_transmission_status_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-ms-uicc-low-level-access.c000066400000000000000000001553531453630424100244670ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2022 Google, Inc. */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbim-common.h" #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean query_uicc_application_list_flag; static gchar *query_uicc_file_status_str; static gchar *query_uicc_read_binary_str; static gchar *query_uicc_read_record_str; static gchar *set_uicc_open_channel_str; static gchar *set_uicc_close_channel_str; static gboolean query_uicc_atr_flag; static gchar *set_uicc_apdu_str; static gchar *set_uicc_reset_str; static gboolean query_uicc_reset_flag; static gchar *set_uicc_terminal_capability_str; static gboolean query_uicc_terminal_capability_flag; static GOptionEntry entries[] = { { "ms-query-uicc-application-list", 0, 0, G_OPTION_ARG_NONE, &query_uicc_application_list_flag, "Query UICC application list", NULL }, { "ms-query-uicc-file-status", 0, 0, G_OPTION_ARG_STRING, &query_uicc_file_status_str, "Query UICC file status (allowed keys: application-id, file-path)", "[\"key=value,...\"]" }, { "ms-query-uicc-read-binary", 0, 0, G_OPTION_ARG_STRING, &query_uicc_read_binary_str, "Read UICC binary file (allowed keys: application-id, file-path, read-offset, read-size, local-pin and data)", "[\"key=value,...\"]" }, { "ms-query-uicc-read-record", 0, 0, G_OPTION_ARG_STRING, &query_uicc_read_record_str, "Read UICC record file (allowed keys: application-id, file-path, record-number, local-pin and data)", "[\"key=value,...\"]" }, { "ms-set-uicc-open-channel", 0, 0, G_OPTION_ARG_STRING, &set_uicc_open_channel_str, "Set UICC open channel (allowed keys: application-id, selectp2arg, channel-group)", "[\"key=value,...\"]" }, { "ms-set-uicc-close-channel", 0, 0, G_OPTION_ARG_STRING, &set_uicc_close_channel_str, "Set UICC close channel (allowed keys: channel, channel-group)", "[\"key=value,...\"]" }, { "ms-query-uicc-atr", 0, 0, G_OPTION_ARG_NONE, &query_uicc_atr_flag, "Query UICC atr", NULL }, { "ms-set-uicc-apdu", 0, 0, G_OPTION_ARG_STRING, &set_uicc_apdu_str, "Set UICC apdu (allowed keys: channel, secure-message, classbyte-type, command)", "[\"key=value,...\"]" }, { "ms-set-uicc-reset", 0, 0, G_OPTION_ARG_STRING, &set_uicc_reset_str, "Set UICC reset", "[(Pass Through Action)]" }, { "ms-query-uicc-reset", 0, 0, G_OPTION_ARG_NONE, &query_uicc_reset_flag, "Query UICC reset", NULL }, { "ms-set-uicc-terminal-capability", 0, 0, G_OPTION_ARG_STRING, &set_uicc_terminal_capability_str, "Set UICC terminal capability (allowed keys: terminal-capability)", "[\"key=value,...\"]" }, { "ms-query-uicc-terminal-capability", 0, 0, G_OPTION_ARG_NONE, &query_uicc_terminal_capability_flag, "Query UICC terminal capability", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_ms_uicc_low_level_access_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("ms-uicc-low-level-access", "Microsoft UICC Low Level Access Service options:", "Show Microsoft UICC Low Level Access Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_ms_uicc_low_level_access_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = query_uicc_application_list_flag + !!query_uicc_file_status_str + !!query_uicc_read_binary_str + !!query_uicc_read_record_str + !!set_uicc_open_channel_str + !!set_uicc_close_channel_str + query_uicc_atr_flag + !!set_uicc_apdu_str + !!set_uicc_reset_str + query_uicc_reset_flag + !!set_uicc_terminal_capability_str + query_uicc_terminal_capability_flag; if (n_actions > 1) { g_printerr ("error: too many Microsoft UICC Low Level Access Service actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void read_record_query_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 status_word_1; guint32 status_word_2; const guint8 *data; guint32 data_size; g_autofree gchar *data_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_read_record_response_parse ( response, NULL, /* version */ &status_word_1, &status_word_2, &data_size, &data, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } data_str = mbim_common_str_hex (data, data_size, ':'); g_print ("[%s] UICC file record read:\n" "\tStatus word 1: %u\n" "\tStatus word 2: %u\n" "\t Data: %s\n", mbim_device_get_path_display (device), status_word_1, status_word_2, data_str); shutdown (TRUE); } typedef struct { gsize application_id_size; guint8 *application_id; gsize file_path_size; guint8 *file_path; guint32 record_number; gchar *local_pin; gsize data_size; guint8 *data; } ReadRecordQueryProperties; static void read_record_query_properties_clear (ReadRecordQueryProperties *props) { g_clear_pointer (&props->application_id, g_free); g_clear_pointer (&props->file_path, g_free); g_clear_pointer (&props->local_pin, g_free); g_clear_pointer (&props->data, g_free); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ReadRecordQueryProperties, read_record_query_properties_clear); static gboolean read_record_query_properties_handle (const gchar *key, const gchar *value, GError **error, gpointer user_data) { ReadRecordQueryProperties *props = user_data; if (g_ascii_strcasecmp (key, "application-id") == 0) { g_clear_pointer (&props->application_id, g_free); props->application_id_size = 0; props->application_id = mbimcli_read_buffer_from_string (value, -1, &props->application_id_size, error); if (!props->application_id) return FALSE; } else if (g_ascii_strcasecmp (key, "file-path") == 0) { g_clear_pointer (&props->file_path, g_free); props->file_path_size = 0; props->file_path = mbimcli_read_buffer_from_string (value, -1, &props->file_path_size, error); if (!props->file_path) return FALSE; } else if (g_ascii_strcasecmp (key, "record-number") == 0) { if (!mbimcli_read_uint_from_string (value, &props->record_number)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse field as an integer"); return FALSE; } } else if (g_ascii_strcasecmp (key, "local-pin") == 0) { g_clear_pointer (&props->local_pin, g_free); props->local_pin = g_strdup (value); } else if (g_ascii_strcasecmp (key, "data") == 0) { g_clear_pointer (&props->data, g_free); props->data_size = 0; props->data = mbimcli_read_buffer_from_string (value, -1, &props->data_size, error); if (!props->data) return FALSE; } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static gboolean read_record_query_input_parse (const gchar *str, ReadRecordQueryProperties *props, GError **error) { if (!mbimcli_parse_key_value_string (str, error, read_record_query_properties_handle, props)) return FALSE; if (!props->application_id_size || !props->application_id) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'application-id' is missing"); return FALSE; } if (!props->file_path_size || !props->file_path) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'file-path' is missing"); return FALSE; } /* all the other fields are optional */ return TRUE; } static void read_binary_query_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 status_word_1; guint32 status_word_2; const guint8 *data; guint32 data_size; g_autofree gchar *data_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_read_binary_response_parse ( response, NULL, /* version */ &status_word_1, &status_word_2, &data_size, &data, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } data_str = mbim_common_str_hex (data, data_size, ':'); g_print ("[%s] UICC file binary read:\n" "\tStatus word 1: %u\n" "\tStatus word 2: %u\n" "\t Data: %s\n", mbim_device_get_path_display (device), status_word_1, status_word_2, data_str); shutdown (TRUE); } typedef struct { gsize application_id_size; guint8 *application_id; gsize file_path_size; guint8 *file_path; guint32 read_offset; guint32 read_size; gchar *local_pin; gsize data_size; guint8 *data; } ReadBinaryQueryProperties; static void read_binary_query_properties_clear (ReadBinaryQueryProperties *props) { g_clear_pointer (&props->application_id, g_free); g_clear_pointer (&props->file_path, g_free); g_clear_pointer (&props->local_pin, g_free); g_clear_pointer (&props->data, g_free); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ReadBinaryQueryProperties, read_binary_query_properties_clear); static gboolean read_binary_query_properties_handle (const gchar *key, const gchar *value, GError **error, gpointer user_data) { ReadBinaryQueryProperties *props = user_data; if (g_ascii_strcasecmp (key, "application-id") == 0) { g_clear_pointer (&props->application_id, g_free); props->application_id_size = 0; props->application_id = mbimcli_read_buffer_from_string (value, -1, &props->application_id_size, error); if (!props->application_id) return FALSE; } else if (g_ascii_strcasecmp (key, "file-path") == 0) { g_clear_pointer (&props->file_path, g_free); props->file_path_size = 0; props->file_path = mbimcli_read_buffer_from_string (value, -1, &props->file_path_size, error); if (!props->file_path) return FALSE; } else if (g_ascii_strcasecmp (key, "read-offset") == 0) { if (!mbimcli_read_uint_from_string (value, &props->read_offset)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse field as an integer"); return FALSE; } } else if (g_ascii_strcasecmp (key, "read-size") == 0) { if (!mbimcli_read_uint_from_string (value, &props->read_size)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse field as an integer"); return FALSE; } } else if (g_ascii_strcasecmp (key, "local-pin") == 0) { g_clear_pointer (&props->local_pin, g_free); props->local_pin = g_strdup (value); } else if (g_ascii_strcasecmp (key, "data") == 0) { g_clear_pointer (&props->data, g_free); props->data_size = 0; props->data = mbimcli_read_buffer_from_string (value, -1, &props->data_size, error); if (!props->data) return FALSE; } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static gboolean read_binary_query_input_parse (const gchar *str, ReadBinaryQueryProperties *props, GError **error) { if (!mbimcli_parse_key_value_string (str, error, read_binary_query_properties_handle, props)) return FALSE; if (!props->application_id_size || !props->application_id) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'application-id' is missing"); return FALSE; } if (!props->file_path_size || !props->file_path) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'file-path' is missing"); return FALSE; } /* all the other fields are optional */ return TRUE; } static void file_status_query_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 status_word_1; guint32 status_word_2; MbimUiccFileAccessibility file_accessibility; MbimUiccFileType file_type; MbimUiccFileStructure file_structure; guint32 file_item_count; guint32 file_item_size; MbimPinType access_condition_read; MbimPinType access_condition_update; MbimPinType access_condition_activate; MbimPinType access_condition_deactivate; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_file_status_response_parse ( response, NULL, /* version */ &status_word_1, &status_word_2, &file_accessibility, &file_type, &file_structure, &file_item_count, &file_item_size, &access_condition_read, &access_condition_update, &access_condition_activate, &access_condition_deactivate, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] UICC file status retrieved:\n" "\t Status word 1: %u\n" "\t Status word 2: %u\n" "\t Accessibility: %s\n" "\t Type: %s\n" "\t Structure: %s\n" "\t Item count: %u\n" "\t Item size: %u\n" "\tAccess conditions:\n" "\t Read: %s\n" "\t Update: %s\n" "\t Activate: %s\n" "\t Deactivate: %s\n", mbim_device_get_path_display (device), status_word_1, status_word_2, mbim_uicc_file_accessibility_get_string (file_accessibility), mbim_uicc_file_type_get_string (file_type), mbim_uicc_file_structure_get_string (file_structure), file_item_count, file_item_size, mbim_pin_type_get_string (access_condition_read), mbim_pin_type_get_string (access_condition_update), mbim_pin_type_get_string (access_condition_activate), mbim_pin_type_get_string (access_condition_deactivate)); shutdown (TRUE); } typedef struct { gsize application_id_size; guint8 *application_id; gsize file_path_size; guint8 *file_path; } FileStatusQueryProperties; static void file_status_query_properties_clear (FileStatusQueryProperties *props) { g_clear_pointer (&props->application_id, g_free); g_clear_pointer (&props->file_path, g_free); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(FileStatusQueryProperties, file_status_query_properties_clear); static gboolean file_status_query_properties_handle (const gchar *key, const gchar *value, GError **error, gpointer user_data) { FileStatusQueryProperties *props = user_data; if (g_ascii_strcasecmp (key, "application-id") == 0) { g_clear_pointer (&props->application_id, g_free); props->application_id_size = 0; props->application_id = mbimcli_read_buffer_from_string (value, -1, &props->application_id_size, error); if (!props->application_id) return FALSE; } else if (g_ascii_strcasecmp (key, "file-path") == 0) { g_clear_pointer (&props->file_path, g_free); props->file_path_size = 0; props->file_path = mbimcli_read_buffer_from_string (value, -1, &props->file_path_size, error); if (!props->file_path) return FALSE; } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static gboolean file_status_query_input_parse (const gchar *str, FileStatusQueryProperties *props, GError **error) { if (!mbimcli_parse_key_value_string (str, error, file_status_query_properties_handle, props)) return FALSE; if (!props->application_id_size || !props->application_id) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'application-id' is missing"); return FALSE; } if (!props->file_path_size || !props->file_path) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'file-path' is missing"); return FALSE; } return TRUE; } static void application_list_query_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 application_count; guint32 active_application_index; g_autoptr(MbimUiccApplicationArray) applications = NULL; guint32 i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_application_list_response_parse ( response, NULL, /* version */ &application_count, &active_application_index, NULL, /* application_list_size_bytes */ &applications, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("[%s] UICC applications: (%u)\n", mbim_device_get_path_display (device), application_count); for (i = 0; i < application_count; i++) { g_autofree gchar *application_id_str = NULL; g_autofree gchar *pin_key_references_str = NULL; application_id_str = mbim_common_str_hex (applications[i]->application_id, applications[i]->application_id_size, ':'); pin_key_references_str = mbim_common_str_hex (applications[i]->pin_key_references, applications[i]->pin_key_references_size, ':'); g_print ("Application %u:%s\n", i, (i == active_application_index) ? " (active)" : ""); g_print ("\tApplication type: %s\n", mbim_uicc_application_type_get_string (applications[i]->application_type)); g_print ("\tApplication ID: %s\n", application_id_str); g_print ("\tApplication name: %s\n", applications[i]->application_name); g_print ("\tPIN key reference count: %u\n", applications[i]->pin_key_reference_count); g_print ("\tPIN key references: %s\n", pin_key_references_str); } shutdown (TRUE); } static void open_channel_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 status = 0; guint32 channel = 0; const guint8 *open_channel_response = NULL; guint32 open_channel_response_size = 0; g_autofree gchar *open_channel_response_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_open_channel_response_parse ( response, &status, &channel, &open_channel_response_size, &open_channel_response, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } open_channel_response_str = mbim_common_str_hex (open_channel_response, open_channel_response_size, ':'); g_print ("Succesfully retrieved open channel info:\n" "\t status: %u\n" "\t channel: %u\n" "\tresponse: %s\n", status, channel, open_channel_response_str); shutdown (TRUE); } typedef struct { guint32 channel_group; guint32 selectprg; gsize application_id_size; guint8 *application_id; } OpenChannelProperties; static void open_channel_properties_clear (OpenChannelProperties *props) { g_clear_pointer (&props->application_id, g_free); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(OpenChannelProperties, open_channel_properties_clear); static gboolean open_channel_properties_handle (const gchar *key, const gchar *value, GError **error, gpointer user_data) { OpenChannelProperties *props = user_data; if (g_ascii_strcasecmp (key, "application-id") == 0) { g_clear_pointer (&props->application_id, g_free); props->application_id_size = 0; props->application_id = mbimcli_read_buffer_from_string (value, -1, &props->application_id_size, error); if (!props->application_id) return FALSE; } else if (g_ascii_strcasecmp (key, "selectp2arg") == 0) { if (!mbimcli_read_uint_from_string (value, &props->selectprg)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse selectp2arg field as an integer"); return FALSE; } } else if (g_ascii_strcasecmp (key, "channel-group") == 0) { if (!mbimcli_read_uint_from_string (value, &props->channel_group)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse channel-group field as an integer"); return FALSE; } } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static gboolean open_channel_input_parse (const gchar *str, OpenChannelProperties *props, GError **error) { if (!mbimcli_parse_key_value_string (str, error, open_channel_properties_handle, props)) return FALSE; if (!props->application_id_size || !props->application_id) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'application-id' is missing"); return FALSE; } return TRUE; } static void close_channel_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 status = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_close_channel_response_parse ( response, &status, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("Succesfully retrieved close channel info:\n" "\tstatus: %u\n", status); shutdown (TRUE); } typedef struct { guint32 channel; guint32 channel_group; } CloseChannelProperties; static gboolean close_channel_properties_handle (const gchar *key, const gchar *value, GError **error, gpointer user_data) { CloseChannelProperties *props = user_data; if (g_ascii_strcasecmp (key, "channel") == 0) { if (!mbimcli_read_uint_from_string (value, &props->channel)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse channel field as an integer"); return FALSE; } } else if (g_ascii_strcasecmp (key, "channel-group") == 0) { if (!mbimcli_read_uint_from_string (value, &props->channel_group)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse channel-group field as an integer"); return FALSE; } } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static void query_atr_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; const guint8 *atr = NULL; g_autofree gchar *atr_buffer = NULL; guint32 atr_size = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_atr_response_parse ( response, &atr_size, &atr, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } atr_buffer = mbim_common_str_hex (atr, atr_size, ':'); g_print ("Succesfully retrieved ATR info:\n" "\tresponse: %s\n", atr_buffer); shutdown (TRUE); } static void set_apdu_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 status = 0; const guint8 *apdu_response; guint32 apdu_response_size = 0; g_autofree gchar *apdu_response_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_apdu_response_parse ( response, &status, &apdu_response_size, &apdu_response, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } apdu_response_str = mbim_common_str_hex (apdu_response, apdu_response_size, ':'); g_print ("Succesfully retrieved UICC APDU response:\n" "\t status: %u\n" "\tresponse: %s\n", status, apdu_response_str); shutdown (TRUE); } typedef struct { MbimUiccSecureMessaging secure_messaging; MbimUiccClassByteType class_byte_type; guint32 channel; gsize command_size; guint8 *command; } ApduProperties; static void apdu_properties_clear (ApduProperties *props) { g_clear_pointer (&props->command, g_free); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ApduProperties, apdu_properties_clear); static gboolean apdu_properties_handle (const gchar *key, const gchar *value, GError **error, gpointer user_data) { ApduProperties *props = user_data; if (g_ascii_strcasecmp (key, "command") == 0) { g_clear_pointer (&props->command, g_free); props->command_size = 0; props->command = mbimcli_read_buffer_from_string (value, -1, &props->command_size, error); if (!props->command) return FALSE; } else if (g_ascii_strcasecmp (key, "secure-message") == 0) { if (!mbimcli_read_uicc_secure_messaging_from_string (value, &props->secure_messaging)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse secure-message field"); return FALSE; } } else if (g_ascii_strcasecmp (key, "channel") == 0) { if (!mbimcli_read_uint_from_string (value, &props->channel)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse channel field as an integer"); return FALSE; } } else if (g_ascii_strcasecmp (key, "classbyte-type") == 0) { if (!mbimcli_read_uicc_class_byte_type_from_string (value, &props->class_byte_type)) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Failed to parse classbyte-type field"); return FALSE; } } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static gboolean apdu_input_parse (const gchar *str, ApduProperties *props, GError **error) { if (!mbimcli_parse_key_value_string (str, error, apdu_properties_handle, props)) return FALSE; if (!props->command_size || !props->command) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'command' is missing"); return FALSE; } return TRUE; } static void uicc_reset_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimUiccPassThroughStatus pass_through_status; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_reset_response_parse ( response, &pass_through_status, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("Succesfully retrieved reset info:\n" "\tpass through action: %s\n", mbim_uicc_pass_through_status_get_string (pass_through_status)); shutdown (TRUE); } static void set_terminal_capability_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } g_print ("Succesfully set terminal capability info\n"); shutdown (TRUE); } static void query_terminal_capability_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimTerminalCapabilityInfoArray) terminal_capability = NULL; guint32 terminal_capability_count; guint32 i = 0; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_uicc_low_level_access_terminal_capability_response_parse ( response, &terminal_capability_count, &terminal_capability, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Successfully queried terminal capability information"); g_print ("Terminal capability: (%u)\n", terminal_capability_count); for (i = 0; i < terminal_capability_count; i++) { g_autofree gchar *terminal_caps = NULL; guint32 terminal_size = 0; if (terminal_capability) { terminal_size = terminal_capability[i]->terminal_capability_data_size; terminal_caps = mbim_common_str_hex (terminal_capability[i]->terminal_capability_data, terminal_size, ':'); } else { g_assert_not_reached (); } g_print ("\t terminal capability count: %u\n", i); g_print ("\t terminal capability size : %u\n", terminal_size); g_print ("\t terminal capability : %s\n", VALIDATE_UNKNOWN (terminal_caps)); } shutdown (TRUE); } typedef struct { GPtrArray *array; gchar *terminal_capability; } terminalcapabilityProperties; static void mbim_terminal_capability_free (MbimTerminalCapabilityInfo *var) { if (!var) return; g_free (var->terminal_capability_data); g_free (var); } static void terminal_capability_properties_clear (terminalcapabilityProperties *props) { g_free(props->terminal_capability); g_ptr_array_unref (props->array); } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(terminalcapabilityProperties, terminal_capability_properties_clear); static gboolean check_terminal_add (terminalcapabilityProperties *props, GError **error) { MbimTerminalCapabilityInfo *terminal; g_autofree guint8 *terminal_capability = NULL; gsize terminal_capability_data_size = 0; if (!props->terminal_capability) { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "Option 'Terminal Capability' is missing"); return FALSE; } terminal_capability = mbimcli_read_buffer_from_string (props->terminal_capability, -1, &terminal_capability_data_size, error); if (!terminal_capability) return FALSE; terminal = g_new0 (MbimTerminalCapabilityInfo, 1); terminal->terminal_capability_data_size = terminal_capability_data_size; terminal->terminal_capability_data = g_steal_pointer (&terminal_capability); g_ptr_array_add (props->array, terminal); g_clear_pointer (&props->terminal_capability, g_free); return TRUE; } static gboolean set_terminal_foreach_cb (const gchar *key, const gchar *value, GError **error, terminalcapabilityProperties *props) { if (g_ascii_strcasecmp (key, "terminal-capability") == 0) { if (props->terminal_capability) { if (!check_terminal_add (props, error)) return FALSE; g_clear_pointer (&props->terminal_capability, g_free); } props->terminal_capability = g_strdup (value); } else { g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED, "unrecognized option '%s'", key); return FALSE; } return TRUE; } static gboolean terminal_capability_parse (const gchar *str, terminalcapabilityProperties *props) { g_autoptr(GError) error = NULL; if (!mbimcli_parse_key_value_string (str, &error, (MbimParseKeyValueForeachFn)set_terminal_foreach_cb, props)) { g_printerr ("error: couldn't parse input string: %s\n", error->message); shutdown (FALSE); return FALSE; } if (props->terminal_capability && !check_terminal_add (props, &error)) { g_printerr ("error: failed to add last terminal item: %s\n", error->message); return FALSE; } return TRUE; } void mbimcli_ms_uicc_low_level_access_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; g_autoptr(GError) error = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to query UICC application list? */ if (query_uicc_application_list_flag) { g_debug ("Asynchronously querying UICC application list..."); request = mbim_message_ms_uicc_low_level_access_application_list_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)application_list_query_ready, NULL); return; } /* Request to query UICC file status? */ if (query_uicc_file_status_str) { g_auto(FileStatusQueryProperties) props = { .application_id_size = 0, .application_id = NULL, .file_path_size = 0, .file_path = NULL, }; g_debug ("Asynchronously querying UICC file status..."); if (!file_status_query_input_parse (query_uicc_file_status_str, &props, &error)) { g_printerr ("error: couldn't parse input arguments: %s\n", error->message); shutdown (FALSE); return; } request = mbim_message_ms_uicc_low_level_access_file_status_query_new (1, /* version fixed */ props.application_id_size, props.application_id, props.file_path_size, props.file_path, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)file_status_query_ready, NULL); return; } /* Request to UICC read binary? */ if (query_uicc_read_binary_str) { g_auto(ReadBinaryQueryProperties) props = { .application_id_size = 0, .application_id = NULL, .file_path_size = 0, .file_path = NULL, .read_offset = 0, .read_size = 0, .local_pin = NULL, .data_size = 0, .data = NULL, }; g_debug ("Asynchronously reading from UICC in binary..."); if (!read_binary_query_input_parse (query_uicc_read_binary_str, &props, &error)) { g_printerr ("error: couldn't parse input arguments: %s\n", error->message); shutdown (FALSE); return; } request = mbim_message_ms_uicc_low_level_access_read_binary_query_new (1, /* version fixed */ props.application_id_size, props.application_id, props.file_path_size, props.file_path, props.read_offset, props.read_size, props.local_pin, props.data_size, props.data, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)read_binary_query_ready, NULL); return; } /* Request to UICC read record? */ if (query_uicc_read_record_str) { g_auto(ReadRecordQueryProperties) props = { .application_id_size = 0, .application_id = NULL, .file_path_size = 0, .file_path = NULL, .record_number = 0, .local_pin = NULL, .data_size = 0, .data = NULL, }; g_debug ("Asynchronously reading from UICC record..."); if (!read_record_query_input_parse (query_uicc_read_record_str, &props, &error)) { g_printerr ("error: couldn't parse input arguments: %s\n", error->message); shutdown (FALSE); return; } request = mbim_message_ms_uicc_low_level_access_read_record_query_new (1, /* version fixed */ props.application_id_size, props.application_id, props.file_path_size, props.file_path, props.record_number, props.local_pin, props.data_size, props.data, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)read_record_query_ready, NULL); return; } /* Request to Set UICC open channel */ if (set_uicc_open_channel_str) { g_auto(OpenChannelProperties) props = { .application_id_size = 0, .application_id = NULL, .selectprg = 0, .channel_group = 0, }; if (!open_channel_input_parse (set_uicc_open_channel_str, &props, &error)) { g_printerr ("error: couldn't parse input arguments: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Asynchronously setting UICC open channel."); request = mbim_message_ms_uicc_low_level_access_open_channel_set_new (props.application_id_size, props.application_id, props.selectprg, props.channel_group, &error); if (!request) { g_printerr ("error: couldn't create open channel Request %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 30, ctx->cancellable, (GAsyncReadyCallback)open_channel_ready, NULL); return; } /* Request to Set UICC close channel */ if (set_uicc_close_channel_str) { CloseChannelProperties props = { .channel = 0, .channel_group = 0, }; if (!mbimcli_parse_key_value_string (set_uicc_close_channel_str, &error, close_channel_properties_handle, &props)) { g_printerr ("error: couldn't parse input arguments: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Asynchronously setting UICC close channel..."); request = mbim_message_ms_uicc_low_level_access_close_channel_set_new (props.channel, props.channel_group, &error); if (!request) { g_printerr ("error: couldn't create close channel request %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 30, ctx->cancellable, (GAsyncReadyCallback)close_channel_ready, NULL); return; } /* Request to UICC atr? */ if (query_uicc_atr_flag) { g_debug ("Asynchronously querying UICC atr Info..."); request = mbim_message_ms_uicc_low_level_access_atr_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_atr_ready, NULL); return; } /* Request to set UICC Apdu */ if (set_uicc_apdu_str) { g_auto(ApduProperties) props = { .secure_messaging = MBIM_UICC_SECURE_MESSAGING_NONE, .class_byte_type = MBIM_UICC_CLASS_BYTE_TYPE_INTER_INDUSTRY, .channel = 0, .command_size = 0, .command = NULL, }; if (!apdu_input_parse (set_uicc_apdu_str, &props, &error)) { g_printerr ("error: couldn't parse input arguments: %s\n", error->message); shutdown (FALSE); return; } g_debug ("Asynchronously sending UICC set apdu command."); request = mbim_message_ms_uicc_low_level_access_apdu_set_new (props.channel, props.secure_messaging, props.class_byte_type, props.command_size, props.command, &error); if (!request) { g_printerr ("error: couldn't create APDU request %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 30, ctx->cancellable, (GAsyncReadyCallback)set_apdu_ready, NULL); return; } /* Request to set UICC reset */ if (set_uicc_reset_str) { MbimUiccPassThroughAction pass_through_action; if(!mbimcli_read_uicc_pass_through_action_from_string (set_uicc_reset_str, &pass_through_action)) { shutdown (FALSE); return; } request = mbim_message_ms_uicc_low_level_access_reset_set_new (pass_through_action, &error); if (!request) { g_printerr ("error: couldn't create Reset request %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 30, ctx->cancellable, (GAsyncReadyCallback)uicc_reset_ready, NULL); return; } /* Request to query UICC reset */ if (query_uicc_reset_flag) { g_debug ("Asynchronously querying UICC reset..."); request = mbim_message_ms_uicc_low_level_access_reset_query_new (NULL); mbim_device_command (ctx->device, request, 30, ctx->cancellable, (GAsyncReadyCallback)uicc_reset_ready, NULL); return; } /* Request to set UICC terminal capability */ if (set_uicc_terminal_capability_str) { g_auto(terminalcapabilityProperties) props = {NULL, NULL}; props.array = g_ptr_array_new_with_free_func ((GDestroyNotify)mbim_terminal_capability_free); if (!terminal_capability_parse (set_uicc_terminal_capability_str, &props)) { shutdown (FALSE); return; } g_debug ("Asynchronously set UICC terminal capability."); request = mbim_message_ms_uicc_low_level_access_terminal_capability_set_new ((guint32)props.array->len, (const MbimTerminalCapabilityInfo *const *)props.array->pdata, &error); if (!request) { g_printerr ("error: couldn't create Terminal Capability request %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 30, ctx->cancellable, (GAsyncReadyCallback)set_terminal_capability_ready, NULL); return; } /* Request to query UICC terminal capability */ if (query_uicc_terminal_capability_flag) { g_debug ("Asynchronously querying UICC terminal capability..."); request = mbim_message_ms_uicc_low_level_access_terminal_capability_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_terminal_capability_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-ms-voice-extensions.c000066400000000000000000000116771453630424100237030ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2022 Intel Corporation */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbim-common.h" #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean query_nitz_flag; static GOptionEntry entries[] = { { "ms-query-nitz", 0, 0, G_OPTION_ARG_NONE, &query_nitz_flag, "Query network identity and time zone", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_ms_voice_extensions_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("ms-voice-extensions", "Microsoft Voice Extensions Service options:", "Show Microsoft Voice Extensions Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_ms_voice_extensions_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = query_nitz_flag; if (n_actions > 1) { g_printerr ("error: too many Microsoft Voice Extensions Service actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void query_nitz_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; guint32 day = 0; guint32 month = 0; guint32 year = 0; guint32 hour = 0; guint32 minutes = 0; guint32 second = 0; guint32 time_zone_offset_minutes = 0; guint32 daylight_saving_time_offset_minutes = 0; MbimDataClass data_class; g_autofree gchar *data_class_str = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_ms_voice_extensions_nitz_response_parse ( response, &year, &month, &day, &hour, &minutes, &second, &time_zone_offset_minutes, &daylight_saving_time_offset_minutes, &data_class, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } data_class_str = mbim_data_class_build_string_from_mask (data_class); g_print ("Successfully queried NITZ info from modem:\n" "\t Date: %02u/%02u/%u\n" "\t Time: %02u:%02u:%02u\n" "\t Time zone offset minutes: %u\n" "\tDaylight saving time offset minutes: %u\n" "\t Data class: %s\n", day, month, year, hour, minutes, second, time_zone_offset_minutes, daylight_saving_time_offset_minutes, VALIDATE_UNKNOWN (data_class_str)); shutdown (TRUE); } void mbimcli_ms_voice_extensions_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to reboot modem? */ if (query_nitz_flag) { g_debug ("Asynchronously querying nitz info..."); request = mbim_message_ms_voice_extensions_nitz_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_nitz_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-phonebook.c000066400000000000000000000332161453630424100217410ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2013 - 2014 Nagaraju Kadiri */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean phonebook_configuration_flag; static gint phonebook_read_index; static gboolean phonebook_read_all_flag; static gchar *phonebook_write_str; static gint phonebook_delete_index; static gboolean phonebook_delete_all_flag; static GOptionEntry entries[] = { { "phonebook-query-configuration", 0, 0, G_OPTION_ARG_NONE, &phonebook_configuration_flag, "Query the phonebook configuration", NULL }, { "phonebook-read", 0, 0, G_OPTION_ARG_INT, &phonebook_read_index, "Read phonebook entry with given index", "[(Phonebook index)]" }, { "phonebook-read-all", 0, 0, G_OPTION_ARG_NONE, &phonebook_read_all_flag, "Read all phonebook entries", NULL }, { "phonebook-write", 0, 0, G_OPTION_ARG_STRING, &phonebook_write_str, "Add new phonebook entry or update an existing one", "[(Name),(Number)[,(Index)]]" }, { "phonebook-delete", 0, 0, G_OPTION_ARG_INT, &phonebook_delete_index, "Delete phonebook entry with given index", "[(Phonebook index)]" }, { "phonebook-delete-all", 0, 0, G_OPTION_ARG_NONE, &phonebook_delete_all_flag, "Delete all phonebook entries", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_phonebook_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("phonebook", "Phonebook options:", "Show Phonebook Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_phonebook_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (phonebook_configuration_flag + !!phonebook_read_index + phonebook_read_all_flag + !!phonebook_write_str + !!phonebook_delete_index + phonebook_delete_all_flag); if (n_actions > 1) { g_printerr ("error: too many phonebook actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static gboolean phonebook_write_input_parse (const gchar *str, gchar **name, gchar **number, guint *idx) { g_auto(GStrv) split = NULL; g_assert (name != NULL); g_assert (number != NULL); g_assert (idx != NULL); /* Format of the string is: * "[(Name),(Number)(,[Index])]" * i.e. index is optional */ split = g_strsplit (str, ",", -1); if (g_strv_length (split) > 3) { g_printerr ("error: couldn't parse input string, too many arguments\n"); return FALSE; } if (g_strv_length (split) < 2) { g_printerr ("error: couldn't parse input string, missing arguments\n"); return FALSE; } /* Check whether we have the optional Index item */ if (split[2]) { if (!mbimcli_read_uint_from_string (split[2], idx)) { g_printerr ("error: couldn't parse input string, invalid index '%s'\n", split[2]); return FALSE; } } else { /* Default to index 0, which is an invalid one */ *idx = 0; } /* First two items will always be available */ *name = g_strdup (split[0]); *number = g_strdup (split[1]); return TRUE; } static void set_phonebook_write_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_phonebook_write_response_parse (response, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("Phonebook entry successfully written\n"); shutdown (TRUE); } static void set_phonebook_delete_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_phonebook_delete_response_parse (response, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("Phonebook entry/entries successfully deleted"); shutdown (TRUE); } static void query_phonebook_read_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimPhonebookEntryArray) phonebook_entries = NULL; guint32 entry_count; guint i; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_phonebook_read_response_parse (response, &entry_count, &phonebook_entries, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } g_print ("Successfully read phonebook entries (%d)\n", entry_count); for (i = 0; i < entry_count; i++) { g_print ("\tEntry index : %d \n" "\t Number: %s \n" "\t Name: %s \n", phonebook_entries[i]->entry_index, phonebook_entries[i]->number, phonebook_entries[i]->name); } shutdown (TRUE); } static void query_phonebook_configuration_ready (MbimDevice *device, GAsyncResult *res) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimPhonebookState state; const gchar *state_str; guint32 number_of_entries; guint32 used_entries; guint32 max_number_length; guint32 max_name; response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_phonebook_configuration_response_parse (response, &state, &number_of_entries, &used_entries, &max_number_length, &max_name, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } state_str = mbim_phonebook_state_get_string (state); g_print ("\n Phonebook configuration retrieved... \n" "\t Phonebook state: %s \n" "\t Number of entries: %d \n" "\t used entries: %d \n" "\t max number length: %d \n" "\t max name : %d \n", VALIDATE_UNKNOWN (state_str), number_of_entries, used_entries, max_number_length, max_name); shutdown (TRUE); } void mbimcli_phonebook_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to get configuration? */ if (phonebook_configuration_flag) { g_debug ("Asynchronously querying phonebook configurations..."); request = mbim_message_phonebook_configuration_query_new (NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_phonebook_configuration_ready, NULL); return; } /* Phonebook read */ if (phonebook_read_index) { g_debug ("Asynchronously querying phonebook read..."); request = mbim_message_phonebook_read_query_new (MBIM_PHONEBOOK_FLAG_INDEX, phonebook_read_index, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_phonebook_read_ready, NULL); return; } /* Phonebook read all */ if (phonebook_read_all_flag) { g_debug ("Asynchronously querying phonebook read all..."); request = mbim_message_phonebook_read_query_new (MBIM_PHONEBOOK_FLAG_ALL, 0, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)query_phonebook_read_ready, NULL); return; } /* Phonebook delete */ if (phonebook_delete_index) { g_debug ("Asynchronously phonebook delete..."); request = mbim_message_phonebook_delete_set_new (MBIM_PHONEBOOK_FLAG_INDEX, phonebook_delete_index, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_phonebook_delete_ready, NULL); return; } /* Phonebook delete all */ if (phonebook_delete_all_flag) { g_debug ("Asynchronously phonebook delete all..."); request = mbim_message_phonebook_delete_set_new (MBIM_PHONEBOOK_FLAG_ALL, 0, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_phonebook_delete_ready, NULL); return; } /* Phonebook write */ if (phonebook_write_str) { g_autofree gchar *name = NULL; g_autofree gchar *number = NULL; guint idx; g_debug ("Asynchronously writing phonebook..."); if (!phonebook_write_input_parse (phonebook_write_str, &name, &number, &idx)) { shutdown (FALSE); return; } request = mbim_message_phonebook_write_set_new ((idx ? MBIM_PHONEBOOK_WRITE_FLAG_SAVE_INDEX : MBIM_PHONEBOOK_WRITE_FLAG_SAVE_UNUSED), idx, number, name, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)set_phonebook_write_ready, NULL); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-quectel.c000066400000000000000000000126071453630424100214200ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2021 Aleksander Morgado */ #include "config.h" #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gboolean query_radio_state_flag; static gchar *set_radio_state_str; static GOptionEntry entries[] = { { "quectel-query-radio-state", 0, 0, G_OPTION_ARG_NONE, &query_radio_state_flag, "Query radio state", NULL }, { "quectel-set-radio-state", 0, 0, G_OPTION_ARG_STRING, &set_radio_state_str, "Set radio state", "[(on)]" }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; GOptionGroup * mbimcli_quectel_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("quectel", "Quectel options:", "Show Quectel Service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_quectel_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (query_radio_state_flag + !!set_radio_state_str); if (n_actions > 1) { g_printerr ("error: too many Quectel actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void radio_state_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimQuectelRadioSwitchState radio_state; const gchar *radio_state_str; gboolean action_flag; action_flag = GPOINTER_TO_UINT (user_data); response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (action_flag) { g_print ("[%s] Successfully requested to enable radio\n", mbim_device_get_path_display (device)); shutdown (TRUE); return; } /* The body is only included in the query response, not in the set response */ if (!mbim_message_quectel_radio_state_response_parse (response, &radio_state, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } radio_state_str = mbim_quectel_radio_switch_state_get_string (radio_state); g_print ("[%s] Radio state retrieved: '%s'\n", mbim_device_get_path_display (device), VALIDATE_UNKNOWN (radio_state_str)); shutdown (TRUE); } void mbimcli_quectel_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; /* Request to get radio state? */ if (query_radio_state_flag) { g_debug ("Asynchronously querying radio state..."); request = (mbim_message_quectel_radio_state_query_new (NULL)); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)radio_state_ready, GUINT_TO_POINTER (FALSE)); return; } /* Request to set radio state? */ if (set_radio_state_str) { MbimQuectelRadioSwitchState radio_state; if (g_ascii_strcasecmp (set_radio_state_str, "on") == 0) radio_state = MBIM_QUECTEL_RADIO_SWITCH_STATE_ON; else { g_printerr ("error: invalid radio state (only 'on' allowed): '%s'\n", set_radio_state_str); shutdown (FALSE); return; } g_debug ("Asynchronously setting radio state to on..."); request = mbim_message_quectel_radio_state_set_new (radio_state, NULL); mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)radio_state_ready, GUINT_TO_POINTER (TRUE)); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli-sms.c000066400000000000000000000176401453630424100205620ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2022 Ulrich Mohr */ #include "config.h" #include #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" /* Context */ typedef struct { MbimDevice *device; GCancellable *cancellable; } Context; static Context *ctx; /* Options */ static gchar *delete_str = NULL; static gchar *read_str = NULL; static GOptionEntry entries[] = { { "sms-delete", 0, 0, G_OPTION_ARG_STRING, &delete_str, "Delete all SMS matching a given filter", "[(all|new|old|sent|draft|index=N)]" }, { "sms-read", 0, 0, G_OPTION_ARG_STRING, &read_str, "Read all SMS matching a given filter", "[(all|new|old|sent|draft|index=N)]" }, { NULL } }; GOptionGroup * mbimcli_sms_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("sms", "Simple message service options:", "Show SMS service options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mbimcli_sms_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (!!delete_str + !!read_str); if (n_actions > 1) { g_printerr ("error: too many SIM actions requested\n"); exit (EXIT_FAILURE); } checked = TRUE; return !!n_actions; } static void context_free (Context *context) { if (!context) return; if (context->cancellable) g_object_unref (context->cancellable); if (context->device) g_object_unref (context->device); g_slice_free (Context, context); } static void shutdown (gboolean operation_status) { /* Cleanup context and finish async operation */ context_free (ctx); mbimcli_async_operation_done (operation_status); } static void delete_sms_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; MbimSmsFlag filter = GPOINTER_TO_INT (user_data); response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_sms_delete_response_parse (response, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } if (filter != MBIM_SMS_FLAG_INDEX) g_print ("Successfully deleted %s sms\n", mbim_sms_flag_get_string (filter)); else g_print ("Successfully deleted sms\n"); shutdown (TRUE); return; } static void read_sms_ready (MbimDevice *device, GAsyncResult *res, gpointer user_data) { g_autoptr(MbimMessage) response = NULL; g_autoptr(GError) error = NULL; g_autoptr(MbimSmsPduReadRecordArray) pdu_messages = NULL; guint32 num_messages = 0; MbimSmsFlag filter = GPOINTER_TO_INT (user_data); response = mbim_device_command_finish (device, res, &error); if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { g_printerr ("error: operation failed: %s\n", error->message); shutdown (FALSE); return; } if (!mbim_message_sms_read_response_parse (response, NULL, &num_messages, &pdu_messages, NULL, &error)) { g_printerr ("error: couldn't parse response message: %s\n", error->message); shutdown (FALSE); return; } if (num_messages && pdu_messages) { guint32 i = 0; g_print ("Successfully read sms\n"); if (filter != MBIM_SMS_FLAG_INDEX) g_print ("Got %d messages\n", num_messages); while (pdu_messages[i]) { g_print (" PDU on index %u, status %s\n", pdu_messages[i]->message_index, mbim_sms_status_get_string (pdu_messages[i]->message_status)); i++; } } else { if (filter == MBIM_SMS_FLAG_ALL) g_print ("No messages found\n"); else if (filter != MBIM_SMS_FLAG_INDEX) g_print ("No %s messages found\n", mbim_sms_flag_get_string (filter) ); else g_print ("Message not found\n"); } shutdown (TRUE); return; } static gboolean op_parse (const gchar *str, MbimSmsFlag *filter, guint32 *index) { gboolean status = FALSE; gchar **filter_parts = NULL; g_assert (filter != NULL); /* according to the mbim specification, index must be > 0 and 0 is used when not needed */ *index = 0; filter_parts = g_strsplit (str, "=", -1); if (filter_parts[0]) status = mbimcli_read_sms_flag_from_string (filter_parts[0], filter); if (status) { if (*filter == MBIM_SMS_FLAG_INDEX) { status = filter_parts[1] && mbimcli_read_uint_from_string (filter_parts[1], index); if (!status) { if (!filter_parts[1]) g_printerr ("error: required index not given\n"); else g_printerr ("error: couln't parse sms index, should be a number\n"); } if (*index == 0) g_printerr ("error: index must be > 0\n"); } else if (filter_parts[1]) { g_printerr ("error: unexpected assignment for the given operation\n"); status = FALSE; } } else status = FALSE; g_strfreev (filter_parts); return status; } void mbimcli_sms_run (MbimDevice *device, GCancellable *cancellable) { g_autoptr(MbimMessage) request = NULL; g_autoptr(GError) error = NULL; /* Initialize context */ ctx = g_slice_new (Context); ctx->device = g_object_ref (device); ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; if (delete_str) { MbimSmsFlag filter; guint32 index; if (!op_parse (delete_str, &filter, &index)) { shutdown (FALSE); return; } request = mbim_message_sms_delete_set_new (filter, index, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)delete_sms_ready, GINT_TO_POINTER (filter)); return; } if (read_str) { MbimSmsFlag filter; guint32 index; if (!op_parse (read_str, &filter, &index)) { shutdown (FALSE); return; } request = mbim_message_sms_read_query_new (MBIM_SMS_FORMAT_PDU, filter, index, &error); if (!request) { g_printerr ("error: couldn't create request: %s\n", error->message); shutdown (FALSE); return; } mbim_device_command (ctx->device, request, 10, ctx->cancellable, (GAsyncReadyCallback)read_sms_ready, GINT_TO_POINTER (filter)); return; } g_warn_if_reached (); } libmbim-1.31.2-dev/src/mbimcli/mbimcli.c000066400000000000000000000464721453630424100177670ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2013 - 2023 Aleksander Morgado * Copyright (C) 2022 Intel Corporation */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "mbimcli.h" #include "mbimcli-helpers.h" #define PROGRAM_NAME "mbimcli" #define PROGRAM_VERSION PACKAGE_VERSION /* Globals */ static GMainLoop *loop; static GCancellable *cancellable; static MbimDevice *device; static MbimService service; static gboolean operation_status; /* Main options */ static gchar *device_str; static gboolean device_open_proxy_flag; static gboolean device_open_ms_mbimex_v2_flag; static gboolean device_open_ms_mbimex_v3_flag; static gchar *no_open_str; static gboolean no_close_flag; static gboolean noop_flag; static gboolean verbose_flag; static gboolean verbose_full_flag; static gboolean silent_flag; static gchar *printable_str; static gboolean version_flag; static GOptionEntry main_entries[] = { { "device", 'd', 0, G_OPTION_ARG_STRING, &device_str, "Specify device path", "[PATH]" }, { "device-open-proxy", 'p', 0, G_OPTION_ARG_NONE, &device_open_proxy_flag, "Request to use the 'mbim-proxy' proxy", NULL }, { "device-open-ms-mbimex-v2", 0, 0, G_OPTION_ARG_NONE, &device_open_ms_mbimex_v2_flag, "Request to enable Microsoft MBIMEx v2.0 support", NULL }, { "device-open-ms-mbimex-v3", 0, 0, G_OPTION_ARG_NONE, &device_open_ms_mbimex_v3_flag, "Request to enable Microsoft MBIMEx v3.0 support", NULL }, { "no-open", 0, 0, G_OPTION_ARG_STRING, &no_open_str, "Do not explicitly open the MBIM device before running the command", "[Transaction ID]" }, { "no-close", 0, 0, G_OPTION_ARG_NONE, &no_close_flag, "Do not close the MBIM device after running the command", NULL }, { "noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag, "Don't run any command", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose_flag, "Run action with verbose logs, including the debug ones", NULL }, { "verbose-full", 0, 0, G_OPTION_ARG_NONE, &verbose_full_flag, "Run action with verbose logs, including the debug ones and personal info", NULL }, { "silent", 0, 0, G_OPTION_ARG_NONE, &silent_flag, "Run action with no logs; not even the error/warning ones", NULL }, { "printable", 0, 0, G_OPTION_ARG_STRING, &printable_str, "Get the printable info of the given hex encoded MBIM message", "[(Data)]" }, { "version", 'V', 0, G_OPTION_ARG_NONE, &version_flag, "Print version", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL } }; static gboolean signals_handler (gpointer psignum) { if (cancellable) { /* Ignore consecutive requests of cancellation */ if (!g_cancellable_is_cancelled (cancellable)) { g_printerr ("cancelling the operation...\n"); g_cancellable_cancel (cancellable); /* Re-set the signal handler to allow main loop cancellation on * second signal */ g_unix_signal_add (GPOINTER_TO_INT (psignum), (GSourceFunc) signals_handler, psignum); return FALSE; } } if (loop && g_main_loop_is_running (loop)) { g_printerr ("cancelling the main loop...\n"); g_idle_add ((GSourceFunc) g_main_loop_quit, loop); } return FALSE; } static void log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { const gchar *log_level_str; time_t now; gchar time_str[64]; struct tm *local_time; gboolean err; /* Nothing to do if we're silent */ if (silent_flag) return; now = time ((time_t *) NULL); local_time = localtime (&now); strftime (time_str, 64, "%d %b %Y, %H:%M:%S", local_time); err = FALSE; switch (log_level) { case G_LOG_LEVEL_WARNING: log_level_str = "-Warning **"; err = TRUE; break; case G_LOG_LEVEL_CRITICAL: case G_LOG_LEVEL_ERROR: log_level_str = "-Error **"; err = TRUE; break; case G_LOG_LEVEL_DEBUG: log_level_str = "[Debug]"; break; case G_LOG_LEVEL_MESSAGE: case G_LOG_LEVEL_INFO: log_level_str = ""; break; case G_LOG_FLAG_FATAL: case G_LOG_LEVEL_MASK: case G_LOG_FLAG_RECURSION: default: g_assert_not_reached (); } if (!verbose_flag && !verbose_full_flag && !err) return; g_fprintf (err ? stderr : stdout, "[%s] %s %s\n", time_str, log_level_str, message); } G_GNUC_NORETURN static void print_version_and_exit (void) { g_print (PROGRAM_NAME " " PROGRAM_VERSION "\n" "Copyright (C) 2013-2023 Aleksander Morgado\n" "License GPLv2+: GNU GPL version 2 or later \n" "This is free software: you are free to change and redistribute it.\n" "There is NO WARRANTY, to the extent permitted by law.\n" "\n"); exit (EXIT_SUCCESS); } /*****************************************************************************/ G_GNUC_NORETURN static void print_printable_str_and_exit (const gchar *hex) { g_autofree gchar *printable = NULL; g_autoptr(MbimMessage) message = NULL; g_autoptr(GError) error = NULL; gsize data_size = 0; g_autofree guint8 *data = NULL; data = mbimcli_read_buffer_from_string (hex, -1, &data_size, &error); if (!data) { g_printerr ("Failed to read data: %s\n", error->message); exit (EXIT_FAILURE); } message = mbim_message_new (data, data_size); if (!mbim_message_validate (message, &error)) { g_printerr ("error: message validation failed: %s\n", error->message); exit (EXIT_FAILURE); } printable = mbim_message_get_printable_full (message, 1, 0, "---- ", FALSE, &error); if (!printable) { g_printerr ("error: printable info retrieval failed: %s\n", error->message); exit (EXIT_FAILURE); } g_print ("%s\n", printable); exit (EXIT_SUCCESS); } /*****************************************************************************/ /* Running asynchronously */ static void device_close_ready (MbimDevice *dev, GAsyncResult *res) { GError *error = NULL; if (!mbim_device_close_finish (dev, res, &error)) { g_printerr ("error: couldn't close device: %s\n", error->message); g_error_free (error); } else g_debug ("Device closed"); /* If we left the device open, dump next transaction id */ if (no_close_flag) { guint transaction_id; g_object_get (dev, MBIM_DEVICE_TRANSACTION_ID, &transaction_id, NULL); g_print ("[%s] Session not closed:\n" "\t TRID: '%u'\n", mbim_device_get_path_display (dev), transaction_id); } g_main_loop_quit (loop); } void mbimcli_async_operation_done (gboolean reported_operation_status) { /* Keep the result of the operation */ operation_status = reported_operation_status; /* Cleanup cancellation */ g_clear_object (&cancellable); /* Set the in-session setup */ g_object_set (device, MBIM_DEVICE_IN_SESSION, no_close_flag, NULL); /* Close the device */ mbim_device_close (device, 15, cancellable, (GAsyncReadyCallback) device_close_ready, NULL); } static void device_open_ready (MbimDevice *dev, GAsyncResult *res) { GError *error = NULL; if (!mbim_device_open_finish (dev, res, &error)) { g_printerr ("error: couldn't open the MbimDevice: %s\n", error->message); exit (EXIT_FAILURE); } g_debug ("MBIM Device at '%s' ready", mbim_device_get_path_display (dev)); /* If no operation requested, finish */ if (noop_flag) { mbimcli_async_operation_done (TRUE); return; } /* Link management action? */ if (mbimcli_link_management_options_enabled ()) { mbimcli_link_management_run (dev, cancellable); return; } /* Run the service-specific action */ switch (service) { case MBIM_SERVICE_BASIC_CONNECT: mbimcli_basic_connect_run (dev, cancellable); return; case MBIM_SERVICE_PHONEBOOK: mbimcli_phonebook_run (dev, cancellable); return; case MBIM_SERVICE_DSS: mbimcli_dss_run (dev, cancellable); return; case MBIM_SERVICE_MS_FIRMWARE_ID: mbimcli_ms_firmware_id_run (dev, cancellable); return; case MBIM_SERVICE_MS_HOST_SHUTDOWN: mbimcli_ms_host_shutdown_run (dev, cancellable); return; case MBIM_SERVICE_MS_SAR: mbimcli_ms_sar_run (dev, cancellable); return; case MBIM_SERVICE_ATDS: mbimcli_atds_run (dev, cancellable); return; case MBIM_SERVICE_INTEL_FIRMWARE_UPDATE: mbimcli_intel_firmware_update_run (dev, cancellable); return; case MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS: mbimcli_ms_basic_connect_extensions_run (dev, cancellable); return; case MBIM_SERVICE_QUECTEL: mbimcli_quectel_run (dev, cancellable); return; case MBIM_SERVICE_INTEL_THERMAL_RF: mbimcli_intel_thermal_rf_run (dev, cancellable); return; case MBIM_SERVICE_MS_VOICE_EXTENSIONS: mbimcli_ms_voice_extensions_run (dev, cancellable); return; case MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS: mbimcli_ms_uicc_low_level_access_run (dev, cancellable); return; case MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: mbimcli_intel_mutual_authentication_run (dev, cancellable); return; case MBIM_SERVICE_GOOGLE: mbimcli_google_run (dev, cancellable); return; case MBIM_SERVICE_SMS: mbimcli_sms_run (dev, cancellable); return; case MBIM_SERVICE_USSD: case MBIM_SERVICE_STK: case MBIM_SERVICE_AUTH: case MBIM_SERVICE_PROXY_CONTROL: case MBIM_SERVICE_QMI: case MBIM_SERVICE_QDU: case MBIM_SERVICE_INTEL_TOOLS: mbimcli_intel_tools_run (dev, cancellable); return; case MBIM_SERVICE_FIBOCOM: mbimcli_fibocom_run (dev, cancellable); return; /* unsupported actions in the CLI */ case MBIM_SERVICE_INVALID: default: g_assert_not_reached (); } } static void device_new_ready (GObject *unused, GAsyncResult *res) { GError *error = NULL; MbimDeviceOpenFlags open_flags = MBIM_DEVICE_OPEN_FLAGS_NONE; device = mbim_device_new_finish (res, &error); if (!device) { g_printerr ("error: couldn't create MbimDevice: %s\n", error->message); exit (EXIT_FAILURE); } /* Set the in-session setup */ if (no_open_str) { guint transaction_id; if (!mbimcli_read_uint_from_string (no_open_str, &transaction_id)) { g_printerr ("error: invalid transaction ID specified: %s\n", no_open_str); exit (EXIT_FAILURE); } g_object_set (device, MBIM_DEVICE_IN_SESSION, TRUE, MBIM_DEVICE_TRANSACTION_ID, transaction_id, NULL); } /* Setup device open flags */ if (device_open_proxy_flag) open_flags |= MBIM_DEVICE_OPEN_FLAGS_PROXY; if (device_open_ms_mbimex_v2_flag) open_flags |= MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V2; if (device_open_ms_mbimex_v3_flag) open_flags |= MBIM_DEVICE_OPEN_FLAGS_MS_MBIMEX_V3; /* Open the device */ mbim_device_open_full (device, open_flags, 30, cancellable, (GAsyncReadyCallback) device_open_ready, NULL); } /*****************************************************************************/ static void parse_actions (void) { guint actions_enabled = 0; if (mbimcli_link_management_options_enabled ()) actions_enabled++; if (mbimcli_basic_connect_options_enabled ()) { service = MBIM_SERVICE_BASIC_CONNECT; actions_enabled++; } if (mbimcli_phonebook_options_enabled ()) { service = MBIM_SERVICE_PHONEBOOK; actions_enabled++; } if (mbimcli_dss_options_enabled ()) { service = MBIM_SERVICE_DSS; actions_enabled++; } if (mbimcli_ms_firmware_id_options_enabled ()) { service = MBIM_SERVICE_MS_FIRMWARE_ID; actions_enabled++; } if (mbimcli_ms_host_shutdown_options_enabled ()) { service = MBIM_SERVICE_MS_HOST_SHUTDOWN; actions_enabled++; } if (mbimcli_ms_sar_options_enabled ()) { service = MBIM_SERVICE_MS_SAR; actions_enabled++; } if (mbimcli_atds_options_enabled ()) { service = MBIM_SERVICE_ATDS; actions_enabled++; } if (mbimcli_intel_firmware_update_options_enabled ()) { service = MBIM_SERVICE_INTEL_FIRMWARE_UPDATE; actions_enabled++; } if (mbimcli_ms_basic_connect_extensions_options_enabled ()) { service = MBIM_SERVICE_MS_BASIC_CONNECT_EXTENSIONS; actions_enabled++; } if (mbimcli_quectel_options_enabled ()) { service = MBIM_SERVICE_QUECTEL; actions_enabled++; } if (mbimcli_intel_thermal_rf_options_enabled ()) { service = MBIM_SERVICE_INTEL_THERMAL_RF; actions_enabled++; } if (mbimcli_ms_voice_extensions_options_enabled ()) { service = MBIM_SERVICE_MS_VOICE_EXTENSIONS; actions_enabled++; } if (mbimcli_ms_uicc_low_level_access_options_enabled ()) { service = MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS; actions_enabled++; } if (mbimcli_intel_mutual_authentication_options_enabled ()) { service = MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION; actions_enabled++; } if (mbimcli_intel_tools_options_enabled ()) { service = MBIM_SERVICE_INTEL_TOOLS; actions_enabled++; } if (mbimcli_google_options_enabled ()) { service = MBIM_SERVICE_GOOGLE; actions_enabled++; } if (mbimcli_fibocom_options_enabled ()) { service = MBIM_SERVICE_FIBOCOM; actions_enabled++; } if (mbimcli_sms_options_enabled()) { service = MBIM_SERVICE_SMS; actions_enabled++; } /* Noop */ if (noop_flag) actions_enabled++; /* Cannot mix actions from different services */ if (actions_enabled > 1) { g_printerr ("error: cannot execute multiple actions of different services\n"); exit (EXIT_FAILURE); } /* No options? */ if (actions_enabled == 0) { g_printerr ("error: no actions specified\n"); exit (EXIT_FAILURE); } if (device_open_ms_mbimex_v2_flag && device_open_ms_mbimex_v3_flag) { g_printerr ("error: cannot request both MBIMEx v2.0 and 3.0 at the same time\n"); exit (EXIT_FAILURE); } /* Go on! */ } int main (int argc, char **argv) { g_autoptr(GError) error = NULL; g_autoptr(GFile) file = NULL; g_autoptr(GOptionContext) context = NULL; setlocale (LC_ALL, ""); /* Setup option context, process it and destroy it */ context = g_option_context_new ("- Control MBIM devices"); g_option_context_add_group (context, mbimcli_basic_connect_get_option_group ()); g_option_context_add_group (context, mbimcli_phonebook_get_option_group ()); g_option_context_add_group (context, mbimcli_dss_get_option_group ()); g_option_context_add_group (context, mbimcli_ms_firmware_id_get_option_group ()); g_option_context_add_group (context, mbimcli_ms_host_shutdown_get_option_group ()); g_option_context_add_group (context, mbimcli_ms_sar_get_option_group ()); g_option_context_add_group (context, mbimcli_atds_get_option_group ()); g_option_context_add_group (context, mbimcli_intel_firmware_update_get_option_group ()); g_option_context_add_group (context, mbimcli_ms_basic_connect_extensions_get_option_group ()); g_option_context_add_group (context, mbimcli_quectel_get_option_group ()); g_option_context_add_group (context, mbimcli_link_management_get_option_group ()); g_option_context_add_group (context, mbimcli_intel_thermal_rf_get_option_group ()); g_option_context_add_group (context, mbimcli_ms_voice_extensions_get_option_group ()); g_option_context_add_group (context, mbimcli_ms_uicc_low_level_access_get_option_group ()); g_option_context_add_group (context, mbimcli_intel_mutual_authentication_get_option_group ()); g_option_context_add_group (context, mbimcli_intel_tools_get_option_group ()); g_option_context_add_group (context, mbimcli_google_get_option_group()); g_option_context_add_group (context, mbimcli_fibocom_get_option_group()); g_option_context_add_group (context, mbimcli_sms_get_option_group ()); g_option_context_add_main_entries (context, main_entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("error: %s\n", error->message); exit (EXIT_FAILURE); } if (version_flag) print_version_and_exit (); g_log_set_handler (NULL, G_LOG_LEVEL_MASK, log_handler, NULL); g_log_set_handler ("Mbim", G_LOG_LEVEL_MASK, log_handler, NULL); if (verbose_flag && verbose_full_flag) { g_printerr ("error: cannot specify --verbose and --verbose-full at the same time\n"); exit (EXIT_FAILURE); } else if (verbose_flag) { mbim_utils_set_traces_enabled (TRUE); mbim_utils_set_show_personal_info (FALSE); } else if (verbose_full_flag) { mbim_utils_set_traces_enabled (TRUE); mbim_utils_set_show_personal_info (TRUE); } if (printable_str) print_printable_str_and_exit (printable_str); /* No device path given? */ if (!device_str) { g_printerr ("error: no device path specified\n"); exit (EXIT_FAILURE); } /* Build new GFile from the commandline arg */ file = g_file_new_for_commandline_arg (device_str); parse_actions (); /* Create requirements for async options */ cancellable = g_cancellable_new (); loop = g_main_loop_new (NULL, FALSE); /* Setup signals */ g_unix_signal_add (SIGINT, (GSourceFunc)signals_handler, GUINT_TO_POINTER (SIGINT)); g_unix_signal_add (SIGHUP, (GSourceFunc)signals_handler, GUINT_TO_POINTER (SIGHUP)); g_unix_signal_add (SIGTERM, (GSourceFunc)signals_handler, GUINT_TO_POINTER (SIGTERM)); /* Launch MbimDevice creation */ mbim_device_new (file, cancellable, (GAsyncReadyCallback)device_new_ready, NULL); g_main_loop_run (loop); if (cancellable) g_object_unref (cancellable); if (device) g_object_unref (device); g_main_loop_unref (loop); return (operation_status ? EXIT_SUCCESS : EXIT_FAILURE); } libmbim-1.31.2-dev/src/mbimcli/mbimcli.h000066400000000000000000000145601453630424100177650ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * mbimcli -- Command line interface to control MBIM devices * * Copyright (C) 2013 - 2014 Aleksander Morgado * Copyright (C) 2022 Intel Corporation */ #include #ifndef __MBIMCLI_H__ #define __MBIMCLI_H__ #define VALIDATE_UNKNOWN(str) ((str) ? (str) : "unknown") /* Common */ void mbimcli_async_operation_done (gboolean operation_status); /* Basic Connect group */ GOptionGroup *mbimcli_basic_connect_get_option_group (void); GOptionGroup *mbimcli_phonebook_get_option_group (void); GOptionGroup *mbimcli_dss_get_option_group (void); GOptionGroup *mbimcli_ms_firmware_id_get_option_group (void); GOptionGroup *mbimcli_ms_host_shutdown_get_option_group (void); GOptionGroup *mbimcli_ms_sar_get_option_group (void); GOptionGroup *mbimcli_atds_get_option_group (void); GOptionGroup *mbimcli_intel_firmware_update_get_option_group (void); GOptionGroup *mbimcli_ms_basic_connect_extensions_get_option_group (void); GOptionGroup *mbimcli_quectel_get_option_group (void); GOptionGroup *mbimcli_intel_thermal_rf_get_option_group (void); GOptionGroup *mbimcli_ms_voice_extensions_get_option_group (void); GOptionGroup *mbimcli_ms_uicc_low_level_access_get_option_group (void); GOptionGroup *mbimcli_intel_mutual_authentication_get_option_group (void); GOptionGroup *mbimcli_intel_tools_get_option_group (void); GOptionGroup *mbimcli_google_get_option_group (void); GOptionGroup *mbimcli_fibocom_get_option_group (void); GOptionGroup *mbimcli_sms_get_option_group (void); gboolean mbimcli_basic_connect_options_enabled (void); gboolean mbimcli_phonebook_options_enabled (void); gboolean mbimcli_dss_options_enabled (void); gboolean mbimcli_ms_firmware_id_options_enabled (void); gboolean mbimcli_ms_host_shutdown_options_enabled (void); gboolean mbimcli_ms_sar_options_enabled (void); gboolean mbimcli_atds_options_enabled (void); gboolean mbimcli_intel_firmware_update_options_enabled (void); gboolean mbimcli_ms_basic_connect_extensions_options_enabled (void); gboolean mbimcli_quectel_options_enabled (void); gboolean mbimcli_intel_thermal_rf_options_enabled (void); gboolean mbimcli_ms_voice_extensions_options_enabled (void); gboolean mbimcli_ms_uicc_low_level_access_options_enabled (void); gboolean mbimcli_intel_mutual_authentication_options_enabled (void); gboolean mbimcli_intel_tools_options_enabled (void); gboolean mbimcli_google_options_enabled (void); gboolean mbimcli_fibocom_options_enabled (void); gboolean mbimcli_sms_options_enabled (void); void mbimcli_basic_connect_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_phonebook_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_dss_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_ms_firmware_id_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_ms_host_shutdown_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_ms_sar_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_atds_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_intel_firmware_update_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_ms_basic_connect_extensions_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_quectel_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_intel_thermal_rf_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_ms_voice_extensions_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_ms_uicc_low_level_access_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_intel_mutual_authentication_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_intel_tools_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_google_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_fibocom_run (MbimDevice *device, GCancellable *cancellable); void mbimcli_sms_run (MbimDevice *device, GCancellable *cancellable); /* link management */ GOptionGroup *mbimcli_link_management_get_option_group (void); gboolean mbimcli_link_management_options_enabled (void); void mbimcli_link_management_run (MbimDevice *device, GCancellable *cancellable); #endif /* __MBIMCLI_H__ */ libmbim-1.31.2-dev/src/mbimcli/meson.build000066400000000000000000000020471453630424100203370ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez mbimcli_sources = files( 'mbimcli.c', 'mbimcli-atds.c', 'mbimcli-basic-connect.c', 'mbimcli-dss.c', 'mbimcli-fibocom.c', 'mbimcli-google.c', 'mbimcli-intel-firmware-update.c', 'mbimcli-intel-mutual-authentication.c', 'mbimcli-intel-thermal-rf.c', 'mbimcli-intel-tools.c', 'mbimcli-ms-basic-connect-extensions.c', 'mbimcli-ms-firmware-id.c', 'mbimcli-ms-host-shutdown.c', 'mbimcli-ms-sar.c', 'mbimcli-ms-uicc-low-level-access.c', 'mbimcli-ms-voice-extensions.c', 'mbimcli-phonebook.c', 'mbimcli-quectel.c', 'mbimcli-sms.c', ) sources = mbimcli_sources + files( 'mbimcli-helpers.c', 'mbimcli-link-management.c', ) deps = [ libmbim_common_dep, libmbim_glib_dep, ] mbimcli = executable( 'mbimcli', sources: sources, include_directories: top_inc, dependencies: deps, install: true, ) if enable_bash_completion install_data( 'mbimcli', install_dir: bash_completion_completionsdir, ) endif libmbim-1.31.2-dev/src/meson.build000066400000000000000000000002731453630424100167220ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez subdir('common') subdir('libmbim-glib') subdir('mbimcli') subdir('mbim-proxy') libmbim-1.31.2-dev/utils/000077500000000000000000000000001453630424100151275ustar00rootroot00000000000000libmbim-1.31.2-dev/utils/mbim-network.in000077500000000000000000000261211453630424100200770ustar00rootroot00000000000000#!/bin/sh # SPDX-License-Identifier: GPL-2.0-or-later # # Copyright (C) 2013-2016 Aleksander Morgado # # Based on libqmi's qmi-network script # print_usage () { echo "usage: $0 [OPTIONS] [DEVICE] [COMMAND]" } help () { echo "Usage: mbim-network [OPTIONS] [DEVICE] [COMMAND]" echo echo "Simple network management of MBIM devices" echo echo "Commands:" echo " start Start network connection" echo " stop Stop network connection" echo " status Query network connection status" echo echo "Options:" echo " --profile=[PATH] Use the profile in the specified path" echo " --help, -h Show help options" echo " --version Show version" echo echo "Notes:" echo echo " 1) [DEVICE] is given as the full path to the cdc-wdm character" echo " device, e.g.:" echo " /dev/cdc-wdm0" echo echo " 2) The mbim-network script requires a profile to work. Unless" echo " explicitly specified with \`--profile', the file is assumed to" echo " be available in the following path:" echo " /etc/mbim-network.conf" echo echo " 3) The APN to use should be configured in the profile, in the" echo " following way (e.g. assuming APN is called 'internet'):" echo " APN=internet" echo echo " 4) Optional APN user/password strings may be given in the" echo " following way:" echo " APN_USER=user" echo " APN_PASS=password" echo echo " 5) If APN user/password is specified, the authentication protocol" echo " to use (one of PAP, CHAP or MSCHAPV2) must also be specified in" echo " the following way:" echo " APN_AUTH=protocol" echo echo " 6) If you want to instruct the mbim-network script to use the" echo " mbim-proxy setup, you can do so by configuring the following line" echo " in the profile:" echo " PROXY=yes" echo echo " 7) Once the mbim-network script reports a successful connection" echo " you still need to run a DHCP client on the associated WWAN network" echo " interface." echo } version () { echo "mbim-network @VERSION@" echo "Copyright (C) 2013-2021 Aleksander Morgado" echo "License GPLv2+: GNU GPL version 2 or later " echo "This is free software: you are free to change and redistribute it." echo "There is NO WARRANTY, to the extent permitted by law." echo } # Basic options if [ $# -lt 2 ]; then if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then help exit 0 elif [ "$1" = "--version" ]; then version exit 0 fi echo "error: missing arguments" 1>&2 print_usage exit 255 fi # Defaults PROFILE_FILE=/etc/mbim-network.conf # Device + Command with options; options given first while [ $# -gt 2 ]; do OPT="$1" shift case "$OPT" in "--") break 2;; "--profile") if [ $# -gt 2 ]; then PROFILE_FILE="$1" shift else PROFILE_FILE="" fi ;; "--profile="*) PROFILE_FILE="${OPT#*=}";; *) echo >&2 "Invalid option: $OPT" print_usage exit 255;; esac done if [ -z "$PROFILE_FILE" ]; then echo "error: empty profile path given" 1>&2 print_usage exit 255 fi if [ $# -ne 2 ] || [ "$1" = "--*" ] || [ "$2" = "--*" ]; then echo "error: missing arguments" 1>&2 print_usage exit 255 fi DEVICE=$1 COMMAND=$2 STATE_FILE=/tmp/mbim-network-state-`basename $DEVICE` load_profile () { if [ -f "$PROFILE_FILE" ]; then echo "Loading profile at ${PROFILE_FILE}..." . $PROFILE_FILE if [ -n "$APN" ]; then echo " APN: $APN" else echo " APN: unset" fi if [ -n "$APN_AUTH" ]; then echo " APN auth protocol: $APN_AUTH" else echo " APN auth protocol: unset" fi if [ -n "$APN_USER" ]; then echo " APN user: $APN_USER" if [ -z "$APN_AUTH" ]; then echo "error: APN_USER in the profile requires APN_AUTH" 1>&2 exit 32 fi else echo " APN user: unset" fi if [ -n "$APN_PASS" ]; then echo " APN password: $APN_PASS" if [ -z "$APN_USER" ]; then echo "error: APN_PASS in the profile requires APN_USER" 1>&2 exit 32 fi else echo " APN password: unset" fi if [ "$PROXY" = "yes" ]; then echo " mbim-proxy: $PROXY" PROXY_OPT='--device-open-proxy' else echo " mbim-proxy: no" fi else echo "Profile at '$PROFILE_FILE' not found..." fi } save_state () { KEY=$1 VAL=$2 if [ -n "${PROXY_OPT}" ]; then return fi echo "Saving state at ${STATE_FILE}... ($KEY: $VAL)" if [ -f "$STATE_FILE" ]; then PREVIOUS=`cat $STATE_FILE` PREVIOUS=`echo "$PREVIOUS" | grep -v $KEY` if [ -n "$PREVIOUS" ]; then echo $PREVIOUS > $STATE_FILE else rm $STATE_FILE fi fi if [ -n "$VAL" ]; then echo "$KEY=\"$VAL\"" >> $STATE_FILE fi } load_state () { if [ -n "${PROXY_OPT}" ]; then return fi if [ -f "$STATE_FILE" ]; then echo "Loading previous state from ${STATE_FILE}..." . $STATE_FILE if [ -n "$TRID" ]; then echo " Previous Transaction ID: $TRID" fi fi } clear_state () { if [ -n "${PROXY_OPT}" ]; then return fi echo "Clearing state at ${STATE_FILE}..." rm -f $STATE_FILE } # # $ sudo mbimcli -d /dev/cdc-wdm0 --connect="Internet" --no-close # [/dev/cdc-wdm0] Successfully connected # [/dev/cdc-wdm0] Connection status: # Session ID: '0' # Activation state: 'activated' # Voice call state: 'none' # IP type: 'ipv4' # Context type: 'internet' # Network error: 'unknown' # connect () { # Always try to connect using a fresh session if [ -z "${PROXY_OPT}" ]; then if [ -n "$TRID" ]; then # This will implicitly close the previous session mbimcli -d $DEVICE --no-open=$TRID clear_state fi fi if [ -z "${PROXY_OPT}" ]; then EXTRA_OPT="--no-close" else EXTRA_OPT="${PROXY_OPT}" fi SUBSCRIBER_READY_CMD="mbimcli -d $DEVICE --query-subscriber-ready-status ${EXTRA_OPT}" echo "Querying subscriber ready status '$SUBSCRIBER_READY_CMD'..." SUBSCRIBER_READY_OUT=`$SUBSCRIBER_READY_CMD` echo $SUBSCRIBER_READY_OUT if [ -z "${PROXY_OPT}" ]; then TRID=`echo "$SUBSCRIBER_READY_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` EXTRA_OPT="--no-open=$TRID --no-close" else EXTRA_OPT="${PROXY_OPT}" fi REGISTRATION_STATE_CMD="mbimcli -d $DEVICE --query-registration-state ${EXTRA_OPT}" echo "Querying registration state '$REGISTRATION_STATE_CMD'..." REGISTRATION_STATE_OUT=`$REGISTRATION_STATE_CMD` echo $REGISTRATION_STATE_OUT if [ -z "${PROXY_OPT}" ]; then TRID=`echo "$REGISTRATION_STATE_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` EXTRA_OPT="--no-open=$TRID --no-close" else EXTRA_OPT="${PROXY_OPT}" fi ATTACH_CMD="mbimcli -d $DEVICE --attach-packet-service ${EXTRA_OPT}" echo "Attaching to packet service with '$ATTACH_CMD'..." ATTACH_OUT=`$ATTACH_CMD` echo $ATTACH_OUT if [ -z "${PROXY_OPT}" ]; then TRID=`echo "$ATTACH_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` EXTRA_OPT="--no-open=$TRID --no-close" else EXTRA_OPT="${PROXY_OPT}" fi CONNECT_ARGS="apn='$APN'" if [ -n "$APN_AUTH" ]; then CONNECT_ARGS="${CONNECT_ARGS},auth='$APN_AUTH'" if [ -n "$APN_USER" ]; then CONNECT_ARGS="${CONNECT_ARGS},username='$APN_USER'" if [ -n "$APN_PASS" ]; then CONNECT_ARGS="${CONNECT_ARGS},password='$APN_PASS'" fi fi fi CONNECT_CMD="mbimcli -d $DEVICE --connect=$CONNECT_ARGS ${EXTRA_OPT}" echo "Starting network with '$CONNECT_CMD'..." CONNECT_OUT=`$CONNECT_CMD` if [ $? -eq 0 ]; then echo "Network started successfully" else echo "Network start failed" echo $CONNECT_OUT fi # Save the new TRID if [ -z "${PROXY_OPT}" ]; then TRID=`echo "$CONNECT_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` if [ -n "$TRID" ]; then save_state "TRID" $TRID fi fi } # # $ sudo mbimcli -d /dev/cdc-wdm0 --disconnect="0" # [/dev/cdc-wdm0] Successfully disconnected # [/dev/cdc-wdm0] Connection status: # Session ID: '0' # Activation state: 'deactivated' # Voice call state: 'none' # IP type: 'default' # Context type: 'internet' # Network error: 'unknown' # disconnect () { # Always close the session when disconnecting if [ -n "${PROXY_OPT}" ]; then EXTRA_OPT="${PROXY_OPT}" elif [ -n "$TRID" ]; then EXTRA_OPT="--no-open=$TRID" else EXTRA_OPT="" fi DISCONNECT_CMD="mbimcli -d $DEVICE --disconnect ${EXTRA_OPT}" echo "Stopping network with '$DISCONNECT_CMD'..." DISCONNECT_OUT=`$DISCONNECT_CMD` if [ $? -eq 0 ]; then echo "Network stopped successfully" else echo "Network stop failed" echo $DISCONNECT_OUT fi clear_state } # # $ sudo mbimcli -d /dev/cdc-wdm0 --query-connection-state --no-close # [/dev/cdc-wdm0] Connection status: # Session ID: '0' # Activation state: 'deactivated' # Voice call state: 'none' # IP type: 'default' # Context type: 'none' # Network error: 'unknown' # status () { if [ -n "${PROXY_OPT}" ]; then EXTRA_OPT="${PROXY_OPT}" elif [ -n "$TRID" ]; then EXTRA_OPT="--no-open=$TRID --no-close" else EXTRA_OPT="" fi STATUS_CMD="mbimcli -d $DEVICE --query-connection-state ${EXTRA_OPT}" echo "Getting status with '$STATUS_CMD'..." STATUS_OUT=`$STATUS_CMD` # Save the new TRID if [ -z "${PROXY_OPT}" ]; then TRID=`echo "$STATUS_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` if [ -n "$TRID" ]; then save_state "TRID" $TRID fi fi CONN=`echo "$STATUS_OUT" | sed -n "s/.*Activation state:.*'\(.*\)'.*/\1/p"` if [ -z "$CONN" ]; then echo "error: couldn't get connection status" 1>&2 exit 2 else echo "Status: $CONN" if [ "$CONN" != "connected" ]; then exit 64 fi fi } # Main # Load profile, if any load_profile # Load previous state, if any load_state # Process commands case $COMMAND in "start") connect ;; "stop") disconnect ;; "status") status ;; *) echo "error: unexpected command '$COMMAND'" 1>&2 print_usage exit 255 ;; esac exit 0 libmbim-1.31.2-dev/utils/meson.build000066400000000000000000000004311453630424100172670ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2021 Iñigo Martinez mbim_network = configure_file( input: 'mbim-network.in', output: '@BASENAME@', configuration: version_conf, install_dir: mbim_bindir, install_mode: 'rwxr-xr-x', )