pax_global_header00006660000000000000000000000064147203372230014515gustar00rootroot0000000000000052 comment=ee81423b69803405344658b78a0ecf21942d502c libtypec-libtypec-0.6.0/000077500000000000000000000000001472033722300151445ustar00rootroot00000000000000libtypec-libtypec-0.6.0/.gitignore000066400000000000000000000000351472033722300171320ustar00rootroot00000000000000build*/ bin/ .* !.gitignore libtypec-libtypec-0.6.0/CMakeLists.txt000066400000000000000000000050611472033722300177060ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.16.3) project(libtypec VERSION 0.6.0 DESCRIPTION "Library to interface with USB Type-C and USB Power Delivery class devices") # Distributions set arch-specific include dir by patching GNUInstallDirs include(GNUInstallDirs) # Saying ${CMAKE_CURRENT_BINARY_DIR}/ here is redundant but more readable configure_file(libtypec_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/libtypec_config.h) include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSES") set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") SET(CPACK_SET_DESTDIR "ON") set(CPACK_PACKAGE_VENDOR "Rajaram Regupathy") set(CPACK_PACKAGE_CONTACT "rajaram.regupathy@gmail.com") set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries") set(CPACK_RPM_SPEC_CHANGELOG "${CPACK_RPM_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}\n Generated by CPack RPM (Refer:https://github.com/Rajaram-Regupathy/libtypec/releases)") set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_PROCESSOR}") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Rajaram Regupathy") set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_PACKAGE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/package) set(CPACK_SOURCE_IGNORE_FILES .git/ build/ bin/ CMakeCache.txt cmake_install.cmake _CPack_Packages/ CMakeFiles/ package/ ) include(CPack) add_library(libtypec SHARED libtypec.c libtypec_sysfs_ops.c libtypec_dbgfs_ops.c) target_include_directories(libtypec PUBLIC $ $) option(LIBTYPEC_STRICT_CFLAGS "Compile for strict warnings" ON) if(LIBTYPEC_STRICT_CFLAGS) target_compile_options(libtypec PRIVATE -g -O2 -fstack-protector-strong -Wformat=1 -Werror=format-security -Wdate-time -fasynchronous-unwind-tables -D_FORTIFY_SOURCE=2) endif() set_target_properties(libtypec PROPERTIES OUTPUT_NAME "typec" VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MINOR} PUBLIC_HEADER "libtypec.h;${CMAKE_CURRENT_BINARY_DIR}/libtypec_config.h") add_subdirectory(utils) install(TARGETS libtypec lstypec typecstatus ucsicontrol LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" RUNTIME DESTINATION bin PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") configure_file( libtypec.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libtypec.pc @ONLY ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libtypec.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) libtypec-libtypec-0.6.0/LICENSES/000077500000000000000000000000001472033722300163515ustar00rootroot00000000000000libtypec-libtypec-0.6.0/LICENSES/MIT License.txt000066400000000000000000000021201472033722300211010ustar00rootroot00000000000000MIT License Copyright (c) 2022 Rajaram Regupathy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libtypec-libtypec-0.6.0/LICENSES/gpl-2.0.txt000066400000000000000000000432541472033722300202010ustar00rootroot00000000000000 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. libtypec-libtypec-0.6.0/README000066400000000000000000000037041472033722300160300ustar00rootroot00000000000000MIT License Copyright (c) 2023 Rajaram Regupathy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libtypec ++++++++ USB Type-C and USB Power Delivery systems are with multiple specification versions, platform designs and microcontroller vendors to manage data, power and display. This library defines a generic way for userspace System Software on Linux, Android, Chrome OS or Other OSes to build developer tools or other management applications for USB Type-C and USB Power Delivery class devices. Build Procedure +++++++++++++++ You could build and generate packages using the steps given below: Step 1 - Generate build configuration for libtypec ../libtypec$ cmake -DCMAKE_BUILD_TYPE=Release . Step 2 - Build libtypec and install library and binaries ../libtypec$ sudo cmake --build . --target install --config Release Step 3 - Generate debian package as follows ../libtypec$ sudo cpack -G DEB Step 4 - Generate RPM package as follows ../libtypec$ sudo cpack -G RPM libtypec-libtypec-0.6.0/debian/000077500000000000000000000000001472033722300163665ustar00rootroot00000000000000libtypec-libtypec-0.6.0/debian/changelog000066400000000000000000000002121472033722300202330ustar00rootroot00000000000000libtypec (0.1-1) unstable; urgency=low * Initial release -- Colin Ian King Tue, 25 Apr 2023 09:00:00 +0000 libtypec-libtypec-0.6.0/debian/control000066400000000000000000000024651472033722300200000ustar00rootroot00000000000000Source: libtypec Rules-Requires-Root: no Section: utils Priority: optional Maintainer: Colin Ian King Build-Depends: debhelper (>= 13), debhelper-compat (=13), cmake, dh-cmake Standards-Version: 4.1.2 Homepage: https://github.com/Rajaram-Regupathy/libtypec Package: libtypec1 Section: libs Architecture: any Priority: optional Depends: ${shlibs:Depends}, ${misc:Depends} Pre-Depends: ${misc:Pre-Depends} Description: generic interface for efficient USB-C port management libtypec is aimed to provide a generic interface abstracting all platform complexity for user space to develop tools for efficient USB-C port management. The library can also enable development of diagnostic and debug tools to debug system issues around USB-C/USB PD topology. Package: libtypec-dev Section: libdevel Architecture: any Priority: optional Depends: ${misc:Depends}, libtypec1 (= ${binary:Version}) Pre-Depends: ${misc:Pre-Depends} Description: Development files for an interface for USB-C port management libtypec is aimed to provide a generic interface abstracting all platform complexity for user space to develop tools for efficient USB-C port management. The library can also enable development of diagnostic and debug tools to debug system issues around USB-C/USB PD topology. libtypec-libtypec-0.6.0/debian/copyright000066400000000000000000000026341472033722300203260ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: libtypec Upstream-Contact: Rajaram Regupathy Source: https://github.com/Rajaram-Regupathy/libtypec Files: * Copyright: 2022, Rajaram Regupathy License: MIT MIT License . Copyright (c) 2022 Rajaram Regupathy . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libtypec-libtypec-0.6.0/debian/files000066400000000000000000000000611472033722300174100ustar00rootroot00000000000000libtypec_0.4.0-1_source.buildinfo utils optional libtypec-libtypec-0.6.0/debian/install000066400000000000000000000001031472033722300177510ustar00rootroot00000000000000usr/lib/*/lib*so* usr/include/*/*h usr/share/pkgconfig/libtypec.pc libtypec-libtypec-0.6.0/debian/rules000077500000000000000000000003741472033722300174520ustar00rootroot00000000000000#!/usr/bin/make -f DPKG_EXPORT_BUILDFLAGS = 1 export DH_VERBOSE=1 include /usr/share/dpkg/buildflags.mk %: dh $@ override_dh_auto_configure: dh_auto_configure -- $(CMAKE_FLAGS) override_dh_auto_install: echo "Now installing.." dh_auto_install libtypec-libtypec-0.6.0/debian/source/000077500000000000000000000000001472033722300176665ustar00rootroot00000000000000libtypec-libtypec-0.6.0/debian/source/format000066400000000000000000000000141472033722300210740ustar00rootroot000000000000003.0 (quilt) libtypec-libtypec-0.6.0/debian/watch000066400000000000000000000003201472033722300174120ustar00rootroot00000000000000version=4 opts="filenamemangle=s%(?:.*?)?V?(\d[\d.]*)\.tar\.gz%@PACKAGE@-$1.tar.gz%" \ https://github.com/ColinIanKing/forkstat/tags \ (?:.*?/)?V?(\d[\d.]*)\.tar\.gz debian uupdate libtypec-libtypec-0.6.0/libtypec.c000066400000000000000000000341131472033722300171250ustar00rootroot00000000000000/* MIT License Copyright (c) 2022 Rajaram Regupathy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // SPDX-License-Identifier: MIT /** * @file libtypec.c * @author Rajaram Regupathy * @brief Core functions for libtypec */ #include #include #include #include "libtypec.h" #include "libtypec_ops.h" #include #include #include #include #include #include #include #include static char ver_buf[64]; static struct utsname ker_uname; static const struct libtypec_os_backend *cur_libtypec_os_backend; /** * \mainpage libtypec 0.4.0 API Reference * * \section intro Introduction * * Existing USB-Type C and USB Power Delivery solutions, platform * designs vary because of USB PD Specification versions, Vendor * specific host interface and division in the protocol stack/policy * management across the software layers. This necessitates tools and * applications that enable efficient port management and allows end * users to root cause/debug system issues. * * Existing TypeC class ABI is tied up between 1) Multiple Interface * Protocols 2) Need for OS level PD policy for System level management * against the static PD policy. * * Multiple Interface Protocols : * * Adding to this complexity is the multiple specification versions and * platform designs there are different interface protocols ( PD Host * Interface, UCSI, CrOS EC, TCPC) that provide inconsistent information * to the TypeC Class ABI or hold additional design specific hooks. This * necessitates an abstraction that provides a transparent interface to * user space software. * * Static Capabilities: * * With policy management defined as implementation specific by USB-C and * USB PD specifications, implementation of these policies are scattered * in different platform drivers or firmware modules. This necessitates a * common interface across all designs that allows management of port * policy. * * “libtypec” is aimed to provide a generic interface abstracting all * platform complexity for user space to develop tools for efficient USB-C * port management and efficient diagnostic and debugging tools to debug of * system issues around USB-C/USB PD topology. * * The data structures and interface APIs would match closer to USB Type-C® * Connector System Software Interface (UCSI) Specification. * */ static char *ops_str[] = {"sysfs","debugfs"}; char *get_kernel_verion(void) { if (uname(&ker_uname) != 0) return 0; else return ker_uname.release; } char *get_os_name(void) { FILE *fp = fopen("/etc/os-release", "r"); static char buf[128]; char *p = NULL; if (fp) { while (fgets(buf, sizeof(buf), fp)) { char *ptr; /* Ensure buffer always has eos marker at end */ buf[sizeof(buf) - 1] = '\0'; /* Remove \n */ for (ptr = buf; *ptr && *ptr != '\n'; ptr++) ; *ptr = '\0'; if (strncmp(buf, "ID=", 3) == 0) { p = buf + 3; break; } } fclose(fp); } return p; } /** * This function initializes libtypec and must be called before * calling any other libtypec function. * * The function is responsible for setting up the backend interface and * also provides necessary platform session information * * \param Array of platform session strings * * \returns 0 on success */ int libtypec_init(char **session_info, enum libtypec_backend backend) { int ret; struct statfs sb; sprintf(ver_buf, "libtypec %d.%d.%d", LIBTYPEC_MAJOR_VERSION, LIBTYPEC_MINOR_VERSION,LIBTYPEC_PATCH_VERSION); session_info[LIBTYPEC_VERSION_INDEX] = ver_buf; session_info[LIBTYPEC_KERNEL_INDEX] = get_kernel_verion(); session_info[LIBTYPEC_OS_INDEX] = get_os_name(); if (backend == LIBTYPEC_BACKEND_DBGFS) { cur_libtypec_os_backend = &libtypec_lnx_dbgfs_backend; if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->init ) { ret = -EIO; printf("Failed to initialize dbgfs backend\n"); } else ret = cur_libtypec_os_backend->init(session_info); } else { cur_libtypec_os_backend = &libtypec_lnx_sysfs_backend; if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->init ) { printf("Failed to initialize sysfs backend\n"); ret = -EIO; } else ret = cur_libtypec_os_backend->init(session_info); } session_info[LIBTYPEC_OPS_INDEX] = ops_str[backend]; return ret; } /** * This function must be called before exiting libtypec session to perform * cleanup. * * \param * * \returns 0 on success */ int libtypec_exit(void) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->exit ) return -EIO; /* clear session info */ return cur_libtypec_os_backend->exit(); } /** * This function shall be used to set the connector reset * * \param conn_num connector number * \param rst_type connector reset type * * \returns 0 on success */ int libtypec_connector_reset(int conn_num, int rst_type) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->connector_reset) return -EIO; return cur_libtypec_os_backend->connector_reset(conn_num, rst_type); } /** * This function shall be used to set the data operation role * * \param conn_num connector number * \param uor data operation role * \returns 0 on success */ int libtypec_set_uor_ops(unsigned char conn_num, unsigned char uor) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->set_uor_ops) return -EIO; return cur_libtypec_os_backend->set_uor_ops(conn_num, uor); } /** * This function shall be used to set the power operation role * * \param conn_num Data structure to hold platform capability * * \returns 0 on success */ int libtypec_set_pdr_ops(unsigned char conn_num, unsigned char pdr) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->set_pdr_ops) return -EIO; return cur_libtypec_os_backend->set_pdr_ops(conn_num, pdr); } /** * This function shall be used to get the platform policy capabilities * * \param cap_data Data structure to hold platform capability * * \returns 0 on success */ int libtypec_get_capability(struct libtypec_capability_data *cap_data) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_capability_ops ) return -EIO; return cur_libtypec_os_backend->get_capability_ops(cap_data); } /** * This function shall be used to get the capabilities of a connector * * \param conn_num Indicates which connector's capability needs to be retrieved * * \param conn_cap_data Data structure to hold connector capability * * \returns 0 on success */ int libtypec_get_conn_capability(int conn_num, struct libtypec_connector_cap_data *conn_cap_data) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_conn_capability_ops ) return -EIO; return cur_libtypec_os_backend->get_conn_capability_ops(conn_num, conn_cap_data); } /** * This function shall be used to get the Alternate Modes that the Connector/ * Cable/Attached Device is capable of supporting. * * \param recipient Represents alternate mode to be retrieved from local * or SOP or SOP' or SOP" * * \param conn_num Indicates which connector's capability needs to be retrivied * * \returns number of alternate modes on success */ int libtypec_get_alternate_modes(int recipient, int conn_num, struct altmode_data *alt_mode_data) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_alternate_modes ) return -EIO; return cur_libtypec_os_backend->get_alternate_modes(recipient, conn_num, alt_mode_data); } /** * This function shall be used to get the Cable Property of a connector * * \param conn_num Indicates which connector's status needs to be retrieved * * \returns 0 on success */ int libtypec_get_cable_properties(int conn_num, struct libtypec_cable_property *cbl_prop_data) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_cable_properties_ops ) return -EIO; return cur_libtypec_os_backend->get_cable_properties_ops(conn_num, cbl_prop_data); } /** * This function shall be used to get the Connector status * * \param conn_num Indicates which connector's status needs to be retrieved * * \returns 0 on success */ int libtypec_get_connector_status(int conn_num, struct libtypec_connector_status *conn_sts) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_connector_status_ops ) return -EIO; return cur_libtypec_os_backend->get_connector_status_ops(conn_num, conn_sts); } /** * This function shall be used to get the Current cam of a connector * * \param conn_num connector number * \param cur_cur data structure containing current cam * * \returns 0 on success */ int libtypec_get_current_cam(int conn_num, struct libtypec_current_cam *cur_cam) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_current_cam_ops) return -EIO; return cur_libtypec_os_backend->get_current_cam_ops(conn_num, cur_cam); } /** * This function shall be used to get the USB PD response messages from * * \param recipient Represents PD response message to be retrieved from local * or SOP or SOP' or SOP" * * \param conn_num Indicates which connector's PD message needs to be retrieved * * \param pd_msg_resp * \returns 0 on success */ int libtypec_get_pd_message(int recipient, int conn_num, int num_bytes, int resp_type, char *pd_msg_resp) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_pd_message_ops ) return -EIO; return cur_libtypec_os_backend->get_pd_message_ops(recipient, conn_num, num_bytes, resp_type, pd_msg_resp); } /** * This function shall be used to get PDOs from local and partner Policy Managers * * \param conn_num Represents connector to be queried * * \param partner Set to TRUE to retrieve partner PDOs * * \param offset Index from which PDO needs to be retrieved * * \param num_pdo Represents number of PDOs to be retrieved * * \param src_snk Set to TRUE to retrieve Source PDOs * * \param type Represents type of Source PDOs requested * * \param pdo_data Holds PDO data retrieved * * \returns PDO retrieved on success */ int libtypec_get_pdos (int conn_num, int partner, int offset, int *num_pdo, int src_snk, int type, struct libtypec_get_pdos *pdo_data) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_pdos_ops ) return -EIO; return cur_libtypec_os_backend->get_pdos_ops(conn_num, partner, offset, num_pdo, src_snk, type, pdo_data); } /** * This function shall be used to retrive number of billboard interfaces in the system * * \param num_bb_instance Reference passed to retrive number of billboard interfaces. If 0 then * no billboard interface and >0 indicates number of BB devices enumerated in the system. * * \returns 0 on success */ int libtypec_get_bb_status(unsigned int *num_bb_instance) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_bb_status ) return -EIO; return cur_libtypec_os_backend->get_bb_status(num_bb_instance); } /** * This function shall be used to retrive Billboard Capability Descriptor of BB device instances * in the system. When multiple BB devices are in the system instance shall indicate the instance * index for data to be retrived * * \param bb_instance index of the BB instance * \param bb_data BB capability descriptor of the device instance * * \returns 0 on success */ int libtypec_get_bb_data(int bb_instance,char* bb_data) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->get_bb_data ) return -EIO; return cur_libtypec_os_backend->get_bb_data(bb_instance,bb_data); } int libtypec_register_typec_notification_callback(enum usb_typec_event event, usb_typec_callback_t cb, void* data) { if (event >= USBC_EVENT_COUNT) { fprintf(stderr, "Invalid event\n"); return -1; } libtypec_notification_list_t* node = malloc(sizeof(libtypec_notification_list_t)); if (!node) { fprintf(stderr, "Failed to allocate memory for callback node\n"); return -1; } node->cb_func = cb; node->data = data; node->next = registered_callbacks[event]; registered_callbacks[event] = node; } int libtypec_unregister_callback(enum usb_typec_event event, usb_typec_callback_t cb) { if (event >= USBC_EVENT_COUNT) { fprintf(stderr, "Invalid event\n"); return -1; } libtypec_notification_list_t** node = ®istered_callbacks[event]; while (*node) { if ((*node)->cb_func == cb) { libtypec_notification_list_t* next = (*node)->next; free(*node); *node = next; } else { node = &(*node)->next; } } } void libtypec_monitor_events(void) { if (!cur_libtypec_os_backend || !cur_libtypec_os_backend->monitor_events ) return; cur_libtypec_os_backend->monitor_events(); } libtypec-libtypec-0.6.0/libtypec.h000066400000000000000000000324411472033722300171340ustar00rootroot00000000000000/* MIT License Copyright (c) 2022 Rajaram Regupathy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // SPDX-License-Identifier: MIT /** * @file libtypec.h * @author Rajaram Regupathy * @brief * Public libtypec header file providing interfaces for USB Type-C * Connector System Software. * */ #ifndef LIBTYPEC_H #define LIBTYPEC_H #include #include "libtypec_config.h" union optionalfeature { struct { unsigned char setccomsupported : 1; unsigned char setpowerlevelsupported : 1; unsigned char altmodedetailssupported : 1; unsigned char altmodeoverridesupported : 1; unsigned char pdodetailssupported : 1; unsigned char cabledetailssupported : 1; unsigned char extsupplynotificationsupported : 1; unsigned char pdresetnotificationsupported : 1; unsigned char getpdmessagesupported : 1; unsigned char getattentionvdosupported : 1; unsigned char fwupdaterequestsupported : 1; unsigned char negotiatedpowerlevelchangesupported : 1; unsigned char securityrequestsupported : 1; unsigned char setretimermodesupported : 1; unsigned char chunkingsupportsupported : 1; unsigned char reserved1 : 1; unsigned char reserved2; }; unsigned char raw_optfeas[3]; }; union powersource { struct { unsigned char acsupply : 1; unsigned char reserved1 : 1; unsigned char other : 1; unsigned char reserved2 : 3; unsigned char vbus : 1; unsigned char reserved3 : 1; }; unsigned char raw_powersrc; }; union attributes { struct { unsigned int disabledstatesupport : 1; unsigned int batterycharging : 1; unsigned int usbpowerdelivery : 1; unsigned int reserved1 : 3; unsigned int usbtypeccurrent : 1; unsigned int reserved2 : 1; union powersource bmPowerSource; unsigned int reserved3 : 16; }; unsigned int raw_attrs; }; struct libtypec_capability_data { union attributes bmAttributes; unsigned int bNumConnectors : 7; unsigned int reserved1 : 1; union optionalfeature bmOptionalFeatures; unsigned int bNumAltModes : 8; unsigned int reserved2 : 8; unsigned int bcdBCVersion : 16; unsigned int bcdPDVersion : 16; unsigned int bcdTypeCVersion : 16; }; union operationmode { struct { unsigned char rponly : 1; unsigned char rdonly : 1; unsigned char drp : 1; unsigned char analogaudioaccessorymode : 1; unsigned char debugaccessorymode : 1; unsigned char usb2 : 1; unsigned char usb3 : 1; unsigned char alternatemode : 1; }; unsigned char raw_operationmode; }; union extendedoperationmode { struct { unsigned char usb4gen2 : 1; unsigned char eprsrc : 1; unsigned char eprsnk : 1; unsigned char usb4gen3 : 1; unsigned char usb4gen4 : 1; unsigned char reserved : 3; }; unsigned char raw_extendedoperationmode; }; union miscellaneouscapabilities { struct { unsigned char fwupdate : 1; unsigned char security : 1; unsigned char reserved : 2; }; unsigned char raw_miscellaneouscapabilities; }; struct libtypec_connector_cap_data { union operationmode opr_mode; unsigned int provider : 1; unsigned int consumer : 1; unsigned int swap2dfp : 1; unsigned int swap2ufp : 1; unsigned int swap2src : 1; unsigned int swap2snk : 1; unsigned int extended_operation_mode : 8; unsigned int miscellaneous_capabilities : 4; unsigned int reverse_current_protection_support : 1; unsigned int partner_pd_rev : 2; unsigned int reserved :3; }__attribute__((packed)); struct libtypec_current_cam { unsigned char current_altmode[4]; }; struct libtypec_get_pdos { unsigned int pdo[4]; }; struct altmode_data { uint16_t svid; uint32_t vdo; }; union libtypec_discovered_identity { char buf_disc_id[24]; struct discovered_identity { uint32_t cert_stat; uint32_t id_header; uint32_t product; uint32_t product_type_vdo1; uint32_t product_type_vdo2; uint32_t product_type_vdo3; } disc_id; }; union connectorstatuschange { struct { unsigned char reserved1 : 1; unsigned char ExternalSupplyChange : 1; unsigned char PowerOperationModechange : 1; unsigned char Attention : 1; unsigned char Reserved2 : 1; unsigned char SupportedProviderCapabilitiesChange : 1; unsigned char NegotiatedPowerLevelChange : 1; unsigned char PDResetComplete : 1; unsigned char SupportedCAMChange : 1; unsigned char BatteryChargingStatusChange : 1; unsigned char Reserved3 : 1; unsigned char ConnectorPartnerChanged : 1; unsigned char PowerDirectionChanged : 1; unsigned char SinkPathStatusChange : 1; unsigned char ConnectChange : 1; unsigned char Error : 1; }; unsigned short int raw_conn_stschang; }; enum power_operation_mode { /** USB_DEFAULT_OPERATION */ USB_DEFAULT_OPERATION = 1, /** BC_OPERATION */ BC_OPERATION = 2, /** PD_OPERATION */ PD_OPERATION = 3, /** USB_TC_CURRENT_1_5A */ USB_TC_CURRENT_1_5A = 4, /** USB_TC_CURRENT_3A */ USB_TC_CURRENT_3A = 5, /** USB_TC_CURRENT_5A */ USB_TC_CURRENT_5A = 6, }; union connectorpartnerflags { struct { unsigned char usb : 1; unsigned char altmode : 1; unsigned char usb4_gen3 : 1; unsigned char usb4_gen4 : 1; unsigned char reserved : 4; }; unsigned char raw_conn_part_flags; }; enum conn_partner_type { /** DFP_ATTACHED */ DFP_ATTACHED = 1, /** UFP_ATTACHED */ UFP_ATTACHED = 2, /** POWERED_CABLE_NO_UFP_ATTACHED */ POWERED_CABLE_NO_UFP_ATTACHED = 3, /** POWERED_CABLE_UFP_ATTACHED */ POWERED_CABLE_UFP_ATTACHED = 4, /** DEBUG_ACCESSORY_ATTACHED */ DEBUG_ACCESSORY_ATTACHED = 5, /** AUDIO_ADAPTER_ACCESSORY_ATTACHED */ AUDIO_ADAPTER_ACCESSORY_ATTACHED = 6, }; struct libtypec_connector_status { union connectorstatuschange ConnectorStatusChange; unsigned int PowerOperationMode : 3; unsigned int ConnectStatus : 1; unsigned int PowerDirection : 1; unsigned int ConnectorPartnerFlags :8; unsigned int ConnectorPartnerType : 3; unsigned int RequestDataObject : 32; unsigned int BatteryChargingCapabilityStatus : 2; unsigned int ProviderCapabilitiesLimitedReason : 4; unsigned int bcdPDVersionOperationMode : 16; unsigned int Orientation : 1; unsigned int SinkPathStatus : 1; unsigned int ReverseCurrentProtectionStatus : 1; unsigned int PowerReadingReady : 1; unsigned int CurrentScale : 3; unsigned int PeakCurrent : 16; unsigned int AverageCurrent : 16; unsigned int VoltageScale : 4; unsigned int VoltageReading : 16; unsigned int Reserved : 7; }__attribute__((packed)); struct libtypec_cable_property { unsigned short speed_supported; unsigned int current_capability : 8; unsigned int vbus_support : 1; unsigned int cable_type : 1; unsigned int directionality : 1; unsigned int plug_end_type : 2 ; unsigned int mode_support : 1; unsigned int cable_pd_revision : 2; unsigned int latency : 4; unsigned int reserved : 28; }__attribute__((packed)); struct libtypec_get_lpm_ppm_info { unsigned short vid; unsigned short pid; unsigned int xid; unsigned int fw_version_upper; unsigned int fw_version_lower; unsigned int hw_version; }; union libtypec_fixed_supply_src { unsigned fixed_supply; struct fixed_supply_bits { unsigned max_cur:10; unsigned volt:10; unsigned peak_cur:2; unsigned rsvd:1; unsigned epr:1; unsigned unchunked:1; unsigned drd:1; unsigned usb_comm:1; unsigned uncons_pwr:1; unsigned usb_suspend:1; unsigned dual_pwr:1; unsigned type:2; }obj_fixed_sply; }; union libtypec_variable_supply_src { unsigned int variable_supply; struct variable_supply_bits { unsigned max_cur:10; unsigned min_volt:10; unsigned max_volt:10; unsigned type:2; }obj_var_sply; }; union libtypec_battery_supply_src { unsigned int battery_supply; struct battery_supply_bits { unsigned max_pwr:10; unsigned min_volt:10; unsigned max_volt:10; unsigned type:2; }obj_bat_sply; }; union libtypec_pps_src { unsigned int spr_pps_supply; struct pps_supply_bits { unsigned max_cur:7; unsigned rsvd1:1; unsigned min_volt:8; unsigned rsvd2:1; unsigned max_volt:8; unsigned rsvd3:2; unsigned pwr_ltd:1; unsigned pps_type:2; unsigned type:2; }obj_pps_sply; }; union libtypec_fixed_supply_snk { unsigned int fixed_supply; struct fixed_sply_bits { unsigned opr_cur:10; unsigned volt:10; unsigned rsvd:3; unsigned fr_swp:2; unsigned drd:1; unsigned usb_comm_cap:1; unsigned uncons_pwr:1; unsigned higher_caps:1; unsigned drp:1; unsigned type:2; }obj_fixed_supply; }; union libtypec_variable_sply_sink { unsigned int var_sply_snk; struct var_supply_bits { unsigned opr_cur:10; unsigned min_volt:10; unsigned max_volt:10; unsigned type:2; }obj_var_sply; }; union libtypec_battery_sply_sink { unsigned int battery_supply; struct battery_sply_bits { unsigned opr_pwr:10; unsigned min_volt:10; unsigned max_volt:10; unsigned type:2; }obj_bat_sply; }; union libtypec_pps_sink { unsigned int spr_pps; struct spr_pps_bits { unsigned max_cur:7; unsigned rsvd1:1; unsigned min_volt:8; unsigned rsvd2:1; unsigned max_volt:8; unsigned rsvd3:3; unsigned pps_type:2; unsigned type:2; }obj_spr_pps; }; #define LIBTYPEC_VERSION_INDEX 0 #define LIBTYPEC_KERNEL_INDEX 1 #define LIBTYPEC_OS_INDEX 2 #define LIBTYPEC_INTF_INDEX 3 #define LIBTYPEC_OPS_INDEX 4 #define LIBTYPEC_SESSION_MAX_INDEX 5 #define OPR_MODE_RP_ONLY 0 #define OPR_MODE_RD_ONLY 1 #define OPR_MODE_DRP_ONLY 2 #define AM_CONNECTOR 0 #define AM_SOP 1 #define AM_SOP_PR 2 #define AM_SOP_DPR 3 #define PLUG_TYPE_A 0 #define PLUG_TYPE_B 1 #define PLUG_TYPE_C 2 #define PLUG_TYPE_OTH 3 #define CABLE_TYPE_PASSIVE 0 #define CABLE_TYPE_ACTIVE 1 #define CABLE_TYPE_UNKNOWN 2 #define GET_SINK_CAP_EXTENDED 0 #define GET_SOURCE_CAP_EXTENDED 1 #define GET_BATTERY_CAP 2 #define GET_BATTERY_STATUS 3 #define DISCOVER_ID_REQ 4 #define POWER_OP_MODE_PD 3 #define POWER_OP_MODE_TC_1_5 4 #define POWER_OP_MODE_TC_3 5 #define PDO_FIXED 0 #define PDO_BATTERY 1 #define PDO_VARIABLE 2 #define PDO_AUGMENTED 3 enum usb_typec_event { USBC_DEVICE_CONNECTED, USBC_DEVICE_DISCONNECTED, USBC_EVENT_COUNT }; enum libtypec_backend { LIBTYPEC_BACKEND_SYSFS=0, LIBTYPEC_BACKEND_DBGFS, /*LIBTYPEC_BACKEND_I2C,*/ /*Potential backend interface*/ }; typedef void (*usb_typec_callback_t)(enum usb_typec_event event, void* data); typedef struct libtypec_notification_list{ usb_typec_callback_t cb_func; void* data; struct libtypec_notification_list* next; } libtypec_notification_list_t; int libtypec_init(char **session_info,enum libtypec_backend backend); int libtypec_exit(void); /** * @brief * */ int libtypec_connector_reset(int conn_num, int rst_type); int libtypec_get_capability(struct libtypec_capability_data *cap_data); int libtypec_get_conn_capability(int conn_num, struct libtypec_connector_cap_data *conn_cap_data); int libtypec_get_alternate_modes(int recipient, int conn_num, struct altmode_data *alt_mode_data); int libtypec_get_cam_supported(int conn_num, char *cam_data); int libtypec_get_current_cam(int conn_num, struct libtypec_current_cam *cur_cam); int libtypec_get_pdos(int conn_num, int partner, int offset, int *num_pdo, int src_snk, int type, struct libtypec_get_pdos *pdo_data); int libtypec_get_cable_properties(int conn_num, struct libtypec_cable_property *cbl_prop_data); int libtypec_get_connector_status(int conn_num, struct libtypec_connector_status *conn_sts); int libtypec_get_pd_message(int recipient, int conn_num, int num_bytes, int resp_type, char *pd_msg_resp); int libtypec_get_bb_status(unsigned int *num_bb_instance); int libtypec_get_bb_data(int num_billboards,char* bb_data); int libtypec_set_uor_ops(unsigned char conn_num, unsigned char uor); int libtypec_set_pdr_ops(unsigned char conn_num, unsigned char pdr); int libtypec_register_typec_notification_callback(enum usb_typec_event event, usb_typec_callback_t cb, void* data); int libtypec_unregister_typec_notification_callback(enum usb_typec_event event, usb_typec_callback_t cb); void libtypec_monitor_events(void); #endif /*LIBTYPEC_H*/ libtypec-libtypec-0.6.0/libtypec.pc.in000066400000000000000000000004301472033722300177050ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=${exec_prefix}/lib includedir=${prefix}/include Name: @CMAKE_PROJECT_NAME@ Description: @PROJECT_DESCRIPTION@ Version: @CMAKE_PROJECT_VERSION@ Requires: Libs: -L${libdir} -llibtypec Cflags: -I${includedir} libtypec-libtypec-0.6.0/libtypec_config.h.in000066400000000000000000000002501472033722300210570ustar00rootroot00000000000000#define LIBTYPEC_MAJOR_VERSION @libtypec_VERSION_MAJOR@ #define LIBTYPEC_MINOR_VERSION @libtypec_VERSION_MINOR@ #define LIBTYPEC_PATCH_VERSION @libtypec_VERSION_PATCH@ libtypec-libtypec-0.6.0/libtypec_dbgfs_ops.c000066400000000000000000000274531472033722300211640ustar00rootroot00000000000000 /* MIT License Copyright (c) 2023 Rajaram Regupathy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // SPDX-License-Identifier: MIT /** * @file libtypec_dbgfs_ops.c * @author Rajaram Regupathy * @brief Functions for libtypec debugfs based operations */ #include "libtypec_ops.h" #include #include #include #include #include #include #include #include #include #include #include #include int fp_command; int fp_response; struct pollfd pfds; int hexCharToInt(char 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; // Invalid character } int get_ucsi_response(unsigned char *data) { char c[64]; unsigned char temp[64]; // Temporary buffer for reversal, assuming data will not exceed 64 bytes int i = 0, j = 0, result, dataIndex = 0; if (fp_response <= 0) return -1; result = poll(&pfds, 1, -1); if (result < 0) return -1; j = read(fp_response, c, 64); if (j <= 2) return -1; // Not enough data read or no data to process // Process two characters at a time for (i = 2; i < j - 1; i += 2) { // Ensure there are always pairs of characters to process int high = hexCharToInt(c[i]); int low = hexCharToInt(c[i + 1]); if (high < 0 || low < 0) return -1; // Invalid hex character temp[dataIndex] = (high << 4) | low; // Combine two hex digits into one byte, store in temp dataIndex++; } // Reverse the bytes from temp into data for (i = 0; i < dataIndex; i++) { data[i] = temp[dataIndex - 1 - i]; } lseek(fp_response, 0, SEEK_SET); return dataIndex; // Return the number of bytes processed and stored in data } #define MAX_PATH 1000 int search_dbgfs_files(char *basePath, char *commandPath, char *responsePath) { char path[MAX_PATH]; struct dirent *dp; DIR *dir = opendir(basePath); int commandFound = 0, responseFound = 0; // Unable to open directory stream if (!dir) return -1; while ((dp = readdir(dir)) != NULL) { if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) { // Construct new path from our base path strncpy(path, basePath, sizeof(path)); strncat(path, "/", sizeof(path) - strlen(path) - 1); strncat(path, dp->d_name, sizeof(path) - strlen(path) - 1); if (strcmp(dp->d_name, "command") == 0) { strncpy(commandPath, path, MAX_PATH); commandFound = 1; } if (strcmp(dp->d_name, "response") == 0) { strncpy(responsePath, path, MAX_PATH); responseFound = 1; } if (commandFound && responseFound) { closedir(dir); return 0; } if (search_dbgfs_files(path, commandPath, responsePath) == 0) { closedir(dir); return 0; } } } closedir(dir); return -1; } static int libtypec_dbgfs_init(char **session_info) { char commandPath[MAX_PATH] = {0}; char responsePath[MAX_PATH] = {0}; if (search_dbgfs_files("/sys/kernel/debug/usb/ucsi", commandPath, responsePath) == 0) { fp_command = open(commandPath, O_WRONLY); if (fp_command <= 0) return -1; fp_response = open(responsePath,O_RDONLY); if (fp_response <= 0) return -1; pfds.fd = fp_response; pfds.events = POLLIN; return 0; } else { printf("Failed to open ucsi debugfs files\n"); return -EIO; } } static int libtypec_dbgfs_connector_reset_ops(int conn_num, int rst_type) { int ret=-1; unsigned char buf[64]; union conn_rst_cmd { struct { unsigned int cmd : 8; unsigned int data_leng : 8; unsigned int con_num : 7; unsigned int rst_type : 1; }; unsigned int rst_cmd; }rstcmd; if(fp_command > 0) { rstcmd.cmd = 0x03; rstcmd.data_leng = 0x00; rstcmd.con_num = conn_num + 1; rstcmd.rst_type = rst_type; snprintf(buf, sizeof(buf), "0x%x", rstcmd.rst_cmd); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret < 16) ret = -1; } } return ret; } static int libtypec_dbgfs_exit(void) { close(fp_command); close(fp_response); fp_command = -1; fp_response = -1; return 0; } static int libtypec_dbgfs_get_capability_ops(struct libtypec_capability_data *cap_data) { int ret=-1; char buf[64] = {0}; if(fp_command > 0) { ret = write(fp_command,"6",sizeof("6")); if(ret) { ret = get_ucsi_response(buf); if(ret < 16) ret = -1; // Copy the entire buf into cap_data memcpy(cap_data, buf, sizeof(*cap_data)); } } return ret; } static int libtypec_dbgfs_get_conn_capability_ops(int conn_num, struct libtypec_connector_cap_data *conn_cap_data) { int ret=-1; unsigned char buf[64] = {0}; if(fp_command > 0) { snprintf(buf, sizeof(buf), "0x%x", (conn_num + 1) << 16 | 0x7); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret < 16) ret = -1; // Copy the entire buf into cap_data memcpy(conn_cap_data, buf, sizeof(*conn_cap_data)); } } return ret; } static int libtypec_dbgfs_get_alternate_modes(int recipient, int conn_num, struct altmode_data *alt_mode_data) { union get_am_cmd { unsigned long long cmd_val; struct{ char cmd; char len; char rcp; char con; char offset; char num_am; }s; }am_cmd; int ret=-1,i=0; unsigned char buf[64]; unsigned short psvid = 0; if(fp_command > 0) { do { am_cmd.s.cmd = 0xc; am_cmd.s.len = 0; am_cmd.s.rcp = recipient; am_cmd.s.con = conn_num+1; am_cmd.s.offset = i; am_cmd.s.num_am = 0; snprintf(buf, sizeof(buf), "%lld", am_cmd.cmd_val); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret< 16) return -1; alt_mode_data[i].svid = buf[1] << 8 | buf[0]; alt_mode_data[i].vdo = buf[5] << 24 | buf[4] << 16 | buf[3] << 8 | buf[2]; if(alt_mode_data[i].svid == 0 | alt_mode_data[i].svid == psvid) break; psvid = alt_mode_data[i].svid; } i++; }while(1); } return i; } static int libtypec_dbfs_get_current_cam_ops(int conn_num, struct libtypec_current_cam *cur_cam) { int ret=-1; unsigned char buf[64]; if(fp_command > 0) { snprintf(buf, sizeof(buf), "0x%x", (conn_num + 1) << 16 | 0x0E); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret < 16) ret = -1; // Copy the entire buf into cap_data memcpy(cur_cam, buf, ret); } } return ret; } static int libtypec_dbgfs_get_pdos_ops(int conn_num, int partner, int offset, int *num_pdo, int src_snk, int type, struct libtypec_get_pdos *pdo_data) { union get_pdo_cmd { unsigned long long cmd_val; struct{ unsigned int cmd : 8; unsigned int len : 8; unsigned int con : 7; unsigned int ptnr : 1; unsigned int offset : 8; unsigned int num : 2; unsigned int src_snk : 1; unsigned int type : 2; }s; }pdo_cmd; int ret=-1,i=0; unsigned char buf[64]; unsigned ppdo = 0; if(fp_command > 0) { do { pdo_cmd.s.cmd = 0x10; pdo_cmd.s.len = 0; pdo_cmd.s.con = conn_num+1; pdo_cmd.s.ptnr = partner; pdo_cmd.s.offset = i; pdo_cmd.s.num = 0; pdo_cmd.s.src_snk = src_snk; pdo_cmd.s.type = type; snprintf(buf, sizeof(buf), "0x%llx", pdo_cmd.cmd_val); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret< 16) return -1; pdo_data->pdo[i] = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]; if(pdo_data->pdo[i] == 0 | pdo_data->pdo[i] == ppdo) break; ppdo = pdo_data->pdo[i]; } i++; }while(1); } *num_pdo = i; return i; } static int libtypec_dbgfs_get_cable_properties_ops(int conn_num, struct libtypec_cable_property *conn_cap) { int ret=-1; unsigned char buf[64]; if(fp_command > 0) { snprintf(buf, sizeof(buf), "0x%x", (conn_num + 1) << 16 | 0x11); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret < 16) ret = -1; // Copy the entire buf into cap_data memcpy(conn_cap, buf, ret); } } return ret; } static int libtypec_dbgs_get_connector_status_ops(int conn_num, struct libtypec_connector_status *conn_sts) { int ret=-1; unsigned char buf[64]; if(fp_command > 0) { snprintf(buf, sizeof(buf), "0x%x", (conn_num + 1) << 16 | 0x12); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret < 16) ret = -1; // Copy the entire buf into cap_data memcpy(conn_sts, buf, ret); } } return ret; } static int libtypec_dbgfs_set_uor_ops(unsigned char conn_num, unsigned char uor) { int ret=-1; unsigned char buf[64]; union set_uor_cmd { struct { unsigned int cmd : 8; unsigned int data_leng : 8; unsigned int con_num : 7; unsigned int uor_type : 3; }; unsigned int uor_cmd; }setuorcmd; if(fp_command > 0) { setuorcmd.cmd = 0x09; setuorcmd.data_leng = 0x00; setuorcmd.con_num = conn_num + 1; setuorcmd.uor_type = 0x4 | uor; snprintf(buf, sizeof(buf), "0x%x", setuorcmd.uor_cmd); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret < 16) ret = -1; } } return ret; } static int libtypec_dbgfs_set_pdr_ops(unsigned char conn_num, unsigned char pdr) { int ret=-1; unsigned char buf[64]; union set_pdr_cmd { struct { unsigned int cmd : 8; unsigned int data_leng : 8; unsigned int con_num : 7; unsigned int pdr_type : 3; }; unsigned int pdr_cmd; }setpdrcmd; if(fp_command > 0) { setpdrcmd.cmd = 0x0B; setpdrcmd.data_leng = 0x00; setpdrcmd.con_num = conn_num + 1; setpdrcmd.pdr_type = pdr; snprintf(buf, sizeof(buf), "0x%x", setpdrcmd.pdr_cmd); ret = write(fp_command,buf,sizeof(buf)); if(ret) { ret = get_ucsi_response(buf); if(ret < 16) ret = -1; } } return ret; } const struct libtypec_os_backend libtypec_lnx_dbgfs_backend = { .init = libtypec_dbgfs_init, .exit = libtypec_dbgfs_exit, .connector_reset = libtypec_dbgfs_connector_reset_ops, .get_capability_ops = libtypec_dbgfs_get_capability_ops, .get_conn_capability_ops = libtypec_dbgfs_get_conn_capability_ops, .get_alternate_modes = libtypec_dbgfs_get_alternate_modes, .get_cam_supported_ops = NULL, .get_current_cam_ops = libtypec_dbfs_get_current_cam_ops, .get_pdos_ops = libtypec_dbgfs_get_pdos_ops, .get_cable_properties_ops = libtypec_dbgfs_get_cable_properties_ops, .get_connector_status_ops = libtypec_dbgs_get_connector_status_ops, .get_pd_message_ops = NULL, .get_bb_status = NULL, .get_bb_data = NULL, .get_lpm_ppm_info_ops = NULL, .set_uor_ops = libtypec_dbgfs_set_uor_ops, .set_pdr_ops = libtypec_dbgfs_set_pdr_ops, }; libtypec-libtypec-0.6.0/libtypec_ops.h000066400000000000000000000060701472033722300200140ustar00rootroot00000000000000/* MIT License Copyright (c) 2022 Rajaram Regupathy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // SPDX-License-Identifier: MIT /** * @file libtypec_ops.h * @author Rajaram Regupathy * @brief Interface "ops" for abstracting backend typec framework * */ #ifndef LIBTYPEC_OPS_H #define LIBTYPEC_OPS_H #include "libtypec.h" #define SYSFS_TYPEC_PATH "/sys/class/typec" #define SYSFS_PSY_PATH "/sys/class/power_supply" #define UCSI_DEBUGFS_PATH "/sys/kernel/debug/usb/ucsi/USBC000:00" /** * @brief * */ extern const struct libtypec_os_backend libtypec_lnx_dbgfs_backend; extern const struct libtypec_os_backend libtypec_lnx_sysfs_backend; extern libtypec_notification_list_t* registered_callbacks[USBC_EVENT_COUNT]; struct libtypec_os_backend { int (*init)(char **); int (*exit)(void); int (*connector_reset)(int conn_num, int rst_type); int (*get_capability_ops)(struct libtypec_capability_data *cap_data); int (*get_conn_capability_ops)(int conn_num, struct libtypec_connector_cap_data *conn_cap_data); int (*get_alternate_modes)(int recipient, int conn_num, struct altmode_data *alt_mode_data); int (*get_cam_supported_ops)(int conn_num, char *cam_data); int (*get_current_cam_ops)(int conn_num, struct libtypec_current_cam *cur_cam); int (*get_pdos_ops)(int conn_num, int partner, int offset, int *num_pdo, int src_snk, int type, struct libtypec_get_pdos *pdo_data); int (*get_cable_properties_ops)(int conn_num, struct libtypec_cable_property *cbl_prop_data); int (*get_connector_status_ops)(int conn_num, struct libtypec_connector_status *conn_sts); int (*get_pd_message_ops)(int recipient, int conn_num, int num_bytes, int resp_type, char *pd_msg_resp); int (*get_bb_status)(unsigned int *num_bb_instance); int (*get_bb_data)(int num_billboards,char* bb_data); void (*monitor_events)(void); int (*get_lpm_ppm_info_ops)(void); int (*set_uor_ops)(unsigned char conn_num, unsigned char uor); int (*set_pdr_ops)(unsigned char conn_num, unsigned char pdr); }; #endif /*LIBTYPEC_OPS_H*/ libtypec-libtypec-0.6.0/libtypec_sysfs_ops.c000066400000000000000000000712021472033722300212350ustar00rootroot00000000000000/* MIT License Copyright (c) 2022 Rajaram Regupathy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // SPDX-License-Identifier: MIT /** * @file libtypec_sysfs_ops.c * @author Rajaram Regupathy * @brief Functions for libtypec sysfs based operations */ /** * required for enalbing nftw(), which is part of SUSv1. */ #define _XOPEN_SOURCE 500 #include "libtypec_ops.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_PORT_STR 7 /* port%d with 7 bit numPorts */ #define MAX_PORT_MODE_STR 7 /* port%d with 5+2 bit numPorts */ #define OS_TYPE_CHROME 1 static int num_bb_if; #define MAX_BB_PATH_STORED 4 char bb_dev_path[MAX_BB_PATH_STORED][512]; static int get_os_type(void) { FILE *fp = fopen("/etc/os-release", "r"); char buf[128], *p = NULL; if (fp) { while (fgets(buf, 128, fp)) { p = strstr(buf, "chrome"); if (p) { fclose(fp); return OS_TYPE_CHROME; } } fclose(fp); } return 0; } static unsigned long get_hex_dword_from_path(char *path) { char buf[64]; unsigned long dword; FILE *fp = fopen(path, "r"); if (fp == NULL) return -1; else { if (fgets(buf, 64, fp) == NULL) { fclose(fp); return -1; } dword = strtol(buf, NULL, 16); fclose(fp); } return dword; } static unsigned long get_dword_from_path(char *path) { char buf[64]; unsigned long dword=0; FILE *fp = fopen(path, "r"); if (fp) { if (fgets(buf, 64, fp) == NULL) { fclose(fp); return -1; } dword = strtoul(buf, NULL, 10); fclose(fp); } return dword; } unsigned char get_opr_mode(char *path) { char buf[64]; char *pEnd; short ret = OPR_MODE_RD_ONLY; /*Rd sink*/ FILE *fp = fopen(path, "r"); if (fp == NULL) return -1; if (fgets(buf, 64, fp) == NULL) { fclose(fp); return -1; } pEnd = strstr(buf, "source"); if (pEnd != NULL) { pEnd = strstr(buf, "sink"); if (pEnd != NULL) ret = OPR_MODE_DRP_ONLY; /*DRP*/ else ret = OPR_MODE_RP_ONLY; /*Rp only*/ } fclose(fp); return ret; } static short get_bcd_from_rev_file(char *path) { char buf[10]; short bcd = 0; FILE *fp = fopen(path, "r"); if (fp) { if (fgets(buf, 10, fp) == NULL) { fclose(fp); return -1; } bcd = ((buf[0] - '0') << 8) | ((buf[2] - '0') << 4); fclose(fp); } return bcd; } static int get_pd_rev(char *path) { char buf[10]; int rev = 0; FILE *fp = fopen(path, "r"); if (fp) { if (fgets(buf, 10, fp) == NULL) { fclose(fp); return -1; } rev = ((buf[0] - '0') << 8 ) | (buf[2] - '0'); fclose(fp); } return rev; } static int get_cable_plug_type(char *path) { char buf[64]; char *pEnd; short ret = PLUG_TYPE_OTH; /*not USB*/ FILE *fp = fopen(path, "r"); if (fp == NULL) return -1; if (fgets(buf, 64, fp) == NULL) { fclose(fp); return -1; } pEnd = strstr(buf, "type-c"); if (pEnd == NULL) { pEnd = strstr(buf, "type-a"); if (pEnd == NULL) { pEnd = strstr(buf, "type-b"); if (pEnd == NULL) { ret = PLUG_TYPE_OTH; } else { ret = PLUG_TYPE_B; } } else ret = PLUG_TYPE_A; } else ret = PLUG_TYPE_C; fclose(fp); return ret; } static int get_cable_type(char *path) { char buf[64]; char *pEnd; short ret = CABLE_TYPE_PASSIVE; FILE *fp = fopen(path, "r"); if (fp == NULL) return -1; if (fgets(buf, 64, fp) == NULL) { fclose(fp); return -1; } pEnd = strstr(buf, "passive"); if (pEnd == NULL) { pEnd = strstr(buf, "active"); if (pEnd == NULL) ret = CABLE_TYPE_UNKNOWN; else ret = CABLE_TYPE_ACTIVE; } fclose(fp); return ret; } static int get_cable_mode_support(char *path) { char buf[64]; short ret; FILE *fp = fopen(path, "r"); if (fp == NULL) return -1; if (fgets(buf, 64, fp) == NULL) { fclose(fp); return -1; } ret = (buf[0] - '0') ? 1 : 0; fclose(fp); return ret; } static unsigned int get_variable_supply_pdo(char *path, int src_snk) { char path_str[512], port_content[1024]; union libtypec_variable_supply_src var_src; unsigned int tmp; var_src.obj_var_sply.type = PDO_VARIABLE; snprintf(port_content, sizeof(port_content), "%s/%s", path, "maximum_voltage"); tmp = get_dword_from_path(port_content); var_src.obj_var_sply.max_volt = tmp/50; snprintf(port_content, sizeof(port_content), "%s/%s", path, "minimum_voltage"); tmp = get_dword_from_path(port_content); var_src.obj_var_sply.min_volt = tmp/50; if(src_snk) { snprintf(port_content, sizeof(port_content), "%s/%s", path, "maximum_current"); tmp = get_dword_from_path(port_content); var_src.obj_var_sply.max_cur = tmp/10; } else { snprintf(port_content, sizeof(port_content), "%s/%s", path, "operational_current"); tmp = get_dword_from_path(port_content); var_src.obj_var_sply.max_cur = tmp/10; } return var_src.variable_supply; } static unsigned int get_battery_supply_pdo(char *path, int src_snk) { char path_str[512], port_content[512 + 512]; union libtypec_battery_supply_src bat_src; unsigned int tmp; bat_src.obj_bat_sply.type = 2; snprintf(port_content, sizeof(port_content), "%s/%s", path, "maximum_voltage"); tmp = get_dword_from_path(port_content); bat_src.obj_bat_sply.max_volt = tmp/50; snprintf(port_content, sizeof(port_content), "%s/%s", path, "minimum_voltage"); tmp = get_dword_from_path(port_content); bat_src.obj_bat_sply.min_volt = tmp/50; if(src_snk) { snprintf(port_content, sizeof(port_content), "%s/%s", path, "maximum_power"); tmp = get_dword_from_path(port_content); bat_src.obj_bat_sply.max_pwr = tmp/250; } else { snprintf(port_content, sizeof(port_content), "%s/%s", path, "operational_power"); tmp = get_dword_from_path(port_content); bat_src.obj_bat_sply.max_pwr = tmp/250; } return bat_src.battery_supply; } static unsigned int get_programmable_supply_pdo(char *path, int src_snk) { char path_str[512], port_content[512 + 512]; union libtypec_pps_src pps_src={0}; unsigned int tmp; pps_src.obj_pps_sply.type = 3; if(src_snk) { snprintf(port_content, sizeof(port_content), "%s/%s", path, "pps_power_limited"); pps_src.obj_pps_sply.pwr_ltd = get_dword_from_path(port_content); } snprintf(port_content, sizeof(port_content), "%s/%s", path, "maximum_voltage"); tmp = get_dword_from_path(port_content); pps_src.obj_pps_sply.max_volt = tmp/100; snprintf(port_content, sizeof(port_content), "%s/%s", path, "minimum_voltage"); tmp = get_dword_from_path(port_content); pps_src.obj_pps_sply.min_volt = tmp/100; snprintf(port_content, sizeof(port_content), "%s/%s", path, "maximum_current"); tmp = get_dword_from_path(port_content); pps_src.obj_pps_sply.max_cur = tmp/50; return pps_src.spr_pps_supply; } static unsigned int get_fixed_supply_pdo(char *path, int src_snk) { char path_str[512], port_content[512 + 512]; union libtypec_fixed_supply_src fxd_src; union libtypec_fixed_supply_snk fxd_snk; unsigned int tmp; memset(&fxd_src, 0, sizeof(fxd_src)); memset(&fxd_snk, 0, sizeof(fxd_snk)); if(src_snk) { fxd_src.obj_fixed_sply.type = 0; snprintf(port_content, sizeof(port_content), "%s/%s", path, "dual_role_power"); fxd_src.obj_fixed_sply.dual_pwr = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "usb_suspend_supported"); fxd_src.obj_fixed_sply.usb_suspend = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "unconstrained_power"); fxd_src.obj_fixed_sply.uncons_pwr = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "usb_communication_capable"); fxd_src.obj_fixed_sply.usb_comm = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "dual_role_data"); fxd_src.obj_fixed_sply.drd = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "unchunked_extended_messages_supported"); fxd_src.obj_fixed_sply.unchunked = get_dword_from_path(port_content); fxd_src.obj_fixed_sply.epr = 0; fxd_src.obj_fixed_sply.peak_cur = 0; snprintf(port_content, sizeof(port_content), "%s/%s", path, "voltage"); tmp = get_dword_from_path(port_content); fxd_src.obj_fixed_sply.volt = tmp/50; snprintf(port_content, sizeof(port_content), "%s/%s", path, "maximum_current"); tmp = get_dword_from_path(port_content); fxd_src.obj_fixed_sply.max_cur = tmp/10; return fxd_src.fixed_supply; } else { fxd_snk.obj_fixed_supply.type = 0; snprintf(port_content, sizeof(port_content), "%s/%s", path, "dual_role_power"); fxd_snk.obj_fixed_supply.drp = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "higher_capability"); fxd_snk.obj_fixed_supply.higher_caps = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "unconstrained_power"); fxd_snk.obj_fixed_supply.uncons_pwr = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "usb_communication_capable"); fxd_snk.obj_fixed_supply.usb_comm_cap = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "dual_role_data"); fxd_snk.obj_fixed_supply.drd = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "fast_role_swap_current"); fxd_snk.obj_fixed_supply.fr_swp = get_dword_from_path(port_content); snprintf(port_content, sizeof(port_content), "%s/%s", path, "voltage"); tmp = get_dword_from_path(port_content); fxd_snk.obj_fixed_supply.volt = tmp/50; snprintf(port_content, sizeof(port_content), "%s/%s", path, "operational_current"); tmp = get_dword_from_path(port_content); fxd_snk.obj_fixed_supply.opr_cur = tmp/10; return fxd_snk.fixed_supply; } } static int count_billbrd_if(const char *usb_path, const struct stat *sb, int typeflag, struct FTW *ftw) { FILE *fd; union { char buf[256]; struct usb_interface_descriptor intf; } u_usb_if; if (typeflag != FTW_F) return 0; fd = fopen(usb_path, "rb"); if (!fd) { return -EIO; } for (;;) { if (fread(u_usb_if.buf, 1, 1, fd) != 1) break; if (fread(u_usb_if.buf + 1, (unsigned char)u_usb_if.buf[0] - 1, 1, fd) != 1) break; if (u_usb_if.intf.bLength == sizeof u_usb_if.intf && u_usb_if.intf.bDescriptorType == USB_DT_INTERFACE && u_usb_if.intf.bNumEndpoints == 0 && u_usb_if.intf.bInterfaceClass == 0x11 && u_usb_if.intf.bInterfaceSubClass == 0 && u_usb_if.intf.bInterfaceProtocol == 0) { if(num_bb_if < MAX_BB_PATH_STORED) { int len = strlen(usb_path); if(len > 512 ) { /*exceeds buffer size*/ fclose(fd); return 0; } strcpy(bb_dev_path[num_bb_if],usb_path); } num_bb_if++; } } fclose(fd); return 0; } static int read_bb_bos_descriptor(int num_billboards,char * bb_data) { int fd1 = open(bb_dev_path[num_billboards-1],O_RDWR ); if(fd1 < 0) return -errno; int len,ret; struct usbdevfs_ctrltransfer msg; msg.bRequestType = 0x80; msg.bRequest = 6; msg.wValue = 15 << 8; msg.wIndex = 0; msg.wLength = 5; msg.data = bb_data; msg.timeout = 5000; ret = ioctl(fd1,USBDEVFS_CONTROL,&msg); len = (bb_data[3] << 8 | bb_data[2]); memset(&msg,0,sizeof(struct usbdevfs_ctrltransfer)); memset(bb_data,0,512); msg.bRequestType = 0x80; msg.bRequest = 6; msg.wValue = 15 << 8; msg.wIndex = 0; msg.wLength = len; msg.data = bb_data; msg.timeout = 5000; ret = ioctl(fd1,USBDEVFS_CONTROL,&msg); close(fd1); return ret; } static int libtypec_sysfs_init(char **session_info) { return 0; } static int libtypec_sysfs_exit(void) { return 0; } static int libtypec_sysfs_get_capability_ops(struct libtypec_capability_data *cap_data) { DIR *typec_path = opendir(SYSFS_TYPEC_PATH), *port_path; struct dirent *typec_entry, *port_entry; int num_ports = 0, num_alt_mode = 0, num_port_alt = 0; char path_str[512], port_content[512 + 64]; if (!typec_path) { printf("opendir typec class failed, %s", SYSFS_TYPEC_PATH); return -1; } while ((typec_entry = readdir(typec_path))) { if (!(strncmp(typec_entry->d_name, "port", 4)) && (strlen(typec_entry->d_name) <= MAX_PORT_STR)) { num_ports++; snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/%s", typec_entry->d_name); /*Scan the port capability*/ port_path = opendir(path_str); num_port_alt = 0; while ((port_entry = readdir(port_path))) { if (!(strncmp(port_entry->d_name, "port", 4)) && (strlen(port_entry->d_name) <= MAX_PORT_MODE_STR)) { num_port_alt++; } } /*Counting different alt modes supported by the PPM*/ if(num_alt_mode < num_port_alt) num_alt_mode = num_port_alt; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "usb_power_delivery_revision"); cap_data->bcdPDVersion = get_bcd_from_rev_file(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "usb_typec_revision"); cap_data->bcdTypeCVersion = get_bcd_from_rev_file(port_content); closedir(port_path); } } cap_data->bNumConnectors = num_ports; cap_data->bNumAltModes = num_alt_mode; closedir(typec_path); return 0; } static int libtypec_sysfs_get_conn_capability_ops(int conn_num, struct libtypec_connector_cap_data *conn_cap_data) { struct stat sb; struct dirent *port_entry; char path_str[512], port_content[512 + 64]; snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d", conn_num); if (lstat(path_str, &sb) == -1) { printf("Incorrect connector number : failed to open, %s\n", path_str); return -1; } snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "power_role"); conn_cap_data->opr_mode.raw_operationmode = get_opr_mode(port_content); if (conn_cap_data->opr_mode.raw_operationmode == OPR_MODE_DRP_ONLY) { conn_cap_data->provider = 1; conn_cap_data->consumer = 1; } else if (conn_cap_data->opr_mode.raw_operationmode == OPR_MODE_RD_ONLY) conn_cap_data->consumer = 1; else conn_cap_data->provider = 1; conn_cap_data->opr_mode.raw_operationmode = 1 << conn_cap_data->opr_mode.raw_operationmode; if (get_os_type() == OS_TYPE_CHROME) { snprintf(port_content, sizeof(port_content), "%s/port%d-partner/%s", path_str, conn_num, "usb_power_delivery_revision"); conn_cap_data->partner_pd_rev = get_pd_rev(port_content); } return 0; } static int libtypec_sysfs_get_alternate_modes(int recipient, int conn_num, struct altmode_data *alt_mode_data) { struct stat sb; int num_alt_mode = 0; char path_str[512], port_content[512 + 64]; snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d", conn_num); if (lstat(path_str, &sb) == -1) { printf("Incorrect connector number : failed to open, %s\n", path_str); return -1; } if (recipient == AM_CONNECTOR) { do { snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d/port%d.%d", conn_num, conn_num, num_alt_mode); if (lstat(path_str, &sb) == -1) break; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "svid"); alt_mode_data[num_alt_mode].svid = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "vdo"); alt_mode_data[num_alt_mode].vdo = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); memset(path_str, 0, sizeof(path_str)); num_alt_mode++; } while (1); } else if (recipient == AM_SOP) { do { snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d/port%d-partner/port%d-partner.%d", conn_num, conn_num, conn_num, num_alt_mode); if (lstat(path_str, &sb) == -1) break; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "svid"); alt_mode_data[num_alt_mode].svid = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "vdo"); alt_mode_data[num_alt_mode].vdo = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); memset(path_str, 0, sizeof(path_str)); num_alt_mode++; } while (1); } else if (recipient == AM_SOP_PR) { do { snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d-cable/port%d-plug0/port%d-plug0.%d", conn_num, conn_num, conn_num, num_alt_mode); if (lstat(path_str, &sb) == -1) break; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "svid"); alt_mode_data[num_alt_mode].svid = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "vdo"); alt_mode_data[num_alt_mode].vdo = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); memset(path_str, 0, sizeof(path_str)); num_alt_mode++; } while (1); } else { } return num_alt_mode; } static int libtypec_sysfs_get_cable_properties_ops(int conn_num, struct libtypec_cable_property *cbl_prop_data) { struct stat sb; struct dirent *port_entry; char path_str[512], port_content[512 + 64]; snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d-cable", conn_num); /* No cable identified or connector number is incorrect */ if (lstat(path_str, &sb) == -1) return -1; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "plug_type"); cbl_prop_data->plug_end_type = get_cable_plug_type(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "type"); cbl_prop_data->cable_type = get_cable_type(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), SYSFS_TYPEC_PATH "/port%d-plug0/%s", conn_num, "number_of_alternate_modes"); cbl_prop_data->mode_support = get_cable_mode_support(port_content); return 0; } static int libtypec_sysfs_get_connector_status_ops(int conn_num, struct libtypec_connector_status *conn_sts) { struct stat sb; struct dirent *port_entry; char path_str[512], port_content[512 + 64]; int ret; snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d", conn_num); if (lstat(path_str, &sb) == -1) { printf("Incorrect connector number : failed to open, %s\n", path_str); return -1; } snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d/port%d-partner", conn_num, conn_num); conn_sts->ConnectStatus = (lstat(path_str, &sb) == -1) ? 0 : 1; snprintf(path_str, sizeof(path_str), SYSFS_PSY_PATH "/ucsi-source-psy-USBC000:00%d", conn_num + 1); if (lstat(path_str, &sb) == -1) { printf("Non UCSI based Type-C connector Class - PSY not supported\n:%s\n", path_str); return 0; } else { snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "online"); ret = get_hex_dword_from_path(port_content); if (ret) { unsigned long cur, volt, op_mw, max_mw; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "current_now"); cur = get_dword_from_path(port_content) / 1000; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "voltage_now"); volt = get_dword_from_path(port_content) / 1000; op_mw = (cur * volt) / (250 * 1000); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "current_max"); cur = get_dword_from_path(port_content) / 1000; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "voltage_max"); volt = get_dword_from_path(port_content) / 1000; max_mw = (cur * volt) / (250 * 1000); conn_sts->RequestDataObject = ((op_mw << 10)) | (max_mw)&0x3FF; } } return 0; } static int libtypec_sysfs_get_discovered_identity_ops(int recipient, int conn_num, char *pd_resp_data) { struct stat sb; char path_str[512], port_content[512 + 64]; union libtypec_discovered_identity *id = (void *)pd_resp_data; snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d", conn_num); if (lstat(path_str, &sb) == -1) { printf("Incorrect connector number : failed to open, %s\n", path_str); return -1; } if (recipient == AM_SOP) { snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d-partner/identity", conn_num); if (lstat(path_str, &sb) == -1) return -1; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "cert_stat"); id->disc_id.cert_stat = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "id_header"); id->disc_id.id_header = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "product"); id->disc_id.product = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "product_type_vdo1"); id->disc_id.product_type_vdo1 = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "product_type_vdo2"); id->disc_id.product_type_vdo2 = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "product_type_vdo3"); id->disc_id.product_type_vdo3 = get_hex_dword_from_path(port_content); } else if (recipient == AM_SOP_PR) { snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d-cable/identity", conn_num); if (lstat(path_str, &sb) == -1) return -1; snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "cert_stat"); id->disc_id.cert_stat = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "id_header"); id->disc_id.id_header = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "product"); id->disc_id.product = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "product_type_vdo1"); id->disc_id.product_type_vdo1 = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "product_type_vdo2"); id->disc_id.product_type_vdo2 = get_hex_dword_from_path(port_content); memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str, "product_type_vdo3"); id->disc_id.product_type_vdo3 = get_hex_dword_from_path(port_content); } return 0; } static int libtypec_sysfs_get_pd_message_ops(int recipient, int conn_num, int num_bytes, int resp_type, char *pd_msg_resp) { if (resp_type == DISCOVER_ID_REQ) { return libtypec_sysfs_get_discovered_identity_ops(recipient, conn_num, pd_msg_resp); } return 0; } static int libtypec_sysfs_get_pdos_ops(int conn_num, int partner, int offset, int *num_pdo, int src_snk, int type, struct libtypec_get_pdos *pdo_data) { int num_pdos_read = 0; char path_str[512], port_content[512 + 256]; DIR *typec_path , *port_path; struct dirent *typec_entry, *port_entry; snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d", conn_num); typec_path = opendir(path_str); if (typec_path == NULL) { printf("Incorrect connector number : failed to open, %s\n", path_str); return -1; } closedir(typec_path); if (partner == 0) { if(src_snk) snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d/usb_power_delivery/source-capabilities", conn_num); else snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d/usb_power_delivery/sink-capabilities", conn_num); } else { if(src_snk) snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d-partner/usb_power_delivery/source-capabilities", conn_num); else snprintf(path_str, sizeof(path_str), SYSFS_TYPEC_PATH "/port%d-partner/usb_power_delivery/sink-capabilities", conn_num); } typec_path = opendir(path_str); if (typec_path == NULL) goto finalize; /*No PDOs*/ while ((typec_entry = readdir(typec_path))) { memset(port_content, 0, sizeof(port_content)); snprintf(port_content, sizeof(port_content), "%s/%s", path_str,typec_entry->d_name); if(strstr(typec_entry->d_name, "fixed")) { pdo_data->pdo[num_pdos_read++] = get_fixed_supply_pdo(port_content,src_snk); } else if(strstr(typec_entry->d_name, "variable")) { pdo_data->pdo[num_pdos_read++] = get_variable_supply_pdo(port_content,src_snk); } else if(strstr(typec_entry->d_name, "battery")) { pdo_data->pdo[num_pdos_read++] = get_battery_supply_pdo(port_content,src_snk); } else if(strstr(typec_entry->d_name, "programmable")) { pdo_data->pdo[num_pdos_read++] = get_programmable_supply_pdo(port_content,src_snk); } } closedir(typec_path); finalize: *num_pdo = num_pdos_read; return num_pdos_read; } static int libtypec_sysfs_get_bb_status(unsigned int *num_bb_instance) { num_bb_if = 0; int fd_limit = getdtablesize() - 5; if (nftw ("/dev/bus/usb/", count_billbrd_if, fd_limit, 0) != 0) { return -EIO; } *num_bb_instance = num_bb_if; return 0; } static int libtypec_sysfs_get_bb_data(int num_billboards,char* bb_data) { int ret = 0, count; ret = libtypec_sysfs_get_bb_status(&count); if(num_billboards >count) return -EINVAL; ret = read_bb_bos_descriptor(num_billboards,bb_data); return ret; } void libtypec_lnx_monitor_udev_events() { struct udev *udev = udev_new(); struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev"); udev_monitor_filter_add_match_subsystem_devtype(mon, "typec", NULL); udev_monitor_enable_receiving(mon); while (1) { struct udev_device *dev = udev_monitor_receive_device(mon); if (dev) { const char *subsystem = udev_device_get_subsystem(dev); enum usb_typec_event event; if (strcmp(subsystem, "typec") == 0) { // typec event const char *action = udev_device_get_action(dev); if (strcmp(action, "add") == 0) { event = USBC_DEVICE_CONNECTED; } else if (strcmp(action, "remove") == 0) { event = USBC_DEVICE_DISCONNECTED; } } udev_device_unref(dev); // call all callbacks for this event libtypec_notification_list_t* node = registered_callbacks[event]; while (node) { node->cb_func(event, node->data); node = node->next; } } } udev_unref(udev); } libtypec_notification_list_t* registered_callbacks[USBC_EVENT_COUNT] = {0}; const struct libtypec_os_backend libtypec_lnx_sysfs_backend = { .init = libtypec_sysfs_init, .exit = libtypec_sysfs_exit, .get_capability_ops = libtypec_sysfs_get_capability_ops, .get_conn_capability_ops = libtypec_sysfs_get_conn_capability_ops, .get_alternate_modes = libtypec_sysfs_get_alternate_modes, .get_cam_supported_ops = NULL, .get_current_cam_ops = NULL, .get_pdos_ops = libtypec_sysfs_get_pdos_ops, .get_cable_properties_ops = libtypec_sysfs_get_cable_properties_ops, .get_connector_status_ops = libtypec_sysfs_get_connector_status_ops, .get_pd_message_ops = libtypec_sysfs_get_pd_message_ops, .get_bb_status = libtypec_sysfs_get_bb_status, .get_bb_data = libtypec_sysfs_get_bb_data, .monitor_events = libtypec_lnx_monitor_udev_events }; libtypec-libtypec-0.6.0/meson.build000066400000000000000000000014101472033722300173020ustar00rootroot00000000000000project('libtypec','c', license: 'MIT', version: '0.6.0', default_options : [ 'warning_level=0']) conf_data = configuration_data() split = meson.project_version().split('.') conf_data.set('libtypec_VERSION_MAJOR', split[0]) conf_data.set('libtypec_VERSION_MINOR', split[1]) conf_data.set('libtypec_VERSION_PATCH', split[2]) libudev_dep = dependency('libudev', required: true) configure_file(input : 'libtypec_config.h.in', output : 'libtypec_config.h', configuration : conf_data) library('typec', 'libtypec.c', 'libtypec_sysfs_ops.c', 'libtypec_dbgfs_ops.c', version : meson.project_version(), soversion : '0', dependencies: libudev_dep, install: true, ) install_headers( 'libtypec.h', meson.current_build_dir() + '/libtypec_config.h', install_dir: 'include' )libtypec-libtypec-0.6.0/utils/000077500000000000000000000000001472033722300163045ustar00rootroot00000000000000libtypec-libtypec-0.6.0/utils/CMakeLists.txt000066400000000000000000000027771472033722300210610ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.16.3) project(libtypec_utils VERSION 0.6.0) configure_file(libtypec_utils_config.h.in libtypec_utils_config.h) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 REQUIRED gtk+-3.0) include_directories(${GTK3_INCLUDE_DIRS}) link_directories(${GTK3_LIBRARY_DIRS}) add_definitions(${GTK3_CFLAGS_OTHER}) add_executable(lstypec lstypec.c names.c) target_include_directories(lstypec PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(lstypec PUBLIC libtypec udev) add_executable(usbcview usbcview.c names.c) target_include_directories(usbcview PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(usbcview PUBLIC libtypec udev ${GTK3_LIBRARIES}) add_executable(typecstatus typecstatus.c names.c) target_link_libraries(typecstatus PUBLIC libtypec udev) add_executable(ucsicontrol ucsicontrol.c names.c) target_link_libraries(ucsicontrol PUBLIC libtypec udev) option(LIBTYPEC_STRICT_CFLAGS "Compile for strict warnings" ON) if(LIBTYPEC_STRICT_CFLAGS) target_compile_options(lstypec PRIVATE -g -O2 -fstack-protector-strong -Wformat=1 -Werror=format-security -Wdate-time -fasynchronous-unwind-tables -D_FORTIFY_SOURCE=2) target_compile_options(typecstatus PRIVATE -g -O2 -fstack-protector-strong -Wformat=1 -Werror=format-security -Wdate-time -fasynchronous-unwind-tables -D_FORTIFY_SOURCE=2) target_compile_options(ucsicontrol PRIVATE -g -O2 -fstack-protector-strong -Wformat=1 -Werror=format-security -Wdate-time -fasynchronous-unwind-tables -D_FORTIFY_SOURCE=2) endif() libtypec-libtypec-0.6.0/utils/libtypec_utils_config.h.in000066400000000000000000000002671472033722300234470ustar00rootroot00000000000000#define LSTYPEC_MAJOR_VERSION @libtypec_utils_VERSION_MAJOR@ #define LSTYPEC_MINOR_VERSION @libtypec_utils_VERSION_MINOR@ #define LSTYPEC_PATCH_VERSION @libtypec_utils_VERSION_PATCH@ libtypec-libtypec-0.6.0/utils/lstypec.c000066400000000000000000001243011472033722300201340ustar00rootroot00000000000000/* Copyright (c) 2021-2022 by Rajaram Regupathy, rajaram.regupathy@gmail.com 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; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. (See the full license text in the LICENSES directory) */ // SPDX-License-Identifier: GPL-2.0-only /** * @file lstypec.c * @author Rajaram Regupathy * @coauthor Jameson Thies * @brief Implements listing of typec port and port partner details * */ #include #include #include #include #include #include #include "../libtypec.h" #include "lstypec.h" #include "names.h" #include "libtypec_utils_config.h" struct altmode_data am_data[64]; char *session_info[LIBTYPEC_SESSION_MAX_INDEX]; typedef struct { int verbose; int help; int port_num; int ppm; int partner_num; int cb_num; int am; int backend; // 0 for sysfs, 1 for debugfs } CmdArgs; CmdArgs lstypec_args; struct option long_options[] = { {"verbose", no_argument, &lstypec_args.verbose, 1}, {"help", no_argument, &lstypec_args.help, 1}, {"[p]ort", required_argument, NULL, 'p'}, {"ppm", no_argument, &lstypec_args.ppm, 1}, {"partner", required_argument, NULL, 'r'}, {"cb", required_argument, NULL, 'c'}, {"am", no_argument, &lstypec_args.am, 1}, {"backend", required_argument, NULL, 'b'}, {0, 0, 0, 0} }; void print_usage() { printf("-v display verbose info\n"); printf("-h display usage\n"); printf("-p [num] prints details specific of a port number indicated in num\n"); printf("-ppm print only Platform Policy Manager details only\n"); printf("-partner [num] print port partner details of the port represented in num\n"); printf("-cb [num] print cable details from the particular port\n"); printf("-am print alternate mode details of port/partner/cable\n"); printf("-backend [string] where string is debugfs or sysfs sets, convert it to int. backend to be used by libtypec\n"); } void parse_args(int argc, char *argv[]) { int opt; // Initialize the CmdArgs structure with default values lstypec_args.verbose = 0; lstypec_args.help = 0; lstypec_args.port_num = -1; // -1 indicates no port number specified lstypec_args.ppm = 0; lstypec_args.partner_num = -1; // -1 indicates no partner number specified lstypec_args.cb_num = -1; // -1 indicates no cable number specified lstypec_args.am = -1; // -1 indicates no alternate mode number specified lstypec_args.backend = 0; // default backend is sysfs for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-v") == 0) { lstypec_args.verbose = 1; } else if (strcmp(argv[i], "-h") == 0) { lstypec_args.help = 1; print_usage(); exit(EXIT_SUCCESS); } else if (strcmp(argv[i], "-p") == 0) { if (i+1 >= argc || !isdigit(argv[i+1][0])) { printf("Error: -p requires a number argument\n"); exit(EXIT_FAILURE); } lstypec_args.port_num = atoi(argv[++i]); } else if (strcmp(argv[i], "-ppm") == 0) { lstypec_args.ppm = 1; } else if (strcmp(argv[i], "-partner") == 0) { if (i+1 >= argc || !isdigit(argv[i+1][0])) { printf("Error: -partner requires a number argument\n"); exit(EXIT_FAILURE); } lstypec_args.partner_num = atoi(argv[++i]); } else if (strcmp(argv[i], "-cb") == 0) { if (i+1 >= argc || !isdigit(argv[i+1][0])) { printf("Error: -cb requires a number argument\n"); exit(EXIT_FAILURE); } lstypec_args.cb_num = atoi(argv[++i]); } else if (strcmp(argv[i], "-am") == 0) { lstypec_args.am = 1 ; } else if (strcmp(argv[i], "-backend") == 0) { if (i+1 >= argc || (strcmp(argv[i+1], "debugfs") != 0 && strcmp(argv[i+1], "sysfs") != 0)) { printf("Error: -backend requires a string argument (debugfs or sysfs)\n"); exit(EXIT_FAILURE); } if (strcmp(argv[++i], "debugfs") == 0) { lstypec_args.backend = LIBTYPEC_BACKEND_DBGFS; } else if (strcmp(argv[i], "sysfs") == 0) { lstypec_args.backend = LIBTYPEC_BACKEND_SYSFS; } } else { printf("Error: Unknown argument %s\n", argv[i]); exit(EXIT_FAILURE); } } } enum product_type get_cable_product_type(short rev, uint32_t id) { // Decode cable product type if (rev == 0x200) { // USB PD 2.0 cable if ((id & pd_ufp_product_type_mask) == pd2p0_passive_cable) return product_type_pd2p0_passive_cable; else if ((id & pd_ufp_product_type_mask) == pd2p0_active_cable) return product_type_pd2p0_active_cable; else return product_type_other; } else if (rev == 0x300) { // USB PD 3.0 cable if ((id & pd_ufp_product_type_mask) == pd3p0_passive_cable) return product_type_pd3p0_passive_cable; else if ((id & pd_ufp_product_type_mask) == pd3p0_active_cable) return product_type_pd3p0_active_cable; else return product_type_other; } else if (rev == 0x310) { // USB PD 3.1 cable if ((id & pd_ufp_product_type_mask) == pd3p1_passive_cable) return product_type_pd3p1_passive_cable; else if ((id & pd_ufp_product_type_mask) == pd3p1_active_cable) return product_type_pd3p1_active_cable; else if ((id & pd_ufp_product_type_mask) == pd3p1_vpd) return product_type_pd3p1_vpd; else return product_type_other; } return product_type_other; } enum product_type get_partner_product_type(short rev, uint32_t id) { // Decode partner product type if (rev == 0x200) { // USB PD 2.0 partner if ((id & pd_ufp_product_type_mask) == pd2p0_ama) return product_type_pd2p0_ama; else return product_type_other; } else if (rev == 0x300) { // USB PD 3.0 partner char ufp_supported = 0; if ((id & pd_ufp_product_type_mask) == pd3p0_hub) ufp_supported = 1; else if ((id & pd_ufp_product_type_mask) == pd3p0_peripheral) ufp_supported = 1; else if ((id & pd_ufp_product_type_mask) == pd3p0_ama) return product_type_pd3p0_ama; else if ((id & pd_ufp_product_type_mask) == pd3p0_vpd) return product_type_pd3p0_vpd; char dfp_supported = 0; if ((id & pd_dfp_product_type_mask) == pd3p0_dfp_hub) dfp_supported = 1; else if ((id & pd_dfp_product_type_mask) == pd3p0_dfp_host) dfp_supported = 1; else if ((id & pd_dfp_product_type_mask) == pd3p0_power_brick) dfp_supported = 1; if (ufp_supported && dfp_supported) return product_type_pd3p0_drd; else if (ufp_supported) return product_type_pd3p0_ufp; else if (dfp_supported) return product_type_pd3p0_dfp; else return product_type_other; } else if (rev == 0x310) { // USB PD 3.1 partner char ufp_supported = 0; if ((id & pd_ufp_product_type_mask) == pd3p1_hub) ufp_supported = 1; else if ((id & pd_ufp_product_type_mask) == pd3p1_peripheral) ufp_supported = 1; char dfp_supported = 0; if ((id & pd_dfp_product_type_mask) == pd3p1_dfp_hub) dfp_supported = 1; else if ((id & pd_dfp_product_type_mask) == pd3p1_dfp_host) dfp_supported = 1; else if ((id & pd_dfp_product_type_mask) == pd3p1_power_brick) dfp_supported = 1; if (ufp_supported && dfp_supported) return product_type_pd3p1_drd; else if (ufp_supported) return product_type_pd3p1_ufp; else if (dfp_supported) return product_type_pd3p1_dfp; else return product_type_other; } return product_type_other; } void print_vdo(uint32_t vdo, int num_fields, const struct vdo_field vdo_fields[], const char *vdo_field_desc[][MAX_FIELDS]) { for (int i = 0; i < num_fields; i++) { if (!vdo_fields[i].print) continue; uint32_t field = (vdo >> vdo_fields[i].index) & vdo_fields[i].mask; printf(" %s: %*d", vdo_fields[i].name, FIELD_WIDTH(MAX_FIELD_LENGTH - ((int) strlen(vdo_fields[i].name))), ((vdo >> vdo_fields[i].index) & vdo_fields[i].mask)); if (vdo_field_desc[i][0] != NULL) { // decode field printf(" (%s)\n", vdo_field_desc[i][field]); } else if (strcmp(vdo_fields[i].name, "USB Vendor ID") == 0) { // decode vendor id char vendor_str[128]; uint16_t svid = ((vdo >> vdo_fields[i].index) & vdo_fields[i].mask); get_vendor_string(vendor_str, sizeof(vendor_str), svid); printf(" (%s)\n", (vendor_str[0] == '\0' ? "unknown" : vendor_str)); } else { // No decoding printf("\n"); } } } /** * Prints the session information for the lstypec library. * The session information includes the library version, operating system, kernel version, * and library operations. */ void print_session_info() { printf("lstypec %d.%d.%d Session Info\n", LSTYPEC_MAJOR_VERSION, LSTYPEC_MINOR_VERSION, LSTYPEC_PATCH_VERSION); printf(" Using %s\n", session_info[LIBTYPEC_VERSION_INDEX]); printf(" %s with Kernel %s\n", session_info[LIBTYPEC_OS_INDEX], session_info[LIBTYPEC_KERNEL_INDEX]); printf(" libtypec using %s\n", session_info[LIBTYPEC_OPS_INDEX]); } /** * Prints the USB-C Platform Policy Manager capability data. * * @param ppm_data The structure containing the capability data. */ void print_ppm_capability(struct libtypec_capability_data ppm_data) { printf("\nUSB-C Platform Policy Manager Capability\n"); printf(" Number of Connectors: %x\n", ppm_data.bNumConnectors); printf(" Number of Alternate Modes: %x\n", ppm_data.bNumAltModes); printf(" USB Power Delivery Revision: %x.%x\n", (ppm_data.bcdPDVersion >> 8) & 0XFF, (ppm_data.bcdPDVersion) & 0XFF); printf(" USB Type-C Revision: %x.%x\n",(ppm_data.bcdTypeCVersion >> 8) & 0XFF, (ppm_data.bcdTypeCVersion) & 0XFF); printf(" USB BC Revision: %x.%x\n", (ppm_data.bcdBCVersion >> 8) & 0XFF, (ppm_data.bcdBCVersion) & 0XFF); } void print_conn_capability(struct libtypec_connector_cap_data conn_data) { char *opr_mode_str[] = {"Rp Only", "Rd Only", "DRP(Rp/Rd)", "Analog Audio", "Debug Accessory", "USB2", "USB3", "Alternate Mode"}; printf(" Operation Modes Supported: 0x%02x ", conn_data.opr_mode.raw_operationmode); for (int i = 0; i < sizeof(opr_mode_str) / sizeof(opr_mode_str[0]); i++) { if (conn_data.opr_mode.raw_operationmode & (1 << i)) { printf("(%s)", opr_mode_str[i]); } } printf("\n"); } void print_cable_prop(struct libtypec_cable_property cable_prop, int conn_num) { char *cable_type[] = {"Passive", "Active", "Unknown"}; char *cable_plug_type[] = {"USB Type A", "USB Type B", "USB Type C", "Non-USB Type", "Unknown"}; printf(" Cable Property in Port %d:\n", conn_num); printf(" Cable Type: %s\n", cable_type[cable_prop.cable_type]); printf(" Cable Plug Type: %s\n", cable_plug_type[cable_prop.plug_end_type]); } void get_svid_string(uint32_t svid, char* str) { switch (svid) { case 0xFF01: strcpy(str, "Display Alternate Mode"); break; case 0x8087: strcpy(str, "TBT Alternate Mode"); break; default: get_vendor_string(str, sizeof(str), svid); break; } } void print_alternate_mode_data(int recipient, uint32_t id_header, int num_modes, struct altmode_data *am_data) { char vendor_id[128]; if (recipient == AM_CONNECTOR) { for (int i = 0; i < num_modes; i++) { get_svid_string(am_data[i].svid,vendor_id); printf(" Local Mode %d:\n", i); printf(" SVID: 0x%04x (%s)\n", am_data[i].svid,vendor_id); printf(" VDO: 0x%08x\n", am_data[i].vdo); if (lstypec_args.verbose) { switch(am_data[i].svid){ case 0x8087: print_vdo(am_data[i].vdo, 7, tbt3_sop_fields, tbt3_sop_field_desc); break; case 0xff01: print_vdo(am_data[i].vdo, 7, dp_alt_mode_partner_fields, dp_alt_mode_partner_field_desc); break; default: get_vendor_string(vendor_id, sizeof(vendor_id), am_data[i].svid); printf(" VDO Decoding not supported for 0x%04x (%s)\n", am_data[i].svid, (vendor_id[0] == '\0' ? "unknown" : vendor_id)); break; } } } } if (recipient == AM_SOP) { for (int i = 0; i < num_modes; i++) { get_svid_string(am_data[i].svid,vendor_id); printf(" Partner Mode %d:\n", i); printf(" SVID: 0x%04x (%s)\n", am_data[i].svid,vendor_id); printf(" VDO: 0x%08x\n", am_data[i].vdo); if (lstypec_args.verbose) { switch(am_data[i].svid){ case 0x8087: print_vdo(am_data[i].vdo, 7, tbt3_sop_fields, tbt3_sop_field_desc); break; case 0xff01: print_vdo(am_data[i].vdo, 7, dp_alt_mode_partner_fields, dp_alt_mode_partner_field_desc); break; default: get_vendor_string(vendor_id, sizeof(vendor_id), am_data[i].svid); printf(" VDO Decoding not supported for 0x%04x (%s)\n", am_data[i].svid, (vendor_id[0] == '\0' ? "unknown" : vendor_id)); break; } } } } if (recipient == AM_SOP_PR) { for (int i = 0; i < num_modes; i++) { get_svid_string(am_data[i].svid,vendor_id); printf(" Cable Plug Modes %d:\n", i); printf(" SVID: 0x%04x (%s)\n", am_data[i].svid,vendor_id); printf(" VDO: 0x%08x\n", am_data[i].vdo); if (lstypec_args.verbose) { switch(am_data[i].svid){ case 0x8087: print_vdo(am_data[i].vdo, 7, tbt3_sop_pr_fields, tbt3_sop_pr_field_desc); break; case 0xff01: if ((id_header & ACTIVE_CABLE_MASK) == ACTIVE_CABLE_COMP) { print_vdo(am_data[i].vdo, 7, dp_alt_mode_active_cable_fields, dp_alt_mode_active_cable_field_desc); } else { get_vendor_string(vendor_id, sizeof(vendor_id), am_data[i].svid); printf(" SVID Decoding not supported for 0x%04x (%s)\n", am_data[i].svid, (vendor_id[0] == '\0' ? "unknown" : vendor_id)); } break; default: get_vendor_string(vendor_id, sizeof(vendor_id), am_data[i].svid); printf(" SVID Decoding not supported for 0x%04x (%s)\n", am_data[i].svid, (vendor_id[0] == '\0' ? "unknown" : vendor_id)); break; } } } } } void print_identity_data(int recipient, union libtypec_discovered_identity id, struct libtypec_connector_cap_data conn_data) { union id_header id_hdr_val; id_hdr_val.id_hdr = id.disc_id.id_header; if (recipient == AM_SOP) { printf(" Partner Identity :\n"); // Partner ID if (lstypec_args.verbose) { // ID Header/Cert Stat/Product are base on revision switch (conn_data.partner_pd_rev) { case 0x200: printf(" ID Header: 0x%08x\n", id.disc_id.id_header); print_vdo(((uint32_t) id.disc_id.id_header), 6, pd2p0_partner_id_header_fields, pd2p0_partner_id_header_field_desc); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); print_vdo(((uint32_t) id.disc_id.cert_stat), 1, pd2p0_cert_stat_fields, pd2p0_cert_stat_field_desc); printf(" Product: 0x%08x\n", id.disc_id.product); print_vdo(((uint32_t) id.disc_id.product), 2, pd2p0_product_fields, pd2p0_product_field_desc); break; case 0x300: printf(" ID Header: 0x%08x\n", id.disc_id.id_header); print_vdo(((uint32_t) id.disc_id.id_header), 7, pd3p0_partner_id_header_fields, pd3p0_partner_id_header_field_desc); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); print_vdo(((uint32_t) id.disc_id.cert_stat), 1, pd3p0_cert_stat_fields, pd3p0_cert_stat_field_desc); printf(" Product: 0x%08x\n", id.disc_id.product); print_vdo(((uint32_t) id.disc_id.product), 2, pd3p0_product_fields, pd3p0_product_field_desc); break; case 0x310: printf(" ID Header: 0x%08x\n", id.disc_id.id_header); print_vdo(((uint32_t) id.disc_id.id_header), 8, pd3p1_partner_id_header_fields, pd3p1_partner_id_header_field_desc); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); print_vdo(((uint32_t) id.disc_id.cert_stat), 1, pd3p1_cert_stat_fields, pd3p1_cert_stat_field_desc); printf(" Product: 0x%08x\n", id.disc_id.product); print_vdo(((uint32_t) id.disc_id.product), 2, pd3p1_product_fields, pd3p1_product_field_desc); break; default: printf(" ID Header: 0x%08x\n", id.disc_id.id_header); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); printf(" Product: 0x%08x\n", id.disc_id.product); break; } //Product Type VDOs based on product type enum product_type partner_product_type = get_partner_product_type(conn_data.partner_pd_rev, ((uint32_t) id.disc_id.id_header)); switch (partner_product_type) { case product_type_pd2p0_ama: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 11, pd2p0_ama_fields, pd2p0_ama_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p0_ama: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 8, pd3p0_ama_fields, pd3p0_ama_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p0_vpd: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 10, pd3p0_vpd_fields, pd3p0_vpd_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p0_ufp: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 6, pd3p0_ufp_vdo1_fields, pd3p0_ufp_vdo1_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); print_vdo(((uint32_t) id.disc_id.product_type_vdo2), 6, pd3p0_ufp_vdo2_fields, pd3p0_ufp_vdo2_field_desc); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p0_dfp: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 5, pd3p0_dfp_fields, pd3p0_dfp_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p0_drd: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 6, pd3p0_ufp_vdo1_fields, pd3p0_ufp_vdo1_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); print_vdo(((uint32_t) id.disc_id.product_type_vdo2), 6, pd3p0_ufp_vdo2_fields, pd3p0_ufp_vdo2_field_desc); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); print_vdo(((uint32_t) id.disc_id.product_type_vdo3), 5, pd3p0_dfp_fields, pd3p0_dfp_field_desc); break; case product_type_pd3p1_ufp: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 10, pd3p1_ufp_fields, pd3p1_ufp_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p1_dfp: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 6, pd3p1_dfp_fields, pd3p1_dfp_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p1_drd: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 10, pd3p1_ufp_fields, pd3p1_ufp_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); print_vdo(((uint32_t) id.disc_id.product_type_vdo3), 6, pd3p1_dfp_fields, pd3p1_dfp_field_desc); break; default: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; } } else { printf(" ID Header: 0x%08x\n", id.disc_id.id_header); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); printf(" Product: 0x%08x\n", id.disc_id.product); printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); } } else if (recipient == AM_SOP_PR) { printf(" Cable Identity :\n"); // Partner ID if (lstypec_args.verbose) { // ID Header/Cert Stat/Product are base on revision switch (conn_data.partner_pd_rev) { case 0x200: printf(" ID Header: 0x%08x\n", id.disc_id.id_header); print_vdo(((uint32_t) id.disc_id.id_header), 6, pd2p0_cable_id_header_fields, pd2p0_cable_id_header_field_desc); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); print_vdo(((uint32_t) id.disc_id.cert_stat), 1, pd2p0_cert_stat_fields, pd2p0_cert_stat_field_desc); printf(" Product: 0x%08x\n", id.disc_id.product); print_vdo(((uint32_t) id.disc_id.product), 2, pd2p0_product_fields, pd2p0_product_field_desc); break; case 0x300: printf(" ID Header: 0x%08x\n", id.disc_id.id_header); print_vdo(((uint32_t) id.disc_id.id_header), 7, pd3p0_cable_id_header_fields, pd3p0_cable_id_header_field_desc); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); print_vdo(((uint32_t) id.disc_id.cert_stat), 1, pd3p0_cert_stat_fields, pd3p0_cert_stat_field_desc); printf(" Product: 0x%08x\n", id.disc_id.product); print_vdo(((uint32_t) id.disc_id.product), 2, pd3p0_product_fields, pd3p0_product_field_desc); break; case 0x310: printf(" ID Header: 0x%08x\n", id.disc_id.id_header); print_vdo(((uint32_t) id.disc_id.id_header), 8, pd3p1_cable_id_header_fields, pd3p1_cable_id_header_field_desc); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); print_vdo(((uint32_t) id.disc_id.cert_stat), 1, pd3p1_cert_stat_fields, pd3p1_cert_stat_field_desc); printf(" Product: 0x%08x\n", id.disc_id.product); print_vdo(((uint32_t) id.disc_id.product), 2, pd3p1_product_fields, pd3p1_product_field_desc); break; default: printf(" ID Header: 0x%08x\n", id.disc_id.id_header); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); printf(" Product: 0x%08x\n", id.disc_id.product); break; } //Product Type VDOs based on product type enum product_type cable_product_type = get_cable_product_type(conn_data.partner_pd_rev, ((uint32_t) id.disc_id.id_header)); switch (cable_product_type) { case product_type_pd2p0_passive_cable: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 15, pd2p0_passive_cable_fields, pd2p0_passive_cable_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd2p0_active_cable: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 15, pd2p0_active_cable_fields, pd2p0_active_cable_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p0_passive_cable: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 13, pd3p0_passive_cable_fields, pd3p0_passive_cable_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p0_active_cable: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 15, pd3p0_active_cable_vdo1_fields, pd3p0_active_cable_vdo1_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); print_vdo(((uint32_t) id.disc_id.product_type_vdo2), 15, pd3p0_active_cable_vdo2_fields, pd3p0_active_cable_vdo2_field_desc); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p1_passive_cable: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 13, pd3p1_passive_cable_fields, pd3p1_passive_cable_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p1_active_cable: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 15, pd3p1_active_cable_vdo1_fields, pd3p1_active_cable_vdo1_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); print_vdo(((uint32_t) id.disc_id.product_type_vdo2), 15, pd3p1_active_cable_vdo2_fields, pd3p1_active_cable_vdo2_field_desc); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; case product_type_pd3p1_vpd: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); print_vdo(((uint32_t) id.disc_id.product_type_vdo1), 10, pd3p1_vpd_fields, pd3p0_vpd_field_desc); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; default: printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); break; } } else { printf(" ID Header: 0x%08x\n", id.disc_id.id_header); printf(" Cert Stat: 0x%08x\n", id.disc_id.cert_stat); printf(" Product: 0x%08x\n", id.disc_id.product); printf(" Product VDO 1: 0x%08x\n", id.disc_id.product_type_vdo1); printf(" Product VDO 2: 0x%08x\n", id.disc_id.product_type_vdo2); printf(" Product VDO 3: 0x%08x\n", id.disc_id.product_type_vdo3); } } } void print_source_pdo_data(struct libtypec_get_pdos *pdo_data, int num_pdos, int revision) { for (int i = 0; i < num_pdos; i++) { printf(" PDO%d: 0x%08x\n", i+1, pdo_data->pdo[i]); if (lstypec_args.verbose) { if (revision == 0x200) { switch((pdo_data->pdo[i] >> 30)) { case PDO_FIXED: print_vdo(pdo_data->pdo[i], 10, pd2p0_fixed_supply_src_fields, pd2p0_fixed_supply_src_field_desc); break; case PDO_BATTERY: print_vdo(pdo_data->pdo[i], 4, pd2p0_battery_supply_src_fields, pd2p0_battery_supply_src_field_desc); break; case PDO_VARIABLE: print_vdo(pdo_data->pdo[i], 4, pd2p0_variable_supply_src_fields, pd2p0_variable_supply_src_field_desc); break; } } else if (revision == 0x300) { switch((pdo_data->pdo[i] >> 30)) { case PDO_FIXED: print_vdo(pdo_data->pdo[i], 11, pd3p0_fixed_supply_src_fields, pd3p0_fixed_supply_src_field_desc); break; case PDO_BATTERY: print_vdo(pdo_data->pdo[i], 4, pd3p0_battery_supply_src_fields, pd3p0_battery_supply_src_field_desc); break; case PDO_VARIABLE: print_vdo(pdo_data->pdo[i], 4, pd3p0_variable_supply_src_fields, pd3p0_variable_supply_src_field_desc); break; case PDO_AUGMENTED: print_vdo(pdo_data->pdo[i], 9, pd3p0_pps_apdo_src_fields, pd3p0_pps_apdo_src_field_desc); break; } } else if (revision == 0x310) { switch((pdo_data->pdo[i] >> 30)) { case PDO_FIXED: print_vdo(pdo_data->pdo[i], 12, pd3p1_fixed_supply_src_fields, pd3p1_fixed_supply_src_field_desc); break; case PDO_BATTERY: print_vdo(pdo_data->pdo[i], 4, pd3p1_battery_supply_src_fields, pd3p1_battery_supply_src_field_desc); break; case PDO_VARIABLE: print_vdo(pdo_data->pdo[i], 4, pd3p1_variable_supply_src_fields, pd3p1_variable_supply_src_field_desc); break; case PDO_AUGMENTED: print_vdo(pdo_data->pdo[i], 9, pd3p1_pps_apdo_src_fields, pd3p1_pps_apdo_src_field_desc); break; } } } } } void print_sink_pdo_data(struct libtypec_get_pdos *pdo_data, int num_pdos, int revision) { for (int i = 0; i < num_pdos; i++) { printf(" PDO%d: 0x%08x\n", i+1, pdo_data->pdo[i]); if (lstypec_args.verbose) { if (revision == 0x200) { switch((pdo_data->pdo[i] >> 30)) { case PDO_FIXED: print_vdo(pdo_data->pdo[i], 9, pd2p0_fixed_supply_snk_fields, pd2p0_fixed_supply_snk_field_desc); break; case PDO_BATTERY: print_vdo(pdo_data->pdo[i], 4, pd2p0_battery_supply_snk_fields, pd2p0_battery_supply_snk_field_desc); break; case PDO_VARIABLE: print_vdo(pdo_data->pdo[i], 4, pd2p0_variable_supply_snk_fields, pd2p0_variable_supply_snk_field_desc); break; } } else if (revision == 0x300) { switch((pdo_data->pdo[i] >> 30)) { case PDO_FIXED: print_vdo(pdo_data->pdo[i], 10, pd3p0_fixed_supply_snk_fields, pd3p0_fixed_supply_snk_field_desc); break; case PDO_BATTERY: print_vdo(pdo_data->pdo[i], 4, pd3p0_battery_supply_snk_fields, pd3p0_battery_supply_snk_field_desc); break; case PDO_VARIABLE: print_vdo(pdo_data->pdo[i], 4, pd3p0_variable_supply_snk_fields, pd3p0_variable_supply_snk_field_desc); break; case PDO_AUGMENTED: print_vdo(pdo_data->pdo[i], 8, pd3p0_pps_apdo_snk_fields, pd3p0_pps_apdo_snk_field_desc); break; } } else if (revision == 0x310) { switch((pdo_data->pdo[i] >> 30)) { case PDO_FIXED: print_vdo(pdo_data->pdo[i], 10, pd3p1_fixed_supply_snk_fields, pd3p1_fixed_supply_snk_field_desc); break; case PDO_BATTERY: print_vdo(pdo_data->pdo[i], 4, pd3p1_battery_supply_snk_fields, pd3p1_battery_supply_snk_field_desc); break; case PDO_VARIABLE: print_vdo(pdo_data->pdo[i], 4, pd3p1_variable_supply_snk_fields, pd3p1_variable_supply_snk_field_desc); break; case PDO_AUGMENTED: print_vdo(pdo_data->pdo[i], 8, pd3p1_pps_apdo_snk_fields, pd3p1_pps_apdo_snk_field_desc); break; } } } } } void lstypec_print(char *val, int type) { if (type == LSTYPEC_ERROR) { printf("lstypec - ERROR - %s\n", val); exit(1); } else printf("lstypec - INFO - %s\n", val); } void print_capabilities_partner(int i) { int ret, opt, num_modes, num_pdos; // Partner num_modes = libtypec_get_alternate_modes(AM_SOP, i, am_data); if (num_modes >= 0) print_alternate_mode_data(AM_SOP, id.disc_id.id_header, num_modes, am_data); ret = libtypec_get_pd_message(AM_SOP, i, 24, DISCOVER_ID_REQ, id.buf_disc_id); if (ret >= 0) { print_identity_data(AM_SOP, id, conn_data); } pdo_data = malloc(sizeof(int)*8); ret = libtypec_get_pdos(i, 1, 0, &num_pdos, 1, 0, pdo_data); if (ret > 0) { printf(" Partner PDO Data (Source):\n"); print_source_pdo_data(pdo_data, num_pdos, conn_data.partner_pd_rev); } ret = libtypec_get_pdos(i, 1, 0, &num_pdos, 0, 0, pdo_data); if (ret > 0) { printf(" Partner PDO Data (Sink):\n"); print_sink_pdo_data(pdo_data, num_pdos, conn_data.partner_pd_rev); } free(pdo_data); } void print_capabilities_cable(int i) { int ret, opt, num_modes, num_pdos; // Resetting port properties cable_prop.cable_type = CABLE_TYPE_UNKNOWN; cable_prop.plug_end_type = PLUG_TYPE_OTH; // Cable Properties ret = libtypec_get_cable_properties(i, &cable_prop); if (ret >= 0) print_cable_prop(cable_prop, i); // Cable num_modes = libtypec_get_alternate_modes(AM_SOP_PR, i, am_data); if (num_modes >= 0) print_alternate_mode_data(AM_SOP_PR, id.disc_id.id_header, num_modes, am_data); ret = libtypec_get_pd_message(AM_SOP_PR, i, 24, DISCOVER_ID_REQ, id.buf_disc_id); if (ret >= 0) { print_identity_data(AM_SOP_PR, id, conn_data); } } void print_capabilities_port(int i) { int ret, opt, num_modes, num_pdos; // Connector Capabilities printf("\nConnector %d Capability/Status\n", i); libtypec_get_conn_capability(i, &conn_data); print_conn_capability(conn_data); // Connector PDOs pdo_data = malloc(sizeof(int)*8); ret = libtypec_get_pdos(i, 0, 0, &num_pdos, 1, 0, pdo_data); if (ret > 0) { printf(" Connector PDO Data (Source):\n"); print_source_pdo_data(pdo_data, num_pdos, get_cap_data.bcdPDVersion); } else printf(" Connector PDO Data (Source) returned : %d\n", ret); ret = libtypec_get_pdos(i, 0, 0, &num_pdos, 0, 0, pdo_data); if (ret > 0) { printf(" Connector PDO Data (Sink):\n"); print_sink_pdo_data(pdo_data, num_pdos, get_cap_data.bcdPDVersion); } else printf(" Connector PDO Data (Source) returned : %d\n", ret); free(pdo_data); // Supported Alternate Modes printf(" Alternate Modes Supported:\n"); num_modes = libtypec_get_alternate_modes(AM_CONNECTOR, i, am_data); if (num_modes > 0) print_alternate_mode_data(AM_CONNECTOR, 0x0, num_modes, am_data); else printf(" No Local Modes listed with typec class\n"); } void lstypec_print_am() { int ret; if(lstypec_args.backend == LIBTYPEC_BACKEND_DBGFS) ret = libtypec_init(session_info,LIBTYPEC_BACKEND_DBGFS); else // Initialize libtypec by default with sysfs and print session info ret = libtypec_init(session_info,LIBTYPEC_BACKEND_SYSFS); if (ret < 0) lstypec_print("Failed in Initializing libtypec", LSTYPEC_ERROR); // PPM Capabilities ret = libtypec_get_capability(&get_cap_data); if (ret < 0) lstypec_print("Failed in Get Capability", LSTYPEC_ERROR); if(lstypec_args.port_num != -1) { if(lstypec_args.port_num >= get_cap_data.bNumConnectors) { printf("lstypec - ERROR - %s, Provide one less than Num Ports %d \n", "Port number out of range",get_cap_data.bNumConnectors); exit(1); } int num_modes = libtypec_get_alternate_modes(AM_CONNECTOR, lstypec_args.port_num, am_data); if (num_modes > 0) print_alternate_mode_data(AM_CONNECTOR, 0x0, num_modes, am_data); else printf(" No Local Modes listed with typec class\n"); } else if(lstypec_args.partner_num != -1) { if(lstypec_args.partner_num >= get_cap_data.bNumConnectors) { printf("lstypec - ERROR - %s, Provide one less than Num Ports %d \n", "Port number out of range",get_cap_data.bNumConnectors); exit(1); } // Partner int num_modes = libtypec_get_alternate_modes(AM_SOP, lstypec_args.partner_num, am_data); if (num_modes >= 0) print_alternate_mode_data(AM_SOP, id.disc_id.id_header, num_modes, am_data); ret = libtypec_get_pd_message(AM_SOP, lstypec_args.partner_num, 24, DISCOVER_ID_REQ, id.buf_disc_id); if (ret >= 0) { print_identity_data(AM_SOP, id, conn_data); } } else if(lstypec_args.cb_num != -1) { if(lstypec_args.cb_num >= get_cap_data.bNumConnectors) { printf("lstypec - ERROR - %s, Provide one less than Num Ports %d \n", "Port number out of range",get_cap_data.bNumConnectors); exit(1); } // Cable int num_modes = libtypec_get_alternate_modes(AM_SOP_PR, lstypec_args.cb_num, am_data); if (num_modes >= 0) print_alternate_mode_data(AM_SOP_PR, id.disc_id.id_header, num_modes, am_data); } else { printf("lstypec - ERROR - %s\n", "Provide Port/Partner/Cable number for Alternate Mode Information"); exit(1); } printf("\n"); } void lstypec_print_partner() { int ret; if(lstypec_args.backend == LIBTYPEC_BACKEND_DBGFS) ret = libtypec_init(session_info,LIBTYPEC_BACKEND_DBGFS); else // Initialize libtypec by default with sysfs and print session info ret = libtypec_init(session_info,LIBTYPEC_BACKEND_SYSFS); if (ret < 0) lstypec_print("Failed in Initializing libtypec", LSTYPEC_ERROR); // PPM Capabilities ret = libtypec_get_capability(&get_cap_data); if (ret < 0) lstypec_print("Failed in Get Capability", LSTYPEC_ERROR); if(lstypec_args.partner_num >= get_cap_data.bNumConnectors) { printf("lstypec - ERROR - %s, Provide one less than Num Ports %d \n", "Port number out of range",get_cap_data.bNumConnectors); exit(1); } print_capabilities_partner(lstypec_args.partner_num); } void lstypec_print_cable() { int ret; if(lstypec_args.backend == LIBTYPEC_BACKEND_DBGFS) ret = libtypec_init(session_info,LIBTYPEC_BACKEND_DBGFS); else // Initialize libtypec by default with sysfs and print session info ret = libtypec_init(session_info,LIBTYPEC_BACKEND_SYSFS); if (ret < 0) lstypec_print("Failed in Initializing libtypec", LSTYPEC_ERROR); // PPM Capabilities ret = libtypec_get_capability(&get_cap_data); if (ret < 0) lstypec_print("Failed in Get Capability", LSTYPEC_ERROR); if(lstypec_args.cb_num >= get_cap_data.bNumConnectors) { printf("lstypec - ERROR - %s, Provide one less than Num Ports %d \n", "Port number out of range",get_cap_data.bNumConnectors); exit(1); } print_capabilities_cable(lstypec_args.cb_num); } void lstypec_print_port() { int ret; if(lstypec_args.backend == LIBTYPEC_BACKEND_DBGFS) ret = libtypec_init(session_info,LIBTYPEC_BACKEND_DBGFS); else // Initialize libtypec by default with sysfs and print session info ret = libtypec_init(session_info,LIBTYPEC_BACKEND_SYSFS); if (ret < 0) lstypec_print("Failed in Initializing libtypec", LSTYPEC_ERROR); // PPM Capabilities ret = libtypec_get_capability(&get_cap_data); if (ret < 0) lstypec_print("Failed in Get Capability", LSTYPEC_ERROR); if(lstypec_args.port_num >= get_cap_data.bNumConnectors) { printf("lstypec - ERROR - %s, Provide one less than Num Ports %d \n", "Port number out of range",get_cap_data.bNumConnectors); exit(1); } print_capabilities_port(lstypec_args.port_num); } void lstypec_default_verbose() { int ret; if(lstypec_args.backend == LIBTYPEC_BACKEND_DBGFS) ret = libtypec_init(session_info,LIBTYPEC_BACKEND_DBGFS); else // Initialize libtypec by default with sysfs and print session info ret = libtypec_init(session_info,LIBTYPEC_BACKEND_SYSFS); if (ret < 0) lstypec_print("Failed in Initializing libtypec", LSTYPEC_ERROR); print_session_info(); // PPM Capabilities ret = libtypec_get_capability(&get_cap_data); if (ret < 0) lstypec_print("Failed in Get Capability", LSTYPEC_ERROR); print_ppm_capability(get_cap_data); for (int i = 0; i < get_cap_data.bNumConnectors; i++) { print_capabilities_port(i); print_capabilities_cable(i); print_capabilities_partner(i); } printf("\n"); } int main(int argc, char *argv[]) { parse_args(argc, argv); names_init(); if (lstypec_args.port_num != -1) { lstypec_print_port(); goto cleanup; } if (lstypec_args.ppm) { int ret; if(lstypec_args.backend == LIBTYPEC_BACKEND_DBGFS) ret = libtypec_init(session_info,LIBTYPEC_BACKEND_DBGFS); else // Initialize libtypec by default with sysfs and print session info ret = libtypec_init(session_info,LIBTYPEC_BACKEND_SYSFS); if (ret < 0) lstypec_print("Failed in Initializing libtypec", LSTYPEC_ERROR); print_session_info(); // PPM Capabilities ret = libtypec_get_capability(&get_cap_data); if (ret < 0) lstypec_print("Failed in Get Capability", LSTYPEC_ERROR); print_ppm_capability(get_cap_data); goto cleanup; } if(lstypec_args.am != -1) { lstypec_print_am(); goto cleanup; } if (lstypec_args.partner_num != -1) { lstypec_print_partner(); goto cleanup; } if (lstypec_args.cb_num != -1) { lstypec_print_cable(); goto cleanup; } lstypec_default_verbose(); cleanup: names_exit(); } libtypec-libtypec-0.6.0/utils/lstypec.h000066400000000000000000001253061472033722300201470ustar00rootroot00000000000000/* Copyright (c) 2021-2022 by Rajaram Regupathy, rajaram.regupathy@gmail.com 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; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. (See the full license text in the LICENSES directory) */ // SPDX-License-Identifier: GPL-2.0-only /** * @file lstypec.c * @author Rajaram Regupathy * @coauthor Jameson Thies * @brief Implements listing of typec port and port partner details * */ #include #include #include #include "../libtypec.h" #include "names.h" #define LSTYPEC_ERROR 1 #define LSTYPEC_INFO 2 #define MAX_FIELDS 16 #define ACTIVE_CABLE_MASK 0x38000000 #define ACTIVE_CABLE_COMP 0x20000000 //used for spacing #define MAX_FIELD_LENGTH 32 #define FIELD_WIDTH(n) n > 0 ? n : 0 enum product_type { product_type_other = 0, product_type_pd2p0_passive_cable = 1, product_type_pd2p0_active_cable = 2, product_type_pd2p0_ama = 3, product_type_pd3p0_passive_cable = 4, product_type_pd3p0_active_cable = 5, product_type_pd3p0_ama = 6, product_type_pd3p0_vpd = 7, product_type_pd3p0_ufp = 8, product_type_pd3p0_dfp = 9, product_type_pd3p0_drd = 10, product_type_pd3p1_passive_cable = 11, product_type_pd3p1_active_cable = 12, product_type_pd3p1_vpd = 13, product_type_pd3p1_ufp = 14, product_type_pd3p1_dfp = 15, product_type_pd3p1_drd = 16, }; struct vdo_field{ char *name; uint8_t print; uint8_t index; uint32_t mask; }; union id_header { uint32_t id_hdr; struct { unsigned usb_vendor_id : 16; unsigned reserved : 10; unsigned modal_operation : 1; unsigned product_type : 3; unsigned usb_capable_device : 1; unsigned usb_capable_host : 1; } id_hdr_pd2p0; struct { unsigned usb_vendor_id : 16; unsigned reserved : 7; unsigned prd_type_dfp : 3; unsigned modal_operation : 1; unsigned product_type : 3; unsigned usb_capable_device : 1; unsigned usb_capable_host : 1; } id_hdr_pd3p0; struct { unsigned usb_vendor_id : 16; unsigned reserved : 5; unsigned connector_type : 2; unsigned prd_type_dfp : 3; unsigned modal_operation : 1; unsigned product_type : 3; unsigned usb_capable_device : 1; unsigned usb_capable_host : 1; } id_hdr_pd3p1; }; union passive_vdo_1 { uint32_t psv_vdo_1; struct { unsigned usb_signalling : 3; unsigned reserved3 : 1; unsigned vbus_thru_cbl : 1; unsigned vbus_handling : 2; unsigned dir_support : 4; unsigned termination_type : 2; unsigned latency : 4; unsigned reserved17 : 1; unsigned plug_type : 2; unsigned reserved20 : 4; unsigned fw_ver : 4; unsigned hw_ver : 4; } psv_vdo1_pd2p0; struct { unsigned usb_signalling : 3; unsigned reserved3 : 2; unsigned vbus_current_cap : 2; unsigned reserved7 : 2; unsigned vbus_max_volt : 2; unsigned termination_type : 2; unsigned latency : 4; unsigned reserved17 : 1; unsigned plug_type : 2; unsigned reserved20 : 1; unsigned vdo_version : 3; unsigned fw_ver : 4; unsigned hw_ver : 4; } psv_vdo1_pd3p0; struct { unsigned usb_signalling : 3; unsigned reserved3 : 2; unsigned vbus_current_cap : 2; unsigned reserved7 : 2; unsigned vbus_max_volt : 2; unsigned termination_type : 2; unsigned latency : 4; unsigned epr_mode : 1; unsigned plug_type : 2; unsigned reserved20 : 1; unsigned vdo_version : 3; unsigned fw_ver : 4; unsigned hw_ver : 4; } psv_vdo1_pd3p1; }; //Constants // ID Header product type masks const int pd_ufp_product_type_mask = 0x38000000; const int pd_dfp_product_type_mask = 0x03800000; const int pd2p0_passive_cable = 0x20000000; const int pd2p0_active_cable = 0x18000000; const int pd2p0_ama = 0x28000000; const int pd3p0_passive_cable = 0x18000000; const int pd3p0_active_cable = 0x20000000; const int pd3p0_ama = 0x28000000; const int pd3p0_vpd = 0x30000000; const int pd3p0_hub = 0x08000000; const int pd3p0_peripheral = 0x10000000; const int pd3p0_dfp_hub = 0x00800000; const int pd3p0_dfp_host = 0x01000000; const int pd3p0_power_brick = 0x01800000; const int pd3p1_passive_cable = 0x18000000; const int pd3p1_active_cable = 0x20000000; const int pd3p1_vpd = 0x30000000; const int pd3p1_hub = 0x08000000; const int pd3p1_peripheral = 0x10000000; const int pd3p1_dfp_hub = 0x00800000; const int pd3p1_dfp_host = 0x01000000; const int pd3p1_power_brick = 0x01800000; // USB PD 2.0 ID Header VDO (Section 6.4.4.3.1.1) const struct vdo_field pd2p0_partner_id_header_fields[] = { {"USB Vendor ID", 1, 0, 0xffff}, {"Reserved", 0, 16, 0x3ff}, {"Modal Operation Supported", 1, 26, 0x1}, {"Produt Type (UFP)", 1, 27, 0x7}, {"USB Capable as a Device", 1, 30, 0x1}, {"USB Capable as a Host", 1, 31, 0x1}, }; const char *pd2p0_partner_id_header_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {"No", "Yes"}, {"Undefined", "PDUSB Hub", "PDUSB Peripheral", "Reserved", "Reserved", "Alternate Mode Adapter", "Reserved", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, }; const struct vdo_field pd2p0_cable_id_header_fields[] = { {"USB Vendor ID", 1, 0, 0xffff}, {"Reserved", 0, 16, 0x3ff}, {"Modal Operation Supported", 1, 26, 0x1}, {"Produt Type (UFP)", 1, 27, 0x7}, {"USB Capable as a Device", 1, 30, 0x1}, {"USB Capable as a Host", 1, 31, 0x1}, }; const char *pd2p0_cable_id_header_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {"No", "Yes"}, {"Undefined", "Reserved", "Reserved", "Passive Cable", "Active Cable", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, }; // USB PD 2.0 Cert Stat VDO (Section 6.4.4.3.1.2) const struct vdo_field pd2p0_cert_stat_fields[] = { {"XID", 1, 0, 0xffffffff}, }; const char *pd2p0_cert_stat_field_desc[][MAX_FIELDS] = { {NULL}, }; // USB PD 2.0 Product VDO (Section 6.4.4.3.1.3) const struct vdo_field pd2p0_product_fields[] = { {"bcdDevice", 1, 0, 0xffff}, {"USB Product ID", 1, 16, 0xffff}, }; const char *pd2p0_product_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, }; // USB PD 2.0 Passive Cable VDO (Section 6.4.4.3.1.4.1) const struct vdo_field pd2p0_passive_cable_fields[] = { {"USB SuperSpeed Support", 1, 0, 0x7}, {"Reserved", 0, 3, 0x1}, {"Vbus Through Cable", 1, 4, 0x1}, {"Vbus Current Handling", 1, 5, 0x3}, {"SSRX2 Support", 1, 7, 0x1}, {"SSRX1 Support", 1, 8, 0x1}, {"SSTX2 Support", 1, 9, 0x1}, {"SSTX1 Support", 1, 10, 0x1}, {"Cable Termination Type", 1, 11, 0x3}, {"Cable Latency", 1, 13, 0xf}, {"Reserved", 0, 17, 0x1}, {"USB Type-C plug to", 1, 18, 0x3}, {"Reserved", 0, 20, 0xf}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd2p0_passive_cable_field_desc[][MAX_FIELDS] = { {"USB 2.0 Only", "USB 3.1 Gen1", "USB 3.1 Gen1 and Gen2", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"No", "Yes"}, {"Reserved", "3A", "5A", "Reserved"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {"Vconn Not Required", "Vconn Required", "Reserved", "Reserved"}, {"Reserved", "<10ns (~1m)", "10ns to 20ns (~2m)", "20ns to 30ns (~3m)", "30ns to 40ns (~4m)", "40ns to 50ns (~5m)", "50ns to 60ns (~6m)", "60ns to 70ns (~7m)", " 70ns (>~7m)", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"USB Type-A", "USB Type-B", "USB Type-C", "Captive"}, {NULL}, {NULL}, {NULL}, }; // USB PD 2.0 Active Cable VDO (Section 6.4.4.3.1.4.2) const struct vdo_field pd2p0_active_cable_fields[] = { {"USB SuperSpeed Support", 1, 0, 0x7}, {"SOP'' Controller Present", 1, 3, 0x1}, {"Vbus Through Cable", 1, 4, 0x1}, {"Vbus Current Handling", 1, 5, 0x3}, {"SSRX2 Support", 1, 7, 0x1}, {"SSRX1 Support", 1, 8, 0x1}, {"SSTX2 Support", 1, 9, 0x1}, {"SSTX1 Support", 1, 10, 0x1}, {"Cable Termination Type", 1, 11, 0x3}, {"Cable Latency", 1, 13, 0xf}, {"Reserved", 0, 17, 0x1}, {"USB Type-C plug to", 1, 18, 0x3}, {"Reserved", 0, 20, 0xf}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd2p0_active_cable_field_desc[][MAX_FIELDS] = { {"USB 2.0 Only", "USB 3.1 Gen1", "USB 3.1 Gen1 and Gen2", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"No", "Yes"}, {"Reserved", "3A", "5A", "Reserved"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {"Vconn Not Required", "Vconn Required", "Reserved", "Reserved"}, {"Reserved", "<10ns (~1m)", "10ns to 20ns (~2m)", "20ns to 30ns (~3m)", "30ns to 40ns (~4m)", "40ns to 50ns (~5m)", "50ns to 60ns (~6m)", "60ns to 70ns (~7m)", " 70ns (>~7m)", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"USB Type-A", "USB Type-B", "USB Type-C", "Captive"}, {NULL}, {NULL}, {NULL}, }; // USB PD 2.0 AMA VDO (Section 6.4.4.3.1.5) const struct vdo_field pd2p0_ama_fields[] = { {"USB SuperSpeed Support", 1, 0, 0x7}, {"Vbus required", 1, 3, 0x1}, {"Vconn required", 1, 4, 0x1}, {"Vconn power", 1, 5, 0x7}, {"SSRX2 Support", 1, 8, 0x1}, {"SSRX1 Support", 1, 9, 0x1}, {"SSTX2 Support", 1, 10, 0x1}, {"SSTX1 Support", 1, 11, 0x1}, {"Reserved", 0, 12, 0xfff}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd2p0_ama_field_desc[][MAX_FIELDS] = { {"USB 2.0 Only", "USB 3.1 Gen1", "USB 3.1 Gen1 and Gen2", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, {"1W", "1.5W", "2W", "3W", "4W", "5W", "6W", "Reserved"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {"Fixed", "Configurable"}, {NULL}, {NULL}, {NULL}, }; // USB PD 2.0 Fixed Supply PDO - Source (Section 6.4.1.2.3) const struct vdo_field pd2p0_fixed_supply_src_fields[] = { {"Maximum Current in 10mA units", 1, 0, 0x3ff}, {"Voltage in 50mV units", 1, 10, 0x3ff}, {"Peak Current", 1, 20, 0x3}, {"Reserved", 0, 22, 0x7}, {"Dual-Role Data", 1, 25, 0x1}, {"USB Communications Capable", 1, 26, 0x1}, {"Unconstrained Power", 1, 27, 0x1}, {"USB Suspend Supported", 1, 28, 0x1}, {"Daul-Role Power", 1, 29, 0x1}, {"Fixed supply", 1, 30, 0x3}, }; const char *pd2p0_fixed_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 2.0 Variable Supply PDO - Source (Section 6.4.1.2.4) const struct vdo_field pd2p0_variable_supply_src_fields[] = { {"Maximum Current in 10mA units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Variable Supply", 1, 30, 0x3}, }; const char *pd2p0_variable_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 2.0 Battery Supply PDO - Source (Section 6.4.1.2.5) const struct vdo_field pd2p0_battery_supply_src_fields[] = { {"Maximum Allowable Power in 250mW units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Battery", 1, 30, 0x3}, }; const char *pd2p0_battery_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 2.0 Fixed Supply PDO - Sink (Section 6.4.1.3.1) const struct vdo_field pd2p0_fixed_supply_snk_fields[] = { {"Operational Current in 10mA units", 1, 0, 0x3ff}, {"Voltage in 50mV units", 1, 10, 0x3ff}, {"Reserved", 0, 20, 0x1f}, {"Dual-Role Data", 1, 25, 0x1}, {"USB Communications Capable", 1, 26, 0x1}, {"Unconstrained Power", 1, 27, 0x1}, {"Higher Capability", 1, 28, 0x1}, {"Daul-Role Power", 1, 29, 0x1}, {"Fixed supply", 1, 30, 0x3}, }; const char *pd2p0_fixed_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 2.0 Variable Supply PDO - Sink (Section 6.4.1.3.2) const struct vdo_field pd2p0_variable_supply_snk_fields[] = { {"Operational Current in 10mA units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Variable Supply", 1, 30, 0x3}, }; const char *pd2p0_variable_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 2.0 Battery Supply PDO - Sink (Section 6.4.1.3.3) const struct vdo_field pd2p0_battery_supply_snk_fields[] = { {"Operational Power in 250mW units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Battery", 1, 30, 0x3}, }; const char *pd2p0_battery_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 ID Header VDO (Section 6.4.4.3.1.1) const struct vdo_field pd3p0_partner_id_header_fields[] = { {"USB Vendor ID", 1, 0, 0xffff}, {"Reserved", 0, 16, 0x3f}, {"Product Type (DFP)", 1, 23, 0x7}, {"Modal Operation Supported", 1, 26, 0x1}, {"Product Type (UFP)", 1, 27, 0x7}, {"USB Capable as a Device", 1, 30, 0x1}, {"USB Capable as a Host", 1, 31, 0x1}, }; const char *pd3p0_partner_id_header_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {"Undefined", "PDUSB Hub", "PDUSB Host", "Power Brick", "Alternate Mode Controller", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"Undefined", "PDUSB Hub", "PDUSB Peripheral", "PSD", "Reserved", "Alternate Mode Adapter", "Vconn Powered USB Device", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, }; const struct vdo_field pd3p0_cable_id_header_fields[] = { {"USB Vendor ID", 1, 0, 0xffff}, {"Reserved", 0, 16, 0x3f}, {"Product Type (DFP)", 0, 23, 0x7}, {"Modal Operation Supported", 1, 26, 0x1}, {"Product Type (Cable Plug)", 1, 27, 0x7}, {"USB Capable as a Device", 1, 30, 0x1}, {"USB Capable as a Host", 1, 31, 0x1}, }; const char *pd3p0_cable_id_header_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {"No", "Yes"}, {"Undefined", "Reserved", "Reserved", "Passive Cable", "Active Cable", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, }; // USB PD 3.0 Cert Stat VDO (Section 6.4.4.3.1.2) const struct vdo_field pd3p0_cert_stat_fields[] = { {"XID", 1, 0, 0xffffffff}, }; const char *pd3p0_cert_stat_field_desc[][MAX_FIELDS] = { {NULL}, }; // USB PD 3.0 Product VDO (Section 6.4.4.3.1.3) const struct vdo_field pd3p0_product_fields[] = { {"bcdDevice", 1, 0, 0xffff}, {"USB Product ID", 1, 16, 0xffff}, }; const char *pd3p0_product_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, }; // USB PD 3.0 Passive Cable VDO (Section 6.4.4.3.1.6) const struct vdo_field pd3p0_passive_cable_fields[] = { {"USB Highest Speed", 1, 0, 0x7}, {"Reserved", 0, 3, 0x3}, {"Vbus Current Handling", 1, 5, 0x3}, {"Reserved", 0, 7, 0x3}, {"Maximum Vbus Voltage", 1, 9, 0x3}, {"Cable Termination Type", 1, 11, 0x3}, {"Cable Latency", 1, 13, 0xf}, {"Reserved", 0, 17, 0x1}, {"Connector Type", 1, 18, 0x3}, {"Reserved", 0, 20, 0x1}, {"VDO version", 1, 21, 0x7}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd3p0_passive_cable_field_desc[][MAX_FIELDS] = { {"USB 2.0 Only", "USB 3.2 Gen1", "USB 3.2/USB4 Gen2", "USB4 Gen3", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"Reserved", "3A", "5A", "Reserved"}, {NULL}, {"20V", "30V", "40V", "50V"}, {"Vconn Not Required", "Vconn Required", "Reserved", "Reserved"}, {"Reserved", "<10ns (~1m)", "10ns to 20ns (~2m)", "20ns to 30ns (~3m)", "30ns to 40ns (~4m)", "40ns to 50ns (~5m)", "50ns to 60ns (~6m)", "60ns to 70ns (~7m)", " 70ns (>~7m)", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"Reserved", "Reserved", "USB Type-C", "Captive"}, {NULL}, {"Version 1.0", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {NULL}, }; // USB PD 3.0 Active Cable VDO1/VDO2 (Section 6.4.4.3.1.7) const struct vdo_field pd3p0_active_cable_vdo1_fields[] = { {"USB Highest Speed", 1, 0, 0x7}, {"SOP'' Controller Present", 1, 3, 0x1}, {"Vbus Through Cable", 1, 4, 0x1}, {"Vbus Current Handling", 1, 5, 0x3}, {"SBU Type", 1, 7, 0x1}, {"SBU Supported", 1, 8, 0x1}, {"Maximum Vbus Voltage", 1, 9, 0x3}, {"Cable Termination Type", 1, 11, 0x3}, {"Cable Latency", 1, 13, 0xf}, {"Reserved", 0, 17, 0x1}, {"Connector Type", 1, 18, 0x3}, {"Reserved", 0, 20, 0x1}, {"VDO version", 1, 21, 0x7}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd3p0_active_cable_vdo1_field_desc[][MAX_FIELDS] = { {"USB 2.0 Only", "USB 3.2 Gen1", "USB 3.2/USB4 Gen2", "USB4 Gen3", "Reserved", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, {"USB Type-C Default Current", "3A", "5A", "Reserved"}, {"SBU is passive", "SBU is active"}, {"SBU connections supported", "SBU connections are not supported"}, {"20V", "30V", "40V", "50V"}, {"Reserved", "Reserved", "One end active, one end passive, Vconn required", "Both ends active, Vconn required"}, {"Reserved", "<10ns (~1m)", "10ns to 20ns (~2m)", "20ns to 30ns (~3m)", "30ns to 40ns (~4m)", "40ns to 50ns (~5m)", "50ns to 60ns (~6m)", "60ns to 70ns (~7m)", "1000b –1000ns (~100m)", "1001b –2000ns (~200m)", "1010b – 3000ns (~300m)", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"Reserved", "Reserved", "USB Type-C", "Captive"}, {NULL}, {"Reserved", "Reserved", "Reserved", "Version 1.3", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {NULL}, }; const struct vdo_field pd3p0_active_cable_vdo2_fields[] = { {"USB Gen", 1, 0, 0x1}, {"Reserved", 0, 1, 0x1}, {"Optically Isolated Active Cable", 1, 2, 0x1}, {"USB Lanes Supported", 1, 3, 0x1}, {"USB 3.2 Supported", 1, 4, 0x1}, {"USB 2.0 Supported", 1, 5, 0x1}, {"USB 2.0 Hub Hops Consumed", 1, 6, 0x3}, {"USB4 Supported", 1, 8, 0x1}, {"Active element", 1, 9, 0x1}, {"Physical connection", 1, 10, 0x1}, {"U3 to U0 transition mode", 1, 11, 0x1}, {"U3/Cld Power", 1, 12, 0x7}, {"Reserved", 0, 15, 0x1}, {"Shutdown Temperature", 1, 16, 0xff}, {"Maximum Operating Temperature", 1, 24, 0xff}, }; const char *pd3p0_active_cable_vdo2_field_desc[][MAX_FIELDS] = { {"Gen 1", "Gen 2 or higher"}, {NULL}, {"No", "Yes"}, {"One Lane", "Two Lanes"}, {"USB 3.2 SuperSpeed supported", "USB 3.2 SuperSpeed not supported"}, {"USB 2.0 supported", "USB 2.0 not supported"}, {NULL}, {"USB4 Supported", "USB4 Not Supported"}, {"Active Redriver", "Active Retimer"}, {"Copper", "Optical"}, {"U3 to U0 direct", "U3 to U0 through U35"}, {">10mW", "5-10mW", "1-5mW", "0.5-1mW", "0.2-0.5mW", "50-200uW", "<50uW", "Reserved"}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 AMA VDO (Section 6.4.4.3.1.8) const struct vdo_field pd3p0_ama_fields[] = { {"USB Highest Speed", 1, 0, 0x7}, {"Vbus required", 1, 3, 0x1}, {"Vconn required", 1, 4, 0x1}, {"Vconn power", 1, 5, 0x7}, {"Reserved", 0, 8, 0x1fff}, {"VDO Version", 1, 21, 0x7}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd3p0_ama_field_desc[][MAX_FIELDS] = { {"USB 2.0 only", "USB 3.2 Gen1 and USB 2.0", "USB 3.2 Gen1, Gen2 and USB 2.0", "billboard only", "Reserved", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, {"1W", "1.5W", "2W", "3W", "4W", "5W", "6W", "Reserved"}, {NULL}, {"Version 1.0", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {NULL}, }; // USB PD 3.0 VPD VDO (Section 6.4.4.3.1.9) const struct vdo_field pd3p0_vpd_fields[] = { {"Charge Through Support", 1, 0, 0x1}, {"Ground Impedance", 1, 1, 0x3f}, {"Vbus Impedance", 1, 7, 0x3f}, {"Reserved", 0, 13, 0x3}, {"Charge Through Current Support", 1, 14, 0x1}, {"Maximum Vbus Voltage", 1, 15, 0x3}, {"Reserved", 0, 17, 0xf}, {"VDO Version", 1, 21, 0x7}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd3p0_vpd_field_desc[][MAX_FIELDS] = { {"No","Yes"}, {NULL}, {NULL}, {NULL}, {"3A capable", "5A capable"}, {"20V", "30V", "40V", "50V"}, {NULL}, {"Version 1.0", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {NULL}, }; // USB PD 3.0 UFP VDO1/VDO2 (Section 6.4.4.3.1.4) const struct vdo_field pd3p0_ufp_vdo1_fields[] = { {"USB Highest Speed", 1, 0, 0x7}, {"Alternate Modes", 1, 3, 0x7}, {"Reserved", 0, 6, 0x3ffff}, {"Device Capability", 1, 24, 0xf}, {"Reserved", 0, 28, 0x1}, {"UFP VDO Version", 1, 29, 0x7}, }; const char *pd3p0_ufp_vdo1_field_desc[][MAX_FIELDS] = { {"USB 2.0 only", "USB 3.2 Gen1", "USB 3.2/USB4 Gen2", "USB4 Gen3", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {NULL}, {NULL}, {NULL}, {"Version 1.0", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, }; const struct vdo_field pd3p0_ufp_vdo2_fields[] = { {"USB3 Max Power", 1, 0, 0x7f}, {"USB3 Min Power", 1, 7, 0x7f}, {"Reserved", 0, 14, 0x3}, {"USB4 Max Power", 1, 16, 0x7f}, {"USB4 Min Power", 1, 23, 0x7f}, {"Reserved", 0, 30, 0x3}, }; const char *pd3p0_ufp_vdo2_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 DFP VDO (Section 6.4.4.3.1.5) const struct vdo_field pd3p0_dfp_fields[] = { {"Port Number", 1, 0, 0x1f}, {"Reserved", 0, 5, 0x7ffff}, {"Host Capability", 1, 24, 0x7}, {"Reserved", 0, 27, 0x3}, {"DFP VDO Version", 1, 29, 0x7}, }; const char *pd3p0_dfp_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {"Version 1.0", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, }; // USB PD 3.0 Fixed Supply PDO - Source (Section 6.4.1.2.2) const struct vdo_field pd3p0_fixed_supply_src_fields[] = { {"Maximum Current in 10mA units", 1, 0, 0x3ff}, {"Voltage in 50mV units", 1, 10, 0x3ff}, {"Peak Current", 1, 20, 0x3}, {"Reserved", 0, 22, 0x3}, {"Unchunked Extended Messages Supported", 0, 24, 0x1}, {"Dual-Role Data", 1, 25, 0x1}, {"USB Communications Capable", 1, 26, 0x1}, {"Unconstrained Power", 1, 27, 0x1}, {"USB Suspend Supported", 1, 28, 0x1}, {"Daul-Role Power", 1, 29, 0x1}, {"Fixed supply", 1, 30, 0x3}, }; const char *pd3p0_fixed_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 Variable Supply PDO - Source (Section 6.4.1.2.3) const struct vdo_field pd3p0_variable_supply_src_fields[] = { {"Maximum Current in 10mA units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Variable Supply", 1, 30, 0x3}, }; const char *pd3p0_variable_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 Battery Supply PDO - Source (Section 6.4.1.2.4) const struct vdo_field pd3p0_battery_supply_src_fields[] = { {"Maximum Allowable Power in 250mW units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Battery", 1, 30, 0x3}, }; const char *pd3p0_battery_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 PPS APDO - Source (Section 6.4.1.2.5) const struct vdo_field pd3p0_pps_apdo_src_fields[] = { {"Maximum Current in 50mA increments", 1, 0, 0x7f}, {"Reserved", 0, 7, 0x0}, {"Minimum Voltage in 100mV increments", 1, 8, 0xff}, {"Reserved", 0, 16, 0x0}, {"Maximum Voltage in 100mV increments", 1, 17, 0xff}, {"Reserved", 0, 25, 0x0}, {"PPS Power Limited", 1, 27, 0x1}, {"Programable Power Supply", 1, 28, 0x3}, {"Augmented Power Data Object", 1, 30, 0x3}, }; const char *pd3p0_pps_apdo_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 Fixed Supply PDO - Sink (Section 6.4.1.3.1) const struct vdo_field pd3p0_fixed_supply_snk_fields[] = { {"Operational Current in 10mA units", 1, 0, 0x3ff}, {"Voltage in 50mV units", 1, 10, 0x3ff}, {"Reserved", 0, 20, 0x7}, {"Fast Role Swap Required", 1, 23, 0x3}, {"Dual-Role Data", 1, 25, 0x1}, {"USB Communications Capable", 1, 26, 0x1}, {"Unconstrained Power", 1, 27, 0x1}, {"Higher Capability", 1, 28, 0x1}, {"Daul-Role Power", 1, 29, 0x1}, {"Fixed supply", 1, 30, 0x3}, }; const char *pd3p0_fixed_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {"Fast Swap not supported", "Default USB Power", "1.5A @ 5V", "3.0A @ 5V"}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 Variable Supply PDO - Sink (Section 6.4.1.3.2) const struct vdo_field pd3p0_variable_supply_snk_fields[] = { {"Operational Current in 10mA units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Variable Supply", 1, 30, 0x3}, }; const char *pd3p0_variable_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 Battery Supply PDO - Sink (Section 6.4.1.3.3) const struct vdo_field pd3p0_battery_supply_snk_fields[] = { {"Operational Power in 250mW units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Battery", 1, 30, 0x3}, }; const char *pd3p0_battery_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 PPS APDO - Sink (Section 6.4.1.3.4) const struct vdo_field pd3p0_pps_apdo_snk_fields[] = { {"Maximum Current in 50mA increments", 1, 0, 0x7f}, {"Reserved", 0, 7, 0x0}, {"Minimum Voltage in 100mV increments", 1, 8, 0xff}, {"Reserved", 0, 16, 0x0}, {"Maximum Voltage in 100mV increments", 1, 17, 0xff}, {"Reserved", 0, 25, 0x7}, {"Programable Power Supply", 1, 28, 0x3}, {"Augmented Power Data Object", 1, 30, 0x3}, }; const char *pd3p0_pps_apdo_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.1 ID Header VDO (Section 6.4.4.3.1.1) const struct vdo_field pd3p1_partner_id_header_fields[] = { {"USB Vendor ID", 1, 0, 0xffff}, {"Reserved", 0, 16, 0x1f}, {"Connector Type", 1, 21, 0x3}, {"Product Type (DFP)", 1, 23, 0x7}, {"Modal Operation Supported", 1, 26, 0x1}, {"Product Type (UFP)", 1, 27, 0x7}, {"USB Capable as a Device", 1, 30, 0x1}, {"USB Capable as a Host", 1, 31, 0x1}, }; const char *pd3p1_partner_id_header_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {"Reserved", "Reserved", "USB Type-C Receptacle", "USB Type-C Plug"}, {"Undefined", "PDUSB Hub", "PDUSB Host", "Power Brick", "Alternate Mode Controller", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"Undefined", "PDUSB Hub", "PDUSB Peripheral", "PSD", "Reserved", "Alternate Mode Adapter", "Vconn Powered USB Device", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, }; const struct vdo_field pd3p1_cable_id_header_fields[] = { {"USB Vendor ID", 1, 0, 0xffff}, {"Reserved", 0, 16, 0x1f}, {"Connector Type", 1, 21, 0x3}, {"Product Type (DFP)", 0, 23, 0x7}, {"Modal Operation Supported", 1, 26, 0x1}, {"Product Type (Cable Plug)", 1, 27, 0x7}, {"USB Capable as a Device", 1, 30, 0x1}, {"USB Capable as a Host", 1, 31, 0x1}, }; const char *pd3p1_cable_id_header_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {"Reserved", "Reserved", "USB Type-C Receptacle", "USB Type-C Plug"}, {NULL}, {"No", "Yes"}, {"Undefined", "Reserved", "Reserved", "Passive Cable", "Active Cable", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, }; // USB PD 3.1 Cert Stat VDO (Section 6.4.4.3.1.2) const struct vdo_field pd3p1_cert_stat_fields[] = { {"XID", 1, 0, 0xffffffff}, }; const char *pd3p1_cert_stat_field_desc[][MAX_FIELDS] = { {NULL}, }; // USB PD 3.1 Product VDO (Section 6.4.4.3.1.3) const struct vdo_field pd3p1_product_fields[] = { {"bcdDevice", 1, 0, 0xffff}, {"USB Product ID", 1, 16, 0xffff}, }; const char *pd3p1_product_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, }; // USB PD 3.1 Passive Cable VDO (Section 6.4.4.3.1.6) const struct vdo_field pd3p1_passive_cable_fields[] = { {"USB Highest Speed", 1, 0, 0x7}, {"Reserved", 0, 3, 0x3}, {"Vbus Current Handling", 1, 5, 0x3}, {"Reserved", 0, 7, 0x3}, {"Maximum Vbus Voltage", 1, 9, 0x3}, {"Cable Termination Type", 1, 11, 0x3}, {"Cable Latency", 1, 13, 0xf}, {"EPR Mode Capable", 1, 17, 0x1}, {"Type-C Connector to", 1, 18, 0x3}, {"Reserved", 0, 20, 0x1}, {"VDO version", 1, 21, 0x7}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd3p1_passive_cable_field_desc[][MAX_FIELDS] = { {"USB 2.0 Only", "USB 3.2 Gen1", "USB 3.2/USB4 Gen2", "USB4 Gen3", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"Reserved", "3A", "5A", "Reserved"}, {NULL}, {"20V", "30V (Deprecated)", "40V (Deprecated)", "50V"}, {"Vconn Not Required", "Vconn Required", "Reserved", "Reserved"}, {"Reserved", "<10ns (~1m)", "10ns to 20ns (~2m)", "20ns to 30ns (~3m)", "30ns to 40ns (~4m)", "40ns to 50ns (~5m)", "50ns to 60ns (~6m)", "60ns to 70ns (~7m)", " 70ns (>~7m)", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"Reserved", "Reserved", "USB Type-C", "Captive"}, {NULL}, {"Version 1.0", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {NULL}, }; // USB PD 3.1 Active Cable VDO1/VDO2 (Section 6.4.4.3.1.7) const struct vdo_field pd3p1_active_cable_vdo1_fields[] = { {"USB Highest Speed", 1, 0, 0x7}, {"SOP'' Controller Present", 1, 3, 0x1}, {"Vbus Through Cable", 1, 4, 0x1}, {"Vbus Current Handling", 1, 5, 0x3}, {"SBU Type", 1, 7, 0x1}, {"SBU Supported", 1, 8, 0x1}, {"Maximum Vbus Voltage", 1, 9, 0x3}, {"Cable Termination Type", 1, 11, 0x3}, {"Cable Latency", 1, 13, 0xf}, {"EPR Mode Capable", 1, 17, 0x1}, {"USB Type-C to", 1, 18, 0x3}, {"Reserved", 0, 20, 0x1}, {"VDO version", 1, 21, 0x7}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd3p1_active_cable_vdo1_field_desc[][MAX_FIELDS] = { {"USB 2.0 Only", "USB 3.2 Gen1", "USB 3.2/USB4 Gen2", "USB4 Gen3", "Reserved", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"No", "Yes"}, {"USB Type-C Default Current", "3A", "5A", "Reserved"}, {"SBU is passive", "SBU is active"}, {"SBU connections supported", "SBU connections are not supported"}, {"20V", "30V", "40V", "50V"}, {"Reserved", "Reserved", "One end active, one end passive, Vconn required", "Both ends active, Vconn required"}, {"Reserved", "<10ns (~1m)", "10ns to 20ns (~2m)", "20ns to 30ns (~3m)", "30ns to 40ns (~4m)", "40ns to 50ns (~5m)", "50ns to 60ns (~6m)", "60ns to 70ns (~7m)", "1000b –1000ns (~100m)", "1001b –2000ns (~200m)", "1010b – 3000ns (~300m)", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {"No", "Yes"}, {"Reserved", "Reserved", "USB Type-C", "Captive"}, {NULL}, {"Reserved", "Reserved", "Reserved", "Version 1.3", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {NULL}, }; const struct vdo_field pd3p1_active_cable_vdo2_fields[] = { {"USB Gen", 1, 0, 0x1}, {"Reserved", 0, 1, 0x1}, {"Optically Isolated Active Cable", 1, 2, 0x1}, {"USB Lanes Supported", 1, 3, 0x1}, {"USB 3.2 Supported", 1, 4, 0x1}, {"USB 2.0 Supported", 1, 5, 0x1}, {"USB 2.0 Hub Hops Consumed", 1, 6, 0x3}, {"USB4 Supported", 1, 8, 0x1}, {"Active element", 1, 9, 0x1}, {"Physical connection", 1, 10, 0x1}, {"U3 to U0 transition mode", 1, 11, 0x1}, {"U3/Cld Power", 1, 12, 0x7}, {"Reserved", 0, 15, 0x1}, {"Shutdown Temperature", 1, 16, 0xff}, {"Maximum Operating Temperature", 1, 24, 0xff}, }; const char *pd3p1_active_cable_vdo2_field_desc[][MAX_FIELDS] = { {"Gen 1", "Gen 2 or higher"}, {NULL}, {"No", "Yes"}, {"One Lane", "Two Lanes"}, {"USB 3.2 SuperSpeed supported", "USB 3.2 SuperSpeed not supported"}, {"USB 2.0 supported", "USB 2.0 not supported"}, {NULL}, {"USB4 Supported", "USB4 Not Supported"}, {"Active Redriver", "Active Retimer"}, {"Copper", "Optical"}, {"U3 to U0 direct", "U3 to U0 through U35"}, {">10mW", "5-10mW", "1-5mW", "0.5-1mW", "0.2-0.5mW", "50-200uW", "<50uW", "Reserved"}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.0 VPD VDO (Section 6.4.4.3.1.9) const struct vdo_field pd3p1_vpd_fields[] = { {"Charge Through Support", 1, 0, 0x1}, {"Ground Impedance", 1, 1, 0x3f}, {"Vbus Impedance", 1, 7, 0x3f}, {"Reserved", 0, 13, 0x3}, {"Charge Through Current Support", 1, 14, 0x1}, {"Maximum Vbus Voltage", 1, 15, 0x3}, {"Reserved", 0, 17, 0xf}, {"VDO Version", 1, 21, 0x7}, {"Firmware Version", 1, 24, 0xf}, {"HW Version", 1, 28, 0xf}, }; const char *pd3p1_vpd_field_desc[][MAX_FIELDS] = { {"No","Yes"}, {NULL}, {NULL}, {NULL}, {"3A capable", "5A capable"}, {"20V", "30V (Deprecated)", "40V (Deprecated)", "50V (Deprecated)"}, {NULL}, {"Version 1.0", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {NULL}, }; // USB PD 3.1 UFP VDO (Section 6.4.4.3.1.4) const struct vdo_field pd3p1_ufp_fields[] = { {"USB Highest Speed", 1, 0, 0x7}, {"Alternate Modes", 1, 3, 0x7}, {"Vbus Required", 1, 6, 0x1}, {"Vconn Required", 1, 7, 0x1}, {"Vconn Power", 1, 8, 0x7}, {"Reserved", 0, 11, 0x7ff}, {"Connector Type", 1, 22, 0x3}, {"Device Capability", 1, 24, 0xf}, {"Reserved", 0, 28, 0x1}, {"UFP VDO Version", 1, 29, 0x7}, }; const char *pd3p1_ufp_field_desc[][MAX_FIELDS] = { {"USB 2.0 only", "USB 3.2 Gen1", "USB 3.2/USB4 Gen2", "USB4 Gen3", "Reserved", "Reserved", "Reserved", "Reserved"}, {NULL}, {"Yes", "No"}, {"No", "Yes"}, {"1W", "1.5W", "2W", "3W", "4W", "5W", "6W", "Reserved"}, {NULL}, {NULL}, {NULL}, {NULL}, {"Reserved", "Reserved", "Reserved", "Version 1.3", "Reserved", "Reserved", "Reserved", "Reserved"}, }; // USB PD 3.1 DFP VDO (Section 6.4.4.3.1.5) const struct vdo_field pd3p1_dfp_fields[] = { {"Port Number", 1, 0, 0x1f}, {"Reserved", 0, 5, 0x1ffff}, {"Connector Type", 1, 22, 0x3}, {"Host Capability", 1, 24, 0x7}, {"Reserved", 0, 27, 0x3}, {"DFP VDO Version", 1, 29, 0x7}, }; const char *pd3p1_dfp_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {"Version 1.0", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved"}, }; // USB PD 3.1 Fixed Supply PDO - Source (Section 6.4.1.2.2) const struct vdo_field pd3p1_fixed_supply_src_fields[] = { {"Maximum Current in 10mA units", 1, 0, 0x3ff}, {"Voltage in 50mV units", 1, 10, 0x3ff}, {"Peak Current", 1, 20, 0x3}, {"Reserved", 0, 22, 0x1}, {"EPR Mode Capable", 1, 23, 0x1}, {"Unchunked Extended Messages Supported", 0, 24, 0x1}, {"Dual-Role Data", 1, 25, 0x1}, {"USB Communications Capable", 1, 26, 0x1}, {"Unconstrained Power", 1, 27, 0x1}, {"USB Suspend Supported", 1, 28, 0x1}, {"Daul-Role Power", 1, 29, 0x1}, {"Fixed supply", 1, 30, 0x3}, }; const char *pd3p1_fixed_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.1 Variable Supply PDO - Source (Section 6.4.1.2.3) const struct vdo_field pd3p1_variable_supply_src_fields[] = { {"Maximum Current in 10mA units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Variable Supply", 1, 30, 0x3}, }; const char *pd3p1_variable_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.1 Battery Supply PDO - Source (Section 6.4.1.2.4) const struct vdo_field pd3p1_battery_supply_src_fields[] = { {"Maximum Allowable Power in 250mW units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Battery", 1, 30, 0x3}, }; const char *pd3p1_battery_supply_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.1 PPS APDO - Source (Section 6.4.1.2.5) const struct vdo_field pd3p1_pps_apdo_src_fields[] = { {"Maximum Current in 50mA increments", 1, 0, 0x7f}, {"Reserved", 0, 7, 0x0}, {"Minimum Voltage in 100mV increments", 1, 8, 0xff}, {"Reserved", 0, 16, 0x0}, {"Maximum Voltage in 100mV increments", 1, 17, 0xff}, {"Reserved", 0, 25, 0x0}, {"PPS Power Limited", 1, 27, 0x1}, {"SPR PPS", 1, 28, 0x3}, {"Augmented Power Data Object", 1, 30, 0x3}, }; const char *pd3p1_pps_apdo_src_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.1 Fixed Supply PDO - Sink (Section 6.4.1.3.1) const struct vdo_field pd3p1_fixed_supply_snk_fields[] = { {"Operational Current in 10mA units", 1, 0, 0x3ff}, {"Voltage in 50mV units", 1, 10, 0x3ff}, {"Reserved", 0, 20, 0x7}, {"Fast Role Swap Required", 1, 23, 0x3}, {"Dual-Role Data", 1, 25, 0x1}, {"USB Communications Capable", 1, 26, 0x1}, {"Unconstrained Power", 1, 27, 0x1}, {"Higher Capability", 1, 28, 0x1}, {"Daul-Role Power", 1, 29, 0x1}, {"Fixed supply", 1, 30, 0x3}, }; const char *pd3p1_fixed_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {"Fast Swap not supported", "Default USB Power", "1.5A @ 5V", "3.0A @ 5V"}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.1 Variable Supply PDO - Sink (Section 6.4.1.3.2) const struct vdo_field pd3p1_variable_supply_snk_fields[] = { {"Operational Current in 10mA units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Variable Supply", 1, 30, 0x3}, }; const char *pd3p1_variable_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.1 Battery Supply PDO - Sink (Section 6.4.1.3.3) const struct vdo_field pd3p1_battery_supply_snk_fields[] = { {"Operational Power in 250mW units", 1, 0, 0x3ff}, {"Minimum Voltage in 50mV units", 1, 10, 0x3ff}, {"Maximum Voltage in 50mV units", 1, 20, 0x3ff}, {"Battery", 1, 30, 0x3}, }; const char *pd3p1_battery_supply_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, }; // USB PD 3.1 PPS APDO - Sink (Section 6.4.1.3.4) const struct vdo_field pd3p1_pps_apdo_snk_fields[] = { {"Maximum Current in 50mA increments", 1, 0, 0x7f}, {"Reserved", 0, 7, 0x0}, {"Minimum Voltage in 100mV increments", 1, 8, 0xff}, {"Reserved", 0, 16, 0x0}, {"Maximum Voltage in 100mV increments", 1, 17, 0xff}, {"Reserved", 0, 25, 0x7}, {"SPR PPS", 1, 28, 0x3}, {"Augmented Power Data Object", 1, 30, 0x3}, }; const char *pd3p1_pps_apdo_snk_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; // Alternate mode VDOs const struct vdo_field dp_alt_mode_partner_fields[] = { {"Port Capability", 1, 0, 0x3}, {"Signaling for Transport of DisplaPort Protocol", 1, 2, 0xf}, {"Receptacle Indication", 1, 6, 0x1}, {"USB 2.0 Signaling Not Used", 1, 7, 0x1}, {"DP Source Device Pin Supported", 1, 8, 0xff}, {"DP Sink Device Pin Supported", 1, 16, 0xff}, {"Reserved", 0, 24, 0xff}, }; const char *dp_alt_mode_partner_field_desc[][MAX_FIELDS] = { {"Reserved", "DP Sink Deice Capable", "DP Source Device Capable", "Both Sink and Source Device Capable"}, {NULL}, {"DP interface presents as a plug", "DP interface presents as a receptacle"}, {"USB 2.0 may be needed", "USB 2.0 not needed"}, {NULL}, {NULL}, {NULL}, }; const struct vdo_field dp_alt_mode_active_cable_fields[] = { {"Reserved", 0, 0, 0x3}, {"Signaling for Transport of DisplaPort Protocol", 1, 2, 0xf}, {"Reserved", 0, 6, 0x3}, {"DP Source Device Pin Assignments Supported", 1, 8, 0xff}, {"DP Sink Device Pin Assignments Supported", 1, 16, 0xff}, {"Reserved", 0, 24, 0xff}, }; const char *dp_alt_mode_active_cable_field_desc[][MAX_FIELDS] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, }; const struct vdo_field tbt3_sop_fields[] = { {"TBT Alternate Mode", 1, 0, 0xffff}, {"TBT Adapter", 1, 16, 0x1}, {"Reserved", 1, 17, 0x1ff}, {"Intel Specific B0", 1, 26, 0x1}, {"Reserved", 1, 27, 0x7}, {"Vendor Specific B0", 1, 30, 0x1}, {"Vendor Specific B1", 1, 31, 0x1}, }; const char *tbt3_sop_field_desc[][MAX_FIELDS] = { {NULL}, {"TBT3 Adapter", "TBT2 Legacy Adapter"}, {NULL}, {"Not Supported", "Supported"}, {NULL}, {"Not Supported", "Supported"}, {"Not Supported", "Supported"}, }; const struct vdo_field tbt3_sop_pr_fields[] = { {"TBT Alternate Mode", 1, 0, 0xffff}, {"Cable Speed", 1, 16, 0x7}, {"TBT Rounded Support", 1, 19, 0x3}, {"Cable Type", 1, 21, 0x1}, {"Re-timer", 1, 22, 0x1}, {"Active Cable Plug Link Training", 1, 23, 0x1}, {"Reserved", 0, 24, 0x1}, {"Active_Passive", 1, 25, 0x1}, {"Reserved", 0, 26, 0x3f}, }; const char *tbt3_sop_pr_field_desc[][MAX_FIELDS] = { {NULL}, {"Reserved", "USB 3.1 Gen1 (10 Gbps TBT Support)", "10 Gbps (USB 3.2 Gen1 and Gen2 passive cables)", "10 Gbps and 20 Gbps (TBT 3rd Gen active cables and 20 Gbps passive cables)", "Reserved", "Reserved", "Reserved", "Reserved"}, {"3rd Gen Non-Rounded TBT", "3rd & 4th Gen Rounded and Non-Rounded TBT", "Reserved", "Reserved"}, {"Non-Optical", "Optical"}, {"Not re-timer", "Re-timer"}, {"Active with bi-directional LSRX", "Active with uni-directional LSRX"}, {NULL}, {"Passive Cable", "Active Cable"}, {NULL}, }; struct libtypec_capability_data get_cap_data; struct libtypec_connector_cap_data conn_data; struct libtypec_connector_status conn_sts; struct libtypec_cable_property cable_prop; union libtypec_discovered_identity id; struct libtypec_get_pdos *pdo_data; struct altmode_data am_data[64]; char *session_info[LIBTYPEC_SESSION_MAX_INDEX]; enum product_type get_cable_product_type(short rev, uint32_t id); enum product_type get_partner_product_type(short rev, uint32_t id); void print_vdo(uint32_t vdo, int num_fields, const struct vdo_field vdo_fields[], const char *vdo_field_desc[][MAX_FIELDS]); void print_session_info(); void print_ppm_capability(struct libtypec_capability_data ppm_data); void print_conn_capability(struct libtypec_connector_cap_data conn_data); void print_cable_prop(struct libtypec_cable_property cable_prop, int conn_num); void print_alternate_mode_data(int recipient, uint32_t id_header, int num_modes, struct altmode_data *am_data); void print_identity_data(int recipient, union libtypec_discovered_identity id, struct libtypec_connector_cap_data conn_data); void print_source_pdo_data(struct libtypec_get_pdos *pdo_data, int num_pdos, int revision); void print_sink_pdo_data(struct libtypec_get_pdos *pdo_data, int num_pdos, int revision); void lstypec_print(char *val, int type); libtypec-libtypec-0.6.0/utils/meson.build000066400000000000000000000026371472033722300204560ustar00rootroot00000000000000project('libtypec_utils','c', license: 'MIT', version: '0.6.0', default_options : [ 'warning_level=0']) conf_data = configuration_data() split = meson.project_version().split('.') conf_data.set('libtypec_utils_VERSION_MAJOR', split[0]) conf_data.set('libtypec_utils_VERSION_MINOR', split[1]) conf_data.set('libtypec_utils_VERSION_PATCH', split[2]) configure_file(input : 'libtypec_utils_config.h.in', output : 'libtypec_utils_config.h', configuration : conf_data) # Include current build dir for the above generated file inc_dir = include_directories('.') cc = meson.get_compiler('c') dep = declare_dependency( dependencies : cc.find_library('typec') ) udev_dep = meson.get_compiler('c').find_library('udev') gtk3_dep = dependency('gtk+-3.0') executable( 'lstypec', 'lstypec.c', 'names.c', dependencies: [dep, udev_dep], include_directories: inc_dir, install: true, install_dir: get_option('bindir') ) executable( 'typecstatus', 'typecstatus.c', 'names.c', dependencies: [dep, udev_dep], include_directories: inc_dir, install: true, install_dir: get_option('bindir') ) executable( 'ucsicontrol', 'ucsicontrol.c', 'names.c', dependencies: [dep, udev_dep], include_directories: inc_dir, install: true, install_dir: get_option('bindir') ) executable( 'usbcview', 'usbcview.c', 'names.c', dependencies: [dep, gtk3_dep,udev_dep], include_directories: inc_dir, install: true, install_dir: get_option('bindir') ) libtypec-libtypec-0.6.0/utils/names.c000066400000000000000000000045071472033722300175610ustar00rootroot00000000000000/* Copyright (c) 2021-2022 by Rajaram Regupathy, rajaram.regupathy@gmail.com 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; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. (See the full license text in the LICENSES directory) */ // SPDX-License-Identifier: GPL-2.0-only /* * Code based on usbutils: https://github.com/gregkh/usbutils */ #include #include #include static struct udev *udev = NULL; static struct udev_hwdb *hwdb = NULL; int names_init(void) { udev = udev_new(); if (udev == NULL) { return -1; } hwdb = udev_hwdb_new(udev); if (hwdb == NULL) { return -1; } return 0; } void names_exit(void) { hwdb = udev_hwdb_unref(hwdb); udev = udev_unref(udev); } static const char *hwdb_get(const char *modalias, const char *key) { struct udev_list_entry *entry; udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0)) { if (strcmp(udev_list_entry_get_name(entry), key) == 0) { return udev_list_entry_get_value(entry); } } return NULL; } const char *names_vendor(u_int16_t vendorid) { char modalias[64]; sprintf(modalias, "usb:v%04X*", vendorid); return hwdb_get(modalias, "ID_VENDOR_FROM_DATABASE"); } const char *names_product(u_int16_t vendorid, u_int16_t productid) { char modalias[64]; sprintf(modalias, "usb:v%04Xp%04X*", vendorid, productid); return hwdb_get(modalias, "ID_MODEL_FROM_DATABASE"); } int get_vendor_string(char *buf, size_t size, u_int16_t vid) { const char *cp; if (size < 1) return 0; *buf = 0; if (!(cp = names_vendor(vid))) return 0; return snprintf(buf, size, "%s", cp); } int get_product_string(char *buf, size_t size, u_int16_t vid, u_int16_t pid) { const char *cp; if (size < 1) return 0; *buf = 0; if (!(cp = names_product(vid, pid))) return 0; return snprintf(buf, size, "%s", cp); }libtypec-libtypec-0.6.0/utils/names.h000066400000000000000000000017001472033722300175560ustar00rootroot00000000000000/* Copyright (c) 2021-2022 by Rajaram Regupathy, rajaram.regupathy@gmail.com 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; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. (See the full license text in the LICENSES directory) */ // SPDX-License-Identifier: GPL-2.0-only /* * Code based on usbutils: https://github.com/gregkh/usbutils */ #ifndef NAMES_H #define NAMES_H int names_init(void); void names_exit(void); int get_vendor_string(char *buf, size_t size, unsigned short vid); int get_product_string(char *buf, size_t size, unsigned short vid, unsigned short pid); #endif //NAMES_Hlibtypec-libtypec-0.6.0/utils/typecstatus.c000066400000000000000000000163341472033722300210470ustar00rootroot00000000000000/* MIT License Copyright (c) 2022 Rajaram Regupathy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // SPDX-License-Identifier: MIT /** * @file typecstatus.c * @author Rajaram Regupathy * @brief Initial prototype. Performs status check of typec ports. */ #include #include #include #include #include #include #include "libtypec.h" #include #include "names.h" struct libtypec_connector_status conn_sts; struct bb_bos_header {; unsigned char cap_desc_blength; unsigned char cap_desc_desc_type; unsigned char cap_desc_cap_type; }; struct bb_bos_descritor { unsigned char cap_desc_blength; unsigned char cap_desc_desc_type; unsigned char cap_desc_cap_type; unsigned char cap_desc_url_info; unsigned char cap_desc_num_aum; unsigned char cap_desc_pref_aum; unsigned char cap_desc_vconn_pwr[2]; unsigned char cap_desc_bmconfig[32]; unsigned char cap_desc_bcd_ver[2]; unsigned char cap_desc_addln_fail_info; unsigned char cap_desc_rsvd; unsigned char cap_desc_aum_array_start; }; int find_bb_bos_index(char *bb_data, int len) { struct bb_bos_header *level; int index=5; while (index < len) { level = (struct bb_bos_header *) &bb_data[index]; if(level->cap_desc_cap_type == 0x0D) return index; index = index + level->cap_desc_blength; } return -1; } static unsigned long get_dword_from_path(char *path) { char buf[64]; unsigned long dword; FILE *fp = fopen(path, "r"); if (fp == NULL) return -1; if(fgets(buf, 64, fp) == NULL) { fclose(fp); return -1; } dword = strtoul(buf, NULL, 10); fclose(fp); return dword; } int typec_status_billboard() { int ret,index=0;; unsigned char bb_data[512]; ret = libtypec_get_bb_status(&index); printf("Detected %d BB device(s)\n=======================\n",index); if(index > 0) { for(int i=1;i<=index;i++) { int bb_loc = 0; ret = libtypec_get_bb_data(i,bb_data); if(ret < 0) { printf("\tUnable to read Billboard device. Try running with higher privileges. Returned error code %d\n", ret); return -1; } bb_loc = find_bb_bos_index(bb_data,ret); if(bb_loc > 0 ) { struct bb_bos_descritor *bb_bos_desc = (struct bb_bos_descritor *)&bb_data[bb_loc]; printf("\tBillboard Device Version : %x.%x\n",bb_bos_desc->cap_desc_bcd_ver[1],bb_bos_desc->cap_desc_bcd_ver[0]); printf("\tNumber of Alternate Mode : %d\n",bb_bos_desc->cap_desc_num_aum); for(int x=0;xcap_desc_num_aum;x++) { int idx = 0, k=0, j=0; #define bmCONF_STR_ARR_MAX 4 char *bmconf_str_array[]= {"Unspecified Error","AUM not attempted","AUM attempt unsuccessful","AUM configuration successful","Undefined Configuration"}; if( (x !=0) && ((x % 4) == 0)) { j++; k=0; } idx = bb_bos_desc->cap_desc_bmconfig[j]; idx = (idx >> k) & 0x3; k++; idx = idx < bmCONF_STR_ARR_MAX ? idx : bmCONF_STR_ARR_MAX; char *aum = &bb_bos_desc->cap_desc_aum_array_start; aum = aum + (x*4); printf("\tAlternate Mode 0x%02X%02X in state : %s\n",aum[1]&0xFF,aum[0]&0xFF,bmconf_str_array[idx]); } } } } return 0; } int typecstatus_power_contract() { unsigned long tdp, bst_pwr; int ret; struct libtypec_capability_data get_cap_data; // PPM Capabilities ret = libtypec_get_capability(&get_cap_data); if (ret < 0) printf("Unable to read typec capabilities\n==================\n"); else { printf("USB-C Power Status\n==================\n"); printf("Number of USB-C port(s): %d\n======================\n",get_cap_data.bNumConnectors); for(int i=0;i>10)&0x3ff) * 250)/1000,((conn_sts.RequestDataObject &0x3ff) * 250)/1000); tdp = get_dword_from_path("/sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw")/1000000; bst_pwr = get_dword_from_path("/sys/class/powercap/intel-rapl:0/constraint_1_power_limit_uw")/1000000; printf("\tCharging System with TDP %ld W, with boost power requirement of %ld W\n",tdp,bst_pwr); } else printf("\tNo Power Contract on port %d\n",i); } } return 0; } /* Check all typec ports */ static int ro_flag; char *session_info[LIBTYPEC_SESSION_MAX_INDEX]; int main (int argc, char **argv) { int ret,index=0; if(argc == 1) { printf("typecstatus - Check status of typec ports\n Usage:\t typecstatus --ro | --rb \n\ --ro\t Run once to gather typec port status \n\t--rb\t Run as background and notify\n"); exit(0); } static struct option options[] = { /* These options set a flag. */ {"ro", no_argument,&ro_flag, 1}, }; ret = getopt_long (argc, argv, "", options, &index); if(ret != 0) printf("typecstatus - Check status of typec ports\n Usage:\t typecstatus --all \n"); names_init(); ret = libtypec_init(session_info,LIBTYPEC_BACKEND_SYSFS); if (ret < 0) { printf("Failed in Initializing libtypec\n"); return -1; } if(ro_flag) { typecstatus_power_contract(); typec_status_billboard(); } names_exit(); } libtypec-libtypec-0.6.0/utils/ucsicontrol.c000066400000000000000000000577671472033722300210420ustar00rootroot00000000000000/* Copyright (c) 2021-2022 by Madhu M, madhu.m@intel.com 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; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. (See the full license text in the LICENSES directory) */ // SPDX-License-Identifier: GPL-2.0-only /** * @file ucsicontrol.c * @author Madhu M * @coauthor Rajaram Regupathy * @brief Implements listing of ucsi connector details * */ #include #include #include #include #include #include "../libtypec.h" #include "lstypec.h" #include "names.h" struct libtypec_capability_data cap_data; struct libtypec_connector_cap_data conn_cap; struct libtypec_current_cam cur_cam; struct libtypec_connector_status conn_sts; struct libtypec_cable_property cable_prop; union libtypec_discovered_identity id; struct libtypec_get_pdos pdo_data_val; struct altmode_data alt_mode_data[64]; char *session_info[LIBTYPEC_SESSION_MAX_INDEX]; void hex_to_decimal(unsigned int version) { uint8_t major = (version >> 8) & 0xFF; uint8_t minor = version & 0xFF; printf("%x.%02x\n", major, minor); } /** * Prints the USB-C Platform Policy Manager capability data. * * @param cap_data The structure containing the capability data. */ void print_get_capability(struct libtypec_capability_data *cap_data) { printf("UCSI MESSAGE_IN:\n"); printf("==================\n"); for (int i = 0; i < sizeof(*cap_data); i++) { printf("%02x ", ((unsigned char*)cap_data)[i]); if ((i + 1) % 8 == 0) { printf("\n"); } } printf("\n\nUCSI_GET_CAPABILITY_IN:\n"); printf("-------------------------\n"); printf("bmAttributes:\n"); printf(" disabledStateSupport: %u\n", cap_data->bmAttributes.disabledstatesupport); printf(" batteryCharging: %u\n", cap_data->bmAttributes.batterycharging); printf(" usbPowerDelivery: %u\n", cap_data->bmAttributes.usbpowerdelivery); printf(" usbTypeCCurrent: %u\n", cap_data->bmAttributes.usbtypeccurrent); printf(" bmPowerSource.acsupply: %u\n", cap_data->bmAttributes.bmPowerSource.acsupply); printf(" bmPowerSource.other: %u\n", cap_data->bmAttributes.bmPowerSource.other); printf(" bmPowerSource.vbus: %u\n", cap_data->bmAttributes.bmPowerSource.vbus); printf("bNumConnectors: %x\n", cap_data->bNumConnectors); printf("bmOptionalFeatures:\n"); printf(" setccomsupported: %u\n", cap_data->bmOptionalFeatures.setccomsupported); printf(" setpowerlevelsupported: %u\n", cap_data->bmOptionalFeatures.setpowerlevelsupported); printf(" altmodedetailssupported: %u\n", cap_data->bmOptionalFeatures.altmodedetailssupported); printf(" altmodeoverridesupported: %u\n", cap_data->bmOptionalFeatures.altmodeoverridesupported); printf(" pdodetailssupported: %u\n", cap_data->bmOptionalFeatures.pdodetailssupported); printf(" cabledetailssupported: %u\n", cap_data->bmOptionalFeatures.cabledetailssupported); printf(" extsupplynotificationsupported: %u\n", cap_data->bmOptionalFeatures.extsupplynotificationsupported); printf(" pdresetnotificationsupported: %u\n", cap_data->bmOptionalFeatures.pdresetnotificationsupported); printf(" getpdmessagesupported: %u\n", cap_data->bmOptionalFeatures.getpdmessagesupported); printf(" getattentionvdosupported: %u\n", cap_data->bmOptionalFeatures.getattentionvdosupported); printf(" fwupdaterequestsupported: %u\n", cap_data->bmOptionalFeatures.fwupdaterequestsupported); printf(" negotiatedpowerlevelchangesupported: %u\n", cap_data->bmOptionalFeatures.negotiatedpowerlevelchangesupported); printf(" securityrequestsupported: %u\n", cap_data->bmOptionalFeatures.securityrequestsupported); printf(" setretimermodesupported: %u\n", cap_data->bmOptionalFeatures.setretimermodesupported); printf(" chunkingsupportsupported: %u\n", cap_data->bmOptionalFeatures.chunkingsupportsupported); printf("bNumAltModes: %x\n", cap_data->bNumAltModes); printf("bcdBCVersion: "); hex_to_decimal(cap_data->bcdBCVersion); printf("bcdPDVersion: "); hex_to_decimal(cap_data->bcdPDVersion); printf("bcdTypeCVersion: "); hex_to_decimal(cap_data->bcdTypeCVersion); } /** * Prints the USB-C Platform Policy Manager connector capability data. * * @param conn_cap The structure containing the connector capability data. */ void print_get_connector_capability(struct libtypec_connector_cap_data *conn_cap) { union extendedoperationmode extend_opr_mode; union miscellaneouscapabilities misc_cap; printf("UCSI MESSAGE_IN:\n"); printf("==================\n"); for (int i = 0; i < sizeof(*conn_cap); i++) { printf("%02x ", ((unsigned char*)conn_cap)[i]); if ((i + 1) % 8 == 0) { printf("\n"); } } printf("\n\nGET_CONNECTOR_CAPABILITY:\n"); printf("-------------------------\n"); printf("OperationMode: 0x%x\n", conn_cap->opr_mode.raw_operationmode); printf(" Rponly: %d\n", conn_cap->opr_mode.rponly); printf(" Rdonly: %d\n", conn_cap->opr_mode.rdonly); printf(" Drp: %d\n", conn_cap->opr_mode.drp); printf(" AnalogAudioAccessorymode: %d\n", conn_cap->opr_mode.analogaudioaccessorymode); printf(" DebugAccessorymode: %d\n", conn_cap->opr_mode.debugaccessorymode); printf(" Usb2: %d\n", conn_cap->opr_mode.usb2); printf(" Usb3: %d\n", conn_cap->opr_mode.usb3); printf(" AlternateMode: %d\n", conn_cap->opr_mode.alternatemode); printf("Provider: %d\n", conn_cap->provider); printf("Consumer: %d\n", conn_cap->consumer); printf("SwapToDfp: %d\n", conn_cap->swap2dfp); printf("SwapToUfp: %d\n", conn_cap->swap2ufp); printf("SwapToSrc: %d\n", conn_cap->swap2src); printf("SwapToSnk: %d\n", conn_cap->swap2snk); printf("ExtendedOperationMode: 0x%x\n", conn_cap->extended_operation_mode); extend_opr_mode.raw_extendedoperationmode = conn_cap->extended_operation_mode; printf(" Usb4Gen2: %d\n", extend_opr_mode.usb4gen2); printf(" EprSrc: %d\n", extend_opr_mode.eprsrc); printf(" EprSnk: %d\n", extend_opr_mode.eprsnk); printf(" Usb4Gen3: %d\n", extend_opr_mode.usb4gen3); printf(" Usb4Gen4: %d\n", extend_opr_mode.usb4gen4); printf("MiscellaneousCapabilities: 0x%x\n", conn_cap->miscellaneous_capabilities); misc_cap.raw_miscellaneouscapabilities = conn_cap->miscellaneous_capabilities; printf(" FwUpdate: %d\n", misc_cap.fwupdate); printf(" Security: %d\n", misc_cap.security); printf("ReverseCurrentProtectionSupport: %d\n", conn_cap->reverse_current_protection_support); printf("PartnerPDRevision: %d\n", conn_cap->partner_pd_rev); } /** * Prints the USB-C Platform Policy Manager connector status data. * * @param conn_sts The structure containing the connector status data. */ void print_get_connector_status(struct libtypec_connector_status *conn_sts) { union connectorpartnerflags conn_parn_flg; printf("UCSI MESSAGE_IN:\n"); printf("==================\n"); for (int i = 0; i < sizeof(*conn_sts); i++) { printf("%02x ", ((unsigned char*)conn_sts)[i]); if ((i + 1) % 8 == 0) { printf("\n"); } } printf("\n\nUCSI_GET_CONNECTOR_STATUS:\n"); printf("-------------------------\n"); printf("ConnectorStatusChange: 0x%x\n", conn_sts->ConnectorStatusChange.raw_conn_stschang); printf(" ExternalSupplyChange: %d\n", conn_sts->ConnectorStatusChange.ExternalSupplyChange); printf(" Attention: %d\n", conn_sts->ConnectorStatusChange.Attention); printf(" SupportedProviderCapabilitiesChange: %d\n", conn_sts->ConnectorStatusChange.SupportedProviderCapabilitiesChange); printf(" NegotiatedPowerLevelChange: %d\n", conn_sts->ConnectorStatusChange.NegotiatedPowerLevelChange); printf(" PDResetComplete: %d\n", conn_sts->ConnectorStatusChange.PDResetComplete); printf(" SupportedCAMChange: %d\n", conn_sts->ConnectorStatusChange.SupportedCAMChange); printf(" BatteryChargingStatusChange: %d\n", conn_sts->ConnectorStatusChange.BatteryChargingStatusChange); printf(" ConnectorPartnerChanged: %d\n", conn_sts->ConnectorStatusChange.ConnectorPartnerChanged); printf(" PowerDirectionChanged: %d\n", conn_sts->ConnectorStatusChange.PowerDirectionChanged); printf(" SinkPathStatusChange: %d\n", conn_sts->ConnectorStatusChange.SinkPathStatusChange); printf(" ConnectChange: %d\n", conn_sts->ConnectorStatusChange.ConnectChange); printf(" Error: %d\n", conn_sts->ConnectorStatusChange.Error); printf("PowerOperationMode: %d\n", conn_sts->PowerOperationMode); printf(" UsbDefaultOperation: %d\n", (conn_sts->PowerOperationMode == 1) ? 1 : 0); printf(" BC: %d\n", (conn_sts->PowerOperationMode == 2) ? 1 : 0); printf(" PD: %d\n", (conn_sts->PowerOperationMode == 3) ? 1 : 0); printf(" UsbTypecCurrent1.5A: %d\n", (conn_sts->PowerOperationMode == 4) ? 1 : 0); printf(" UsbTypecCurrent3A: %d\n", (conn_sts->PowerOperationMode == 5) ? 1 : 0); printf(" UsbTypecCurrent5A: %d\n", (conn_sts->PowerOperationMode == 6) ? 1 : 0); printf("ConnectStatus: %d\n", conn_sts->ConnectStatus); printf("PowerDirection: %d\n", conn_sts->PowerDirection); printf(" Consumer: %d\n", (conn_sts->PowerDirection == 0) ? 1 : 0); printf(" Provider: %d\n", (conn_sts->PowerDirection == 1) ? 1 : 0); printf("ConnectorPartnerFlags: 0x%x\n", conn_sts->ConnectorPartnerFlags); conn_parn_flg.raw_conn_part_flags = conn_sts->ConnectorPartnerFlags; printf(" Usb: %d\n", conn_parn_flg.usb); printf(" Dp: %d\n", conn_parn_flg.altmode); printf(" Tbt: %d\n", conn_parn_flg.usb4_gen3); printf(" Usb4: %d\n", conn_parn_flg.usb4_gen4); printf("ConnectorPartnerType: %d\n", conn_sts->ConnectorPartnerType); printf(" DFPattached: %d\n", (conn_sts->ConnectorPartnerType == 1) ? 1 : 0); printf(" UFPattached: %d\n", (conn_sts->ConnectorPartnerType == 2) ? 1 : 0); printf(" PoweredCableNoUFPattached: %d\n", (conn_sts->ConnectorPartnerType == 3) ? 1 : 0); printf(" PoweredCableUFPattached: %d\n", (conn_sts->ConnectorPartnerType == 4) ? 1 : 0); printf(" DebugAccessoryattched: %d\n", (conn_sts->ConnectorPartnerType == 5) ? 1 : 0); printf(" AudioAccessoryAttached: %d\n", (conn_sts->ConnectorPartnerType == 6) ? 1 : 0); printf("RequestDataObject: 0x%x\n", conn_sts->RequestDataObject); printf("BatteryChargingCapabilityStatus: %d\n", conn_sts->BatteryChargingCapabilityStatus); printf(" NotCharging: %d\n", (conn_sts->BatteryChargingCapabilityStatus == 0) ? 1 : 0); printf(" NominalChargingRate: %d\n", (conn_sts->BatteryChargingCapabilityStatus == 1) ? 1 : 0); printf(" SlowChargingRate: %d\n", (conn_sts->BatteryChargingCapabilityStatus == 2) ? 1 : 0); printf(" VerySlowCharingRate: %d\n", (conn_sts->BatteryChargingCapabilityStatus == 3) ? 1 : 0); printf("ProviderCapabilitiesLimitedReason: %d\n", conn_sts->ProviderCapabilitiesLimitedReason); printf("bcdPDVersionOperationMode: "); hex_to_decimal(conn_sts->bcdPDVersionOperationMode); printf("Orientation: %d\n", conn_sts->Orientation); printf(" DirectOrientation : %d\n", (conn_sts->Orientation == 0) ? 1 : 0); printf(" FlippedOrientation : %d\n", (conn_sts->Orientation == 1) ? 1 : 0); printf("SinkPathStatus: %d\n", conn_sts->SinkPathStatus); printf("ReverseCurrentProtectionStatus: %d\n", conn_sts->ReverseCurrentProtectionStatus); printf("PowerReadingReady: %d\n", conn_sts->PowerReadingReady); printf("CurrentScale: %d\n", conn_sts->CurrentScale); printf("PeakCurrent: %d\n", conn_sts->PeakCurrent); printf("AverageCurrent: %d\n", conn_sts->AverageCurrent); printf("VoltageScale: %d\n", conn_sts->VoltageScale); printf("VoltageReading: %d\n", conn_sts->VoltageReading); printf("Voltage: %d\n", (conn_sts->VoltageReading * conn_sts->VoltageScale * 5)); } /** * Prints the USB-C Platform Policy Manager cable property data. * * @param cable_prop The structure containing the cable property data. */ void print_get_cable_property(struct libtypec_cable_property *cable_prop) { printf("UCSI MESSAGE_IN:\n"); printf("==================\n"); for (int i = 0; i < sizeof(*cable_prop); i++) { printf("%02x ", ((unsigned char*)cable_prop)[i]); if ((i + 1) % 8 == 0) { printf("\n"); } } printf("\n\nGET_CABLE_PROPERTY:\n"); printf("-------------------------\n"); printf("bmSpeedSupported: 0x%x\n", cable_prop->speed_supported); printf(" Bits/s: %d\n", ((cable_prop->speed_supported & 0x3) == 0) ? 1 : 0); printf(" Kb/s: %d\n", ((cable_prop->speed_supported & 0x3) == 1) ? 1 : 0); printf(" Mb/s: %d\n", ((cable_prop->speed_supported & 0x3) == 2) ? 1 : 0); printf(" Gb/s: %d\n", ((cable_prop->speed_supported & 0x3) == 3) ? 1 : 0); printf("bCurrentCapability: %d mA\n", cable_prop->current_capability * 50); printf("VBUSInCable: %d\n", cable_prop->vbus_support); printf("CableType: %d\n", cable_prop->cable_type); printf(" PassiveCable: %d\n", (cable_prop->cable_type == 0) ? 1 : 0); printf(" ActiveCable: %d\n", (cable_prop->cable_type == 1) ? 1 : 0); printf("Directionality: %d\n", cable_prop->directionality); printf("PlugEndType: %d\n", cable_prop->plug_end_type); printf(" USBtypeA: %d\n", (cable_prop->plug_end_type == 0) ? 1 : 0); printf(" USBtypeB: %d\n", (cable_prop->plug_end_type == 1) ? 1 : 0); printf(" USBtypeC: %d\n", (cable_prop->plug_end_type == 2) ? 1 : 0); printf(" Other: %d\n", (cable_prop->plug_end_type == 3) ? 1 : 0); printf("ModeSupport: %d\n", cable_prop->mode_support); printf("CablePDRevision: %d\n", cable_prop->cable_pd_revision); printf("Latency: %d\n", cable_prop->latency); } /** * Prints the USB-C Platform Policy Manager current cam data. * * @param cur_cam The structure containing the current cam data. */ void print_get_current_cam(struct libtypec_current_cam *cur_cam) { printf("UCSI MESSAGE_IN:\n"); printf("==================\n"); for (int i = 0; i < sizeof(*cur_cam); i++) { printf("%02x ", ((unsigned char*)cur_cam)[i]); if ((i + 1) % 8 == 0) { printf("\n"); } } printf("\n\nGET_CURRENT_CAM :\n"); printf("-------------------------\n"); for(int i = 0; i < 4; i++) { printf("CurrentAlternateMode[%d]: 0x%x\n", i, cur_cam->current_altmode[i]); } } /** * Prints the USB-C Platform Policy Manager connector altmodes data. * * @param * num_alt_mode number of alternate mode * alt_mode_data The structure containing the connector altmode data. */ void print_get_altmode(unsigned char num_alt_mode, struct altmode_data *alt_mode_data) { printf("UCSI MESSAGE_IN:\n"); printf("==================\n"); for (int i = 0; i < sizeof(*alt_mode_data); i++) { printf("%02x ", ((unsigned char*)alt_mode_data)[i]); if ((i + 1) % 8 == 0) { printf("\n"); } } printf("\n\nGET_ALTERNATE_MODE :\n"); printf("-------------------------\n"); for(int i = 0; i < num_alt_mode; i++) { printf("Mode [%d]\n", i); printf(" svid: 0x%x\n", alt_mode_data[i].svid); printf(" vdo : 0x%x\n", alt_mode_data[i].vdo); } } /** * Prints the USB-C Platform Policy Manager connector pdo data. * * @param * num_pdo number pdos * pdo_data The structure containing the connector pdo data. */ void print_get_pdos(unsigned char num_pdo, struct libtypec_get_pdos *pdo_data) { printf("UCSI MESSAGE_IN:\n"); printf("==================\n"); for (int i = 0; i < sizeof(*pdo_data); i++) { printf("%02x ", ((unsigned char*)pdo_data)[i]); if ((i + 1) % 8 == 0) { printf("\n"); } } printf("\n\nGET_PDOS :\n"); printf("-------------------------\n"); for(int i = 0; i < num_pdo; i++) { printf("PDO [%d]: 0x%x\n", i, pdo_data->pdo[i]); } } char *session_info[LIBTYPEC_SESSION_MAX_INDEX]; void ucsicontrol_print(const char *ucsictrl) { printf("Usage: %s [OPTIONS]\n", ucsictrl); printf("Options:\n"); printf(" --help, -h Show this help message\n"); printf(" --conn_rst Reset the Connector\n"); printf(" --get_cap Get Capabilities\n"); printf(" --get_conn_cap Get Connector Capability\n"); printf(" --get_conn_sts Get Connector Status\n"); printf(" --get_cable_prop Get Cable Properties\n"); printf(" --get_cur_cam Get Current Alternate mode\n"); printf(" --get_alt_mode Get Alternate Modes\n"); printf(" --get_pdos \n"); printf(" Get PDOS\n"); printf(" --set_uor Set USB(Data) Operation Role\n"); printf(" --set_pdr Set Power Direction Role\n"); } int main(int argc, char *argv[]) { int ret; int option_index = 0; int c, conn_num; static const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"conn_rst", required_argument, NULL, 't'}, {"get_cap", no_argument, NULL, 'g'}, {"get_conn_cap", required_argument, NULL, 'c'}, {"get_conn_sts", required_argument, NULL, 's'}, {"get_cable_prop", required_argument, NULL, 'p'}, {"get_cur_cam", required_argument, NULL, 'r'}, {"get_alt_mode", required_argument, NULL, 'a'}, {"get_pdos", required_argument, NULL, 'd'}, {"set_uor", required_argument, NULL, 'o'}, {"set_pdr", required_argument, NULL, 'e'}, {NULL, 0, NULL, 0} // End of options marker }; // Initialize libtypec and print session info ret = libtypec_init(session_info, LIBTYPEC_BACKEND_DBGFS); if (ret < 0) { printf("Failed in Initializing libtypec\n"); return -1; } while ((c = getopt_long(argc, argv, "htgcspradoe", long_options, &option_index)) != -1) { switch (c) { case 'h': ucsicontrol_print(argv[0]); return 0; case 't': conn_num = atoi(optarg); char reset_type[10]; int rst_type; strcpy(reset_type, argv[optind]); if(strcmp(reset_type, "soft") == 0) rst_type = 0; else if(strcmp(reset_type, "hard") == 0) rst_type = 1; else { printf("Invalid reset type: %s\n", reset_type); return -1; } if (conn_num < 0) { printf("Invalid connector number: %s\n", optarg); return -1; } ret = libtypec_connector_reset(conn_num, rst_type); if(ret < 0) printf("connector%d %s reset failed\n", conn_num, ((rst_type == 0) ? "soft" : "hard")); else printf("connector%d %s reset\n", conn_num, ((rst_type == 0) ? "soft" : "hard")); return 0; case 'g': ret = libtypec_get_capability(&cap_data); if (ret < 0) { printf("Failed in getting capabilities\n"); return -1; } print_get_capability(&cap_data); return 0; case 'c': conn_num = atoi(optarg); if (conn_num < 0) { printf("Invalid connector number: %s\n", optarg); return -1; } ret = libtypec_get_conn_capability(conn_num, &conn_cap); if (ret < 0) { printf("Failed in get connector capability for connector %d\n", conn_num); return -1; } print_get_connector_capability(&conn_cap); return 0; case 's': conn_num = atoi(optarg); if (conn_num < 0) { printf("Invalid connector number: %s\n", optarg); return -1; } ret = libtypec_get_connector_status(conn_num, &conn_sts); if (ret < 0) { printf("Failed in get connector status for connector %d\n", conn_num); return -1; } print_get_connector_status(&conn_sts); return 0; case 'p': conn_num = atoi(optarg); if (conn_num < 0) { printf("Invalid connector number: %s\n", optarg); return -1; } ret = libtypec_get_cable_properties(conn_num, &cable_prop); if (ret < 0) { printf("Failed in get cable property for connector %d\n", conn_num); return -1; } print_get_cable_property(&cable_prop); return 0; case 'r': conn_num = atoi(optarg); if (conn_num < 0) { printf("Invalid connector number: %s\n", optarg); return -1; } ret = libtypec_get_current_cam(conn_num, &cur_cam); if (ret < 0) { printf("Failed in get current cam for connector %d\n", conn_num); return -1; } print_get_current_cam(&cur_cam); return 0; case 'a': int num_alt_mode = 0; int recipient; conn_num = atoi(optarg); recipient = atoi(argv[optind]); if (conn_num < 0) { printf("Invalid connector number: %s\n", optarg); return -1; } num_alt_mode = libtypec_get_alternate_modes(recipient, conn_num, alt_mode_data); print_get_altmode(num_alt_mode, alt_mode_data); return 0; case 'd': int partner, offset, num_pdo = 0, src_snk, type; conn_num = atoi(optarg); partner = atoi(argv[3]); offset = atoi(argv[4]); src_snk = atoi(argv[5]); type = atoi(argv[6]); if (conn_num < 0) { printf("Invalid connector number: %s\n", optarg); return -1; } ret = libtypec_get_pdos(conn_num, partner, offset, &num_pdo, src_snk, type, &pdo_data_val); print_get_pdos(num_pdo, &pdo_data_val); return 0; case 'o': conn_num = atoi(optarg); char uor_type[10]; int uor; strcpy(uor_type, argv[optind]); if(strcmp(uor_type, "DFP") == 0) uor = 1; else if(strcmp(uor_type, "UFP") == 0) uor = 2; else if(strcmp(uor_type, "Accept") == 0) uor = 4; else printf("Invalid UOR type: %s\n", uor_type); ret = libtypec_set_uor_ops(conn_num, uor); if (ret < 0) printf("connector%d set data role operation %s failed\n", conn_num, uor_type); else printf("connector%d set data role operation %s\n", conn_num, uor_type); return 0; case 'e': conn_num = atoi(optarg); char pdr_type[10]; int pdr; strcpy(pdr_type, argv[optind]); if(strcmp(pdr_type, "SRC") == 0) pdr = 1; else if(strcmp(pdr_type, "SNK") == 0) pdr = 2; else if(strcmp(pdr_type, "Accept") == 0) pdr = 4; else { printf("Invalid PDR type: %s\n", pdr_type); return -1; } ret = libtypec_set_pdr_ops(conn_num, pdr); if (ret < 0) printf("connector%d power role swap operation %s failed", conn_num, pdr_type); else printf("connector%d power role swap operation %s\n", conn_num, pdr_type); return 0; default: ucsicontrol_print(argv[0]); return 0; } } // If no options were provided ucsicontrol_print(argv[0]); return 0; } libtypec-libtypec-0.6.0/utils/usbcview.c000077500000000000000000000337271472033722300203160ustar00rootroot00000000000000#include #include "../libtypec.h" #include "lstypec.h" #include "names.h" GtkTextBuffer *txt_buffer; // Function to create the tree store GtkTreeStore *create_tree_store() { int ret; GtkTreeStore *store = gtk_tree_store_new(1, G_TYPE_STRING); GtkTreeIter parent, child, grandchild; names_init(); // Initialize libtypec by default with sysfs and print session info ret = libtypec_init(session_info,LIBTYPEC_BACKEND_SYSFS); if (ret < 0) { show_error_dialog("Failed in Initializing libtypec"); return -1; } // Level 1 gtk_tree_store_append(store, &parent, NULL); gtk_tree_store_set(store, &parent, 0, "USB-C/PD Platform Policy", -1); // PPM Capabilities ret = libtypec_get_capability(&get_cap_data); if (ret < 0) { show_error_dialog("Failed in Get Capability"); return -1; } for (int i = 0; i < get_cap_data.bNumConnectors; i++) { char string[255]; gtk_tree_store_append(store, &child, &parent); sprintf (string, "Port: %d", i); gtk_tree_store_set(store, &child, 0, string, -1); } return store; } void build_vdo(uint32_t vdo, int num_fields, const struct vdo_field vdo_fields[], const char *vdo_field_desc[][MAX_FIELDS]) { char val[1024]; for (int i = 0; i < num_fields; i++) { if (!vdo_fields[i].print) continue; uint32_t field = (vdo >> vdo_fields[i].index) & vdo_fields[i].mask; sprintf(val," %s: %*d", vdo_fields[i].name, FIELD_WIDTH(MAX_FIELD_LENGTH - ((int) strlen(vdo_fields[i].name))), ((vdo >> vdo_fields[i].index) & vdo_fields[i].mask)); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); if (vdo_field_desc[i][0] != NULL) { // decode field sprintf(val," (%s)\n", vdo_field_desc[i][field]); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } else if (strcmp(vdo_fields[i].name, "USB Vendor ID") == 0) { // decode vendor id char vendor_str[128]; uint16_t svid = ((vdo >> vdo_fields[i].index) & vdo_fields[i].mask); get_vendor_string(vendor_str, sizeof(vendor_str), svid); sprintf(val," (%s)\n", (vendor_str[0] == '\0' ? "unknown" : vendor_str)); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } else { // No decoding sprintf(val,"\n"); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } } } void build_conn_capability(struct libtypec_connector_cap_data conn_data) { char *opr_mode_str[] = {"Rp Only", "Rd Only", "DRP(Rp/Rd)", "Analog Audio", "Debug Accessory", "USB2", "USB3", "Alternate Mode"}; char val[512]; sprintf(val," Operation Modes Supported: 0x%02x ", conn_data.opr_mode.raw_operationmode); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); for (int i = 0; i < sizeof(opr_mode_str) / sizeof(opr_mode_str[0]); i++) { if (conn_data.opr_mode.raw_operationmode & (1 << i)) { sprintf(val, "(%s)", opr_mode_str[i]); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } } sprintf(val,"\n"); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } void get_svid_string(uint32_t svid, char* str) { switch (svid) { case 0xFF01: strcpy(str, "Display Alternate Mode"); break; case 0x8087: strcpy(str, "TBT Alternate Mode"); break; default: get_vendor_string(str, sizeof(str), svid); break; } } void build_alternate_mode_data(int recipient, uint32_t id_header, int num_modes, struct altmode_data *am_data) { char vendor_id[128]; char val[512]; if (recipient == AM_CONNECTOR) { for (int i = 0; i < num_modes; i++) { get_svid_string(am_data[i].svid,vendor_id); sprintf(val," Local Mode %d:\n", i); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," SVID: 0x%04x (%s)\n", am_data[i].svid,vendor_id); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," VDO: 0x%08x\n", am_data[i].vdo); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); switch(am_data[i].svid){ case 0x8087: build_vdo(am_data[i].vdo, 7, tbt3_sop_fields, tbt3_sop_field_desc); break; case 0xff01: build_vdo(am_data[i].vdo, 7, dp_alt_mode_partner_fields, dp_alt_mode_partner_field_desc); break; default: get_vendor_string(vendor_id, sizeof(vendor_id), am_data[i].svid); sprintf(val," VDO Decoding not supported for 0x%04x (%s)\n", am_data[i].svid, (vendor_id[0] == '\0' ? "unknown" : vendor_id)); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); break; } } } if (recipient == AM_SOP) { for (int i = 0; i < num_modes; i++) { get_svid_string(am_data[i].svid,vendor_id); sprintf(val," Partner Mode %d:\n", i); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," SVID: 0x%04x (%s)\n", am_data[i].svid,vendor_id); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," VDO: 0x%08x\n", am_data[i].vdo); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); switch(am_data[i].svid){ case 0x8087: build_vdo(am_data[i].vdo, 7, tbt3_sop_fields, tbt3_sop_field_desc); break; case 0xff01: build_vdo(am_data[i].vdo, 7, dp_alt_mode_partner_fields, dp_alt_mode_partner_field_desc); break; default: get_vendor_string(vendor_id, sizeof(vendor_id), am_data[i].svid); sprintf(val," VDO Decoding not supported for 0x%04x (%s)\n", am_data[i].svid, (vendor_id[0] == '\0' ? "unknown" : vendor_id)); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); break; } } } if (recipient == AM_SOP_PR) { for (int i = 0; i < num_modes; i++) { get_svid_string(am_data[i].svid,vendor_id); sprintf(val," Cable Plug Modes %d:\n", i); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," SVID: 0x%04x (%s)\n", am_data[i].svid,vendor_id); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," VDO: 0x%08x\n", am_data[i].vdo); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); switch(am_data[i].svid){ case 0x8087: build_vdo(am_data[i].vdo, 7, tbt3_sop_pr_fields, tbt3_sop_pr_field_desc); break; case 0xff01: if ((id_header & ACTIVE_CABLE_MASK) == ACTIVE_CABLE_COMP) { build_vdo(am_data[i].vdo, 7, dp_alt_mode_active_cable_fields, dp_alt_mode_active_cable_field_desc); } else { get_vendor_string(vendor_id, sizeof(vendor_id), am_data[i].svid); sprintf(val," SVID Decoding not supported for 0x%04x (%s)\n", am_data[i].svid, (vendor_id[0] == '\0' ? "unknown" : vendor_id)); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } break; default: get_vendor_string(vendor_id, sizeof(vendor_id), am_data[i].svid); sprintf(val," SVID Decoding not supported for 0x%04x (%s)\n", am_data[i].svid, (vendor_id[0] == '\0' ? "unknown" : vendor_id)); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); break; } } } } void build_cable_prop(struct libtypec_cable_property cable_prop, int conn_num) { char *cable_type[] = {"Passive", "Active", "Unknown"}; char *cable_plug_type[] = {"USB Type A", "USB Type B", "USB Type C", "Non-USB Type", "Unknown"}; char val[512]; sprintf(val," Cable Property in Port %d:\n", conn_num); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," Cable Type: %s\n", cable_type[cable_prop.cable_type]); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," Cable Plug Type: %s\n", cable_plug_type[cable_prop.plug_end_type]); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } void build_capabilities_partner(int i) { int ret, opt, num_modes, num_pdos; // Partner num_modes = libtypec_get_alternate_modes(AM_SOP, i, am_data); if (num_modes >= 0) build_alternate_mode_data(AM_SOP, id.disc_id.id_header, num_modes, am_data); } void build_capabilities_cable(int i) { int ret, opt, num_modes, num_pdos; // Resetting port properties cable_prop.cable_type = CABLE_TYPE_UNKNOWN; cable_prop.plug_end_type = PLUG_TYPE_OTH; // Cable Properties ret = libtypec_get_cable_properties(i, &cable_prop); if (ret >= 0) build_cable_prop(cable_prop, i); // Cable num_modes = libtypec_get_alternate_modes(AM_SOP_PR, i, am_data); if (num_modes >= 0) build_alternate_mode_data(AM_SOP_PR, id.disc_id.id_header, num_modes, am_data); } void build_capabilities_port(int i) { int ret, opt, num_modes, num_pdos; char val[512]; // Connector Capabilities sprintf(val,"\nConnector %d Capability/Status\n", i); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); libtypec_get_conn_capability(i, &conn_data); build_conn_capability(conn_data); // Supported Alternate Modes sprintf(val," Alternate Modes Supported:\n"); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); num_modes = libtypec_get_alternate_modes(AM_CONNECTOR, i, am_data); if (num_modes > 0) build_alternate_mode_data(AM_CONNECTOR, 0x0, num_modes, am_data); else { sprintf(val," No Local Modes listed with typec class\n"); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } } void build_ppm_capability(struct libtypec_capability_data ppm_data) { char val[512]; sprintf(val,"\nUSB-C Platform Policy Manager Capability\n"); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," Number of Connectors: %x\n", ppm_data.bNumConnectors); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," Number of Alternate Modes: %x\n", ppm_data.bNumAltModes); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," USB Power Delivery Revision: %x.%x\n", (ppm_data.bcdPDVersion >> 8) & 0XFF, (ppm_data.bcdPDVersion) & 0XFF); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," USB Type-C Revision: %x.%x\n",(ppm_data.bcdTypeCVersion >> 8) & 0XFF, (ppm_data.bcdTypeCVersion) & 0XFF); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); sprintf(val," USB BC Revision: %x.%x\n", (ppm_data.bcdBCVersion >> 8) & 0XFF, (ppm_data.bcdBCVersion) & 0XFF); gtk_text_buffer_insert_at_cursor(txt_buffer, val,strlen(val)); } // Function to update the text buffer based on the selected tree item void on_tree_selection_changed(GtkTreeSelection *selection, gpointer data) { GtkTreeIter iter; GtkTreeModel *model; gchar *text; char string_data[1024]; GtkTextIter begin; GtkTextIter end; int num; gtk_text_buffer_get_start_iter(txt_buffer,&begin); gtk_text_buffer_get_end_iter(txt_buffer,&end); gtk_text_buffer_delete (txt_buffer, &begin, &end); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { gtk_tree_model_get(model, &iter, 0, &text, -1); GtkTextBuffer *buffer = (GtkTextBuffer *)data; if (strstr(text, "Port") != NULL) { char *p = strchr(text,' '); sscanf(p,"%d",&num); build_capabilities_port(num); build_capabilities_cable(num); build_capabilities_partner(num); } else { build_ppm_capability(get_cap_data); } g_free(text); } } void show_error_dialog(const gchar *message) { GtkWidget *dialog; gtk_init (NULL, NULL); dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message); gtk_window_set_title (GTK_WINDOW (dialog), "Error"); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } int main(int argc, char *argv[]) { int ret; gtk_init(&argc, &argv); // Create the main window GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "USB-C/PD Viewer"); gtk_window_set_default_size(GTK_WINDOW(window), 1080, 800); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); // Create the main layout (horizontal box) GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); gtk_container_add(GTK_CONTAINER(window), hbox); // Create the tree view GtkTreeStore *store = create_tree_store(); GtkWidget *treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes( "USB-C/PD - Ports/Partners", renderer, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); // Create the tree selection GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); // Create the text buffer txt_buffer = gtk_text_buffer_new(NULL); GtkWidget *textview = gtk_text_view_new_with_buffer(txt_buffer); gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE); // Connect the tree selection changed signal g_signal_connect(selection, "changed", G_CALLBACK(on_tree_selection_changed), txt_buffer); // Add the tree view and text view to the main layout GtkWidget *scrolled_window_tree = gtk_scrolled_window_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(scrolled_window_tree), treeview); gtk_box_pack_start(GTK_BOX(hbox), scrolled_window_tree, TRUE, TRUE, 0); GtkWidget *scrolled_window_text = gtk_scrolled_window_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(scrolled_window_text), textview); gtk_box_pack_start(GTK_BOX(hbox), scrolled_window_text, TRUE, TRUE, 0); // Show all widgets gtk_widget_show_all(window); gtk_main(); return 0; }