From 287a28f7891bd3d6a081ab3922001bdb1e8073b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 11 Feb 2025 22:21:56 +0100 Subject: [PATCH] Creation --- CMakeLists.txt | 5 + LICENSE | 502 ++++ README.md | 0 app/CMakeLists.txt | 11 + app/main.c | 21 + lib_jtag_core/CMakeLists.txt | 22 + lib_jtag_core/src/COPYING.LESSER | 502 ++++ lib_jtag_core/src/bsdl_parser/bsdl_loader.c | 1524 ++++++++++ lib_jtag_core/src/bsdl_parser/bsdl_loader.h | 81 + lib_jtag_core/src/bsdl_parser/bsdl_strings.c | 95 + lib_jtag_core/src/bsdl_parser/bsdl_strings.h | 77 + .../src/bus_over_jtag/i2c_over_jtag.c | 359 +++ .../src/bus_over_jtag/mdio_over_jtag.c | 292 ++ .../src/bus_over_jtag/memory_over_jtag.c | 325 ++ .../src/bus_over_jtag/spi_over_jtag.c | 290 ++ lib_jtag_core/src/config.script | 182 ++ lib_jtag_core/src/config_script.h | 500 ++++ lib_jtag_core/src/dbg_logs.c | 139 + lib_jtag_core/src/dbg_logs.h | 26 + lib_jtag_core/src/drivers/drivers_list.c | 65 + lib_jtag_core/src/drivers/drivers_list.h | 33 + lib_jtag_core/src/drivers/drv_loader.c | 120 + lib_jtag_core/src/drivers/drv_loader.h | 50 + .../src/drivers/ftdi_jtag/ftdi/WinTypes.h | 136 + .../src/drivers/ftdi_jtag/ftdi/ftd2xx.h | 1443 +++++++++ .../src/drivers/ftdi_jtag/ftdi_jtag_drv.c | 967 ++++++ .../src/drivers/ftdi_jtag/ftdi_jtag_drv.h | 26 + .../src/drivers/jlink_jtag/jlink_jtag_drv.c | 389 +++ .../src/drivers/jlink_jtag/jlink_jtag_drv.h | 26 + .../linux_gpio_jtag/linux_gpio_jtag_drv.c | 452 +++ .../linux_gpio_jtag/linux_gpio_jtag_drv.h | 26 + .../src/drivers/lpt_jtag/lpt_jtag_drv.c | 426 +++ .../src/drivers/lpt_jtag/lpt_jtag_drv.h | 26 + lib_jtag_core/src/jtag_core.c | 1112 +++++++ lib_jtag_core/src/jtag_core.h | 342 +++ lib_jtag_core/src/jtag_core_internal.h | 155 + lib_jtag_core/src/natsort/strnatcmp.c | 178 ++ lib_jtag_core/src/natsort/strnatcmp.h | 31 + lib_jtag_core/src/os_interface/fs.c | 597 ++++ lib_jtag_core/src/os_interface/network.c | 203 ++ lib_jtag_core/src/os_interface/network.h | 33 + lib_jtag_core/src/os_interface/os_interface.c | 672 +++++ lib_jtag_core/src/os_interface/os_interface.h | 126 + .../src/os_interface/win32/libjtagcore.def | 66 + .../src/os_interface/win32/libjtagcore.rc | 107 + lib_jtag_core/src/os_interface/win32/stdint.h | 247 ++ lib_jtag_core/src/script/env.c | 563 ++++ lib_jtag_core/src/script/env.h | 60 + lib_jtag_core/src/script/script.c | 2658 +++++++++++++++++ lib_jtag_core/src/script/script.h | 86 + lib_jtag_core/src/version.h | 16 + 51 files changed, 16390 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 100644 app/CMakeLists.txt create mode 100644 app/main.c create mode 100644 lib_jtag_core/CMakeLists.txt create mode 100644 lib_jtag_core/src/COPYING.LESSER create mode 100644 lib_jtag_core/src/bsdl_parser/bsdl_loader.c create mode 100644 lib_jtag_core/src/bsdl_parser/bsdl_loader.h create mode 100644 lib_jtag_core/src/bsdl_parser/bsdl_strings.c create mode 100644 lib_jtag_core/src/bsdl_parser/bsdl_strings.h create mode 100644 lib_jtag_core/src/bus_over_jtag/i2c_over_jtag.c create mode 100644 lib_jtag_core/src/bus_over_jtag/mdio_over_jtag.c create mode 100644 lib_jtag_core/src/bus_over_jtag/memory_over_jtag.c create mode 100644 lib_jtag_core/src/bus_over_jtag/spi_over_jtag.c create mode 100644 lib_jtag_core/src/config.script create mode 100644 lib_jtag_core/src/config_script.h create mode 100644 lib_jtag_core/src/dbg_logs.c create mode 100644 lib_jtag_core/src/dbg_logs.h create mode 100644 lib_jtag_core/src/drivers/drivers_list.c create mode 100644 lib_jtag_core/src/drivers/drivers_list.h create mode 100644 lib_jtag_core/src/drivers/drv_loader.c create mode 100644 lib_jtag_core/src/drivers/drv_loader.h create mode 100644 lib_jtag_core/src/drivers/ftdi_jtag/ftdi/WinTypes.h create mode 100644 lib_jtag_core/src/drivers/ftdi_jtag/ftdi/ftd2xx.h create mode 100644 lib_jtag_core/src/drivers/ftdi_jtag/ftdi_jtag_drv.c create mode 100644 lib_jtag_core/src/drivers/ftdi_jtag/ftdi_jtag_drv.h create mode 100644 lib_jtag_core/src/drivers/jlink_jtag/jlink_jtag_drv.c create mode 100644 lib_jtag_core/src/drivers/jlink_jtag/jlink_jtag_drv.h create mode 100644 lib_jtag_core/src/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.c create mode 100644 lib_jtag_core/src/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.h create mode 100644 lib_jtag_core/src/drivers/lpt_jtag/lpt_jtag_drv.c create mode 100644 lib_jtag_core/src/drivers/lpt_jtag/lpt_jtag_drv.h create mode 100644 lib_jtag_core/src/jtag_core.c create mode 100644 lib_jtag_core/src/jtag_core.h create mode 100644 lib_jtag_core/src/jtag_core_internal.h create mode 100644 lib_jtag_core/src/natsort/strnatcmp.c create mode 100644 lib_jtag_core/src/natsort/strnatcmp.h create mode 100644 lib_jtag_core/src/os_interface/fs.c create mode 100644 lib_jtag_core/src/os_interface/network.c create mode 100644 lib_jtag_core/src/os_interface/network.h create mode 100644 lib_jtag_core/src/os_interface/os_interface.c create mode 100644 lib_jtag_core/src/os_interface/os_interface.h create mode 100644 lib_jtag_core/src/os_interface/win32/libjtagcore.def create mode 100644 lib_jtag_core/src/os_interface/win32/libjtagcore.rc create mode 100644 lib_jtag_core/src/os_interface/win32/stdint.h create mode 100644 lib_jtag_core/src/script/env.c create mode 100644 lib_jtag_core/src/script/env.h create mode 100644 lib_jtag_core/src/script/script.c create mode 100644 lib_jtag_core/src/script/script.h create mode 100644 lib_jtag_core/src/version.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fcb5102 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.10) +project(BoundaryScan) + +add_subdirectory(lib_jtag_core) +add_subdirectory(app) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/LICENSE @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..8b47ed1 --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,11 @@ + +# Application configuration +add_executable( + bs + main.c +) + +# linking configuration +target_link_libraries( + bs PRIVATE jtag_core +) \ No newline at end of file diff --git a/app/main.c b/app/main.c new file mode 100644 index 0000000..6bbcdb1 --- /dev/null +++ b/app/main.c @@ -0,0 +1,21 @@ +#include + +#include "jtag_core.h" + + +void jtcprint(jtag_core *jc, const char *msg) { + printf(msg); +} + +int main(int argc, char **argv) { + + jtag_core *jc; + + jc = jtagcore_init(); + if (jtagcore_set_logs_callback(jc, jtcprint) < 0) goto end; + +end: + jtagcore_deinit(jc); + printf("Finished."); + return 0; +} \ No newline at end of file diff --git a/lib_jtag_core/CMakeLists.txt b/lib_jtag_core/CMakeLists.txt new file mode 100644 index 0000000..89c5c20 --- /dev/null +++ b/lib_jtag_core/CMakeLists.txt @@ -0,0 +1,22 @@ +set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") + +file(GLOB_RECURSE ALL_SOURCES "src/*.c") + +# Custom command to be executed before the build +add_custom_command( + OUTPUT prebuild_command_done + COMMAND cd "${SOURCE_DIR}" && xxd -i config.script > config_script.h + COMMENT "Generating the config script" + VERBATIM +) + +# Custom target that depends on the custom command +add_custom_target( + prebuild ALL + DEPENDS prebuild_command_done +) + +add_library(jtag_core ${ALL_SOURCES}) +add_dependencies(jtag_core prebuild) + +target_include_directories(jtag_core PUBLIC ${SOURCE_DIR}) \ No newline at end of file diff --git a/lib_jtag_core/src/COPYING.LESSER b/lib_jtag_core/src/COPYING.LESSER new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/lib_jtag_core/src/COPYING.LESSER @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/lib_jtag_core/src/bsdl_parser/bsdl_loader.c b/lib_jtag_core/src/bsdl_parser/bsdl_loader.c new file mode 100644 index 0000000..4f32909 --- /dev/null +++ b/lib_jtag_core/src/bsdl_parser/bsdl_loader.c @@ -0,0 +1,1524 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bsdl_loader.c + * @brief bsdl file parser + * @author Jean-François DEL NERO + */ + +#include +#include +#include +#include +#include + +#include "../drivers/drv_loader.h" +#include "../jtag_core_internal.h" +#include "../jtag_core.h" + +#include "bsdl_loader.h" +#include "bsdl_strings.h" + +#include "../natsort/strnatcmp.h" + +#include "../os_interface/os_interface.h" + +#include "../dbg_logs.h" +#define DEBUG 1 + +char *string_upper(char *str) +{ + while (*str != '\0') + { + *str = toupper((unsigned char)*str); + str++; + } + return str; +} + +int strcmp_nocase(char *str1,char *str2) +{ + int d; + + for(;; str1++, str2++) + { + d = tolower(*str1) - tolower(*str2); + + if(d != 0 || !*str1) + return d; + } + + return 0; +} + +int getnextvalidline(char *buffer,int buffersize,int * offset) +{ + int l_offset; + int current_line_offset; + + l_offset = *offset; + current_line_offset = *offset; + + do + { + // Skip all the blank characters + while( (l_offset < buffersize) && (buffer[l_offset] == ' ' || buffer[l_offset] == '\t') ) + { + l_offset++; + } + + // End of buffer reached ? + if(l_offset == buffersize) + { + *offset = l_offset; + + return 1; + } + + // Is it a return or comment ? + if( buffer[l_offset] != '\r' && buffer[l_offset] != '\n' && (buffer[l_offset] != '-' || buffer[l_offset+1] != '-')) + { + // No. There is something interesting into this line. + *offset = current_line_offset; + return 0; + } + else + { + // Is it a comment ? + if(buffer[l_offset] == '-' && buffer[l_offset+1] == '-') + { + // Yes. Go to the end of the line... + while(buffer[l_offset] != 0 && buffer[l_offset] != '\r' && buffer[l_offset] != '\n') + { + l_offset += 1; + } + } + } + + if( buffer[l_offset] == '\r' || buffer[l_offset] == '\n') + { + l_offset++; + + if(l_offset < buffersize) + { + if( buffer[l_offset] == '\n' ) + { + l_offset++; + } + } + + current_line_offset = l_offset; + } + }while ( (l_offset < buffersize) && buffer[l_offset] ); + + *offset = l_offset; + + return 1; +} + +char getnextchar(char *buffer,int buffersize,int * offset) +{ + char c; + + if (*offset < buffersize) + { + c = buffer[*offset]; + + switch (c) + { + case 0: + return 0; + break; + + case '\r': + *offset += 1; + + if (*offset < buffersize) + { + if (buffer[*offset] == '\n') + { + *offset += 1; + } + + getnextvalidline(buffer, buffersize, offset); + } + + return ' '; + break; + case '\t': + *offset += 1; + return ' '; + break; + case '\n': + *offset += 1; + getnextvalidline(buffer, buffersize, offset); + return ' '; + break; + case '-': + if (buffer[*offset + 1] == '-') + { + while ((*offset < buffersize) && buffer[*offset] != 0 && buffer[*offset] != '\r' && buffer[*offset] != '\n') + { + *offset += 1; + } + + if (*offset < buffersize) + { + if (buffer[*offset] == '\r') + { + *offset += 1; + if (buffer[*offset] == '\n') + { + *offset += 1; + } + + getnextvalidline(buffer, buffersize, offset); + + return ' '; + } + + if (buffer[*offset] == '\n') + { + *offset += 1; + getnextvalidline(buffer, buffersize, offset); + + return ' '; + } + } + else + return 0; + + return ' '; + } + else + { + *offset += 1; + return '-'; + } + + break; + + default: + *offset += 1; + return c; + break; + } + } + + return 0; +} + +int extract_bsdl_lines(char * bsdl_txt, char ** lines) +{ + int offset; + int line_start_offset; + int line_end_offset; + int endofline; + int parenthesis_number; + int inside_quote; + int number_of_lines; + + offset = 0; + number_of_lines = 0; + + do + { + // Find the first word offset into the line... + while( bsdl_txt[offset] ==' ' && bsdl_txt[offset] ) + { + offset++; + } + + line_start_offset = offset; + + parenthesis_number = 0; + endofline = 0; + inside_quote = 0; + + // Scan the line + while( !endofline ) + { + switch( bsdl_txt[offset] ) + { + case 0: + endofline = 1; + break; + + case '(': + if( !inside_quote ) + parenthesis_number++; + offset++; + break; + case ')': + if(parenthesis_number && !inside_quote) + parenthesis_number--; + offset++; + break; + case ';': + if( !parenthesis_number && !inside_quote ) + { + line_end_offset = offset; + + if( line_end_offset - line_start_offset > 0 ) + { + if(lines) + { + lines[number_of_lines] = malloc( (line_end_offset - line_start_offset) + 2 ); + if( lines[number_of_lines] ) + { + memset(lines[number_of_lines],0, (line_end_offset - line_start_offset) + 2 ); + memcpy(lines[number_of_lines],&bsdl_txt[line_start_offset], (line_end_offset - line_start_offset) ); + } + } + + number_of_lines++; + } + + endofline = 1; + + } + offset++; + break; + + case '"': + if(!inside_quote) + inside_quote = 1; + else + inside_quote = 0; + + offset++; + break; + + default: + offset++; + break; + } + } + }while(bsdl_txt[offset]); + + return number_of_lines; +} + +void preprocess_line(char * line) +{ + int inside_quote; + int read_offset,write_offset; + int is_string; + int number_of_spaces; + + inside_quote = 0; + read_offset = 0; + write_offset = 0; + number_of_spaces = 0; + + if(!line) + return; + + // first pass : remove extra blank + while( line[read_offset] ) + { + switch( line[read_offset] ) + { + case ' ': + + if(!number_of_spaces || inside_quote) + { + line[write_offset] = line[read_offset]; + write_offset++; + } + + read_offset++; + number_of_spaces++; + + break; + + case '"': + if(!inside_quote) + inside_quote = 1; + else + inside_quote = 0; + + line[write_offset] = line[read_offset]; + write_offset++; + read_offset++; + number_of_spaces = 0; + + break; + + default: + line[write_offset] = line[read_offset]; + number_of_spaces = 0; + + write_offset++; + read_offset++; + break; + + } + } + + line[write_offset] = 0; + + // second pass : concatenate strings. + + inside_quote = 0; + read_offset = 0; + write_offset = 0; + number_of_spaces = 0; + is_string = 0; + + while( line[read_offset] ) + { + switch( line[read_offset] ) + { + + case '&': + if( inside_quote || !is_string) + { + line[write_offset] = line[read_offset]; + write_offset++; + } + read_offset++; + break; + + case ' ': + if( inside_quote || !is_string) + { + line[write_offset] = line[read_offset]; + write_offset++; + } + read_offset++; + break; + + case '"': + if(!inside_quote) + { + inside_quote = 1; + if( !is_string ) + { + line[write_offset] = line[read_offset]; + write_offset++; + } + + is_string = 1; + } + else + { + inside_quote = 0; + + } + + read_offset++; + break; + + default: + if( !inside_quote ) + { + if( is_string ) + { + line[write_offset] = '"'; + write_offset++; + } + is_string = 0; + } + + line[write_offset] = line[read_offset]; + + write_offset++; + read_offset++; + break; + + } + } + + if( is_string ) + { + line[write_offset] = '"'; + write_offset++; + line[write_offset] = 0; + } +}; + +char * check_next_keyword(char * buffer, char * keyword, char sep) +{ + int i; + char sep_list[16]; + + sep_list[0] = sep; + sep_list[1] = '\0'; + strcat((char*)sep_list,"\"() "); + + if( !buffer ) + return 0; + + // skip the current word + i = 0; + while (buffer[i] && !strchr(sep_list, buffer[i]) ) + { + i++; + } + + // skip the following blank + while (buffer[i] && strchr(sep_list, buffer[i]) ) + { + i++; + } + + if( !strncmp(&buffer[i],keyword,strlen(keyword)) ) + { + return &buffer[i + strlen(keyword)]; + } + + return 0; +} + +int get_next_keyword(jtag_core * jc,char * buffer, char * keyword) +{ + int i,j; + + if( !buffer ) + return 0; + + // skip the current word + i = 0; + while (buffer[i] && !strchr("\"():, ", buffer[i]) ) + { + i++; + } + + // skip the following blank + while (buffer[i] && strchr("\"():, ", buffer[i])) + { + i++; + } + + // copy the word + j = 0; + while (buffer[i] && !strchr("\"():;, ", buffer[i])) + { + if(j < MAX_ELEMENT_SIZE-1) + { + keyword[j] = buffer[i]; + j++; + } + i++; + } + + keyword[j] = 0; + + if( j >= (MAX_ELEMENT_SIZE-1) ) + { + jtagcore_logs_printf(jc,MSG_WARNING,"BSDL loader / get_next_keyword : element too long / truncated : %s\r\n",keyword); + } + + return i; +} + +int get_next_parameter(jtag_core * jc,char * buffer, char * parameter) +{ + int i,j; + + if( !buffer ) + return 0; + + // skip the current word + i = 0; + while (buffer[i] && !strchr("\":, ", buffer[i])) + { + i++; + } + + // skip the following blank + while (buffer[i] && strchr("\":, ", buffer[i])) + { + i++; + } + + // copy the word + j = 0; + while (buffer[i] && !strchr("\":, ;", buffer[i])) + { + if(j < MAX_ELEMENT_SIZE-1) + { + parameter[j] = buffer[i]; + j++; + } + i++; + } + + parameter[j] = 0; + + if( j >= (MAX_ELEMENT_SIZE-1) ) + { + jtagcore_logs_printf(jc,MSG_WARNING,"BSDL loader / get_next_parameter : element too long / truncated : %s\r\n",parameter); + } + + return i; +} + +int check_next_symbol(char * buffer, char c ) +{ + int i; + + if( !buffer ) + return 0; + + // skip the current word + i = 0; + while (buffer[i] && !strchr("\"(): ", buffer[i]) && buffer[i] != c) + { + i++; + } + + // skip the following blank + while(buffer[i] && ( buffer[i] == ' ') ) + { + i++; + } + + if( buffer[i] == c ) + { + return i; + } + else + { + return -1; + } +} + +char * get_attribut(char ** lines,char * name, char * entity) +{ + int i,j; + char * ptr; + i = 0; + + while( lines[i] ) + { + if(!strncmp(lines[i],"attribute ",10)) + { + if(!strncmp(&lines[i][10],name,strlen(name))) + { + ptr = check_next_keyword(&lines[i][10], "of", '\0'); + ptr = check_next_keyword(ptr, entity, ':'); + + if( ptr ) + { + j = 0; + while( ptr[j] && ptr[j] != ':' && ptr[j] == ' ') + { + j++; + } + + if( ptr[j] == ':' ) + { + ptr = check_next_keyword(&ptr[j], "entity", ':'); + ptr = check_next_keyword(ptr, "is", '\0'); + + return ptr; + } + } + + return NULL; + } + } + i++; + } + + return NULL; +} + +char * get_attribut_txt(char ** lines,char * name, char * entity) +{ + int i; + char * attribut_data; + + attribut_data = get_attribut(lines,name, entity); + + if( attribut_data ) + { + i = 0; + while( attribut_data[i] && attribut_data[i]!='"') + { + i++; + } + + if( attribut_data[i] == '"' ) + { + return &attribut_data[i]; + } + + return 0; + } + + return 0; +} + +int get_attribut_int(char ** lines,char * name, char * entity) +{ + int i; + char * attribut_data; + + attribut_data = get_attribut(lines,name, entity); + + if( attribut_data ) + { + i = 0; + while( attribut_data[i] && !( attribut_data[i]>='0' && attribut_data[i]<='9' ) ) + { + i++; + } + + if( ( attribut_data[i]>='0' && attribut_data[i]<='9' ) ) + { + return atoi(&attribut_data[i]); + } + + return 0; + } + + return 0; +} + +int get_next_pin(jtag_core * jc,char * name,int * type, char *line, int * start_index, int * end_index ) +{ + int i; + int io_list_offset; + char tmp_str[256]; + int line_parsed,inside_block; + + i = get_next_keyword(jc,line,name); + + io_list_offset = 0; + + while(line[i] == ' ') + i++; + + if( line[i] == ':' || line[i] == ',' ) + { + *start_index = 0; + *end_index = 0; + + if( line[i] == ',' ) + { + io_list_offset = i + 1; + + while(line[i] != ':' && line[i] != ';' && line[i]) + i++; + if( line[i] != ':' ) + return 0; + } + + i += get_next_keyword(jc,&line[i],(char*)&tmp_str); + + string_upper(tmp_str); + + *type = get_typecode(pintype_str,tmp_str); + + i += get_next_keyword(jc,&line[i],(char*)&tmp_str); + + if (!strcmp_nocase("bit_vector",tmp_str)) + { + while(line[i] != '(' && line[i] != ')' && line[i] != ';') + { + i++; + } + + line_parsed = 0; + inside_block = 0; + + do + { + + switch( line[i] ) + { + case '(': + inside_block++; + if(!line_parsed) + { + i += get_next_keyword(jc,&line[i],(char*)&tmp_str); + *start_index = atoi(tmp_str); + + i += get_next_keyword(jc,&line[i],(char*)&tmp_str); + + i += get_next_keyword(jc,&line[i],(char*)&tmp_str); + *end_index = atoi(tmp_str); + + line_parsed = 1; + + } + break; + case ')': + if ( !inside_block ) + { + return 0; + } + + inside_block--; + break; + case ';': + if( io_list_offset ) + return io_list_offset; + else + return i; + break; + case 0: + break; + + } + i++; + }while (line[i]); + + return 0; + } + + if (!strcmp_nocase("bit",tmp_str)) + { + do + { + switch( line[i] ) + { + case ';': + if( io_list_offset ) + return io_list_offset; + else + return i; + break; + case 0: + break; + } + i++; + }while (line[i]); + } + + } + + return 0; +} + +int get_pins_list(jtag_core * jc,jtag_bsdl * bsdl_desc,char ** lines) +{ + int i,j,k,inc,offset, number_of_pins,vector_size; + char tmp_str[MAX_ELEMENT_SIZE]; + int tmp_type,tmp_start,tmp_end; + i = 0; + + while( lines[i] ) + { + if( !strncmp(lines[i],"port ",5) || !strncmp(lines[i],"port(",5)) + { + j = 0; + number_of_pins = 0; + + while( lines[i][j] != '(' && lines[i][j]) + { + j++; + } + + do + { + offset = get_next_pin(jc,(char*)&tmp_str,&tmp_type, &lines[i][j], &tmp_start, &tmp_end ); + + if( tmp_start <=tmp_end) + { + number_of_pins += ( (tmp_end - tmp_start) + 1 ); + } + else + { + number_of_pins += ( (tmp_start - tmp_end) + 1 ); + } + + j += offset; + + } while( offset); + + if (number_of_pins == 0 || ( number_of_pins > MAX_NUMBER_PINS_PER_DEV ) ) + { + jtagcore_logs_printf(jc, MSG_ERROR, "get_pins_list : bad number of pin found ! : %d\r\n", number_of_pins); + return -1; + } + + bsdl_desc->pins_list = malloc (sizeof(pin_ctrl) * (number_of_pins+1)); + if( bsdl_desc->pins_list ) + { + memset( bsdl_desc->pins_list, 0, sizeof(pin_ctrl) * (number_of_pins+1) ); + + j = 0; + number_of_pins = 0; + + while( lines[i][j] != '(' && lines[i][j]) + { + j++; + } + + do + { + offset = get_next_pin(jc,(char*)&tmp_str,&tmp_type, &lines[i][j], &tmp_start, &tmp_end ); + + if( tmp_start <= tmp_end ) + { + vector_size = ( (tmp_end - tmp_start) + 1 ); + inc = 1; + } + else + { + vector_size = ( (tmp_start - tmp_end) + 1 ); + inc = -1; + } + + j += offset; + + for(k = 0;k < vector_size; k++) + { + snprintf((char*)&bsdl_desc->pins_list[number_of_pins].pinname,sizeof(((pin_ctrl *)0)->pinname),"%s",(char*)tmp_str); + + if( vector_size > 1 ) + { + char digistr[32]; + snprintf((char*)digistr,sizeof(digistr),"(%d)",tmp_start); + genos_strndstcat((char*)&bsdl_desc->pins_list[number_of_pins].pinname,digistr,sizeof(((pin_ctrl *)0)->pinname)); + } + bsdl_desc->pins_list[number_of_pins].pinname[sizeof(((pin_ctrl *)0)->pinname)-1] = '\0'; + + bsdl_desc->pins_list[number_of_pins].pintype = tmp_type; + number_of_pins++; + tmp_start += inc; + } + + } while( offset ); + + bsdl_desc->number_of_pins = number_of_pins; + + return number_of_pins; + } + } + i++; + }; + + return 0; +} + +int get_jtag_chain(jtag_core * jc,jtag_bsdl * bsdl_desc,char ** lines, char * entityname) +{ + char * jtagchain_str; + int i,j,bit_count,end_parse; + char tmp_str[MAX_ELEMENT_SIZE]; + int bit_index; + + bit_count = 0; + bsdl_desc->number_of_chainbits = get_attribut_int(lines,"BOUNDARY_LENGTH", entityname); + if ( ( bsdl_desc->number_of_chainbits > 0 ) && ( bsdl_desc->number_of_chainbits < MAX_NUMBER_BITS_IN_CHAIN ) ) + { + jtagcore_logs_printf(jc,MSG_DEBUG,"Number of bit in the chain = %d\r\n",bsdl_desc->number_of_chainbits); + + bsdl_desc->chain_list = malloc( sizeof(jtag_chain) * bsdl_desc->number_of_chainbits ); + if( !bsdl_desc->chain_list ) + { + jtagcore_logs_printf(jc,MSG_ERROR,"get_jtag_chain : memory alloc error !\r\n"); + return -1; + } + + memset(bsdl_desc->chain_list,0, sizeof(jtag_chain) * bsdl_desc->number_of_chainbits ); + + jtagchain_str = get_attribut_txt(lines,"BOUNDARY_REGISTER", entityname); + + end_parse = 0; + + if(jtagchain_str) + { + if( jtagchain_str[0] == '"' ) + { + i = 0; + while( jtagchain_str[i] && !end_parse ) + { + jtagcore_logs_printf(jc,MSG_DEBUG,"--------------\r\n"); + + // Get index + i += get_next_keyword(jc,&jtagchain_str[i], tmp_str); + bit_index = atoi(tmp_str); + if (bit_index >= 0 && bit_index < bsdl_desc->number_of_chainbits) + { + bsdl_desc->chain_list[bit_index].bit_index = bit_index; + + jtagcore_logs_printf(jc, MSG_DEBUG, "%d\r\n", bsdl_desc->chain_list[bit_index].bit_index); + + // Look for ( + while (jtagchain_str[i] != '(' && jtagchain_str[i]) + i++; + + // Get the pin type + i += get_next_keyword(jc,&jtagchain_str[i], tmp_str); + string_upper(tmp_str); + bsdl_desc->chain_list[bit_index].bit_cell_type = get_typecode(celltype_str, tmp_str); + + jtagcore_logs_printf(jc, MSG_DEBUG, "%d\r\n", bsdl_desc->chain_list[bit_index].bit_cell_type); + + // , + j = check_next_symbol(&jtagchain_str[i], ','); + if (j < 0) + return -1; + i += j; + + // Get the name + i += get_next_parameter(jc,&jtagchain_str[i], bsdl_desc->chain_list[bit_index].pinname); + + jtagcore_logs_printf(jc, MSG_DEBUG, "%s\r\n", bsdl_desc->chain_list[bit_index].pinname); + + // , + j = check_next_symbol(&jtagchain_str[i], ','); + if (j < 0) + return -1; + i += j; + + // Get the type + i += get_next_keyword(jc,&jtagchain_str[i], tmp_str); + string_upper(tmp_str); + bsdl_desc->chain_list[bit_index].bit_type = get_typecode(bittype_str, tmp_str); + + jtagcore_logs_printf(jc, MSG_DEBUG, "%s , %d\r\n", tmp_str, bsdl_desc->chain_list[bit_index].bit_type); + + // , + j = check_next_symbol(&jtagchain_str[i], ','); + if (j < 0) + return -1; + i += j; + + // Get the default state + i += get_next_keyword(jc,&jtagchain_str[i], tmp_str); + string_upper(tmp_str); + bsdl_desc->chain_list[bit_index].safe_state = get_typecode(statetype_str, tmp_str); + + bsdl_desc->chain_list[bit_index].control_bit_index = -1; + + // If no ) Get the ctrl index + j = check_next_symbol(&jtagchain_str[i], ')'); + + if (jtagchain_str[i]==',' || j < 0) + { + // , + j = check_next_symbol(&jtagchain_str[i], ','); + if (j < 0) + return -1; + i += j; + + // Get the control bit + i += get_next_keyword(jc,&jtagchain_str[i], tmp_str); + + bsdl_desc->chain_list[bit_index].control_bit_index = atoi(tmp_str); + + j = check_next_symbol(&jtagchain_str[i], ','); + if (j < 0) + return -1; + i += j; + + // Get the polarity + i += get_next_keyword(jc,&jtagchain_str[i], tmp_str); + string_upper(tmp_str); + bsdl_desc->chain_list[bit_index].control_disable_state = get_typecode(statetype_str, tmp_str); + + j = check_next_symbol(&jtagchain_str[i], ','); + if (j < 0) + return -1; + i += j; + + // Get the off state + i += get_next_keyword(jc,&jtagchain_str[i], tmp_str); + string_upper(tmp_str); + bsdl_desc->chain_list[bit_index].control_disable_result = get_typecode(statetype_str, tmp_str); + + // Find and skip ) + j = check_next_symbol(&jtagchain_str[i], ')'); + if (j < 0) + return -1; + } + + i += j; + + // Find , (Next bit) or " (End of the chain) + i++; + bit_count++; + + if (check_next_symbol(&jtagchain_str[i], '"') >= 0) + { + end_parse = 1; + } + } + else + { + jtagcore_logs_printf(jc, MSG_ERROR, "get_jtag_chain : Error bit index overrun !\r\n"); + } + } + } + } + } + + if( ( bit_count == bsdl_desc->number_of_chainbits ) && ( bsdl_desc->number_of_chainbits != 0 ) ) + { + jtagcore_logs_printf(jc,MSG_DEBUG,"Jtag chain parsing Ok !\r\n"); + + for( i = 0 ; i < (long)bsdl_desc->number_of_pins ; i++ ) + { + + bsdl_desc->pins_list[i].in_bit_number = -1; + bsdl_desc->pins_list[i].out_bit_number = -1; + bsdl_desc->pins_list[i].ctrl_bit_number = -1; + + switch( bsdl_desc->pins_list[i].pintype) + { + case IO_IN: + case IO_OUT: + case IO_INOUT: + + for( j = 0 ; j < (long)bsdl_desc->number_of_chainbits ; j++ ) + { + if(!strcmp(bsdl_desc->chain_list[j].pinname, bsdl_desc->pins_list[i].pinname)) + { + switch( bsdl_desc->chain_list[j].bit_type) + { + case BITTYPE_INPUT: + bsdl_desc->pins_list[i].in_bit_number = bsdl_desc->chain_list[j].bit_index; + break; + case BITTYPE_OUTPUT: + bsdl_desc->pins_list[i].out_bit_number = bsdl_desc->chain_list[j].bit_index; + break; + case BITTYPE_TRISTATE_OUTPUT: + bsdl_desc->pins_list[i].out_bit_number = bsdl_desc->chain_list[j].bit_index; + bsdl_desc->pins_list[i].ctrl_bit_number = bsdl_desc->chain_list[j].control_bit_index; + break; + case BITTYPE_INOUT: + bsdl_desc->pins_list[i].in_bit_number = bsdl_desc->chain_list[j].bit_index; + bsdl_desc->pins_list[i].out_bit_number = bsdl_desc->chain_list[j].bit_index; + bsdl_desc->pins_list[i].ctrl_bit_number = bsdl_desc->chain_list[j].control_bit_index; + break; + } + } + } + break; + } + } + + return 1; + } + else + { + jtagcore_logs_printf(jc,MSG_DEBUG,"JTAG chain parsing error : %d - %d !\r\n",bit_count,bsdl_desc->number_of_chainbits); + return -1; + } +} + +static int compare_pin_name(const void *a, const void *b) +{ + int ret; + pin_ctrl const *pa = (pin_ctrl const *)a; + pin_ctrl const *pb = (pin_ctrl const *)b; + + ret = strnatcmp(pa->pinname, pb->pinname); + + return ret; +} + +jtag_bsdl * load_bsdlfile(jtag_core * jc,char *filename) +{ + FILE * bsdl_file; + jtag_bsdl * bsdl; + int file_size,offset; + char * bsdl_txt,*tmp_bsdl_txt; + char * tmp_ptr; + int i,number_of_bsdl_lines; + char entityname[256]; + char * chipid_str,* instruct_str; + char * instruct_strchr; + char ** lines; + + jtagcore_logs_printf(jc,MSG_INFO_0,"Open BSDL file %s\r\n",filename); + + bsdl = 0; + + bsdl_file = fopen(filename,"rb"); + if (bsdl_file) + { + fseek(bsdl_file, 0, SEEK_END); + file_size = ftell(bsdl_file); + fseek(bsdl_file, 0, SEEK_SET); + + if ( file_size <= 0 || file_size > MAX_BSDL_FILE_SIZE ) + { + jtagcore_logs_printf(jc, MSG_ERROR, "Bad BSDL File size ! : %d\r\n", file_size); + fclose(bsdl_file); + return 0; + } + + jtagcore_logs_printf(jc, MSG_DEBUG, "BSDL file size : %d\r\n", file_size); + + bsdl_txt = malloc(file_size + 1); + if (bsdl_txt) + { + memset(bsdl_txt, 0, file_size + 1); + if( fread(bsdl_txt, file_size, 1, bsdl_file) != 1 ) + { + free(bsdl_txt); + jtagcore_logs_printf(jc, MSG_ERROR, "BSDL File read error !\r\n"); + fclose(bsdl_file); + return 0; + } + + tmp_bsdl_txt = malloc(file_size + 1); + if (tmp_bsdl_txt) + { + memset(tmp_bsdl_txt, 0, file_size + 1); + offset = 0; + + i = 0; + while (offset < file_size && i < file_size) + { + tmp_bsdl_txt[i] = getnextchar(bsdl_txt, file_size, &offset); + i++; + } + + free(bsdl_txt); + + if (offset < i) + { + jtagcore_logs_printf(jc, MSG_ERROR, "Preprocessing error !\r\n"); + free(tmp_bsdl_txt); + return 0; + } + + bsdl_txt = tmp_bsdl_txt; + } + else + { + jtagcore_logs_printf(jc, MSG_ERROR, "Can't allocate file memory !\r\n"); + free(bsdl_txt); + fclose(bsdl_file); + return 0; + } + } + else + { + jtagcore_logs_printf(jc, MSG_ERROR, "Can't allocate file memory !\r\n"); + fclose(bsdl_file); + return 0; + } + } + else + { + jtagcore_logs_printf(jc, MSG_ERROR, "Can't open %s !\r\n", filename); + return 0; + } + + fclose(bsdl_file); + + // Get the first entity offset + tmp_ptr = strstr(bsdl_txt,"entity"); + if (!tmp_ptr) + { + jtagcore_logs_printf(jc, MSG_ERROR, "entry \"entity\" not found !\r\n"); + free(bsdl_txt); + return 0; + } + + offset = tmp_ptr - bsdl_txt; + + // skip the entity keyword + while( bsdl_txt[offset] !=' ' && bsdl_txt[offset] ) + offset++; + + // skip the blank spaces + while( bsdl_txt[offset] ==' ' && bsdl_txt[offset] ) + offset++; + + // copy the entity name + i = 0; + memset(entityname,0,sizeof(entityname)); + while( bsdl_txt[offset] !=' ' && bsdl_txt[offset] && i < ( sizeof(entityname) - 1 )) + { + entityname[i] = bsdl_txt[offset]; + + offset++; + i++; + } + + // skip the blank spaces + while( bsdl_txt[offset] ==' ' && bsdl_txt[offset] ) + offset++; + + // Check the "is" keyword presence + if( strncmp(&bsdl_txt[offset],"is",2) ) + { + jtagcore_logs_printf(jc, MSG_ERROR, "Bad entity entry (\"is\" not found)\r\n"); + free(bsdl_txt); + return 0; + } + + jtagcore_logs_printf(jc,MSG_DEBUG,"Entity : %s\r\n",entityname); + + offset += 2; + + // extract and separate each bsdl line + number_of_bsdl_lines = extract_bsdl_lines(&bsdl_txt[offset],0); + jtagcore_logs_printf(jc,MSG_DEBUG,"lines :%d\r\n",number_of_bsdl_lines); + + if (number_of_bsdl_lines <= 0 || number_of_bsdl_lines > MAX_NUMBER_OF_BSDL_LINES) + { + jtagcore_logs_printf(jc, MSG_ERROR, "No line found !\r\n"); + free(bsdl_txt); + return 0; + } + + lines = malloc( sizeof(char*) * ( number_of_bsdl_lines + 1 ) ); + if( !lines ) + { + jtagcore_logs_printf(jc,MSG_ERROR,"load_bsdlfile : memory alloc error !\r\n"); + free(tmp_bsdl_txt); + return 0; + } + + memset( lines, 0, sizeof(char*) * ( number_of_bsdl_lines + 1 ) ); + + extract_bsdl_lines(&bsdl_txt[offset],lines); + + for(i= 0 ;i< number_of_bsdl_lines;i++) + { + preprocess_line(lines[i]); + } + + bsdl = malloc ( sizeof(jtag_bsdl) ); + if (!bsdl) + { + jtagcore_logs_printf(jc, MSG_ERROR, "load_bsdlfile : memory alloc error !\r\n"); + for( i = 0 ;i < number_of_bsdl_lines ; i++ ) + { + if(lines[i]) + { + free(lines[i]); + lines[i] = 0; + } + } + free(lines); + + free(bsdl_txt); + + return 0; + } + + memset( bsdl , 0 , sizeof(jtag_bsdl) ); + + /////////////////////// + // copy the entity name & the file name + strncpy(bsdl->entity_name,entityname,sizeof(((jtag_bsdl *)0)->entity_name) - 1); + bsdl->entity_name[ sizeof(((jtag_bsdl *)0)->entity_name) - 1 ] = '\0'; + + i = strlen(filename); + while(i && filename[i] != '\\') + { + i--; + } + + if(filename[i] == '\\') + i++; + + strncpy(bsdl->src_filename,&filename[i],sizeof(bsdl->src_filename) - 1); + bsdl->src_filename[ sizeof(bsdl->src_filename) - 1 ] = '0'; + + /////////////////////// + // Extract the chip ID + bsdl->chip_id = 0x00000000; + bsdl->chip_id_mask = 0xFFFFFFFF; + + chipid_str = get_attribut_txt(lines,"IDCODE_REGISTER", entityname); + if(chipid_str) + { + if( chipid_str[0] == '"' ) + { + chipid_str++; + i = 0; + while(chipid_str[i]!='"' && chipid_str[i]!=';' && chipid_str[i] && i < 32) + { + switch( chipid_str[i] ) + { + case '0': + bsdl->chip_id &= ~(0x80000000 >> i); + break; + + case '1': + bsdl->chip_id |= (0x80000000 >> i); + break; + + case 'x': + case 'X': + bsdl->chip_id_mask &= ~(0x80000000 >> i); + break; + + default: + break; + } + + i++; + } + } + } + + jtagcore_logs_printf(jc,MSG_INFO_0,"ID Code: 0x%.8X\r\n",bsdl->chip_id); + + /////////////////////// + // Extract the pins list + get_pins_list(jc,bsdl,lines); + + /////////////////////// + // Extract the JTAG Chain + if(get_jtag_chain(jc,bsdl,lines,entityname)<0) + { + jtagcore_logs_printf(jc,MSG_ERROR,"load_bsdlfile : Error during jtag chain parsing !\r\n"); + } + + if(jtagcore_getEnvVarValue( jc, "BSDL_LOADER_SORT_PINS_NAME" ) > 0) + { + // Count the pins + i = 0; + while(bsdl->pins_list[i].pinname[0]) + { + i++; + } + + // Sort them + qsort(bsdl->pins_list, i, sizeof bsdl->pins_list[0], compare_pin_name); + } + + if(bsdl->pins_list) + { + i = 0; + while(bsdl->pins_list[i].pinname[0]) + { + char dbg_str[512]; + int namelen,j,k; + char disval; + + namelen = strlen(bsdl->pins_list[i].pinname); + + sprintf(dbg_str,"Pin %s",bsdl->pins_list[i].pinname); + for(j=0;j<(16 - namelen);j++) + { + strcat(dbg_str," "); + } + + k = strlen(dbg_str); + + disval = 'X'; + + if(bsdl->pins_list[i].out_bit_number >=0 ) + { + if( bsdl->chain_list[bsdl->pins_list[i].out_bit_number].control_disable_state >= 0 ) + { + disval = '0' + bsdl->chain_list[bsdl->pins_list[i].out_bit_number].control_disable_state; + } + } + + sprintf(&dbg_str[k]," type %.2d, ctrl %.3d (disval:%c), out %.3d, in %.3d\r\n", + bsdl->pins_list[i].pintype, + bsdl->pins_list[i].ctrl_bit_number, + disval, + bsdl->pins_list[i].out_bit_number, + bsdl->pins_list[i].in_bit_number); + + jtagcore_logs_printf(jc,MSG_DEBUG,dbg_str); + + i++; + } + } + + /////////////////////// + // Get the instruction code + + bsdl->number_of_bits_per_instruction = get_attribut_int(lines,"INSTRUCTION_LENGTH", entityname); + + jtagcore_logs_printf(jc,MSG_INFO_0,"Instructions lenght : %d\r\n",bsdl->number_of_bits_per_instruction); + + instruct_str = get_attribut_txt(lines,"INSTRUCTION_OPCODE", entityname); + if(instruct_str) + { + instruct_strchr = strstr(instruct_str,"IDCODE"); + if(!instruct_strchr) + instruct_strchr = strstr(instruct_str,"idcode"); + if(instruct_strchr) + { + get_next_keyword(jc,instruct_strchr, bsdl->IDCODE_Instruction); + jtagcore_logs_printf(jc,MSG_DEBUG,"IDCODE : %s\r\n",bsdl->IDCODE_Instruction); + } + + instruct_strchr = strstr(instruct_str,"EXTEST"); + if(!instruct_strchr) + instruct_strchr = strstr(instruct_str,"extest"); + + if(instruct_strchr) + { + get_next_keyword(jc,instruct_strchr, bsdl->EXTEST_Instruction); + jtagcore_logs_printf(jc,MSG_DEBUG,"EXTEST : %s\r\n",bsdl->EXTEST_Instruction); + } + + instruct_strchr = strstr(instruct_str,"BYPASS"); + if(!instruct_strchr) + instruct_strchr = strstr(instruct_str,"bypass"); + + if(instruct_strchr) + { + get_next_keyword(jc,instruct_strchr, bsdl->BYPASS_Instruction); + jtagcore_logs_printf(jc,MSG_DEBUG,"BYPASS : %s\r\n",bsdl->BYPASS_Instruction); + } + + instruct_strchr = strstr(instruct_str,"SAMPLE"); + if(!instruct_strchr) + instruct_strchr = strstr(instruct_str,"sample"); + if(instruct_strchr) + { + get_next_keyword(jc,instruct_strchr, bsdl->SAMPLE_Instruction); + jtagcore_logs_printf(jc,MSG_DEBUG,"SAMPLE : %s\r\n",bsdl->SAMPLE_Instruction); + } + } + + free( bsdl_txt ); + + for( i = 0 ;i < number_of_bsdl_lines ; i++ ) + { + if(lines[i]) + { + free(lines[i]); + lines[i] = 0; + } + } + + free(lines); + + jtagcore_logs_printf(jc,MSG_INFO_0,"BSDL file %s loaded and parsed\r\n",filename); + + return bsdl; +} + +void unload_bsdlfile(jtag_core * jc, jtag_bsdl * bsdl) +{ + if( bsdl ) + { + if(bsdl->chain_list) + free(bsdl->chain_list); + + if(bsdl->pins_list) + free(bsdl->pins_list); + + free( bsdl ); + } +} diff --git a/lib_jtag_core/src/bsdl_parser/bsdl_loader.h b/lib_jtag_core/src/bsdl_parser/bsdl_loader.h new file mode 100644 index 0000000..dd3f885 --- /dev/null +++ b/lib_jtag_core/src/bsdl_parser/bsdl_loader.h @@ -0,0 +1,81 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bsdl_loader.h + * @brief bsdl file parser header + * @author Jean-François DEL NERO + */ + +#define MAX_ELEMENT_SIZE (64+1) + +typedef struct _pin_ctrl +{ + char pinname[MAX_ELEMENT_SIZE]; + int pintype; + + char physical_pin[MAX_ELEMENT_SIZE]; + + int ctrl_bit_number; + int out_bit_number; + int in_bit_number; +}pin_ctrl; + +typedef struct _jtag_chain +{ + int bit_index; + + int bit_cell_type; // BC_1,BC_2,... + + char pinname[MAX_ELEMENT_SIZE]; // Pin name. + + int bit_type; // None , ctrl , in, out. + + int safe_state; // Default - Safe state. (0,1,-1) + + int control_bit_index; // Indicate the associated control bit. -1 if no control bit. + int control_disable_state; + int control_disable_result; + +}jtag_chain; + +typedef struct _jtag_bsdl +{ + unsigned long chip_id; + unsigned long chip_id_mask; + + char src_filename[512]; + char entity_name[512]; + + int number_of_chainbits; + jtag_chain * chain_list; + + int number_of_pins; + pin_ctrl * pins_list; + + int number_of_bits_per_instruction; + char IDCODE_Instruction[MAX_ELEMENT_SIZE]; + char EXTEST_Instruction[MAX_ELEMENT_SIZE]; + char BYPASS_Instruction[MAX_ELEMENT_SIZE]; + char SAMPLE_Instruction[MAX_ELEMENT_SIZE]; + +}jtag_bsdl; + +jtag_bsdl * load_bsdlfile(jtag_core * jc,char *filename); +void unload_bsdlfile(jtag_core * jc, jtag_bsdl * bsdl); diff --git a/lib_jtag_core/src/bsdl_parser/bsdl_strings.c b/lib_jtag_core/src/bsdl_parser/bsdl_strings.c new file mode 100644 index 0000000..a3667b9 --- /dev/null +++ b/lib_jtag_core/src/bsdl_parser/bsdl_strings.c @@ -0,0 +1,95 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bsdl_strings.c + * @brief bsdl file string keywords + * @author Jean-François DEL NERO + */ + +#include + +#include "../drivers/drv_loader.h" +#include "../jtag_core_internal.h" +#include "../jtag_core.h" + +#include "bsdl_loader.h" +#include "bsdl_strings.h" + +type_strings celltype_str[]= +{ + {"BC_1",CELLTYPE_BC1}, + {"BC_2",CELLTYPE_BC2}, + {"BC_3",CELLTYPE_BC3}, + {"BC_4",CELLTYPE_BC4}, + {"BC_5",CELLTYPE_BC5}, + {"BC_6",CELLTYPE_BC6}, + {"BC_7",CELLTYPE_BC7}, + + {0,CELLTYPE_UNKNOWN} +}; + +type_strings bittype_str[]= +{ + {"INPUT",BITTYPE_INPUT}, + {"OBSERVE_ONLY",BITTYPE_INPUT}, + {"OUTPUT",BITTYPE_OUTPUT}, + {"OUTPUT2", BITTYPE_OUTPUT }, + {"OUTPUT3",BITTYPE_TRISTATE_OUTPUT}, + {"BIDIR",BITTYPE_INOUT}, + {"CONTROL",BITTYPE_CONTROL}, + {"CONTROLR",BITTYPE_CONTROL}, + {"INTERNAL",BITTYPE_INTERNAL}, + {0,BITTYPE_UNKNOWN} +}; + +type_strings statetype_str[]= +{ + {"X",STATE_UNDEF}, + {"1",STATE_HIGH}, + {"0",STATE_LOW}, + {"Z",STATE_HIGHZ}, + {0,STATE_UNKNOWN} +}; + +type_strings pintype_str[]= +{ + {"IN",IO_IN}, + {"OUT",IO_OUT}, + {"INOUT",IO_INOUT}, + {"BUFFER", IO_OUT }, + {0,IO_UNDEF} +}; + +int get_typecode(type_strings * typelist,char * name) +{ + int i; + + i = 0; + while( typelist[i].type_name ) + { + if(!strcmp( typelist[i].type_name, name ) ) + { + return typelist[i].type_code; + } + i++; + } + + return typelist[i].type_code; +} diff --git a/lib_jtag_core/src/bsdl_parser/bsdl_strings.h b/lib_jtag_core/src/bsdl_parser/bsdl_strings.h new file mode 100644 index 0000000..d28e603 --- /dev/null +++ b/lib_jtag_core/src/bsdl_parser/bsdl_strings.h @@ -0,0 +1,77 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bsdl_strings.h + * @brief bsdl file string keywords header + * @author Jean-François DEL NERO + */ + +typedef struct type_strings_ +{ + char * type_name; + int type_code; +}type_strings; + +enum CELLTYPE +{ + CELLTYPE_UNKNOWN = 0x00, + CELLTYPE_BC1, + CELLTYPE_BC2, + CELLTYPE_BC3, + CELLTYPE_BC4, + CELLTYPE_BC5, + CELLTYPE_BC6, + CELLTYPE_BC7 +}; + +enum BITTYPE +{ + BITTYPE_UNKNOWN = 0x00, + BITTYPE_INPUT, + BITTYPE_OUTPUT, + BITTYPE_TRISTATE_OUTPUT, + BITTYPE_INOUT, + BITTYPE_CONTROL, + BITTYPE_INTERNAL +}; + +enum STATETYPE +{ + STATE_UNKNOWN = 0x00, + STATE_UNDEF, + STATE_HIGH, + STATE_LOW, + STATE_HIGHZ +}; + +enum PINIOTYPE +{ + IO_UNDEF = 0x00, + IO_IN, + IO_OUT, + IO_INOUT +}; + +extern type_strings celltype_str[]; +extern type_strings bittype_str[]; +extern type_strings statetype_str[]; +extern type_strings pintype_str[]; + +int get_typecode(type_strings * typelist,char * name); diff --git a/lib_jtag_core/src/bus_over_jtag/i2c_over_jtag.c b/lib_jtag_core/src/bus_over_jtag/i2c_over_jtag.c new file mode 100644 index 0000000..028ec22 --- /dev/null +++ b/lib_jtag_core/src/bus_over_jtag/i2c_over_jtag.c @@ -0,0 +1,359 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file i2c_over_jtag.c + * @brief I2C over jtag API + * @author Jean-François DEL NERO + */ + +#include +#include +#include + +#include "../drivers/drv_loader.h" +#include "../jtag_core_internal.h" +#include "../jtag_core.h" + +#include "../bsdl_parser/bsdl_loader.h" + +#include "../drivers/drivers_list.h" + +#include "../dbg_logs.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// I2C Over JTAG API +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int jtagcore_i2c_set_scl_pin(jtag_core * jc, int device, int pin) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins && pin >= 0) + { + jc->i2c_scl_pin = pin; + jc->i2c_scl_device = device; + + jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_scl_pin : device %d, pin %d\r\n",device,pin); + + return JTAG_CORE_NO_ERROR; + } + else + jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_scl_pin : ERROR invalid pin %d\r\n",pin); + } + else + jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_scl_pin : ERROR bsdl not loaded\r\n"); + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_i2c_set_sda_pin(jtag_core * jc, int device, int pin) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins && pin >= 0) + { + jc->i2c_sda_pin = pin; + jc->i2c_sda_device = device; + + jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_sda_pin : device %d, pin %d\r\n",device,pin); + + return JTAG_CORE_NO_ERROR; + } + else + jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_sda_pin : ERROR invalid pin %d\r\n",pin); + } + else + jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_sda_pin : ERROR bsdl not loaded\r\n"); + } + + return JTAG_CORE_BAD_PARAMETER; +} + +static void jtagcore_i2c_set_scl_state_high(jtag_core * jc) +{ + jtagcore_set_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_OE, 0); + jtagcore_set_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_OUTPUT, 1); +} + +static void jtagcore_i2c_set_scl_state_low(jtag_core * jc) +{ + jtagcore_set_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_OE, 1); + jtagcore_set_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_OUTPUT, 0); +} + +static void jtagcore_i2c_set_sda_state_high(jtag_core * jc) +{ + jtagcore_set_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_OE, 0); + jtagcore_set_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_OUTPUT, 1); +} + +static void jtagcore_i2c_set_sda_state_low(jtag_core * jc) +{ + jtagcore_set_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_OE, 1); + jtagcore_set_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_OUTPUT, 0); +} + +static void i2c_start_bit(jtag_core * jc) +{ + // Start bit. + + jtagcore_i2c_set_sda_state_low(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_i2c_set_scl_state_low(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); +} + +static void i2c_push_bit(jtag_core * jc, int sda_state) +{ + if (sda_state) + { + jtagcore_i2c_set_sda_state_high(jc); + } + else + { + jtagcore_i2c_set_sda_state_low(jc); + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_i2c_set_scl_state_high(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_i2c_set_scl_state_low(jc); + + jtagcore_i2c_set_sda_state_high(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + if (!sda_state) + { + // jtagcore_i2c_set_sda_state_high(jc); + // jtagcore_push_and_pop_chain(jc); + } +} + + +static void i2c_stop_bit(jtag_core * jc) +{ + // Stop bit. + + jtagcore_i2c_set_sda_state_low(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_i2c_set_scl_state_high(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_i2c_set_sda_state_high(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); +} + + +static int i2c_wait_ack(jtag_core * jc) +{ + int i, acknowledged; + + acknowledged = 0; + + // ACK + jtagcore_i2c_set_sda_state_high(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_i2c_set_scl_state_high(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + i = 0; + do + { + if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR ) + { + return JTAG_CORE_IO_ERROR; + } + + i++; + } while (jtagcore_get_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_INPUT) && i < 10); + + if (i < 10) + acknowledged = 1; + + jtagcore_i2c_set_scl_state_low(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + return acknowledged; +} + +int jtagcore_i2c_write_read(jtag_core * jc, int address, int address10bits,int wr_size,unsigned char * wr_buffer,int rd_size,unsigned char * rd_buffer) +{ + int i,j,acknowledged; + + acknowledged = 0; + + if( jc ) + { + jtagcore_i2c_set_scl_state_high(jc); + jtagcore_i2c_set_sda_state_high(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + // Is the bus Free / High state? + if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR ) + { + return JTAG_CORE_IO_ERROR; + } + + if (!jtagcore_get_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_INPUT) || !jtagcore_get_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_INPUT)) + { + return JTAG_CORE_I2C_BUS_NOTFREE; + } + + // Start bit. + i2c_start_bit(jc); + + for(i=0;i<7;i++) + { + i2c_push_bit(jc, address & (0x80 >> i)); + } + + // WR/RD + if(wr_size) + { + i2c_push_bit(jc, 0); + } + else + { + i2c_push_bit(jc, 1); + } + + // ACK + acknowledged = i2c_wait_ack(jc); + + if( acknowledged < 0 ) // Error ? + { + jtagcore_i2c_set_scl_state_high(jc); + jtagcore_i2c_set_sda_state_high(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + return acknowledged; + } + + if(wr_size) + { + for(i=0;i> j)); + } + + // ACK + i2c_push_bit(jc, 1); + } + + // Stop bit. + i2c_stop_bit(jc); + } + else + { + for(i=0;ii2c_scl_device,jc->i2c_scl_pin,JTAG_CORE_INPUT)); + + + if(jtagcore_get_pin_state(jc,jc->i2c_sda_device,jc->i2c_sda_pin,JTAG_CORE_INPUT)) + { + rd_buffer[i] |= 0x80>>j; + } + + jtagcore_i2c_set_scl_state_low(jc); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + } + + if(i!=rd_size-1) + { + // ACK + i2c_push_bit(jc, 0); + } + else + { + // NACK + i2c_push_bit(jc, 1); + } + } + + // Stop bit. + i2c_stop_bit(jc); + } + + return acknowledged; + } + + return JTAG_CORE_BAD_PARAMETER; +} diff --git a/lib_jtag_core/src/bus_over_jtag/mdio_over_jtag.c b/lib_jtag_core/src/bus_over_jtag/mdio_over_jtag.c new file mode 100644 index 0000000..587a4db --- /dev/null +++ b/lib_jtag_core/src/bus_over_jtag/mdio_over_jtag.c @@ -0,0 +1,292 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file mdio_over_jtag.c + * @brief MDC/MDIO over jtag API + * @author Jean-François DEL NERO + */ + +#include +#include +#include + +#include "../drivers/drv_loader.h" + +#include "../jtag_core_internal.h" +#include "../jtag_core.h" + +#include "../bsdl_parser/bsdl_loader.h" + +#include "../drivers/drivers_list.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// MDIO Over JTAG API +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int jtagcore_mdio_set_mdc_pin(jtag_core * jc, int device, int pin) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins && pin >= 0) + { + jc->mdio_mdc_pin = pin; + jc->mdio_mdc_device = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_mdio_set_mdio_pin(jtag_core * jc, int device, int pin) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >=0) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins && pin >= 0) + { + jc->mdio_mdio_pin = pin; + jc->mdio_mdio_device = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +static void mdio_push_bit(jtag_core * jc, int bit_state) +{ + if (bit_state) + jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OE, 0); // MDIO High + else + jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OE, 1); // MDIO Low + + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0); // MDC Low + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 1); // MDC High + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + } + + +static int mdio_get_bit(jtag_core * jc) +{ + int state; + + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 1); // MDC High + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0); // MDC Low + + if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR ) + { + return JTAG_CORE_IO_ERROR; + } + + state = jtagcore_get_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_INPUT); + + return state; +} + + +int jtagcore_mdio_write(jtag_core * jc, int phy_adr, int reg_adr, int data) +{ + int i; + + if( jc ) + { + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OE, 1); + jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OE, 0); + + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0); + jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OUTPUT, 0); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + for (i = 0; i < 32; i++) + { + mdio_push_bit(jc, 1); + } + + // Start. + mdio_push_bit(jc, 0); + mdio_push_bit(jc, 1); + + //Write + mdio_push_bit(jc, 0); + mdio_push_bit(jc, 1); + + // dev address + for (i=0;i<5;i++) + { + if(phy_adr & (0x10>>i)) + { + mdio_push_bit(jc, 1); + } + else + { + mdio_push_bit(jc, 0); + } + } + + // reg address + for (i=0;i<5;i++) + { + if(reg_adr & (0x10>>i)) + { + mdio_push_bit(jc, 1); + } + else + { + mdio_push_bit(jc, 0); + } + } + + //TA + mdio_push_bit(jc, 1); + mdio_push_bit(jc, 0); + + // data + for (i=0;i<16;i++) + { + if(data & (0x8000>>i)) + { + mdio_push_bit(jc, 1); + } + else + { + mdio_push_bit(jc, 0); + } + } + + mdio_push_bit(jc, 1); + mdio_push_bit(jc, 1); + mdio_push_bit(jc, 1); + + return 0; + } + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_mdio_read(jtag_core * jc, int phy_adr, int reg_adr) +{ + int i,data; + int bit_state; + + if( jc ) + { + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OE, 1); + jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OE, 0); + + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0); + jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OUTPUT, 0); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + for (i = 0; i < 32; i++) + { + mdio_push_bit(jc, 1); + } + + // Start. + mdio_push_bit(jc, 0); + mdio_push_bit(jc, 1); + + //Read + mdio_push_bit(jc, 1); + mdio_push_bit(jc, 0); + + // dev address + for (i=0;i<5;i++) + { + if(phy_adr & (0x10>>i)) + { + mdio_push_bit(jc, 1); + } + else + { + mdio_push_bit(jc, 0); + } + } + + // reg address + for (i=0;i<5;i++) + { + if(reg_adr & (0x10>>i)) + { + mdio_push_bit(jc, 1); + } + else + { + mdio_push_bit(jc, 0); + } + } + + // TA + mdio_push_bit(jc, 1); + + jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0); // MDC Low + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + data = 0; + // data + for (i=0;i<16;i++) + { + bit_state = mdio_get_bit(jc); + if(bit_state < 0 ) + { + mdio_push_bit(jc, 1); + mdio_push_bit(jc, 1); + mdio_push_bit(jc, 1); + + return bit_state; + } + + if(bit_state) + { + data |= (0x8000>>i); + } + } + + mdio_push_bit(jc, 1); + mdio_push_bit(jc, 1); + mdio_push_bit(jc, 1); + + + return data; + } + return JTAG_CORE_BAD_PARAMETER; +} + diff --git a/lib_jtag_core/src/bus_over_jtag/memory_over_jtag.c b/lib_jtag_core/src/bus_over_jtag/memory_over_jtag.c new file mode 100644 index 0000000..bbc3a2b --- /dev/null +++ b/lib_jtag_core/src/bus_over_jtag/memory_over_jtag.c @@ -0,0 +1,325 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file memory_over_jtag.c + * @brief parallel memory over jtag API + * @author Jean-François DEL NERO + */ + +#include +#include +#include + +#include "../drivers/drv_loader.h" + +#include "../jtag_core_internal.h" +#include "../jtag_core.h" + +#include "../bsdl_parser/bsdl_loader.h" + +#include "../drivers/drivers_list.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Memory Over JTAG API +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int jtagcore_memory_clear_pins(jtag_core * jc) +{ + int i; + + for(i=0;iram_address_pin[i] = -1; + jc->ram_address_device[i] = -1; + jc->ram_data_pin[i] = -1; + jc->ram_data_device[i] = -1; + } + + for(i=0;i<16;i++) + { + jc->ram_ctrl_pin[i] = -1; + jc->ram_ctrl_pin_pol[i] = -1; + jc->ram_ctrl_device[i] = -1; + } + + return JTAG_CORE_NO_ERROR; +} + +int jtagcore_memory_set_address_pin(jtag_core * jc, int address_bit, int device, int pin) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && address_bit < MAX_BUS_WIDTH) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if ( pin < bsdl_file->number_of_pins && pin >= 0 ) + { + jc->ram_address_pin[address_bit] = pin; + jc->ram_address_device[address_bit] = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_memory_set_data_pin(jtag_core * jc, int data_bit, int device, int pin) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && data_bit < MAX_BUS_WIDTH) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if ( pin < bsdl_file->number_of_pins && pin >= 0 ) + { + jc->ram_data_pin[data_bit] = pin; + jc->ram_data_device[data_bit] = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_memory_set_ctrl_pin(jtag_core * jc, int ctrl, int polarity, int device, int pin) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && ctrl < 16) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if ( pin < bsdl_file->number_of_pins && pin >= 0 ) + { + jc->ram_ctrl_pin[ctrl] = pin; + jc->ram_ctrl_pin_pol[ctrl] = polarity; + jc->ram_ctrl_device[ctrl] = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +unsigned long jtagcore_memory_read(jtag_core * jc, int mem_adr) +{ + int i; + unsigned long value; + + // Set address bus + for(i=0;iram_address_pin[i]>=0 && jc->ram_address_device[i]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OE, 1); + + if( mem_adr & (0x00000001<ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OUTPUT, 1); + + } + else + { + jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OUTPUT, 0); + } + } + } + + // Set data bus tristate. + for(i=0;iram_data_pin[i]>=0 && jc->ram_data_device[i]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OE, 0); + } + } + + // deassert control pins. + for(i=0;i<16;i++) + { + if(jc->ram_ctrl_pin[i]>=0 && jc->ram_ctrl_device[i]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[i], jc->ram_ctrl_pin[i], JTAG_CORE_OE, 1); + + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[i], jc->ram_ctrl_pin[i], JTAG_CORE_OUTPUT, (jc->ram_ctrl_pin_pol[i]&1)^1 ); + } + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + // Assert CS + if(jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL], JTAG_CORE_OUTPUT, jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_CS_CTRL] & 1 ); + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + // Assert RD + if(jc->ram_ctrl_pin[JTAG_CORE_RAM_RD_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_RD_CTRL]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_RD_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_RD_CTRL], JTAG_CORE_OUTPUT, jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_RD_CTRL] & 1 ); + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR ) + { + return (unsigned long)-1; + } + + // read the data bus. + value = 0x00000000; + for(i=0;iram_data_pin[i]>=0 && jc->ram_data_device[i]>=0) + { + if(jtagcore_get_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_INPUT)) + { + value |= (0x00000001<ram_ctrl_pin[JTAG_CORE_RAM_RD_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_RD_CTRL]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_RD_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_RD_CTRL], JTAG_CORE_OUTPUT, ( jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_RD_CTRL] & 1 ) ^ 1 ); + } + + // deassert CS + if(jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL], JTAG_CORE_OUTPUT, ( jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_CS_CTRL] & 1 ) ^ 1 ); + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + return value; +} + +int jtagcore_memory_write(jtag_core * jc, int mem_adr, unsigned long data) +{ + + int i; + + // Set address bus + for(i=0;iram_address_pin[i]>=0 && jc->ram_address_device[i]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OE, 1); + + if( mem_adr & (0x00000001<ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OUTPUT, 1); + + } + else + { + jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OUTPUT, 0); + } + } + } + + // Set data bus + for(i=0;iram_data_pin[i]>=0 && jc->ram_data_device[i]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OE, 1); + + if( data & (0x00000001<ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OUTPUT, 1); + + } + else + { + jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OUTPUT, 0); + } + } + } + + // deassert control pins. + for(i=0;i<16;i++) + { + if(jc->ram_ctrl_pin[i]>=0 && jc->ram_ctrl_device[i]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[i], jc->ram_ctrl_pin[i], JTAG_CORE_OE, 1); + + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[i], jc->ram_ctrl_pin[i], JTAG_CORE_OUTPUT, (jc->ram_ctrl_pin_pol[i]&1)^1 ); + } + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + // Assert CS + if(jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL], JTAG_CORE_OUTPUT, jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_CS_CTRL] & 1 ); + } + + // Assert WR + if(jc->ram_ctrl_pin[JTAG_CORE_RAM_WR_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_WR_CTRL]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_WR_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_WR_CTRL], JTAG_CORE_OUTPUT, jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_WR_CTRL] & 1 ); + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + // dessert WR + if(jc->ram_ctrl_pin[JTAG_CORE_RAM_WR_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_WR_CTRL]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_WR_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_WR_CTRL], JTAG_CORE_OUTPUT, (jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_WR_CTRL] & 1) ^ 1 ); + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + // deassert CS + if(jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL], JTAG_CORE_OUTPUT, ( jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_CS_CTRL] & 1 ) ^ 1 ); + } + + // Set data bus tristate. + for(i=0;iram_data_pin[i]>=0 && jc->ram_data_device[i]>=0) + { + jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OE, 0); + } + } + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + return JTAG_CORE_NO_ERROR; +} diff --git a/lib_jtag_core/src/bus_over_jtag/spi_over_jtag.c b/lib_jtag_core/src/bus_over_jtag/spi_over_jtag.c new file mode 100644 index 0000000..5df3188 --- /dev/null +++ b/lib_jtag_core/src/bus_over_jtag/spi_over_jtag.c @@ -0,0 +1,290 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file spi_over_jtag.c + * @brief spi over jtag API + * @author Jean-François DEL NERO + */ + +#include +#include +#include + +#include "../drivers/drv_loader.h" + +#include "../jtag_core_internal.h" +#include "../jtag_core.h" + +#include "../bsdl_parser/bsdl_loader.h" + +#include "../drivers/drivers_list.h" + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SPI Over JTAG API +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int jtagcore_spi_set_mosi_pin(jtag_core * jc, int device, int pin, int sample_clk_phase) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins && pin >= 0) + { + jc->spi_mosi_pin = pin; + if(sample_clk_phase) + jc->spi_mosi_pol = 1; + else + jc->spi_mosi_pol = 0; + jc->spi_mosi_device = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_spi_set_miso_pin(jtag_core * jc, int device, int pin, int sample_clk_phase) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins && pin >= 0) + { + jc->spi_miso_pin = pin; + if(sample_clk_phase) + jc->spi_miso_pol = 1; + else + jc->spi_miso_pol = 0; + jc->spi_miso_device = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_spi_set_clk_pin(jtag_core * jc, int device, int pin, int polarity) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins && pin >= 0) + { + jc->spi_clk_pin = pin; + if(polarity) + jc->spi_clk_pol = 1; + else + jc->spi_clk_pol = 0; + jc->spi_clk_device = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_spi_set_cs_pin(jtag_core * jc, int device, int pin, int polarity) +{ + jtag_bsdl * bsdl_file; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins && pin >= 0) + { + jc->spi_cs_pin = pin; + if(polarity) + jc->spi_cs_pol = 1; + else + jc->spi_cs_pol = 0; + jc->spi_cs_device = device; + return JTAG_CORE_NO_ERROR; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_spi_set_bitorder(jtag_core * jc, int lsb_first) +{ + if(lsb_first) + jc->spi_lsb_first = 1; + else + jc->spi_lsb_first = 0; + + return JTAG_CORE_NO_ERROR; +} + + +int jtagcore_spi_write_read(jtag_core * jc, int wr_size,unsigned char * wr_buffer,unsigned char * rd_buffer, int flags) +{ + int i,j; + unsigned char byte_mask; + + if( jc ) + { + if(jc->spi_lsb_first) + byte_mask = (0x01); + else + byte_mask = (0x80); + + jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 0); + if(wr_size) + { + if( wr_buffer[0] & byte_mask ) + { + jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 1); + } + } + + jtagcore_set_pin_state(jc, jc->spi_miso_device, jc->spi_miso_pin, JTAG_CORE_OUTPUT, 1); + jtagcore_set_pin_state(jc, jc->spi_cs_device, jc->spi_cs_pin, JTAG_CORE_OUTPUT, 1 ^ jc->spi_cs_pol); + jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 0 ^ jc->spi_clk_pol); + + jtagcore_set_pin_state(jc, jc->spi_miso_device, jc->spi_miso_pin, JTAG_CORE_OE, 0); + jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OE, 1); + jtagcore_set_pin_state(jc, jc->spi_cs_device, jc->spi_cs_pin, JTAG_CORE_OE, 1); + jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OE, 1); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + jtagcore_set_pin_state(jc, jc->spi_cs_device, jc->spi_cs_pin, JTAG_CORE_OUTPUT, 0 ^ jc->spi_cs_pol); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + for(i=0;ispi_lsb_first) + byte_mask = (0x01<>j); + + if(!jc->spi_mosi_pol) // CPHA = 0 + { // MOSI OUT on clock phase 0 + if( wr_buffer[i] & byte_mask ) + { + jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 1); + } + else + { + jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 0); + } + } + + if(!jc->spi_miso_pol) // CPHA = 0 + { // MISO IN on clock phase 0 + + // clock phase 0 + jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 1 ^ jc->spi_clk_pol); + if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR ) + { + return JTAG_CORE_IO_ERROR; + } + + if(jtagcore_get_pin_state(jc,jc->spi_miso_device,jc->spi_miso_pin,JTAG_CORE_INPUT)) + { + rd_buffer[i] |= byte_mask; + } + else + { + rd_buffer[i] &= ~(byte_mask); + } + } + else + { + // clock phase 0 + jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 1 ^ jc->spi_clk_pol); + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + } + + if(jc->spi_mosi_pol) // CPHA = 1 + { // MOSI OUT on clock phase 1 + if( wr_buffer[i] & byte_mask ) + { + jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 1); + } + else + { + jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 0); + } + } + + if(jc->spi_miso_pol) // CPHA = 1 + { + // clock phase 1 + jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 0 ^ jc->spi_clk_pol); + + if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR ) + { + return JTAG_CORE_IO_ERROR; + } + + // MISO IN on clock phase 1 + if(jtagcore_get_pin_state(jc,jc->spi_miso_device,jc->spi_miso_pin,JTAG_CORE_INPUT)) + { + rd_buffer[i] |= byte_mask; + } + else + { + rd_buffer[i] &= ~(byte_mask); + } + } + else + { + // clock phase 1 + jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 0 ^ jc->spi_clk_pol); + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + } + } + } + + jtagcore_set_pin_state(jc, jc->spi_cs_device, jc->spi_cs_pin, JTAG_CORE_OUTPUT, 1 ^ jc->spi_cs_pol); + + jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY); + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_BAD_PARAMETER; +} diff --git a/lib_jtag_core/src/config.script b/lib_jtag_core/src/config.script new file mode 100644 index 0000000..8c16e73 --- /dev/null +++ b/lib_jtag_core/src/config.script @@ -0,0 +1,182 @@ +# +# lib jtag core init config script +# +# This script is built-in the jtag library and is executed at startup to apply +# the default variables values. +# +# You can put a "config.script" file in the JTAG boundaryscanner software's +# folder to change one or more of these variables if needed. +# Your "config.script" will be executed right after this script at startup. +# The syntax to use in your script is exactly the same. +# + +# ---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- + +# Log messages filter level +# +# 0 : Debug messages +# 1 : Info level 0 messages +# 2 : Info level 1 messages +# 3 : Warning level messages +# 4 : Error level messages +# 5 : No log / no message + +set LOG_MESSAGES_FILTER_LEVEL 1 + +# Log file + +#set LOG_MESSAGES_FILE_OUTPUT "logs_file.txt" + +# ---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- + +# +# Pins name sorter +# +# 0 To keep the bsdl pins order. +# 1 To sort the bsdl pins name. +# + +set BSDL_LOADER_SORT_PINS_NAME 1 + +# ---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- + +# +# This section expose the FTDI probes parameters +# + +# +# Parameters to compute the FDTI FT2232D/H clock divisor. +# ( TCK clock = (12Mhz or 60Mhz)/ ((1 + ([ValueH << 8 | ValueL]))*2) ) +# + +# Internal clock : FT2232H -> 60 MHz, FT2232D -> 12MHz + +set PROBE_FTDI_INTERNAL_FREQ_KHZ 60000 + +# Max TCK Clock + +set PROBE_FTDI_TCK_FREQ_KHZ 1000 + +# +# To enable the RTCK / adaptative clock mode set the following +# variable to 1. +# Warning : Need a FDTI chip supporting this mode (FT2232H,...) +# + +set PROBE_FTDI_JTAG_ENABLE_RTCK 0 + +# +# Probe internal mapping +# +# Olimex ARM-USB-OCD-H JTAG signals example +# +# VREF – voltage follower input for the output buffers adjust +# JTAG signals as per your target board voltage levels +# +# The TCK/TDI/TDO/TMS signals are fixed to these pins +# ADBUS0 -> TCK; (out) +# ADBUS1 -> TDI; (out) +# ADBUS2 -> TDO; (in) +# ADBUS3 -> TMS; (out) + +# ADBUS4 -> 0 to enable JTAG buffers; (GPIOL0) (out) +# ADBUS5 -> 0 if target present; (GPIOL1) (in) +# ADBUS6 -> TSRST in; (GPIOL2) (in) +# ADBUS7 -> RTCK; (in) (GPIOL3) (in) +# ACBUS0 -> TRST; (GPIOH0) +# ACBUS1 -> SRST; (GPIOH1) +# ACBUS2 -> TRST buffer enable (GPIOH2) +# ACBUS3 -> RED LED; (GPIOH3) + +# +# Set the internal GPIO direction (0 -> input, 1 -> output) +# + +set PROBE_FTDI_SET_PIN_DIR_ADBUS0 1 # TCK -> out +set PROBE_FTDI_SET_PIN_DIR_ADBUS1 1 # TDI -> out +set PROBE_FTDI_SET_PIN_DIR_ADBUS2 0 # TDO -> in +set PROBE_FTDI_SET_PIN_DIR_ADBUS3 1 # TMS -> out +set PROBE_FTDI_SET_PIN_DIR_ADBUS4 1 # Buffers enable -> out +set PROBE_FTDI_SET_PIN_DIR_ADBUS5 0 # Target presence : 0 if target present -> in +set PROBE_FTDI_SET_PIN_DIR_ADBUS6 0 # TSRST -> in +set PROBE_FTDI_SET_PIN_DIR_ADBUS7 0 # RTCK -> in + +set PROBE_FTDI_SET_PIN_DIR_ACBUS0 1 # TRST -> out +set PROBE_FTDI_SET_PIN_DIR_ACBUS1 1 # SRST -> out +set PROBE_FTDI_SET_PIN_DIR_ACBUS2 1 # TRST buffer enable -> out +set PROBE_FTDI_SET_PIN_DIR_ACBUS3 1 # RED LED -> out + +# +# Set the internal GPIOs output state +# + +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS0 0 +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS1 0 +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS2 0 +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS3 1 +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS4 0 # JTAG buffer enable (active low) +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS5 0 +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS6 0 +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS7 0 + +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS0 0 # TRST +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS1 0 # SRST +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS2 0 # TRST buffer enable +set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS3 0 # RED LED + +# +# Set the internal GPIOs polarity +# 0 : Active High. +# 1 : Active Low. +# + +set PROBE_FTDI_SET_PIN_POLARITY_ADBUS0 0 +set PROBE_FTDI_SET_PIN_POLARITY_ADBUS1 0 +set PROBE_FTDI_SET_PIN_POLARITY_ADBUS2 0 +set PROBE_FTDI_SET_PIN_POLARITY_ADBUS3 0 +set PROBE_FTDI_SET_PIN_POLARITY_ADBUS4 0 +set PROBE_FTDI_SET_PIN_POLARITY_ADBUS5 0 +set PROBE_FTDI_SET_PIN_POLARITY_ADBUS6 0 +set PROBE_FTDI_SET_PIN_POLARITY_ADBUS7 0 + +set PROBE_FTDI_SET_PIN_POLARITY_ACBUS0 1 # TRST is active-low +set PROBE_FTDI_SET_PIN_POLARITY_ACBUS1 0 +set PROBE_FTDI_SET_PIN_POLARITY_ACBUS2 0 +set PROBE_FTDI_SET_PIN_POLARITY_ACBUS3 0 + +# +# Assign the TRST / SRST control pins +# 0<>7 : ADBUS +# 8<>11 : ACBUS +# Set to -1 when not available/used. +# + +set PROBE_FTDI_SET_TRST_OE_PINNUM 10 +set PROBE_FTDI_SET_TRST_STATE_PINNUM 8 + +set PROBE_FTDI_SET_SRST_OE_PINNUM -1 +set PROBE_FTDI_SET_SRST_STATE_PINNUM -1 + +set PROBE_FTDI_SET_CONNECTION_LED_PINNUM 11 + +set PROBE_FTDI_JTAG_TRST_DELAY_MS 200 + +# ---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- + +set PROBE_LINUXGPIO_ENABLE 0 + +set PROBE_LINUXGPIO_BASE_FOLDER "/sys/class/gpio" + +set PROBE_LINUXGPIO_TMS_PIN 24 +set PROBE_LINUXGPIO_TDI_PIN 25 +set PROBE_LINUXGPIO_TDO_PIN 26 +set PROBE_LINUXGPIO_TCK_PIN 27 + +set PROBE_LINUXGPIO_TMS_PIN_INVERT_POLARITY 0 +set PROBE_LINUXGPIO_TDI_PIN_INVERT_POLARITY 0 +set PROBE_LINUXGPIO_TDO_PIN_INVERT_POLARITY 0 +set PROBE_LINUXGPIO_TCK_PIN_INVERT_POLARITY 0 diff --git a/lib_jtag_core/src/config_script.h b/lib_jtag_core/src/config_script.h new file mode 100644 index 0000000..177649d --- /dev/null +++ b/lib_jtag_core/src/config_script.h @@ -0,0 +1,500 @@ +unsigned char config_script[] = { + 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x6c, 0x69, 0x62, 0x20, 0x6a, 0x74, 0x61, + 0x67, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x20, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x69, 0x73, 0x20, 0x62, + 0x75, 0x69, 0x6c, 0x74, 0x2d, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6a, 0x74, 0x61, 0x67, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x75, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x0d, 0x0a, 0x23, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x0d, 0x0a, 0x23, + 0x0d, 0x0a, 0x23, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, + 0x70, 0x75, 0x74, 0x20, 0x61, 0x20, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4a, 0x54, + 0x41, 0x47, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x73, + 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, + 0x61, 0x72, 0x65, 0x27, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x66, 0x6f, 0x6c, + 0x64, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, + 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x76, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x20, 0x69, 0x66, 0x20, + 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2e, 0x0d, 0x0a, 0x23, 0x20, 0x59, + 0x6f, 0x75, 0x72, 0x20, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x62, 0x65, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, + 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, + 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x20, 0x61, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x2e, + 0x0d, 0x0a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x6e, 0x74, + 0x61, 0x78, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x69, 0x6e, + 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x20, 0x69, 0x73, 0x20, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x2e, 0x0d, 0x0a, 0x23, + 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, + 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, + 0x4c, 0x6f, 0x67, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x30, 0x20, 0x3a, 0x20, + 0x44, 0x65, 0x62, 0x75, 0x67, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x31, 0x20, 0x3a, 0x20, 0x49, 0x6e, + 0x66, 0x6f, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x30, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x32, + 0x20, 0x3a, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x20, 0x31, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x0d, 0x0a, 0x23, 0x20, 0x33, 0x20, 0x3a, 0x20, 0x57, 0x61, 0x72, 0x6e, + 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x34, 0x20, + 0x3a, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0d, 0x0a, + 0x23, 0x20, 0x35, 0x20, 0x3a, 0x20, 0x4e, 0x6f, 0x20, 0x6c, 0x6f, 0x67, + 0x20, 0x2f, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x4c, 0x4f, 0x47, + 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x53, 0x5f, 0x46, 0x49, + 0x4c, 0x54, 0x45, 0x52, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x20, 0x31, + 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x4c, 0x6f, 0x67, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x73, 0x65, 0x74, 0x20, 0x4c, + 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x53, 0x5f, + 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x20, + 0x22, 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, + 0x78, 0x74, 0x22, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x0d, + 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x50, 0x69, 0x6e, 0x73, 0x20, 0x6e, + 0x61, 0x6d, 0x65, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x0d, 0x0a, + 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x30, 0x20, 0x54, 0x6f, 0x20, 0x6b, 0x65, + 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x73, 0x64, 0x6c, 0x20, + 0x70, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x0d, + 0x0a, 0x23, 0x20, 0x31, 0x20, 0x54, 0x6f, 0x20, 0x73, 0x6f, 0x72, 0x74, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x73, 0x64, 0x6c, 0x20, 0x70, 0x69, + 0x6e, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x0d, 0x0a, 0x23, 0x0d, + 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x42, 0x53, 0x44, 0x4c, 0x5f, + 0x4c, 0x4f, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f, + 0x50, 0x49, 0x4e, 0x53, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x20, 0x31, 0x0d, + 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x23, + 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, + 0x23, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x46, 0x54, 0x44, 0x49, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x65, + 0x73, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, + 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x74, + 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x46, 0x44, 0x54, 0x49, 0x20, 0x46, 0x54, 0x32, 0x32, 0x33, + 0x32, 0x44, 0x2f, 0x48, 0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x64, + 0x69, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x2e, 0x0d, 0x0a, 0x23, 0x20, 0x28, + 0x20, 0x54, 0x43, 0x4b, 0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3d, + 0x20, 0x28, 0x31, 0x32, 0x4d, 0x68, 0x7a, 0x20, 0x6f, 0x72, 0x20, 0x36, + 0x30, 0x4d, 0x68, 0x7a, 0x29, 0x2f, 0x20, 0x28, 0x28, 0x31, 0x20, 0x2b, + 0x20, 0x28, 0x5b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x20, 0x3c, 0x3c, + 0x20, 0x38, 0x20, 0x7c, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x5d, + 0x29, 0x29, 0x2a, 0x32, 0x29, 0x20, 0x29, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, + 0x0d, 0x0a, 0x23, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3a, 0x20, 0x46, 0x54, 0x32, + 0x32, 0x33, 0x32, 0x48, 0x20, 0x2d, 0x3e, 0x20, 0x36, 0x30, 0x20, 0x4d, + 0x48, 0x7a, 0x2c, 0x20, 0x46, 0x54, 0x32, 0x32, 0x33, 0x32, 0x44, 0x20, + 0x2d, 0x3e, 0x20, 0x31, 0x32, 0x4d, 0x48, 0x7a, 0x0d, 0x0a, 0x0d, 0x0a, + 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, + 0x44, 0x49, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, + 0x46, 0x52, 0x45, 0x51, 0x5f, 0x4b, 0x48, 0x5a, 0x20, 0x36, 0x30, 0x30, + 0x30, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x4d, 0x61, 0x78, 0x20, + 0x54, 0x43, 0x4b, 0x20, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x0d, + 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, + 0x54, 0x44, 0x49, 0x5f, 0x54, 0x43, 0x4b, 0x5f, 0x46, 0x52, 0x45, 0x51, + 0x5f, 0x4b, 0x48, 0x5a, 0x20, 0x31, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x0d, + 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x54, 0x6f, 0x20, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x54, 0x43, 0x4b, + 0x20, 0x2f, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x61, 0x74, 0x69, 0x76, + 0x65, 0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6d, 0x6f, 0x64, 0x65, + 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, + 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x23, 0x20, 0x76, 0x61, + 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x31, 0x2e, + 0x0d, 0x0a, 0x23, 0x20, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, + 0x3a, 0x20, 0x4e, 0x65, 0x65, 0x64, 0x20, 0x61, 0x20, 0x46, 0x44, 0x54, + 0x49, 0x20, 0x63, 0x68, 0x69, 0x70, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, + 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d, + 0x6f, 0x64, 0x65, 0x20, 0x28, 0x46, 0x54, 0x32, 0x32, 0x33, 0x32, 0x48, + 0x2c, 0x2e, 0x2e, 0x2e, 0x29, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, + 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, + 0x44, 0x49, 0x5f, 0x4a, 0x54, 0x41, 0x47, 0x5f, 0x45, 0x4e, 0x41, 0x42, + 0x4c, 0x45, 0x5f, 0x52, 0x54, 0x43, 0x4b, 0x20, 0x30, 0x0d, 0x0a, 0x0d, + 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x20, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x4f, + 0x6c, 0x69, 0x6d, 0x65, 0x78, 0x20, 0x41, 0x52, 0x4d, 0x2d, 0x55, 0x53, + 0x42, 0x2d, 0x4f, 0x43, 0x44, 0x2d, 0x48, 0x20, 0x4a, 0x54, 0x41, 0x47, + 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x20, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x56, + 0x52, 0x45, 0x46, 0x20, 0xe2, 0x80, 0x93, 0x20, 0x76, 0x6f, 0x6c, 0x74, + 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, + 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x62, 0x75, + 0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, + 0x0d, 0x0a, 0x23, 0x20, 0x4a, 0x54, 0x41, 0x47, 0x20, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x6c, 0x73, 0x20, 0x61, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, + 0x79, 0x6f, 0x75, 0x72, 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, 0x76, 0x6f, 0x6c, 0x74, 0x61, 0x67, + 0x65, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x0d, 0x0a, 0x23, 0x0d, + 0x0a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x54, 0x43, 0x4b, 0x2f, 0x54, + 0x44, 0x49, 0x2f, 0x54, 0x44, 0x4f, 0x2f, 0x54, 0x4d, 0x53, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, + 0x69, 0x78, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x73, + 0x65, 0x20, 0x70, 0x69, 0x6e, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, + 0x42, 0x55, 0x53, 0x30, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x43, 0x4b, 0x3b, + 0x20, 0x28, 0x6f, 0x75, 0x74, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, + 0x42, 0x55, 0x53, 0x31, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x44, 0x49, 0x3b, + 0x20, 0x28, 0x6f, 0x75, 0x74, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, + 0x42, 0x55, 0x53, 0x32, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x44, 0x4f, 0x3b, + 0x20, 0x28, 0x69, 0x6e, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, 0x42, + 0x55, 0x53, 0x33, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x4d, 0x53, 0x3b, 0x20, + 0x28, 0x6f, 0x75, 0x74, 0x29, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x41, + 0x44, 0x42, 0x55, 0x53, 0x34, 0x20, 0x2d, 0x3e, 0x20, 0x30, 0x20, 0x74, + 0x6f, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x4a, 0x54, 0x41, + 0x47, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x3b, 0x20, 0x20, + 0x28, 0x47, 0x50, 0x49, 0x4f, 0x4c, 0x30, 0x29, 0x20, 0x28, 0x6f, 0x75, + 0x74, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, 0x42, 0x55, 0x53, 0x35, + 0x20, 0x2d, 0x3e, 0x20, 0x30, 0x20, 0x69, 0x66, 0x20, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x3b, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, + 0x4c, 0x31, 0x29, 0x20, 0x28, 0x69, 0x6e, 0x29, 0x0d, 0x0a, 0x23, 0x20, + 0x41, 0x44, 0x42, 0x55, 0x53, 0x36, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x53, + 0x52, 0x53, 0x54, 0x20, 0x69, 0x6e, 0x3b, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x4c, 0x32, 0x29, 0x20, 0x28, 0x69, + 0x6e, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, 0x42, 0x55, 0x53, 0x37, + 0x20, 0x2d, 0x3e, 0x20, 0x52, 0x54, 0x43, 0x4b, 0x3b, 0x20, 0x28, 0x69, + 0x6e, 0x29, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, + 0x4c, 0x33, 0x29, 0x20, 0x28, 0x69, 0x6e, 0x29, 0x0d, 0x0a, 0x23, 0x20, + 0x41, 0x43, 0x42, 0x55, 0x53, 0x30, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x52, + 0x53, 0x54, 0x3b, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x48, 0x30, 0x29, 0x0d, 0x0a, 0x23, + 0x20, 0x41, 0x43, 0x42, 0x55, 0x53, 0x31, 0x20, 0x2d, 0x3e, 0x20, 0x53, + 0x52, 0x53, 0x54, 0x3b, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x48, 0x31, 0x29, 0x0d, 0x0a, + 0x23, 0x20, 0x41, 0x43, 0x42, 0x55, 0x53, 0x32, 0x20, 0x2d, 0x3e, 0x20, + 0x54, 0x52, 0x53, 0x54, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x48, 0x32, 0x29, 0x0d, + 0x0a, 0x23, 0x20, 0x41, 0x43, 0x42, 0x55, 0x53, 0x33, 0x20, 0x2d, 0x3e, + 0x20, 0x52, 0x45, 0x44, 0x20, 0x4c, 0x45, 0x44, 0x3b, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x48, 0x33, 0x29, + 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x53, 0x65, 0x74, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x20, 0x47, 0x50, 0x49, 0x4f, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x30, 0x20, 0x2d, 0x3e, 0x20, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x31, 0x20, 0x2d, 0x3e, 0x20, 0x6f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x0d, + 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, + 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, + 0x44, 0x49, 0x52, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x30, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, + 0x20, 0x23, 0x20, 0x54, 0x43, 0x4b, 0x20, 0x2d, 0x3e, 0x20, 0x6f, 0x75, + 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, + 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, + 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x31, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x31, 0x20, 0x23, 0x20, 0x54, 0x44, 0x49, 0x20, 0x2d, 0x3e, 0x20, + 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, + 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, + 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x44, 0x42, 0x55, + 0x53, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54, 0x44, 0x4f, 0x20, 0x2d, + 0x3e, 0x20, 0x69, 0x6e, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, + 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, + 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x44, 0x42, + 0x55, 0x53, 0x33, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x54, 0x4d, 0x53, 0x20, + 0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, + 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, + 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, + 0x44, 0x42, 0x55, 0x53, 0x34, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x42, 0x75, + 0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x20, 0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, + 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, + 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, + 0x41, 0x44, 0x42, 0x55, 0x53, 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, + 0x63, 0x65, 0x20, 0x3a, 0x20, 0x30, 0x20, 0x69, 0x66, 0x20, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, + 0x20, 0x2d, 0x3e, 0x20, 0x69, 0x6e, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, + 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, + 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, + 0x44, 0x42, 0x55, 0x53, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54, 0x53, + 0x52, 0x53, 0x54, 0x20, 0x2d, 0x3e, 0x20, 0x69, 0x6e, 0x0d, 0x0a, 0x73, + 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, + 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, + 0x52, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x37, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, + 0x20, 0x52, 0x54, 0x43, 0x4b, 0x20, 0x2d, 0x3e, 0x20, 0x69, 0x6e, 0x0d, + 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, + 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, + 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x43, 0x42, 0x55, 0x53, 0x30, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x31, 0x20, 0x23, 0x20, 0x54, 0x52, 0x53, 0x54, 0x20, 0x2d, 0x3e, + 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, + 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, + 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x43, 0x42, + 0x55, 0x53, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x53, 0x52, 0x53, 0x54, + 0x20, 0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, + 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, + 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, + 0x41, 0x43, 0x42, 0x55, 0x53, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x54, + 0x52, 0x53, 0x54, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, + 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, + 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, + 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x43, 0x42, 0x55, 0x53, 0x33, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x31, 0x20, 0x23, 0x20, 0x52, 0x45, 0x44, 0x20, 0x4c, 0x45, 0x44, 0x20, + 0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, + 0x0a, 0x23, 0x20, 0x53, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x47, 0x50, 0x49, 0x4f, + 0x73, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, + 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, + 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x41, + 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x44, + 0x42, 0x55, 0x53, 0x30, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, + 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, + 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, + 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, + 0x44, 0x42, 0x55, 0x53, 0x31, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, + 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, + 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, + 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, + 0x41, 0x44, 0x42, 0x55, 0x53, 0x32, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, + 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, + 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, + 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, + 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x33, 0x20, 0x20, 0x20, 0x31, 0x0d, + 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, + 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, + 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x45, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x34, 0x20, 0x20, 0x20, 0x30, + 0x20, 0x23, 0x20, 0x4a, 0x54, 0x41, 0x47, 0x20, 0x62, 0x75, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x28, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x29, 0x0d, 0x0a, + 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, + 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, + 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, + 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x35, 0x20, 0x20, 0x20, 0x30, 0x0d, + 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, + 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, + 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x45, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x36, 0x20, 0x20, 0x20, 0x30, + 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, + 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, + 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x45, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x37, 0x20, 0x20, 0x20, + 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, + 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, + 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43, 0x42, 0x55, 0x53, 0x30, + 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54, 0x52, 0x53, 0x54, 0x0d, + 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, + 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, + 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x45, 0x5f, 0x41, 0x43, 0x42, 0x55, 0x53, 0x31, 0x20, 0x20, 0x20, 0x30, + 0x20, 0x23, 0x20, 0x53, 0x52, 0x53, 0x54, 0x0d, 0x0a, 0x73, 0x65, 0x74, + 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, + 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x41, + 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43, + 0x42, 0x55, 0x53, 0x32, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54, + 0x52, 0x53, 0x54, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, + 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, + 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, + 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43, 0x42, 0x55, + 0x53, 0x33, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x52, 0x45, 0x44, + 0x20, 0x4c, 0x45, 0x44, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, + 0x20, 0x53, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x47, 0x50, 0x49, 0x4f, 0x73, 0x20, + 0x70, 0x6f, 0x6c, 0x61, 0x72, 0x69, 0x74, 0x79, 0x0d, 0x0a, 0x23, 0x20, + 0x30, 0x20, 0x3a, 0x20, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x48, + 0x69, 0x67, 0x68, 0x2e, 0x0d, 0x0a, 0x23, 0x20, 0x31, 0x20, 0x3a, 0x20, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x4c, 0x6f, 0x77, 0x2e, 0x0d, + 0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, + 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, + 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, + 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x30, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, + 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, + 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, + 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x31, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, + 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, + 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, + 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x32, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, + 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, + 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, + 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x33, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, + 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, + 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, + 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x34, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, + 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, + 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, + 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, + 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, + 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, + 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, + 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, + 0x53, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, + 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, + 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, + 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, + 0x55, 0x53, 0x37, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, + 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, + 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, + 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, + 0x41, 0x43, 0x42, 0x55, 0x53, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x54, 0x52, 0x53, 0x54, 0x20, 0x69, + 0x73, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x6c, 0x6f, 0x77, + 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, + 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, + 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x43, + 0x42, 0x55, 0x53, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, + 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, + 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, + 0x43, 0x42, 0x55, 0x53, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, + 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, + 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, + 0x41, 0x43, 0x42, 0x55, 0x53, 0x33, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, + 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, + 0x52, 0x53, 0x54, 0x20, 0x2f, 0x20, 0x53, 0x52, 0x53, 0x54, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x70, 0x69, 0x6e, 0x73, 0x0d, + 0x0a, 0x23, 0x20, 0x30, 0x3c, 0x3e, 0x37, 0x20, 0x20, 0x3a, 0x20, 0x41, + 0x44, 0x42, 0x55, 0x53, 0x0d, 0x0a, 0x23, 0x20, 0x38, 0x3c, 0x3e, 0x31, + 0x31, 0x20, 0x3a, 0x20, 0x41, 0x43, 0x42, 0x55, 0x53, 0x0d, 0x0a, 0x23, + 0x20, 0x53, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x2d, 0x31, 0x20, 0x77, + 0x68, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2f, 0x75, 0x73, 0x65, 0x64, 0x2e, 0x0d, + 0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, + 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, + 0x5f, 0x54, 0x52, 0x53, 0x54, 0x5f, 0x4f, 0x45, 0x5f, 0x50, 0x49, 0x4e, + 0x4e, 0x55, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, + 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, + 0x45, 0x54, 0x5f, 0x54, 0x52, 0x53, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x45, 0x5f, 0x50, 0x49, 0x4e, 0x4e, 0x55, 0x4d, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, + 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, + 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x53, 0x52, 0x53, 0x54, 0x5f, 0x4f, + 0x45, 0x5f, 0x50, 0x49, 0x4e, 0x4e, 0x55, 0x4d, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x0d, + 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, + 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x53, 0x52, 0x53, 0x54, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x49, 0x4e, 0x4e, 0x55, + 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, + 0x31, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, + 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, + 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, + 0x45, 0x44, 0x5f, 0x50, 0x49, 0x4e, 0x4e, 0x55, 0x4d, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x31, 0x31, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, + 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, + 0x4a, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x52, 0x53, 0x54, 0x5f, 0x44, 0x45, + 0x4c, 0x41, 0x59, 0x5f, 0x4d, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x30, 0x30, 0x0d, 0x0a, + 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x23, 0x20, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, + 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, + 0x50, 0x49, 0x4f, 0x5f, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x30, + 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, + 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f, 0x5f, + 0x42, 0x41, 0x53, 0x45, 0x5f, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x20, + 0x22, 0x2f, 0x73, 0x79, 0x73, 0x2f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2f, + 0x67, 0x70, 0x69, 0x6f, 0x22, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, + 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, + 0x47, 0x50, 0x49, 0x4f, 0x5f, 0x54, 0x4d, 0x53, 0x5f, 0x50, 0x49, 0x4e, + 0x20, 0x32, 0x34, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, + 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f, + 0x5f, 0x54, 0x44, 0x49, 0x5f, 0x50, 0x49, 0x4e, 0x20, 0x32, 0x35, 0x0d, + 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, + 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f, 0x5f, 0x54, 0x44, 0x4f, + 0x5f, 0x50, 0x49, 0x4e, 0x20, 0x32, 0x36, 0x0d, 0x0a, 0x73, 0x65, 0x74, + 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, + 0x47, 0x50, 0x49, 0x4f, 0x5f, 0x54, 0x43, 0x4b, 0x5f, 0x50, 0x49, 0x4e, + 0x20, 0x32, 0x37, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, + 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, + 0x49, 0x4f, 0x5f, 0x54, 0x4d, 0x53, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x49, + 0x4e, 0x56, 0x45, 0x52, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, + 0x54, 0x59, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, + 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, + 0x4f, 0x5f, 0x54, 0x44, 0x49, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x49, 0x4e, + 0x56, 0x45, 0x52, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, + 0x59, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, + 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f, + 0x5f, 0x54, 0x44, 0x4f, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x49, 0x4e, 0x56, + 0x45, 0x52, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, + 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, + 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f, 0x5f, + 0x54, 0x43, 0x4b, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x49, 0x4e, 0x56, 0x45, + 0x52, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x20, + 0x30, 0x0d, 0x0a +}; +unsigned int config_script_len = 5955; diff --git a/lib_jtag_core/src/dbg_logs.c b/lib_jtag_core/src/dbg_logs.c new file mode 100644 index 0000000..d62aa28 --- /dev/null +++ b/lib_jtag_core/src/dbg_logs.c @@ -0,0 +1,139 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file dbg_logs.c + * @brief logs/debug output + * @author Jean-François DEL NERO + */ +#include +#include +#include +#include +#include +#include + +#include "./drivers/drv_loader.h" +#include "jtag_core_internal.h" +#include "jtag_core.h" + +#include "./os_interface/os_interface.h" + +#include "dbg_logs.h" + +int jtagcore_logs_printf(jtag_core * jc,int MSGTYPE,char * chaine, ...) +{ + char tmp_msg[1024+1]; + char tmp_msg2[1024]; + JTAGCORE_PRINT_FUNC print_callback; + + if( jc->logs_level <= MSGTYPE ) + { + if( jc->jtagcore_print_callback ) + { + va_list marker; + va_start( marker, chaine ); + + print_callback = jc->jtagcore_print_callback; + + switch(MSGTYPE) + { + case MSG_INFO_0: + strcpy(tmp_msg,"Info : "); + break; + case MSG_INFO_1: + strcpy(tmp_msg,"Info : "); + break; + case MSG_WARNING: + strcpy(tmp_msg,"Warning : "); + break; + case MSG_ERROR: + strcpy(tmp_msg,"Error : "); + break; + case MSG_DEBUG: + strcpy(tmp_msg,"Debug : "); + break; + default: + strcpy(tmp_msg,"Unknown : "); + break; + } + + vsprintf(tmp_msg2,chaine,marker); + genos_strndstcat(tmp_msg, tmp_msg2, sizeof(tmp_msg) ); + tmp_msg[sizeof(tmp_msg) - 1] = '\0'; + + print_callback( jc, tmp_msg); + + va_end( marker ); + } + } + return 0; +} + +int jtagcore_set_logs_callback(jtag_core * jc, JTAGCORE_PRINT_FUNC jtag_core_print) +{ + if(jc) + { + jc->jtagcore_print_callback = jtag_core_print; + + return JTAG_CORE_NO_ERROR; + } + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_set_logs_level(jtag_core * jc,int level) +{ + if(jc) + { + jc->logs_level = level; + + return JTAG_CORE_NO_ERROR; + } + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_get_logs_level(jtag_core * jc) +{ + if(jc) + { + return jc->logs_level; + } + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_set_logs_file(jtag_core * jc,char * path) +{ + if(jc) + { + strncpy(jc->log_file_path, path, DEFAULT_BUFLEN - 1); + + return JTAG_CORE_NO_ERROR; + } + return JTAG_CORE_BAD_PARAMETER; +} + +char * jtagcore_get_logs_file(jtag_core * jc) +{ + if(jc) + { + return jc->log_file_path; + } + + return NULL; +} diff --git a/lib_jtag_core/src/dbg_logs.h b/lib_jtag_core/src/dbg_logs.h new file mode 100644 index 0000000..8e01291 --- /dev/null +++ b/lib_jtag_core/src/dbg_logs.h @@ -0,0 +1,26 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file dbg_logs.c + * @brief logs/debug output + * @author Jean-François DEL NERO + */ + +int jtagcore_logs_printf(jtag_core * jc, int MSGTYPE, char * chaine, ...); diff --git a/lib_jtag_core/src/drivers/drivers_list.c b/lib_jtag_core/src/drivers/drivers_list.c new file mode 100644 index 0000000..2b1dfb3 --- /dev/null +++ b/lib_jtag_core/src/drivers/drivers_list.c @@ -0,0 +1,65 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file drivers_list.h + * @brief drivers list + * @author Jean-François DEL NERO + */ + +#include "drv_loader.h" + +#include "../jtag_core_internal.h" +#include "../jtag_core.h" + +#include "../bsdl_parser/bsdl_loader.h" + +#ifdef WIN32 +#include "./ftdi_jtag/ftdi_jtag_drv.h" +#include "./lpt_jtag/lpt_jtag_drv.h" +#endif + +#if defined(__linux__) +#include "./linux_gpio_jtag/linux_gpio_jtag_drv.h" +#endif + +#if defined(__linux__) || defined(WIN32) +#include "./jlink_jtag/jlink_jtag_drv.h" +#endif + +#include "drivers_list.h" + +const drv_entry staticdrvs[] = +{ +#ifdef WIN32 + {(DRV_GETMODULEINFOS)drv_FTDI_libGetDrv,0}, +#if !defined(_WIN64) + {(DRV_GETMODULEINFOS)drv_LPT_libGetDrv,0}, + {(DRV_GETMODULEINFOS)drv_LPT_libGetDrv,1}, + {(DRV_GETMODULEINFOS)drv_LPT_libGetDrv,2}, +#endif +#endif +#if defined(__linux__) || defined(WIN32) + {(DRV_GETMODULEINFOS)drv_JLINK_libGetDrv,0}, +#endif +#if defined(__linux__) + {(DRV_GETMODULEINFOS)drv_LinuxGPIO_libGetDrv,0}, +#endif + {(DRV_GETMODULEINFOS)-1,0} +}; diff --git a/lib_jtag_core/src/drivers/drivers_list.h b/lib_jtag_core/src/drivers/drivers_list.h new file mode 100644 index 0000000..76edbb4 --- /dev/null +++ b/lib_jtag_core/src/drivers/drivers_list.h @@ -0,0 +1,33 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file drivers_list.h + * @brief drivers list struct + * @author Jean-François DEL NERO + */ +typedef struct _drv_entry +{ + DRV_GETMODULEINFOS getinfosfunc; + int sub_drv_id; +}drv_entry; + +extern const drv_entry staticdrvs[]; + + diff --git a/lib_jtag_core/src/drivers/drv_loader.c b/lib_jtag_core/src/drivers/drv_loader.c new file mode 100644 index 0000000..d555575 --- /dev/null +++ b/lib_jtag_core/src/drivers/drv_loader.c @@ -0,0 +1,120 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file drv_loader.c + * @brief driver loader + * @author Jean-François DEL NERO + */ + +#include +#include + +#include "drv_loader.h" + +#include "../jtag_core_internal.h" +#include "../jtag_core.h" + +#include "../bsdl_parser/bsdl_loader.h" + +#include "drivers_list.h" + +#include "../dbg_logs.h" + +int GetDrvInfo(void * jc_ctx,unsigned long infotype,void * returnvalue,const char * drv_id,const char * drv_desc,drv_ptr * drv_func) +{ + if(jc_ctx) + { + if(returnvalue) + { + switch(infotype) + { + case GET_DRV_ID: + *(char**)(returnvalue)=(char*)drv_id; + break; + + case GET_DRV_DESCRIPTION: + strcpy(returnvalue, (char*)drv_desc); + break; + + case GET_DRV_FUNCPTR: + memcpy(returnvalue,drv_func,sizeof(drv_ptr)); + break; + + case GET_DRV_DETECT: + *((int*)(returnvalue)) = drv_func->drv_Detect(jc_ctx); + break; + + default: + return JTAG_CORE_BAD_PARAMETER; + break; + } + + return JTAG_CORE_NO_ERROR; + } + } + return JTAG_CORE_BAD_PARAMETER; +} + + +int jtagcore_loaddriver(jtag_core * jc, int id, char * parameters) +{ + int i,ret; + i = 0; + + while (staticdrvs[i].getinfosfunc != (DRV_GETMODULEINFOS)-1 ) + { + i++; + } + + if ( (id >> 8) < i) + { + if (jc->io_functions.drv_DeInit) + { + jc->io_functions.drv_DeInit(jc); + memset(&jc->io_functions, 0, sizeof(drv_ptr)); + } + + staticdrvs[id>>8].getinfosfunc(jc, id & 0xFF, GET_DRV_FUNCPTR, &jc->io_functions); + + if( jc->io_functions.drv_Init ) + { + ret = jc->io_functions.drv_Init(jc, id & 0xFF,0); + if (ret < 0) + { + jtagcore_logs_printf(jc, MSG_ERROR, "jtagcore_loaddriver : Can't load the driver !\r\n"); + memset(&jc->io_functions, 0, sizeof(drv_ptr)); + } + else + { + jtagcore_logs_printf(jc, MSG_INFO_0, "jtagcore_loaddriver : Probe Driver 0x%.8X loaded...\r\n", id); + } + } + else + goto fail; + + return ret; + } + +fail: + jtagcore_logs_printf(jc, MSG_ERROR, "jtagcore_loaddriver : Driver ID not found !\r\n"); + + return JTAG_CORE_NOT_FOUND; +}; + diff --git a/lib_jtag_core/src/drivers/drv_loader.h b/lib_jtag_core/src/drivers/drv_loader.h new file mode 100644 index 0000000..93ea1cd --- /dev/null +++ b/lib_jtag_core/src/drivers/drv_loader.h @@ -0,0 +1,50 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file drv_loader.h + * @brief driver functions definitions + * @author Jean-François DEL NERO + */ + +enum { + GET_DRV_ID = 1, + GET_DRV_DESCRIPTION, + GET_DRV_FUNCPTR, + GET_DRV_DETECT +}; + +typedef int (*DRV_DETECT) (void* jtag_core); +typedef int (*DRV_INIT) (void* jtag_core,int sub_drv,char * params); +typedef int (*DRV_TXRXDATA) (void* jtag_core, unsigned char * str_out, unsigned char * str_in, int size); +typedef int (*DRV_TXTMS) (void* jtag_core, unsigned char * str_out, int size); +typedef int (*DRV_GETMODULEINFOS) (void* jtag_core,int sub_drv,unsigned int infotype, void * returnvalue); +typedef int (*DRV_DEINIT) (void* jtag_core); + +typedef struct drv_ptr_ +{ + DRV_DETECT drv_Detect; + DRV_INIT drv_Init; + DRV_DEINIT drv_DeInit; + DRV_TXTMS drv_TX_TMS; + DRV_TXRXDATA drv_TXRX_DATA; + DRV_GETMODULEINFOS drv_Get_ModInfos; +} drv_ptr; + +int GetDrvInfo(void * jc_ctx, unsigned long infotype, void * returnvalue, const char * drv_id, const char * drv_desc, drv_ptr * drv_func); \ No newline at end of file diff --git a/lib_jtag_core/src/drivers/ftdi_jtag/ftdi/WinTypes.h b/lib_jtag_core/src/drivers/ftdi_jtag/ftdi/WinTypes.h new file mode 100644 index 0000000..5114b95 --- /dev/null +++ b/lib_jtag_core/src/drivers/ftdi_jtag/ftdi/WinTypes.h @@ -0,0 +1,136 @@ +#ifndef __WINDOWS_TYPES__ +#define __WINDOWS_TYPES__ + +#define WINAPI + +typedef unsigned int DWORD; +typedef unsigned int ULONG; +typedef unsigned short USHORT; +typedef unsigned short SHORT; +typedef unsigned char UCHAR; +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef BYTE *LPBYTE; +typedef unsigned int BOOL; +typedef unsigned char BOOLEAN; +typedef unsigned char CHAR; +typedef BOOL *LPBOOL; +typedef UCHAR *PUCHAR; +typedef const char *LPCSTR; +typedef char *PCHAR; +typedef void *PVOID; +typedef void *HANDLE; +typedef unsigned int LONG; +typedef int INT; +typedef unsigned int UINT; +typedef char *LPSTR; +typedef char *LPTSTR; +typedef const char *LPCTSTR; +typedef DWORD *LPDWORD; +typedef WORD *LPWORD; +typedef ULONG *PULONG; +typedef LONG *LPLONG; +typedef PVOID LPVOID; +typedef void VOID; +typedef unsigned long long int ULONGLONG; + +typedef struct _OVERLAPPED { + DWORD Internal; + DWORD InternalHigh; + DWORD Offset; + DWORD OffsetHigh; + HANDLE hEvent; +} OVERLAPPED, *LPOVERLAPPED; + +typedef struct _SECURITY_ATTRIBUTES { + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; + +#include +// Substitute for HANDLE returned by Windows CreateEvent API. +// FT_SetEventNotification expects parameter 3 to be the address +// of one of these structures. +typedef struct _EVENT_HANDLE +{ + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + int iVar; +} EVENT_HANDLE; + +typedef struct timeval SYSTEMTIME; +typedef struct timeval FILETIME; +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +// +// Modem Status Flags +// +#define MS_CTS_ON ((DWORD)0x0010) +#define MS_DSR_ON ((DWORD)0x0020) +#define MS_RING_ON ((DWORD)0x0040) +#define MS_RLSD_ON ((DWORD)0x0080) + +// +// Error Flags +// +#define CE_RXOVER 0x0001 // Receive Queue overflow +#define CE_OVERRUN 0x0002 // Receive Overrun Error +#define CE_RXPARITY 0x0004 // Receive Parity Error +#define CE_FRAME 0x0008 // Receive Framing error +#define CE_BREAK 0x0010 // Break Detected +#define CE_TXFULL 0x0100 // TX Queue is full +#define CE_PTO 0x0200 // LPTx Timeout +#define CE_IOE 0x0400 // LPTx I/O Error +#define CE_DNS 0x0800 // LPTx Device not selected +#define CE_OOP 0x1000 // LPTx Out-Of-Paper +#define CE_MODE 0x8000 // Requested mode unsupported + +// +// Events +// +#define EV_RXCHAR 0x0001 // Any Character received +#define EV_RXFLAG 0x0002 // Received certain character +#define EV_TXEMPTY 0x0004 // Transmit Queue Empty +#define EV_CTS 0x0008 // CTS changed state +#define EV_DSR 0x0010 // DSR changed state +#define EV_RLSD 0x0020 // RLSD changed state +#define EV_BREAK 0x0040 // BREAK received +#define EV_ERR 0x0080 // Line status error occurred +#define EV_RING 0x0100 // Ring signal detected +#define EV_PERR 0x0200 // Printer error occured +#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full +#define EV_EVENT1 0x0800 // Provider specific event 1 +#define EV_EVENT2 0x1000 // Provider specific event 2 + +// +// Escape Functions +// +#define SETXOFF 1 // Simulate XOFF received +#define SETXON 2 // Simulate XON received +#define SETRTS 3 // Set RTS high +#define CLRRTS 4 // Set RTS low +#define SETDTR 5 // Set DTR high +#define CLRDTR 6 // Set DTR low +#define RESETDEV 7 // Reset device if possible +#define SETBREAK 8 // Set the device break line. +#define CLRBREAK 9 // Clear the device break line. + +// +// PURGE function flags. +// +#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port. +#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port. +#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there. +#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there. + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE 0xFFFFFFFF +#endif + +#endif /* __WINDOWS_TYPES__ */ diff --git a/lib_jtag_core/src/drivers/ftdi_jtag/ftdi/ftd2xx.h b/lib_jtag_core/src/drivers/ftdi_jtag/ftdi/ftd2xx.h new file mode 100644 index 0000000..d5cac72 --- /dev/null +++ b/lib_jtag_core/src/drivers/ftdi_jtag/ftdi/ftd2xx.h @@ -0,0 +1,1443 @@ +/*++ + +Copyright © 2001-2011 Future Technology Devices International Limited + +THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. + +FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. + +IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE +RESPONSIBILITY OF THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL +RE-CERTIFICATION AS A RESULT OF MAKING THESE CHANGES. + + +Module Name: + +ftd2xx.h + +Abstract: + +Native USB device driver for FTDI FT232x, FT245x, FT2232x and FT4232x devices +FTD2XX library definitions + +Environment: + +kernel & user mode + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +#ifdef _WIN32 +// Compiling on Windows +#include + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#elif defined(FTD2XX_STATIC) +// Avoid decorations when linking statically to D2XX. +#define FTD2XX_API +// Static D2XX depends on these Windows libs: +#pragma comment(lib, "setupapi.lib") +#pragma comment(lib, "advapi32.lib") +#pragma comment(lib, "user32.lib") +#else +#define FTD2XX_API __declspec(dllimport) +#endif + +#else // _WIN32 +// Compiling on non-Windows platform. +#include "WinTypes.h" +// No decorations needed. +#define FTD2XX_API + +#endif // _WIN32 + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR, + FT_DEVICE_LIST_NOT_READY, +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +#define FT_OPEN_MASK (FT_OPEN_BY_SERIAL_NUMBER | \ + FT_OPEN_BY_DESCRIPTION | \ + FT_OPEN_BY_LOCATION) + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 +#define FT_EVENT_LINE_STATUS 4 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R, + FT_DEVICE_2232H, + FT_DEVICE_4232H, + FT_DEVICE_232H, + FT_DEVICE_X_SERIES, + FT_DEVICE_4222H_0, + FT_DEVICE_4222H_1_2, + FT_DEVICE_4222H_3, + FT_DEVICE_4222_PROG, +}; + +// +// Bit Modes +// + +#define FT_BITMODE_RESET 0x00 +#define FT_BITMODE_ASYNC_BITBANG 0x01 +#define FT_BITMODE_MPSSE 0x02 +#define FT_BITMODE_SYNC_BITBANG 0x04 +#define FT_BITMODE_MCU_HOST 0x08 +#define FT_BITMODE_FAST_SERIAL 0x10 +#define FT_BITMODE_CBUS_BITBANG 0x20 +#define FT_BITMODE_SYNC_FIFO 0x40 + +// +// FT232R CBUS Options EEPROM values +// + +#define FT_232R_CBUS_TXDEN 0x00 // Tx Data Enable +#define FT_232R_CBUS_PWRON 0x01 // Power On +#define FT_232R_CBUS_RXLED 0x02 // Rx LED +#define FT_232R_CBUS_TXLED 0x03 // Tx LED +#define FT_232R_CBUS_TXRXLED 0x04 // Tx and Rx LED +#define FT_232R_CBUS_SLEEP 0x05 // Sleep +#define FT_232R_CBUS_CLK48 0x06 // 48MHz clock +#define FT_232R_CBUS_CLK24 0x07 // 24MHz clock +#define FT_232R_CBUS_CLK12 0x08 // 12MHz clock +#define FT_232R_CBUS_CLK6 0x09 // 6MHz clock +#define FT_232R_CBUS_IOMODE 0x0A // IO Mode for CBUS bit-bang +#define FT_232R_CBUS_BITBANG_WR 0x0B // Bit-bang write strobe +#define FT_232R_CBUS_BITBANG_RD 0x0C // Bit-bang read strobe + +// +// FT232H CBUS Options EEPROM values +// + +#define FT_232H_CBUS_TRISTATE 0x00 // Tristate +#define FT_232H_CBUS_TXLED 0x01 // Tx LED +#define FT_232H_CBUS_RXLED 0x02 // Rx LED +#define FT_232H_CBUS_TXRXLED 0x03 // Tx and Rx LED +#define FT_232H_CBUS_PWREN 0x04 // Power Enable +#define FT_232H_CBUS_SLEEP 0x05 // Sleep +#define FT_232H_CBUS_DRIVE_0 0x06 // Drive pin to logic 0 +#define FT_232H_CBUS_DRIVE_1 0x07 // Drive pin to logic 1 +#define FT_232H_CBUS_IOMODE 0x08 // IO Mode for CBUS bit-bang +#define FT_232H_CBUS_TXDEN 0x09 // Tx Data Enable +#define FT_232H_CBUS_CLK30 0x0A // 30MHz clock +#define FT_232H_CBUS_CLK15 0x0B // 15MHz clock +#define FT_232H_CBUS_CLK7_5 0x0C // 7.5MHz clock + +// +// FT X Series CBUS Options EEPROM values +// + +#define FT_X_SERIES_CBUS_TRISTATE 0x00 // Tristate +#define FT_X_SERIES_CBUS_TXLED 0x01 // Tx LED +#define FT_X_SERIES_CBUS_RXLED 0x02 // Rx LED +#define FT_X_SERIES_CBUS_TXRXLED 0x03 // Tx and Rx LED +#define FT_X_SERIES_CBUS_PWREN 0x04 // Power Enable +#define FT_X_SERIES_CBUS_SLEEP 0x05 // Sleep +#define FT_X_SERIES_CBUS_DRIVE_0 0x06 // Drive pin to logic 0 +#define FT_X_SERIES_CBUS_DRIVE_1 0x07 // Drive pin to logic 1 +#define FT_X_SERIES_CBUS_IOMODE 0x08 // IO Mode for CBUS bit-bang +#define FT_X_SERIES_CBUS_TXDEN 0x09 // Tx Data Enable +#define FT_X_SERIES_CBUS_CLK24 0x0A // 24MHz clock +#define FT_X_SERIES_CBUS_CLK12 0x0B // 12MHz clock +#define FT_X_SERIES_CBUS_CLK6 0x0C // 6MHz clock +#define FT_X_SERIES_CBUS_BCD_CHARGER 0x0D // Battery charger detected +#define FT_X_SERIES_CBUS_BCD_CHARGER_N 0x0E // Battery charger detected inverted +#define FT_X_SERIES_CBUS_I2C_TXE 0x0F // I2C Tx empty +#define FT_X_SERIES_CBUS_I2C_RXF 0x10 // I2C Rx full +#define FT_X_SERIES_CBUS_VBUS_SENSE 0x11 // Detect VBUS +#define FT_X_SERIES_CBUS_BITBANG_WR 0x12 // Bit-bang write strobe +#define FT_X_SERIES_CBUS_BITBANG_RD 0x13 // Bit-bang read strobe +#define FT_X_SERIES_CBUS_TIMESTAMP 0x14 // Toggle output when a USB SOF token is received +#define FT_X_SERIES_CBUS_KEEP_AWAKE 0x15 // + + +// Driver types +#define FT_DRIVER_TYPE_D2XX 0 +#define FT_DRIVER_TYPE_VCP 1 + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef FTD2XX_STATIC + FTD2XX_API + FT_STATUS WINAPI FT_Initialise( + void + ); + + FTD2XX_API + void WINAPI FT_Finalise( + void + ); +#endif // FTD2XX_STATIC + + FTD2XX_API + FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToRead, + LPDWORD lpBytesReturned + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToWrite, + LPDWORD lpBytesWritten + ); + + FTD2XX_API + FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + + FTD2XX_API + FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + + // + // structure to hold program data for FT_EE_Program, FT_EE_ProgramEx, FT_EE_Read + // and FT_EE_ReadEx functions + // + typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232 extensions + // 2 = FT232R extensions + // 3 = FT2232H extensions + // 4 = FT4232H extensions + // 5 = FT232H extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 (FT232B) extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // Rev 5 (FT2232) extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // Rev 6 (FT232R) extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR RIsD2XX; // non-zero if using D2XX driver + // + // Rev 7 (FT2232H) Extensions + // + UCHAR PullDownEnable7; // non-zero if pull down enabled + UCHAR SerNumEnable7; // non-zero if serial number to be used + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial + UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial + UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // + // Rev 8 (FT4232H) Extensions + // + UCHAR PullDownEnable8; // non-zero if pull down enabled + UCHAR SerNumEnable8; // non-zero if serial number to be used + UCHAR ASlowSlew; // non-zero if A pins have slow slew + UCHAR ASchmittInput; // non-zero if A pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if B pins have slow slew + UCHAR BSchmittInput; // non-zero if B pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if C pins have slow slew + UCHAR CSchmittInput; // non-zero if C pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if D pins have slow slew + UCHAR DSchmittInput; // non-zero if D pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers + // + // Rev 9 (FT232H) Extensions + // + UCHAR PullDownEnableH; // non-zero if pull down enabled + UCHAR SerNumEnableH; // non-zero if serial number to be used + UCHAR ACSlowSlewH; // non-zero if AC pins have slow slew + UCHAR ACSchmittInputH; // non-zero if AC pins are Schmitt input + UCHAR ACDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlewH; // non-zero if AD pins have slow slew + UCHAR ADSchmittInputH; // non-zero if AD pins are Schmitt input + UCHAR ADDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR Cbus0H; // Cbus Mux control + UCHAR Cbus1H; // Cbus Mux control + UCHAR Cbus2H; // Cbus Mux control + UCHAR Cbus3H; // Cbus Mux control + UCHAR Cbus4H; // Cbus Mux control + UCHAR Cbus5H; // Cbus Mux control + UCHAR Cbus6H; // Cbus Mux control + UCHAR Cbus7H; // Cbus Mux control + UCHAR Cbus8H; // Cbus Mux control + UCHAR Cbus9H; // Cbus Mux control + UCHAR IsFifoH; // non-zero if interface is 245 FIFO + UCHAR IsFifoTarH; // non-zero if interface is 245 FIFO CPU target + UCHAR IsFastSerH; // non-zero if interface is Fast serial + UCHAR IsFT1248H; // non-zero if interface is FT1248 + UCHAR FT1248CpolH; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248LsbH; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControlH; // FT1248 flow control enable + UCHAR IsVCPH; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnableH; // non-zero if using ACBUS7 to save power for self-powered designs + + } FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + + FTD2XX_API + FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + + + typedef struct ft_eeprom_header { + FT_DEVICE deviceType; // FTxxxx device type to be programmed + // Device descriptor options + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + UCHAR SerNumEnable; // non-zero if serial number to be used + // Config descriptor options + WORD MaxPower; // 0 < MaxPower <= 500 + UCHAR SelfPowered; // 0 = bus powered, 1 = self powered + UCHAR RemoteWakeup; // 0 = not capable, 1 = capable + // Hardware options + UCHAR PullDownEnable; // non-zero if pull down in suspend enabled + } FT_EEPROM_HEADER, *PFT_EEPROM_HEADER; + + + // FT232B EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_232b { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + } FT_EEPROM_232B, *PFT_EEPROM_232B; + + + // FT2232 EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_2232 { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + // Hardware options + UCHAR AIsFifo; // non-zero if interface is 245 FIFO + UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR AIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsFifo; // non-zero if interface is 245 FIFO + UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR BIsFastSer; // non-zero if interface is Fast serial + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // + } FT_EEPROM_2232, *PFT_EEPROM_2232; + + + // FT232R EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_232r { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR IsHighCurrent; // non-zero if interface is high current + // Hardware options + UCHAR UseExtOsc; // Use External Oscillator + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + // Driver option + UCHAR DriverType; // + } FT_EEPROM_232R, *PFT_EEPROM_232R; + + + // FT2232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_2232h { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // Hardware options + UCHAR AIsFifo; // non-zero if interface is 245 FIFO + UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR AIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsFifo; // non-zero if interface is 245 FIFO + UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR BIsFastSer; // non-zero if interface is Fast serial + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // + } FT_EEPROM_2232H, *PFT_EEPROM_2232H; + + + // FT4232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_4232h { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ASlowSlew; // non-zero if A pins have slow slew + UCHAR ASchmittInput; // non-zero if A pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if B pins have slow slew + UCHAR BSchmittInput; // non-zero if B pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if C pins have slow slew + UCHAR CSchmittInput; // non-zero if C pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if D pins have slow slew + UCHAR DSchmittInput; // non-zero if D pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // Hardware options + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // + UCHAR CDriverType; // + UCHAR DDriverType; // + } FT_EEPROM_4232H, *PFT_EEPROM_4232H; + + + // FT232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_232h { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew + UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input + UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew + UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input + UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // CBUS options + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR Cbus5; // Cbus Mux control + UCHAR Cbus6; // Cbus Mux control + UCHAR Cbus7; // Cbus Mux control + UCHAR Cbus8; // Cbus Mux control + UCHAR Cbus9; // Cbus Mux control + // FT1248 options + UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControl; // FT1248 flow control enable + // Hardware options + UCHAR IsFifo; // non-zero if interface is 245 FIFO + UCHAR IsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IsFastSer; // non-zero if interface is Fast serial + UCHAR IsFT1248 ; // non-zero if interface is FT1248 + UCHAR PowerSaveEnable; // + // Driver option + UCHAR DriverType; // + } FT_EEPROM_232H, *PFT_EEPROM_232H; + + + // FT X Series EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_x_series { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew + UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input + UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew + UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input + UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // CBUS options + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR Cbus5; // Cbus Mux control + UCHAR Cbus6; // Cbus Mux control + // UART signal options + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + // Battery Charge Detect options + UCHAR BCDEnable; // Enable Battery Charger Detection + UCHAR BCDForceCbusPWREN; // asserts the power enable signal on CBUS when charging port detected + UCHAR BCDDisableSleep; // forces the device never to go into sleep mode + // I2C options + WORD I2CSlaveAddress; // I2C slave device address + DWORD I2CDeviceId; // I2C device ID + UCHAR I2CDisableSchmitt; // Disable I2C Schmitt trigger + // FT1248 options + UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControl; // FT1248 flow control enable + // Hardware options + UCHAR RS485EchoSuppress; // + UCHAR PowerSaveEnable; // + // Driver option + UCHAR DriverType; // + } FT_EEPROM_X_SERIES, *PFT_EEPROM_X_SERIES; + + + FTD2XX_API + FT_STATUS WINAPI FT_EEPROM_Read( + FT_HANDLE ftHandle, + void *eepromData, + DWORD eepromDataSize, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + + + FTD2XX_API + FT_STATUS WINAPI FT_EEPROM_Program( + FT_HANDLE ftHandle, + void *eepromData, + DWORD eepromDataSize, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + + + FTD2XX_API + FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +#ifndef _WIN32 + // Extra functions for non-Windows platforms to compensate + // for lack of .INF file to specify Vendor and Product IDs. + + FTD2XX_API + FT_STATUS FT_SetVIDPID( + DWORD dwVID, + DWORD dwPID + ); + + FTD2XX_API + FT_STATUS FT_GetVIDPID( + DWORD * pdwVID, + DWORD * pdwPID + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetDeviceLocId( + FT_HANDLE ftHandle, + LPDWORD lpdwLocId + ); +#endif // _WIN32 + + FTD2XX_API + FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + + FTD2XX_API + FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + + // + // Win32-type functions + // + + FTD2XX_API + FT_HANDLE WINAPI FT_W32_CreateFile( + LPCTSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + + FTD2XX_API + BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + + FTD2XX_API + BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + + FTD2XX_API + BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + + FTD2XX_API + DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + + FTD2XX_API + BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + + // + // Win32 COMM API type functions + // + typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; + } FTCOMSTAT, *LPFTCOMSTAT; + + typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ + } FTDCB, *LPFTDCB; + + typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ + } FTTIMEOUTS,*LPFTTIMEOUTS; + + + FTD2XX_API + BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + + FTD2XX_API + BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + + FTD2XX_API + BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + + FTD2XX_API + BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetCommMask( + FT_HANDLE ftHandle, + LPDWORD lpdwEventMask + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + + FTD2XX_API + BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + + // + // Device information + // + + typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; + } FT_DEVICE_LIST_INFO_NODE; + + // Device information flags + enum { + FT_FLAGS_OPENED = 1, + FT_FLAGS_HISPEED = 2 + }; + + + FTD2XX_API + FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + + // + // Version information + // + + FTD2XX_API + FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + + FTD2XX_API + FT_STATUS WINAPI FT_Rescan( + void + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Reload( + WORD wVid, + WORD wPid + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetComPortNumber( + FT_HANDLE ftHandle, + LPLONG lpdwComPortNumber + ); + + + // + // FT232H additional EEPROM functions + // + + FTD2XX_API + FT_STATUS WINAPI FT_EE_ReadConfig( + FT_HANDLE ftHandle, + UCHAR ucAddress, + PUCHAR pucValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_WriteConfig( + FT_HANDLE ftHandle, + UCHAR ucAddress, + UCHAR ucValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_ReadECC( + FT_HANDLE ftHandle, + UCHAR ucOption, + LPWORD lpwValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetQueueStatusEx( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ComPortIdle( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ComPortCancelIdle( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_VendorCmdGet( + FT_HANDLE ftHandle, + UCHAR Request, + UCHAR *Buf, + USHORT Len + ); + + FTD2XX_API + FT_STATUS WINAPI FT_VendorCmdSet( + FT_HANDLE ftHandle, + UCHAR Request, + UCHAR *Buf, + USHORT Len + ); + + FTD2XX_API + FT_STATUS WINAPI FT_VendorCmdGetEx( + FT_HANDLE ftHandle, + USHORT wValue, + UCHAR *Buf, + USHORT Len + ); + + FTD2XX_API + FT_STATUS WINAPI FT_VendorCmdSetEx( + FT_HANDLE ftHandle, + USHORT wValue, + UCHAR *Buf, + USHORT Len + ); + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + diff --git a/lib_jtag_core/src/drivers/ftdi_jtag/ftdi_jtag_drv.c b/lib_jtag_core/src/drivers/ftdi_jtag/ftdi_jtag_drv.c new file mode 100644 index 0000000..3b2b324 --- /dev/null +++ b/lib_jtag_core/src/drivers/ftdi_jtag/ftdi_jtag_drv.c @@ -0,0 +1,967 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file ftdi_jtag_drv.c + * @brief FTDI based probes driver + * @author Jean-François DEL NERO + */ + +#include +#include +#include + +#if !defined(WIN32) +#include +#endif + +#include "../drv_loader.h" +#include "../../jtag_core_internal.h" +#include "../../jtag_core.h" + +#include "../../bsdl_parser/bsdl_loader.h" + +#include "../../dbg_logs.h" + +#include "../../os_interface/os_interface.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ftdi/ftd2xx.h" + +#ifdef __cplusplus +} +#endif + +#if defined(_WIN64) +#define MACH_WORD long long +#else +#define MACH_WORD int +#endif + +#if defined(WIN32) + +typedef struct _drv_desc +{ + char drv_id[128]; + char drv_desc[128]; + int id; + int ftdi_index; +}drv_desc; + +#define PROBE_GENERIC_FTDI 0 + +#define MAX_PROBES_FTDI 8 + +static drv_desc subdrv_list[MAX_PROBES_FTDI]= +{ + {"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0}, + {"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0}, + {"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0}, + {"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0}, + {"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0}, + {"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0}, + {"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0}, + {"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0} +}; + +/////////////////////////////////////////////////////////////////////////////// +// Command Processor for MPSSE and MCU Host Bus Emulation Modes +// +// The data shifting commands are made up of the following definitions: +// Bit 7 : 0 +// Bit 6 : Do write TMS +// Bit 5 : Do read TDO +// Bit 4 : Do write TDI +// Bit 3 : LSB first = 1 else MSB first = 0 +// Bit 2 : -ve CLK on read +// Bit 1 : bit mode = 1 else byte mode = 0 +// Bit 0 : -ve CLK on write + +// The write commands to TDI take effect when bits 7 and 6 are '0'. Read TDO will operate with TMS output or TDI output or on its own. + +// Clock Data Bytes Out on +ve clock edge MSB first (no read) +// 0x10, LengthL, LengthH, [Byte1..Byte65536 (max)] + +#define OP_WR_TMS (0x1 << 6) +#define OP_RD_TDO (0x1 << 5) +#define OP_WR_TDI (0x1 << 4) +#define OP_LSB_FIRST (0x1 << 3) +#define OP_FEDGE_RD (0x1 << 2) +#define OP_BIT_MODE (0x1 << 1) +#define OP_FEDGE_WR (0x1 << 0) + +#define CMD_ENABLE_LOOPBACK 0x84 +#define CMD_DISABLE_LOOPBACK 0x85 +#define CMD_SET_DIVISOR 0x86 // +0xValueL, 0xValueH +#define CMD_WAIT_IO_HIGH 0x88 +#define CMD_WAIT_IO_LOW 0x89 + +/////////////////////////////////////////////////////////////////////////////// + +static HMODULE lib_handle = 0; + +static FT_HANDLE ftdih = NULL; +static FT_DEVICE ftdi_device; + +static int trst_oe_pin, trst_state_pin; +static int srst_oe_pin, srst_state_pin; +static int led_pin; + +static unsigned char low_direction; +static unsigned char low_polarity; +static unsigned char low_output; + +static unsigned char high_output; +static unsigned char high_polarity; +static unsigned char high_direction; + +unsigned char ftdi_out_buf[64 * 1024]; +unsigned char ftdi_in_buf[64 * 1024]; + +#if !defined(WIN32) + +int Sleep( unsigned int timeout_ms ) +{ + struct timeval tv; + tv.tv_sec = timeout_ms/1000; + tv.tv_usec = (timeout_ms%1000) * 1000; + select(0, NULL, NULL, NULL, &tv); + + return 0; +} +#endif + + + +#if !defined(FTDILIB) + +typedef FT_STATUS(WINAPI * FT_OPEN)(DWORD deviceNumber, FT_HANDLE *pHandle); +typedef FT_STATUS(WINAPI * FT_OPENEX)(PVOID pArg1, DWORD Flags, FT_HANDLE *pHandle); +typedef FT_STATUS(WINAPI * FT_READ)(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesReturned); +typedef FT_STATUS(WINAPI * FT_WRITE)(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesWritten); +typedef FT_STATUS(WINAPI * FT_GETSTATUS)(FT_HANDLE ftHandle, DWORD *dwRxBytes, DWORD *dwTxBytes, DWORD *dwEventDWord); +typedef FT_STATUS(WINAPI * FT_PURGE)(FT_HANDLE ftHandle, ULONG Mask); +typedef FT_STATUS(WINAPI * FT_SETUSBPARAMETERS)(FT_HANDLE ftHandle, ULONG ulInTransferSize, ULONG ulOutTransferSize); +typedef FT_STATUS(WINAPI * FT_SETLATENCYTIMER)(FT_HANDLE ftHandle, UCHAR ucLatency); +typedef FT_STATUS(WINAPI * FT_SETEVENTNOTIFICATION)(FT_HANDLE ftHandle, DWORD dwEventMask, PVOID pvArg); +typedef FT_STATUS(WINAPI * FT_CLOSE)(FT_HANDLE ftHandle); +typedef FT_STATUS(WINAPI * FT_LISTDEVICES)(LPVOID pArg1, LPVOID pArg2, DWORD Flags); +typedef FT_STATUS(WINAPI * FT_SETBITMODE)(FT_HANDLE ftHandle, UCHAR ucMask, UCHAR ucEnable); +typedef FT_STATUS(WINAPI * FT_SETTIMEOUTS)(FT_HANDLE ftHandle, ULONG ReadTimeout, ULONG WriteTimeout); +typedef FT_STATUS(WINAPI * FT_GETQUEUESTATUS)(FT_HANDLE ftHandle, DWORD *dwRxBytes); +typedef FT_STATUS(WINAPI * FT_GETDEVICEINFO)(FT_HANDLE ftHandle, FT_DEVICE *lpftDevice, LPDWORD lpdwID, PCHAR SerialNumber, PCHAR Description, LPVOID Dummy); +typedef FT_STATUS(WINAPI * FT_RESETDEVICE)(FT_HANDLE ftHandle); +typedef FT_STATUS(WINAPI * FT_SETCHARS)(FT_HANDLE ftHandle, UCHAR EventChar, UCHAR EventCharEnabled, UCHAR ErrorChar, UCHAR ErrorCharEnabled); + +FT_OPEN pFT_Open; +FT_OPENEX pFT_OpenEx; +FT_READ pFT_Read; +FT_WRITE pFT_Write; +FT_GETSTATUS pFT_GetStatus; +FT_PURGE pFT_Purge; +FT_SETUSBPARAMETERS pFT_SetUSBParameters; +FT_SETLATENCYTIMER pFT_SetLatencyTimer; +FT_SETEVENTNOTIFICATION pFT_SetEventNotification; +FT_CLOSE pFT_Close; +FT_LISTDEVICES pFT_ListDevices; +FT_SETBITMODE pFT_SetBitMode; +FT_SETTIMEOUTS pFT_SetTimeouts; +FT_GETQUEUESTATUS pFT_GetQueueStatus; +FT_GETDEVICEINFO pFT_GetDeviceInfo; +FT_RESETDEVICE pFT_ResetDevice; +FT_SETCHARS pFT_SetChars; + +#else + + +#endif + + +static int ft2232_set_data_bits_low_byte(unsigned char value, unsigned char direction) +{ + FT_STATUS status; + DWORD dw_bytes_written = 0; + unsigned char buf[3]; + + buf[0] = 0x80; // command "set data bits low byte" + buf[1] = value; // value + buf[2] = direction; // direction + + status = pFT_Write(ftdih, buf, sizeof(buf), &dw_bytes_written); + if ( (status != FT_OK) || (dw_bytes_written != sizeof(buf) ) ) { + return -1; + } + + return 0; +} + +static int ft2232_set_data_bits_high_byte(unsigned char value, unsigned char direction) +{ + FT_STATUS status; + DWORD dw_bytes_written = 0; + unsigned char buf[3]; + + buf[0] = 0x82; // command "set data bits high byte" + buf[1] = value; // value + buf[2] = direction; // direction + + status = pFT_Write(ftdih, buf, sizeof(buf), &dw_bytes_written); + if ( (status != FT_OK) || ( dw_bytes_written != sizeof(buf) ) ) { + return -1; + } + + return 0; +} + +static int ft2232h_enable_rtck(int enable) +{ + FT_STATUS status; + DWORD dw_bytes_written = 0; + unsigned char buf; + + buf = enable ? 0x96 : 0x97; + + status = pFT_Write(ftdih, &buf, sizeof(buf), &dw_bytes_written); + if ( (status != FT_OK) || ( dw_bytes_written != sizeof(buf) ) ) { + return -1; + } + + return 0; +} + +int drv_FTDI_Detect(jtag_core * jc) +{ + int numDevs,i; + FT_STATUS status; + char SerialNumber[512]; + + if(lib_handle == NULL) + lib_handle = LoadLibrary("ftd2xx.dll"); + + if (lib_handle) + { + pFT_ListDevices = (FT_LISTDEVICES)GetProcAddress(lib_handle, "FT_ListDevices"); + if (!pFT_ListDevices) + return 0; + + status = pFT_ListDevices(&numDevs, NULL, FT_LIST_NUMBER_ONLY); + if (status != FT_OK && !numDevs) + { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_ListDevices : Error %x !\r\n",status); + return 0; + } + + i = 0; + while( i=0 ) + { + if(index < 8) + { + if(state) + low_output |= (0x01< 0) + pFT_Read(ftdih, &ftdi_in_buf, nbRead, &nbRead); + + //Set USB request transfer sizes to 64K + status = pFT_SetUSBParameters(ftdih, 65536, 65535); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetUSBParameters : Error %x !\r\n",status); + goto loadliberror; + } + + //Disable event and error characters + status = pFT_SetChars(ftdih, 0, 0, 0, 0); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetChars : Error %x !\r\n",status); + goto loadliberror; + } + + //Sets the read and write timeouts in milliseconds + status = pFT_SetTimeouts(ftdih, 5000, 5000); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetTimeouts : Error %x !\r\n",status); + goto loadliberror; + } + + //Set the latency timer (default is 16mS) + status = pFT_SetLatencyTimer(ftdih, 2); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetLatencyTimer : Error %x !\r\n",status); + goto loadliberror; + } + + //Reset controller + status = pFT_SetBitMode(ftdih, 0x0, 0x00); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetBitMode : Error %x !\r\n",status); + goto loadliberror; + } + + //Enable MPSSE mode + status = pFT_SetBitMode(ftdih, 0x0, 0x02); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetBitMode : Error %x !\r\n",status); + goto loadliberror; + } + + status = pFT_SetBitMode(ftdih, 0x0b, 2); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetBitMode : Error %x !\r\n",status); + goto loadliberror; + } + + status = pFT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID, + SerialNumber, Description, NULL); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_GetDeviceInfo : Error %x !\r\n",status); + goto loadliberror; + } + + /* + Olimex ARM-USB-OCD-H JTAG signals + + VREF – voltage follower input for the output buffers adjust JTAG signals as per your target board voltage levels + ADBUS0 -> TCK; (out) + ADBUS1 -> TDI; (out) + ADBUS2 -> TDO; (in) + ADBUS3 -> TMS; (out) + ADBUS4 -> 0 to enable JTAG buffers; (GPIOL0) (out) + ADBUS5 -> 0 if target present; (GPIOL1) (in) + ADBUS6 -> TSRST in; (GPIOL2) (in) + ADBUS7 -> RTCK; (in) (GPIOL3) (in) + + ACBUS0 -> TRST; (GPIOH0) + ACBUS1 -> SRST; (GPIOH1) + ACBUS2 -> TRST buffer enable (GPIOH2) + ACBUS3 -> RED LED; (GPIOH3) + */ + + low_direction = 0x00; + for(i=0;i<8;i++) + { + sprintf(tmp_str,"PROBE_FTDI_SET_PIN_DIR_ADBUS%d",i); + if( jtagcore_getEnvVarValue( jc, tmp_str) > 0 ) + { + low_direction |= (0x01< 0 ) + { + low_output |= (0x01< 0 ) + { + low_polarity |= (0x01< 0 ) + { + high_direction |= (0x01< 0 ) + { + high_output |= (0x01< 0 ) + { + high_polarity |= (0x01<>8) & 0xFF; + + status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_Write : Error %x !\r\n",status); + goto loadliberror; + } + +#if 0 // Loopback + nbtosend = 0; + ftdi_out_buf[nbtosend++] = CMD_ENABLE_LOOPBACK; + + status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend); + if (status != FT_OK) { + jtagcore_logs_printf(jc,MSG_ERROR,"pFT_Write : Error %x !\r\n",status); + goto loadliberror; + } +#endif + + if(jtagcore_getEnvVarValue( jc, "PROBE_FTDI_JTAG_ENABLE_RTCK") > 0) + { + ft2232h_enable_rtck(1); + } + + /* Delay... */ + genos_pause(jtagcore_getEnvVarValue( jc, "PROBE_FTDI_JTAG_TRST_DELAY_MS")); + + /* turn red LED on */ + update_gpio_state(led_pin,1); + + /* Release system & jtag reset */ + update_gpio_state(trst_state_pin,0); + update_gpio_state(srst_state_pin,0); + + ft2232_set_data_bits_low_byte( (unsigned char)(low_output ^ low_polarity), low_direction); + ft2232_set_data_bits_high_byte( (unsigned char)(high_output ^ high_polarity), high_direction); + + jtagcore_logs_printf(jc,MSG_INFO_0,"drv_FTDI_Init : Probe Driver loaded successfully...\r\n"); + + return 0; + +loadliberror: + FreeLibrary(lib_handle); + lib_handle = NULL; + return -1; +} + +int drv_FTDI_DeInit(jtag_core * jc) +{ + pFT_Close(ftdih); + FreeLibrary(lib_handle); + lib_handle = NULL; + return 0; +} + +int drv_FTDI_TDOTDI_xfer(jtag_core * jc, unsigned char * str_out, unsigned char * str_in, int size) +{ + int wr_bit_index,rd_bit_index; + int i,payloadsize; + unsigned char bitscnt; + int rounded_size; + DWORD nbRead,nbtosend; + FT_STATUS status; + unsigned char opcode,data; + + rd_bit_index = 0; + wr_bit_index = 0; + + memset(ftdi_out_buf, 0, sizeof(ftdi_out_buf)); + memset(ftdi_in_buf, 0, sizeof(ftdi_in_buf)); + + if (size) + { + // Set the first TMS/DOUT bit + if ( str_out[wr_bit_index] & JTAG_STR_TMS ) + { + if( str_in ) + opcode = ( OP_WR_TMS | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR | OP_RD_TDO ); // with TDO read back + else + opcode = ( OP_WR_TMS | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR ); + + nbtosend = 0; + + ftdi_out_buf[nbtosend++] = opcode; + ftdi_out_buf[nbtosend++] = 0x00; // Size field : 1 Bit + + data = 0x7F; // TMS state set + + if (str_out[wr_bit_index] & JTAG_STR_DOUT) + data |= 0x80; // Bit 7: TDI/DO pin state + + wr_bit_index++; + + ftdi_out_buf[nbtosend++] = data; // Data field + + status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend); + + if ( opcode & OP_RD_TDO ) + { + status = pFT_GetQueueStatus(ftdih, &nbRead); + while (nbRead < 1 && (status == FT_OK)) + { + Sleep(3); + status = pFT_GetQueueStatus(ftdih, &nbRead); + } + + status = pFT_Read(ftdih, &ftdi_in_buf, nbRead, &nbRead); + + // bits are shifted in from MSB to LSB ... + if ( ftdi_in_buf[0] & 0x80 ) + { + str_in[rd_bit_index++] = JTAG_STR_DOUT; + } + else + { + str_in[rd_bit_index++] = 0x00; + } + } + } + + if( wr_bit_index >= size ) + return 0; + + rounded_size = (size - wr_bit_index) & ~(0x7); + if( rounded_size ) + { + // byte(s) buffer transmission/reception + + if( str_in ) + opcode = ( OP_WR_TDI | OP_LSB_FIRST | OP_FEDGE_WR | OP_RD_TDO ); + else + opcode = ( OP_WR_TDI | OP_LSB_FIRST | OP_FEDGE_WR ); + + nbtosend = 0; + + ftdi_out_buf[nbtosend++] = opcode; + ftdi_out_buf[nbtosend++] = ( ( (rounded_size>>3)-1 ) & 0xff ); // (Size-1) Low byte + ftdi_out_buf[nbtosend++] = ( ( (rounded_size>>3)-1 ) >> 8 ); // (Size-1) High byte + + ftdi_out_buf[nbtosend] = 0x00; + + i = 0; + payloadsize = 0; + while (payloadsize < rounded_size) + { + if (str_out[wr_bit_index] & JTAG_STR_DOUT) + { + ftdi_out_buf[nbtosend] |= (0x01 << (i & 0x7)); + } + + i++; + + if (!(i & 0x7)) + { + nbtosend++; + ftdi_out_buf[nbtosend] = 0x00; + } + + payloadsize++; + wr_bit_index++; + } + + status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend); + + if (str_in) + { + do + { + Sleep(3); + status = pFT_GetQueueStatus(ftdih, &nbRead); + } while (nbRead < (unsigned long)(rounded_size >> 3) && (status == FT_OK )); + + status = pFT_Read(ftdih, &ftdi_in_buf, nbRead, &nbRead); + + for (i = 0; i < rounded_size; i++) + { + if (ftdi_in_buf[i >> 3] & (0x01 << (i & 7))) + { + str_in[rd_bit_index++] = JTAG_STR_DOUT; + } + else + { + str_in[rd_bit_index++] = 0x00; + } + } + } + } + + // Send the remaining bits... + while( wr_bit_index < size ) + { + if( str_in ) + opcode = ( OP_WR_TDI | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR | OP_RD_TDO ); //bit mode with TDO read back + else + opcode = ( OP_WR_TDI | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR ); //bit mode + + nbtosend = 0; + + bitscnt = (size - wr_bit_index); + if( bitscnt > 8 ) + { + bitscnt = 8; + } + + ftdi_out_buf[nbtosend++] = opcode; + ftdi_out_buf[nbtosend++] = (bitscnt - 1) & 7; // Size field + ftdi_out_buf[nbtosend] = 0x00; + + i = 0; + while( i < bitscnt ) + { + if (str_out[wr_bit_index++] & JTAG_STR_DOUT) + ftdi_out_buf[nbtosend] |= 0x01 << i; // Data field + + i++; + } + nbtosend++; + + status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend); + + if ( opcode & OP_RD_TDO ) + { + do + { + Sleep(3); + status = pFT_GetQueueStatus(ftdih, &nbRead); + } while ( ( nbRead < 1 ) && ( status == FT_OK ) ); + + status = pFT_Read(ftdih, &ftdi_in_buf, nbRead, &nbRead); + + // bits are shifted in from MSB to LSB ... + i = 0; + while( i < bitscnt ) + { + if ( ftdi_in_buf[0] & (0x01 << ( (8 - bitscnt) + i ) ) ) + { + str_in[rd_bit_index++] = JTAG_STR_DOUT; + } + else + { + str_in[rd_bit_index++] = 0x00; + } + i++; + } + } + } + } + + return 0; +} + +int drv_FTDI_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size) +{ + int i; + int wr_bit_index; + DWORD nbtosend; + FT_STATUS status; + unsigned char bitscnt; + unsigned char opcode; + + status = FT_OK; + + memset(ftdi_out_buf, 0, sizeof(ftdi_out_buf)); + memset(ftdi_in_buf, 0, sizeof(ftdi_in_buf)); + + wr_bit_index = 0; + while( wr_bit_index < size ) + { + opcode = ( OP_WR_TMS | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR ); + + nbtosend = 0; + + bitscnt = (size - wr_bit_index); + if( bitscnt > 7 ) + { + bitscnt = 7; + } + + ftdi_out_buf[nbtosend++] = opcode; + ftdi_out_buf[nbtosend++] = (bitscnt - 1); // Size field + ftdi_out_buf[nbtosend] = 0x00; + + i = 0; + while( i < bitscnt ) + { + if (str_out[wr_bit_index++] & JTAG_STR_TMS) + ftdi_out_buf[nbtosend] |= 0x01 << i; // Data field + + i++; + } + nbtosend++; + + status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend); + } + + if (status != FT_OK) + { + return -1; + } + else + { + return 0; + } +} + +int drv_FTDI_libGetDrv(jtag_core * jc,int sub_drv,unsigned int infotype,void * returnvalue) +{ + + drv_ptr drv_funcs = + { + (DRV_DETECT) drv_FTDI_Detect, + (DRV_INIT) drv_FTDI_Init, + (DRV_DEINIT) drv_FTDI_DeInit, + (DRV_TXTMS) drv_FTDI_TMS_xfer, + (DRV_TXRXDATA) drv_FTDI_TDOTDI_xfer, + (DRV_GETMODULEINFOS) drv_FTDI_libGetDrv + }; + + return GetDrvInfo( + jc, + infotype, + returnvalue, + subdrv_list[sub_drv].drv_id, + subdrv_list[sub_drv].drv_desc, + &drv_funcs + ); +} + +#endif \ No newline at end of file diff --git a/lib_jtag_core/src/drivers/ftdi_jtag/ftdi_jtag_drv.h b/lib_jtag_core/src/drivers/ftdi_jtag/ftdi_jtag_drv.h new file mode 100644 index 0000000..3f5c09c --- /dev/null +++ b/lib_jtag_core/src/drivers/ftdi_jtag/ftdi_jtag_drv.h @@ -0,0 +1,26 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file ftdi_jtag_drv.h + * @brief FTDI based probes driver entry point definition + * @author Jean-François DEL NERO + */ + +int drv_FTDI_libGetDrv(jtag_core * jc,int sub_drv, unsigned int infotype,void * returnvalue); diff --git a/lib_jtag_core/src/drivers/jlink_jtag/jlink_jtag_drv.c b/lib_jtag_core/src/drivers/jlink_jtag/jlink_jtag_drv.c new file mode 100644 index 0000000..3cff8b8 --- /dev/null +++ b/lib_jtag_core/src/drivers/jlink_jtag/jlink_jtag_drv.c @@ -0,0 +1,389 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file jlink_jtag_drv.c + * @brief JLINK based probes driver + * @author Jean-François DEL NERO + */ + +#include +#include +#include "../drv_loader.h" +#include "../../jtag_core_internal.h" +#include "../../jtag_core.h" + +#include "../../bsdl_parser/bsdl_loader.h" + +#include "../../dbg_logs.h" + +#if defined(WIN32) +// Compiling on Windows +#include +#elif defined(__linux__) +#include +#include +#else +#error "Unsupported OS (only available on Windows or Linux)" +#endif + +typedef struct _drv_desc +{ + char *drv_id; + char *drv_desc; + int id; +}drv_desc; + +#define PROBE_JLINK_ARM 0 + +const static drv_desc subdrv_list[]= +{ + {"JLINK_ARM","USB JLINK ARM",PROBE_JLINK_ARM} +}; + +unsigned char jlink_out_tms_buf[64 * 1024]; +unsigned char jlink_out_tdi_buf[64 * 1024]; +unsigned char jlink_in_buf[64 * 1024]; + +#if defined(WIN32) + +#if defined(_WIN64) + #define MODULE_NAME "JLink_x64.dll" +#else + #define MODULE_NAME "JLinkARM.dll" +#endif + +typedef const char* (WINAPIV * JL_OPENEX)(const char* pfLog, void*); +typedef int (WINAPIV * JL_JTAG_STORERAW)(const unsigned char* pTDI, const unsigned char* pTMS, unsigned int NumBits); +typedef int (WINAPIV * JL_JTAG_STOREGETRAW)(const unsigned char* pTDI, unsigned char* pTDO, const unsigned char* pTMS, unsigned int NumBits); +typedef void (WINAPIV * JL_JTAG_SYNCBITS)(void); +typedef void (WINAPIV * JL_SETSPEED)(unsigned int Speed); +typedef void (WINAPIV * JL_SETRESETDELAY)(int ms); +typedef void (WINAPIV * JL_RESETPULLSRESET)(unsigned char OnOff); +typedef void (WINAPIV * JL_RESET)(void); +typedef int (WINAPIV * JL_HASERROR)(void); +typedef void (WINAPIV * JL_CLOSE)(void); + +#else + +#define MODULE_NAME "./libjlinkarm.so" + +#if defined(__i386__) + #define __cdecl __attribut__((cdecl)) +#else // __x86_64__ and others... + #define __cdecl +#endif + +typedef void* HMODULE; + +typedef const char* (__cdecl * JL_OPENEX)(const char* pfLog, void*); +typedef int (__cdecl * JL_JTAG_STORERAW)(const unsigned char* pTDI, const unsigned char* pTMS, unsigned int NumBits); +typedef int (__cdecl * JL_JTAG_STOREGETRAW)(const unsigned char* pTDI, unsigned char* pTDO, const unsigned char* pTMS, unsigned int NumBits); +typedef void (__cdecl * JL_JTAG_SYNCBITS)(void); +typedef void (__cdecl * JL_SETSPEED)(unsigned int Speed); +typedef void (__cdecl * JL_SETRESETDELAY)(int ms); +typedef void (__cdecl * JL_RESETPULLSRESET)(unsigned char OnOff); +typedef void (__cdecl * JL_RESET)(void); +typedef int (__cdecl * JL_HASERROR)(void); +typedef void (__cdecl * JL_CLOSE)(void); + +void* GetProcAddress(HMODULE handle, const char* name) +{ + if(!handle || !name) + return NULL; + + dlerror(); + + return dlsym(handle, name); +} + +bool FreeLibrary(HMODULE handle) +{ + dlerror(); + if(0 != dlclose(handle)) { + return false; + } + + return true; +} + +HMODULE LoadLibrary(const char* path) +{ + dlerror(); + return dlopen(path, RTLD_NOW); +} + +#endif + +static HMODULE lib_handle = 0; + +JL_OPENEX pJLINKARM_OpenEx; +JL_JTAG_STORERAW pJLINKARM_JTAG_StoreRaw; +JL_JTAG_STOREGETRAW pJLINKARM_JTAG_StoreGetRaw; +JL_JTAG_SYNCBITS pJLINKARM_JTAG_SyncBits; +JL_SETSPEED pJLINKARM_SetSpeed; +JL_SETRESETDELAY pJLINKARM_SetResetDelay; +JL_RESETPULLSRESET pJLINKARM_ResetPullsRESET; +JL_RESET pJLINKARM_Reset; +JL_HASERROR pJLINKARM_HasError; +JL_CLOSE pJLINKARM_Close; + +int drv_JLINK_Detect(jtag_core * jc) +{ + if(lib_handle == NULL) { + lib_handle = LoadLibrary(MODULE_NAME); + } + + if (lib_handle) + { + jtagcore_logs_printf(jc,MSG_INFO_1,"drv_JLINK_Detect : %s JLink library found !\r\n",MODULE_NAME); + + return 1; + } + else + { + jtagcore_logs_printf(jc,MSG_INFO_1,"drv_JLINK_Detect : %s JLink library not found !\r\n",MODULE_NAME); + } + + return 0; +} + +static void * drv_JLINK_GetDrvFunc(jtag_core * jc, HMODULE libh, char * function_name) +{ + void * function_ptr; + + function_ptr = (void *)GetProcAddress(libh, function_name); + if (!function_ptr) + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_JLINK_GetDrvFunc : Can't get %s function !\r\n",function_name); + + return NULL; + } + + return function_ptr; +} + +int drv_JLINK_Init(jtag_core * jc, int sub_drv, char * params) +{ + const char* sError; + + if(lib_handle == NULL) { + lib_handle = LoadLibrary(MODULE_NAME); + } + + if (lib_handle) + { + pJLINKARM_OpenEx = (JL_OPENEX)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_OpenEx"); + if (!pJLINKARM_OpenEx) + goto loadliberror; + + pJLINKARM_JTAG_StoreRaw = (JL_JTAG_STORERAW)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_JTAG_StoreRaw"); + if (!pJLINKARM_JTAG_StoreRaw) + goto loadliberror; + + pJLINKARM_JTAG_StoreGetRaw = (JL_JTAG_STOREGETRAW)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_JTAG_StoreGetRaw"); + if (!pJLINKARM_JTAG_StoreGetRaw) + goto loadliberror; + + pJLINKARM_JTAG_SyncBits = (JL_JTAG_SYNCBITS)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_JTAG_SyncBits"); + if (!pJLINKARM_JTAG_SyncBits) + goto loadliberror; + + pJLINKARM_SetSpeed = (JL_SETSPEED)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_SetSpeed"); + if (!pJLINKARM_SetSpeed) + goto loadliberror; + + pJLINKARM_SetResetDelay = (JL_SETRESETDELAY)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_SetResetDelay"); + if (!pJLINKARM_SetResetDelay) + goto loadliberror; + + pJLINKARM_ResetPullsRESET = (JL_RESETPULLSRESET)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_ResetPullsRESET"); + if (!pJLINKARM_ResetPullsRESET) + goto loadliberror; + + pJLINKARM_Reset = (JL_RESET)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_Reset"); + if (!pJLINKARM_Reset) + goto loadliberror; + + pJLINKARM_HasError = (JL_HASERROR)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_HasError"); + if (!pJLINKARM_HasError) + goto loadliberror; + + pJLINKARM_Close = (JL_CLOSE)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_Close"); + if (!pJLINKARM_Close) + goto loadliberror; + } + else + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_JLINK_Init : Can't load JLinkARM.dll !\r\n"); + return -1; + } + + sError = pJLINKARM_OpenEx(NULL, 0); + if (sError) { + jtagcore_logs_printf(jc,MSG_ERROR,"pJLINKARM_OpenEx : Error 0x%x !\r\n",sError); + return -1; + } + + pJLINKARM_SetSpeed(1000); // 1 Mhz + + jtagcore_logs_printf(jc,MSG_INFO_0,"drv_JLINK_Init : Probe Driver loaded successfully...\r\n"); + + return 0; + +loadliberror: + jtagcore_logs_printf(jc,MSG_ERROR,"drv_JLINK_Init : Something wrong happened ! JLink probe support not enabled.\r\n"); + + FreeLibrary(lib_handle); + + lib_handle = NULL; + return -1; +} + +int drv_JLINK_DeInit(jtag_core * jc) +{ + pJLINKARM_Close(); + FreeLibrary(lib_handle); + lib_handle = NULL; + return 0; +} + +int drv_JLINK_TDOTDI_xfer(jtag_core * jc, unsigned char * str_out, unsigned char * str_in, int size) +{ + int i; + int bitoffset; + + memset(jlink_out_tms_buf, 0, sizeof(jlink_out_tms_buf)); + memset(jlink_out_tdi_buf, 0, sizeof(jlink_out_tdi_buf)); + + if (!str_in) + { + if (size) + { + i = 0; + bitoffset = 0; + while (i < size) + { + if (str_out[i] & JTAG_STR_TMS) + jlink_out_tms_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7)); + + if (str_out[i] & JTAG_STR_DOUT) + jlink_out_tdi_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7)); + + bitoffset++; + i++; + } + + pJLINKARM_JTAG_StoreRaw(jlink_out_tdi_buf, jlink_out_tms_buf, bitoffset); + pJLINKARM_JTAG_SyncBits(); + } + } + else + { + if (size) + { + memset(jlink_in_buf, 0, sizeof(jlink_in_buf)); + + i = 0; + bitoffset = 0; + while (i < size) + { + if (str_out[i] & JTAG_STR_TMS) + jlink_out_tms_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7)); + + if (str_out[i] & JTAG_STR_DOUT) + jlink_out_tdi_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7)); + + bitoffset++; + i++; + } + + pJLINKARM_JTAG_StoreGetRaw(jlink_out_tdi_buf, jlink_in_buf, jlink_out_tms_buf, bitoffset); + pJLINKARM_JTAG_SyncBits(); + + i = 0; + while (i < size) + { + if (jlink_in_buf[i >> 3] & (0x01 << (i & 7))) + { + str_in[i] = JTAG_STR_DOUT; + } + else + { + str_in[i] = 0x00; + } + i++; + } + + } + } + + return 0; +} + +int drv_JLINK_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size) +{ + int bitoffset,i; + + memset(jlink_out_tms_buf, 0, sizeof(jlink_out_tms_buf)); + memset(jlink_out_tdi_buf, 0, sizeof(jlink_out_tdi_buf)); + + if (size) + { + i = 0; + bitoffset = 0; + while (i < size) + { + if (str_out[i] & JTAG_STR_TMS) + jlink_out_tms_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7)); + + bitoffset++; + i++; + } + + pJLINKARM_JTAG_StoreRaw(jlink_out_tdi_buf, jlink_out_tms_buf, bitoffset); + pJLINKARM_JTAG_SyncBits(); + + } + + return 0; +} + +int drv_JLINK_libGetDrv(jtag_core * jc,int sub_drv,unsigned int infotype,void * returnvalue) +{ + drv_ptr drv_funcs = + { + (DRV_DETECT) drv_JLINK_Detect, + (DRV_INIT) drv_JLINK_Init, + (DRV_DEINIT) drv_JLINK_DeInit, + (DRV_TXTMS) drv_JLINK_TMS_xfer, + (DRV_TXRXDATA) drv_JLINK_TDOTDI_xfer, + (DRV_GETMODULEINFOS) drv_JLINK_libGetDrv + }; + + return GetDrvInfo( + jc, + infotype, + returnvalue, + subdrv_list[sub_drv].drv_id, + subdrv_list[sub_drv].drv_desc, + &drv_funcs + ); +} + diff --git a/lib_jtag_core/src/drivers/jlink_jtag/jlink_jtag_drv.h b/lib_jtag_core/src/drivers/jlink_jtag/jlink_jtag_drv.h new file mode 100644 index 0000000..15bb40b --- /dev/null +++ b/lib_jtag_core/src/drivers/jlink_jtag/jlink_jtag_drv.h @@ -0,0 +1,26 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file jlink_jtag_drv.h + * @brief JLINK based probes driver entry point definition + * @author Jean-François DEL NERO + */ + +int drv_JLINK_libGetDrv(jtag_core * jc,int sub_drv, unsigned int infotype,void * returnvalue); diff --git a/lib_jtag_core/src/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.c b/lib_jtag_core/src/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.c new file mode 100644 index 0000000..9c67588 --- /dev/null +++ b/lib_jtag_core/src/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.c @@ -0,0 +1,452 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file linux_gpio_jtag_drv.c + * @brief jtag linux gpio probes driver + * @author Jean-François DEL NERO + */ + +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +#include +#endif + +#include "../drv_loader.h" +#include "../../jtag_core_internal.h" +#include "../../jtag_core.h" + +#include "../../bsdl_parser/bsdl_loader.h" + +#include "../../os_interface/os_interface.h" + +#include "../../dbg_logs.h" + +char linux_gpio_base[512]; + +#define IGNORE_PORT 0 +#define READ_PORT 1 + +typedef struct +{ + const char* name; + int gpio_num; + int dir; + int state; + int old_state; + int negate_polarity; + int handle; +}io_defs; + +#define TMS_INDEX 0 +#define TDO_INDEX 1 +#define TDI_INDEX 2 +#define TCK_INDEX 3 + +io_defs gpio_var_names[]= +{ + {(const char*)"PROBE_LINUXGPIO_TMS_PIN",-1,1,0,-1,0,-1}, + {(const char*)"PROBE_LINUXGPIO_TDO_PIN",-1,0,0,-1,0,-1}, + {(const char*)"PROBE_LINUXGPIO_TDI_PIN",-1,1,0,-1,0,-1}, + {(const char*)"PROBE_LINUXGPIO_TCK_PIN",-1,1,0,-1,0,-1}, + {(const char*)NULL,-1,-1,0,-1,-1} +}; + +#if defined(__linux__) + +static int putp(int tdi, int tms, int rp) +{ + int tdo = -1; + int ret; + char tmp_str[512]; + char rd_value; + + tmp_str[0] = '0'; + tmp_str[1] = '\n'; + tmp_str[2] = 0; + + rd_value = 0; + + if (rp == READ_PORT) + { + + rd_value = 0; + lseek(gpio_var_names[TDO_INDEX].handle, 0, SEEK_SET); + ret = read(gpio_var_names[TDO_INDEX].handle,&rd_value,1); + if(ret < 1) + goto wr_error; + + if(rd_value >= '0' && rd_value <='1') + { + gpio_var_names[TDO_INDEX].old_state = gpio_var_names[TDO_INDEX].state; + tdo = (rd_value - '0') ^ (gpio_var_names[TDO_INDEX].negate_polarity&1); + gpio_var_names[TDO_INDEX].state = tdo; + } + } + + if( gpio_var_names[TMS_INDEX].old_state != (tms&1)) + { + tmp_str[0] = '0' + ((tms&1) ^ (gpio_var_names[TMS_INDEX].negate_polarity&1)); + + ret = write(gpio_var_names[TMS_INDEX].handle,tmp_str,2); + if(ret < 2) + goto wr_error; + + gpio_var_names[TMS_INDEX].old_state = (tms&1); + } + + if( gpio_var_names[TDI_INDEX].old_state != (tdi&1)) + { + tmp_str[0] = '0' + ((tdi&1) ^ (gpio_var_names[TDI_INDEX].negate_polarity&1)); + ret = write(gpio_var_names[TDI_INDEX].handle,tmp_str,2); + if(ret < 2) + goto wr_error; + + gpio_var_names[TDI_INDEX].old_state = (tdi&1); + } + + tmp_str[0] = '0' + (gpio_var_names[TCK_INDEX].negate_polarity&1); + ret = write(gpio_var_names[TCK_INDEX].handle,tmp_str,2); + if(ret < 2) + goto wr_error; + + gpio_var_names[TCK_INDEX].old_state = 0; + + tmp_str[0] = '0' + (1 ^ (gpio_var_names[TCK_INDEX].negate_polarity&1)); + ret = write(gpio_var_names[TCK_INDEX].handle,tmp_str,2); + if(ret < 2) + goto wr_error; + + gpio_var_names[TCK_INDEX].old_state = 1; + + tmp_str[0] = '0' + (gpio_var_names[TCK_INDEX].negate_polarity&1); + ret = write(gpio_var_names[TCK_INDEX].handle,tmp_str,2); + if(ret < 2) + goto wr_error; + + gpio_var_names[TCK_INDEX].old_state = 0; + + return tdo; + +wr_error: + return 0; + +} +#endif + +int drv_LinuxGPIO_Detect(jtag_core * jc) +{ +#if defined(__linux__) + char tmp_str[1024]; + FILE * f; + + if( jtagcore_getEnvVarValue( jc, "PROBE_GPIO_LINUX_ENABLE") > 0) + { + jtagcore_getEnvVar( jc, "PROBE_GPIO_LINUX_BASE_FOLDER", (char*)&linux_gpio_base); + + strncpy(tmp_str, linux_gpio_base, sizeof(tmp_str) - 1); + genos_strndstcat(tmp_str,"/export",sizeof(tmp_str)); + tmp_str[sizeof(tmp_str) - 1] = '\0'; + + f = fopen(tmp_str,"rb"); + if(f) + { + fclose(f); + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LinuxGPIO_Detect : JTAG GPIO interface enabled\r\n",tmp_str); + return 3; + } + else + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LinuxGPIO_Detect : Can't open %s !\r\n",tmp_str); + } + } +#endif + return 0; +} + +#if defined(__linux__) + +static int exportGPIO(char * path_base,int pin) +{ + char tmp_str[512]; + FILE * f; + + strcpy(tmp_str,path_base); + strcat(tmp_str,"/export"); + + f = fopen(tmp_str,"w"); + if(!f) + { + return JTAG_CORE_ACCESS_ERROR; + } + + fprintf(f,"%d\n", pin); + fclose(f); + + return JTAG_CORE_NO_ERROR; +} + +static int setdirGPIO(char * path_base,int pin,int dir) +{ + char tmp_str[1024]; + char tmp_str2[64]; + FILE * f; + + strncpy(tmp_str,path_base,sizeof(tmp_str)-1); + snprintf(tmp_str2,sizeof(tmp_str2)-1,"/gpio%d/direction",pin); + genos_strndstcat(tmp_str,tmp_str2,sizeof(tmp_str)); + tmp_str[sizeof(tmp_str) - 1] = '\0'; + + f = fopen(tmp_str,"w"); + if(!f) + { + return JTAG_CORE_ACCESS_ERROR; + } + + if(dir) + fprintf(f,"out\n"); + else + fprintf(f,"in\n"); + + fclose(f); + + return JTAG_CORE_NO_ERROR; +} + +#endif + +int drv_LinuxGPIO_Init(jtag_core * jc, int sub_drv,char * params) +{ + int probe_detected; + + probe_detected = 0; + + if( jtagcore_getEnvVarValue( jc, "PROBE_LINUXGPIO_ENABLE") <= 0) + { + return JTAG_CORE_NO_PROBE; + } + +#if defined(__linux__) + int i; + char tmp_str[1024]; + + jtagcore_getEnvVar( jc, "PROBE_LINUXGPIO_BASE_FOLDER", (char*)&linux_gpio_base); + + i = 0; + while(gpio_var_names[i].name) + { + gpio_var_names[i].gpio_num = jtagcore_getEnvVarValue( jc, (char*)gpio_var_names[i].name); + + strncpy(tmp_str,(char*)gpio_var_names[i].name,sizeof(tmp_str) - 1); + tmp_str[sizeof(tmp_str) - 1] = '\0'; + + genos_strndstcat(tmp_str,"_INVERT_POLARITY",sizeof(tmp_str)); + tmp_str[sizeof(tmp_str) - 1] = '\0'; + + gpio_var_names[i].negate_polarity = jtagcore_getEnvVarValue( jc, (char*)tmp_str); + + if( exportGPIO(linux_gpio_base, gpio_var_names[i].gpio_num) != JTAG_CORE_NO_ERROR ) + break; + + if( setdirGPIO(linux_gpio_base, gpio_var_names[i].gpio_num, gpio_var_names[i].dir) != JTAG_CORE_NO_ERROR ) + break; + + i++; + } + + if(!gpio_var_names[i].name) + { + probe_detected = 1; + + for(i=0;i<4;i++) + { + snprintf(tmp_str,sizeof(tmp_str),"%s/gpio%d/value",linux_gpio_base,gpio_var_names[i].gpio_num); + + if(gpio_var_names[i].handle != -1) + close(gpio_var_names[i].handle); + + if(gpio_var_names[i].dir) + gpio_var_names[i].handle = open(tmp_str, O_WRONLY); + else + gpio_var_names[i].handle = open(tmp_str, O_RDONLY); + + if(gpio_var_names[i].handle < 0) + break; + } + + if( i == 4 ) + { + // init gpio + putp(0, 0, IGNORE_PORT); + putp(0, 0, IGNORE_PORT); + } + else + { + probe_detected = 0; + } + } +#endif + + if(probe_detected) + { + jtagcore_logs_printf(jc,MSG_INFO_0,"drv_LinuxGPIO_Init : Probe Driver loaded successfully...\r\n"); + return 0; + } + else + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LinuxGPIO_Init : No probe found !\r\n"); + return -1; + } +} + +int drv_LinuxGPIO_DeInit(jtag_core * jc) +{ + return 0; +} + +int drv_LinuxGPIO_TDOTDI_xfer(jtag_core * jc, unsigned char * str_out, unsigned char * str_in, int size) +{ +#if defined(__linux__) + int i; + + i = 0; + + if (!str_in) + { + while (i < size) + { + + if (str_out[i] & JTAG_STR_TMS) + { + gpio_var_names[TMS_INDEX].state = 1; + } + else + { + gpio_var_names[TMS_INDEX].state = 0; + } + + if (str_out[i] & JTAG_STR_DOUT) + { + gpio_var_names[TDI_INDEX].state = 1; + } + else + { + gpio_var_names[TDI_INDEX].state = 0; + } + + putp(gpio_var_names[TDI_INDEX].state, gpio_var_names[TMS_INDEX].state, IGNORE_PORT); + + i++; + } + } + else + { + while (i < size) + { + if (str_out[i] & JTAG_STR_DOUT) + { + gpio_var_names[TDI_INDEX].state = 1; + } + else + { + gpio_var_names[TDI_INDEX].state = 0; + } + + if (str_out[i] & JTAG_STR_TMS) + { + gpio_var_names[TMS_INDEX].state = 1; + } + else + { + gpio_var_names[TMS_INDEX].state = 0; + } + + str_in[i] = putp(gpio_var_names[TDI_INDEX].state, gpio_var_names[TMS_INDEX].state, READ_PORT); + + i++; + } + + } + + return 0; + +#endif + return -1; +} + +int drv_LinuxGPIO_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size) +{ +#if defined(__linux__) + int i; + + gpio_var_names[TDI_INDEX].state = 0; + + i = 0; + while (i < size) + { + if (str_out[i] & JTAG_STR_TMS) + { + gpio_var_names[TMS_INDEX].state = 1; + } + else + { + gpio_var_names[TMS_INDEX].state = 0; + } + + putp(gpio_var_names[TDI_INDEX].state, gpio_var_names[TMS_INDEX].state, IGNORE_PORT); + + i++; + } + + return 0; + +#endif + + return -1; + +} + +int drv_LinuxGPIO_libGetDrv(jtag_core * jc, int sub_drv, unsigned int infotype,void * returnvalue) +{ + + drv_ptr drv_funcs = + { + (DRV_DETECT) drv_LinuxGPIO_Detect, + (DRV_INIT) drv_LinuxGPIO_Init, + (DRV_DEINIT) drv_LinuxGPIO_DeInit, + (DRV_TXTMS) drv_LinuxGPIO_TMS_xfer, + (DRV_TXRXDATA) drv_LinuxGPIO_TDOTDI_xfer, + (DRV_GETMODULEINFOS) drv_LinuxGPIO_libGetDrv + }; + + return GetDrvInfo( + jc, + infotype, + returnvalue, + "LINUX_GPIO", + "GENERIC LINUX GPIO JTAG", + &drv_funcs + ); +} diff --git a/lib_jtag_core/src/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.h b/lib_jtag_core/src/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.h new file mode 100644 index 0000000..81c6dc1 --- /dev/null +++ b/lib_jtag_core/src/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.h @@ -0,0 +1,26 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file linux_gpio_jtag_drv.h + * @brief jtag linux gpio probes driver + * @author Jean-François DEL NERO + */ + +int drv_LinuxGPIO_libGetDrv(jtag_core * jc,int sub_drv,unsigned int infotype,void * returnvalue); diff --git a/lib_jtag_core/src/drivers/lpt_jtag/lpt_jtag_drv.c b/lib_jtag_core/src/drivers/lpt_jtag/lpt_jtag_drv.c new file mode 100644 index 0000000..d6b4489 --- /dev/null +++ b/lib_jtag_core/src/drivers/lpt_jtag/lpt_jtag_drv.c @@ -0,0 +1,426 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file lpt_jtag_drv.c + * @brief parallel port probes driver + * @author Jean-François DEL NERO + */ + +#ifndef _WIN64 + +#include +#include + +#if defined(WIN32) +#include +#endif + +#include "../drv_loader.h" +#include "../../jtag_core_internal.h" +#include "../../jtag_core.h" + +#include "../../bsdl_parser/bsdl_loader.h" + +#include "../../dbg_logs.h" + +#if defined(WIN32) + +#include + +HANDLE h; + +#endif + +#define LPT1 0x3bc +#define LPT2 0x378 +#define LPT3 0x278 + +#define IGNORE_PORT 0 +#define READ_PORT 1 + +unsigned short lpt_address; + + +int sub_probe_id; + +typedef struct _drv_desc +{ + char *drv_id; + char *drv_desc; + int id; +}drv_desc; + +#define PROBE_INSIGHT_IJC 0 +#define PROBE_ALTERA_BYTEBLASTER 1 +#define PROBE_MACRAIGOR_WIGGLER 2 + +const static drv_desc subdrv_list[]= +{ + {"LPT_INSIGHT_JTAG","LPT Memec IJC-4",PROBE_INSIGHT_IJC}, + {"LPT_ALTERA_BYTEBLASTER_JTAG","LPT Altera ByteBlaster",PROBE_ALTERA_BYTEBLASTER}, + {"LPT_MACRAIGOR_WIGGLERJTAG","LPT Macgraigor Wiggler",PROBE_MACRAIGOR_WIGGLER} +}; + +void out_io_port( unsigned short port, unsigned char data ) +{ +#if defined(WIN32) + _outp( port, data ); +#endif +} + +unsigned char in_io_port( unsigned short port ) +{ +#if defined(WIN32) + return _inp( port ); +#else + return 0x00; +#endif +} + + +int test_port(void) +{ + // search for valid parallel port + out_io_port(LPT1, 0x55); + if ((int)in_io_port(LPT1) == 0x55) + { + return LPT1; + } + + out_io_port(LPT2, 0x55); + if ((int)in_io_port(LPT2) == 0x55) + { + return LPT2; + } + + out_io_port(LPT3, 0x55); + if ((int)in_io_port(LPT3) == 0x55) + { + return LPT3; + } + + return(0); // return zero if none found +} + +int putp(int tdi, int tms, int rp) +{ + int tdo = -1; + int lpt_data; + + switch (sub_probe_id) + { + case PROBE_INSIGHT_IJC: + // Insight/Xilinx : + // D4 : TDO DRV LOW (AL) + // D3 : OE (AL) + // D1 : TCK (AH) + // D2 : TMS (AH) + // D0 : TDI (AH) (To device) + // OnLine :TDO (AH) (From device) + + lpt_data = 0x10; //Output to TDO off / Outputs enabled + if (tms == 1) lpt_data |= 0x04; + if (tdi == 1) lpt_data |= 0x01; + + out_io_port(lpt_address, (unsigned char)lpt_data); // TCK low + + lpt_data |= 0x02; + out_io_port(lpt_address, (unsigned char)lpt_data); // TCK high + + if (rp == READ_PORT) + { + tdo = ((int)in_io_port((unsigned short)(lpt_address + 1)) & 0x10) >> 4; // get TDO data + } + + break; + + case PROBE_ALTERA_BYTEBLASTER: + // Byteblaster : + // AutoF : OE (AH) + // D0 : TCK (AH) + // D1 : TMS (AH) + // D6 : TDI (AH) (To device) + // BUSY : TDO (AL) (From device) + // D4 : Loopback test out (AH) + // Ack : Loopback test in (AH) + + lpt_data = 0x00; + + if (tms == 1) lpt_data |= 0x02; + if (tdi == 1) lpt_data |= 0x40; + + out_io_port(lpt_address, (unsigned char)lpt_data); // TCK low + + lpt_data |= 0x01; + out_io_port(lpt_address, (unsigned char)lpt_data); // TCK high + + if (rp == READ_PORT) + { + tdo = (((int)in_io_port((unsigned short)(lpt_address + 1)) & 0x80) >> 7) ^ 1; // get TDO data + } + + break; + + case PROBE_MACRAIGOR_WIGGLER: + // Macraigor Wiggler : + // AutoF : OE (AH) + // D0 : RST (AH) + // D1 : TMS (AH) + // D2 : TCK (AH) + // D3 : TDI (AH) (To device) + // D4 : TRST (AH) + // D7 : "PC VCC" + // BUSY : TDO (AL) (From device) + // D6 : Loopback test out (AH) + // Error : Loopback test in (AH) + + lpt_data = 0x10 | 0x80; //Set PC VCC & TRST to 1 + + if (tms == 1) lpt_data |= 0x02; + if (tdi == 1) lpt_data |= 0x08; + + out_io_port(lpt_address, (unsigned char)lpt_data); // TCK low + + lpt_data |= 0x04; + out_io_port(lpt_address, (unsigned char)lpt_data); // TCK high + + if (rp == READ_PORT) + { + tdo = (((int)in_io_port((unsigned short)(lpt_address + 1)) & 0x80) >> 7) ^ 1; // get TDO data + } + + break; + + default: + return 0; + break; + } + + return tdo; +} + +int drv_LPT_Detect(jtag_core * jc) +{ + +#if defined(WIN32) + h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : Can't load giveio !\r\n"); + return 0; + } + + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Detect : giveio enabled !\r\n"); +#endif + + lpt_address = test_port(); // find a valid parallel port address + if (!lpt_address) + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : No LPT port found !\r\n"); + return 0; + } + + return 3; +} + + +int drv_LPT_Init(jtag_core * jc, int sub_drv,char * params) +{ + int probe_detected; + +#if defined(WIN32) + h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : Can't load giveio !\r\n"); + return -1; + } +#endif + + lpt_address = test_port(); // find a valid parallel port address + if (!lpt_address) + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : No LPT port found !\r\n"); + return -2; + } + + sub_probe_id = subdrv_list[sub_drv].id; + + switch(sub_probe_id) + { + case PROBE_ALTERA_BYTEBLASTER: + probe_detected = 1; + + /* + // Loop back test + out_io_port(lpt_address, 0x00); + if( in_io_port(lpt_address + 1) & 0x40) + { + probe_detected = 0; + } + + out_io_port(lpt_address, 0x10); + if( !(in_io_port(lpt_address + 1) & 0x40)) + { + probe_detected = 0; + } + */ + + // Enable outputs. + if(probe_detected) + out_io_port((unsigned short)(lpt_address + 0x02), 0x02); + break; + + default: + probe_detected = 1; + break; + } + + if(probe_detected) + { + jtagcore_logs_printf(jc,MSG_INFO_0,"drv_LPT_Init : Probe Driver loaded successfully...\r\n"); + return 0; + } + else + { + jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : No probe found !\r\n"); + return -1; + } +} + +int drv_LPT_DeInit(jtag_core * jc) +{ +#if defined(WIN32) + CloseHandle(h); +#endif + return 0; +} + +int drv_LPT_TDOTDI_xfer(jtag_core * jc, unsigned char * str_out, unsigned char * str_in, int size) +{ + int i; + int tms, tdi; + + + if (size) + { + if (str_out[0] & JTAG_STR_TMS) + { + tms = 1; + } + else + { + tms = 0; + } + } + + i = 0; + if (!str_in) + { + while (i < size) + { + + if (str_out[i] & JTAG_STR_DOUT) + { + tdi = 1; + } + else + { + tdi = 0; + } + + putp(tdi, tms, IGNORE_PORT); + + i++; + } + } + else + { + while (i < size) + { + + if (str_out[i] & JTAG_STR_DOUT) + { + tdi = 1; + } + else + { + tdi = 0; + } + + str_in[i] = putp(tdi, tms, READ_PORT); + + i++; + } + } + return 0; +} + +int drv_LPT_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size) +{ + int i; + int tms, tdi; + + tdi = 0; + i = 0; + + while (i < size) + { + if (str_out[i] & JTAG_STR_TMS) + { + tms = 1; + } + else + { + tms = 0; + } + + putp(tdi, tms, IGNORE_PORT); + + i++; + } + + return 0; +} + +int drv_LPT_libGetDrv(jtag_core * jc, int sub_drv, unsigned int infotype,void * returnvalue) +{ + + drv_ptr drv_funcs = + { + (DRV_DETECT) drv_LPT_Detect, + (DRV_INIT) drv_LPT_Init, + (DRV_DEINIT) drv_LPT_DeInit, + (DRV_TXTMS) drv_LPT_TMS_xfer, + (DRV_TXRXDATA) drv_LPT_TDOTDI_xfer, + (DRV_GETMODULEINFOS) drv_LPT_libGetDrv + }; + + return GetDrvInfo( + jc, + infotype, + returnvalue, + subdrv_list[sub_drv].drv_id, + subdrv_list[sub_drv].drv_desc, + &drv_funcs + ); +} + +#endif \ No newline at end of file diff --git a/lib_jtag_core/src/drivers/lpt_jtag/lpt_jtag_drv.h b/lib_jtag_core/src/drivers/lpt_jtag/lpt_jtag_drv.h new file mode 100644 index 0000000..32781cd --- /dev/null +++ b/lib_jtag_core/src/drivers/lpt_jtag/lpt_jtag_drv.h @@ -0,0 +1,26 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file lpt_jtag_drv.h + * @brief parallel port probes driver entry point definition + * @author Jean-François DEL NERO + */ + +int drv_LPT_libGetDrv(jtag_core * jc,int sub_drv,unsigned int infotype,void * returnvalue); diff --git a/lib_jtag_core/src/jtag_core.c b/lib_jtag_core/src/jtag_core.c new file mode 100644 index 0000000..82bdab4 --- /dev/null +++ b/lib_jtag_core/src/jtag_core.c @@ -0,0 +1,1112 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file jtag_core.c + * @brief Main jtag core library functions + * @author Jean-François DEL NERO + */ + +#include +#include +#include +#include + +#include "drivers/drv_loader.h" +#include "jtag_core_internal.h" +#include "jtag_core.h" +#include "version.h" + +#include "script/env.h" + +#include "bsdl_parser/bsdl_loader.h" +#include "bsdl_parser/bsdl_strings.h" + +#include "drivers/drivers_list.h" + +#include "config_script.h" + +jtag_core * jtagcore_init() +{ + jtag_core * jc; + script_ctx * sctx; + + jc = (jtag_core *)malloc(sizeof(jtag_core)); + if ( jc ) + { + memset( jc, 0, sizeof(jtag_core) ); + + jc->envvar = (void*)initEnv(NULL, NULL); + + jtagcore_setEnvVar( jc, "LIBVERSION", "v"LIB_JTAG_CORE_VERSION); + + sctx = jtagcore_initScript(jc); + + jtagcore_execScriptRam( sctx, config_script, config_script_len ); + + jtagcore_execScriptFile( sctx, "config.script" ); + + if(jtagcore_getEnvVar( jc, "LOG_MESSAGES_FILTER_LEVEL", NULL)) + { + jtagcore_set_logs_level( jc, jtagcore_getEnvVarValue( jc, "LOG_MESSAGES_FILTER_LEVEL") ); + } + + if(jtagcore_getEnvVar( jc, "LOG_MESSAGES_FILE_OUTPUT", NULL)) + { + jtagcore_set_logs_file( jc, jtagcore_getEnvVar( jc, "LOG_MESSAGES_FILE_OUTPUT", NULL) ); + } + + jtagcore_deinitScript(sctx); + } + + return jc; +} + +int jtagcore_resetchain(jtag_core * jc) +{ + int i; + unsigned char buf_out[16]; + + if (jc) + { + // Jtag Sync / Reset + for (i = 0; i < 6; i++) + { + buf_out[i] = JTAG_STR_TMS; + } + + jc->io_functions.drv_TX_TMS(jc, (unsigned char *)&buf_out, i); + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_scan_and_init_chain(jtag_core * jc) +{ + unsigned char buf_in[512], buf_out[512]; + int i,j; + int device_found_1, device_found_2, device_found; + + device_found = 0; + if (jc ) + { + for(i = 0;inb_of_devices_in_chain;i++) + { + if (jc->devices_list[i].bsdl) + { + unload_bsdlfile(jc,jc->devices_list[i].bsdl); + jc->devices_list[i].bsdl = 0; + } + } + + jc->nb_of_devices_in_chain = 0; + jc->IR_filled = 0; + + if (!jc->io_functions.drv_TX_TMS) + return JTAG_CORE_NO_PROBE; + + jtagcore_resetchain(jc); + + // Go to shift-IR + buf_out[0] = 0x00; + buf_out[1] = JTAG_STR_TMS; + buf_out[2] = JTAG_STR_TMS; + buf_out[3] = 0x00; + buf_out[4] = 0x00; + jc->io_functions.drv_TX_TMS(jc, (unsigned char *)&buf_out, 5); + + // Measure the total IR lenght + + //Flush the IR regs + for (i = 0; i < sizeof(buf_out); i++) + { + buf_out[i] = 0; + } + + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, (unsigned char *)&buf_in, sizeof(buf_out)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, (unsigned char *)&buf_in, sizeof(buf_out)); + + for (i = 0; i < sizeof(buf_out); i++) + { + buf_out[i] = JTAG_STR_DOUT; + } + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, (unsigned char *)&buf_in, sizeof(buf_out)); + + i = 0; + while( i < sizeof(buf_in) && !buf_in[i]) + { + i++; + } + + jc->total_IR_lenght = i; + + // Send the bypass instruction to all devices + for (i = 0; i < sizeof(buf_out); i++) + { + buf_out[i] = JTAG_STR_DOUT; + } + + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_out)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_out)); + buf_out[0] = JTAG_STR_DOUT | JTAG_STR_TMS; + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1); + + // Go to the Shift-DR + buf_out[0] = JTAG_STR_TMS; + buf_out[1] = JTAG_STR_TMS; + buf_out[2] = 0x00; + buf_out[3] = 0x00; + jc->io_functions.drv_TX_TMS(jc, (unsigned char *)&buf_out, 4); + + + // Now fill the full chain to count the number of devices + for (i = 0; i < sizeof(buf_out); i++) + { + buf_out[i] = 0x00; + } + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_out)); + + for (i = 0; i < sizeof(buf_out); i++) + { + buf_out[i] = JTAG_STR_DOUT; + } + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, (unsigned char *)&buf_in, sizeof(buf_out)); + + device_found_1 = 0; + i = 0; + while ((device_found_1 < sizeof(buf_out)) && (!buf_in[device_found_1])) + { + device_found_1++; + } + + // Fill the full chain with the opposite state to count again the number of devices + for (i = 0; i < sizeof(buf_out); i++) + { + buf_out[i] = JTAG_STR_DOUT; + } + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_out)); + + for (i = 0; i < sizeof(buf_out); i++) + { + buf_out[i] = 0x00; + } + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, (unsigned char *)&buf_in, sizeof(buf_out)); + + device_found_2 = 0; + i = 0; + while ((device_found_2 < sizeof(buf_out)) && (buf_in[device_found_2])) + { + device_found_2++; + } + + if (device_found_1 == device_found_2) + { + if(device_found_1!=sizeof(buf_out)) + { + // Detection valid ! + device_found = device_found_1; + + jc->nb_of_devices_in_chain = device_found; + } + } + + if (device_found) + { + // Jtag Sync / Reset + jtagcore_resetchain(jc); + + // Go to shift-DR + buf_out[0] = 0x00; + buf_out[1] = JTAG_STR_TMS; + buf_out[2] = 0x00; + buf_out[3] = 0x00; + jc->io_functions.drv_TX_TMS(jc, (unsigned char *)&buf_out, 4); + + memset(buf_out, 0x00, sizeof(buf_out)); + + // Read all the devices ID. + for (i = 0; i < device_found && i < MAX_NB_JTAG_DEVICE; i++) + { + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, (unsigned char *)&buf_in, 32); + jc->devices_list[i].devices_id = 0x00000000; + for (j = 0; j < 32; j++) + { + if (buf_in[j]) + jc->devices_list[i].devices_id |= (0x00000001 << j); + } + } + } + + jtagcore_resetchain(jc); + + // Idle... + buf_out[0] = 0x00; + buf_out[1] = 0x00; + buf_out[2] = 0x00; + buf_out[3] = 0x00; + buf_out[4] = 0x00; + buf_out[5] = 0x00; + jc->io_functions.drv_TX_TMS(jc, (unsigned char *)&buf_out, 6); + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_BAD_PARAMETER; + +} + +int jtagcore_get_number_of_devices(jtag_core * jc) +{ + if (jc) + { + return jc->nb_of_devices_in_chain; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +unsigned long jtagcore_get_dev_id(jtag_core * jc,int device) +{ + if (jc && device >= 0) + { + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE) + { + return jc->devices_list[device].devices_id; + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_loadbsdlfile(jtag_core * jc, char * path, int device) +{ + jtag_bsdl * bsdl_file; + int i; + + if ( (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) || device == -1) + { + bsdl_file = load_bsdlfile(jc,path); + if (bsdl_file) + { + if (device == -1) + { + device = 0; + i = 0; + while (i < jc->nb_of_devices_in_chain) + { + if (jc->devices_list[i].bsdl) + { + unload_bsdlfile(jc,jc->devices_list[i].bsdl); + jc->devices_list[i].bsdl = 0; + } + + i++; + } + + jc->nb_of_devices_in_chain = 1; + + jc->devices_list[0].bsdl = bsdl_file; + + } + else + { + if (jc->devices_list[device].bsdl) + { + unload_bsdlfile(jc,jc->devices_list[device].bsdl); + } + + jc->devices_list[device].bsdl = bsdl_file; + } + + if (jc->devices_list[device].in_boundary_scan) + free(jc->devices_list[device].in_boundary_scan); + + if (jc->devices_list[device].out_boundary_scan) + free(jc->devices_list[device].out_boundary_scan); + + jc->devices_list[device].in_boundary_scan = malloc(bsdl_file->number_of_chainbits); + if (jc->devices_list[device].in_boundary_scan) + memset(jc->devices_list[device].in_boundary_scan, 0, bsdl_file->number_of_chainbits); + + jc->devices_list[device].out_boundary_scan = malloc(bsdl_file->number_of_chainbits); + if (jc->devices_list[device].out_boundary_scan) + { + memset(jc->devices_list[device].out_boundary_scan, 0, bsdl_file->number_of_chainbits); + for (i = 0; i < bsdl_file->number_of_chainbits; i++) + { + if(bsdl_file->chain_list[i].safe_state == STATE_HIGH) + jc->devices_list[device].out_boundary_scan[i] = 0x01; + else + jc->devices_list[device].out_boundary_scan[i] = 0x00; + + } + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_MEM_ERROR; + + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +unsigned long jtagcore_get_bsdl_id(jtag_core * jc, char * path, unsigned long * mask) +{ + jtag_bsdl * bsdl_file; + unsigned long chip_id; + + bsdl_file = load_bsdlfile(jc,path); + if (bsdl_file) + { + chip_id = bsdl_file->chip_id; + if( mask ) + { + *mask = bsdl_file->chip_id_mask; + } + unload_bsdlfile(jc,bsdl_file); + return chip_id; + } + + return 0; +} + +int jtagcore_get_dev_name(jtag_core * jc, int device, char * devname, char * bsdlpath) +{ + jtag_bsdl * bsdl_file; + + if ( device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 ) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if(devname) + { + strcpy(devname,bsdl_file->entity_name); + } + + if(bsdlpath) + { + strcpy(bsdlpath,bsdl_file->src_filename); + } + + return JTAG_CORE_NO_ERROR; + } + + if(devname) + { + devname[0] = '\0'; + } + + if(bsdlpath) + { + bsdlpath[0] = '\0'; + } + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_get_number_of_pins(jtag_core * jc, int device) +{ + jtag_bsdl * bsdl_file; + + if ( device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 ) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + return bsdl_file->number_of_pins; + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_get_pin_properties(jtag_core * jc, int device,int pin,char * pinname,int maxsize,int * type) +{ + jtag_bsdl * bsdl_file; + int type_code; + + if (device >= jc->nb_of_devices_in_chain || + device >= MAX_NB_JTAG_DEVICE || + device < 0 || + pin < 0 ) + { + return JTAG_CORE_BAD_PARAMETER; + } + + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins ) + { + type_code = 0x00; + + if (pinname) + { + strncpy(pinname, bsdl_file->pins_list[pin].pinname, maxsize - 1); + pinname[maxsize - 1] = '\0'; + } + + if (type) + { + if (bsdl_file->pins_list[pin].ctrl_bit_number != -1) + type_code |= JTAG_CORE_PIN_IS_TRISTATES; + + if (bsdl_file->pins_list[pin].out_bit_number != -1) + type_code |= JTAG_CORE_PIN_IS_OUTPUT; + + if (bsdl_file->pins_list[pin].in_bit_number != -1) + type_code |= JTAG_CORE_PIN_IS_INPUT; + + *type = type_code; + } + + return JTAG_CORE_NO_ERROR; + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_get_pin_state(jtag_core * jc, int device, int pin, int type) +{ + jtag_bsdl * bsdl_file; + int bit_number, ret; + int disable_state; + + ret = JTAG_CORE_BAD_PARAMETER; + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && pin >= 0 ) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins) + { + switch (type) + { + case JTAG_CORE_OUTPUT: + bit_number = bsdl_file->pins_list[pin].out_bit_number; + + if (bit_number != -1) + { + if (jc->devices_list[device].scan_mode == JTAG_CORE_EXTEST_SCANMODE) + { + if (jc->devices_list[device].out_boundary_scan[bit_number]) + ret = 0x01; + else + ret = 0x00; + } + else + { + if (jc->devices_list[device].in_boundary_scan[bit_number]) + ret = 0x01; + else + ret = 0x00; + } + } + + break; + + case JTAG_CORE_OE: + bit_number = bsdl_file->pins_list[pin].ctrl_bit_number; + + if (bit_number != -1) + { + disable_state = bsdl_file->chain_list[bsdl_file->pins_list[pin].out_bit_number].control_disable_state; + if (jc->devices_list[device].scan_mode == JTAG_CORE_EXTEST_SCANMODE) + { + if (disable_state == STATE_HIGH) + { + if (jc->devices_list[device].out_boundary_scan[bit_number]) + ret = 0x00; + else + ret = 0x01; + } + else + { + if (jc->devices_list[device].out_boundary_scan[bit_number]) + ret = 0x01; + else + ret = 0x00; + } + } + else + { + if (disable_state) + { + if (jc->devices_list[device].in_boundary_scan[bit_number]) + ret = 0x00; + else + ret = 0x01; + } + else + { + if (jc->devices_list[device].in_boundary_scan[bit_number]) + ret = 0x01; + else + ret = 0x00; + } + } + } + break; + + case JTAG_CORE_INPUT: + bit_number = bsdl_file->pins_list[pin].in_bit_number; + + if (bit_number != -1) + { + if (jc->devices_list[device].in_boundary_scan[bit_number]) + ret = 0x01; + else + ret = 0x00; + } + break; + + } + } + } + } + return ret; +} + +int jtagcore_set_pin_state(jtag_core * jc, int device, int pin, int type,int state) +{ + jtag_bsdl * bsdl_file; + int bit_number,ret; + int disable_state; + + ret = JTAG_CORE_BAD_PARAMETER; + + if ( device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && pin >= 0 ) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + if (pin < bsdl_file->number_of_pins) + { + switch (type) + { + case JTAG_CORE_OUTPUT: + bit_number = bsdl_file->pins_list[pin].out_bit_number; + + if (bit_number != -1) + { + if (state) + jc->devices_list[device].out_boundary_scan[bit_number] = 0x01; + else + jc->devices_list[device].out_boundary_scan[bit_number] = 0x00; + + ret = 0; + } + + break; + + case JTAG_CORE_OE: + bit_number = bsdl_file->pins_list[pin].ctrl_bit_number; + + if (bit_number != -1) + { + disable_state = bsdl_file->chain_list[bsdl_file->pins_list[pin].out_bit_number].control_disable_state; + + if (disable_state == STATE_HIGH) + { + if (state) + jc->devices_list[device].out_boundary_scan[bit_number] = 0x00; + else + jc->devices_list[device].out_boundary_scan[bit_number] = 0x01; + } + else + { + if (state) + jc->devices_list[device].out_boundary_scan[bit_number] = 0x01; + else + jc->devices_list[device].out_boundary_scan[bit_number] = 0x00; + } + ret = 0; + } + break; + + } + } + } + } + return ret; + +} + +int jtagcore_get_pin_id(jtag_core * jc, int device, char * pinname) +{ + jtag_bsdl * bsdl_file; + int pin; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && pinname) + { + if (jc->devices_list[device].bsdl) + { + bsdl_file = jc->devices_list[device].bsdl; + + for ( pin = 0; pin < bsdl_file->number_of_pins; pin++) + { + if(bsdl_file->pins_list[pin].pinname) + { + if(!strcmp(bsdl_file->pins_list[pin].pinname, pinname)) + { + return pin; + } + } + } + + return JTAG_CORE_NOT_FOUND; + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + + +int jtagcore_set_scan_mode(jtag_core * jc, int device, int scan_mode) +{ + int ret; + + ret = JTAG_CORE_BAD_PARAMETER; + + if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) + { + switch (scan_mode) + { + case JTAG_CORE_SAMPLE_SCANMODE: + jc->devices_list[device].scan_mode = JTAG_CORE_SAMPLE_SCANMODE; + jc->IR_filled = 0; + + ret = JTAG_CORE_NO_ERROR; + break; + case JTAG_CORE_EXTEST_SCANMODE: + jc->devices_list[device].scan_mode = JTAG_CORE_EXTEST_SCANMODE; + jc->IR_filled = 0; + + ret = JTAG_CORE_NO_ERROR; + break; + default: + break; + } + } + + return ret; +} + +int jtagcore_push_and_pop_chain(jtag_core * jc, int mode) +{ + unsigned char buf_out[512]; + unsigned char buf_in[512]; + int d,i,irlen; + int bit,first_bit,jtag_chain_check_needed; + jtag_bsdl * bsdl; + + jtag_chain_check_needed = 0; + + if (jc) + { + if (jc->nb_of_devices_in_chain && jc->io_functions.drv_TX_TMS) + { + //Idle State -> Go to shift-DR + buf_out[0] = 0x00; + buf_out[1] = JTAG_STR_TMS; + buf_out[2] = 0x00; + buf_out[3] = 0x00; + jc->io_functions.drv_TX_TMS(jc, (unsigned char *)&buf_out, 4); + for (d = 0; d < jc->nb_of_devices_in_chain; d++) + { + bsdl = jc->devices_list[d].bsdl; + if (bsdl && jc->devices_list[d].out_boundary_scan && jc->devices_list[d].in_boundary_scan) + { + if (mode == JTAG_CORE_WRITE_READ) + { + if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ? + { + jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, jc->devices_list[d].in_boundary_scan, bsdl->number_of_chainbits - 1); + buf_out[0] = jc->devices_list[d].out_boundary_scan[bsdl->number_of_chainbits - 1] | JTAG_STR_TMS; + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, &jc->devices_list[d].in_boundary_scan[bsdl->number_of_chainbits - 1], 1); + } + else + { + jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, jc->devices_list[d].in_boundary_scan, bsdl->number_of_chainbits); + } + + // Check the incomming data + if(bsdl->number_of_chainbits) + { + first_bit = jc->devices_list[d].in_boundary_scan[0]; + bit = 0; + while( (bit < bsdl->number_of_chainbits) && (first_bit == jc->devices_list[d].in_boundary_scan[bit]) ) + { + bit++; + } + + if( bit == bsdl->number_of_chainbits) + { + // All bits have the same value. + // Program a jtag chain check + jtag_chain_check_needed |= 1; + jc->IR_filled = 0; + } + } + } + else + { + // Write only mode - Ignore incoming chain. + if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ? + { + jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, 0, bsdl->number_of_chainbits - 1); + buf_out[0] = jc->devices_list[d].out_boundary_scan[bsdl->number_of_chainbits - 1] | JTAG_STR_TMS; + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1); + } + else + { + jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, 0, bsdl->number_of_chainbits); + } + } + + } + else + { + // Bypassed + if (d == (jc->nb_of_devices_in_chain-1)) // Last device in chain ? + buf_out[0] = JTAG_STR_TMS; + else + buf_out[0] = 0x00; + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1); + } + } + + if (!jc->IR_filled) + { + jc->IR_filled = 1; + // Exit1-DR -> Go to shift-IR + buf_out[0] = JTAG_STR_TMS; + buf_out[1] = JTAG_STR_TMS; + buf_out[2] = JTAG_STR_TMS; + buf_out[3] = 0x00; + buf_out[4] = 0x00; + jc->io_functions.drv_TX_TMS(jc, (unsigned char *)&buf_out, 5); + + + if(jtag_chain_check_needed) + { + // Zero test + for(i=0;i<512;i++) + { + buf_out[i] = 0; + } + + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + memset(buf_in,1,sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, buf_in, sizeof(buf_in)); + + i = 0; + while(iio_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + memset(buf_in,0,sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, buf_in, sizeof(buf_in)); + + i = 0; + while(iio_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_in)); + memset(buf_in,0,sizeof(buf_in)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, buf_in, sizeof(buf_in)); + + i = 1; + bit = buf_in[0]; + while( i < sizeof(buf_in) && buf_in[i] != bit) + { + bit = buf_in[i]; + i++; + } + + if( i != sizeof(buf_in) ) + { + goto jtag_error; + } + + // All tests passed - reprogram the IR register. + } + + for (d = 0; d < jc->nb_of_devices_in_chain; d++) + { + bsdl = jc->devices_list[d].bsdl; + if ( bsdl ) + { + switch ( jc->devices_list[d].scan_mode ) + { + case JTAG_CORE_SAMPLE_SCANMODE: + for (i = 0; i < bsdl->number_of_bits_per_instruction; i++) + { + buf_out[(bsdl->number_of_bits_per_instruction - 1) - i] = bsdl->SAMPLE_Instruction[i] - '0'; + } + break; + case JTAG_CORE_EXTEST_SCANMODE: + for (i = 0; i < bsdl->number_of_bits_per_instruction; i++) + { + buf_out[(bsdl->number_of_bits_per_instruction - 1) - i] = bsdl->EXTEST_Instruction[i] - '0'; + } + break; + } + + + if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ? + { + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, bsdl->number_of_bits_per_instruction - 1); + buf_out[0] = buf_out[bsdl->number_of_bits_per_instruction - 1] | JTAG_STR_TMS; + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1); + } + else + { + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, bsdl->number_of_bits_per_instruction); + } + } + else + { + // Bypass + irlen = 3; + switch ( jc->nb_of_devices_in_chain ) + { + case 1: + irlen = jc->total_IR_lenght; + break; + case 2: + if (d) + { + if ( jc->devices_list[0].bsdl ) + { + bsdl = jc->devices_list[0].bsdl; + irlen = jc->total_IR_lenght - bsdl->number_of_bits_per_instruction; + } + } + else + { + if ( jc->devices_list[1].bsdl ) + { + bsdl = jc->devices_list[1].bsdl; + irlen = jc->total_IR_lenght - bsdl->number_of_bits_per_instruction; + } + } + break; + default: + irlen = 3; + break; + } + + memset(buf_out, JTAG_STR_DOUT, sizeof(buf_out)); + + if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ? + { + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, irlen - 1); + buf_out[0] = JTAG_STR_DOUT | JTAG_STR_TMS; + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1); + } + else + { + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, irlen); + } + } + } + } + + // Return To idle + buf_out[0] = JTAG_STR_TMS; + buf_out[1] = 0x00; + buf_out[2] = 0x00; + buf_out[3] = 0x00; + buf_out[4] = 0x00; + buf_out[5] = 0x00; + buf_out[6] = 0x00; + buf_out[7] = 0x00; + jc->io_functions.drv_TX_TMS(jc, (unsigned char *)&buf_out, 6); + + return JTAG_CORE_NO_ERROR; + } + } + + return JTAG_CORE_BAD_PARAMETER; + +jtag_error: + // General error, bypass all devices. + + jc->IR_filled = 0; + + // Send the bypass instruction to all devices + for (i = 0; i < sizeof(buf_out); i++) + { + buf_out[i] = JTAG_STR_DOUT; + } + + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_out)); + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, sizeof(buf_out)); + buf_out[0] = JTAG_STR_DOUT | JTAG_STR_TMS; + jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1); + + return JTAG_CORE_IO_ERROR; +} + +int jtagcore_get_number_of_probes_drv(jtag_core * jc) +{ + int i; + + if (jc) + { + i = 0; + while (staticdrvs[i].getinfosfunc != (const DRV_GETMODULEINFOS)-1) + { + i++; + } + + return i; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_get_number_of_probes(jtag_core * jc, int probe_driver_id) +{ + int totalprobe; + + if (jc) + { + totalprobe = 0; + if( probe_driver_id < jtagcore_get_number_of_probes_drv(jc) && probe_driver_id >= 0 ) + { + if( staticdrvs[probe_driver_id].getinfosfunc(jc,staticdrvs[ probe_driver_id ].sub_drv_id, GET_DRV_DETECT, &totalprobe) == JTAG_CORE_NO_ERROR ) + { + return totalprobe; + } + } + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_get_probe_name(jtag_core * jc, int probe_id, char * name) +{ + if ( ( probe_id >> 8 ) < jtagcore_get_number_of_probes_drv(jc) && probe_id >= 0 ) + { + staticdrvs[ probe_id>>8 ].getinfosfunc(jc, probe_id & 0xFF, GET_DRV_DESCRIPTION, name); + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_select_and_open_probe(jtag_core * jc, int probe_id) +{ + if ( ( probe_id >> 8 ) < jtagcore_get_number_of_probes_drv(jc) && probe_id >= 0 ) + { + return jtagcore_loaddriver(jc, probe_id, NULL); + } + + return JTAG_CORE_BAD_PARAMETER; +} + +int jtagcore_setEnvVar( jtag_core * jc, char * varname, char * varvalue ) +{ + if( setEnvVarDat( jc->envvar, varname, varvalue ) >= 0 ) + { + return JTAG_CORE_NO_ERROR; + } + else + { + return JTAG_CORE_MEM_ERROR; + } +} + +char * jtagcore_getEnvVar( jtag_core * jc, char * varname, char * varvalue) +{ + return getEnvVarDat( jc->envvar, varname, varvalue, 512 ); +} + +char * jtagcore_getEnvVarIndex( jtag_core * jc, int index, char * varvalue) +{ + return getEnvVarDatIndex( jc->envvar, index, varvalue, 512 ); +} + +int jtagcore_getEnvVarValue( jtag_core * jc, char * varname) +{ + return getEnvVarValue( jc->envvar, varname); +} + +void jtagcore_deinit(jtag_core * jc) +{ + if( jc ) + { + deinitEnv( (envvar_entry *)jc->envvar ); + free( jc ); + } +} diff --git a/lib_jtag_core/src/jtag_core.h b/lib_jtag_core/src/jtag_core.h new file mode 100644 index 0000000..a61bd69 --- /dev/null +++ b/lib_jtag_core/src/jtag_core.h @@ -0,0 +1,342 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file jtag_core.h + * @brief Main jtag core library header + * @author Jean-François DEL NERO + */ + +#ifndef _jtag_core_ +typedef void jtag_core; +#define _jtag_core_ +#endif + +#ifndef _script_ctx_ +typedef void script_ctx; +#define _script_ctx_ +#endif + +#ifndef _jtag_emu_ +typedef void jtag_emu; +#define _jtag_emu_ +#endif + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Functions Error / return codes + +#define JTAG_CORE_NO_ERROR 0 +#define JTAG_CORE_BAD_PARAMETER -1 +#define JTAG_CORE_ACCESS_ERROR -2 +#define JTAG_CORE_IO_ERROR -3 +#define JTAG_CORE_MEM_ERROR -4 +#define JTAG_CORE_NO_PROBE -5 +#define JTAG_CORE_NOT_FOUND -6 +#define JTAG_CORE_CMD_NOT_FOUND -7 +#define JTAG_CORE_INTERNAL_ERROR -8 +#define JTAG_CORE_BAD_CMD -9 + +#define JTAG_CORE_I2C_BUS_NOTFREE -10 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Lib init functions + +// jtagcore_init : Library alloc and init +jtag_core * jtagcore_init(); + +// jtagcore_init : Library dealloc and deinit +void jtagcore_deinit(jtag_core * jc); + +#ifndef _JTAGCORE_PRINT_FUNC_ +typedef void (*JTAGCORE_PRINT_FUNC)(jtag_core * jc, const char * string); +#define _JTAGCORE_PRINT_FUNC_ +#endif + +int jtagcore_set_logs_callback(jtag_core * jc, JTAGCORE_PRINT_FUNC jtag_core_print); +int jtagcore_set_logs_level(jtag_core * jc,int level); +int jtagcore_get_logs_level(jtag_core * jc); +int jtagcore_set_logs_file(jtag_core * jc,char * path); +char * jtagcore_get_logs_file(jtag_core * jc); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Probe driver selection/initialisation functions + +// jtagcore_get_number_of_probes_drv : Return the "number of supported probes" + +int jtagcore_get_number_of_probes_drv(jtag_core * jc); +int jtagcore_get_number_of_probes(jtag_core * jc, int probe_driver_id); + +#define PROBE_ID(drv_id,probe_index) ( (drv_id<<8) | probe_index ) + +// jtagcore_get_probe_name : Return the probe name (probe_id should be between 0 and "number of supported probes" - 1) + +int jtagcore_get_probe_name(jtag_core * jc, int probe_id,char * name); + +// jtagcore_select_and_open_probe : Try to init the probe (probe_id should be between 0 and "number of supported probes" - 1) + +int jtagcore_select_and_open_probe(jtag_core * jc, int probe_id); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// JTAG Chain init functions + +// jtagcore_scan_and_init_chain : Scan and init the chain (devices detection) + +int jtagcore_scan_and_init_chain(jtag_core * jc); + +// jtagcore_get_number_of_devices : return "the number of devices into the chain" found by jtagcore_scan_and_init_chain + +int jtagcore_get_number_of_devices(jtag_core * jc); + +// jtagcore_get_dev_id : Return the device chip ID +// "device" should be between 0 and "the number of devices into the chain" - 1 + +unsigned long jtagcore_get_dev_id(jtag_core * jc, int device); + +// jtagcore_loadbsdlfile : Load/attach a bsdl file to a device into the chain +// "device" should be between 0 and "the number of devices into the chain" - 1 + +int jtagcore_loadbsdlfile(jtag_core * jc, char * path, int device); + +// jtagcore_get_dev_name : Get the currently loaded bsdl name & path +// "device" should be between 0 and "the number of devices into the chain" - 1 +int jtagcore_get_dev_name(jtag_core * jc, int device, char * devname, char * bsdlpath); + +// jtagcore_get_bsdl_id : Return the chip id present into a bsdl file + +unsigned long jtagcore_get_bsdl_id(jtag_core * jc, char * path, unsigned long * mask); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Pins/IO access functions + +// jtagcore_get_number_of_pins : Return the number of pins of a device. +// "device" should be between 0 and "the number of devices into the chain" - 1 +// and a bsdl must be attached to this device + +int jtagcore_get_number_of_pins(jtag_core * jc,int device); + +// jtagcore_get_pin_properties : Return the pin properties +// "device" should be between 0 and "the number of devices into the chain" - 1 +// and a bsdl must be attached to this device +// "pin" should be between 0 and "number of pins of a device" - 1 +// "type" return is a mask between JTAG_CORE_PIN_IS_INPUT / JTAG_CORE_PIN_IS_OUTPUT / JTAG_CORE_PIN_IS_TRISTATES states + +int jtagcore_get_pin_properties(jtag_core * jc, int device, int pin, char * pinname, int maxsize, int * type); + +#define JTAG_CORE_PIN_IS_INPUT 0x01 +#define JTAG_CORE_PIN_IS_OUTPUT 0x02 +#define JTAG_CORE_PIN_IS_TRISTATES 0x04 + +// jtagcore_get_pin_id : Find and return a pin id (if exist) from the pin name +// "device" should be between 0 and "the number of devices into the chain" - 1 + +int jtagcore_get_pin_id(jtag_core * jc, int device, char * pinname); + +// jtagcore_get_pin_state : Return the current pin state +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 +// "type" should be set to JTAG_CORE_INPUT or JTAG_CORE_OUTPUT or JTAG_CORE_OE + +int jtagcore_get_pin_state(jtag_core * jc, int device, int pin, int type); + +// jtagcore_set_pin_state : Set the pin state +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 +// "type" should be set to JTAG_CORE_INPUT or JTAG_CORE_OUTPUT or JTAG_CORE_OE + +int jtagcore_set_pin_state(jtag_core * jc, int device, int pin, int type, int state); + +#define JTAG_CORE_INPUT 0x01 +#define JTAG_CORE_OUTPUT 0x02 +#define JTAG_CORE_OE 0x04 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Scan chain functions + +// jtagcore_set_scan_mode : Set the scan mode for a particular device +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "scan_mode" should be set to JTAG_CORE_SAMPLE_SCANMODE (observation only) or JTAG_CORE_EXTEST_SCANMODE (full pin control) +int jtagcore_set_scan_mode(jtag_core * jc, int device, int scan_mode); + +// JTAG Scan mode +#define JTAG_CORE_SAMPLE_SCANMODE 0x00 +#define JTAG_CORE_EXTEST_SCANMODE 0x01 + +// jtagcore_push_and_pop_chain : Do a JTAG chain transaction. +// "mode" should be set to JTAG_CORE_WRITE_READ (Push/write and pop/read the chain) or JTAG_CORE_WRITE_ONLY (only Push/write the chain) +int jtagcore_push_and_pop_chain(jtag_core * jc, int mode); + +#define JTAG_CORE_WRITE_READ 0x00 +#define JTAG_CORE_WRITE_ONLY 0x01 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// I2C over JTAG API functions + +// jtagcore_i2c_set_scl_pin : Select the SCL pin +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 + +int jtagcore_i2c_set_scl_pin(jtag_core * jc, int device, int pin); + +// jtagcore_i2c_set_sda_pin : Select the SDA pin +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 + +int jtagcore_i2c_set_sda_pin(jtag_core * jc, int device, int pin); + +// jtagcore_i2c_write_read : Do an I2C transfert +// "address" : I2C address (8 bits aligned) +// "address10bits" != 0 if this is an 10bits address +// "wr_size" write size +// "rd_size" read size +int jtagcore_i2c_write_read(jtag_core * jc, int address, int address10bits,int wr_size,unsigned char * wr_buffer,int rd_size,unsigned char * rd_buffer); + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SPI over JTAG API functions + +// jtagcore_spi_set_cs_pin : Select the CS pin +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 + +int jtagcore_spi_set_cs_pin(jtag_core * jc, int device, int pin, int polarity); + +// jtagcore_spi_set_clk_pin : Select the CLK pin +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 + +int jtagcore_spi_set_clk_pin(jtag_core * jc, int device, int pin, int polarity); + +// jtagcore_spi_set_miso_pin : Select the MISO pin +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 + +int jtagcore_spi_set_miso_pin(jtag_core * jc, int device, int pin, int sample_clk_phase); + +// jtagcore_spi_set_mosi_pin : Select the MOSI pin +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 + +int jtagcore_spi_set_mosi_pin(jtag_core * jc, int device, int pin, int sample_clk_phase); + +// jtagcore_spi_write_read : Do a SPI transfert +// "wr_size" is the transaction size + +int jtagcore_spi_write_read(jtag_core * jc, int wr_size,unsigned char * wr_buffer,unsigned char * rd_buffer, int flags); + +// jtagcore_spi_set_bitorder : Select MSB/LSB first mode + +int jtagcore_spi_set_bitorder(jtag_core * jc, int lsb_first); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// MDIO over JTAG API functions + +// jtagcore_mdio_set_mdio_pin : Select the MDIO pin +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 + +int jtagcore_mdio_set_mdio_pin(jtag_core * jc, int device, int pin); + +// jtagcore_mdio_set_mdc_pin : Select the MDC pin +// "device" should be between 0 and "the number of devices into the chain" - 1 +// "pin" should be between 0 and "number of pins of a device" - 1 + +int jtagcore_mdio_set_mdc_pin(jtag_core * jc, int device, int pin); + +// jtagcore_mdio_read : Read to an MDIO register +// phy_adr : Phylayer address +// reg_adr : Register address + +int jtagcore_mdio_read(jtag_core * jc, int phy_adr, int reg_adr); + +// jtagcore_mdio_write : Write to an MDIO register +// phy_adr : Phylayer address +// reg_adr : Register address +// data : data value to write + +int jtagcore_mdio_write(jtag_core * jc, int phy_adr, int reg_adr, int data); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Parallel Memory over JTAG API functions + +#define JTAG_CORE_RAM_CS_CTRL 0x00 +#define JTAG_CORE_RAM_WR_CTRL 0x01 +#define JTAG_CORE_RAM_RD_CTRL 0x02 +#define JTAG_CORE_RAM_RW_CTRL 0x03 + +int jtagcore_memory_clear_pins(jtag_core * jc); +int jtagcore_memory_set_address_pin(jtag_core * jc, int address_bit, int device, int pin); +int jtagcore_memory_set_data_pin(jtag_core * jc, int data_bit, int device, int pin); +int jtagcore_memory_set_ctrl_pin(jtag_core * jc, int ctrl, int polarity, int device, int pin); +unsigned long jtagcore_memory_read(jtag_core * jc, int mem_adr); +int jtagcore_memory_write(jtag_core * jc, int mem_adr, unsigned long data); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Internal variables functions + +int jtagcore_setEnvVar( jtag_core * jc, char * varname, char * varvalue ); +char * jtagcore_getEnvVar( jtag_core * jc, char * varname, char * varvalue); +int jtagcore_getEnvVarValue( jtag_core * jc, char * varname); +char * jtagcore_getEnvVarIndex( jtag_core * jc, int index, char * varvalue); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Script execution functions + +#define DEFAULT_BUFLEN 1024 + +// Output message types/levels +enum MSGTYPE +{ + MSG_DEBUG = 0, + MSG_INFO_0, + MSG_INFO_1, + MSG_WARNING, + MSG_ERROR, + MSG_NONE +}; + +#ifndef _jtag_script_printf_func_ +typedef int (* SCRIPT_PRINTF_FUNC)(void * ctx, int MSGTYPE, char * string, ... ); +#define _jtag_script_printf_func_ +#endif + +script_ctx * jtagcore_initScript(jtag_core * jc); + +void jtagcore_setScriptOutputFunc( script_ctx * ctx, SCRIPT_PRINTF_FUNC ext_printf ); +int jtagcore_execScriptLine( script_ctx * ctx, char * line ); +int jtagcore_execScriptFile( script_ctx * ctx, char * script_path ); +int jtagcore_execScriptRam( script_ctx * ctx, unsigned char * script_buffer, int buffersize ); + +script_ctx * jtagcore_deinitScript( script_ctx * ctx ); + +int jtagcore_savePinsStateScript( jtag_core * jc, int device, char * script_path ); + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// JTAG Emulation layer (WIP) + +jtag_emu * jtagemu_init(jtag_core * jc); + +int jtagemu_reset(jtag_emu * je); + +int jtagemu_tick(jtag_emu * je, unsigned char io_state); + +int jtagemu_get_regbit_state(jtag_emu * je, int regid, int bit); + +int jtagemu_loadbsdlfile(jtag_emu * je, char * path, int device); + +void jtagemu_deinit(jtag_emu * je); diff --git a/lib_jtag_core/src/jtag_core_internal.h b/lib_jtag_core/src/jtag_core_internal.h new file mode 100644 index 0000000..90978b8 --- /dev/null +++ b/lib_jtag_core/src/jtag_core_internal.h @@ -0,0 +1,155 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file jtag_core_internal.h + * @brief jtag core library internal structures and defines types + * @author Jean-François DEL NERO + */ + +#define _jtag_core_ + +#define MAX_NB_JTAG_DEVICE 64 +#define MAX_NUMBER_BITS_IN_CHAIN ( 256 * 1024 ) +#define MAX_NUMBER_PINS_PER_DEV ( 64 * 1024 ) +#define MAX_BSDL_FILE_SIZE ( 1024 * 1024 ) +#define MAX_NUMBER_OF_BSDL_LINES ( 64 * 1024 ) + +#define MAX_PATH_LEN 4096 + +typedef struct _jtag_device +{ + void * bsdl; + unsigned long devices_id; + unsigned char * out_boundary_scan; + unsigned char * in_boundary_scan; + int boundary_scan_size; + int scan_mode; +}jtag_device; + +#define MAX_BUS_WIDTH 32 + +typedef struct _jtag_core +{ + drv_ptr io_functions; + + void * jtagcore_print_callback; + int logs_level; + + void * envvar; + + int t; + + int nb_of_devices_in_chain; + + int total_IR_lenght; + jtag_device devices_list[MAX_NB_JTAG_DEVICE]; + int IR_filled; + + // I2C over JTAG + int i2c_sda_device; + int i2c_scl_device; + + int i2c_sda_pin; + int i2c_scl_pin; + + // SPI over JTAG + int spi_mosi_device; + int spi_miso_device; + int spi_cs_device; + int spi_clk_device; + + int spi_mosi_pin; + int spi_miso_pin; + int spi_cs_pin; + int spi_clk_pin; + + int spi_cs_pol; + int spi_clk_pol; + int spi_mosi_pol; + int spi_miso_pol; + + int spi_lsb_first; + + // MDIO over JTAG + int mdio_mdc_pin; + int mdio_mdc_device; + int mdio_mdio_pin; + int mdio_mdio_device; + + // Memory over JTAG + int ram_address_pin[MAX_BUS_WIDTH]; + int ram_address_device[MAX_BUS_WIDTH]; + int ram_data_pin[MAX_BUS_WIDTH]; + int ram_data_device[MAX_BUS_WIDTH]; + int ram_ctrl_pin[16]; + int ram_ctrl_pin_pol[16]; + int ram_ctrl_device[16]; + + char log_file_path[MAX_PATH_LEN]; +}jtag_core; + +#define JTAG_STR_DOUT 0x01 +#define JTAG_STR_TMS 0x02 +#define JTAG_STR_CLKDIS 0x04 +#define JTAG_STR_JTAGRST 0x08 +#define JTAG_STR_DIN 0x10 +#define JTAG_STR_DINREQ 0x20 + +int jtagcore_loaddriver(jtag_core * jc,int id, char * parameters); + +// jtag device emulator + +#define _jtag_emu_ + +typedef struct _jtag_emu +{ + jtag_core * jc; + + void * bsdl_file; + + unsigned char * out_boundary_scan; + unsigned char * in_boundary_scan; + unsigned char * data_register; + unsigned char * inst_register; + + int jtag_state_machine; +}jtag_emu; + +enum +{ + JTAG_EMU_STATE_RESET = 0, + JTAG_EMU_STATE_IDLE, + + JTAG_EMU_STATE_SEL_DR_SCAN, + JTAG_EMU_STATE_CAPTURE_DR, + JTAG_EMU_STATE_SHIFT_DR, + JTAG_EMU_STATE_EXIT1_DR, + JTAG_EMU_STATE_PAUSE_DR, + JTAG_EMU_STATE_EXIT2_DR, + JTAG_EMU_STATE_UPDATE_DR, + + JTAG_EMU_STATE_SEL_IR_SCAN, + JTAG_EMU_STATE_CAPTURE_IR, + JTAG_EMU_STATE_SHIFT_IR, + JTAG_EMU_STATE_EXIT1_IR, + JTAG_EMU_STATE_PAUSE_IR, + JTAG_EMU_STATE_EXIT2_IR, + JTAG_EMU_STATE_UPDATE_IR +}; diff --git a/lib_jtag_core/src/natsort/strnatcmp.c b/lib_jtag_core/src/natsort/strnatcmp.c new file mode 100644 index 0000000..5b540a7 --- /dev/null +++ b/lib_jtag_core/src/natsort/strnatcmp.c @@ -0,0 +1,178 @@ +/* -*- mode: c; c-file-style: "k&r" -*- + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000, 2004 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +/* partial change history: + * + * 2004-10-10 mbp: Lift out character type dependencies into macros. + * + * Eric Sosman pointed out that ctype functions take a parameter whose + * value must be that of an unsigned int, even on platforms that have + * negative chars in their default char type. + */ + +#include +#include +#include +#include + +#include "strnatcmp.h" + + +/* These are defined as macros to make it easier to adapt this code to + * different characters types or comparison functions. */ +static /*inline*/ int +nat_isdigit(nat_char a) +{ + return isdigit((unsigned char) a); +} + + +static /*inline*/ int +nat_isspace(nat_char a) +{ + return isspace((unsigned char) a); +} + + +static /*inline*/ nat_char +nat_toupper(nat_char a) +{ + return toupper((unsigned char) a); +} + + + +static int +compare_right(nat_char const *a, nat_char const *b) +{ + int bias = 0; + + /* The longest run of digits wins. That aside, the greatest + value wins, but we can't know that it will until we've scanned + both numbers to know that they have the same magnitude, so we + remember it in BIAS. */ + for (;; a++, b++) { + if (!nat_isdigit(*a) && !nat_isdigit(*b)) + return bias; + else if (!nat_isdigit(*a)) + return -1; + else if (!nat_isdigit(*b)) + return +1; + else if (*a < *b) { + if (!bias) + bias = -1; + } else if (*a > *b) { + if (!bias) + bias = +1; + } else if (!*a && !*b) + return bias; + } + + return 0; +} + + +static int +compare_left(nat_char const *a, nat_char const *b) +{ + /* Compare two left-aligned numbers: the first to have a + different value wins. */ + for (;; a++, b++) { + if (!nat_isdigit(*a) && !nat_isdigit(*b)) + return 0; + else if (!nat_isdigit(*a)) + return -1; + else if (!nat_isdigit(*b)) + return +1; + else if (*a < *b) + return -1; + else if (*a > *b) + return +1; + } + + return 0; +} + + +static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case) +{ + int ai, bi; + nat_char ca, cb; + int fractional, result; + + assert(a && b); + ai = bi = 0; + while (1) { + ca = a[ai]; cb = b[bi]; + + /* skip over leading spaces or zeros */ + while (nat_isspace(ca)) + ca = a[++ai]; + + while (nat_isspace(cb)) + cb = b[++bi]; + + /* process run of digits */ + if (nat_isdigit(ca) && nat_isdigit(cb)) { + fractional = (ca == '0' || cb == '0'); + + if (fractional) { + if ((result = compare_left(a+ai, b+bi)) != 0) + return result; + } else { + if ((result = compare_right(a+ai, b+bi)) != 0) + return result; + } + } + + if (!ca && !cb) { + /* The strings compare the same. Perhaps the caller + will want to call strcmp to break the tie. */ + return 0; + } + + if (fold_case) { + ca = nat_toupper(ca); + cb = nat_toupper(cb); + } + + if (ca < cb) + return -1; + else if (ca > cb) + return +1; + + ++ai; ++bi; + } +} + + + +int strnatcmp(nat_char const *a, nat_char const *b) { + return strnatcmp0(a, b, 0); +} + + +/* Compare, recognizing numeric string and ignoring case. */ +int strnatcasecmp(nat_char const *a, nat_char const *b) { + return strnatcmp0(a, b, 1); +} diff --git a/lib_jtag_core/src/natsort/strnatcmp.h b/lib_jtag_core/src/natsort/strnatcmp.h new file mode 100644 index 0000000..51a3c4e --- /dev/null +++ b/lib_jtag_core/src/natsort/strnatcmp.h @@ -0,0 +1,31 @@ +/* -*- mode: c; c-file-style: "k&r" -*- + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000, 2004 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +/* CUSTOMIZATION SECTION + * + * You can change this typedef, but must then also change the inline + * functions in strnatcmp.c */ +typedef char nat_char; + +int strnatcmp(nat_char const *a, nat_char const *b); +int strnatcasecmp(nat_char const *a, nat_char const *b); diff --git a/lib_jtag_core/src/os_interface/fs.c b/lib_jtag_core/src/os_interface/fs.c new file mode 100644 index 0000000..d0c5001 --- /dev/null +++ b/lib_jtag_core/src/os_interface/fs.c @@ -0,0 +1,597 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file fs.c +* @brief Basic/generic OS file system functions wrapper. +* @author Jean-François DEL NERO +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stdint.h" + +#ifdef WIN32 +# include +# include +# include +# include +#else +# include +# include + +#ifdef OSX +# include +#endif + +#endif + +#include "../jtag_core.h" + +#include "os_interface.h" + + +#ifdef WIN32 + + +int convertpath (const char * path, wchar_t * wpath) +{ + if (!MultiByteToWideChar (CP_UTF8, 0, path, -1, wpath, MAX_PATH)) + { + errno = ENOENT; + return -1; + } + wpath[MAX_PATH] = L'\0'; + return 0; +} +#else + +#endif + + +int genos_open (const char *filename, int flags, ...) +{ + +#ifdef WIN32 + wchar_t wpath[MAX_PATH+1]; +#else + const char *local_name; +#endif + + unsigned int mode = 0; + va_list ap; + +#if defined (DEBUG) + printf("genos_open : filename=%s flags=%x\n",filename,flags); +#endif + + va_start (ap, flags); + if (flags & O_CREAT) + mode = va_arg (ap, unsigned int); + va_end (ap); + +#ifdef WIN32 + + memset(wpath,0,(MAX_PATH+1)*sizeof(wchar_t)); + if(convertpath(filename, wpath)<0) + return -1; + + return _wopen (wpath, flags, mode); + +#else + + local_name = filename; + //local_name = (const char *)ToLocale (filename); + + if (local_name == NULL) + { + errno = ENOENT; + return -1; + } + + int fd = open (local_name, flags, mode); + + //LocaleFree (local_name); + return fd; + +#endif + + +} + +FILE *genos_fopen (const char *filename, const char *mode) +{ + int rwflags, oflags; + int append; + int fd; + const char *ptr; + FILE *stream; + +#if defined (DEBUG) + printf("genos_fopen : filename=%s mode=%s\n",filename,mode); +#endif + + // Try the classic way (ascii path) + stream = fopen(filename,mode); + + if( ( stream == NULL ) && (errno == ENOENT) ) + { + // Try the utf8 way + rwflags = 0; + oflags = 0; + append = 0; + + for(ptr = mode;*ptr;ptr++) + { + switch (*ptr) + { + case 'r': + rwflags = O_RDONLY; + break; + #ifdef O_BINARY + case 'b': + oflags |= O_BINARY; + break; + #endif + case 'a': + rwflags = O_WRONLY; + oflags |= O_CREAT; + append = 1; + break; + + case 'w': + rwflags = O_WRONLY; + oflags |= O_CREAT | O_TRUNC; + break; + + case '+': + rwflags = O_RDWR; + break; + + #ifdef O_TEXT + case 't': + oflags |= O_TEXT; + break; + #endif + } + } + + fd = genos_open (filename, rwflags|oflags, (unsigned int)(0666)); + if(fd==-1) + return NULL; + + if(append) + { +#if defined (WIN32) + if(_lseek(fd,0,SEEK_END) == -1) + { + _close (fd); + + return NULL; + } +#else + if(lseek(fd,0,SEEK_END) == -1) + { + close (fd); + + return NULL; + } +#endif + } + else + { +#if defined (WIN32) + _lseek(fd,0,SEEK_SET); +#else + lseek(fd,0,SEEK_SET); +#endif + } + +#if defined (WIN32) + stream = _fdopen(fd,mode); + if(stream == NULL) + { + _close (fd); + } +#else + stream = fdopen(fd,mode); + if(stream == NULL) + { + close (fd); + } +#endif + } + + return stream; +} + +int genos_fread(void * ptr, size_t size, FILE *f) +{ + +#if defined (DEBUG) + printf("genos_fread : ptr=%p size=%zu file:%p\n",ptr,size,f); +#endif + + if( fread(ptr,size,1,f) != 1 ) + { + return 1; // Error + } + else + { + return 0; // No Error + } +} + +char * genos_fgets(char * str, int num, FILE *f) +{ + return fgets( str, num, f ); +} + +int genos_fclose(FILE * f) +{ +#if defined (DEBUG) + printf("genos_fclose : file:%p\n",f); +#endif + + return fclose(f); +} + +int genos_statex( const char *filename, struct stat *buf) +{ +#if defined (DEBUG) + printf("genos_statex : filename=%s\n",filename); +#endif +#if defined (WIN32) + wchar_t wpath[MAX_PATH+1]; + + if( convertpath(filename, wpath) < 0 ) + return -1; + + return _wstat (wpath,(struct _stat *)buf); +#else + int res; + const char *local_name; + + local_name = filename;//ToLocale( filename ); + + if( local_name != NULL ) + { + res = lstat( local_name, buf ); + // LocaleFree( local_name ); + return res; + } + + errno = ENOENT; + + return -1; +#endif + +} + +int genos_stat( const char *filename, struct stat *buf) +{ + return genos_statex(filename,buf); +} + +void * genos_find_first_file(char *folder, char *file, filefoundinfo* fileinfo) +{ +#if defined (DEBUG) + printf("genos_find_first_file : folder=%s file=%s\n",folder,file); +#endif + +#if defined (WIN32) + + HANDLE hfindfile; + char *folderstr; + WIN32_FIND_DATAW FindFileData; + wchar_t wpath[MAX_PATH+1]; + + if(file) + { + folderstr=(char *) malloc(strlen(folder)+strlen(file)+2); + sprintf((char *)folderstr,"%s\\%s",folder,file); + } + else + { + folderstr = (char *) malloc(strlen(folder)+1); + sprintf((char *)folderstr,"%s",folder); + } + + convertpath (folderstr, wpath); + hfindfile = FindFirstFileW(wpath, &FindFileData); + if(hfindfile!=INVALID_HANDLE_VALUE) + { + WideCharToMultiByte(CP_UTF8,0,FindFileData.cFileName,-1,fileinfo->filename,sizeof(fileinfo->filename),NULL,NULL); + //sprintf(fileinfo->filename,"%s",FindFileData.cFileName); + + fileinfo->isdirectory = 0; + + if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + fileinfo->isdirectory = 1; + } + + fileinfo->size = FindFileData.nFileSizeLow; + free(folderstr); + return (void*)hfindfile; + } + else + { + free(folderstr); + return 0; + } + +#else + struct dirent *d; + DIR * dir; + struct stat fileStat; + char * tmpstr; + + if(!file) + { + // File mode + memset(&fileStat,0,sizeof(struct stat)); + if(!lstat (folder, &fileStat)) + { + if ( !S_ISDIR ( fileStat.st_mode ) ) + { + fileinfo->isdirectory = 0; + fileinfo->size = fileStat.st_size; + strncpy(fileinfo->filename,genos_getfilenamebase(folder,NULL,SYS_PATH_TYPE),FILEFOUND_NAMESIZE - 1); + fileinfo->filename[FILEFOUND_NAMESIZE - 1] = 0; + + return (void*)-1; + } + } + } + + dir = opendir (folder); + if(dir) + { + d = readdir (dir); + if(d) + { + tmpstr = malloc (strlen(folder) + strlen(d->d_name) + 4 ); + if(tmpstr) + { + strcpy(tmpstr,folder); + strcat(tmpstr,"/"); + strcat(tmpstr,d->d_name); + + memset(&fileStat,0,sizeof(struct stat)); + if(!lstat (tmpstr, &fileStat)) + { + + if ( S_ISDIR ( fileStat.st_mode ) ) + fileinfo->isdirectory=1; + else + fileinfo->isdirectory=0; + + fileinfo->size=fileStat.st_size; + + strncpy(fileinfo->filename,d->d_name,FILEFOUND_NAMESIZE - 1); + fileinfo->filename[FILEFOUND_NAMESIZE - 1] = '\0'; + + free(tmpstr); + return (void*)dir; + } + + free(tmpstr); + } + + closedir (dir); + dir=0; + + return (void*)dir; + } + + closedir (dir); + dir=0; + } + + return (void*)dir; + +#endif + + return 0; +} + +int genos_find_next_file(void* handleff, char *folder, char *file, filefoundinfo* fileinfo) +{ + int ret; + +#if defined (DEBUG) + printf("genos_find_next_file : handleff:%p folder=%s file=%s\n",handleff,folder,file); +#endif + +#if defined (WIN32) + WIN32_FIND_DATAW FindFileData; + + + ret=FindNextFileW((HANDLE)handleff,&FindFileData); + if(ret) + { + WideCharToMultiByte(CP_UTF8,0,FindFileData.cFileName,-1,fileinfo->filename,sizeof(fileinfo->filename),NULL,NULL); + //sprintf(fileinfo->filename,"%s",FindFileData.cFileName); + + fileinfo->isdirectory=0; + + if( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + { + fileinfo->isdirectory = 1; + } + + fileinfo->size = FindFileData.nFileSizeLow; + } +#else + struct dirent *d; + DIR * dir; + struct stat fileStat; + char * tmpstr; + + if((long)(handleff) == -1) // File mode + return 0; + + dir = (DIR*) handleff; + d = readdir (dir); + + ret = 0; + if(d) + { + tmpstr = malloc (strlen(folder) + strlen(d->d_name) + 4 ); + if(tmpstr) + { + strcpy(tmpstr,folder); + strcat(tmpstr,"/"); + strcat(tmpstr,d->d_name); + + if(!lstat (tmpstr, &fileStat)) + { + if ( S_ISDIR ( fileStat.st_mode ) ) + fileinfo->isdirectory=1; + else + fileinfo->isdirectory=0; + + fileinfo->size=fileStat.st_size; + strncpy(fileinfo->filename,d->d_name,FILEFOUND_NAMESIZE - 1); + fileinfo->filename[FILEFOUND_NAMESIZE - 1] = '\0'; + + ret = 1; + free(tmpstr); + return ret; + } + + free(tmpstr); + } + } + +#endif + + return ret; +} + +int genos_find_close(void* handle) +{ +#if defined (DEBUG) + printf("genos_find_close : handle:%p\n",handle); +#endif + +#if defined (WIN32) + if(handle) + FindClose((void*)handle); +#else + if((long)(handle) == -1) // File mode + return 0; + + if(handle) + closedir((DIR*) handle); +#endif + return 0; +} + +char * genos_getcurrentdirectory(char *currentdirectory,int buffersize) +{ + memset(currentdirectory,0,buffersize); +#if defined (WIN32) + if(GetModuleFileName(GetModuleHandle(NULL),currentdirectory,buffersize)) + { + if(strrchr(currentdirectory,'\\')) + { + *((char*)strrchr(currentdirectory,'\\')) = 0; + return currentdirectory; + } + } +#else + + #if defined (OSX) + + if (_NSGetExecutablePath(currentdirectory, &buffersize) == 0) + { + if(strrchr(currentdirectory,'/')) + { + *((char*)strrchr(currentdirectory,'/')) = 0; + return currentdirectory; + } + } + + #else + + strncpy(currentdirectory,"./",buffersize - 1); + currentdirectory[buffersize-1] = '\0'; + + return currentdirectory; + + #endif + +#endif + + return 0; +} + +int genos_mkdir(char * folder) +{ +#if defined (DEBUG) + printf("genos_mkdir : folder:%s\n",folder); +#endif + +#ifdef WIN32 + _mkdir(folder); +#else + mkdir(folder,0777); +#endif + return 0; +} + +int genos_fgetsize( FILE * f ) +{ + int cur_pos,filesize; + + filesize = 0; + + if( f ) + { + cur_pos = ftell(f); + if( cur_pos >= 0 ) + { + if(fseek (f , 0 , SEEK_END)) + return 0; + + filesize = ftell(f); + + if( filesize < 0 ) + filesize = 0; + + fseek (f , cur_pos , SEEK_SET); + } + + return filesize; + } + + return 0; +} diff --git a/lib_jtag_core/src/os_interface/network.c b/lib_jtag_core/src/os_interface/network.c new file mode 100644 index 0000000..ecd8dfb --- /dev/null +++ b/lib_jtag_core/src/os_interface/network.c @@ -0,0 +1,203 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file network.c +* @brief Basic/generic network functions wrapper. +* @author Jean-François DEL NERO +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include + +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define closesocket(s) close (s) +typedef int SOCKET; +typedef struct sockaddr_in SOCKADDR_IN; +typedef struct sockaddr SOCKADDR; +#include +#include + +#ifdef OSX +# include +#endif + +#endif + +#include "../jtag_core.h" +#include "network.h" +#include "os_interface.h" + +void * network_connect(char * address,unsigned short port) +{ + genos_tcp_stat * tcp_stat; +#ifdef WIN32 + int iResult; +#endif + + tcp_stat = malloc(sizeof(genos_tcp_stat)); + if(tcp_stat) + { + memset(tcp_stat,0,sizeof(genos_tcp_stat)); + +#ifdef WIN32 + iResult = WSAStartup(MAKEWORD(2,2), &tcp_stat->wsaData); + if (iResult != NO_ERROR) + { + free(tcp_stat); + return (void*)NULL; + } +#endif + + tcp_stat->m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (tcp_stat->m_socket == INVALID_SOCKET) + { +#ifdef WIN32 + WSACleanup(); +#endif + free(tcp_stat); + return (void*)NULL; + } + + tcp_stat->clientService.sin_family = AF_INET; + tcp_stat->clientService.sin_addr.s_addr = inet_addr(address); + tcp_stat->clientService.sin_port = htons(port); + + if (connect(tcp_stat->m_socket, (SOCKADDR*)&tcp_stat->clientService, sizeof(tcp_stat->clientService)) == SOCKET_ERROR) + { +#ifdef WIN32 + WSACleanup(); +#else + close(tcp_stat->m_socket); +#endif + + free(tcp_stat); + return (void*)NULL; + } + + return (void*)tcp_stat; + } + + return (void*)NULL; +} + +int network_read(void * network_connection, unsigned char * buffer, int size,int timeout) +{ + int bytesRecv; + int offset; + genos_tcp_stat * tcp_stat; + + tcp_stat = (genos_tcp_stat *)network_connection; + + offset=0; + + while(offset < size) + { + bytesRecv = recv(tcp_stat->m_socket, (char*)&buffer[offset], size - offset, 0); + if(bytesRecv == SOCKET_ERROR) + { + return -1; + } + else + { + offset += bytesRecv; + } + } + + return size; +} + +int network_read2(void * network_connection, unsigned char * buffer, int size,int timeout) +{ + int bytesRecv; + int offset; + genos_tcp_stat * tcp_stat; + + tcp_stat = (genos_tcp_stat *)network_connection; + + offset=0; + + bytesRecv = recv(tcp_stat->m_socket, (char*)&buffer[offset], size - offset, 0); + + return bytesRecv; +} + +int network_write(void * network_connection, unsigned char * buffer, int size,int timeout) +{ + int bytesSent; + int offset; + genos_tcp_stat * tcp_stat; + + tcp_stat = (genos_tcp_stat *)network_connection; + + offset = 0; + while(offset < size) + { + bytesSent = send(tcp_stat->m_socket, (char*)&buffer[offset], size - offset, 0); + if(bytesSent == SOCKET_ERROR) + { + return -1; + } + else + { + offset += bytesSent; + } + } + + return size; +} + +int network_close(void * network_connection) +{ + genos_tcp_stat * tcp_stat; + + tcp_stat = (genos_tcp_stat *)network_connection; + + closesocket (tcp_stat->m_socket); + +#ifdef WIN32 + WSACleanup(); +#endif + free(tcp_stat); + + return 0; +} diff --git a/lib_jtag_core/src/os_interface/network.h b/lib_jtag_core/src/os_interface/network.h new file mode 100644 index 0000000..d5ef55d --- /dev/null +++ b/lib_jtag_core/src/os_interface/network.h @@ -0,0 +1,33 @@ +/* + * JTAG Boundary Scanner + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Boundary Scanner 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 3.0 of the License, or (at your option) any later version. + * + * JTAG Boundary Scanner 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 version 3 for more details. + * + * You should have received a copy of the GNU General Public License + * along with JTAG Boundary Scanners; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file network.h +* @brief Basic/generic network functions wrapper header. +* @author Jean-François DEL NERO +*/ + +typedef struct genos_tcp_stat_ +{ +#ifdef WIN32 + WSADATA wsaData; +#endif + struct sockaddr_in clientService; + SOCKET m_socket; +}genos_tcp_stat; diff --git a/lib_jtag_core/src/os_interface/os_interface.c b/lib_jtag_core/src/os_interface/os_interface.c new file mode 100644 index 0000000..898cd8f --- /dev/null +++ b/lib_jtag_core/src/os_interface/os_interface.c @@ -0,0 +1,672 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file os_interface.c +* @brief Basic/generic OS functions wrapper. +* @author Jean-François DEL NERO +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef WIN32 + #include + #include +#else + #include + #include + #include +#endif + +#include + +#include + +#include "../drivers/drv_loader.h" +#include "../jtag_core_internal.h" +#include "../script/script.h" +#include "../jtag_core.h" + +#include "os_interface.h" + +#ifdef WIN32 + HANDLE eventtab[256]; + CRITICAL_SECTION criticalsectiontab[256]; +#else + typedef struct _EVENT_HANDLE{ + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + int iVar; + } EVENT_HANDLE; + + EVENT_HANDLE * eventtab[256]; + + pthread_mutex_t criticalsectiontab[256]; +#endif + +#ifdef WIN32 + +DWORD WINAPI ThreadProc( LPVOID lpParameter) +{ + threadinit *threadinitptr; + THREADFUNCTION thread; + jtag_core* jtag_ctx; + void * hw_context; + + if( lpParameter ) + { + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + + threadinitptr=(threadinit*)lpParameter; + thread=threadinitptr->thread; + jtag_ctx = threadinitptr->jtag_ctx; + hw_context=threadinitptr->hwcontext; + thread(jtag_ctx,hw_context); + + free(threadinitptr); + } + + return 0; +} +#else +void * ThreadProc( void *lpParameter) +{ + threadinit *threadinitptr; + THREADFUNCTION thread; + jtag_core* jtag_ctx; + void * hw_context; + + threadinitptr=(threadinit*)lpParameter; + if( threadinitptr ) + { + + thread=threadinitptr->thread; + jtag_ctx = threadinitptr->jtag_ctx; + hw_context=threadinitptr->hwcontext; + thread(jtag_ctx,hw_context); + + free(threadinitptr); + } + + return 0; +} +#endif + +int genos_setevent(jtag_core* jtag_ctx,unsigned char id) +{ +#ifdef WIN32 + SetEvent(eventtab[id]); +#else + pthread_mutex_lock(&eventtab[id]->eMutex); + pthread_cond_signal(&eventtab[id]->eCondVar); + pthread_mutex_unlock(&eventtab[id]->eMutex); +#endif + return 0; +} + +uintptr_t genos_createevent(jtag_core* jtag_ctx,unsigned char id) +{ +#ifdef WIN32 + + eventtab[id] = CreateEvent(NULL,FALSE,FALSE,NULL); + return (uintptr_t)eventtab[id]; + +#else + + eventtab[id]=(EVENT_HANDLE*)malloc(sizeof(EVENT_HANDLE)); + pthread_mutex_init(&eventtab[id]->eMutex, NULL); + pthread_cond_init(&eventtab[id]->eCondVar, NULL); + return (uintptr_t)eventtab[id]; +#endif +} + +int genos_waitevent(jtag_core* jtag_ctx,int id,int timeout) +{ + +#ifdef WIN32 + int ret; + + if(timeout==0) timeout=INFINITE; + ret=WaitForSingleObject(eventtab[id],timeout); + + if(ret==0) + { + return 0; + } + else + { + return 1; + } +#else + struct timeval now; + struct timespec timeoutstr; + int retcode; + + pthread_mutex_lock(&eventtab[id]->eMutex); + gettimeofday(&now,0); + timeoutstr.tv_sec = now.tv_sec + (timeout/1000); + timeoutstr.tv_nsec = (now.tv_usec * 1000) ;//+(timeout*1000000); + retcode = 0; + + retcode = pthread_cond_timedwait(&eventtab[id]->eCondVar, &eventtab[id]->eMutex, &timeoutstr); + if (retcode == ETIMEDOUT) + { + pthread_mutex_unlock(&eventtab[id]->eMutex); + return 1; + } + else + { + pthread_mutex_unlock(&eventtab[id]->eMutex); + return 0; + } +#endif +} + +uintptr_t genos_createcriticalsection(jtag_core* jtag_ctx,unsigned char id) +{ +#ifdef WIN32 + + InitializeCriticalSection(&criticalsectiontab[id]); + return (uintptr_t)&criticalsectiontab[id]; + +#else + //create mutex attribute variable + pthread_mutexattr_t mAttr; + + pthread_mutexattr_init(&mAttr); + +#if defined(__APPLE__) + // setup recursive mutex for mutex attribute + pthread_mutexattr_settype(&mAttr, PTHREAD_MUTEX_RECURSIVE); +#else + pthread_mutexattr_settype(&mAttr, PTHREAD_MUTEX_RECURSIVE_NP); +#endif + // Use the mutex attribute to create the mutex + pthread_mutex_init(&criticalsectiontab[id], &mAttr); + + // Mutex attribute can be destroy after initializing the mutex variable + pthread_mutexattr_destroy(&mAttr); + + return (uintptr_t)&criticalsectiontab[id]; +#endif +} + + +void genos_entercriticalsection(jtag_core* jtag_ctx,unsigned char id) +{ +#ifdef WIN32 + EnterCriticalSection( &criticalsectiontab[id] ); +#else + pthread_mutex_lock( &criticalsectiontab[id] ); +#endif +} + +void genos_leavecriticalsection(jtag_core* jtag_ctx,unsigned char id) +{ +#ifdef WIN32 + LeaveCriticalSection( &criticalsectiontab[id] ); +#else + pthread_mutex_unlock( &criticalsectiontab[id] ); +#endif +} + +void genos_destroycriticalsection(jtag_core* jtag_ctx,unsigned char id) +{ +#ifdef WIN32 + DeleteCriticalSection(&criticalsectiontab[id]); +#else + pthread_mutex_destroy (&criticalsectiontab[id]); +#endif +} + + +#ifndef WIN32 +void genos_msleep (unsigned int ms) { + int microsecs; + struct timeval tv; + microsecs = ms * 1000; + tv.tv_sec = microsecs / 1000000; + tv.tv_usec = microsecs % 1000000; + select (0, NULL, NULL, NULL, &tv); +} +#endif + +void genos_pause(int ms) +{ +#ifdef WIN32 + Sleep(ms); +#else + genos_msleep(ms); +#endif +} + +int genos_createthread(jtag_core* jtag_ctx,void* hwcontext,THREADFUNCTION thread,int priority) +{ +#ifdef WIN32 + DWORD sit; + HANDLE thread_handle; + threadinit *threadinitptr; + + sit = 0; + + threadinitptr=(threadinit*)malloc(sizeof(threadinit)); + if( threadinitptr ) + { + threadinitptr->thread = thread; + threadinitptr->jtag_ctx = jtag_ctx; + threadinitptr->hwcontext = hwcontext; + + thread_handle = CreateThread(NULL,8*1024,&ThreadProc,threadinitptr,0,&sit); + + if(!thread_handle) + { + free(threadinitptr); + // jtag_ctx->jtagcore_print_callback(MSG_ERROR,"genos_createthread : CreateThread failed -> 0x.8X", GetLastError()); + } + } + return sit; +#else + unsigned long sit; + int ret; + pthread_t threadid; + pthread_attr_t threadattrib; + threadinit *threadinitptr; + struct sched_param param; + JTAGCORE_PRINT_FUNC print_callback; + + sit = 0; + + pthread_attr_init(&threadattrib); + + pthread_attr_setinheritsched(&threadattrib, PTHREAD_EXPLICIT_SCHED); + + if(priority) + { + pthread_attr_setschedpolicy(&threadattrib,SCHED_FIFO); + param.sched_priority = sched_get_priority_max(SCHED_FIFO); + } + else + { + pthread_attr_setschedpolicy(&threadattrib,SCHED_OTHER); + param.sched_priority = sched_get_priority_max(SCHED_OTHER); + } + /* set the new scheduling param */ + pthread_attr_setschedparam (&threadattrib, ¶m); + + print_callback = jtag_ctx->jtagcore_print_callback; + + threadinitptr = (threadinit *)malloc(sizeof(threadinit)); + if( threadinitptr ) + { + threadinitptr->thread = thread; + threadinitptr->jtag_ctx = jtag_ctx; + //threadinitptr->hwcontext=hwcontext; + + ret = pthread_create(&threadid, &threadattrib,ThreadProc, threadinitptr); + if(ret) + { + print_callback(jtag_ctx,"genos_createthread : pthread_create failed !"); + free( threadinitptr ); + } + } + else + { + print_callback(jtag_ctx,"genos_createthread : memory allocation failed !"); + } + + return sit; +#endif + +} + +#ifndef WIN32 +/*void strlwr(char *string) +{ + int i; + + i=0; + while (string[i]) + { + string[i] = tolower(string[i]); + i++; + } +}*/ +#endif + +char * genos_strupper(char * str) +{ + int i; + + i=0; + while(str[i]) + { + + if(str[i]>='a' && str[i]<='z') + { + str[i]=str[i]+('A'-'a'); + } + i++; + } + + return str; +} + +char * genos_strlower(char * str) +{ + int i; + + i=0; + while(str[i]) + { + + if(str[i]>='A' && str[i]<='Z') + { + str[i]=str[i]+('a'-'A'); + } + i++; + } + + return str; +} + +char * genos_getfilenamebase(char * fullpath,char * filenamebase, int type) +{ + int len,i; + char separator; + + if(fullpath) + { + len=strlen(fullpath); + + separator = DIR_SEPARATOR_CHAR; // system type by default + + switch(type) + { + case SYS_PATH_TYPE: // System based + separator = DIR_SEPARATOR_CHAR; + break; + + case UNIX_PATH_TYPE: // Unix style + separator = '/'; + break; + + case WINDOWS_PATH_TYPE: // Windows style + separator = '\\'; + break; + } + + i=0; + if(len) + { + i=len-1; + while(i && ( fullpath[i] != separator && fullpath[i]!=':') ) + { + i--; + } + + if( fullpath[i] == separator || fullpath[i]==':' ) + { + i++; + } + + if(i>len) + { + i=len; + } + } + + if(filenamebase) + { + strcpy(filenamebase,&fullpath[i]); + } + + return &fullpath[i]; + } + + return 0; +} + +char * genos_getfilenameext(char * fullpath,char * filenameext, int type ) +{ + char * filename; + int len,i; + + filename = genos_getfilenamebase(fullpath,0,type); + + if(filename) + { + len=strlen(filename); + + i=0; + if(len) + { + i=len-1; + + while(i && ( filename[i] != '.' ) ) + { + i--; + } + + if( filename[i] == '.' ) + { + i++; + } + else + { + i=len; + } + + if(i>len) + { + i=len; + } + } + + if(filenameext) + { + strcpy(filenameext,&filename[i]); + } + + return &filename[i]; + } + + return 0; +} + +int genos_getfilenamewext(char * fullpath,char * filenamewext, int type) +{ + char * filename; + char * ext; + int len; + + len = 0; + if(fullpath) + { + filename = genos_getfilenamebase(fullpath,0,type); + ext = genos_getfilenameext(fullpath,0,type); + + len = ext-filename; + + if(len && filename[len-1]=='.') + { + len--; + } + + if(filenamewext) + { + memcpy(filenamewext,filename,len); + filenamewext[len]=0; + } + } + + return len; +} + +int genos_getpathfolder(char * fullpath,char * folder,int type) +{ + int len; + char * filenameptr; + + len = 0; + if(fullpath) + { + filenameptr = genos_getfilenamebase(fullpath,0,type); + + len = filenameptr-fullpath; + + if(folder) + { + memcpy(folder,fullpath,len); + folder[len]=0; + } + } + + return len; +} + +int genos_checkfileext(char * path,char *ext,int type) +{ + char pathext[16]; + char srcext[16]; + char * ptr; + + if(path && ext) + { + pathext[0] = '\0'; + srcext[0] = ' '; + srcext[1] = '\0'; + + ptr = genos_getfilenameext(path,0,type); + if(!ptr) + return 0; + + if( ( strlen(ptr) < 16 ) && ( strlen(ext) < 16 )) + { + genos_getfilenameext(path,(char*)&pathext,type); + genos_strlower(pathext); + + strcpy((char*)srcext,ext); + genos_strlower(srcext); + + if(!strcmp(pathext,srcext)) + { + return 1; + } + } + } + return 0; +} + +int genos_getfilesize(char * path) +{ + int filesize; + FILE * f; + + filesize=-1; + + if(path) + { + f=genos_fopen(path,"rb"); + if(f) + { + fseek (f , 0 , SEEK_END); + filesize=ftell(f); + + fclose(f); + } + } + + return filesize; +} + +#ifdef WIN32 + +#if defined(_MSC_VER) && _MSC_VER < 1900 + +#define va_copy(dest, src) (dest = src) + +int vsnprintf(char *s, size_t n, const char *fmt, va_list ap) +{ + int ret; + va_list ap_copy; + + if (n == 0) + return 0; + else if (n > INT_MAX) + return 0; + memset(s, 0, n); + va_copy(ap_copy, ap); + ret = _vsnprintf(s, n - 1, fmt, ap_copy); + va_end(ap_copy); + + return ret; +} + +int snprintf(char *s, size_t n, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = vsnprintf(s, n, fmt, ap); + va_end(ap); + + return ret; +} + +#endif + +#endif + +char * genos_strndstcat( char *dest, const char *src, size_t maxdestsize ) +{ + int i,j; + + i = 0; + while( ( i < maxdestsize ) && dest[i] ) + { + i++; + } + + if( !dest[i] ) + { + j = 0; + while( ( i < maxdestsize ) && src[j] ) + { + dest[i] = src[j]; + i++; + j++; + } + + if( i < maxdestsize ) + { + dest[i] = '\0'; + } + } + + return dest; +} diff --git a/lib_jtag_core/src/os_interface/os_interface.h b/lib_jtag_core/src/os_interface/os_interface.h new file mode 100644 index 0000000..309d612 --- /dev/null +++ b/lib_jtag_core/src/os_interface/os_interface.h @@ -0,0 +1,126 @@ +/* + * JTAG Boundary Scanner + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Boundary Scanner 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 3.0 of the License, or (at your option) any later version. + * + * JTAG Boundary Scanner 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 version 3 for more details. + * + * You should have received a copy of the GNU General Public License + * along with JTAG Boundary Scanners; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file os_interface.h +* @brief Basic/generic OS functions wrapper header. +* @author Jean-François DEL NERO +*/ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +#define DIR_SEPARATOR "\\" +#define DIR_SEPARATOR_CHAR '\\' +#if defined(_MSC_VER) && _MSC_VER < 1900 +int snprintf(char *outBuf, size_t size, const char *format, ...); +#endif +#else +#define DIR_SEPARATOR "/" +#define DIR_SEPARATOR_CHAR '/' +#endif + +#define FILEFOUND_NAMESIZE 256 + +/////////////// Thread functions //////////////// + +typedef int (*THREADFUNCTION) (void* jtag_ctx,void* hw_ctx); + +typedef struct threadinit_ +{ + THREADFUNCTION thread; + jtag_core * jtag_ctx; + void * hwcontext; +}threadinit; + +typedef struct filefoundinfo_ +{ + int isdirectory; + char filename[FILEFOUND_NAMESIZE]; + int size; +}filefoundinfo; + +int genos_setevent( jtag_core* jtag_ctx, unsigned char id ); +uintptr_t genos_createevent( jtag_core* jtag_ctx, unsigned char id ); +int genos_waitevent( jtag_core* jtag_ctx, int id, int timeout ); +void genos_pause( int ms ); +int genos_createthread( jtag_core* jtag_ctx, void* hwcontext, THREADFUNCTION thread, int priority ); + +uintptr_t genos_createcriticalsection( jtag_core* jtag_ctx, unsigned char id ); +void genos_entercriticalsection( jtag_core* jtag_ctx, unsigned char id ); +void genos_leavecriticalsection( jtag_core* jtag_ctx, unsigned char id ); +void genos_destroycriticalsection( jtag_core* jtag_ctx, unsigned char id ); + +/////////////// String functions /////////////// + +#ifndef WIN32 +//void strlwr(char *string) +#endif +char * genos_strupper( char * str ); +char * genos_strlower( char * str ); +char * genos_strndstcat( char *dest, const char *src, size_t maxdestsize ); + +/////////////// File functions //////////////// + +int genos_open ( const char *filename, int flags, ... ); + +FILE *genos_fopen ( const char *filename, const char *mode ); +int genos_fread( void * ptr, size_t size, FILE *f ); +char * genos_fgets( char * str, int num, FILE *f ); +int genos_fclose( FILE * f ); +int genos_fgetsize( FILE * f ); +#ifndef stat +#include +#endif +int genos_stat( const char *filename, struct stat *buf ); + +void* genos_find_first_file( char *folder, char *file, filefoundinfo* fileinfo ); +int genos_find_next_file( void* handleff, char *folder, char *file, filefoundinfo* fileinfo ); +int genos_find_close( void* handle ); + +int genos_mkdir( char * folder ); + +char * genos_getcurrentdirectory( char *currentdirectory, int buffersize ); + +enum +{ + SYS_PATH_TYPE = 0, + UNIX_PATH_TYPE, + WINDOWS_PATH_TYPE, +}; + +char * genos_getfilenamebase( char * fullpath, char * filenamebase, int type ); +char * genos_getfilenameext( char * fullpath, char * filenameext, int type ); +int genos_getfilenamewext( char * fullpath, char * filenamewext, int type ); +int genos_getpathfolder( char * fullpath, char * folder, int type ); +int genos_checkfileext( char * path, char *ext, int type ); +int genos_getfilesize( char * path ); + +/////////////// Network functions //////////////// + +void * network_connect(char * address,unsigned short port); +int network_read(void * network_connection, unsigned char * buffer, int size,int timeout); +int network_read2(void * network_connection, unsigned char * buffer, int size,int timeout); +int network_write(void * network_connection, unsigned char * buffer, int size,int timeout); +int network_close(void * network_connection); + +#ifdef __cplusplus +} +#endif diff --git a/lib_jtag_core/src/os_interface/win32/libjtagcore.def b/lib_jtag_core/src/os_interface/win32/libjtagcore.def new file mode 100644 index 0000000..d0a6494 --- /dev/null +++ b/lib_jtag_core/src/os_interface/win32/libjtagcore.def @@ -0,0 +1,66 @@ +LIBRARY LIBJTAGCORE + +EXPORTS + jtagcore_init @1 + jtagcore_set_logs_callback @2 + jtagcore_set_logs_level @3 + setOutputFunc_script @4 + jtagcore_get_logs_level @5 + jtagcore_set_logs_file @6 + jtagcore_get_logs_file @7 + jtagcore_deinit @9 + + jtagcore_scan_and_init_chain @10 + jtagcore_get_number_of_devices @11 + jtagcore_get_dev_id @12 + jtagcore_loadbsdlfile @13 + jtagcore_get_dev_name @14 + jtagcore_get_number_of_pins @15 + jtagcore_get_pin_properties @16 + jtagcore_get_bsdl_id @17 + jtagcore_set_scan_mode @18 + jtagcore_get_pin_state @19 + jtagcore_set_pin_state @20 + jtagcore_push_and_pop_chain @21 + + jtagcore_get_number_of_probes @30 + jtagcore_get_number_of_probes_drv @31 + jtagcore_get_probe_name @32 + jtagcore_select_and_open_probe @33 + jtagcore_get_pin_id @34 + + jtagcore_i2c_set_scl_pin @100 + jtagcore_i2c_set_sda_pin @101 + jtagcore_i2c_write_read @102 + + jtagcore_spi_set_cs_pin @200 + jtagcore_spi_set_clk_pin @201 + jtagcore_spi_set_miso_pin @202 + jtagcore_spi_set_mosi_pin @203 + jtagcore_spi_write_read @204 + jtagcore_spi_set_bitorder @205 + + jtagcore_mdio_set_mdio_pin @300 + jtagcore_mdio_set_mdc_pin @301 + jtagcore_mdio_read @302 + jtagcore_mdio_write @303 + + jtagcore_memory_clear_pins @400 + jtagcore_memory_set_address_pin @401 + jtagcore_memory_set_data_pin @402 + jtagcore_memory_set_ctrl_pin @403 + jtagcore_memory_read @404 + jtagcore_memory_write @405 + + jtagcore_setEnvVar @500 + jtagcore_getEnvVar @501 + jtagcore_getEnvVarValue @502 + jtagcore_getEnvVarIndex @503 + + jtagcore_execScriptLine @600 + jtagcore_execScriptFile @601 + jtagcore_execScriptRam @602 + jtagcore_savePinsStateScript @603 + jtagcore_initScript @604 + jtagcore_setScriptOutputFunc @605 + jtagcore_deinitScript @606 diff --git a/lib_jtag_core/src/os_interface/win32/libjtagcore.rc b/lib_jtag_core/src/os_interface/win32/libjtagcore.rc new file mode 100644 index 0000000..84de267 --- /dev/null +++ b/lib_jtag_core/src/os_interface/win32/libjtagcore.rc @@ -0,0 +1,107 @@ +//Microsoft Developer Studio generated resource script. +// +#include "../../version.h" + +#define FILE_VERSION VDIG1,VDIG2,VDIG3,VDIG4 +#define STR_FILE_VERSION vxstr(VDIG1) "." vxstr(VDIG2) "." vxstr(VDIG3) "." vxstr(VDIG4) + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Language resources + +#if !defined(AFX_RESOURCE_DLL) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION FILE_VERSION + PRODUCTVERSION FILE_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040c04b0" + BEGIN + VALUE "Comments", "lib jtag core " STR_FILE_VERSION " Release : " STR_DATE " Build : " __DATE__ " " __TIME__ "\0" + VALUE "CompanyName", "(c) Viveris\0" + VALUE "FileDescription", "jtag boundary scanner core\0" + VALUE "FileVersion", STR_FILE_VERSION "\0" + VALUE "InternalName", "libjtagcore.dll\0" + VALUE "LegalCopyright", "Copyright © 2023\0" + VALUE "LegalTrademarks", "(c) Viveris\0" + VALUE "OriginalFilename", "libjtagcore.dll\0" + VALUE "ProductName", "jtag-boundary-scanner\0" + VALUE "ProductVersion", STR_FILE_VERSION "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x40c, 1200 + END +END + +#endif // !_MAC + +#endif +///////////////////////////////////////////////////////////////////////////// + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/lib_jtag_core/src/os_interface/win32/stdint.h b/lib_jtag_core/src/os_interface/win32/stdint.h new file mode 100644 index 0000000..e0fb19f --- /dev/null +++ b/lib_jtag_core/src/os_interface/win32/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +/*#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif*/ + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/lib_jtag_core/src/script/env.c b/lib_jtag_core/src/script/env.c new file mode 100644 index 0000000..1953066 --- /dev/null +++ b/lib_jtag_core/src/script/env.c @@ -0,0 +1,563 @@ +/* + * JTAG Boundary Scanner + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Boundary Scanner 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 3.0 of the License, or (at your option) any later version. + * + * JTAG Boundary Scanner 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 version 3 for more details. + * + * You should have received a copy of the GNU General Public License + * along with JTAG Boundary Scanners; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file env.c +* @brief Internal variables support. +* @author Jean-François DEL NERO +*/ + +#include +#include +#include +#include + +#include "env.h" + +/* +|L|H|str varname\0|L|H|str vardata\0|L|H|str varname\0|L|H|str vardata\0|0|0| + +(H*256)+L = str size (\0 included) +if L & H == 0 -> end of buffer +*/ + +static int stringcopy(char * dst, char * src, unsigned int maxsize) +{ + int s; + + if( !dst || (maxsize <= 0)) + return 0; + + if( !src ) + { + *dst = '\0'; + return 1; + } + + s = 0; + while( *src && s < (maxsize - 1)) + { + *dst++ = *src++; + s++; + } + + *dst = '\0'; + s++; + + return s; +} + +static uint16_t getEnvStrSize(unsigned char * buf) +{ + uint16_t size; + + size = *buf++; + size += (((uint16_t)*buf)<<8); + + return size; +} + +static void setEnvStrSize(unsigned char * buf, uint16_t size) +{ + *buf++ = size & 0xFF; + *buf = (size >> 8) & 0xFF; + + return; +} + +static int getEnvEmptyOffset(envvar_entry * env) +{ + int off; + unsigned short varname_size, vardata_size; + + off = 0; + + varname_size = getEnvStrSize(&env->buf[off]); // var name string size + vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size + + while( varname_size ) + { + off += (2 + varname_size + 2 + vardata_size); + + varname_size = getEnvStrSize(&env->buf[off]); // var name string size + vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size + } + + return off; +} + +static int getEnvBufOff(envvar_entry * env, char * varname) +{ + unsigned short curstr_size; + int str_index,i; + + i = 0; + + str_index = 0; + curstr_size = getEnvStrSize(&env->buf[i]); + i += 2; + + while( curstr_size ) + { + if( !(str_index & 1) ) // variable name ? + { + if( !strcmp((char*)&env->buf[i],varname ) ) + { + // this is the variable we are looking for. + return (i - 2); + } + else + { + // not the right variable - skip this string. + i += curstr_size; + } + } + else + { + //variable data - skip this string. + i += curstr_size; + } + + if( i < env->bufsize - 2 ) + { + curstr_size = getEnvStrSize(&env->buf[i]); + i += 2; + } + else + { + curstr_size = 0; + } + + str_index++; + } + + return -1; // Not found. +} + +static int pushStr(envvar_entry * env, int offset, char * str) +{ + int size; + + if(!str || offset < 0) + return -1; + + size = strlen(str) + 1; + if(size > 0xFFFF) + return -1; + + if( ( offset + 2 + size ) < env->bufsize ) + { + setEnvStrSize(&env->buf[offset], size); + offset += 2; + stringcopy((char*)&env->buf[offset], str, size); + offset += size; + + return offset; + } + + return -1; +} + +#ifndef STATIC_ENV_BUFFER +static envvar_entry * realloc_env_buffer(envvar_entry * env, unsigned int size) +{ + unsigned int tmp_bufsize; + unsigned char * tmpbuf; + + if( !env ) + { + env = malloc( sizeof(envvar_entry) ); + if(!env) + return NULL; + + memset( env,0,sizeof(envvar_entry)); + } + + tmp_bufsize = size; + + if( tmp_bufsize & (ENV_PAGE_SIZE - 1) ) + { + tmp_bufsize = (tmp_bufsize & (~(ENV_PAGE_SIZE - 1))) + ENV_PAGE_SIZE; + } + + if( tmp_bufsize > ENV_MAX_TOTAL_BUFFER_SIZE ) + { + return env; + } + + if( env->bufsize != tmp_bufsize ) + { + tmpbuf = realloc(env->buf, tmp_bufsize); + if(tmpbuf) + { + if( env->bufsize < tmp_bufsize ) + memset(&tmpbuf[env->bufsize], 0, tmp_bufsize - env->bufsize ); + + env->bufsize = tmp_bufsize; + env->buf = tmpbuf; + } + } + + return env; +} +#endif + +static int pushEnvEntry(envvar_entry * env, char * varname, char * vardata) +{ + unsigned int total_size; + int varname_len,vardata_len; + int offset; + + if(!varname || !vardata) + return -1; + + varname_len = strlen(varname) + 1; + vardata_len = strlen(vardata) + 1; + + if( varname_len > ENV_MAX_STRING_SIZE || vardata_len > ENV_MAX_STRING_SIZE) + { + return -2; + } + + total_size = 2 + varname_len + 2 + vardata_len; + + offset = getEnvEmptyOffset(env); + if( offset < 0 ) + { + return -1; + } + +#ifndef STATIC_ENV_BUFFER + realloc_env_buffer(env, offset + total_size + 4); +#endif + + if( (total_size + offset) < env->bufsize ) + { + offset = pushStr(env, offset, varname); + offset = pushStr(env, offset, vardata); + + return offset; + } + + return -1; +} + +int setEnvVarDat( envvar_entry * env, char * varname, char * vardata ) +{ + int i,off,ret; + unsigned short varname_size, vardata_size; + int varname_len, vardata_len; + int oldentrysize; + + ret = 0; + + if(!env) + return -1; + + i = 0; + + varname_len = 0; + vardata_len = 0; + + if( !varname ) + return -1; + + varname_len = strlen(varname); + + if( vardata ) + vardata_len = strlen(vardata); + + if( varname_len > ENV_MAX_STRING_SIZE || vardata_len > ENV_MAX_STRING_SIZE) + { + return -1; + } + + off = getEnvBufOff( env, varname ); + if( off >= 0 ) + { + varname_size = getEnvStrSize(&env->buf[off]); // var name string size + vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size + + oldentrysize = 2 + varname_size + 2 + vardata_size; + + if(vardata) + { + vardata_len = strlen(vardata); + if( vardata_len + 1 > 0xFFFF ) + return -1; + + if( vardata_len + 1 > vardata_size ) + { + // add new entry, and pack the strings + ret = pushEnvEntry(env, varname, vardata); + if( ret > 0 ) + { + unsigned char byte; + for(i=0;ibufsize - (off + oldentrysize);i++) + { + byte = env->buf[off + i + oldentrysize]; + env->buf[off + i + oldentrysize] = '\0'; + env->buf[off + i] = byte; + } + } + } + else + { + vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size + if(vardata_size) + { + memset((char*)&env->buf[off + 2 + varname_size + 2], 0, vardata_size ); + stringcopy( (char*)&env->buf[off + 2 + varname_size + 2], vardata, vardata_size); + } + } + } + else + { + // unset variable + unsigned char byte; + for(i=0;ibufsize - (off + oldentrysize);i++) + { + byte = env->buf[off + i + oldentrysize]; + env->buf[off + i + oldentrysize] = '\0'; + env->buf[off + i] = byte; + } + } + } + else + { + if(vardata) + { + // New variable + ret = pushEnvEntry(env, varname, vardata); + } + } + + return ret; +} + +char * getEnvVarDat( envvar_entry * env, char * varname, char * vardata, int maxsize) +{ + int off; + unsigned short varname_size, vardata_size; + + envvar_entry * tmp_envvars; + + tmp_envvars = (envvar_entry *)env; + if(!tmp_envvars) + return NULL; + + off = getEnvBufOff( env, varname ); + if( off >= 0 ) + { + varname_size = getEnvStrSize(&env->buf[off]); // var name string size + vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size + + if( varname_size>0 && vardata_size>0) + { + if(vardata) + { + stringcopy(vardata, (char*)&env->buf[off + 2 + varname_size + 2], maxsize); + } + + return (char*)&env->buf[off + 2 + varname_size + 2]; + } + } + + return NULL; +} + +env_var_value getEnvVarValue( envvar_entry * env, char * varname) +{ + env_var_value value; + char * str_return; + + value = 0; + + if(!varname) + return 0; + + str_return = getEnvVarDat( env, varname, NULL, 0); + + if(str_return) + { + if( strlen(str_return) > 2 ) + { + if( str_return[0]=='0' && ( str_return[1]=='x' || str_return[1]=='X')) + { + value = (env_var_value)STRTOVALUE(str_return, NULL, 0); + } + else + { + value = atoi(str_return); + } + } + else + { + value = atoi(str_return); + } + } + + return value; +} + +int setEnvVarValue( envvar_entry * env, char * varname, env_var_value value) +{ + char tmp_str[128]; + + tmp_str[128 - 1] = 0; + + snprintf(tmp_str,sizeof(tmp_str) - 1, "%d",value); + + return setEnvVarDat( env, varname, tmp_str ); +} + +char * getEnvVarDatIndex( envvar_entry * env, int index, char * vardata, int maxsize) +{ + int str_index, off; + unsigned short varname_size, vardata_size; + + off = 0; + + str_index = 0; + + varname_size = getEnvStrSize(&env->buf[off]); // var name string size + vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size + + while( varname_size ) + { + if( str_index == index ) + { + if( varname_size>0 && vardata_size>0) + { + if(vardata) + { + stringcopy(vardata,(char*)&env->buf[off + 2 + varname_size + 2], maxsize); + } + + return (char*)&env->buf[off + 2]; + } + } + + off += (2 + varname_size + 2 + vardata_size); + + varname_size = getEnvStrSize(&env->buf[off]); // var name string size + vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size + + str_index++; + } + + return NULL; // Not found. +} + +envvar_entry * initEnv(envvar_entry * src, envvar_entry * dst) +{ + if( !dst ) + { +#ifdef STATIC_ENV_BUFFER + return NULL; +#else + dst = malloc( sizeof(envvar_entry) ); + if(!dst) + return NULL; + + memset( dst, 0, sizeof(envvar_entry) ); + + if( src ) + dst->bufsize = src->bufsize; + else + dst->bufsize = ENV_PAGE_SIZE; + + dst->buf = malloc(dst->bufsize); + if(!dst->buf) + { + free(dst); + return NULL; + } + + if( src ) + memcpy( dst->buf, src->buf, src->bufsize ); + else + memset( dst->buf, 0, dst->bufsize ); + + return dst; +#endif + } + else + { +#ifdef STATIC_ENV_BUFFER + + memset( dst, 0, sizeof(envvar_entry) ); + dst->bufsize = ENV_PAGE_SIZE; + if(src) + { + memcpy( dst->buf, src->buf, dst->bufsize ); + } + else + { + memset( dst->buf, 0, dst->bufsize ); + } + + return dst; +#else + free(dst->buf); + + dst->buf = NULL; + + if( src ) + dst->bufsize = src->bufsize; + else + dst->bufsize = ENV_PAGE_SIZE; + + dst->buf = malloc(dst->bufsize); + if(!dst->buf) + { + dst->bufsize = 0; + return NULL; + } + + if(src) + { + memcpy( dst->buf, src->buf, dst->bufsize ); + } + else + { + memset( dst->buf, 0, dst->bufsize ); + } + + return dst; +#endif + } + + return NULL; +} + +void deinitEnv(envvar_entry * env) +{ +#ifndef STATIC_ENV_BUFFER + if(!env) + return; + + free(env->buf); + + free(env); +#else + memset(env,0,sizeof(envvar_entry)); +#endif + return; +} diff --git a/lib_jtag_core/src/script/env.h b/lib_jtag_core/src/script/env.h new file mode 100644 index 0000000..311074e --- /dev/null +++ b/lib_jtag_core/src/script/env.h @@ -0,0 +1,60 @@ +/* + * JTAG Boundary Scanner + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Boundary Scanner 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 3.0 of the License, or (at your option) any later version. + * + * JTAG Boundary Scanner 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 version 3 for more details. + * + * You should have received a copy of the GNU General Public License + * along with JTAG Boundary Scanners; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file env.h +* @brief Internal variables support header file. +* @author Jean-François DEL NERO +*/ +#ifdef SCRIPT_64BITS_SUPPORT +#define env_var_value uint64_t +#define signed_env_var_value int64_t +#define STRTOVALUE strtoull +#else +#define env_var_value uint32_t +#define signed_env_var_value int32_t +#define STRTOVALUE strtoul +#endif + +//#define STATIC_ENV_BUFFER 1 +#define ENV_PAGE_SIZE (16*1024) +#define ENV_MAX_TOTAL_BUFFER_SIZE (1024 * 1024) // 1MB +#define ENV_MAX_STRING_SIZE 512 + +typedef struct envvar_entry_ +{ +#ifdef STATIC_ENV_BUFFER + unsigned char buf[ENV_PAGE_SIZE]; +#else + unsigned char * buf; +#endif + unsigned int bufsize; +}envvar_entry; + +envvar_entry * initEnv( envvar_entry * src, envvar_entry * dst ); + +int setEnvVarDat( envvar_entry * env, char * varname, char * vardata ); +int setEnvVarValue( envvar_entry * env, char * varname, env_var_value value ); + +char * getEnvVarDat( envvar_entry * env, char * varname, char * vardata, int maxsize ); +env_var_value getEnvVarValue( envvar_entry * env, char * varname ); + +char * getEnvVarDatIndex( envvar_entry * env, int index, char * vardata, int maxsize ); + +void deinitEnv( envvar_entry * env ); diff --git a/lib_jtag_core/src/script/script.c b/lib_jtag_core/src/script/script.c new file mode 100644 index 0000000..0c14188 --- /dev/null +++ b/lib_jtag_core/src/script/script.c @@ -0,0 +1,2658 @@ +/* + * JTAG Core library + * Copyright (c) 2008 - 2024 Viveris Technologies + * + * JTAG Core library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * JTAG Core library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with JTAG Core library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file script.c +* @brief Script engine. +* @author Jean-François DEL NERO +*/ + +#include +#include +#include + +#include + +#define MAX_PATH 256 + +#include "../drivers/drv_loader.h" +#include "../jtag_core_internal.h" +#include "script.h" +#include "../jtag_core.h" +#include "../version.h" + +#include "../bsdl_parser/bsdl_loader.h" +#include "../os_interface/os_interface.h" + +#include "env.h" + +#ifndef _script_cmd_func_ +typedef int (* CMD_FUNC)( script_ctx * ctx, char * line); +#define _script_cmd_func_ +#endif + +typedef struct cmd_list_ +{ + char * command; + CMD_FUNC func; +}cmd_list; + +typedef struct label_list_ +{ + char * label; + unsigned int file_offset; +}label_list; + +extern cmd_list script_commands_list[]; + +static int dummy_script_printf(void * ctx, int MSGTYPE, char * string, ... ) +{ + return 0; +} + +static int is_end_line(char c) +{ + if( c == 0 || c == '#' || c == '\r' || c == '\n' ) + { + return 1; + } + else + { + return 0; + } +} + +static int is_space(char c) +{ + if( c == ' ' || c == '\t' ) + { + return 1; + } + else + { + return 0; + } +} + +static int is_label(char * command) +{ + int i; + + i = 0; + while(command[i]) + { + i++; + } + + if(i>1) + { + if(command[i - 1] == ':') + return 1; + } + + return 0; +} + +static int is_variable(char * command) +{ + if(strlen(command)>1) + { + if(command[0] == '$' && command[1] && ( command[1] != ' ' || command[1] != '\t' )) + return 1; + else + return 0; + } + + return 0; +} + +static int get_next_word(char * line, int offset) +{ + while( !is_end_line(line[offset]) && ( line[offset] == ' ' || line[offset] == '\t' ) ) + { + offset++; + } + + return offset; +} + +static int copy_param(char * dest, char * line, int offs) +{ + int i,insidequote; + + i = 0; + insidequote = 0; + while( !is_end_line(line[offs]) && ( insidequote || !is_space(line[offs]) ) && (i < (DEFAULT_BUFLEN - 1)) ) + { + if(line[offs] != '"') + { + if(dest) + dest[i] = line[offs]; + + i++; + } + else + { + if(insidequote) + insidequote = 0; + else + insidequote = 1; + } + + offs++; + } + + if(dest) + dest[i] = 0; + + return offs; +} + +static int get_param_offset(char * line, int param) +{ + int param_cnt, offs; + + offs = 0; + offs = get_next_word(line, offs); + + if( param ) + { + param_cnt = 0; + do + { + offs = copy_param(NULL, line, offs); + + offs = get_next_word( line, offs ); + + if(line[offs] == 0 || line[offs] == '#' || line[offs] == '\r' || line[offs] == '\n') + return -1; + + param_cnt++; + }while( param_cnt < param ); + } + + return offs; +} + +static int get_param( script_ctx * ctx, char * line, int param_offset,char * param) +{ + int offs; + char var_str[DEFAULT_BUFLEN]; + + offs = get_param_offset(line, param_offset); + + if(offs>=0) + { + if(line[offs] != '$') + { + offs = copy_param(param, line, offs); + } + else + { + copy_param(var_str, line, offs); + + if(!strcmp(var_str,"$LASTDATA")) + { + sprintf(param,"0x"LONGHEXSTR,ctx->last_data_value); + return 1; + } + + if(!strcmp(var_str,"$LASTFLAGS")) + { + sprintf(param,"0x%X",ctx->last_flags); + return 1; + } + + if(!strcmp(var_str,"$LASTERROR")) + { + sprintf(param,"%d",ctx->last_error_code); + return 1; + } + + if( !getEnvVarDat( (envvar_entry *)ctx->env, (char*)&var_str[1], param, DEFAULT_BUFLEN) ) + { + copy_param(param, line, offs); + } + } + + return 1; + } + + return -1; +} + +static int get_param_str( script_ctx * ctx, char * line, int param_offset,char * param) +{ + int offs; + + offs = get_param_offset(line, param_offset); + + if(offs>=0) + { + offs = copy_param(param, line, offs); + + return 1; + } + + return -1; +} + +env_var_value strbin_to_val( char * str ) +{ + int l; + env_var_value val; + env_var_value mask; + + val = 0; + + // -> end of the string + l = 0; + while(str[l]) + { + l++; + } + + // -> find the lowest bit + while(l) + { + if( str[l] == '1' || str[l] == '0' ) + { + break; + } + l--; + }; + + mask = 0x1; + // convert + while(l >= 0) + { + if( str[l] != '1' && str[l] != '0' ) + { + break; + } + + if( str[l] == '1') + { + val |= mask; + } + + mask <<= 1; + + l--; + } + + return val; +} + +static env_var_value str_to_int(char * str) +{ + env_var_value value; + + value = 0; + + if(str) + { + if( strlen(str) > 2 ) + { + if( str[0]=='0' ) + { + switch( str[1] ) + { + // hex + case 'x': + case 'X': + value = (env_var_value)STRTOVALUE(str, NULL, 0); + break; + + // binary + case 'b': + case 'B': + value = strbin_to_val(str); + break; + + // decimal + default: + value = atoi(str); + break; + } + } + else + { + value = atoi(str); + } + } + else + { + value = atoi(str); + } + } + + return value; +} + +static env_var_value get_script_variable( script_ctx * ctx, char * varname) +{ + env_var_value value; + + if(!strcmp(varname,"$LASTDATA")) + { + return ctx->last_data_value; + } + + if(!strcmp(varname,"$LASTFLAGS")) + { + return ctx->last_flags; + } + + if(!strcmp(varname,"$LASTERROR")) + { + return (env_var_value)(ctx->last_error_code); + } + + if(varname[0] == '$') + value = getEnvVarValue( (envvar_entry *)ctx->env, (char*)&varname[1]); + else + value = str_to_int((char*)varname); + + return value; +} + +static void set_script_variable( script_ctx * ctx, char * varname, env_var_value value) +{ + char tmp_str[64]; + + if(!strcmp(varname,"$LASTDATA")) + { + ctx->last_data_value = value; + + return; + } + + if(!strcmp(varname,"$LASTFLAGS")) + { + ctx->last_flags = value; + + return; + } + + if(!strcmp(varname,"$LASTERROR")) + { + ctx->last_error_code = value; + + return; + } + + if(varname[0] == '$' && varname[1]) + { + sprintf(tmp_str,"0x"LONGHEXSTR,value); + setEnvVarDat( (envvar_entry *)ctx->env, (char*)&varname[1], tmp_str ); + + return; + } +} + +script_ctx * init_script(void * app_ctx, unsigned int flags, void * env) +{ + script_ctx * ctx; + + ctx = malloc(sizeof(script_ctx)); + if(ctx) + { + memset(ctx,0,sizeof(script_ctx)); + + ctx->env = env; + + setOutputFunc_script( ctx, dummy_script_printf ); + + ctx->app_ctx = (void*)app_ctx; + ctx->cur_label_index = 0; + + ctx->cmdlist = (void*)script_commands_list; + + ctx->script_file = NULL; + } + + return ctx; +} + +static int extract_cmd( script_ctx * ctx, char * line, char * command) +{ + int offs,i; + + i = 0; + offs = 0; + + offs = get_next_word(line, offs); + + if( !is_end_line(line[offs]) ) + { + while( !is_end_line(line[offs]) && !is_space(line[offs]) && i < (DEFAULT_BUFLEN - 1) ) + { + command[i] = line[offs]; + offs++; + i++; + } + + command[i] = 0; + + return i; + } + + return 0; +} + +static int exec_cmd( script_ctx * ctx, char * command,char * line) +{ + int i; + cmd_list * cmdlist; + + cmdlist = (cmd_list*)ctx->cmdlist; + + i = 0; + while(cmdlist[i].func) + { + if( !strcmp(cmdlist[i].command,command) ) + { + return cmdlist[i].func(ctx,line); + } + + i++; + } + + return JTAG_CORE_CMD_NOT_FOUND; +} + +static int add_label( script_ctx * ctx, char * label ) +{ + int i,j; + char tmp_label[MAX_LABEL_SIZE]; + + if(ctx->cur_label_index < MAX_LABEL) + { + i = 0; + while(i<(MAX_LABEL_SIZE - 1) && label[i] && label[i] != ':') + { + tmp_label[i] = label[i]; + i++; + } + tmp_label[i] = 0; + + i = 0; + while(icur_label_index) + { + if( !strcmp( tmp_label, ctx->labels[i].label_name ) ) + { + break; + } + i++; + } + + j = i; + + i = 0; + while(i<(MAX_LABEL_SIZE - 1) && label[i]) + { + ctx->labels[j].label_name[i] = tmp_label[i]; + i++; + } + + ctx->labels[j].label_name[i] = 0; + ctx->labels[j].offset = ctx->cur_script_offset; + + if(ctx->cur_label_index == j) + { + ctx->cur_label_index++; + } + } + return 0; +} + +static int goto_label( script_ctx * ctx, char * label ) +{ + int i; + char tmp_label[MAX_LABEL_SIZE]; + + i = 0; + while(i<(MAX_LABEL_SIZE - 1) && label[i] && label[i] != ':') + { + tmp_label[i] = label[i]; + i++; + } + tmp_label[i] = 0; + + i = 0; + while(icur_label_index) + { + if( !strcmp( tmp_label, ctx->labels[i].label_name ) ) + { + break; + } + i++; + } + + if( i != ctx->cur_label_index) + { + ctx->cur_script_offset = ctx->labels[i].offset; + + if(ctx->script_file) + fseek(ctx->script_file,ctx->cur_script_offset,SEEK_SET); + + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Label %s not found\n", tmp_label ); + + return JTAG_CORE_NOT_FOUND; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +static int alu_operations( script_ctx * ctx, char * line) +{ + int i; + int valid; + env_var_value data_value; + env_var_value value_1,value_2; + + char params_str[5][DEFAULT_BUFLEN]; + + for(i=0;i<5;i++) + { + params_str[i][0] = 0; + } + + valid = 0; + for(i=0;i<5;i++) + { + get_param_str( ctx, line, i, (char*)¶ms_str[i] ); + if(strlen((char*)¶ms_str[i])) + valid++; + } + + data_value = 0; + if( ( (valid == 3) || (valid == 5) ) && params_str[1][0] == '=' && params_str[0][0] == '$') + { + value_1 = get_script_variable( ctx, params_str[2]); + + if(valid == 5) + { + value_2 = get_script_variable( ctx, params_str[4]); + + if(!strcmp(params_str[3],"+")) + data_value = value_1 + value_2; + + if(!strcmp(params_str[3],"-")) + data_value = value_1 - value_2; + + if(!strcmp(params_str[3],"*")) + data_value = value_1 * value_2; + + if(!strcmp(params_str[3],"/") && value_2) + data_value = value_1 / value_2; + + if(!strcmp(params_str[3],"&")) + data_value = value_1 & value_2; + + if(!strcmp(params_str[3],"^")) + data_value = value_1 ^ value_2; + + if(!strcmp(params_str[3],"|")) + data_value = value_1 | value_2; + + if(!strcmp(params_str[3],">>")) + data_value = value_1 >> value_2; + + if(!strcmp(params_str[3],"<<")) + data_value = value_1 << value_2; + } + else + { + data_value = value_1; + } + + if(data_value) + ctx->last_flags = 1; + else + ctx->last_flags = 0; + + set_script_variable( ctx, (char*)¶ms_str[0], data_value); + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +void setOutputFunc_script( script_ctx * ctx, SCRIPT_PRINTF_FUNC ext_printf ) +{ + ctx->script_printf = ext_printf; + + return; +} + +int execute_line_script( script_ctx * ctx, char * line ) +{ + char command[DEFAULT_BUFLEN]; + + command[0] = 0; + + if( extract_cmd(ctx, line, command) ) + { + if(strlen(command)) + { + if(!is_label(command)) + { + if(!ctx->dry_run) + { + if(!is_variable(command)) + { + ctx->last_error_code = exec_cmd(ctx,command,line); + + if( ctx->last_error_code == JTAG_CORE_CMD_NOT_FOUND ) + { + ctx->script_printf( ctx, MSG_ERROR, "Command not found ! : %s\n", line ); + + return ctx->last_error_code; + } + } + else + { + ctx->last_error_code = alu_operations(ctx,line); + } + } + else + ctx->last_error_code = JTAG_CORE_NO_ERROR; + } + else + { + add_label(ctx,command); + + ctx->last_error_code = JTAG_CORE_NO_ERROR; + } + + return ctx->last_error_code; + } + } + + ctx->last_error_code = JTAG_CORE_BAD_CMD; + + return ctx->last_error_code; +} + +int execute_file_script( script_ctx * ctx, char * filename ) +{ + int err; + char line[DEFAULT_BUFLEN]; + + err = JTAG_CORE_INTERNAL_ERROR; + + ctx->script_file = fopen(filename,"r"); + if(ctx->script_file) + { + strncpy(ctx->script_file_path,filename,DEFAULT_BUFLEN - 1); + ctx->script_file_path[DEFAULT_BUFLEN-1] = 0; + + // Dry run -> populate the labels... + ctx->dry_run++; + do + { + if(!fgets(line,sizeof(line),ctx->script_file)) + break; + + ctx->cur_script_offset = ftell(ctx->script_file); + + if(feof(ctx->script_file)) + break; + + execute_line_script(ctx, line); + }while(1); + + fseek(ctx->script_file,0,SEEK_SET); + ctx->cur_script_offset = ftell(ctx->script_file); + + ctx->dry_run--; + if(!ctx->dry_run) + { + if(strlen(ctx->pre_command)) + { + err = execute_line_script(ctx, ctx->pre_command); + if(err != JTAG_CORE_NO_ERROR) + { + fclose(ctx->script_file); + return err; + } + } + + do + { + if(!fgets(line,sizeof(line),ctx->script_file)) + break; + + ctx->cur_script_offset = ftell(ctx->script_file); + + if(feof(ctx->script_file)) + break; + + err = execute_line_script(ctx, line); + }while(1); + } + + fclose(ctx->script_file); + + err = JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Can't open %s !", filename ); + ctx->script_file_path[0] = 0; + + err = JTAG_CORE_ACCESS_ERROR; + } + + return err; +} + +int execute_ram_script( script_ctx * ctx, unsigned char * script_buffer, int buffersize ) +{ + int err = 0; + int buffer_offset,line_offset; + char line[DEFAULT_BUFLEN]; + int cont; + + ctx->dry_run++; + cont = 1; + + while( cont ) + { + buffer_offset = 0; + line_offset = 0; + ctx->cur_script_offset = 0; + + do + { + memset(line,0,DEFAULT_BUFLEN); + line_offset = 0; + while( (buffer_offset < buffersize) && script_buffer[buffer_offset] && script_buffer[buffer_offset]!='\n' && script_buffer[buffer_offset]!='\r' && (line_offset < DEFAULT_BUFLEN - 1)) + { + line[line_offset++] = script_buffer[buffer_offset++]; + } + + while( (buffer_offset < buffersize) && script_buffer[buffer_offset] && (script_buffer[buffer_offset]=='\n' || script_buffer[buffer_offset]=='\r') ) + { + buffer_offset++; + } + + ctx->cur_script_offset = buffer_offset; + + execute_line_script(ctx, line); + + buffer_offset = ctx->cur_script_offset; + + if( (buffer_offset >= buffersize) || !script_buffer[buffer_offset]) + break; + + }while(buffer_offset < buffersize); + + if( !ctx->dry_run || (ctx->dry_run > 1) ) + { + cont = 0; + } + else + { + ctx->dry_run = 0; + + if(strlen(ctx->pre_command)) + execute_line_script(ctx, ctx->pre_command); + } + } + + return err; +} + +script_ctx * deinit_script(script_ctx * ctx) +{ + if(ctx) + { + free(ctx); + } + + ctx = NULL; + + return ctx; +} + +/////////////////////////////////////////////////////////////////////////////// +///////////////////// Generic commands/operations ///////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +static int cmd_goto( script_ctx * ctx, char * line) +{ + int i; + char label_str[DEFAULT_BUFLEN]; + + i = get_param( ctx, line, 1, label_str ); + + if(i>=0) + { + return goto_label( ctx, label_str ); + } + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_if( script_ctx * ctx, char * line) +{ + //"if" command example : + // if $VARIABLE > 0x2222 then goto label + + int i; + int eval; + int ret; + int valid; + char params_str[5][DEFAULT_BUFLEN]; + env_var_value value_1,value_2,tmp_val; + int op_offset; + + ret = JTAG_CORE_BAD_PARAMETER; + + eval = 0; + + for(i=0;i<5;i++) + { + params_str[i][0] = 0; + } + + valid = 0; + for(i=0;i<5;i++) + { + get_param( ctx, line, i, (char*)¶ms_str[i] ); + if(strlen((char*)¶ms_str[i])) + valid++; + } + + i = 0; + while( i < 5 && strcmp((char*)¶ms_str[i],"then") ) + { + i++; + } + + if( i < 5 ) + { + if( i == 2) + { + value_1 = get_script_variable( ctx, params_str[1]); + + if(value_1) + eval = 1; + + ret = JTAG_CORE_NO_ERROR; + } + + if ( i == 4 ) + { + value_1 = get_script_variable( ctx, params_str[1]); + value_2 = get_script_variable( ctx, params_str[3]); + + if(!strcmp((char*)¶ms_str[2],">=") && ( (signed_env_var_value)value_1 >= (signed_env_var_value)value_2 ) ) + eval = 1; + + if(!strcmp((char*)¶ms_str[2],"<=") && ( (signed_env_var_value)value_1 <= (signed_env_var_value)value_2 ) ) + eval = 1; + + if(!strcmp((char*)¶ms_str[2],">") && ( (signed_env_var_value)value_1 > (signed_env_var_value)value_2 ) ) + eval = 1; + + if(!strcmp((char*)¶ms_str[2],"<") && ( (signed_env_var_value)value_1 < (signed_env_var_value)value_2 ) ) + eval = 1; + + if(!strcmp((char*)¶ms_str[2],"==") && ( value_1 == value_2 ) ) + eval = 1; + + if(!strcmp((char*)¶ms_str[2],"!=") && ( value_1 != value_2 ) ) + eval = 1; + + if(!strcmp((char*)¶ms_str[2],"&") && ( value_1 & value_2 ) ) + eval = 1; + + if(!strcmp((char*)¶ms_str[2],"^") && ( value_1 ^ value_2 ) ) + eval = 1; + + if(!strcmp((char*)¶ms_str[2],"|") && ( value_1 | value_2 ) ) + eval = 1; + + tmp_val = value_1 >> value_2; + if(!strcmp((char*)¶ms_str[2],">>") && tmp_val ) + eval = 1; + + tmp_val = value_1 << value_2; + if(!strcmp((char*)¶ms_str[2],"<<") && tmp_val ) + eval = 1; + + ret = JTAG_CORE_NO_ERROR; + } + + if( eval ) + { + op_offset = get_param_offset(line, i + 1); + + if(op_offset >= 0) + { + ret = execute_line_script( ctx, (char*)&line[op_offset] ); + } + } + + return ret; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_return( script_ctx * ctx, char * line ) +{ + if(ctx->script_file) + { + fseek(ctx->script_file,0,SEEK_END); + } + + return JTAG_CORE_NO_ERROR; +} + +static int cmd_system( script_ctx * ctx, char * line ) +{ + int offs; + int ret; + + offs = get_param_offset(line, 1); + + if(offs>=0) + { + ret = system(&line[offs]); + + if( ret != 1 ) + return JTAG_CORE_NO_ERROR; + else + return JTAG_CORE_NOT_FOUND; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_print_env_var( script_ctx * ctx, char * line ) +{ + int i; + char varname[DEFAULT_BUFLEN]; + char varvalue[DEFAULT_BUFLEN]; + char * ptr; + + i = get_param( ctx, line, 1, varname ); + + if(i>=0) + { + ptr = getEnvVarDat( (envvar_entry *)ctx->env, (char*)&varname, (char*)&varvalue, sizeof(varvalue) ); + if(ptr) + { + ctx->script_printf( ctx, MSG_INFO_1, "%s = %s", varname, varvalue ); + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_NOT_FOUND; + } + else + { + return JTAG_CORE_BAD_PARAMETER; + } +} + +static int cmd_version( script_ctx * ctx, char * line) +{ + ctx->script_printf( ctx, MSG_INFO_0, "Lib version : %s, Date : "__DATE__" "__TIME__"\n", LIB_JTAG_CORE_VERSION ); + + return JTAG_CORE_NO_ERROR; +} + +static int cmd_print( script_ctx * ctx, char * line) +{ + int i,j,s; + char tmp_str[DEFAULT_BUFLEN]; + char str[DEFAULT_BUFLEN*2]; + char * ptr; + + str[0] = '\0'; + + j = 1; + do + { + ptr = NULL; + + i = get_param_offset(line, j); + s = 0; + + if(i>=0) + { + tmp_str[0] = '\0'; + get_param( ctx, line, j, (char *)&tmp_str ); + s = strlen(tmp_str); + if(s) + { + if(tmp_str[0] != '$') + { + genos_strndstcat((char*)str,tmp_str,sizeof(str)); + genos_strndstcat((char*)str," ",sizeof(str)); + str[sizeof(str) - 1] = '\0'; + } + else + { + ptr = getEnvVarDat( (envvar_entry *)ctx->env, &tmp_str[1], NULL, 0); + if( ptr ) + { + genos_strndstcat((char*)str,ptr,sizeof(str)); + genos_strndstcat((char*)str," ",sizeof(str)); + } + else + { + genos_strndstcat((char*)str,tmp_str,sizeof(str)); + genos_strndstcat((char*)str," ",sizeof(str)); + } + str[sizeof(str) - 1] = '\0'; + } + } + } + + j++; + }while(s); + + ctx->script_printf( ctx, MSG_NONE, "%s\n", str ); + + return JTAG_CORE_NO_ERROR; +} + +static int cmd_pause( script_ctx * ctx, char * line) +{ + int i; + char delay_str[DEFAULT_BUFLEN]; + + i = get_param( ctx, line, 1, delay_str ); + + if(i>=0) + { + genos_pause(str_to_int(delay_str)); + + return JTAG_CORE_NO_ERROR; + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_help( script_ctx * ctx, char * line) +{ + int i; + + cmd_list * cmdlist; + + cmdlist = (cmd_list*)ctx->cmdlist; + + ctx->script_printf( ctx, MSG_INFO_0, "Supported Commands :\n\n" ); + + i = 0; + while(cmdlist[i].func) + { + ctx->script_printf( ctx, MSG_NONE, "%s\n", cmdlist[i].command ); + i++; + } + + return JTAG_CORE_NO_ERROR; +} + +static int cmd_call( script_ctx * ctx, char * line ) +{ + int offs; + char path[DEFAULT_BUFLEN]; + char function[DEFAULT_BUFLEN]; + script_ctx * new_ctx; + int ret; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + path[0] = '\0'; + get_param( ctx, line, 1, (char*)&path ); + + offs = get_param_offset(line, 1); + + if(offs>=0) + { + + ret = JTAG_CORE_INTERNAL_ERROR; + + new_ctx = init_script((void*)jc,0x00000000,(void*)jc->envvar); + if(new_ctx) + { + new_ctx->script_printf = ctx->script_printf; + + function[0] = '\0'; + get_param( ctx, line, 2, (char*)&function ); + + if(!strcmp(path,".")) + { + if(strlen(function)) + { + snprintf(new_ctx->pre_command,sizeof(new_ctx->pre_command),"goto %s",function); + + ret = execute_file_script( new_ctx, (char*)&ctx->script_file_path ); + + new_ctx->pre_command[0] = 0; + + if( ret == JTAG_CORE_ACCESS_ERROR ) + { + ctx->script_printf( ctx, MSG_ERROR, "call : script not found ! : %s\n", path ); + } + } + } + else + { + if(strlen(function)) + { + snprintf(new_ctx->pre_command,sizeof(new_ctx->pre_command),"goto %s",function); + + ret = execute_file_script( new_ctx, (char*)&path ); + + new_ctx->pre_command[0] = 0; + + if( ret == JTAG_CORE_ACCESS_ERROR ) + { + ctx->script_printf( ctx, MSG_ERROR, "call : script/function not found ! : %s %s\n", path,function ); + } + } + else + { + ret = execute_file_script( new_ctx, (char*)&path ); + + if( ret == JTAG_CORE_ACCESS_ERROR ) + { + ctx->script_printf( ctx, MSG_ERROR, "call : script not found ! : %s\n", path ); + } + } + } + + deinit_script(new_ctx); + } + + ctx->last_error_code = ret; + + return ret; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_set_env_var( script_ctx * ctx, char * line ) +{ + int i,j,ret; + char varname[DEFAULT_BUFLEN]; + char varvalue[DEFAULT_BUFLEN]; + + ret = JTAG_CORE_BAD_PARAMETER; + + i = get_param( ctx, line, 1, varname ); + j = get_param( ctx, line, 2, varvalue ); + + if(i>=0 && j>=0) + { + if( setEnvVarDat( (envvar_entry *)ctx->env, (char*)&varname, (char*)&varvalue ) >= 0 ) + { + ret = JTAG_CORE_NO_ERROR; + } + else + ret = JTAG_CORE_MEM_ERROR; + } + + return ret; +} + +static int cmd_rand( script_ctx * ctx, char * line) +{ + int i; + uint32_t seed; + + char rand_seed[DEFAULT_BUFLEN]; + + seed = ctx->rand_seed; + + i = get_param( ctx, line, 1, rand_seed ); + if(i>=0) + { + seed = str_to_int((char*)rand_seed); + } + + /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */ + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + + ctx->rand_seed = seed; + + ctx->last_data_value = seed; + + return JTAG_CORE_NO_ERROR; +} + +int is_valid_hex_quartet(char c) +{ + if( (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') ) + return 1; + else + return 0; +} + +int is_valid_hex_byte(char *str) +{ + if( is_valid_hex_quartet(str[0]) && is_valid_hex_quartet(str[1]) ) + return 1; + else + return 0; +} + +char * arrayresize(char * array, int size, unsigned char c) +{ + int cursize; + char * ptr; + + if( size < 0 ) + return array; + + if(array) + { + if( array[0] == '0' && (array[1] == 'x' || array[1] == 'X') ) + { + ptr = (array + 2); + } + else + { + ptr = (array); + } + } + else + { + array = malloc(DEFAULT_BUFLEN + 1); + if(array) + { + size = DEFAULT_BUFLEN / 2; + memset(array,0,DEFAULT_BUFLEN + 1); + } + + ptr = array; + } + + if(ptr) + { + cursize = 0; + while(is_valid_hex_byte(&ptr[cursize*2])) + { + cursize++; + } + + ptr[cursize*2] = '\0'; + + if( cursize < size ) + { + while( cursize < size ) + { + sprintf(&ptr[(cursize*2) + 0],"%.2X",c); + ptr[(cursize*2) + 2] = '\0'; + cursize++; + } + } + } + + return array; +} + + +static int cmd_initarray( script_ctx * ctx, char * line) +{ + //initarray $VARIABLE_1_TEST $BYTES $VALUE + + int i,j,ret; + char varname[DEFAULT_BUFLEN]; + char varsize[DEFAULT_BUFLEN]; + char varvalue[DEFAULT_BUFLEN]; + char * ptr; + int size; + + ret = JTAG_CORE_BAD_PARAMETER; + + strcpy(varvalue,"0"); + varname[0] = '\0'; + + i = get_param_str( ctx, line, 1, varname ); + j = get_param( ctx, line, 2, varsize ); + get_param( ctx, line, 3, varvalue ); + + if(i>=0 && j>=0) + { + size = str_to_int(varsize); + + if(size >= 0 && strlen(varname) ) + { + ptr = getEnvVarDat( (envvar_entry *)ctx->env,(char*)&varname, NULL, 0); + if(ptr) + { + arrayresize(ptr, size, (unsigned char)(str_to_int((char*)&varvalue)&0xFF)); + } + else + { + ptr = malloc( DEFAULT_BUFLEN ); + if(ptr) + { + memset(ptr,0x00, DEFAULT_BUFLEN); + arrayresize(ptr, size, (unsigned char)(str_to_int((char*)&varvalue)&0xFF)); + } + } + + if(ptr) + setEnvVarDat( (envvar_entry *)ctx->env, (char*)&varname[1], ptr ); + } + ret = JTAG_CORE_NO_ERROR; + } + + return ret; + +} + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////// JTAG commands/operations ////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +static int cmd_autoinit( script_ctx * ctx, char * line) +{ + jtag_core * jc; + int number_of_devices, dev_nb; + int loaded_bsdl; + char szExecPath[MAX_PATH + 1]; + char scanfolder[MAX_PATH + 1]; + char filename[MAX_PATH + 1]; + char entityname[DEFAULT_BUFLEN]; + char file[MAX_PATH + 1]; + + filefoundinfo fileinfo; + void* h_file_find; + + unsigned long chip_id,chip_id_mask; + + jc = (jtag_core *)ctx->app_ctx; + loaded_bsdl = 0; + + // BSDL Auto load : check which bsdl file match with the device + // And load it. + + jtagcore_scan_and_init_chain(jc); + + number_of_devices = jtagcore_get_number_of_devices(jc); + + ctx->script_printf( ctx, MSG_INFO_0, "%d device(s) found\n", number_of_devices ); + + // Get the bsdl_files folder path + + genos_getcurrentdirectory(szExecPath,MAX_PATH); + + strncpy(scanfolder, szExecPath, sizeof(scanfolder) ); + genos_strndstcat(scanfolder, DIR_SEPARATOR"bsdl_files"DIR_SEPARATOR, sizeof(scanfolder) - 1 ); + scanfolder[sizeof(scanfolder) - 1] = '\0'; + + h_file_find = genos_find_first_file( scanfolder, "*.*", &fileinfo ); + + // Scan and check files in the folder. + if (h_file_find) + { + do + { + strcpy(filename,szExecPath); + genos_strndstcat(filename,DIR_SEPARATOR"bsdl_files"DIR_SEPARATOR,sizeof(filename)); + genos_strndstcat(filename,fileinfo.filename,sizeof(filename)); + filename[sizeof(filename) - 1] = '\0'; + + if ( ! fileinfo.isdirectory ) + { + chip_id_mask = 0xFFFFFFFF; + chip_id = jtagcore_get_bsdl_id(jc, filename, &chip_id_mask); + if( chip_id ) + { + for(dev_nb=0;dev_nb < number_of_devices;dev_nb++) + { + if( ( chip_id & chip_id_mask ) == ( jtagcore_get_dev_id(jc, dev_nb) & chip_id_mask ) ) + { + if(jtagcore_get_number_of_pins(jc, dev_nb) > 0) + { + // Device already loaded ! + ctx->script_printf( ctx, MSG_WARNING, "Device %d BSDL already loaded ! ID conflit ?\n", dev_nb ); + } + + // The BSDL ID match with the device. + if(jtagcore_loadbsdlfile(jc, filename, dev_nb) == JTAG_CORE_NO_ERROR) + { + entityname[0] = 0; + jtagcore_get_dev_name(jc, dev_nb, entityname, file); + + ctx->script_printf( ctx, MSG_INFO_0, "Device %d (%.8X - %s) - BSDL Loaded : %s\n", dev_nb, chip_id, entityname, file ); + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "ERROR while loading %s !\n", filename ); + } + } + } + } + } + }while(genos_find_next_file( h_file_find, scanfolder, "*.*", &fileinfo )); + + genos_find_close( h_file_find ); + + loaded_bsdl = 0; + // Count the loaded bsdl + for(dev_nb=0;dev_nb < number_of_devices;dev_nb++) + { + if(jtagcore_get_number_of_pins(jc, dev_nb) > 0) + { + loaded_bsdl++; + } + else + { + ctx->script_printf( ctx, MSG_WARNING, "Device %d (%.8X) - NO BSDL Loaded !\n", dev_nb, jtagcore_get_dev_id(jc, dev_nb ) ); + } + } + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Can't access the bsdl sub folder ! : %s\n", filename ); + return JTAG_CORE_ACCESS_ERROR; + } + + return loaded_bsdl; +} + +static int cmd_init_and_scan( script_ctx * ctx, char * line) +{ + jtag_core * jc; + int ret; + + jc = (jtag_core *)ctx->app_ctx; + + ret = jtagcore_scan_and_init_chain(jc); + + if( ret == JTAG_CORE_NO_ERROR ) + { + ctx->script_printf( ctx, MSG_INFO_0, "JTAG Scan done\n" ); + + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_INFO_0, "JTAG Scan return code : %d\n", ret ); + } + + return ret; +} + +static int cmd_print_nb_dev( script_ctx * ctx, char * line) +{ + jtag_core * jc; + int i; + + jc = (jtag_core *)ctx->app_ctx; + + i = jtagcore_get_number_of_devices(jc); + + ctx->script_printf( ctx, MSG_INFO_0, "%d device(s) found in chain\n", i ); + + ctx->last_data_value = i; + + return JTAG_CORE_NO_ERROR; +} + +static void bsdl_id_str(unsigned long id, char * str) +{ + int i; + + str[0] = 0; + + for (i = 0; i < 32; i++) + { + if ((0x80000000 >> i)&id) + { + strcat(str, "1"); + } + else + { + strcat(str, "0"); + } + if (i == 3) strcat(str, " "); + if (i == 19) strcat(str, " "); + if (i == 30) strcat(str, " "); + } + + str[i] = 0; +} + +static char * get_id_str( script_ctx * ctx, int numberofdevice) +{ + // compare passed device ID to the one returned from the ID command + jtag_core * jc; + int i; + unsigned int idcode = 0; + char * stringbuffer; + char tempstr[DEFAULT_BUFLEN]; + + jc = (jtag_core *)ctx->app_ctx; + + stringbuffer = NULL; + + if( numberofdevice < 0 || numberofdevice > 256) + return NULL; + + stringbuffer = malloc(256 * numberofdevice); + if (stringbuffer) + { + memset(stringbuffer, 0, 256 * numberofdevice); + + // and read the IDCODES + for (i = 0; i < numberofdevice; i++) + { + idcode = jtagcore_get_dev_id(jc, i); + sprintf(tempstr, "Device %d : 0x%.8X - ", i, idcode); + + bsdl_id_str(idcode, &tempstr[strlen(tempstr)]); + + strcat(stringbuffer, tempstr); + strcat(stringbuffer, "\n"); + } + } + + return stringbuffer; +} + +static int cmd_print_devs_list( script_ctx * ctx, char * line) +{ + jtag_core * jc; + int i; + char *ptr; + + jc = (jtag_core *)ctx->app_ctx; + + i = jtagcore_get_number_of_devices(jc); + if(i>0) + { + ptr = get_id_str(ctx,i); + if(ptr) + { + ctx->script_printf( ctx, MSG_INFO_0, "%s\n", ptr ); + free(ptr); + } + } + + return JTAG_CORE_NOT_FOUND; +} + +static int cmd_print_probes_list( script_ctx * ctx, char * line) +{ + jtag_core * jc; + int i,j; + char probe_list[64]; + int nb_of_drivers,nb_of_probes; + + jc = (jtag_core *)ctx->app_ctx; + + nb_of_drivers = jtagcore_get_number_of_probes_drv(jc); + j = 0; + while (j < nb_of_drivers) + { + nb_of_probes = jtagcore_get_number_of_probes(jc, j); + i = 0; + while( i < nb_of_probes ) + { + jtagcore_get_probe_name(jc, PROBE_ID(j,i), probe_list); + ctx->script_printf( ctx, MSG_INFO_0, "ID 0x%.8X : %s\n", PROBE_ID(j,i), probe_list ); + i++; + } + j++; + } + + return JTAG_CORE_NO_ERROR; +} + +static int cmd_open_probe( script_ctx * ctx, char * line) +{ + int ret; + char probe_id[64]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + if(get_param( ctx, line, 1, probe_id )>0) + { + ret = jtagcore_select_and_open_probe(jc, strtoul(probe_id, NULL, 16)); + if(ret != JTAG_CORE_NO_ERROR) + { + ctx->script_printf( ctx, MSG_ERROR, "Code %d !\n", ret ); + return ret; + } + else + { + ctx->script_printf( ctx, MSG_INFO_0, "Probe Ok !\n" ); + return JTAG_CORE_NO_ERROR; + } + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; + } +} + +static int cmd_load_bsdl( script_ctx * ctx, char * line) +{ + int i,j; + char dev_index[DEFAULT_BUFLEN]; + char filename[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, filename ); + j = get_param( ctx, line, 2, dev_index ); + + if(i>=0 && j>=0) + { + if (jtagcore_loadbsdlfile(jc, filename, str_to_int(dev_index)) >= 0) + { + ctx->script_printf( ctx, MSG_INFO_0, "BSDL %s loaded and parsed !\n", filename ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "File open & parsing error (%s)!\n", filename ); + return JTAG_CORE_ACCESS_ERROR; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_set_scan_mode( script_ctx * ctx, char * line) +{ + int i,j; + char dev_index[DEFAULT_BUFLEN]; + char scan_mode[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, scan_mode ); + + if(i>=0 && j>=0) + { + if( !strcmp(scan_mode,"EXTEST") ) + { + jtagcore_set_scan_mode(jc, str_to_int(dev_index),JTAG_CORE_EXTEST_SCANMODE); + ctx->script_printf( ctx, MSG_INFO_0, "EXTEST mode\n" ); + } + else + { + if( !strcmp(scan_mode,"SAMPLE") ) + { + jtagcore_set_scan_mode(jc, str_to_int(dev_index),JTAG_CORE_SAMPLE_SCANMODE); + + ctx->script_printf( ctx, MSG_INFO_0, "SAMPLE mode\n" ); + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "%s : unknown mode !\n", scan_mode ); + return JTAG_CORE_BAD_PARAMETER; + } + } + + return JTAG_CORE_NO_ERROR; + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_push_and_pop( script_ctx * ctx, char * line) +{ + int ret; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + ret = jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ); + + if(ret != JTAG_CORE_NO_ERROR) + { + ctx->script_printf( ctx, MSG_ERROR, "Code %d !\n", ret ); + return ret; + } + else + { + ctx->script_printf( ctx, MSG_INFO_0, "JTAG chain updated\n" ); + } + + return JTAG_CORE_NO_ERROR; +} + +static int cmd_set_pin_mode( script_ctx * ctx, char * line) +{ + int i,j,k,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + char mode[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + k = get_param( ctx, line, 3, mode ); + + if(i>=0 && j>=0 && k>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_set_pin_state(jc, str_to_int(dev_index), id, JTAG_CORE_OE, str_to_int(mode)); + + ctx->script_printf( ctx, MSG_INFO_0, "Pin %s mode set to %d\n", pinname, str_to_int(mode) ); + + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_set_pin_state( script_ctx * ctx, char * line) +{ + int i,j,k,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + char state[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + k = get_param( ctx, line, 3, state ); + + if(i>=0 && j>=0 && k>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_set_pin_state(jc, str_to_int(dev_index), id, JTAG_CORE_OUTPUT, str_to_int(state)); + + ctx->script_printf( ctx, MSG_INFO_0, "Pin %s set to %d\n", pinname, str_to_int(state) ); + + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_get_pin_state( script_ctx * ctx, char * line) +{ + int i,j,k,ret,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + char mode[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + k = get_param( ctx, line, 3, mode ); + + if(i>=0 && j>=0 && k>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + ret = jtagcore_get_pin_state(jc, str_to_int(dev_index), id, JTAG_CORE_INPUT); + + ctx->script_printf( ctx, MSG_INFO_0, "Pin %s state : %d\n", pinname, ret ); + + ctx->last_data_value = ret; + + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// I2C Commands +///////////////////////////////////////////////////////////////////////////////////////// + +static int cmd_set_i2c_sda_pin( script_ctx * ctx, char * line) +{ + int i,j,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + + if(i>=0 && j>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_i2c_set_sda_pin(jc, str_to_int(dev_index), id); + ctx->script_printf( ctx, MSG_INFO_0, "SDA set to Pin %s\n", pinname ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_set_i2c_scl_pin( script_ctx * ctx, char * line) +{ + int i,j,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + + if(i>=0 && j>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_i2c_set_scl_pin(jc, str_to_int(dev_index), id); + ctx->script_printf( ctx, MSG_INFO_0, "SCL set to Pin %s\n", pinname ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_do_i2c_wr( script_ctx * ctx, char * line) +{ + // jtag_set_do_i2c_wr E8 EAACCDD4455 + int i, j; + int i2cadr, size, ret; + char adresse[DEFAULT_BUFLEN]; + char data[DEFAULT_BUFLEN]; + unsigned char tmp_buffer2[DEFAULT_BUFLEN]; + char tmp_buffer3[16]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, adresse ); + j = get_param( ctx, line, 2, data ); + + if(i>=0 && j>=0) + { + i2cadr = strtoul(adresse,0,16); + size = strlen(data); + size = size / 2; + for(i = 0; iscript_printf( ctx, MSG_WARNING, "Device Ack not detected ! 0x%.2X\n", i2cadr ); + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Code %d !\n", ret ); + } + + return ret; + } + else + { + for(i=0;iscript_printf( ctx, MSG_INFO_0, "WR I2C 0x%.2X :%s\n", i2cadr, data ); + + return JTAG_CORE_NO_ERROR; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_do_i2c_rd( script_ctx * ctx, char * line) +{ + // jtag_set_do_i2c_rd 0xE8 8 + int i,j,i2cadr,size; + char adresse[DEFAULT_BUFLEN]; + char sizebuf[DEFAULT_BUFLEN]; + char tmp_buffer[DEFAULT_BUFLEN]; + char tmp_buffer2[DEFAULT_BUFLEN]; + char tmp_buffer3[16]; + int ret; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, adresse ); + j = get_param( ctx, line, 2, sizebuf ); + + if(i>=0 && j>=0) + { + i2cadr = strtoul(adresse,0,16); + size = str_to_int(sizebuf); + + ret = jtagcore_i2c_write_read(jc, i2cadr, 0, 0, (unsigned char*)tmp_buffer2, size, (unsigned char*)tmp_buffer2); + + if ( ret <= 0) + { + if(ret == 0) + { + ctx->script_printf( ctx, MSG_WARNING, "Device Ack not detected ! 0x%.2X\n", i2cadr ); + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Code %d !\n", ret ); + } + + return ret; + } + else + { + memset(tmp_buffer, 0, sizeof(tmp_buffer)); + for (i = 0; iscript_printf( ctx, MSG_INFO_0, "RD I2C 0x%.2X :%s\n", i2cadr, tmp_buffer ); + + return JTAG_CORE_NO_ERROR; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MDIO Commands +///////////////////////////////////////////////////////////////////////////////////////// + +static int cmd_set_mdio_mdc_pin( script_ctx * ctx, char * line) +{ + int i,j,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + + if(i>=0 && j>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_mdio_set_mdc_pin(jc, str_to_int(dev_index), id); + ctx->script_printf( ctx, MSG_INFO_0, "MDC set to Pin %s\n", pinname ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_set_mdio_mdio_pin( script_ctx * ctx, char * line) +{ + int i,j,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + + if(i>=0 && j>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_mdio_set_mdio_pin(jc, str_to_int(dev_index), id); + ctx->script_printf( ctx, MSG_INFO_0, "MDIO set to Pin %s\n", pinname ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_do_mdio_wr( script_ctx * ctx, char * line) +{ + // jtag_mdio_wr 01 04 EAAC + int i,j,k,mdioadr,regadr,datatowrite; + char address[DEFAULT_BUFLEN]; + char reg[DEFAULT_BUFLEN]; + char data[DEFAULT_BUFLEN]; + int ret; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, address ); + j = get_param( ctx, line, 2, reg ); + k = get_param( ctx, line, 3, data ); + + if(i>=0 && j>=0 && k>=0) + { + mdioadr = strtoul(address,0,16); + regadr = strtoul(reg,0,16); + datatowrite = strtoul(data, 0, 16); + + ret = jtagcore_mdio_write(jc, mdioadr, regadr, datatowrite); + if( ret < 0 ) + { + ctx->script_printf( ctx, MSG_ERROR, "Code %d !\n", ret ); + return ret; + } + + ctx->script_printf( ctx, MSG_INFO_0, "WR MDIO 0x%.2X : [0x%.2X] = 0x%.4X\n", mdioadr ,regadr, datatowrite ); + + return JTAG_CORE_NO_ERROR; + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_do_mdio_rd( script_ctx * ctx, char * line) +{ + // jtag_mdio_rd 01 04 + int i,j,mdioadr,regadr,dataread; + char address[DEFAULT_BUFLEN]; + char reg[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, address ); + j = get_param( ctx, line, 2, reg ); + + if(i>=0 && j>=0) + { + mdioadr = strtoul(address,0,16); + regadr = strtoul(reg,0,16); + + dataread = jtagcore_mdio_read(jc, mdioadr, regadr); + if( dataread < 0 ) + { + ctx->script_printf( ctx, MSG_ERROR, "Code %d !\n", dataread ); + return dataread; + } + + ctx->last_data_value = dataread; + + ctx->script_printf( ctx, MSG_INFO_0, "RD MDIO 0x%.2X : [0x%.2X] = 0x%.4X\n", mdioadr ,regadr, dataread ); + + return JTAG_CORE_NO_ERROR; + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// SPI Commands +///////////////////////////////////////////////////////////////////////////////////////// +static int cmd_set_spi_cs_pin( script_ctx * ctx, char * line) +{ + int i,j,k,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + char polarity[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + k = get_param( ctx, line, 3, polarity ); + + if(i>=0 && j>=0 && k>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_spi_set_cs_pin(jc, str_to_int(dev_index), id, str_to_int(polarity)); + ctx->script_printf( ctx, MSG_INFO_0, "CS set to Pin %s with polarity %d\n", pinname, str_to_int(polarity) ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_set_spi_clk_pin( script_ctx * ctx, char * line) +{ + int i,j,k,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + char polarity[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + k = get_param( ctx, line, 3, polarity ); + + if(i>=0 && j>=0 && k>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_spi_set_clk_pin(jc, str_to_int(dev_index), id, str_to_int(polarity)); + ctx->script_printf( ctx, MSG_INFO_0, "CLK set to Pin %s with polarity %d\n", pinname, str_to_int(polarity) ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_set_spi_mosi_pin( script_ctx * ctx, char * line) +{ + int i,j,k,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + char phase[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + k = get_param( ctx, line, 3, phase ); + + if(i>=0 && j>=0 && k>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_spi_set_mosi_pin(jc, str_to_int(dev_index), id, str_to_int(phase)); + ctx->script_printf( ctx, MSG_INFO_0, "MOSI set to Pin %s with polarity %d\n", pinname, str_to_int(phase) ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_set_spi_miso_pin( script_ctx * ctx, char * line) +{ + int i,j,k,id; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + char phase[DEFAULT_BUFLEN]; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + j = get_param( ctx, line, 2, pinname ); + k = get_param( ctx, line, 3, phase ); + + if(i>=0 && j>=0 && k>=0) + { + id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname); + + if(id>=0) + { + jtagcore_spi_set_miso_pin(jc, str_to_int(dev_index), id, str_to_int(phase)); + ctx->script_printf( ctx, MSG_INFO_0, "MISO set to Pin %s with polarity %d\n", pinname, str_to_int(phase) ); + return JTAG_CORE_NO_ERROR; + } + else + { + ctx->script_printf( ctx, MSG_ERROR, "Pin %s not found\n", pinname ); + return JTAG_CORE_NOT_FOUND; + } + } + + ctx->script_printf( ctx, MSG_ERROR, "Parameters error: %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_spi_rd_wr( script_ctx * ctx, char * line) +{ + int i,j,k,size; + char data_out_txt[DEFAULT_BUFLEN]; + unsigned char data_out[DEFAULT_BUFLEN]; + unsigned char data_in[DEFAULT_BUFLEN]; + char lsbfirst[DEFAULT_BUFLEN]; + char tmp_buffer[3]; + int ret; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + // jtag_spi_rd_wr 00123344 1 (DATA LSBFirst) + i = get_param( ctx, line, 1, data_out_txt ); + j = get_param( ctx, line, 2, lsbfirst ); + + if(i>=0) + { + if(j>=0) + { + jtagcore_spi_set_bitorder(jc, str_to_int(lsbfirst)); + } + + size = strlen(data_out_txt); + size = size / 2; + for(k = 0; kscript_printf( ctx, MSG_ERROR, "Code %d !\n", ret ); + return ret; + } + + ctx->script_printf( ctx, MSG_INFO_0, "SPI TX:" ); + for(k = 0; kscript_printf( ctx, MSG_NONE, " %.2X", data_out[k] ); + } + ctx->script_printf( ctx, MSG_NONE, "\n" ); + + ctx->script_printf( ctx, MSG_INFO_0, "SPI RX:" ); + for(k = 0; kscript_printf( ctx, MSG_NONE, " %.2X", data_in[k] ); + } + ctx->script_printf( ctx, MSG_NONE, "\n" ); + + return JTAG_CORE_NOT_FOUND; + } + + ctx->script_printf( ctx, MSG_ERROR, "Parameters error: %s\n", line ); + + return JTAG_CORE_BAD_PARAMETER; +} + +static int cmd_get_pins_list( script_ctx * ctx, char * line) +{ + int i,j,nb_of_pins; + char dev_index[DEFAULT_BUFLEN]; + char pinname[DEFAULT_BUFLEN]; + int type; + jtag_core * jc; + + jc = (jtag_core *)ctx->app_ctx; + + i = get_param( ctx, line, 1, dev_index ); + if(i>=0) + { + nb_of_pins = jtagcore_get_number_of_pins(jc,str_to_int(dev_index)); + if(nb_of_pins>=0) + { + ctx->script_printf( ctx, MSG_INFO_0, "Device %d : %d pin(s)\n", str_to_int(dev_index), nb_of_pins ); + for(j = 0;j < nb_of_pins;j++) + { + if(jtagcore_get_pin_properties(jc, str_to_int(dev_index), j, pinname, sizeof(pinname), &type) == JTAG_CORE_NO_ERROR) + { + ctx->script_printf( ctx, MSG_NONE, "%s : ", pinname ); + if(type & JTAG_CORE_PIN_IS_INPUT) + { + ctx->script_printf( ctx, MSG_NONE, " in " ); + } + else + { + ctx->script_printf( ctx, MSG_NONE, " " ); + } + + if(type & JTAG_CORE_PIN_IS_OUTPUT) + { + ctx->script_printf( ctx, MSG_NONE, " out " ); + } + else + { + ctx->script_printf( ctx, MSG_NONE, " " ); + } + + if(type & JTAG_CORE_PIN_IS_TRISTATES) + { + ctx->script_printf( ctx, MSG_NONE, " tris" ); + } + else + { + ctx->script_printf( ctx, MSG_NONE, " "); + } + + ctx->script_printf( ctx, MSG_NONE, "\n"); + + } + } + } + + return JTAG_CORE_NO_ERROR; + } + + return JTAG_CORE_BAD_PARAMETER; +} + +cmd_list script_commands_list[] = +{ + {"print", cmd_print}, + {"help", cmd_help}, + {"?", cmd_help}, + {"version", cmd_version}, + {"pause", cmd_pause}, + {"set", cmd_set_env_var}, + {"print_env_var", cmd_print_env_var}, + {"call", cmd_call}, + {"system", cmd_system}, + + {"if", cmd_if}, + {"goto", cmd_goto}, + {"return", cmd_return}, + + {"rand", cmd_rand}, + + {"init_array", cmd_initarray}, + + {"jtag_get_probes_list", cmd_print_probes_list}, + {"jtag_open_probe", cmd_open_probe}, + {"jtag_autoinit", cmd_autoinit}, + + {"jtag_init_scan", cmd_init_and_scan}, + {"jtag_get_nb_of_devices", cmd_print_nb_dev}, + {"jtag_get_devices_list", cmd_print_devs_list}, + {"jtag_load_bsdl", cmd_load_bsdl}, + {"jtag_set_mode", cmd_set_scan_mode}, + + {"jtag_push_pop", cmd_push_and_pop}, + + {"jtag_get_pins_list", cmd_get_pins_list}, + + {"jtag_set_pin_dir", cmd_set_pin_mode}, + {"jtag_set_pin_state", cmd_set_pin_state}, + {"jtag_get_pin_state", cmd_get_pin_state}, + + {"jtag_set_i2c_scl_pin", cmd_set_i2c_scl_pin}, + {"jtag_set_i2c_sda_pin", cmd_set_i2c_sda_pin}, + {"jtag_i2c_rd", cmd_do_i2c_rd}, + {"jtag_i2c_wr", cmd_do_i2c_wr}, + + {"jtag_set_mdio_mdc_pin", cmd_set_mdio_mdc_pin}, + {"jtag_set_mdio_mdio_pin", cmd_set_mdio_mdio_pin}, + {"jtag_mdio_rd", cmd_do_mdio_rd}, + {"jtag_mdio_wr", cmd_do_mdio_wr}, + + {"jtag_set_spi_cs_pin", cmd_set_spi_cs_pin}, + {"jtag_set_spi_mosi_pin", cmd_set_spi_mosi_pin}, + {"jtag_set_spi_miso_pin", cmd_set_spi_miso_pin}, + {"jtag_set_spi_clk_pin", cmd_set_spi_clk_pin}, + {"jtag_spi_rd_wr", cmd_spi_rd_wr}, + + {0 , 0} +}; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +script_ctx * jtagcore_initScript(jtag_core * jc) +{ + return init_script((void*)jc,0x00000000,(void*)jc->envvar); +} + +void jtagcore_setScriptOutputFunc( script_ctx * ctx, SCRIPT_PRINTF_FUNC ext_printf ) +{ + setOutputFunc_script(ctx, ext_printf); +} + +int jtagcore_execScriptLine( script_ctx * ctx, char * line ) +{ + if(!ctx) + return JTAG_CORE_INTERNAL_ERROR; + + return execute_line_script( ctx, line ); +} + +int jtagcore_execScriptFile( script_ctx * ctx, char * script_path ) +{ + if(!ctx) + return JTAG_CORE_INTERNAL_ERROR; + + return execute_file_script( ctx, script_path ); +} + +int jtagcore_execScriptRam( script_ctx * ctx, unsigned char * script_buffer, int buffersize ) +{ + if(!ctx) + return JTAG_CORE_INTERNAL_ERROR; + + return execute_ram_script( ctx, script_buffer, buffersize ); +} + +script_ctx * jtagcore_deinitScript(script_ctx * ctx) +{ + if(!ctx) + return NULL; + + return deinit_script(ctx); +} + +int jtagcore_savePinsStateScript( jtag_core * jc, int device, char * script_path ) +{ + FILE * f; + int number_of_pins; + int pin_type; + int i,state; + char pin_name[DEFAULT_BUFLEN]; + + f = fopen(script_path,"w"); + if(f) + { + if(jc) + { + number_of_pins = jtagcore_get_number_of_pins( jc, device ); + + if(number_of_pins>0) + { + for(i=0;i +*/ + +#define _script_ctx_ + +#ifndef _script_printf_func_ +typedef int (* SCRIPT_PRINTF_FUNC)(void * ctx, int MSGTYPE, char * string, ... ); +#define _script_printf_func_ +#endif + +#ifdef SCRIPT_64BITS_SUPPORT +#define env_var_value uint64_t +#define STRTOVALUE strtoull +#define LONGHEXSTR "%llX" +#else +#define env_var_value uint32_t +#define STRTOVALUE strtoul +#define LONGHEXSTR "%.8X" +#endif + +#define MAX_LABEL_SIZE 64 +#define MAX_LABEL 256 + +typedef struct _script_label +{ + char label_name[MAX_LABEL_SIZE]; + unsigned int offset; +} script_label; + +typedef struct _script_ctx +{ + SCRIPT_PRINTF_FUNC script_printf; + void * app_ctx; + + void * env; + + void * cmdlist; + + FILE * script_file; + char script_file_path[1024]; + + int cur_label_index; + script_label labels[MAX_LABEL]; + + int cur_script_offset; + + int dry_run; + + int last_error_code; + env_var_value last_data_value; + int last_flags; + + char pre_command[1024 + 32]; + + uint32_t rand_seed; + +} script_ctx; + +script_ctx * init_script(void * app_ctx, unsigned int flags, void * env); +int execute_file_script( script_ctx * ctx, char * filename ); +int execute_line_script( script_ctx * ctx, char * line ); +int execute_ram_script( script_ctx * ctx, unsigned char * script_buffer, int buffersize ); +void setOutputFunc_script( script_ctx * ctx, SCRIPT_PRINTF_FUNC ext_printf ); +script_ctx * deinit_script(script_ctx * ctx); diff --git a/lib_jtag_core/src/version.h b/lib_jtag_core/src/version.h new file mode 100644 index 0000000..f3119a6 --- /dev/null +++ b/lib_jtag_core/src/version.h @@ -0,0 +1,16 @@ +#define VDIG1 2 +#define VDIG2 6 +#define VDIG3 7 +#define VDIG4 1 + +#define STR_DATE "28 Oct 2024" + +#define vxstr(s) vstr(s) +#define vstr(s) #s + +#define LIB_JTAG_CORE_VERSION vxstr(VDIG1) "." vxstr(VDIG2) "." vxstr(VDIG3) "." vxstr(VDIG4) +#define LIB_JTAG_CORE_VERSION_COMMA vxstr(VDIG1) "," vxstr(VDIG2) "," vxstr(VDIG3) "," vxstr(VDIG4) + +#define APP_VER VDIG1.VDIG2.VDIG3.VDIG4 +#define APP_VER_TXT( N ) JTAG Boundary Scanner v##N +#define APP_VER_STR( N ) vxstr( APP_VER_TXT( N ) )