pax_global_header00006660000000000000000000000064127322501360014513gustar00rootroot0000000000000052 comment=fd1ad6e7823fa76d8db0d3c5884faffa8ffddafb libsoc-0.8.2/000077500000000000000000000000001273225013600127755ustar00rootroot00000000000000libsoc-0.8.2/.gitignore000066400000000000000000000005721273225013600147710ustar00rootroot00000000000000clean_all.sh build_all.sh sync_all.sh aclocal.m4 arm-oe-linux-gnueabi-libtool autom4te.cache/ bindings/python/gpio.py compile config.guess config.log config.status config.sub config/autoconf configure depcomp install-sh *.deps/ *.libs *Makefile *Makefile.in ltmain.sh missing test/gpio_test test/spi_test test/i2c_test test/pwm_test libtool libsoc.pc *.la *.lo *.o *.pyc *.swp libsoc-0.8.2/ChangeLog000066400000000000000000000107151273225013600145530ustar00rootroot0000000000000021/06/2016 - 0.8.2 ------------------ - Added set_edge and set_direction to python GPIO bindings - Started markdown based written documentation - Build system cleanups 05/05/2016 - 0.8.1 ------------------ - Fixed some configure bugs relating to installing board files 04/05/2016 - 0.8 ---------------- - Automatic board probing support via config file - Python GPIO and I2C bindings - test_configure.sh test script to catch configure regressions - Special Thanks to Andy Doan 09/12/2015 - 0.7.1 ------------------ - Fixed compilation with musl - Remove inline keywords as they dont play nice with GCC 5.2 - Misc cleanups from static analysis 05/11/2015 - 0.7 ---------------- - Add named GPIO board support - Fixed autoconf syntax error - Special Thanks to Andy Doan 02/07/2015 - 0.6.5 ---------------- - Fix bug in GPIO interrupt polling 14/06/2015 - 0.6.4 ---------------- - Fix autotools warnings - Enable silent build - Add packageconfig support - Special Thanks to Yegor Yefremov 22/08/2014 - 0.6.3 ---------------- - Initialise GPIO function pointer to NULL - Style fixes - Small scope optimisations - Juggling of include files to more relevant places - Special Thanks to Yegor Yefremov 16/06/2014 - 0.6.2 ---------------- - Moved some required headers to include files - Fix memory leak in GPIO lib error path - Fix wrong SPI brackets in libsoc_spi_read which caused function to return FAILURE regardless - Special Thanks to Yegor Yefremov 22/05/2014 - 0.6.1 -------------- - Add support for BOTH edge interrupts - Add include guards - Add C++ ifdef support - Include sysfs gpio bug fix for OMAP platforms 02/02/2014 - 0.6 ------------ - PWM sysfs support (Linux 3.12+) - Fixed some bugs - Enabled debugging by default; you will now have to specifically switch it off (./configure --disable-debug) 06/12/2013 - 0.5 ---------------------- - Basic I2C support - Add SPI header to include_header in configure.ac 06/10/2013 - 0.4 -------------- - Basic SPI support - See lib/include/libsoc_spi.h 13/09/2013 - 0.3 -------------- - Non-blocking GPIO interrupts /** * \fn int libsoc_gpio_callback_interrupt(gpio* gpio, int (*callback_fn)(void*), void* arg) * \brief takes a gpio and a callback function, when an interrupt occurs * on the edge previously specified, the callback function is called * \param gpio* gpio - the gpio for which you want the interrupt to * trigger the callback function * \param int (*callback_fn)(void*) - the function you wish to call with * a void* pointer to a possible value you may wish to use in the callback. * \param void* arg - pointer to data you wish to use in the callback function * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_gpio_callback_interrupt(gpio* gpio, int (*callback_fn)(void*), void* arg); /** * \fn int libsoc_gpio_callback_interrupt_cancel(gpio* gpio) * \brief cancel a callback on a gpio interrupt * \param gpio* gpio - gpio with a valid callback enabled * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_gpio_callback_interrupt_cancel(gpio* gpio); - Added modes to gpio_request gpio* libsoc_gpio_request(unsigned int gpio_id, int mode); /** * Valid Modes for libsoc_gpio_request * * LS_SHARED - if the gpio is already exported then it will not unexport * the GPIO on free. If it is not exported, then it will * unexport on free. * * LS_GREEDY - will succeed if the GPIO is already exported, but will * always unexport the GPIO on free. * * LS_WEAK - will fail if GPIO is already exported, will always unexport * on free. */ 03/09/2013 - 0.2 -------------- - GPIO blocking interrupt support /** * \fn int libsoc_gpio_wait_interrupt(gpio* gpio, int timeout) * \brief takes a gpio and waits for length of timeout or until an * interrupt occurs. Will return EXIT_SUCCESS on interrupt or * EXIT_FAILURE on error or timeout. * \param gpio* gpio - the gpio for which you want to wait on interrupt * \param int timeout - the max length of time to wait for interrupt in * milliseconds * \return EXIT_SUCCESS on interrupt caught, EXIT_FAILURE on error or * interrupt missed */ int libsoc_gpio_wait_interrupt(gpio* gpio, int timeout); - Improved error and debug handling 31/08/2013 - 0.1 -------------- - basic sysfs GPIO support libsoc-0.8.2/LICENCE000066400000000000000000000636321273225013600137740ustar00rootroot00000000000000GNU 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. libsoc: C library for interfacing with common SoC peripherals through generic kernel interfaces Copyright (C) 2013 Jack Mitchell 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. {signature of Ty Coon}, 1 April 1990 Ty Coon, President of Vice That's all there is to it! libsoc-0.8.2/Makefile.am000066400000000000000000000004031273225013600150260ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I config/m4 AUTOMAKE_OPTIONS = subdir-objects pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsoc.pc EXTRA_DIST = libsoc.pc.in CLEANFILES = libsoc.pc SUBDIRS=lib contrib/board_files if HAVE_PYTHON SUBDIRS += bindings/python endif libsoc-0.8.2/README.md000077700000000000000000000000001273225013600210452static-docs/docs/index.mdustar00rootroot00000000000000libsoc-0.8.2/bindings/000077500000000000000000000000001273225013600145725ustar00rootroot00000000000000libsoc-0.8.2/bindings/python/000077500000000000000000000000001273225013600161135ustar00rootroot00000000000000libsoc-0.8.2/bindings/python/Makefile.am000066400000000000000000000004751273225013600201550ustar00rootroot00000000000000libsocdir = $(pyexecdir)/libsoc libsoc_PYTHON = __init__.py gpio.py i2c.py AM_CPPFLAGS = $(PYTHON_CFLAGS) -I${top_srcdir}/lib/include -DLIBSOC_SO=\"@prefix@/lib/libsoc.so\" libsoc_LTLIBRARIES = _libsoc.la _libsoc_la_LDFLAGS = -module -avoid-version -export-dynamic $(PYTHON_LIBS) _libsoc_la_SOURCES = gpio_python.c libsoc-0.8.2/bindings/python/__init__.py000066400000000000000000000001351273225013600202230ustar00rootroot00000000000000from ._libsoc import * # NOQA from .gpio import * # NOQA from .i2c import * # NOQA libsoc-0.8.2/bindings/python/gpio.py000066400000000000000000000126171273225013600174320ustar00rootroot00000000000000import atexit import contextlib import threading import time from ._libsoc import ( DIRECTION_INPUT, DIRECTION_OUTPUT, EDGE_BOTH, EDGE_FALLING, EDGE_NONE, EDGE_RISING, LS_SHARED, LS_GREEDY, LS_WEAK, api ) class InterruptHandler(threading.Thread): def __init__(self, gpio, interrupt_callback): super(InterruptHandler, self).__init__() self.gpio = gpio self.isr_cb = interrupt_callback self.running = False def run(self): self.running = True while self.running: if self.gpio.poll(1000): self.isr_cb() def stop(self): self.running = False class GPIO(object): _board_config = None def __init__(self, id, direction, edge=EDGE_NONE, mode=LS_SHARED): self.id = id if not isinstance(id, int): raise TypeError('Invalid gpio id must be an "int"') if mode not in (LS_SHARED, LS_GREEDY, LS_WEAK): raise ValueError('Invalid GPIO mode: %d' % mode) self._validate_direction(direction, edge) self.mode = mode self._gpio = None def _validate_direction(self, direction, edge=EDGE_NONE): if direction not in (DIRECTION_INPUT, DIRECTION_OUTPUT): raise ValueError('Invalid GPIO direction: %d' % direction) edges = (EDGE_RISING, EDGE_FALLING, EDGE_NONE, EDGE_BOTH) if direction == DIRECTION_INPUT and edge not in edges: raise ValueError('Invalid GPIO edge: %d' % edge) self.direction = direction self.edge = edge def open(self): '''Opens a file descriptor to the GPIO and configures it.''' assert self._gpio is None self._gpio = api.libsoc_gpio_request(self.id, self.mode) if self._gpio == 0: # NULL from native code raise IOError('Unable to open GPIO_%d' % self.id) self.set_direction(self.direction, self.edge) def close(self): '''Cleans up the memory and resources allocated by the open method.''' if self._gpio: api.libsoc_gpio_free(self._gpio) self._gpio = None def set_direction(self, direction, edge): self._validate_direction(direction, edge) api.libsoc_gpio_set_direction(self._gpio, self.direction) if self.direction == DIRECTION_INPUT: if api.libsoc_gpio_set_edge(self._gpio, self.edge) != 0: raise IOError('Error setting edge for GPIO_%d' % self.id) def set_edge(self, edge): self._validate_direction(self.direction, edge) if api.libsoc_gpio_set_edge(self._gpio, self.edge) != 0: raise IOError('Error setting edge for GPIO_%d' % self.id) def get_direction(self): d = api.libsoc_gpio_get_direction(self._gpio) if d == -1: raise IOError('Error reading GPIO_%d direction: %d' % self.id) return d @staticmethod def gpio_id(pin): '''Given a pin number on the board, return the actual GPIO ID.''' if not GPIO._board_config: GPIO._board_config = api.libsoc_board_init() atexit.register(api.libsoc_board_free, GPIO._board_config) gpio = api.libsoc_board_gpio_id(GPIO._board_config, pin.encode()) if gpio == -1: raise ValueError('Invalid GPIO pin name(%s)' % pin) return gpio @staticmethod def set_debug(enabled): v = 0 if enabled: v = 1 api.libsoc_set_debug(v) def set_high(self): assert self.direction == DIRECTION_OUTPUT api.libsoc_gpio_set_level(self._gpio, 1) def set_low(self): assert self.direction == DIRECTION_OUTPUT api.libsoc_gpio_set_level(self._gpio, 0) def is_high(self): l = api.libsoc_gpio_get_level(self._gpio) if l == -1: raise IOError('Error reading GPIO_%d level' % self.id) return l == 1 def wait_for_interrupt(self, timeout): assert self.direction == DIRECTION_INPUT if api.libsoc_gpio_wait_interrupt(self._gpio, timeout) != 0: raise IOError('Error waiting for interrupt on GPIO_%d' % self.id) def get_edge(self): '''Return the edge the GPIO is configured with.''' assert self.direction == DIRECTION_INPUT e = api.libsoc_gpio_get_edge(self._gpio) if e == -1: raise IOError('Error reading GPIO_%d edge' % self.id) return e def poll(self, timeout_ms=-1): '''Nearly the same as wait_for_interrupt, but with less overhead. wait_for_interrupt does some sanity checks of the GPIO settings before polling. Returns True if an interrupt occurred, False on an error or timeout ''' return api.libsoc_gpio_poll(self._gpio, timeout_ms) == 0 def start_interrupt_handler(self, interrupt_callback): '''Returns a thread that continuosly polls the GPIO. If an interrupt is encountered, the interrupt_callback function will be run. This thread can be stopped by calling interrupt_handler.stop() ''' ih = InterruptHandler(self, interrupt_callback) ih.start() while not ih.running: time.sleep(0.01) return ih @contextlib.contextmanager def request_gpios(gpios): if not isinstance(gpios, tuple) and not isinstance(gpios, list): gpios = (gpios,) try: for g in gpios: g.open() yield finally: for g in reversed(gpios): g.close() libsoc-0.8.2/bindings/python/gpio_python.c000066400000000000000000000033321273225013600206170ustar00rootroot00000000000000#include #include "libsoc_gpio.h" static PyMethodDef functions[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; static void _add_constants(PyObject *m) { PyObject *mod, *func, *args, *api; PyModule_AddIntConstant(m, "DIRECTION_ERROR", DIRECTION_ERROR); PyModule_AddIntConstant(m, "DIRECTION_INPUT", INPUT); PyModule_AddIntConstant(m, "DIRECTION_OUTPUT", OUTPUT); PyModule_AddIntConstant(m, "LEVEL_ERROR", LEVEL_ERROR); PyModule_AddIntConstant(m, "LEVEL_LOW", LOW); PyModule_AddIntConstant(m, "LEVEL_HIGH", HIGH); PyModule_AddIntConstant(m, "EDGE_ERROR", EDGE_ERROR); PyModule_AddIntConstant(m, "EDGE_RISING", RISING); PyModule_AddIntConstant(m, "EDGE_FALLING", FALLING); PyModule_AddIntConstant(m, "EDGE_NONE", NONE); PyModule_AddIntConstant(m, "EDGE_BOTH", BOTH); PyModule_AddIntConstant(m, "LS_SHARED", LS_SHARED); PyModule_AddIntConstant(m, "LS_GREEDY", LS_GREEDY); PyModule_AddIntConstant(m, "LS_WEAK", LS_WEAK); mod = PyImport_ImportModule("ctypes"); func = PyObject_GetAttrString(mod, "CDLL"); if (!PyCallable_Check(func)) PyErr_Print(); args = Py_BuildValue("(s)", LIBSOC_SO); api = PyObject_CallObject(func, args); Py_DECREF(args); PyModule_AddObject(m, "api", api); } #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_libsoc", NULL, -1, functions, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit__libsoc(void) { PyObject *m; m = PyModule_Create(&moduledef); if (!m) return NULL; _add_constants(m); return m; } #else PyMODINIT_FUNC init_libsoc(void) { PyObject *m; m = Py_InitModule ("_libsoc", functions); _add_constants(m); } #endif libsoc-0.8.2/bindings/python/i2c.py000066400000000000000000000035401273225013600171440ustar00rootroot00000000000000import sys from ctypes import create_string_buffer from ._libsoc import api PY3 = sys.version_info >= (3, 0) class I2C(object): def __init__(self, bus, address): if not isinstance(bus, int): raise TypeError('Invalid bus id must be an "int"') if not isinstance(address, int): raise TypeError('Invalid bus address must be an "int"') self.bus = bus self.addr = address self._i2c = None def __enter__(self): self.open() return self def __exit__(self, type, value, traceback): self.close() def open(self): '''Opens a file descriptor to the GPIO and configures it.''' assert self._i2c is None self._i2c = api.libsoc_i2c_init(self.bus, self.addr) if self._i2c == 0: # NULL from native code raise IOError( 'Unable to open i2c bus(%d) addr(%d)' % (self.bus, self.addr)) def close(self): '''Cleans up the memory and resources allocated by the open method.''' if self._i2c: api.libsoc_i2c_free(self._i2c) self._i2c = None @staticmethod def set_debug(enabled): v = 0 if enabled: v = 1 api.libsoc_set_debug(v) def set_timeout(self, timeout): if not isinstance(timeout, int): raise TypeError('Invalid timeout must be an "int"') api.libsoc_i2c_set_timeout(self._i2c, timeout) def read(self, num_bytes): buff = create_string_buffer(num_bytes) if api.libsoc_i2c_read(self._i2c, buff, num_bytes) == -1: raise IOError('Error reading i2c device') return buff.value def write(self, byte_array): if PY3: buff = bytes(byte_array) else: buff = ''.join(map(chr, byte_array)) api.libsoc_i2c_write(self._i2c, buff, len(buff)) libsoc-0.8.2/config/000077500000000000000000000000001273225013600142425ustar00rootroot00000000000000libsoc-0.8.2/config/m4/000077500000000000000000000000001273225013600145625ustar00rootroot00000000000000libsoc-0.8.2/config/m4/.gitignore000066400000000000000000000000051273225013600165450ustar00rootroot00000000000000*.m4 libsoc-0.8.2/configure.ac000066400000000000000000000040721273225013600152660ustar00rootroot00000000000000AC_INIT([libsoc], [0.8.2]) AC_CONFIG_SRCDIR([lib/gpio.c]) AC_CONFIG_MACRO_DIR([config/m4]) AC_CONFIG_AUX_DIR([config/autoconf]) AC_CANONICAL_SYSTEM AC_PROG_CC AM_INIT_AUTOMAKE([foreign]) AM_PROG_CC_C_O LT_INIT AC_SEARCH_LIBS([pthread_create, pthread_cancel],[pthread], , AC_MSG_WARN(["ERROR: Could not find pthread library"])) AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Enable the debug code])) AS_IF([test "x$enable_debug" != "xno"], [ AC_DEFINE([DEBUG]) ]) AC_ARG_WITH([board-configs], AS_HELP_STRING([--with-board-configs], [Install all board config files])) AM_CONDITIONAL([BOARD_CONFIGS], [test "x$with_board_configs" = xyes]) AC_ARG_ENABLE([python], AS_HELP_STRING([--enable-python=PYTHON_VERSION], [Enable Python language bindings to libsoc API. PYTHON_VERSION can be empty for autodetect, the value 2 or 3 to search the PATH environment variable for python2 or python3, or an absolute path to a python binary]), [python_arg=$enable_python], [python_arg="no"]) AS_IF([test "x$python_arg" != xno], [ AS_CASE(["$python_arg"], [2|3], [ PYTHON="python$python_arg" ], [yes], [], [PYTHON="$python_arg"] ) AM_PATH_PYTHON() if ! which "$PYTHON"; then AC_MSG_ERROR([Python interpreter $PYTHON does not exist]) fi PKG_CHECK_MODULES([PYTHON], [python-"$PYTHON_VERSION"]) ]) AM_CONDITIONAL([HAVE_PYTHON], [test "x$PYTHON" != x]) AC_ARG_ENABLE([board], AS_HELP_STRING([--enable-board=BOARD], [Enable installation of board config])) AS_IF([test "x$enable_board" != "x"], [ valid_boards=`ls $srcdir/contrib/board_files/ | grep .conf | tr '\n' ' ' | sed -e 's/.conf//g' -e 's/example//'` for x in $valid_boards ; do test "$x" = "$enable_board" && found=1 done test -z "$found" && AC_MSG_ERROR([Invalid board name: $enable_board, must be one of: $valid_boards]) ]) AC_SUBST([board], $enable_board) AM_CONDITIONAL([BOARD], [test "x$enable_board" != x]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_CONFIG_FILES(Makefile lib/Makefile contrib/board_files/Makefile bindings/python/Makefile libsoc.pc) AC_OUTPUT libsoc-0.8.2/contrib/000077500000000000000000000000001273225013600144355ustar00rootroot00000000000000libsoc-0.8.2/contrib/board_files/000077500000000000000000000000001273225013600167065ustar00rootroot00000000000000libsoc-0.8.2/contrib/board_files/Makefile.am000066400000000000000000000012341273225013600207420ustar00rootroot00000000000000if BOARD_CONFIGS BOARD_FILES = $(filter-out example.conf, $(wildcard $(srcdir)/*.conf)) libsocdir = $(pkgdatadir) libsoc_DATA = $(BOARD_FILES) if BOARD installdirs-local: install -d $(DESTDIR)$(sysconfdir) install-data-hook: installdirs-local ln -srf $(DESTDIR)$(pkgdatadir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf endif uninstall-local: -rmdir $(DESTDIR)$(pkgdatadir) -rm $(DESTDIR)$(sysconfdir)/libsoc.conf -rmdir $(DESTDIR)$(sysconfdir) else if BOARD install-data-hook: install -D $(srcdir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf uninstall-local: -rm $(DESTDIR)$(sysconfdir)/libsoc.conf -rmdir $(DESTDIR)$(sysconfdir) endif endif libsoc-0.8.2/contrib/board_files/beaglebone_black.conf000066400000000000000000000015171273225013600230000ustar00rootroot00000000000000[board] model = TI AM335x BeagleBone Black [GPIO] # beaglebone pin layout # http://beagleboard.org/support/bone101 # P9_11 = 30 P9_12 = 60 P9_13 = 31 P9_14 = 50 P9_15 = 48 P9_16 = 51 P9_17 = 5 P9_18 = 4 P9_21 = 3 P9_22 = 2 P9_23 = 49 P9_24 = 15 P9_25 = 117 P9_26 = 14 P9_27 = 115 P9_28 = 113 P9_29 = 29 P9_30 = 112 P9_31 = 110 P9_41 = 20 P9_42 = 7 P8_3 = 38 P8_4 = 39 P8_5 = 34 P8_6 = 35 P8_7 = 66 P8_8 = 67 P8_9 = 69 P8_10 = 68 P8_11 = 45 P8_12 = 44 P8_13 = 23 P8_14 = 26 P8_15 = 47 P8_16 = 46 P8_17 = 27 P8_18 = 65 P8_19 = 22 P8_20 = 63 P8_21 = 62 P8_22 = 37 P8_23 = 36 P8_24 = 33 P8_25 = 32 P8_26 = 61 P8_27 = 86 P8_28 = 88 P8_29 = 87 P8_30 = 89 P8_31 = 10 P8_32 = 11 P8_33 = 9 P8_34 = 81 P8_35 = 8 P8_36 = 80 P8_37 = 78 P8_38 = 79 P8_39 = 76 P8_40 = 77 P8_41 = 74 P8_42 = 75 P8_43 = 72 P8_44 = 73 P8_45 = 70 P8_46 = 71 libsoc-0.8.2/contrib/board_files/bubblegum.conf000066400000000000000000000006411273225013600215220ustar00rootroot00000000000000[board] model = s900 [GPIO] # bubblegum pin layout # GPIO-A = 19 GPIO-B = 18 GPIO-C = 17 GPIO-D = 16 GPIO-E = 15 GPIO-F = 14 GPIO-G = 13 GPIO-H = 12 GPIO-I = 11 GPIO-J = 10 GPIO-K = 27 GPIO-L = 26 # include mappings by pin number on board GPIO-23 = 19 GPIO-24 = 18 GPIO-25 = 17 GPIO-26 = 16 GPIO-27 = 15 GPIO-28 = 14 GPIO-29 = 13 GPIO-30 = 12 GPIO-31 = 11 GPIO-32 = 10 GPIO-33 = 27 GPIO-34 = 26 libsoc-0.8.2/contrib/board_files/dragonboard410c.conf000066400000000000000000000007141273225013600224310ustar00rootroot00000000000000[board] model = Qualcomm Technologies, Inc. APQ 8016 SBC [GPIO] # dragonboard 410c pin layout # GPIO-A = 36 GPIO-B = 12 GPIO-C = 13 GPIO-D = 69 GPIO-E = 115 GPIO-F = 4 GPIO-G = 24 GPIO-H = 25 GPIO-I = 35 GPIO-J = 34 GPIO-K = 28 GPIO-L = 33 # include mappings by pin number on board GPIO-23 = 36 GPIO-24 = 12 GPIO-25 = 13 GPIO-26 = 69 GPIO-27 = 115 GPIO-28 = 4 GPIO-29 = 24 GPIO-30 = 25 GPIO-31 = 35 GPIO-32 = 34 GPIO-33 = 28 GPIO-34 = 33 libsoc-0.8.2/contrib/board_files/example.conf000066400000000000000000000016241273225013600212130ustar00rootroot00000000000000# A board config file consists of two required sections, the "board" and "GPIO" # Lines starting with "#" are ignored [board] # When attempting an automatic configuration probe at library runtime, the # dtfile option contains the path to the file which will be read and it's # contents compared against the 'model' option. Change this value if you want # your 'model' option to be compared to a different file. # dtfile = /proc/device-tree/model # The model value is compared to the contents of the file path in 'dtfile'. If # the white space trimmed 'model' option, is equal to the contents of the # whitespace trimmed 'dtfile' then the automatic probe will succed and this # board config file selected. model = Example Board Name [GPIO] # Provide a list of board pin "names" to GPIO IDs on the chip. # P9_42 = 7 # You can list a single GPIO ID more than once if you needed aliases. ie: PIN_23 = 12 SPI_CS = 12 libsoc-0.8.2/contrib/board_files/hikey.conf000066400000000000000000000007101273225013600206640ustar00rootroot00000000000000[board] model = HiKey Development Board [GPIO] # hikey pin layout # GPIO-A = 488 GPIO-B = 489 GPIO-C = 490 GPIO-D = 491 GPIO-E = 492 GPIO-F = 415 GPIO-G = 463 GPIO-H = 495 GPIO-I = 426 GPIO-J = 433 GPIO-K = 427 GPIO-L = 434 # include mappings by pin number on board GPIO-23 = 488 GPIO-24 = 489 GPIO-25 = 490 GPIO-26 = 491 GPIO-27 = 492 GPIO-28 = 415 GPIO-29 = 463 GPIO-30 = 495 GPIO-31 = 426 GPIO-32 = 433 GPIO-33 = 427 GPIO-34 = 434 libsoc-0.8.2/contrib/board_files/odroid_c2.conf000066400000000000000000000006151273225013600214230ustar00rootroot00000000000000[board] model = Hardkernel ODROID-C2 # http://odroid.com/dokuwiki/doku.php?id=en:c2_hardware [GPIO] J2_3 = 205 J2_5 = 206 J2_7 = 249 J2_8 = 240 J2_10 = 241 J2_11 = 247 J2_12 = 238 J2_13 = 239 J2_15 = 237 J2_16 = 236 J2_18 = 233 J2_19 = 235 J2_21 = 232 J2_22 = 231 J2_23 = 230 J2_24 = 229 J2_26 = 225 J2_27 = 207 J2_28 = 208 J2_29 = 228 J2_31 = 219 J2_32 = 224 J2_33 = 234 J2_35 = 214 J2_36 = 218 libsoc-0.8.2/lib/000077500000000000000000000000001273225013600135435ustar00rootroot00000000000000libsoc-0.8.2/lib/Makefile.am000066400000000000000000000012751273225013600156040ustar00rootroot00000000000000lib_LTLIBRARIES = libsoc.la include_HEADERS = include/libsoc_gpio.h \ include/libsoc_spi.h \ include/libsoc_i2c.h \ include/libsoc_pwm.h \ include/libsoc_board.h \ include/libsoc_conffile.h \ include/libsoc_debug.h libsoc_la_SOURCES = gpio.c \ spi.c \ file.c \ i2c.c \ pwm.c \ board.c \ conffile.c \ debug.c libsoc_la_CPPFLAGS = -I${top_srcdir}/lib/include ## interface : source : age libsoc_la_LDFLAGS = -version-info 6:2:4 AM_CFLAGS = -DDATA_DIR=\"$(DESTDIR)$(pkgdatadir)\" -DLIBSOC_CONF=\"@sysconfdir@/libsoc.conf\" libsoc-0.8.2/lib/board.c000066400000000000000000000051411273225013600147770ustar00rootroot00000000000000#include #include #include #include #include #include "libsoc_board.h" #include "libsoc_debug.h" #include "libsoc_file.h" static const char * _get_conf_file() { const char *name = getenv("LIBSOC_CONF"); if (name == NULL) name = LIBSOC_CONF; return name; } static int _probe_config(conffile *conf) { const char *dtfile = conffile_get(conf, "board", "dtfile", "/proc/device-tree/model"); const char *match = conffile_get(conf, "board", "model", NULL); if (match) { char *probed = file_read_contents(dtfile); if (probed) { int rc = strcmp(probed, match); free(probed); return !rc; } } else { libsoc_debug(__func__, "No 'model' value found in 'board' section"); } return 0; } static board_config * _probe() { board_config *bc = NULL; conffile *conf = NULL; const char *confs_dir = DATA_DIR; char tmp[PATH_MAX]; DIR *dirp; struct dirent *dp; if ((dirp = opendir(confs_dir)) != NULL) { do { if ((dp = readdir(dirp)) != NULL) { char *ext = strrchr(dp->d_name, '.'); if (ext && !strcmp(ext, ".conf")) { strcpy(tmp, confs_dir); strcat(tmp, "/"); strcat(tmp, dp->d_name); conf = conffile_load(tmp); if (conf) { libsoc_debug(__func__, "probing %s for board support", tmp); if(_probe_config(conf)) { libsoc_debug(__func__, "probing match for %s", tmp); bc = calloc(1, sizeof(board_config)); bc->conf = conf; } else conffile_free(conf); } } } } while (dp != NULL && bc == NULL); closedir(dirp); } else { libsoc_warn("Unable to read directory: %s", confs_dir); } return bc; } board_config* libsoc_board_init() { board_config *bc = NULL; const char *conf = _get_conf_file(); if (!access(conf, F_OK)) { bc = calloc(sizeof(board_config), 1); bc->conf = conffile_load(conf); if (!bc->conf) { free(bc); bc = NULL; } } else { bc = _probe(); if (!bc) libsoc_warn("Board config(%s) does not exist and could not be probed", conf); } return bc; } void libsoc_board_free(board_config *config) { if (config) { conffile_free(config->conf); free(config); } } unsigned int libsoc_board_gpio_id(board_config *config, const char* pin) { return conffile_get_int(config->conf, "GPIO", pin, -1); } libsoc-0.8.2/lib/conffile.c000066400000000000000000000074221273225013600155010ustar00rootroot00000000000000#include #include #include #include #include #include #include "libsoc_debug.h" #include "libsoc_conffile.h" static char * trim(char *buf) { size_t len = strlen(buf); while (isspace(buf[--len])) buf[len] = '\0'; while (isspace(*buf)) buf++; return buf; } static keyval* _create_keyval(const char *path, char *line) { keyval *kv; char *key, *val, *save; key = strtok_r(line, "=", &save); val = strtok_r(NULL, "\n", &save); if (!val) { libsoc_warn("Invalid key = value in %s:\n%s\n", path, line); return NULL; } key = trim(key); val = trim(val); kv = calloc(1, sizeof(keyval)); kv->key = strdup(key); kv->val = strdup(val); return kv; } conffile * conffile_load(const char *path) { int rc; FILE *fp; char line[256]; conffile *conf = calloc(1, sizeof(conffile)); section *stmp = NULL; keyval *ktmp = NULL; fp = fopen (path, "r"); if (fp) { while(fgets(line, sizeof(line), fp)) { if (*line == '#' || *line == '\0' || *line == '\n') continue; if (line[0] == '[') { // new section stmp = calloc(1, sizeof(section)); stmp->next = conf->sections; conf->sections = stmp; rc = strlen(line); if (line[rc-2] != ']' || (rc-2) > sizeof(stmp->name)) { libsoc_warn("Invalid section line in %s:\n%s\n", path, line); goto cleanup; } line[rc-2] = '\0'; strcpy(stmp->name, trim(&line[1])); } else { if (!conf->sections) { libsoc_warn("Section must be declared in %s before line: %s\n", path, line); } ktmp = _create_keyval(path, line); if (ktmp) { ktmp->next = conf->sections->settings; conf->sections->settings = ktmp; } else { goto cleanup; } } } fclose(fp); } else { libsoc_warn("Unable to open board config: %s\n", path); } return conf; cleanup: if (fp) fclose(fp); conffile_free(conf); return NULL; } void conffile_free(conffile *conf) { section *sptr, *stmp; keyval *kptr, *ktmp; if (!conf) return; sptr = conf->sections; while (sptr) { kptr = sptr->settings; while (kptr) { ktmp = kptr->next; free(kptr->key); free(kptr->val); free(kptr); kptr = ktmp; } stmp = sptr->next; free(sptr); sptr = stmp; } } const char* conffile_get(conffile *conf, const char *sectname, const char *key, const char *defval) { section *s = conf->sections; while(s) { if (!strcmp(s->name, sectname)) { keyval *kv = s->settings; while(kv) { if (!strcmp(kv->key, key)) return kv->val; kv = kv->next; } return defval; } s = s->next; } return defval; } int conffile_get_int(conffile *conf, const char *sectname, const char *key, int defval) { long val = defval; const char *strval = conffile_get(conf, sectname, key, NULL); if (strval) { char *endptr; val = strtol(strval, &endptr, 10); if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0) || endptr == strval || *endptr != '\0' || val > INT_MAX) { libsoc_warn("Invalid number: %s\n", strval); val = defval; } } return val; } libsoc-0.8.2/lib/debug.c000066400000000000000000000020151273225013600147730ustar00rootroot00000000000000#include #include int debug = 0; void libsoc_debug (const char *func, char *format, ...) { #ifdef DEBUG if (debug) { va_list args; fprintf (stderr, "libsoc-debug: "); va_start (args, format); vfprintf (stderr, format, args); va_end (args); fprintf (stderr, " (%s)", func); fprintf (stderr, "\n"); } #endif } void libsoc_warn (const char *format, ...) { va_list args; fprintf (stderr, "libsoc-warn: "); va_start (args, format); vfprintf (stderr, format, args); va_end (args); fprintf (stderr, "\n"); } void libsoc_set_debug (int level) { #ifdef DEBUG if (level) { debug = 1; libsoc_debug (__func__, "debug enabled"); } else { libsoc_debug (__func__, "debug disabled"); debug = 0; } #else printf ("libsoc-gpio: warning debug support missing!\n"); #endif } int libsoc_get_debug () { #ifdef DEBUG return debug; #else printf ("libsoc-debug: warning debug support missing!\n"); #endif } libsoc-0.8.2/lib/file.c000066400000000000000000000055351273225013600146360ustar00rootroot00000000000000#include #include #include #include #include int file_open(const char *path, int flags) { int fd = open(path, flags); if (fd < 0) { perror("libsoc-file-debug"); return -1; } return fd; } int file_write(int fd, const char *str, int len) { int ret_len = write(fd, str, len); if (ret_len < 0) { perror("libsoc-file-debug"); return -1; } return ret_len; } int file_read(int fd, void *buf, int count) { lseek (fd, 0, SEEK_SET); int ret = read(fd, buf, count); if (ret < 0) { perror("libsoc-file-debug"); return -1; } return ret; } int file_valid(char *path) { if (access(path, F_OK) == 0) { return 1; } return 0; } int file_close(int fd) { if (close(fd) < 0) { perror ("libsoc-file-debug"); return -1; } return 0; } #define INT_STR_BUF 20 int file_read_int_fd(int fd, int *tmp) { char buf[INT_STR_BUF]; if (file_read(fd, buf, INT_STR_BUF) < 0) { return EXIT_FAILURE; } *tmp = atoi(buf); return EXIT_SUCCESS; } int file_read_int_path(char *path, int *tmp) { int fd, ret; fd = file_open(path, O_SYNC | O_RDONLY); if (fd < 0) { return EXIT_FAILURE; } ret = file_read_int_fd(fd, tmp); if (file_close(fd) < 0 || ret == EXIT_FAILURE) { return EXIT_FAILURE; } return EXIT_SUCCESS; } int file_write_int_fd(int fd, int val) { char buf[INT_STR_BUF]; sprintf(buf, "%d", val); if (file_write(fd, buf, INT_STR_BUF) < 0) { return EXIT_FAILURE; } return EXIT_SUCCESS; } int file_write_int_path(char *path, int val) { int fd, ret; fd = file_open(path, O_SYNC | O_WRONLY); if (fd < 0) { return EXIT_FAILURE; } ret = file_write_int_fd(fd, val); if (file_close(fd) < 0 || ret == EXIT_FAILURE) { return EXIT_FAILURE; } return EXIT_SUCCESS; } int file_read_str(char *path, char *tmp, int buf_len) { int fd; fd = file_open(path, O_SYNC | O_RDONLY); if (fd < 0) { return EXIT_FAILURE; } if (file_read(fd, tmp, buf_len) < 0) { return EXIT_FAILURE; } if (file_close(fd) < 0) { return EXIT_FAILURE; } return EXIT_SUCCESS; } int file_write_str(char *path, char* buf, int len) { int fd; fd = file_open(path, O_SYNC | O_WRONLY); if (fd < 0) { return EXIT_FAILURE; } if (file_write(fd, buf, len) < 0) { return EXIT_FAILURE; } if (file_close(fd) < 0) { return EXIT_FAILURE; } return EXIT_SUCCESS; } char* file_read_contents(const char *path) { int fd; struct stat st; char *buf; if (stat(path, &st)) { perror("libsoc-file-debug"); return NULL; } fd = file_open(path, O_RDONLY); if (fd < 0) return NULL; buf = malloc(st.st_size); if (buf) { if (file_read(fd, buf, st.st_size) != st.st_size) { free(buf); return NULL; } } return buf; } libsoc-0.8.2/lib/gpio.c000066400000000000000000000265241273225013600146560ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "libsoc_file.h" #include "libsoc_debug.h" #include "libsoc_gpio.h" #define STR_BUF 256 const char gpio_level_strings[2][STR_BUF] = { "0", "1" }; const char gpio_direction_strings[2][STR_BUF] = { "in", "out" }; const char gpio_edge_strings[4][STR_BUF] = { "rising", "falling", "none", "both" }; void libsoc_gpio_debug (const char *func, int gpio, char *format, ...) { #ifdef DEBUG if (libsoc_get_debug ()) { va_list args; fprintf (stderr, "libsoc-gpio-debug: "); va_start (args, format); vfprintf (stderr, format, args); va_end (args); if (gpio >= 0) { fprintf (stderr, " (%d, %s)", gpio, func); } else { fprintf (stderr, " (NULL, %s)", func); } fprintf (stderr, "\n"); } #endif } gpio * libsoc_gpio_request (unsigned int gpio_id, gpio_mode mode) { gpio *new_gpio; char tmp_str[STR_BUF]; int shared = 0; if (mode != LS_SHARED && mode != LS_GREEDY && mode != LS_WEAK) { libsoc_gpio_debug (__func__, gpio_id, "mode was not set, or invalid," " setting mode to LS_SHARED"); mode = LS_SHARED; } libsoc_gpio_debug (__func__, gpio_id, "requested gpio"); sprintf (tmp_str, "/sys/class/gpio/gpio%d/value", gpio_id); if (file_valid (tmp_str)) { libsoc_gpio_debug (__func__, gpio_id, "GPIO already exported"); switch (mode) { case LS_WEAK: { return NULL; } case LS_SHARED: { shared = 1; break; } default: { break; } } } else { int fd = file_open ("/sys/class/gpio/export", O_SYNC | O_WRONLY); if (fd < 0) return NULL; sprintf (tmp_str, "%d", gpio_id); if (file_write (fd, tmp_str, STR_BUF) < 0) return NULL; if (file_close (fd)) return NULL; sprintf (tmp_str, "/sys/class/gpio/gpio%d", gpio_id); if (!file_valid (tmp_str)) { libsoc_gpio_debug (__func__, gpio_id, "gpio did not export correctly"); perror ("libsoc-gpio-debug"); return NULL; } } new_gpio = malloc (sizeof (gpio)); if (new_gpio == NULL) return NULL; sprintf (tmp_str, "/sys/class/gpio/gpio%d/value", gpio_id); new_gpio->value_fd = file_open (tmp_str, O_SYNC | O_RDWR); if (new_gpio->value_fd < 0) { free(new_gpio); return NULL; } new_gpio->gpio = gpio_id; new_gpio->shared = shared; new_gpio->callback = NULL; // Set up a pollfd in case we are used for polling later new_gpio->pfd.fd = new_gpio->value_fd; new_gpio->pfd.events = POLLPRI; new_gpio->pfd.revents = 0; return new_gpio; } int libsoc_gpio_free (gpio * gpio) { char tmp_str[STR_BUF]; int fd; if (gpio == NULL) { libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); return EXIT_FAILURE; } libsoc_gpio_debug (__func__, gpio->gpio, "freeing gpio"); if (gpio->callback != NULL) { printf ("Freeing callback!\n"); // Turn off the callback if there is one enabled libsoc_gpio_callback_interrupt_cancel (gpio); } if (file_close (gpio->value_fd) < 0) return EXIT_FAILURE; if (gpio->shared == 1) { free (gpio); return EXIT_SUCCESS; } fd = file_open ("/sys/class/gpio/unexport", O_SYNC | O_WRONLY); if (fd < 0) return EXIT_FAILURE; sprintf (tmp_str, "%d", gpio->gpio); if (file_write (fd, tmp_str, STR_BUF) < 0) return EXIT_FAILURE; if (file_close (fd) < 0) return EXIT_FAILURE; sprintf (tmp_str, "/sys/class/gpio/gpio%d", gpio->gpio); if (file_valid (tmp_str)) { libsoc_gpio_debug (__func__, gpio->gpio, "freeing failed"); return EXIT_FAILURE; } free (gpio); return EXIT_SUCCESS; } int libsoc_gpio_set_direction (gpio * current_gpio, gpio_direction direction) { int fd; char path[STR_BUF]; if (current_gpio == NULL) { libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); return EXIT_FAILURE; } libsoc_gpio_debug (__func__, current_gpio->gpio, "setting direction to %s", gpio_direction_strings[direction]); sprintf (path, "/sys/class/gpio/gpio%d/direction", current_gpio->gpio); fd = file_open (path, O_SYNC | O_WRONLY); if (fd < 0) return EXIT_FAILURE; if (file_write (fd, gpio_direction_strings[direction], STR_BUF) < 0) return EXIT_FAILURE; if (file_close (fd) < 0) return EXIT_FAILURE; return EXIT_SUCCESS; } gpio_direction libsoc_gpio_get_direction (gpio * current_gpio) { int fd; char tmp_str[STR_BUF]; if (current_gpio == NULL) { libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); return DIRECTION_ERROR; } sprintf (tmp_str, "/sys/class/gpio/gpio%d/direction", current_gpio->gpio); fd = file_open (tmp_str, O_RDONLY); if (fd < 0) return DIRECTION_ERROR; lseek (fd, 0, SEEK_SET); if (file_read (fd, tmp_str, STR_BUF) < 0) return DIRECTION_ERROR; if (file_close (fd) < 0) return DIRECTION_ERROR; if (strncmp (tmp_str, "in", 2) <= 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, "read direction as input"); return INPUT; } else { libsoc_gpio_debug (__func__, current_gpio->gpio, "read direction as output"); return OUTPUT; } } int libsoc_gpio_set_level (gpio * current_gpio, gpio_level level) { if (current_gpio == NULL) { libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); return EXIT_FAILURE; } libsoc_gpio_debug (__func__, current_gpio->gpio, "setting level to %d", level); if (file_write (current_gpio->value_fd, gpio_level_strings[level], 1) < 0) return EXIT_FAILURE; return EXIT_SUCCESS; } gpio_level libsoc_gpio_get_level (gpio * current_gpio) { char level[2]; if (current_gpio == NULL) { libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); return LEVEL_ERROR; } lseek (current_gpio->value_fd, 0, SEEK_SET); if (read (current_gpio->value_fd, level, 2) != 2) { libsoc_gpio_debug (__func__, current_gpio->gpio, "level read failed"); perror ("libgpio"); return LEVEL_ERROR; } if (level[0] == '0') { libsoc_gpio_debug (__func__, current_gpio->gpio, "read level as low"); return LOW; } else { libsoc_gpio_debug (__func__, current_gpio->gpio, "read level as high"); return HIGH; } } int libsoc_gpio_set_edge (gpio * current_gpio, gpio_edge edge) { int fd; char path[STR_BUF]; if (current_gpio == NULL) { libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); return EXIT_FAILURE; } libsoc_gpio_debug (__func__, current_gpio->gpio, "setting edge to %s", gpio_edge_strings[edge]); sprintf (path, "/sys/class/gpio/gpio%d/edge", current_gpio->gpio); fd = file_open (path, O_SYNC | O_WRONLY); if (fd < 0) return EXIT_FAILURE; if (file_write (fd, gpio_edge_strings[edge], STR_BUF) < 0) return EXIT_FAILURE; if (file_close (fd) < 0) return EXIT_FAILURE; return EXIT_SUCCESS; } gpio_edge libsoc_gpio_get_edge (gpio * current_gpio) { int fd; char tmp_str[STR_BUF]; if (current_gpio == NULL) { libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); return EDGE_ERROR; } sprintf (tmp_str, "/sys/class/gpio/gpio%d/edge", current_gpio->gpio); fd = file_open (tmp_str, O_RDONLY); if (fd < 0) return EDGE_ERROR; lseek (fd, 0, SEEK_SET); if (file_read (fd, tmp_str, STR_BUF) < 0) return EDGE_ERROR; if (file_close (fd) < 0) return EDGE_ERROR; if (strncmp (tmp_str, "r", 1) == 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, "read edge as rising"); return RISING; } else if (strncmp (tmp_str, "f", 1) == 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, "read edge as falling"); return FALLING; } else if (strncmp (tmp_str, "b", 1) == 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, "read edge as both"); return BOTH; } else { libsoc_gpio_debug (__func__, current_gpio->gpio, "read edge as none"); return NONE; } } int libsoc_gpio_poll (gpio * gpio, int timeout) { int rc; char c; // do an initial read to clear interrupt, rc = lseek(gpio->value_fd, 0, SEEK_SET); rc = read(gpio->value_fd, &c, 1); rc = poll(&gpio->pfd, 1, timeout); if (rc == -1) { libsoc_gpio_debug (__func__, gpio->gpio, "poll failed"); perror ("libsoc-gpio-debug"); return LS_INT_ERROR; } else if (rc == 1 && gpio->pfd.revents & POLLPRI) { // do a final read to clear interrupt rc = read(gpio->value_fd, &c, 1); return LS_INT_TRIGGERED; } return LS_INT_TIMEOUT; } int libsoc_gpio_wait_interrupt (gpio * gpio, int timeout) { if (gpio == NULL) { libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); return LS_INT_ERROR; } if (libsoc_gpio_get_direction (gpio) != INPUT) { libsoc_gpio_debug (__func__, gpio->gpio, "gpio is not set as input"); return LS_INT_ERROR; } gpio_edge test_edge = libsoc_gpio_get_edge (gpio); if (test_edge == EDGE_ERROR || test_edge == NONE) { libsoc_gpio_debug (__func__, gpio->gpio, "edge must be FALLING, RISING or BOTH"); return LS_INT_ERROR; } return libsoc_gpio_poll(gpio, timeout); } void * __libsoc_new_interrupt_callback_thread (void *void_gpio) { gpio *gpio = void_gpio; gpio->callback->ready = 1; // There is an issue here when I believe a couple of interrupts are // missed in the test case, and they occur between ready = 1 and the // start of the poll. Any suggestions would be welcomed... while (1) { if (libsoc_gpio_poll(gpio, -1) == LS_INT_TRIGGERED) { libsoc_gpio_debug (__func__, gpio->gpio, "caught interrupt"); gpio->callback->callback_fn (gpio->callback->callback_arg); } } } int libsoc_gpio_callback_interrupt (gpio * gpio, int (*callback_fn) (void *), void *arg) { pthread_t *poll_thread = malloc (sizeof (pthread_t)); pthread_attr_t pthread_attr; pthread_attr_init (&pthread_attr); pthread_attr_setschedpolicy (&pthread_attr, SCHED_FIFO); struct gpio_callback *new_gpio_callback; libsoc_gpio_debug (__func__, gpio->gpio, "creating new callback"); new_gpio_callback = malloc (sizeof (struct gpio_callback)); new_gpio_callback->callback_fn = callback_fn; new_gpio_callback->callback_arg = arg; new_gpio_callback->thread = poll_thread; gpio->callback = new_gpio_callback; new_gpio_callback->ready = 0; int ret = pthread_create (poll_thread, NULL, __libsoc_new_interrupt_callback_thread, gpio); if (ret == 0) { // Wait for thread to be initialised and ready while (new_gpio_callback->ready != 1) { usleep (50); } } else { free (gpio->callback->thread); free (gpio->callback); return EXIT_FAILURE; } return EXIT_SUCCESS; } int libsoc_gpio_callback_interrupt_cancel (gpio * gpio) { if (gpio->callback->thread == NULL) { libsoc_gpio_debug (__func__, gpio->gpio, "callback thread was NULL"); return EXIT_FAILURE; } pthread_cancel (*gpio->callback->thread); pthread_join (*gpio->callback->thread, NULL); free (gpio->callback->thread); free (gpio->callback); gpio->callback = NULL; libsoc_gpio_debug (__func__, gpio->gpio, "callback thread was stopped"); return EXIT_SUCCESS; } libsoc-0.8.2/lib/i2c.c000066400000000000000000000066471273225013600144010ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "libsoc_i2c.h" #include "libsoc_debug.h" #include "libsoc_file.h" void libsoc_i2c_debug (const char *func, i2c * i2c, char *format, ...) { #ifdef DEBUG if (libsoc_get_debug ()) { va_list args; fprintf (stderr, "libsoc-i2c-debug: "); va_start (args, format); vfprintf (stderr, format, args); va_end (args); if (i2c == NULL) { fprintf (stderr, " (NULL, %s)", func); } else { fprintf (stderr, " (i2c-%d, %d, %s)", i2c->bus, i2c->address, func); } fprintf (stderr, "\n"); } #endif } i2c * libsoc_i2c_init (uint8_t i2c_bus, uint8_t i2c_address) { i2c *i2c_dev; libsoc_i2c_debug (__func__, NULL, "initialising i2c bus %d at " "address %d", i2c_bus, i2c_address); i2c_dev = malloc (sizeof (i2c)); if (i2c_dev == NULL) { libsoc_i2c_debug (__func__, NULL, "failed to allocate memory"); return NULL; } char path[40]; i2c_dev->bus = i2c_bus; i2c_dev->address = i2c_address; sprintf (path, "/dev/i2c-%d", i2c_dev->bus); if (!file_valid (path)) { libsoc_i2c_debug (__func__, i2c_dev, "%s not a vaild device", path); goto error; } i2c_dev->fd = file_open (path, O_SYNC | O_RDWR); if (i2c_dev->fd < 0) { libsoc_i2c_debug (__func__, i2c_dev, "%s could not be opened", path); goto error; } return i2c_dev; error: free (i2c_dev); return NULL; } int libsoc_i2c_free (i2c * i2c) { if (i2c == NULL) { libsoc_i2c_debug (__func__, NULL, "i2c was not valid"); return EXIT_FAILURE; } libsoc_i2c_debug (__func__, i2c, "freeing i2c device"); free (i2c); return EXIT_SUCCESS; } int libsoc_i2c_ioctl(i2c * i2c, int num_messages) { i2c->packets.msgs = i2c->messages; i2c->packets.nmsgs = num_messages; if (ioctl(i2c->fd, I2C_RDWR, &i2c->packets) < 0) { libsoc_i2c_debug(__func__, i2c, "message failed"); perror ("libsoc-i2c-debug"); return EXIT_FAILURE; } return EXIT_SUCCESS; } int libsoc_i2c_set_timeout(i2c * i2c, int timeout) { if (ioctl(i2c->fd, I2C_TIMEOUT, timeout) < 0) { libsoc_i2c_debug(__func__, i2c, "setting timeout failed"); perror ("libsoc-i2c-debug"); return EXIT_FAILURE; } libsoc_i2c_debug(__func__, i2c, "timeout set to %dms", (timeout*10)); return EXIT_SUCCESS; } int libsoc_i2c_write (i2c * i2c, uint8_t * buffer, uint16_t len) { if (i2c == NULL || buffer == NULL) { libsoc_i2c_debug (__func__, i2c, "i2c | buffer was NULL"); return EXIT_FAILURE; } libsoc_i2c_debug(__func__, i2c, "Writing buffer of length %d", len); i2c->messages[0].addr = i2c->address; i2c->messages[0].flags = 0; i2c->messages[0].len = len; i2c->messages[0].buf = buffer; return libsoc_i2c_ioctl(i2c, 1); } int libsoc_i2c_read (i2c * i2c, uint8_t * buffer, uint16_t len) { if (i2c == NULL || buffer == NULL) { libsoc_i2c_debug (__func__, i2c, "i2c | buffer was NULL"); return EXIT_FAILURE; } libsoc_i2c_debug(__func__, i2c, "Reading buffer of length %d", len); i2c->messages[0].addr = i2c->address; i2c->messages[0].flags = I2C_M_RD; i2c->messages[0].len = len; i2c->messages[0].buf = buffer; return libsoc_i2c_ioctl(i2c, 1); } libsoc-0.8.2/lib/include/000077500000000000000000000000001273225013600151665ustar00rootroot00000000000000libsoc-0.8.2/lib/include/libsoc_board.h000066400000000000000000000021641273225013600177640ustar00rootroot00000000000000#ifndef _LIBSOC_GPIO_ID_H_ #define _LIBSOC_GPIO_ID_H_ #ifdef __cplusplus extern "C" { #endif #include "libsoc_conffile.h" /** * \struct board_config * \brief a struct to hold board specific information * \param conf* - the board config file */ typedef struct { conffile *conf; } board_config; /** * \fn board_config* libsoc_board_init() * \brief initialize board specific values like gpio mappings * \return board_config* or NULL */ board_config *libsoc_board_init(); /** * \fn int libsoc_board_free(board_config *config) * \brief free up memory created from call to libsoc_board_init * \param board_config* config - valid pointer to board_config * \return void */ void libsoc_board_free(board_config *config); /** * \fn unsigned int libsoc_gpio_id(board_config* config, const char* pin) * \brief find the gpio id of a given pin name * \param board_config* config - valid pointer to board_config * \param char* pin - a pin name for the board like "P49" * \return >=0 for gpio id or -1 on failure */ unsigned int libsoc_board_gpio_id(board_config *config, const char* pin); #ifdef __cplusplus } #endif #endif libsoc-0.8.2/lib/include/libsoc_conffile.h000066400000000000000000000040161273225013600204600ustar00rootroot00000000000000#ifndef _LIBSOC_CONFFILE_H_ #define _LIBSOC_CONFFILE_H_ #ifdef __cplusplus extern "C" { #endif /** * \struct keyval * \brief a linked list of key-value pairs * \param char *key - the name of the key * \param char *val - the value of the key * \param keyval* - the next key-value pair */ typedef struct keyval { char *key; char *val; struct keyval *next; } keyval; /** * \struct section * \brief Contains the key-value pairs in a given section * \param char *name - the section name * \param keyval *settings - the key-value pairs for the section * \param section* - the next section in the list */ typedef struct section { char name[16]; keyval *settings; struct section *next; } section; /** * \struct confile * \brief Contains a list of sections * \param section* section - the HEAD pointer of the section list */ typedef struct conffile { section *sections; } conffile; /** * \fn conffile *conffile_load(const char *path) * \brief Loads a given configuration file * \param char* path - The path to the file * \return NULL on error */ conffile* conffile_load(const char *path); /** * \fn conffile *conffile_free(conffile*) * \brief Frees memory allocated in conffile struct */ void conffile_free(conffile *conf); /** * \fn const char *conffile_get(conffile *conf, const char *sectname, const char *key, const char *defval) * \brief Find the key in the given section of conffile and return its value. * \return The value found in the conffile or defval if one is not found. */ const char* conffile_get(conffile *conf, const char *sectname, const char *key, const char *defval); /** * \fn int *conffile_get_int(conffile *conf, const char *sectname, const char *key, int defval) * \brief Find the key in the given section of conffile and return its integer * value. * \brief Returns the value for the given section and key or defval if the key * isn't found or is not numeric. */ int conffile_get_int(conffile *conf, const char *sectname, const char *key, int defval); #ifdef __cplusplus } #endif #endif libsoc-0.8.2/lib/include/libsoc_debug.h000066400000000000000000000005501273225013600177600ustar00rootroot00000000000000#ifndef _LIBSOC_DEBUG_H_ #define _LIBSOC_DEBUG_H_ #ifdef __cplusplus extern "C" { #endif void libsoc_debug(const char *func, char *format, ...) __attribute__((format(printf, 2, 3))); void libsoc_warn(const char *format, ...) __attribute__((format(printf, 1, 2))); int libsoc_get_debug(); void libsoc_set_debug(int level); #ifdef __cplusplus } #endif #endif libsoc-0.8.2/lib/include/libsoc_file.h000066400000000000000000000012431273225013600176110ustar00rootroot00000000000000#ifndef _LIBSOC_FILE_H_ #define _LIBSOC_FILE_H_ #ifdef __cplusplus extern "C" { #endif int file_open(const char* path, int flags); int file_write(int fd, const char* str, int len); int file_read(int fd, void *buf, int count); int file_valid(char* path); int file_close(int fd); int file_write_int(char *path, int val); int file_read_str(char *path, char *tmp, int buf_len); int file_write_str(char *path, char* buf, int len); int file_read_int(char *path, int *tmp); int file_read_int_fd(int fd, int *tmp); int file_write_int_fd(int fd, int val); int file_write_int_path(char *path, int val); char* file_read_contents(const char *path); #ifdef __cplusplus } #endif #endif libsoc-0.8.2/lib/include/libsoc_gpio.h000066400000000000000000000146631273225013600176420ustar00rootroot00000000000000#ifndef _LIBSOC_GPIO_H_ #define _LIBSOC_GPIO_H_ #include #include #ifdef __cplusplus extern "C" { #endif /** * \struct gpio_callback * \brief representation of an interrupt callback * \param int (*callback_fn)(void*) - the function to callback on interrupt * \param void *callback_arg - the argument to pass to the callback function * \param pthread_t *thread - the pthread struct on which the poll and * callback function runs * \param int ready - signal when the pthread is ready to accept interrupts */ struct gpio_callback { int (*callback_fn) (void *); void *callback_arg; pthread_t *thread; int ready; }; /** * \struct gpio * \brief representation of a single requested gpio * \param unsigned int gpio gpio id * \param int value_fd file descriptor to gpio value file * \param struct gpio_callback *callback - struct used to store interrupt * callback data * \param int shared - set if the request flag was shared and the GPIO was * exported on request */ typedef struct { unsigned int gpio; int value_fd; struct gpio_callback *callback; struct pollfd pfd; int shared; } gpio; /** * \enum gpio_int_ret * \brief defined values for return type of blocked gpio interrupts */ typedef enum { LS_INT_ERROR = EXIT_FAILURE, LS_INT_TRIGGERED = EXIT_SUCCESS, LS_INT_TIMEOUT, } gpio_int_ret; /** * \enum gpio_direction * \brief defined values for input/output direction */ typedef enum { DIRECTION_ERROR = -1, INPUT = 0, OUTPUT = 1, } gpio_direction; /** * \enum gpio_level * \brief defined values for high/low gpio level */ typedef enum { LEVEL_ERROR = -1, LOW = 0, HIGH = 1, } gpio_level; /** * \enum gpio_edge * \brief defined values for rising/falling/none/both gpio edge */ typedef enum { EDGE_ERROR = -1, RISING = 0, FALLING = 1, NONE = 2, BOTH = 3, } gpio_edge; /** * \enum gpio_mode * * LS_SHARED - if the gpio is already exported then it will not unexport * the GPIO on free. If it is not exported, then it will * unexport on free. * * LS_GREEDY - will succeed if the GPIO is already exported, but will * always unexport the GPIO on free. * * LS_WEAK - will fail if GPIO is already exported, will always unexport * on free. */ typedef enum gpio_mode { LS_SHARED, LS_GREEDY, LS_WEAK, } gpio_mode; /** * \fn gpio* libsoc_gpio_request(unsigned int gpio_id) * \brief request a gpio to use * \param unsigned int gpio_id - the id of the gpio you wish to request * \param unsigned int mode - mode for opening GPIO * \return pointer to gpio* on success NULL on fail * */ gpio *libsoc_gpio_request(unsigned int gpio_id, enum gpio_mode mode); /** * \fn int libsoc_gpio_free(gpio* gpio) * \brief free a previously requested gpio * \param gpio* gpio - valid pointer to a requested gpio * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_gpio_free(gpio * gpio); /** * \fn int libsoc_gpio_set_direction(gpio* current_gpio, gpio_direction direction) * \brief set GPIO to input or output * \param gpio* current_gpio - pointer to gpio struct on which to set the direction * \param gpio_direction direction - enumerated direction, INPUT or OUTPUT * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_gpio_set_direction(gpio * current_gpio, gpio_direction direction); /** * \fn gpio_direction libsoc_gpio_get_direction(gpio* current_gpio) * \brief get the current direction of the gpio * \param gpio* current_gpio - pointer to gpio struct on which to get the direction * \return current GPIO direction, INPUT or OUTPUT */ gpio_direction libsoc_gpio_get_direction(gpio * current_gpio); /** * \fn in libsoc_gpio_set_level(gpio* current_gpio, gpio_level level) * \brief set the GPIO level to high or low * \param gpio* current_gpio - pointer to gpio struct on which to set the level * \param gpio_level level = enumerated gpio_level, HIGH or LOW * \return EXIT_SUCCES or EXIT_FAILURE */ int libsoc_gpio_set_level(gpio * current_gpio, gpio_level level); /** * \fn gpio_level libsoc_gpio_get_level(gpio* current_gpio) * \brief gets the current gpio level * \param gpio* current_gpio - pointer to gpio struct on which to get the level * \return gpio_level, HIGH or LOW */ gpio_level libsoc_gpio_get_level(gpio * current_gpio); /** * \fn gpio_edge libsoc_gpio_get_edge(gpio* current_gpio) * \brief gets the current gpio edge value * \param gpio* current_gpio - pointer to gpio struct on which to get the edge * \return gpio_edge, RISING, FALLING or NONE */ gpio_edge libsoc_gpio_get_edge(gpio * current_gpio); /** * \fn int libsoc_gpio_set_edge(gpio* current_gpio, gpio_edge edge) * \brief sets the edge value of a gpio for interrupt generation * \param gpio* current_gpio - the gpio for which you wish to set the edge * \param gpio_edge edge - enumerated edge value, RISING, FALLING or NONE * \return EXIT_SUCCESS or EXIT FAILURE */ int libsoc_gpio_set_edge(gpio * current_gpio, gpio_edge edge); /** * \fn int libsoc_gpio_wait_interrupt(gpio* gpio, int timeout) * \brief takes a gpio and waits for length of timeout or until an * interrupt occurs. Will return EXIT_SUCCESS on interrupt or * EXIT_FAILURE on error or timeout. * \param gpio* gpio - the gpio for which you want to wait on interrupt * \param int timeout - the max length of time to wait for interrupt in * milliseconds * \return EXIT_SUCCESS on interrupt caught, EXIT_FAILURE on error or * interrupt missed */ int libsoc_gpio_wait_interrupt(gpio * gpio, int timeout); /** * \fn int libsoc_gpio_callback_interrupt(gpio* gpio, int (*callback_fn)(void*), void* arg) * \brief takes a gpio and a callback function, when an interrupt occurs * on the edge previously specified, the callback function is called * \param gpio* gpio - the gpio for which you want the interrupt to * trigger the callback function * \param int (*callback_fn)(void*) - the function you wish to call with * a void* pointer to a possible value you may wish to use in the callback. * \param void* arg - pointer to data you wish to use in the callback function * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_gpio_callback_interrupt(gpio * gpio, int (*callback_fn) (void *), void *arg); /** * \fn int libsoc_gpio_callback_interrupt_cancel(gpio* gpio) * \brief cancel a callback on a gpio interrupt * \param gpio* gpio - gpio with a valid callback enabled * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_gpio_callback_interrupt_cancel(gpio * gpio); #ifdef __cplusplus } #endif #endif libsoc-0.8.2/lib/include/libsoc_i2c.h000066400000000000000000000042121273225013600173460ustar00rootroot00000000000000#ifndef _LIBSOC_I2C_H_ #define _LIBSOC_I2C_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * \struct i2c * \brief representation of spi device and chipselect * \param int fd - file descriptor to open i2c device * \param uint8_t bus - i2c bus number * \param uint8_t address - address of i2c device on the bus */ typedef struct { int fd; uint8_t bus; uint8_t address; struct i2c_rdwr_ioctl_data packets; struct i2c_msg messages[2]; } i2c; /** * \fn i2c * libsoc_i2c_init (uint8_t i2c_bus, uint8_t i2c_address) * \brief initialises new i2c instance at specified address * \param uint8_t i2c_bus - the linux enumerated bus number * \param uint8_t i2c_address - * \return i2c* struct pointer or NULL on failure */ i2c * libsoc_i2c_init (uint8_t i2c_bus, uint8_t i2c_address); /** * \fn libsoc_i2c_free (i2c * i2c) * \brief frees the malloced i2c struct * \param i2c* i2c - valid i2c struct pointer * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_i2c_free (i2c * i2c); /** * \fn libsoc_i2c_write(i2c *i2c, uint8_t *buffer, uint16_t len) * \brief write a specified amount of data to i2c slave * \param i2c *i2c - valid i2c device struct * \param uint8_t *buffer - pointer to output data buffer * \param uint16_t len - length of buffer in bytes * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_i2c_write (i2c * i2c, uint8_t * buffer, uint16_t len); /** * \fn libsoc_i2c_read(i2c *i2c, uint8_t *buffer, uint16_t len) * \brief read a specified amount of data from an i2c slave * \param i2c *i2c - valid i2c device struct * \param uint8_t *buffer - pointer to input data buffer * \param uint16_t len - length of buffer in bytes * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_i2c_read (i2c * i2c, uint8_t * buffer, uint16_t len); /** * \fn libsoc_i2c_set_timeout(i2c *i2c, int timeout) * \brief set the timeout in is 10's of milliseconds, i.e. a timeout of * 2 is 2 x 10ms = 20ms * \param i2c *i2c - valid i2c device struct * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_i2c_set_timeout(i2c * i2c, int timeout); #ifdef __cplusplus } #endif #endif libsoc-0.8.2/lib/include/libsoc_pwm.h000066400000000000000000000110301273225013600174700ustar00rootroot00000000000000#ifndef _LIBSOC_PWM_H_ #define _LIBSOC_PWM_H_ #ifdef __cplusplus extern "C" { #endif /** * \struct pwm * \brief representation of a single requested pwm * \param unsigned int pwm - pwm num * \param unsigned int pwm_chip - pwm chip num * \param int enabled_fd - file descriptor to pwm enable file * \param int duty_fd - file descriptor to pwm duty_cycle file * \param int period_fd - file descriptor to pwm period file * \param int shared - set if the request flag was shared and the pwm was * exported on request */ typedef struct { unsigned int chip; unsigned int pwm; int enable_fd; int duty_fd; int period_fd; int shared; } pwm; /** * \enum pwm_enabled * \brief defined values for pwm enabled/disabled */ typedef enum { ENABLED_ERROR = -1, DISABLED = 0, ENABLED = 1, } pwm_enabled; /** * \enum pwm_polarity * \brief defined values for pwm polarity */ typedef enum { POLARITY_ERROR = -1, NORMAL = 0, INVERSED = 1, } pwm_polarity; /** * \enum shared_mode * * LS_SHARED - if the pwm is already exported then it will not unexport * the PWM on free. If it is not exported, then it will * unexport on free. * * LS_GREEDY - will succeed if the PWM is already exported, but will * always unexport the PWM on free. * * LS_WEAK - will fail if PWM is already exported, will always unexport * on free. */ typedef enum { LS_SHARED, LS_GREEDY, LS_WEAK, } shared_mode; /** * \fn pwm* libsoc_pwm_request(unsigned int pwm_chip, unsigned int pwm_num) * \brief request a pwm to use * \param unsigned int pwm_chip - the chip number that controls the pwm you wish to use * \param unsigned int pwm_num - the pwm number number within your pwm chip * \param unsigned int mode - mode for opening PWM * \return pointer to pwm* on success NULL on fail * */ pwm* libsoc_pwm_request(unsigned int pwm_chip, unsigned int pwm_num, shared_mode mode); /** * \fn int libsoc_pwm_free(pwm* pwm) * \brief free a previously requested pwm * \param pwm* pwm - valid pointer to a requested pwm * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_pwm_free(pwm *pwm); /** * \fn int libsoc_pwm_set_enabled(pwm *pwm, pwm_enabled enabled) * \brief set PWM enabled/disabled * \param pwm* pwm - pointer to pwm struct on which to set enabled * \param pwm_enabled enabled - enumerated enabled status, ENABLED or DISABLED * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_pwm_set_enabled(pwm *pwm, pwm_enabled enabled); /** * \fn libsoc_pwm_get_enabled(pwm *pwm) * \brief get the current enabled status of the PWM * \param pwm *pwm - pointer to pwm struct on which to get the enabled status * \return current PWM enabled status, ENABLED,DISABLED or ERROR_ENABLED */ pwm_enabled libsoc_pwm_get_enabled(pwm *pwm); /** * \fn libsoc_pwm_set_polarity(pwm *pwm, pwm_polarity polarity) * \brief set the PWM polarity to normal or inverted * \param pwm *pwm - pointer to pwm struct on which to set the polarity * \param pwm_polarity = enumerated pwm_polarity NORMAL or INVERTED * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_pwm_set_polarity(pwm *pwm, pwm_polarity polarity); /** * \fn libsoc_pwm_get_polarity(pwm *pwm) * \brief gets the current pwm polarity * \param pwm *pwm - pointer to pwm struct on which to get the polarity * \return pwm_polarity - NORMAL, INVERTED or ERROR_POLARITY */ pwm_polarity libsoc_pwm_get_polarity(pwm *pwm); /** * \fn libsoc_pwm_set_duty_cycle(pwm *pwm, int duty) * \brief set the PWM duty cycle (active time of the PWM signal) * \param pwm *pwm - pointer to valid pwm struct * \param int duty - duty value in nanoseconds, must be less than period * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_pwm_set_duty_cycle(pwm *pwm, unsigned int duty); /** * \fn libsoc_pwm_get_duty_cycle(pwm *pwm) * \brief gets the current pwm duty cycle * \param pwm *pwm - pointer to valid pwm struct * \return duty_cycle - integer, -1 on failure */ int libsoc_pwm_get_duty_cycle(pwm *pwm); /** * \fn libsoc_pwm_set_period(pwm *pwm, unsigned int period) * \brief set the PWM period (sum of the active and inactive * time of the PWM) * \param pwm *pwm - pointer to valid pwm struct * \param int period - period value in nanoseconds * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_pwm_set_period(pwm *pwm, unsigned int period); /** * \fn libsoc_pwm_get_period(pwm *pwm) * \brief gets the current pwm period * \param pwm *pwm - pointer to valid pwm struct * \return period - integer, -1 on failure */ int libsoc_pwm_get_period(pwm *pwm); #ifdef __cplusplus } #endif #endif libsoc-0.8.2/lib/include/libsoc_spi.h000066400000000000000000000115051273225013600174670ustar00rootroot00000000000000#ifndef _LIBSOC_SPI_H_ #define _LIBSOC_SPI_H_ #include #ifdef __cplusplus extern "C" { #endif /** * \struct spi * \brief representation of spi device and chipselect * \param int fd - file descriptor to open spidev character device * \param struct gpio_callback *callback - struct used to store interrupt * callback data * \param uint8_t spi_dev - major number of spi device * \param uint8_t spi_dev - minor number of spi device */ typedef struct { int fd; uint8_t spi_dev; uint8_t chip_select; } spi; /** * \enum gpio_direction * \brief defined values for bits per word */ typedef enum { BITS_8 = 8, BITS_16 = 16, BPW_ERROR, } spi_bpw; /** * \enum gpio_direction * \brief defined values for spi modes */ typedef enum { MODE_0 = 0, MODE_1 = 1, MODE_2 = 2, MODE_3 = 3, MODE_ERROR, } spi_mode; /** * \fn spi* libsoc_spi_init (uint8_t spidev_device, uint8_t chip_select) * \brief opens the spidev character device and intitialises a new spi * struct * \param uint8_t spidev_device - the major spidev number * \param uint8_t spidev_device - the minor spidev number * \return spi* struct pointer or NULL on failure */ spi* libsoc_spi_init (uint8_t spidev_device, uint8_t chip_select); /** * \fn int libsoc_spi_free(spi* spi) * \brief frees the malloced spi struct * \param spi* spi - valid spi struct pointer * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_spi_free(spi* spi); /** * \fn int libsoc_spi_set_mode(spi* spi, spi_mode mode) * \brief sets the spi mode for the spi device * \param spi* spi - valid spi struct pointer * \param enum spi_mode - valid modes are as follows: * -MODE_0, MODE_1, MODE_2, MODE_3 * Essential Reading: * - https://www.kernel.org/doc/Documentation/spi/spi-summary * - http://www.diolan.com/dln_doc/spi-transfer-modes.html * - http://blackfin.uclinux.org/doku.php?id=spi * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_spi_set_mode(spi* spi, spi_mode mode); /** * \fn int libsoc_spi_set_bits_per_word(spi* spi, spi_bpw bpw) * \brief sets the bits per word of the spi transfer, either 8 or 16 * \param spi* spi - valid spi struct pointer * \param enum spi_bpw - bits per word eith BITS_8 or BITS_16 * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_spi_set_bits_per_word(spi* spi, spi_bpw bpw); /** * \fn int libsoc_spi_set_speed(spi* spi, uint32_t speed) * \brief sets the speed of the spi bus, speed can sometimes be changed * to a sensible value by the kernel, so always do a get and check after * setting the speed. * \param spi* spi - valid spi struct pointer * \param uint32_t speed - set the spi bus speed in Hz * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_spi_set_speed(spi* spi, uint32_t speed); /** * \fn spi_mode libsoc_spi_get_mode(spi* spi) * \brief gets the current mode of the spi bus * \param spi* spi - valid spi struct pointer * \return enum spi_mode - MODE_0/1/2/3 on success, MODE_ERROR on fail */ spi_mode libsoc_spi_get_mode(spi* spi); /** * \fn uint32_t libsoc_spi_get_speed(spi* spi) * \brief gets the current speed of the spi bus * \param spi* spi - valid spi struct pointer * \return uint32 - current speed of spi bus in Hz */ uint32_t libsoc_spi_get_speed(spi* spi); /** * \fn spi_bpw libsoc_spi_get_bits_per_word(spi* spi) * \brief gets the current bits per word of the spi bus * \param spi* spi - valid spi struct pointer * \return enum spi_bpw - BITS_8/16 on success, BITS_ERROR on fail */ spi_bpw libsoc_spi_get_bits_per_word(spi* spi); /** * \fn int libsoc_spi_write(spi* spi, uint8_t* tx, uint32_t len) * \brief writes data to the spi bus * \param spi* spi - valid spi struct pointer * \param uint8_t* tx - array of bytes to send on the bus * \param uint32_t len - the length of the transfer in bytes * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_spi_write(spi* spi, uint8_t* tx, uint32_t len); /** * \fn int libsoc_spi_read(spi* spi, uint8_t* rx, uint32_t len) * \brief reads data from the spi bus * \param spi* spi - valid spi struct pointer * \param uint8_t* rx - array of bytes to populate with data from the bus * \param uint32_t len - the length of the transfer in bytes * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_spi_read(spi* spi, uint8_t* rx, uint32_t len); /** * \fn int libsoc_spi_rw(spi* spi, uint8_t* tx, uint8_t* rx, uint32_t len) * \brief duplex read/write to the spi bus, allows writing data and then * reading back in one single transaction, or writing and reading at the * same time. * \param spi* spi - valid spi struct pointer * \param uint8_t* tx - array of bytes to send on the bus * \param uint8_t* rx - array of bytes to populate with data from the bus * \param uint32_t len - the length of the transfer in bytes * \return EXIT_SUCCESS or EXIT_FAILURE */ int libsoc_spi_rw(spi* spi, uint8_t* tx, uint8_t* rx, uint32_t len); #ifdef __cplusplus } #endif #endif libsoc-0.8.2/lib/pwm.c000066400000000000000000000164131273225013600145170ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "libsoc_file.h" #include "libsoc_debug.h" #include "libsoc_pwm.h" #define STR_BUF 256 static char pwm_polarity_strings[2][STR_BUF] = { "normal", "inversed" }; static char pwm_enabled_strings[2][STR_BUF] = { "0", "1" }; void libsoc_pwm_debug (const char *func, unsigned int chip, unsigned int pwm, char *format, ...) { #ifdef DEBUG if (libsoc_get_debug ()) { va_list args; fprintf (stderr, "libsoc-pwm-debug: "); va_start (args, format); vfprintf (stderr, format, args); va_end (args); fprintf (stderr, " ((%d,%d), %s)", chip, pwm, func); fprintf (stderr, "\n"); } #endif } pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, shared_mode mode) { pwm *new_pwm; char tmp_str[STR_BUF]; int shared = 0; if (mode != LS_SHARED && mode != LS_GREEDY && mode != LS_WEAK) { libsoc_pwm_debug (__func__, chip, pwm_num, "mode was not set, or invalid, setting mode to LS_SHARED"); mode = LS_SHARED; } libsoc_pwm_debug (__func__, chip, pwm_num, "requested PWM"); sprintf (tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, pwm_num); if (file_valid (tmp_str)) { libsoc_pwm_debug(__func__, chip, pwm_num, "PWM already exported"); switch(mode) { case LS_WEAK: { return NULL; } case LS_SHARED: { shared = 1; break; } default: { break; } } } else { sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/export", chip); if (file_write_int_path(tmp_str, pwm_num) == EXIT_FAILURE) { libsoc_pwm_debug(__func__, chip, pwm_num, "write failed"); return NULL; } sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, pwm_num); if (!file_valid(tmp_str)) { libsoc_pwm_debug(__func__, chip, pwm_num, "failed to export PWM"); perror("libsoc-pwm-debug"); return NULL; } } new_pwm = malloc(sizeof(pwm)); sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, pwm_num); new_pwm->enable_fd = file_open(tmp_str, O_SYNC | O_RDWR); sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/period", chip, pwm_num); new_pwm->period_fd = file_open(tmp_str, O_SYNC | O_RDWR); sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/duty_cycle", chip, pwm_num); new_pwm->duty_fd = file_open(tmp_str, O_SYNC | O_RDWR); if (new_pwm->enable_fd < 0 || new_pwm->period_fd < 0 || new_pwm->duty_fd < 0) { free(new_pwm); libsoc_pwm_debug(__func__, chip, pwm_num, "Failed to open pwm sysfs file: %d", new_pwm->enable_fd); return NULL; } new_pwm->chip = chip; new_pwm->pwm = pwm_num; new_pwm->shared = shared; return new_pwm; } int libsoc_pwm_free(pwm *pwm) { char path[STR_BUF]; if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return EXIT_FAILURE; } libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "freeing pwm"); if (file_close(pwm->enable_fd) < 0) { return EXIT_FAILURE; } if (file_close(pwm->period_fd) < 0) { return EXIT_FAILURE; } if (file_close(pwm->duty_fd) < 0) { return EXIT_FAILURE; } if (pwm->shared == 1) { free(pwm); return EXIT_SUCCESS; } sprintf(path, "/sys/class/pwm/pwmchip%d/unexport", pwm->chip); file_write_int_path(path, pwm->pwm); sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d", pwm->chip, pwm->pwm); if (file_valid(path)) { libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "freeing failed"); return EXIT_FAILURE; } free(pwm); return EXIT_SUCCESS; } int libsoc_pwm_set_enabled(pwm *pwm, pwm_enabled enabled) { char path[STR_BUF]; if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return EXIT_FAILURE; } if (enabled != ENABLED && enabled != DISABLED) { return EXIT_FAILURE; } libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "setting enabled to %s", pwm_enabled_strings[enabled]); sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/enable", pwm->chip, pwm->pwm); return file_write_str(path, pwm_enabled_strings[enabled], 1); } pwm_enabled libsoc_pwm_get_enabled(pwm *pwm) { int val; if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return ENABLED_ERROR; } if (file_read_int_fd(pwm->enable_fd, &val) == EXIT_FAILURE) { return ENABLED_ERROR; } if(val == 1) { libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "read as enabled"); return ENABLED; } else if (val == 0) { libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "read as disabled"); return DISABLED; } else { return ENABLED_ERROR; } } int libsoc_pwm_set_period(pwm *pwm, unsigned int period) { if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return EXIT_FAILURE; } libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "setting period to %d", period); return file_write_int_fd(pwm->period_fd, period); } int libsoc_pwm_set_duty_cycle(pwm *pwm, unsigned int duty) { if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return EXIT_FAILURE; } libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "setting duty to %d", duty); return file_write_int_fd(pwm->duty_fd, duty); } int libsoc_pwm_get_period(pwm *pwm) { int period = -1; if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return -1; } file_read_int_fd(pwm->period_fd, &period); libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "got period as %d", period); return period; } int libsoc_pwm_get_duty_cycle(pwm *pwm) { int duty = -1; if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return -1; } file_read_int_fd(pwm->duty_fd, &duty); libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "got duty as %d", duty); return duty; } int libsoc_pwm_set_polarity(pwm *pwm, pwm_polarity polarity) { char path[STR_BUF]; if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return EXIT_FAILURE; } if (polarity != NORMAL && polarity != INVERSED) { return EXIT_FAILURE; } libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "setting polarity to %s", pwm_polarity_strings[polarity]); sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/polarity", pwm->chip, pwm->pwm); return file_write_str(path, pwm_polarity_strings[polarity], STR_BUF); } int libsoc_pwm_get_polarity(pwm *pwm) { int polarity; char path[STR_BUF]; char tmp_str[1]; if (pwm == NULL) { libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); return EXIT_FAILURE; } sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/polarity", pwm->chip, pwm->pwm); if (file_read_str(path, tmp_str, 1) == EXIT_FAILURE) { return POLARITY_ERROR; } if (strncmp(tmp_str, "i", 1) == 0) { polarity = INVERSED; } else if (strncmp(tmp_str, "n", 1) == 0) { polarity = NORMAL; } else { polarity = POLARITY_ERROR; } if (polarity > 0) { libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "got polarity as %s", pwm_polarity_strings[polarity]); } else { libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "getting polarity failed"); } return polarity; } libsoc-0.8.2/lib/spi.c000066400000000000000000000166301273225013600145100ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include "libsoc_spi.h" #include "libsoc_debug.h" #include "libsoc_file.h" void libsoc_spi_debug (const char *func, spi * spi, char *format, ...) { #ifdef DEBUG if (libsoc_get_debug ()) { va_list args; fprintf (stderr, "libsoc-spi-debug: "); va_start (args, format); vfprintf (stderr, format, args); va_end (args); if (spi == NULL) { fprintf (stderr, " (NULL, %s)", func); } else { fprintf (stderr, " (spidev%d.%d, %s)", spi->spi_dev, spi->chip_select, func); } fprintf (stderr, "\n"); } #endif } spi * libsoc_spi_init (uint8_t spidev_device, uint8_t chip_select) { spi *spi_dev; libsoc_spi_debug (__func__, NULL, "initialising spidev device %d.%d", spidev_device, chip_select); spi_dev = malloc (sizeof (spi)); if (spi_dev == NULL) { libsoc_spi_debug (__func__, NULL, "failed to allocate memory"); return NULL; } char path[40]; spi_dev->spi_dev = spidev_device; spi_dev->chip_select = chip_select; sprintf (path, "/dev/spidev%d.%d", spi_dev->spi_dev, spi_dev->chip_select); if (!file_valid (path)) { libsoc_spi_debug (__func__, spi_dev, "%s not a vaild device", path); goto error; } spi_dev->fd = file_open (path, O_SYNC | O_RDWR); if (spi_dev->fd < 0) { libsoc_spi_debug (__func__, spi_dev, "%s could not be opened", path); goto error; } return spi_dev; error: free (spi_dev); return NULL; } int libsoc_spi_set_bits_per_word (spi * spi, spi_bpw bpw) { if (bpw != BITS_8 && bpw != BITS_16) { libsoc_spi_debug (__func__, spi, "bits per word was not BITS_8" " or BITS_16", bpw); return EXIT_FAILURE; } libsoc_spi_debug (__func__, spi, "setting bits per word to %d", bpw); int ret = ioctl (spi->fd, SPI_IOC_WR_BITS_PER_WORD, &bpw); if (ret == -1) { libsoc_spi_debug (__func__, spi, "failed setting bits per word"); return EXIT_FAILURE; } return EXIT_SUCCESS; } spi_bpw libsoc_spi_get_bits_per_word (spi * spi) { uint8_t bpw; int ret = ioctl (spi->fd, SPI_IOC_RD_BITS_PER_WORD, &bpw); if (ret == -1) { libsoc_spi_debug (__func__, spi, "failed reading bits per word"); return BPW_ERROR; } switch (bpw) { case 8: libsoc_spi_debug (__func__, spi, "read bits per word as 8"); return BITS_8; case 16: libsoc_spi_debug (__func__, spi, "read bits per word as 16"); return BITS_16; default: libsoc_spi_debug (__func__, spi, "bits per word not recognised"); return BPW_ERROR; } } int libsoc_spi_set_speed (spi * spi, uint32_t speed) { libsoc_spi_debug (__func__, spi, "setting speed to %dHz", speed); int ret = ioctl (spi->fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret == -1) { libsoc_spi_debug (__func__, spi, "failed setting speed"); return EXIT_FAILURE; } return EXIT_SUCCESS; } uint32_t libsoc_spi_get_speed (spi * spi) { uint32_t speed; int ret = ioctl (spi->fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); if (ret == -1) { libsoc_spi_debug (__func__, spi, "failed reading speed"); return -1; } libsoc_spi_debug (__func__, spi, "read speed as %dHz", speed); return speed; } int libsoc_spi_set_mode (spi * spi, spi_mode mode) { if (spi == NULL) { libsoc_spi_debug (__func__, NULL, "spi was not valid"); return EXIT_FAILURE; } libsoc_spi_debug (__func__, spi, "setting mode to %d", mode); uint8_t new_mode; switch (mode) { case MODE_0: new_mode = SPI_MODE_0; break; case MODE_1: new_mode = SPI_MODE_1; break; case MODE_2: new_mode = SPI_MODE_2; break; case MODE_3: new_mode = SPI_MODE_3; break; default: return EXIT_FAILURE; } int ret = ioctl (spi->fd, SPI_IOC_WR_MODE, &new_mode); if (ret == -1) { libsoc_spi_debug (__func__, spi, "failed setting mode"); return EXIT_FAILURE; } return EXIT_SUCCESS; } spi_mode libsoc_spi_get_mode (spi * spi) { uint8_t mode; if (spi == NULL) { libsoc_spi_debug (__func__, NULL, "spi was not valid"); return EXIT_FAILURE; } int ret = ioctl (spi->fd, SPI_IOC_RD_MODE, &mode); if (ret == -1) { libsoc_spi_debug (__func__, spi, "failed reading mode"); return MODE_ERROR; } switch (mode) { case SPI_MODE_0: libsoc_spi_debug (__func__, spi, "read mode as 0"); return MODE_0; case SPI_MODE_1: libsoc_spi_debug (__func__, spi, "read mode as 1"); return MODE_1; case SPI_MODE_2: libsoc_spi_debug (__func__, spi, "read mode as 2"); return MODE_2; case SPI_MODE_3: libsoc_spi_debug (__func__, spi, "read mode as 3"); return MODE_3; default: libsoc_spi_debug (__func__, spi, "mode not recognised"); return MODE_ERROR; } } int libsoc_spi_write (spi * spi, uint8_t * tx, uint32_t len) { libsoc_spi_debug (__func__, spi, "performing write transfer of %d bytes", len); if (spi == NULL || tx == NULL) { libsoc_spi_debug (__func__, spi, "spi or tx was NULL"); return EXIT_FAILURE; } if (len <= 0) { libsoc_spi_debug (__func__, spi, "length was less than zero"); return EXIT_FAILURE; } int ret; struct spi_ioc_transfer tr = { .tx_buf = (unsigned long) tx, .len = len, }; ret = ioctl (spi->fd, SPI_IOC_MESSAGE (1), &tr); if (ret < 1) { libsoc_spi_debug (__func__, spi, "failed sending message"); return EXIT_FAILURE; } return EXIT_SUCCESS; } int libsoc_spi_read (spi * spi, uint8_t * rx, uint32_t len) { libsoc_spi_debug (__func__, spi, "performing read transfer of %d bytes", len); if (spi == NULL || rx == NULL) { libsoc_spi_debug (__func__, spi, "spi or rx was NULL"); return EXIT_FAILURE; } if (len <= 0) { libsoc_spi_debug (__func__, spi, "length was less than zero"); return EXIT_FAILURE; } int ret; struct spi_ioc_transfer tr = { .rx_buf = (unsigned long) rx, .len = len, }; ret = ioctl (spi->fd, SPI_IOC_MESSAGE (1), &tr); if (ret < 1) { libsoc_spi_debug (__func__, spi, "failed recieving message"); return EXIT_FAILURE; } return EXIT_SUCCESS; } int libsoc_spi_rw (spi * spi, uint8_t * tx, uint8_t * rx, uint32_t len) { libsoc_spi_debug (__func__, spi, "performing duplex rw transfer of %d bytes", len); if (spi == NULL || rx == NULL || tx == NULL) { libsoc_spi_debug (__func__, spi, "spi | rx | tx was NULL"); return EXIT_FAILURE; } if (len <= 0) { libsoc_spi_debug (__func__, spi, "length was less than zero"); return EXIT_FAILURE; } int ret; struct spi_ioc_transfer tr = { .rx_buf = (unsigned long) rx, .tx_buf = (unsigned long) tx, .len = len, }; ret = ioctl (spi->fd, SPI_IOC_MESSAGE (1), &tr); if (ret < 1) { libsoc_spi_debug (__func__, spi, "failed duplex transfer"); return EXIT_FAILURE; } return EXIT_SUCCESS; } int libsoc_spi_free (spi * spi) { if (spi == NULL) { libsoc_spi_debug (__func__, NULL, "spi was not valid"); return EXIT_FAILURE; } libsoc_spi_debug (__func__, spi, "freeing spi device"); free (spi); return EXIT_SUCCESS; } libsoc-0.8.2/libsoc.pc.in000066400000000000000000000003051273225013600151770ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: soc Description: SoC peripherals library Version: @VERSION@ Libs: -L${libdir} -lsoc Cflags: -I${includedir} libsoc-0.8.2/roadmap/000077500000000000000000000000001273225013600144205ustar00rootroot00000000000000libsoc-0.8.2/roadmap/TODO000066400000000000000000000006631273225013600151150ustar00rootroot00000000000000- Investigate using pthread_barrier_wait with GPIO - Investigate using pread for improved GPIO throughput and polling - ADC Support - See file ADC - UART Support - SPI - Add support for more SPI bus config FLAGS - GPIO - Support for setting multiple GPIO's - I2C - Look at using unsigned long to hold spi rw data - Support single register read write, similar to: - http://bunniestudios.com/blog/images/infocast_i2c.c libsoc-0.8.2/roadmap/adc000066400000000000000000000002161273225013600150710ustar00rootroot00000000000000Ordered Texas Instruments LM19CIZ Temperature Sensor to do ADC testing Unit tests will be reading the adc and displaying temperatures values libsoc-0.8.2/static-docs/000077500000000000000000000000001273225013600152125ustar00rootroot00000000000000libsoc-0.8.2/static-docs/.gitignore000066400000000000000000000000061273225013600171760ustar00rootroot00000000000000site/ libsoc-0.8.2/static-docs/README000066400000000000000000000010541273225013600160720ustar00rootroot00000000000000These files are the static content and configuration for the mkdocs documentation deployment on http://jackmitch.github.io/libsoc. To build the docs yo umust first install the mkdocs python package and mkdocs cinder theme. These can be installed via pip. pip install mkdocs mkdocs-cinder The documentation can be served locally from this directory using the command mkdocs serve To add documentation create a pull request and it will be built and deployed at the next release, or sooner if it is just changes to current API documentation or features. libsoc-0.8.2/static-docs/docs/000077500000000000000000000000001273225013600161425ustar00rootroot00000000000000libsoc-0.8.2/static-docs/docs/.gitignore000066400000000000000000000000061273225013600201260ustar00rootroot00000000000000site/ libsoc-0.8.2/static-docs/docs/c/000077500000000000000000000000001273225013600163645ustar00rootroot00000000000000libsoc-0.8.2/static-docs/docs/c/debug.md000066400000000000000000000000001273225013600177620ustar00rootroot00000000000000libsoc-0.8.2/static-docs/docs/c/gpio.md000066400000000000000000000153541273225013600176540ustar00rootroot00000000000000# GPIO --- ## Data Types --- ### gpio_mode Determines the way in which libsoc handles exporting and unexporting GPIOs in the Linux subsystem. * **LS_SHARED** if the gpio is already exported then it will not unexport the GPIO on free. If it is not exported, then it will unexport on free. * **LS_GREEDY** will succeed if the GPIO is already exported, but will always unexport the GPIO on free. * **LS_WEAK** will fail if GPIO is already exported, will always unexport on free. --- ### gpio_direction Used for setting and reading the direction of the GPIO pin. * **DIRECTION_ERROR** Returned when the GPIO direction could not be read * **INPUT** GPIO input mode, it's input value can be read * **OUTPUT** GPIO output mode, it's output value can be written --- ### gpio_level Used for setting and reading the level of the GPIO pin. * **LEVEL_ERROR** Returned when the GPIO level could not be read * **LOW** GPIO value low, usually logic 0 on the pin, but could be 1 if the gpio is inverted. * **HIGH** GPIO value high, usually logic 1 on the pin, but could be 0 if the gpio is inverted. --- ### gpio_edge Used for setting and reading the edge of the GPIO pin. * **EDGE_ERROR** Returned when the GPIO edge could not be read * **RISING** GPIO interrupt is triggered on a rising edge, e.g. logic level 0 followed by 1 * **FALLING** GPIO interrupt is triggered on a falling edge, e.g. logic level 1 followed by 0 * **NONE** GPIO interrupt edge is not set * **BOTH** GPIO interrupt is triggered on both a falling and rising edge --- ### gpio_int_ret Return type for blocked GPIO interrupts. * **LS_INT_ERROR** Error condition * **LS_INT_TRIGGERED** Interrupt was triggered * **LS_INT_TIMEOUT** GPIO poll timedout ## Functions --- ### libsoc_gpio_request ```C gpio * libsoc_gpio_request(unsigned int gpio_id, gpio_mode mode) ``` - *unsigned int* **gpio_id** the Linux ID number for the GPIO you wish to use - *[gpio_mode](#gpio_mode)* **mode** the mode in which libsoc handles the GPIO file descriptor Request a GPIO by it's Linux ID number and set the [gpio_mode](#gpio_mode) under which libsoc will hold the file descriptor. Returns a malloced gpio struct which will need to be freed by [libsoc_gpio_free](#libsoc_gpio_free) when no longer needed. Returns `NULL` on failure. --- ### libsoc_gpio_free ```c int libsoc_gpio_free(gpio * gpio) ``` - *gpioi\** **gpio** the previously requested gpio that you wish to release Free the memory associated with a previously requested GPIO and close the file descriptors. Returns `EXIT_SUCCESS`/`EXIT_FAILURE` --- ### libsoc_gpio_set_direction ```c int libsoc_gpio_set_direction(gpio * current_gpio, gpio_direction direction) ``` - *gpio\** **current_gpio** requested gpio that you wish to set the direction of - *[gpio_direction](#gpio_direction)* **direction** direction you wish to set the gpio to Set the direction of a GPIO, `INPUT` for reading a GPIO, `OUTPUT` for setting a GPIO. Returns `EXIT_SUCCESS`/`EXIT_FAILURE` --- ### libsoc_gpio_get_direction ```c gpio_direction libsoc_gpio_get_direction(gpio * current_gpio) ``` - *gpio\** **current_gpio** requested gpio that you wish to get the direction of Get the current [gpio_direction](#gpio_direction) of a requested GPIO. Returns [gpio_direction](#gpio_direction), `DIRECTION_ERROR` on failure, `INPUT`/`OUTPUT` on success. --- ### libsoc_gpio_set_level ```c int libsoc_gpio_set_level(gpio * current_gpio, gpio_level level) ``` - *gpio \** **current_gpio** requested gpio you wish to set the level of - *[gpio_level](#gpio_level)* **level** level you wish to set the gpio to Set the output level of a requested GPIO to `HIGH` or `LOW`. Returns `EXIT_SUCCESS`/`EXIT_FAILURE` --- ### libsoc_gpio_get_level ```c gpio_level libsoc_gpio_get_level(gpio * current_gpio) ``` - *gpio \** **current_gpio** requested gpio you wish to get the level of Get the current [gpio_level](#gpio_level) of a requested GPIO. Returns [gpio_level](#gpio_level), `LEVEL_ERROR` on failure, `LOW`/`HIGH` on success. --- ### libsoc_gpio_set_edge ```c int libsoc_gpio_set_edge(gpio * current_gpio, gpio_edge edge) ``` - *gpio \** **current_gpio** requested gpio you wish to set the edge of - *[gpio_edge](#gpio_edge)* **edge** edge you wish to set the gpio to Set the edge type of a requested GPIO. The edge is the type of signal change that will trigger interrupt detection. See [gpio_edge](#gpio_edge) for explanations of the different types of edges and how they work. Returns `EXIT_SUCCESS`/`EXIT_FAILURE` --- ### libsoc_gpio_get_edge ```c gpio_edge libsoc_gpio_get_edge(gpio * current_gpio) ``` - *gpio \** **current_gpio** requested gpio you wish to get the edge of Get the current [gpio_edge](#gpio_edge) of a requested GPIO. Returns [gpio_edge](#gpio_edge), `EDGE_ERROR` on failure, `RISING`/`FALLING`/`BOTH`/`NONE` on success. --- ### libsoc_gpio_wait_interrupt ```c int libsoc_gpio_wait_interrupt(gpio * gpio, int timeout) ``` - *gpio \** **gpio** requested gpio you wish to wait for an interrupt on - *int* **timeout** the number of seconds to wait for the interrupt, -1 for block indefinitly Block for a set amount of seconds (or indefinitly) waiting for an interrupt on a GPIO to occur. If you wish to use a non-blocking interrupt mechanism see [libsoc_gpio_callback_interrupt](#libsoc_gpio_callback_interrupt). Returns `LS_INT_ERROR` on failure, `LS_INT_TRIGGERED` on captured interrupt, `LS_INT_TIMEOUT` if no interrupt was captured in the specified time. --- ### libsoc_gpio_callback_interrupt ```c int libsoc_gpio_callback_interrupt(gpio * gpio, int (*callback_fn) (void *), void *arg) ``` - *gpio \** **gpio** requested gpio you wish to set an interrupt handler for - *int (\*callback_fn) (void \*)* **function** name of the function to use as the interrupt handler. Must match the prototype `int* function(void* ptr)` - *void \** **arg** void casted pointer you wish to be passed to your interrupt handler Setup an interrupt handler on a GPIO. This will start a new pthread with an infinite poll on the GPIO waiting for the interrupt. When an interrupt is detected the supplied function will run in the thread, and then return to waiting for an interrupt. Only one interrupt will be queued if it arrives while your supplied function is being run, so it is possible to miss interrupts if they happen too fast. Returns `EXIT_SUCCESS`/`EXIT_FAILURE` --- ### libsoc_gpio_callback_interrupt_cancel ```c int libsoc_gpio_callback_interrupt_cancel(gpio * gpio) ``` - *gpio \** **gpio** the gpio on which to cancel a waiting interrupt handler Cancel a previously set interrupt handler on a GPIO. This uses the pthread_cancel function, so it may cancel mid way through your interrupt handler function. Returns `EXIT_SUCCESS`/`EXIT_FAILURE` libsoc-0.8.2/static-docs/docs/c/i2c.md000066400000000000000000000036471273225013600173750ustar00rootroot00000000000000# I2C --- ## Functions --- ### libsoc_i2c_init ```c i2c* libsoc_i2c_init (uint8_t i2c_bus, uint8_t i2c_address) ``` - *uint8_t* **i2c_bus** the linux enumerated bus number - *uint8_t* **i2c_address** the peripherals address on the i2c bus Initialises a new i2c instance at the specificed address. Returns a malloced i2c struct which must be freed with [libsoc_i2c_free](#libsoc_i2c_free) when no longer needed. Returns `NULL` on failure. --- ### libsoc_i2c_free ```c int libsoc_i2c_free (i2c * i2c) ``` - *i2c\** **i2c** previously initialised i2c struct Free the memory associated with a previously initialised i2c struct and release the hold on the i2c address. Returns `EXIT_SUCCESS` or `EXIT_FAILURE` --- ### libsoc_i2c_write ```c int libsoc_i2c_write (i2c * i2c, uint8_t * buffer, uint16_t len) ``` - *i2c\** **i2c** previously initialised i2c struct - *uint8_t\** **buffer** pointer to output data buffer - *uint16_t* **len** length of data to write in bytes Write `len` bytes starting from the `buffer` data pointer to the specified i2c device. Returns `EXIT_SUCCESS` or `EXIT_FAILURE` --- ### libsoc_i2c_read ```c int libsoc_i2c_read (i2c * i2c, uint8_t * buffer, uint16_t len) ``` - *i2c\** **i2c** previously initialised i2c struct - *uint8_t\** **buffer** pointer to input data buffer - *uint16_t* **len** length of data to read in bytes Read `len` bytes into the `buffer` data pointer from the specified i2c device. Returns `EXIT_SUCCESS` or `EXIT_FAILURE` --- ### libsoc_i2c_set_timeout ```c int libsoc_i2c_set_timeout(i2c * i2c, int timeout) ``` - *i2c\** **i2c** previously initialised i2c struct - *int* **timeout** i2c timeout in milliseconds/10 Set the timeout of a i2c device in milliseconds/10. For example if a timeout of 20ms is requred, `timeout` would be set to 2. ```c // 20ms timeout, 2*10ms libsoc_i2c_set_timeout(device, 2); ``` Returns `EXIT_SUCCESS` or `EXIT_FAILURE` libsoc-0.8.2/static-docs/docs/c/pwm.md000066400000000000000000000107251273225013600175160ustar00rootroot00000000000000# PWM --- ## Data Types --- ### shared_mode Determines the way in which libsoc handles exporting and unexporting PWMs in the Linux subsystem. * **LS_SHARED** if the pwm is already exported then it will not unexport the pwm on free. If it is not exported, then it will unexport on free. * **LS_GREEDY** will succeed if the pwm is already exported, but will always unexport the pwm on free. * **LS_WEAK** will fail if pwm is already exported, will always unexport on free. ### pwm_enabled Used for setting and reading the enabled state of the PWM device * **ENABLED_ERROR** Returned when the enabled state could not be read * **DISABLED** PWM disabled mode, the pwm is not currently running * **ENABLED** PWM enabled mode, the pwm is currently running --- ### pwm_polarity Used for setting and reading the polarity of the PWM device * **POLARITY_ERROR** Returned when the polarity could not be read * **NORMAL** Polarity mode is normal * **INVERSED** Polarity mode is inversed ## Functions --- ### libsoc_pwm_request ```c pwm* libsoc_pwm_request(unsigned int pwm_chip, unsigned int pwm_num, enum shared_mode mode) ``` - *unsigned int* **pwm_chip** the pwm chip number which controls the pwm you wish to use - *unsigned int* **pwm_num** the pwm number within your specified pwm chip - *shared_mode* **mode** the mode in which libsoc handles the PWM file descriptor Request a pwm by specifying its pwm chip number and the pwm number it is on that chip. Set [shared_mode](#shared_mode) to handle how libsoc manages the file descriptor. Returns a malloced pwm struct which will need to be freed by [libsoc_pwm_free](#libsoc_pwm_free) when no longer needed. --- ### libsoc_pwm_free ```c int libsoc_pwm_free(pwm *pwm) ``` - *pwm\** **pwm** the previously requested pwm that you wish to release Free the memory associated with a previously requested PWM device and close the file descriptors. --- ### libsoc_pwm_set_enabled ```c int libsoc_pwm_set_enabled(pwm *pwm, pwm_enabled enabled) ``` - *pwm\** **pwm** requested pwm that you wish to set enabled/disabled - *[pwm_enabled](#pwm_enabled)* **enabled** state you wish to set the pwm device to Set the state of a PWM device, `ENABLED` to enable to the device, `DISABLED` to disable the device. --- ### libsoc_pwm_get_enabled ```c pwm_enabled libsoc_pwm_get_enabled(pwm *pwm) ``` - *pwm\** **pwm** requested pwm that you wish to get the state of Get the current [pwm_enabled](#pwm_enabled) state of a requested PWM device. --- ### libsoc_pwm_set_period ```c int libsoc_pwm_set_period(pwm *pwm, unsigned int period) ``` - *pwm\** **pwm** requested pwm that you wish to set the period of - *unsigned int* **period** the total period of the pwm signal in nanoseconds Set the period of a PWM device, the value is specified in nanoseconds and is the sum of the active and inactive time of the signal. --- ### libsoc_pwm_get_period ```c int libsoc_pwm_get_period(pwm *pwm) ``` - *pwm\** **pwm** requested pwm that you wish to get the period of Get the currently set perioid of the PWM device in nanoseconds. --- ### libsoc_pwm_set_duty_cycle ```c int libsoc_pwm_set_duty_cycle(pwm *pwm, unsigned int duty) ``` - *pwm\** **pwm** requested pwm that you wish to set the duty cycle of - *unsigned int* **duty** the duty cycle in nanoseconds Set the duty cycle of the specified PWM device in nanoseconds. The duty cycle is the active time of the PWM signal and must be less than the period. --- ### libsoc_pwm_get_duty_cycle ```c int libsoc_pwm_get_duty_cycle(pwm *pwm) ``` - *pwm\** **pwm** requested pwm that you wish to get the duty cycle of Get the currently set duty cycle of a requested PWM device in nanoseconds. --- ### libsoc_pwm_set_polarity ```c int libsoc_pwm_set_polarity(pwm *pwm, pwm_polarity polarity) ``` - *pwm\** **pwm** requested pwm that you wish to set the polarity of - *pwm_polarity* **polarity** polarity you wish to set the pwm device to Set the polarity of a PWM device, `NORMAL` will give you the default polarity, `INVERSED` will give you the inverse polarity of normal. Polarity support is optional, ensure your PWM devices kernel driver is capable before relying on this support. The value -1 will be returned on failure to set the polarity. --- ### libsoc_pwm_get_polarity ```c pwm_polarity libsoc_pwm_get_polarity(pwm *pwm) ``` - *pwm\** **pwm** requested pwm that you wish to get the polarity of Get the current [pwm_polarity](#pwm_polarity) of a requested PWM device. --- libsoc-0.8.2/static-docs/docs/c/spi.md000066400000000000000000000000001273225013600174670ustar00rootroot00000000000000libsoc-0.8.2/static-docs/docs/index.md000066400000000000000000000111361273225013600175750ustar00rootroot00000000000000## Introduction --- ### What is libsoc libsoc is a C library to interface with common peripherals found in System on Chips (SoC) through generic Linux Kernel interfaces. It is aimed at new Linux users, and intends to be a stepping stone to enable a user to get started quickly. It is optimised for reliability rather than speed. While the library should be fast, no guarantees are made on it's determinism and it should not be used in time critical routines. ### Why libsoc libsoc was born due to the influx of new embedded Linux boards becoming available cheap, and to hobbyists. There are currently numerous libraries that do interfacing with common SoC peripherals, but they all tend to be centred around a particular board or SoC. This leads to board specific hacks and in some cases direct bypassing of the Linux Kernel. libsoc aims to be generic and compatible with any SoC that has drivers exposing the correct interfaces for the defined peripheral. ## Support --- ### SoC Support If your SoC exposes it's I/O subsystems using the generic Linux kernel interfaces then yes, libsoc supports your SoC! ### Language Support The library is written in C and has a native C API. A subset of the API is also supported with Python bindings. #### [C API](http://jackmitch.github.io/libsoc/c/gpio) - Manual GPIO Manipulation through sysfs (Value, Edge, Direction, Exporting) - Blocking GPIO Interrupts with timeout - Non-blocking GPIO Interrupts with callback mechanism (pthread based) - SPI transfers using spidev - I2C transfers using ioctls - PWM support through sysfs (Linux 3.12+) - Automatic board probing via installed config files #### [Python Bindings](http://jackmitch.github.io/libsoc/python) - Manual GPIO Manipulation through sysfs (Value, Edge, Direction, Exporting) - Blocking GPIO Interrupts with timeout - Non-blocking GPIO Interrupts with callback mechanism - I2C transfers ## Building --- libsoc is built and installed using the autotools build system. This means it follows the traditional linux methodology of autoreconf, configure, make. First, check if your distro packages libsoc. If it does it is easiest to install your distros version of libsoc through it's provided package manager. Depending on your distro this may be `apt-get`, `yum`, `pacman`, etc. Consult your distro documentation for more info. ### Manually Building First clone libsoc from its git repository. git clone https://github.com/jackmitch/libsoc.git libsoc.git Enter the libsoc.git directory cd libsoc.git Run `autoreconf` to generate the libsoc configure scripts autoreconf -i Configure the libsoc library with the required features ```text ./configure [--disable-debug] [--enable-python=] [--enable-board=] [--with-board-configs] ``` ```text --disable-debug disables the debug code, turn off the debug to get the fastest operation but at the cost of any debug print outs. Omitting this flag will leave debug enabled. ``` ```text --enable-python= enable Python language bindings to libsoc API. Value can be empty for autodetect, the value 2 or 3 to search the PATH environment variable for python2 or python3, or an absolute path to a python binary. ``` ```text --enable-board= install a specific board config file to $(sysdir)/libsoc.conf. This enables the use of the board pin name lookup functions and automatic board config probing. Supported boards can be found under ./contrib/board_files. If --with-board-configs is also used, a symlink will be created instead of copying a single file. ``` ```text --with-board-configs install all the contributed board configuration files to $PREFIX/share/libsoc. ``` Compile the code using make ```text make ``` Install the library using make ```text make install ``` ## Documentation Written documentation can be found at [http://jackmitch.github.io/libsoc](http://jackmitch.github.io/libsoc). Test cases can be found in the [test/](https://github.com/jackmitch/libsoc/tree/master/test) directory from the root of the project. All functions and types are also documented directly in the code in the application header files under [lib/include](https://github.com/jackmitch/libsoc/tree/master/lib/include). ## Licencing libsoc is licenced under the LGPLv2.1, please see the COPYING file for further details. ## Contributing libsoc is open-source software and as such you are welcome to browse the code and either add features, or fix bugs. Please submit pull requests, and bugs to [libsoc@github](http://www.github.com/jackmitch/libsoc). If you have any comments or questions, I can be contacted by email at the address [jack@embed.me.uk](mailto:jack@embed.me.uk). libsoc-0.8.2/static-docs/docs/python.md000066400000000000000000000000001273225013600177730ustar00rootroot00000000000000libsoc-0.8.2/static-docs/mkdocs.yml000066400000000000000000000004661273225013600172230ustar00rootroot00000000000000site_name: libsoc repo_url: http://github.com/jackmitch/libsoc site_description: libsoc library documentation theme: cinder pages: - Introduction: index.md - C API: - GPIO: c/gpio.md - SPI (WIP): c/spi.md - I2C: c/i2c.md - PWM: c/pwm.md - DEBUG (WIP): c/debug.md - Python Bindings (WIP): python.md libsoc-0.8.2/test/000077500000000000000000000000001273225013600137545ustar00rootroot00000000000000libsoc-0.8.2/test/board_test.c000066400000000000000000000023271273225013600162520ustar00rootroot00000000000000#include #include #include #include "libsoc_board.h" #define _write(fd, buf) write(fd, buf, sizeof(buf)-1) int main(void) { int fails = 0; char template[] = "/tmp/fileXXXXXX"; int fd = mkstemp(template); board_config *config; unsigned int id; _write(fd, "[GPIO]\n"); _write(fd, "GPIO_FOO= 123\n"); _write(fd, "\n"); _write(fd, "GPIO_BAR =42 \n"); _write(fd, "GPIO_B = 421 \n"); _write(fd, "GPIO_C =21 \n"); close(fd); setenv("LIBSOC_GPIO_CONF", template, 1); config = libsoc_board_init(); id = libsoc_board_gpio_id(config, "GPIO_BAR"); if (id != 42) { printf("ERROR: GPIO_BAR %d != 42\n", id); fails++; } id = libsoc_board_gpio_id(config, "GPIO_FOO"); if (id != 123) { printf("ERROR: GPIO_FOO %d != 123\n", id); fails++; } id = libsoc_board_gpio_id(config, "GPIO_B"); if (id != 421) { printf("ERROR: GPIO_B %d != 421\n", id); fails++; } id = libsoc_board_gpio_id(config, "GPIO_C"); if (id != 21) { printf("ERROR: GPIO_C %d != 21\n", id); fails++; } printf("Tests completed with %d failure(s).\n", fails); libsoc_board_free(config); unlink(template); return fails; } libsoc-0.8.2/test/gpio_test.c000066400000000000000000000123711273225013600161210ustar00rootroot00000000000000#include #include #include #include #include "libsoc_gpio.h" #include "libsoc_debug.h" /** * * This gpio_test is intended to be run on beaglebone white hardware * and uses pins P9_42(gpio7) and P9_27 (gpio115) connected together. * * The GPIO_OUTPUT and INPUT defines can be changed to support any board * all you need to do is ensure that the two pins are connected together * */ #define GPIO_OUTPUT 115 #define GPIO_INPUT 7 static int interrupt_count = 0; int callback_test(void* arg) { int* tmp_count = (int*) arg; *tmp_count = *tmp_count + 1; return EXIT_SUCCESS; } int main(void) { // Create both gpio pointers gpio *gpio_output, *gpio_input; // Enable debug output libsoc_set_debug(1); // Request gpios gpio_output = libsoc_gpio_request(GPIO_OUTPUT, LS_SHARED); gpio_input = libsoc_gpio_request(GPIO_INPUT, LS_SHARED); // Ensure both gpio were successfully requested if (gpio_output == NULL || gpio_input == NULL) { goto fail; } // Set direction to OUTPUT libsoc_gpio_set_direction(gpio_output, OUTPUT); // Check the direction if (libsoc_gpio_get_direction(gpio_output) != OUTPUT) { printf("Failed to set direction to OUTPUT\n"); goto fail; } // Set direction to INPUT libsoc_gpio_set_direction(gpio_input, INPUT); // Check the direction if (libsoc_gpio_get_direction(gpio_input) != INPUT) { printf("Failed to set direction to INPUT\n"); goto fail; } // Set level HIGH and check level in software and hardware libsoc_gpio_set_level(gpio_output, HIGH); if (libsoc_gpio_get_level(gpio_output) != HIGH) { printf("Failed setting gpio level HIGH\n"); goto fail; } if (libsoc_gpio_get_level(gpio_input) != HIGH) { printf("GPIO hardware read was not HIGH\n"); goto fail; } // Set level LOW and check level in software and hardware libsoc_gpio_set_level(gpio_output, LOW); if (libsoc_gpio_get_level(gpio_output) != LOW) { printf("Failed setting gpio level LOW\n"); goto fail; } if (libsoc_gpio_get_level(gpio_input) != LOW) { printf("GPIO hardware read was not LOW\n"); goto fail; } // Turn off debug printing for fast toggle libsoc_set_debug(0); int i; // Toggle the GPIO 1000 times as fast as it can go for (i=0; i<1000; i++) { libsoc_gpio_set_level(gpio_output, HIGH); libsoc_gpio_set_level(gpio_output, LOW); } // Turn debug back on libsoc_set_debug(1); // Set edge to RISING libsoc_gpio_set_edge(gpio_input, RISING); // Check Edge if (libsoc_gpio_get_edge(gpio_input) != RISING) { printf("Failed to set edge to RISING\n"); goto fail; } // Set edge to FALLING libsoc_gpio_set_edge(gpio_input, FALLING); // Check Edge if (libsoc_gpio_get_edge(gpio_input) != FALLING) { printf("Failed to set edge to FALLING\n"); goto fail; } // Set edge to BOTH libsoc_gpio_set_edge(gpio_input, BOTH); // Check Edge if (libsoc_gpio_get_edge(gpio_input) != BOTH) { printf("Failed to set edge to BOTH\n"); goto fail; } // Set edge to NONE libsoc_gpio_set_edge(gpio_input, NONE); // Check Edge if (libsoc_gpio_get_edge(gpio_input) != NONE) { printf("Failed to set edge to NONE\n"); goto fail; } pid_t childPID; // Fork the process so the parent process can wait for the interrupt // on GPIO_INPUT and the child process can generate the interrupt from // GPIO_OUTPUT childPID = fork(); if(childPID >= 0) { if (childPID == 0) { // Allow time to setup the interrupt sleep(1); // Create a falling interrupt libsoc_gpio_set_level(gpio_output, HIGH); libsoc_gpio_set_level(gpio_output, LOW); exit(EXIT_SUCCESS); } } else { printf("Fork failed, interrupt won't be triggered\n"); } // Set the edge to falling in order to test interrupts libsoc_gpio_set_edge(gpio_input, FALLING); // Wait 10 seconds for falling interrupt to occur on GPIO_INPUT int ret = libsoc_gpio_wait_interrupt(gpio_input, 10000); if (ret == LS_INT_TRIGGERED) { printf("Interrupt caught!\n"); } else { printf("Interrupt missed!\n"); } int status; wait(&status); // Setup callback libsoc_gpio_callback_interrupt(gpio_input, &callback_test, (void*) &interrupt_count); // Turn off debug libsoc_set_debug(0); printf("Setting off interrupt generation...\n"); // Toggle the GPIO to generate interrupts for (i=0; i<10000; i++) { libsoc_gpio_set_level(gpio_output, HIGH); libsoc_gpio_set_level(gpio_output, LOW); // Let the other thread get a look in otherwise interrupt success is // ~85%, with usleep(1) success is nearly always %100 with no other load. usleep(1); } // Turn debug back on libsoc_set_debug(1); printf("Caught %d of 10000 interrupts\n", interrupt_count); // Cancel the callback on interrupt libsoc_gpio_callback_interrupt_cancel(gpio_input); fail: // If gpio_request was successful if (gpio_input) { // Free gpio request memory libsoc_gpio_free(gpio_input); } if (gpio_output) { // Free gpio request memory libsoc_gpio_free(gpio_output); } return EXIT_SUCCESS; } libsoc-0.8.2/test/gpio_test.py000077500000000000000000000044441273225013600163340ustar00rootroot00000000000000#!/usr/bin/python import threading import time from libsoc import gpio def test_wait_for_interrupt(gpio_in, gpio_out): def signaller(gpio_out, event): event.wait() # wait 1/100th of a second and create a falling interrupt time.sleep(0.01) gpio_out.set_high() gpio_out.set_low() gpio_out.set_low() event = threading.Event() t = threading.Thread(target=signaller, args=(gpio_out, event)) t.start() gpio_in.set_edge(gpio.EDGE_FALLING) event.set() # wait up to one second for the interrupt gpio_in.wait_for_interrupt(1000) def test_interrupt_handler(gpio_in, gpio_out): class int_handler(object): hits = 0 def cb(self): self.hits += 1 gpio_out.set_low() gpio_in.set_direction(gpio.DIRECTION_INPUT, gpio.EDGE_FALLING) cb = int_handler() h = gpio_in.start_interrupt_handler(cb.cb) for x in range(100): time.sleep(0.01) gpio_out.set_high() gpio_out.set_low() time.sleep(0.1) h.stop() h.join() print('Sent 100 interrupts, received: %d' % cb.hits) def main(gpio_input_id, gpio_output_id): gpio_in = gpio.GPIO(gpio_input_id, gpio.DIRECTION_INPUT) gpio_out = gpio.GPIO(gpio_output_id, gpio.DIRECTION_OUTPUT) with gpio.request_gpios((gpio_in, gpio_out)): assert gpio.DIRECTION_INPUT == gpio_in.get_direction() assert gpio.DIRECTION_OUTPUT == gpio_out.get_direction() gpio_out.set_high() assert gpio_out.is_high() assert gpio_in.is_high() gpio_out.set_low() assert not gpio_out.is_high() assert not gpio_in.is_high() gpio.GPIO.set_debug(False) for i in range(1000): gpio_out.set_high() gpio_out.set_low() gpio.GPIO.set_debug(True) edges = (gpio.EDGE_RISING, gpio.EDGE_FALLING, gpio.EDGE_BOTH, gpio.EDGE_NONE) for edge in edges: gpio_in.set_edge(edge) assert edge == gpio_in.get_edge() test_wait_for_interrupt(gpio_in, gpio_out) test_interrupt_handler(gpio_in, gpio_out) if __name__ == '__main__': import os gpio_input_id = int(os.environ.get('GPIO_IN', '7')) gpio_output_id = int(os.environ.get('GPIO_OUT', '115')) main(gpio_input_id, gpio_output_id) libsoc-0.8.2/test/i2c_test.c000066400000000000000000000057621273225013600156460ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "libsoc_i2c.h" #include "libsoc_debug.h" /** * * This i2c_test is intended to be run on beaglebone white hardware * and uses the I2C2 which is device id 1 by default, as not all 3 I2C * busses are actiavted, and i2c devices are enumerated by amount. * * The i2c bus is on pins P9_19 as SCL, P9_20 as SDA * * The BeagleBone is connected to a ST MicroElectronics M24C01-WBN6P 1K * EEPROM * * The test covers writing 32 bytes of random data, to a random page * on the EEPROM. It then reads the page back, and compares the data * read against the data sent, the test passes if all data matches. * */ #define I2C_BUS 1 #define ADDRESS 0b1010000 #define EEPROM_SIZE 128*8 #define EEPROM_PAGE_SIZE 16 #define EEPROM_NUM_PAGES EEPROM_SIZE/EEPROM_PAGE_SIZE int main() { // Turn debug on libsoc_set_debug(1); // Initialise i2c struct i2c *eeprom = libsoc_i2c_init(I2C_BUS, ADDRESS); if (eeprom == NULL) { printf("Failed to get I2C device!\n"); return EXIT_FAILURE; } // Set the timeout for the i2c slave libsoc_i2c_set_timeout(eeprom, 1); // Setup the seed for the random number struct timeval t1; gettimeofday(&t1, NULL); srand(t1.tv_usec * t1.tv_sec); // Buffers for reading and writing uint8_t data[EEPROM_PAGE_SIZE+1]; uint8_t data_read[EEPROM_PAGE_SIZE]; // Get a random page number uint8_t page = (rand() % EEPROM_NUM_PAGES) * EEPROM_PAGE_SIZE; int i, ret; // The first byte of the i2c write in the EEPROM protocol is the page data[0] = page; // Fill the rest of the write buffer with random data for (i=1; i<(EEPROM_PAGE_SIZE+1); i++) { data[i] = rand() % 255; } // Write page printf ("Writing to page starting at byte address: %d\n", page); ret = libsoc_i2c_write(eeprom, data, EEPROM_PAGE_SIZE+1); printf("Waiting for data to be written\n"); // Wait for the page to be written (spin on bogus write till we get // an ACK, signalling the EEPROM has written the page) while (libsoc_i2c_write(eeprom, &page, 1) == EXIT_FAILURE) { printf("Waiting...\n"); usleep(1); } printf("Data sucessfully written!\n"); printf("Reading data\n"); // Write page address to read ret = libsoc_i2c_write(eeprom, &page, 1); // Read page ret = libsoc_i2c_read(eeprom, data_read, EEPROM_PAGE_SIZE); if (ret != EXIT_SUCCESS) { printf("Read page failed\n"); } printf ("Reading page starting at byte address: %d\n", page); // Print out read back page contects, while checking validity for (i=0; i #include #include #include #include "libsoc_pwm.h" #include "libsoc_debug.h" /** * * This pwm_test is intended to be run on beaglebone white hardware, * however, it will work on any board with a PWM sysfs implementation. * * The PWM sysfs interface was introduced in linux 3.12, if your kernel * is older than this you will need to update or backport the PWM sysfs * patch. * * PWM sysfs Documentation: https://www.kernel.org/doc/Documentation/pwm.txt * */ #define PWM_OUTPUT_CHIP 0 #define PWM_CHIP_OUTPUT 1 int main(void) { int ret = EXIT_SUCCESS; libsoc_set_debug(1); pwm *pwm = libsoc_pwm_request(PWM_OUTPUT_CHIP, PWM_CHIP_OUTPUT, LS_SHARED); if (!pwm) { printf("Failed to get PWM\n"); goto fail; } libsoc_pwm_set_enabled(pwm, ENABLED); int enabled = libsoc_pwm_get_enabled(pwm); if (!enabled) { printf("Failed enabling test\n"); ret = EXIT_FAILURE; goto fail; } libsoc_pwm_set_enabled(pwm, DISABLED); enabled = libsoc_pwm_get_enabled(pwm); if (enabled) { printf("Failed disabling test\n"); ret = EXIT_FAILURE; goto fail; } libsoc_pwm_set_period(pwm, 10); int current_period = libsoc_pwm_get_period(pwm); if (current_period != 10) { printf("Failed period test\n"); goto fail; } libsoc_pwm_set_duty_cycle(pwm, 5); int current_duty = libsoc_pwm_get_duty_cycle(pwm); if (current_duty != 5) { printf("Failed duty test\n"); goto fail; } // This command should fail as the duty should not // be allowed to be greater than the period libsoc_pwm_set_duty_cycle(pwm, 15); current_duty = libsoc_pwm_get_duty_cycle(pwm); if (current_duty != 5) { printf("Failed duty test, this may be a problem with the kernel driver, continuing...\n"); } else { printf("Driver correctly responded to setting duty higher than period, with error\n"); } libsoc_pwm_set_polarity(pwm, INVERSED); int polarity = libsoc_pwm_get_polarity(pwm); if (polarity != INVERSED) { printf("Failed polarity test, this may be an error, or it might not be supported by your driver\n"); } libsoc_pwm_set_polarity(pwm, NORMAL); polarity = libsoc_pwm_get_polarity(pwm); if (polarity != NORMAL) { printf("Failed polarity test, this may be an error, or it might not be supported by your driver\n"); } fail: libsoc_pwm_free(pwm); return ret; } libsoc-0.8.2/test/spi_test.c000066400000000000000000000073441273225013600157620ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "libsoc_spi.h" #include "libsoc_debug.h" /** * * This spi_test is intended to be run on beaglebone white hardware * and uses the SPIDEV1 device on pins P9_31 as SCLK, P9_29 as SI, * P9_30 as as SO, P9_28 as CS. * * The BeagleBone is connected to a MicroChip 25LC640-I/P 64K EEPROM. * * The test covers writing 32 bytes of random data, to a random page * on the EEPROM. It then reads the page back, and compares the data * read against the data sent, the test passes if all data matches. * */ #define SPI_DEVICE 1 #define CHIP_SELECT 0 #define EEPROM_SIZE 8192*8 #define EEPROM_NUM_PAGES EEPROM_SIZE/32 #define WREN 0x06 #define WRDI 0x04 #define WRITE 0x02 #define READ 0x03 #define RDSR 0x05 static uint8_t tx[35], rx[35]; uint8_t read_status_register(spi* spi_dev) { printf("Reading STATUS register\n"); tx[0] = RDSR; tx[1] = 0; rx[0] = 0; rx[1] = 0; libsoc_spi_rw(spi_dev, tx, rx, 2); printf("STATUS is 0x%02x\n", rx[1]); return rx[1]; } int write_page(spi* spi_dev, uint16_t page_address, uint8_t* data, int len) { printf("Writing to page %d\n", page_address); page_address = page_address * 32; tx[0] = WRITE; tx[1] = (page_address >> 8); tx[2] = page_address; if (len > 32) { printf("Page size is 32 bytes\n"); return EXIT_FAILURE; } int i; for (i=0; i> 8); tx[2] = page_address; libsoc_spi_rw(spi_dev, tx, rx, (len+3)); int i; for (i=0; i 0 ]] do key="$1" case $key in --no-python2) python2=0 ;; --no-python3) python3=0 ;; *) echo "unrecognised argument" exit 1 ;; esac shift done cd .. autoreconf -i ./configure ${CONFIGURE_FLAGS} make make clean ./configure ${CONFIGURE_FLAGS} --prefix=$(pwd)/test/tmpinstall make make install find test/ -name *python* | grep -qz . && { echo "python found when not configured"; exit 1; rm -r test/tmpinstall; } rm -r test/tmpinstall make clean ./configure ${CONFIGURE_FLAGS} --enable-python=no --prefix=$(pwd)/test/tmpinstall make make install find test/ -name *python* | grep -qz . && { echo "python found when set to no"; exit 1; rm -r test/tmpinstall; } rm -r test/tmpinstall make clean if ./configure ${CONFIGURE_FLAGS} --enable-python=/usr/bin/python-nope ; then echo "configure succeeded when given bad python path" exit 1 fi if [ $python2 -ne 0 ]; then ./configure ${CONFIGURE_FLAGS} --enable-python --prefix=$(pwd)/test/tmpinstall make make install find test/ -name *python* | grep -qz . || { echo "python auto failed"; exit 1; rm -r test/tmpinstall; } rm -r test/tmpinstall make clean ./configure ${CONFIGURE_FLAGS} --enable-python=2 --prefix=$(pwd)/test/tmpinstall make make install find test/ -name *python2* | grep -qz . || { echo "python2 version build failed"; exit 1; rm -r test/tmpinstall; } rm -r test/tmpinstall make clean ./configure ${CONFIGURE_FLAGS} --enable-python=/usr/bin/python2 --prefix=$(pwd)/test/tmpinstall make make install find test/ -name *python2* | grep -qz . || { echo "python2 full path build failed"; exit 1; rm -r test/tmpinstall; } rm -r test/tmpinstall make clean fi if [ $python3 -ne 0 ]; then ./configure ${CONFIGURE_FLAGS} --enable-python --prefix=$(pwd)/test/tmpinstall make make install find test/ -name *python* | grep -qz . || { echo "python auto build failed"; exit 1; rm -r test/tmpinstall; } rm -r test/tmpinstall make clean ./configure ${CONFIGURE_FLAGS} --enable-python=3 --prefix=$(pwd)/test/tmpinstall make make install find test/ -name *python3* | grep -qz . || { echo "python3 version only build failed"; exit 1; rm -r test/; } rm -r test/tmpinstall make clean ./configure ${CONFIGURE_FLAGS} --enable-python=/usr/bin/python3 --prefix=$(pwd)/test/tmpinstall make make install find test/ -name *python3* | grep -qz . || { echo "python3 full path build failed"; exit 1; rm -r test/; } rm -r test/tmpinstall make clean fi ./configure ${CONFIGURE_FLAGS} --enable-board=beaglebone_black make make clean ./configure ${CONFIGURE_FLAGS} --with-board-configs make make clean ./configure ${CONFIGURE_FLAGS} --disable-debug make make clean echo -e "\n\n\n\n.................. SUCCESS ...................\n\n\n\n"