diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,502 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin 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!
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/hlibBladeRF.cabal b/hlibBladeRF.cabal
new file mode 100644
--- /dev/null
+++ b/hlibBladeRF.cabal
@@ -0,0 +1,77 @@
+-- Initial hlibBladeRF.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                hlibBladeRF
+version:             0.1.0.0
+synopsis:            Haskell binding to libBladeRF SDR library
+description:         IO Monadic binding for libbladeRF software defined radio.
+homepage:            https://victoredwardocallaghan.github.io/hlibBladeRF
+bug-reports:         https://github.com/victoredwardocallaghan/hlibBladeRF/issues
+license:             LGPL-2.1
+license-file:        LICENSE
+author:              Edward O'Callaghan
+maintainer:          eocallaghan@alterapraxis.com
+copyright:           (c) Edward O'Callaghan, 2015
+category:            FFI
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+
+--------------------------------------------
+-- Test suites
+--
+test-suite haddock
+    build-depends:    base, process, regex-compat
+    default-language: Haskell2010
+    hs-source-dirs:   test-suite
+    main-is:          Haddock.hs
+    type:             exitcode-stdio-1.0
+
+test-suite hlint
+    build-depends:    base, hlint
+    default-language: Haskell2010
+    hs-source-dirs:   test-suite
+    main-is:          HLint.hs
+    type:             exitcode-stdio-1.0
+
+--------------------------------------------
+
+library
+  exposed-modules:     Bindings.LibBladeRF
+                       Bindings.LibBladeRF.LibBladeRF
+                       Bindings.LibBladeRF.Utils
+                       Bindings.LibBladeRF.Flash
+                       Bindings.LibBladeRF.Si5338
+                       Bindings.LibBladeRF.Sync
+                       Bindings.LibBladeRF.Lms
+                       Bindings.LibBladeRF.Gain
+                       Bindings.LibBladeRF.Gpio
+                       Bindings.LibBladeRF.Types
+
+                       LibBladeRF
+                       LibBladeRF.LibBladeRF
+                       LibBladeRF.Sampling
+                       LibBladeRF.Sync
+                       LibBladeRF.Gain
+                       LibBladeRF.Gpio
+                       LibBladeRF.Flash
+                       LibBladeRF.Frequency
+                       LibBladeRF.Utils
+                       LibBladeRF.Types
+  -- other-modules:       
+  -- other-extensions:    
+  default-extensions:  ForeignFunctionInterface
+  build-depends:       base >=4 && <4.8,
+                       bindings-DSL >= 1.0.16 && < 1.1,
+                       bytestring
+  pkgconfig-depends:   libbladeRF >= 0.16.2
+  hs-source-dirs:      src
+  c-sources:           src/inlines.c
+  default-language:    Haskell2010
+
+
+source-repository head
+  type:                git
+  location:            git://github.com/victoredwardocallaghan/hlibBladeRF
+  branch:              master
+  subdir:              bindings-hlibbladeRF
diff --git a/src/Bindings/LibBladeRF.hs b/src/Bindings/LibBladeRF.hs
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF.hs
@@ -0,0 +1,25 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module collects together libbladeRF binded FFI
+  C functions into a common namespace.
+-}
+
+{-# OPTIONS_HADDOCK hide, prune #-}
+
+module Bindings.LibBladeRF (module X) where
+
+import Bindings.LibBladeRF.LibBladeRF as X
+import Bindings.LibBladeRF.Utils as X
+import Bindings.LibBladeRF.Flash as X
+import Bindings.LibBladeRF.Si5338 as X
+import Bindings.LibBladeRF.Sync as X
+import Bindings.LibBladeRF.Lms as X
+import Bindings.LibBladeRF.Gpio as X
+import Bindings.LibBladeRF.Gain as X
+import Bindings.LibBladeRF.Types as X
diff --git a/src/Bindings/LibBladeRF/Flash.hsc b/src/Bindings/LibBladeRF/Flash.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/Flash.hsc
@@ -0,0 +1,14 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.Flash where
+
+#strict_import
+import Bindings.LibBladeRF.Types
+
+
+#ccall bladerf_erase_flash , Ptr (<bladerf>) -> Word32 -> Word32 -> IO (CInt)
+#ccall bladerf_read_flash , Ptr (<bladerf>) -> Ptr (Word8) -> Word32 -> Word32 -> IO (CInt)
+#ccall bladerf_write_flash , Ptr (<bladerf>) -> Ptr (Word8) -> Word32 -> Word32 -> IO (CInt)
diff --git a/src/Bindings/LibBladeRF/Gain.hsc b/src/Bindings/LibBladeRF/Gain.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/Gain.hsc
@@ -0,0 +1,30 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.Gain where
+
+#strict_import
+import Bindings.LibBladeRF.Types
+
+
+#ccall bladerf_set_txvga2 , Ptr (<bladerf>) -> CInt -> IO CInt
+#ccall bladerf_get_txvga2 , Ptr (<bladerf>) -> Ptr (CInt) -> IO CInt
+
+#ccall bladerf_set_txvga1 , Ptr (<bladerf>) -> CInt -> IO CInt
+#ccall bladerf_get_txvga1 , Ptr (<bladerf>) -> Ptr (CInt) -> IO CInt
+
+-- symb not found
+-- #ccall bladerf_set_tx_gain , Ptr (<bladerf>) -> CInt -> IO CInt
+
+#ccall bladerf_set_lna_gain , Ptr (<bladerf>) -> <bladerf_lna_gain> -> IO CInt
+#ccall bladerf_get_lna_gain , Ptr (<bladerf>) -> Ptr (<bladerf_lna_gain>) -> IO CInt
+
+#ccall bladerf_set_rxvga1 , Ptr (<bladerf>) -> CInt -> IO CInt
+#ccall bladerf_get_rxvga1 , Ptr (<bladerf>) -> Ptr (CInt) -> IO CInt
+
+#ccall bladerf_set_rxvga2 , Ptr (<bladerf>) -> CInt -> IO CInt
+#ccall bladerf_get_rxvga2 , Ptr (<bladerf>) -> Ptr (CInt) -> IO CInt
+
+#ccall bladerf_set_gain , Ptr (<bladerf>) -> <bladerf_module> -> CInt -> IO CInt
diff --git a/src/Bindings/LibBladeRF/Gpio.hsc b/src/Bindings/LibBladeRF/Gpio.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/Gpio.hsc
@@ -0,0 +1,28 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.Gpio where
+
+#strict_import
+import Bindings.LibBladeRF.Types
+
+
+#ccall bladerf_config_gpio_read , Ptr (<bladerf>) -> Ptr (Word32) -> IO (CInt)
+#ccall bladerf_config_gpio_write , Ptr (<bladerf>) -> Word32 -> IO (CInt)
+
+#ccall bladerf_expansion_gpio_read , Ptr (<bladerf>) -> Ptr (Word32) -> CInt
+#ccall bladerf_expansion_gpio_write , Ptr (<bladerf>) -> Word32 -> CInt
+
+#ccall bladerf_expansion_gpio_dir_read , Ptr (<bladerf>) -> Ptr (Word32) -> CInt
+#ccall bladerf_expansion_gpio_dir_write , Ptr (<bladerf>) -> Word32 -> CInt
+
+
+-- #ccall bladerf_expansion_get_timestamp , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (Word64) -> CInt
+
+-- #ccall bladerf_expansion_dac_write , Ptr (<bladerf>) -> Word16 -> CInt
+
+#ccall bladerf_xb_spi_write , Ptr (<bladerf>) -> Word32 -> CInt
+
+#ccall bladerf_calibrate_dc , Ptr (<bladerf>) -> <bladerf_cal_module> -> CInt
diff --git a/src/Bindings/LibBladeRF/LibBladeRF.hsc b/src/Bindings/LibBladeRF/LibBladeRF.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/LibBladeRF.hsc
@@ -0,0 +1,83 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.LibBladeRF where
+
+#strict_import
+import Bindings.LibBladeRF.Types
+
+
+#ccall bladerf_get_device_list , Ptr (Ptr <bladerf_devinfo>) -> IO (CInt)
+
+#ccall bladerf_free_device_list , Ptr (<bladerf_devinfo>) -> IO ()
+
+
+#ccall bladerf_open_with_devinfo , Ptr (Ptr <bladerf>) -> Ptr (<bladerf_devinfo>) -> IO (CInt)
+
+
+#ccall bladerf_open , Ptr (Ptr <bladerf>) -> Ptr (CChar) -> IO (CInt)
+
+#ccall bladerf_close , Ptr (<bladerf>) -> IO ()
+
+-- #ccall bladerf_set_usb_reset_on_open , CShort -> IO ()
+
+#ccall bladerf_init_devinfo , Ptr (<bladerf_devinfo>) -> IO ()
+
+#ccall bladerf_get_devinfo , Ptr (<bladerf>) -> Ptr (<bladerf_devinfo>) -> IO (CInt)
+
+#ccall bladerf_get_devinfo_from_str , Ptr (CChar) -> Ptr (<bladerf_devinfo>) -> IO (CInt)
+
+#ccall bladerf_devinfo_matches , Ptr (<bladerf_devinfo>) -> Ptr (<bladerf_devinfo>) -> IO (CShort)
+
+#ccall bladerf_devstr_matches , Ptr (CChar) -> Ptr (<bladerf_devinfo>) -> IO (CShort)
+
+#ccall bladerf_backend_str , <bladerf_backend> -> IO (Ptr (CChar))
+
+
+
+#ccall bladerf_enable_module , Ptr (<bladerf>) -> <bladerf_module> -> Bool -> IO CInt
+
+#ccall bladerf_set_loopback , Ptr (<bladerf>) -> <bladerf_loopback> -> CInt
+#ccall bladerf_get_loopback , Ptr (<bladerf>) -> Ptr (<bladerf_loopback>) -> CInt
+
+-- #ccall bladerf_set_sample_rate , Ptr (<bladerf>) -> <bladerf_module> -> CUInt -> Ptr (CUInt) -> CInt
+
+-- #ccall bladerf_set_sample_rate , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (<bladerf_rational_rate>) -> Ptr (<bladerf_rational_rate>) -> CInt
+
+#ccall bladerf_set_sampling , Ptr (<bladerf>) -> <bladerf_sampling> -> CInt
+#ccall bladerf_get_sampling , Ptr (<bladerf>) -> Ptr (<bladerf_sampling>) -> CInt
+
+#ccall bladerf_set_sample_rate , Ptr (<bladerf>) -> <bladerf_module> -> CUInt -> Ptr (CUInt) -> IO (CInt)
+#ccall bladerf_get_sample_rate , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (CUInt) -> CInt
+
+#ccall bladerf_set_rational_sample_rate , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (<bladerf_rational_rate>) -> Ptr (<bladerf_rational_rate>) -> IO (CInt)
+#ccall bladerf_get_rational_sample_rate , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (<bladerf_rational_rate>) -> CInt
+
+#ccall bladerf_set_correction , Ptr (<bladerf>) -><bladerf_module> -> <bladerf_correction> -> Word16 -> IO (CInt)
+#ccall bladerf_get_correction , Ptr (<bladerf>) -><bladerf_module> -> <bladerf_correction> -> Ptr (Word16) -> IO (CInt)
+
+
+#ccall bladerf_set_bandwidth , Ptr (<bladerf>) -> <bladerf_module> -> CUInt -> Ptr (CUInt) -> IO (CInt)
+#ccall bladerf_get_bandwidth , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (CUInt) -> CInt
+
+#ccall bladerf_set_lpf_mode , Ptr (<bladerf>) -> <bladerf_module> -> <bladerf_lpf_mode> -> CInt
+#ccall bladerf_get_lpf_mode , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (<bladerf_lpf_mode>) -> CInt
+
+#ccall bladerf_select_band , Ptr (<bladerf>) -> <bladerf_module> -> CUInt -> CInt
+
+#ccall bladerf_set_frequency , Ptr (<bladerf>) -> <bladerf_module> -> CUInt -> IO (CInt)
+#ccall bladerf_get_frequency , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (CUInt) -> IO (CInt)
+
+#ccall bladerf_dac_write , Ptr (<bladerf>) -> Word16 -> IO (CInt)
+
+#ccall bladerf_expansion_attach , Ptr (<bladerf>) -> <bladerf_xb> -> CInt
+
+#ccall bladerf_expansion_get_attached , Ptr (<bladerf>) -> Ptr (<bladerf_xb>) -> CInt
+
+#ccall bladerf_xb200_set_filterbank , Ptr (<bladerf>) -> <bladerf_module> -> <bladerf_xb200_filter> -> CInt
+#ccall bladerf_xb200_get_filterbank , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (<bladerf_xb200_filter>) -> CInt
+
+#ccall bladerf_xb200_set_path , Ptr (<bladerf>) -> <bladerf_module> -> <bladerf_xb200_path> -> CInt
+#ccall bladerf_xb200_get_path , Ptr (<bladerf>) -> <bladerf_module> -> Ptr (<bladerf_xb200_path>) -> CInt
diff --git a/src/Bindings/LibBladeRF/Lms.hsc b/src/Bindings/LibBladeRF/Lms.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/Lms.hsc
@@ -0,0 +1,16 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.Lms where
+
+#strict_import
+import Bindings.LibBladeRF.Types
+
+
+#ccall bladerf_lms_read , Ptr (<bladerf>) -> Word8 -> Ptr (Word8) -> CInt
+#ccall bladerf_lms_write , Ptr (<bladerf>) -> Word8 -> Word8 -> CInt
+
+#ccall bladerf_lms_set_dc_cals , Ptr (<bladerf>) -> Ptr (<bladerf_lms_dc_cals>) -> CInt
+#ccall bladerf_lms_get_dc_cals , Ptr (<bladerf>) -> Ptr (<bladerf_lms_dc_cals>) -> CInt
diff --git a/src/Bindings/LibBladeRF/Si5338.hsc b/src/Bindings/LibBladeRF/Si5338.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/Si5338.hsc
@@ -0,0 +1,16 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.Si5338 where
+
+#strict_import
+import Bindings.LibBladeRF.Types
+
+
+#ccall bladerf_si5338_read , Ptr (<bladerf>) -> Word8 -> Ptr (Word8) -> CInt
+#ccall bladerf_si5338_write , Ptr (<bladerf>) -> Word8 -> Word8 -> CInt
+
+-- #ccall bladerf_si5338_set_tx_freq , Ptr (<bladerf>) -> CUInt -> CInt
+-- #ccall bladerf_si5338_set_rx_freq , Ptr (<bladerf>) -> CUInt -> CInt
diff --git a/src/Bindings/LibBladeRF/Sync.hsc b/src/Bindings/LibBladeRF/Sync.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/Sync.hsc
@@ -0,0 +1,15 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.Sync where
+
+#strict_import
+import Bindings.LibBladeRF.Types
+
+
+#ccall bladerf_sync_config , Ptr (<bladerf>) -> <bladerf_module> -> <bladerf_format> -> CUInt -> CUInt -> CUInt -> CUInt -> IO (CInt)
+
+#ccall bladerf_sync_tx , Ptr (<bladerf>) -> Ptr a -> CUInt -> Ptr (<bladerf_metadata>) -> CUInt -> IO (CInt)
+#ccall bladerf_sync_rx , Ptr (<bladerf>) -> Ptr a -> CUInt -> Ptr (<bladerf_metadata>) -> CUInt -> IO (CInt)
diff --git a/src/Bindings/LibBladeRF/Types.hsc b/src/Bindings/LibBladeRF/Types.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/Types.hsc
@@ -0,0 +1,312 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.Types where
+
+#strict_import
+import Foreign.Storable
+
+
+#num BLADERF_ERR_UNEXPECTED
+#num BLADERF_ERR_RANGE
+#num BLADERF_ERR_INVAL
+#num BLADERF_ERR_MEM
+#num BLADERF_ERR_IO
+#num BLADERF_ERR_TIMEOUT
+#num BLADERF_ERR_NODEV
+#num BLADERF_ERR_UNSUPPORTED
+#num BLADERF_ERR_MISALIGNED
+#num BLADERF_ERR_CHECKSUM
+#num BLADERF_ERR_NO_FILE
+#num BLADERF_ERR_UPDATE_FPGA
+#num BLADERF_ERR_UPDATE_FW
+#num BLADERF_ERR_TIME_PAST
+
+#opaque_t bladerf
+
+-- #integral_t enum
+#integral_t bladerf_backend
+#num BLADERF_BACKEND_ANY
+#num BLADERF_BACKEND_LINUX
+#num BLADERF_BACKEND_LIBUSB
+#num BLADERF_BACKEND_CYPRESS
+#num BLADERF_BACKEND_DUMMY
+
+-- #integral_t enum
+#integral_t bladerf_dev_speed
+#num BLADERF_DEVICE_SPEED_UNKNOWN
+#num BLADERF_DEVICE_SPEED_HIGH
+#num BLADERF_DEVICE_SPEED_SUPER
+
+
+#num BLADERF_SERIAL_LENGTH
+
+
+#starttype struct bladerf_devinfo
+#field backend , <bladerf_backend>
+#array_field serial , CChar
+#field usb_bus , Word8
+#field usb_addr , Word8
+#field instance , CUInt
+#stoptype
+
+
+#num BLADERF_RXVGA1_GAIN_MIN
+#num BLADERF_RXVGA1_GAIN_MAX
+#num BLADERF_RXVGA2_GAIN_MIN
+#num BLADERF_RXVGA2_GAIN_MAX
+#num BLADERF_TXVGA1_GAIN_MIN
+#num BLADERF_TXVGA1_GAIN_MAX
+#num BLADERF_TXVGA2_GAIN_MIN
+#num BLADERF_TXVGA2_GAIN_MAX
+#num BLADERF_SAMPLERATE_MIN
+#num BLADERF_SAMPLERATE_REC_MAX
+#num BLADERF_BANDWIDTH_MIN
+#num BLADERF_BANDWIDTH_MAX
+#num BLADERF_FREQUENCY_MIN
+#num BLADERF_FREQUENCY_MIN_XB200
+#num BLADERF_FREQUENCY_MAX
+
+
+-- #integral_t enum
+#integral_t bladerf_loopback
+#num BLADERF_LB_FIRMWARE
+#num BLADERF_LB_BB_TXLPF_RXVGA2
+#num BLADERF_LB_BB_TXVGA1_RXVGA2
+#num BLADERF_LB_BB_TXLPF_RXLPF
+#num BLADERF_LB_BB_TXVGA1_RXLPF
+#num BLADERF_LB_RF_LNA1
+#num BLADERF_LB_RF_LNA2
+#num BLADERF_LB_RF_LNA3
+#num BLADERF_LB_NONE
+
+
+#starttype struct bladerf_rational_rate
+#field integer , Word64
+#field num , Word64
+#field den , Word64
+#stoptype
+
+
+-- #integral_t enum
+#integral_t bladerf_sampling
+#num BLADERF_SAMPLING_UNKNOWN
+#num BLADERF_SAMPLING_INTERNAL
+#num BLADERF_SAMPLING_EXTERNAL
+
+
+-- #integral_t enum
+#integral_t bladerf_lna_gain
+#num BLADERF_LNA_GAIN_UNKNOWN
+#num BLADERF_LNA_GAIN_BYPASS
+#num BLADERF_LNA_GAIN_MID
+#num BLADERF_LNA_GAIN_MAX
+
+
+#num BLADERF_LNA_GAIN_MID_DB
+#num BLADERF_LNA_GAIN_MAX_DB
+
+
+-- #integral_t enum
+#integral_t bladerf_lpf_mode
+#num BLADERF_LPF_NORMAL
+#num BLADERF_LPF_BYPASSED
+#num BLADERF_LPF_DISABLED
+
+
+-- #integral_t enum
+#integral_t bladerf_module
+#num BLADERF_MODULE_RX
+#num BLADERF_MODULE_TX
+
+
+-- #integral_t enum
+#integral_t bladerf_xb
+#num BLADERF_XB_NONE
+#num BLADERF_XB_100
+#num BLADERF_XB_200
+
+
+-- #integral_t enum
+#integral_t bladerf_xb200_filter
+#num BLADERF_XB200_50M
+#num BLADERF_XB200_144M
+#num BLADERF_XB200_222M
+#num BLADERF_XB200_CUSTOM
+#num BLADERF_XB200_AUTO_1DB
+#num BLADERF_XB200_AUTO_3DB
+
+
+-- #integral_t enum
+#integral_t bladerf_xb200_path
+#num BLADERF_XB200_BYPASS
+#num BLADERF_XB200_MIX
+
+
+-- #integral_t enum
+#integral_t bladerf_cal_module
+#num BLADERF_DC_CAL_LPF_TUNING
+#num BLADERF_DC_CAL_TX_LPF
+#num BLADERF_DC_CAL_RX_LPF
+#num BLADERF_DC_CAL_RXVGA2
+
+
+-- #integral_t enum
+#integral_t bladerf_correction
+#num BLADERF_CORR_LMS_DCOFF_I
+#num BLADERF_CORR_LMS_DCOFF_Q
+#num BLADERF_CORR_FPGA_PHASE
+#num BLADERF_CORR_FPGA_GAIN
+
+
+-- #integral_t enum
+#integral_t bladerf_format
+#num BLADERF_FORMAT_SC16_Q11
+#num BLADERF_FORMAT_SC16_Q11_META
+
+
+#num BLADERF_META_STATUS_OVERRUN
+
+#num BLADERF_META_STATUS_UNDERRUN
+
+#num BLADERF_META_FLAG_TX_BURST_START
+
+#num BLADERF_META_FLAG_TX_BURST_END
+
+#num BLADERF_META_FLAG_TX_NOW
+
+#num BLADERF_META_FLAG_RX_NOW
+
+
+#starttype struct bladerf_metadata
+#field timestamp , Word64
+#field flags , Word32
+#field status , Word32
+#field actual_count , CInt
+#array_field reserved , Word8
+#stoptype
+
+
+-- #num BLADERF_STREAM_SHUTDOWN (NULL)
+
+-- #num BLADERF_STREAM_NO_DATA  ((void*)(-1))
+
+
+#callback_t bladerf_stream_cb , Ptr() -> Ptr() -> Ptr() -> Ptr() -> CSize -> Ptr() -> IO()
+
+
+#starttype struct bladerf_version
+#field major , Word16
+#field minor , Word16
+#field patch , Word16
+#field describe , CString
+#stoptype
+
+
+-- #integral_t enum
+#integral_t bladerf_fpga_size
+#num BLADERF_FPGA_UNKNOWN
+#num BLADERF_FPGA_40KLE
+#num BLADERF_FPGA_115KLE
+
+
+-- #integral_t enum
+#integral_t bladerf_log_level
+#num BLADERF_LOG_LEVEL_VERBOSE
+#num BLADERF_LOG_LEVEL_DEBUG
+#num BLADERF_LOG_LEVEL_INFO
+#num BLADERF_LOG_LEVEL_WARNING
+#num BLADERF_LOG_LEVEL_ERROR
+#num BLADERF_LOG_LEVEL_CRITICAL
+#num BLADERF_LOG_LEVEL_SILENT
+
+
+-- #integral_t enum
+#integral_t bladerf_image_type
+#num BLADERF_IMAGE_TYPE_INVALID
+#num BLADERF_IMAGE_TYPE_RAW
+#num BLADERF_IMAGE_TYPE_FIRMWARE
+#num BLADERF_IMAGE_TYPE_FPGA_40KLE
+#num BLADERF_IMAGE_TYPE_FPGA_115KLE
+#num BLADERF_IMAGE_TYPE_CALIBRATION
+#num BLADERF_IMAGE_TYPE_RX_DC_CAL
+#num BLADERF_IMAGE_TYPE_TX_DC_CAL
+#num BLADERF_IMAGE_TYPE_RX_IQ_CAL
+#num BLADERF_IMAGE_TYPE_TX_IQ_CAL
+
+
+#num BLADERF_IMAGE_MAGIC_LEN
+
+#num BLADERF_IMAGE_CHECKSUM_LEN
+
+#num BLADERF_IMAGE_RESERVED_LEN
+
+
+#starttype struct bladerf_image
+#array_field magic , CChar
+#array_field checksum , Word8
+#field version , <bladerf_version>
+#field timestamp , Word64
+#array_field serial , CChar
+#array_field reserved , CChar
+#field type , <bladerf_image_type>
+#field address , Word32
+#field length , Word32
+#field data , Ptr (Word8)
+#stoptype
+
+
+#starttype struct bladerf_lms_dc_cals
+#field lpf_tuning , Word16
+#field tx_lpf_i , Word16
+#field tx_lpf_q , Word16
+#field rx_lpf_i , Word16
+#field rx_lpf_q , Word16
+#field dc_ref , Word16
+#field rxvga2a_i , Word16
+#field rxvga2a_q , Word16
+#field rxvga2b_i , Word16
+#field rxvga2b_q , Word16
+#stoptype
+
+
+#num BLADERF_GPIO_LMS_RX_ENABLE
+#num BLADERF_GPIO_LMS_TX_ENABLE
+#num BLADERF_GPIO_TX_LB_ENABLE
+#num BLADERF_GPIO_TX_HB_ENABLE
+#num BLADERF_GPIO_COUNTER_ENABLE
+#num BLADERF_GPIO_RX_LB_ENABLE
+#num BLADERF_GPIO_RX_HB_ENABLE
+#num BLADERF_GPIO_FEATURE_SMALL_DMA_XFER
+#num BLADERF_GPIO_TIMESTAMP
+#num BLADERF_GPIO_TIMESTAMP_DIV2
+
+
+#num BLADERF_FLASH_TOTAL_SIZE
+#num BLADERF_FLASH_PAGE_SIZE
+#num BLADERF_FLASH_EB_SIZE
+#num BLADERF_FLASH_NUM_PAGES
+#num BLADERF_FLASH_NUM_EBS
+-- #num BLADERF_FLASH_TO_PAGES
+-- #num BLADERF_FLASH_TO_EB
+#num BLADERF_FLASH_ADDR_FIRMWARE
+-- #num BLADERF_FLASH_PAGE_FIRMWARE
+-- #num BLADERF_FLASH_EB_FIRMWARE
+#num BLADERF_FLASH_BYTE_LEN_FIRMWARE
+-- #num BLADERF_FLASH_PAGE_LEN_FIRMWARE
+-- #num BLADERF_FLASH_EB_LEN_FIRMWARE
+#num BLADERF_FLASH_ADDR_CAL
+-- #num BLADERF_FLASH_PAGE_CAL
+-- #num BLADERF_FLASH_EB_CAL
+#num BLADERF_FLASH_BYTE_LEN_CAL
+-- #num BLADERF_FLASH_PAGE_LEN_CAL
+#num BLADERF_FLASH_EB_LEN_CAL
+
+
+#num BLADERF_FLASH_ADDR_FPGA
+-- #num BLADERF_FLASH_PAGE_FPGA
+-- #num BLADERF_FLASH_EB_FPGA
+#num BLADERF_FLASH_BYTE_LEN_FPGA
+-- #num BLADERF_FLASH_EB_LEN_FPGA
diff --git a/src/Bindings/LibBladeRF/Utils.hsc b/src/Bindings/LibBladeRF/Utils.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/LibBladeRF/Utils.hsc
@@ -0,0 +1,31 @@
+#include <bindings.dsl.h>
+#include <libbladeRF.h>
+
+{-# OPTIONS_HADDOCK hide #-}
+
+module Bindings.LibBladeRF.Utils where
+
+#strict_import
+import Bindings.LibBladeRF.Types
+
+#ccall bladerf_get_serial , Ptr (<bladerf>) -> CString -> IO (CInt)
+
+#ccall bladerf_get_vctcxo_trim , Ptr (<bladerf>) -> Ptr (Word16) -> CInt
+
+
+#ccall bladerf_get_fpga_size , Ptr (<bladerf>) -> Ptr (<bladerf_fpga_size>) -> IO (CInt)
+#ccall bladerf_is_fpga_configured , Ptr (<bladerf>) -> IO (CInt)
+#ccall bladerf_fpga_version , Ptr (<bladerf>) -> Ptr (<bladerf_version>) -> IO (CInt)
+
+#ccall bladerf_load_fpga , Ptr (<bladerf>) -> CString -> IO (CInt)
+
+
+#ccall bladerf_device_speed , Ptr (<bladerf>) -> IO (<bladerf_dev_speed>)
+
+#ccall bladerf_fw_version , Ptr (<bladerf>) -> Ptr (<bladerf_version>) -> IO (CInt)
+
+-- #ccall bladerf_stderr , CInt -> Ptr (CChar)
+
+#ccall bladerf_version , Ptr (<bladerf_version>) -> IO ()
+
+#ccall bladerf_log_set_verbosity , <bladerf_log_level> -> IO ()
diff --git a/src/LibBladeRF.hs b/src/LibBladeRF.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF.hs
@@ -0,0 +1,25 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module collects together libbladeRF high-level
+  actions and primitives into a common namespace.
+-}
+
+{-# OPTIONS_HADDOCK hide, prune #-}
+
+module LibBladeRF (module X) where
+
+import LibBladeRF.LibBladeRF as X
+import LibBladeRF.Utils as X
+import LibBladeRF.Flash as X
+--import LibBladeRF.Si5338 as X
+import LibBladeRF.Sync as X
+--import LibBladeRF.Lms as X
+import LibBladeRF.Gpio as X
+import LibBladeRF.Gain as X
+import LibBladeRF.Types as X
diff --git a/src/LibBladeRF/Flash.hs b/src/LibBladeRF/Flash.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/Flash.hs
@@ -0,0 +1,57 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module encapsulates flash libbladeRF library functions.
+  WARNING !!! Untested !!!
+-}
+
+module LibBladeRF.Flash ( bladeRFEraseFlash
+                        , bladeRFReadFlash
+--                        , bladeRFWriteFlash
+                        ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+
+import Bindings.LibBladeRF
+import LibBladeRF.LibBladeRF
+
+
+-- | Erase regions of the bladeRF's SPI flash
+--
+-- This function operates in units of 64KiB erase blocks
+bladeRFEraseFlash :: DeviceHandle  -- ^ Device handle
+                  -> Word32        -- ^ Erase block to start erasing at
+                  -> Word32        -- ^ Number of blocks to erase.
+                  -> IO CInt
+bladeRFEraseFlash dev b c = c'bladerf_erase_flash (unDeviceHandle dev) b c
+
+-- | Read data from the bladeRF's SPI flash
+--
+-- This function operates in units of 256-byte pages.
+bladeRFReadFlash :: DeviceHandle -- ^ Device handle
+                 -> Word32       -- ^ Page to begin reading from
+                 -> Word32       -- ^ Number of pages to read
+                 -> IO (CInt, Word8)
+bladeRFReadFlash dev p c = do
+  bptr <- malloc :: IO (Ptr Word8)
+  ret <- c'bladerf_read_flash (unDeviceHandle dev) bptr p c
+  buffer <- peek bptr
+  free bptr
+  return (ret, buffer)
+
+-- | Write data from the bladeRF's SPI flash
+-- FIXME - how to pass in a buffer of data???
+--bladeRFWriteFlash :: DeviceHandle -> Word32 -> Word32 -> IO (CInt, Word8)
+--bladeRFWriteFlash dev p c = do
+--  bptr <- malloc :: IO (Ptr Word8)
+--  ret <- c'bladerf_write_flash (unDeviceHandle dev) bptr p c
+--  buffer <- peek bptr
+--  free bptr
+--  return (ret, buffer)
diff --git a/src/LibBladeRF/Frequency.hs b/src/LibBladeRF/Frequency.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/Frequency.hs
@@ -0,0 +1,76 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module encapsulates frequency adjustments libbladeRF library functions.
+-}
+
+module LibBladeRF.Frequency ( bladeRFDACWrite
+                            , bladeRFGetFrequency
+                            , bladeRFSetFrequency
+                            , bladeRFGetCorrection
+                            , bladeRFSetCorrection
+                            ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+
+import Bindings.LibBladeRF
+import LibBladeRF.LibBladeRF
+import LibBladeRF.Types
+
+
+-- | Write value to VCTCXO DAC
+bladeRFDACWrite :: DeviceHandle -- ^ Device handle
+                -> Word16       -- ^ Data to write to DAC register
+                -> IO ()
+bladeRFDACWrite dev v = do
+  c'bladerf_dac_write (unDeviceHandle dev) v
+  return () -- ignores ret
+
+-- | Get module's current frequency in Hz
+bladeRFGetFrequency :: DeviceHandle  -- ^ Device handle
+                    -> BladeRFModule -- ^ Module to configure
+                    -> IO Int        -- ^ Returned frequency
+bladeRFGetFrequency dev m = do
+  pf <- malloc :: IO (Ptr CUInt)
+  c'bladerf_get_frequency (unDeviceHandle dev) ((fromIntegral . fromEnum) m) pf
+  f <- peek pf
+  free pf
+  return $ fromIntegral f
+
+-- | Set module's frequency in Hz.
+bladeRFSetFrequency :: DeviceHandle  -- ^ Device handle
+                    -> BladeRFModule -- ^ Module to configure
+                    -> Int           -- ^ Desired frequency
+                    -> IO ()
+bladeRFSetFrequency dev m f = do
+  c'bladerf_set_frequency (unDeviceHandle dev) ((fromIntegral . fromEnum) m) (fromIntegral f)
+  return () -- ignores ret
+
+-- | Obtain the current value of the specified configuration parameter
+bladeRFGetCorrection :: DeviceHandle       -- ^ Device handle
+                     -> BladeRFModule      -- ^ Module to retrieve correction information from
+                     -> BladeRFCorrection  -- ^ Correction type
+                     -> IO Word16          -- ^ Current value
+bladeRFGetCorrection dev m c = do
+  pc <- malloc :: IO (Ptr Word16)
+  c'bladerf_get_correction (unDeviceHandle dev) ((fromIntegral . fromEnum) m) ((fromIntegral . fromEnum) c) pc
+  c <- peek pc
+  free pc
+  return c
+
+-- | Set the value of the specified configuration parameter
+bladeRFSetCorrection :: DeviceHandle      -- ^ Device handle
+                     -> BladeRFModule     -- ^ Module to apply correction to
+                     -> BladeRFCorrection -- ^ Correction type
+                     -> Word16            -- ^ Value to apply
+                     -> IO ()
+bladeRFSetCorrection dev m c v = do
+  c'bladerf_set_correction (unDeviceHandle dev) ((fromIntegral . fromEnum) m) ((fromIntegral . fromEnum) c) v
+  return () -- ignores ret
diff --git a/src/LibBladeRF/Gain.hs b/src/LibBladeRF/Gain.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/Gain.hs
@@ -0,0 +1,152 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module deals with Gain control
+-}
+
+module LibBladeRF.Gain ( -- * set,get TxVGA2
+                         bladeRFSetTXVGA2
+                       , bladeRFGetTXVGA2
+                       -- * set,get TxVGA1
+                       , bladeRFSetTXVGA1
+                       , bladeRFGetTXVGA1
+                       -- * set,get RxVGA2
+                       , bladeRFSetRXVGA2
+                       , bladeRFGetRXVGA2
+                       -- * set,get RxVGA1
+                       , bladeRFSetRXVGA1
+                       , bladeRFGetRXVGA1
+                       -- * set,gain LNA Gain
+                       , bladeRFSetLNAGain
+                       , bladeRFGetLNAGain
+                       -- * Optimal gain control
+-- XXX symb not found!!!
+--                       , bladeRFSetTXGain
+                       , bladeRFSetGain
+                       ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+
+import Bindings.LibBladeRF
+import LibBladeRF.LibBladeRF
+import LibBladeRF.Types
+
+
+-- | Set the PA gain in dB
+bladeRFSetTXVGA2 :: DeviceHandle -- ^ Device handle
+                 -> Int          -- ^ Desired gain
+                 -> IO ()
+bladeRFSetTXVGA2 dev g = do
+  c'bladerf_set_txvga2 (unDeviceHandle dev) (fromIntegral g)
+  return () -- ignores ret
+
+-- | Get the PA gain in dB
+bladeRFGetTXVGA2 :: DeviceHandle -- ^ Device handle
+                 -> IO Int       -- ^ Returned gain
+bladeRFGetTXVGA2 dev = do
+  p <- malloc :: IO (Ptr CInt)
+  c'bladerf_get_txvga2 (unDeviceHandle dev) p
+  g <-  peek p
+  free p
+  return $ fromIntegral g
+
+-- | Set the post-LPF gain in dB
+bladeRFSetTXVGA1 :: DeviceHandle         -- ^ Device handle
+                 -> BladeRFVGAGainBounds -- ^ Desired gain
+                 -> IO ()
+bladeRFSetTXVGA1 dev g = do
+  c'bladerf_set_txvga1 (unDeviceHandle dev) ((fromIntegral . fromEnum) g)
+  return () -- ignores ret
+
+-- | Get the post-LPF gain in dB
+bladeRFGetTXVGA1 :: DeviceHandle -- ^ Device handle
+                 -> IO Int       -- ^ Returned gain
+bladeRFGetTXVGA1 dev = do
+  p <- malloc :: IO (Ptr CInt)
+  c'bladerf_get_txvga1 (unDeviceHandle dev) p
+  g <-  peek p
+  free p
+  return $ fromIntegral g
+
+-- | Set the post-LPF VGA gain
+bladeRFSetRXVGA2 :: DeviceHandle         -- ^ Device handle
+                 -> BladeRFVGAGainBounds -- ^ Desired gain
+                 -> IO ()
+bladeRFSetRXVGA2 dev g = do
+  c'bladerf_set_rxvga2 (unDeviceHandle dev) ((fromIntegral . fromEnum) g)
+  return () -- ignores ret
+
+-- | Get the post-LPF VGA gain
+bladeRFGetRXVGA2 :: DeviceHandle -- ^ Device handle
+                 -> IO Int       -- ^ Returned set gain level
+bladeRFGetRXVGA2 dev = do
+  p <- malloc :: IO (Ptr CInt)
+  c'bladerf_get_rxvga2 (unDeviceHandle dev) p
+  g <-  peek p
+  free p
+  return $ fromIntegral g
+
+-- | Set the pre-LPF VGA gain
+bladeRFSetRXVGA1 :: DeviceHandle         -- ^ Device handle
+                 -> BladeRFVGAGainBounds -- ^ Desired gain
+                 -> IO ()
+bladeRFSetRXVGA1 dev g = do
+  c'bladerf_set_rxvga1 (unDeviceHandle dev) ((fromIntegral . fromEnum) g)
+  return () -- ignores ret
+
+-- | Get the pre-LPF VGA gain
+bladeRFGetRXVGA1 :: DeviceHandle -- ^ Device handle
+                 -> IO Int       -- ^ Returned set gain level
+bladeRFGetRXVGA1 dev = do
+  p <- malloc :: IO (Ptr CInt)
+  c'bladerf_get_rxvga1 (unDeviceHandle dev) p
+  g <-  peek p
+  free p
+  return $ fromIntegral g
+
+-- | Set LNA Gain
+bladeRFSetLNAGain :: DeviceHandle   -- ^ Device handle
+                  -> BladeRFLNAGain -- ^ Desired gain level
+                  -> IO ()
+bladeRFSetLNAGain dev g = do
+  c'bladerf_set_lna_gain (unDeviceHandle dev) ((fromIntegral . fromEnum) g)
+  return () -- ignores ret
+
+-- | Get LNA Gain
+bladeRFGetLNAGain :: DeviceHandle      -- ^ Device handle
+                  -> IO BladeRFLNAGain -- ^ Returned set gain level
+bladeRFGetLNAGain dev = do
+  p <- malloc :: IO (Ptr C'bladerf_lna_gain)
+  c'bladerf_get_lna_gain (unDeviceHandle dev) p
+  g <-  peek p
+  free p
+  return $ (toEnum . fromIntegral) g
+
+--
+-- | Set a combined VGA TX gain
+--   This function computes the optimal TXVGA1 and TXVGA2 gains for a requested
+--   amount of gain
+-- XXX symb not found!!!
+--bladeRFSetTXGain :: DeviceHandle -> Int -> IO ()
+--bladeRFSetTXGain dev g = do
+--  c'bladerf_set_tx_gain (unDeviceHandle dev) (fromIntegral g)
+--  return () -- ignores ret
+
+-- | Set a combined pre and post LPF RX gain
+--   This function computes the optimal LNA, RXVGA1, and RVGA2 gains for a
+--   requested amount of RX gain, and computes the optimal TXVGA1 and TXVGA2 gains
+--   for a requested amount of TX gain
+bladeRFSetGain :: DeviceHandle  -- ^ Device handle
+               -> BladeRFModule -- ^ Module
+               -> Int           -- ^ Desired gain
+               -> IO ()
+bladeRFSetGain dev m g = do
+  c'bladerf_set_gain (unDeviceHandle dev) ((fromIntegral . fromEnum) m) (fromIntegral g)
+  return () -- ignores ret
diff --git a/src/LibBladeRF/Gpio.hs b/src/LibBladeRF/Gpio.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/Gpio.hs
@@ -0,0 +1,44 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module GPIO configuration handling
+-}
+
+module LibBladeRF.Gpio ( bladeRFConfigGPIORead
+                       , bladeRFConfigGPIOWrite
+                       ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+
+import Bindings.LibBladeRF
+import LibBladeRF.LibBladeRF
+import LibBladeRF.Types
+
+
+-- | Read a configuration GPIO register
+bladeRFConfigGPIORead :: DeviceHandle -- ^ Device handle
+                      -> IO Word32    -- ^ Read data
+bladeRFConfigGPIORead dev = do
+  pv <- malloc :: IO (Ptr Word32)
+  c'bladerf_config_gpio_read (unDeviceHandle dev) pv
+  v <- peek pv
+  free pv
+  return v
+
+-- | Write a configuration GPIO register. Callers should be sure to perform a
+--
+--   read-modify-write sequence to avoid accidentally clearing other
+--   GPIO bits that may be set by the library internally.
+bladeRFConfigGPIOWrite :: DeviceHandle -- ^ Device handle
+                       -> Word32       -- ^ Data to write to GPIO register
+                       -> IO ()
+bladeRFConfigGPIOWrite dev v = do
+  c'bladerf_config_gpio_write (unDeviceHandle dev) v
+  return () -- ignores ret
diff --git a/src/LibBladeRF/LibBladeRF.hs b/src/LibBladeRF/LibBladeRF.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/LibBladeRF.hs
@@ -0,0 +1,101 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module encapsulates the foundational libbladeRF functions
+  commonly used into a Monadic style. This Monadic style avoids
+  passing around references of indirection to the device type and
+  so on.
+-}
+
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# OPTIONS_HADDOCK prune #-}
+
+module LibBladeRF.LibBladeRF ( withBladeRF
+                             , DeviceHandle(..)
+                             , BladeRFError(..)
+                             ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+import Foreign.Ptr
+
+import Control.Exception
+import Data.Typeable (Typeable, cast)
+
+import Bindings.LibBladeRF
+
+
+-- | Error codes returned by internal libbladeRF functions.
+data BladeRFError = BLADERF_ERR_UNEXPECTED  -- ^ An unexpected failure occurred
+                  | BLADERF_ERR_RANGE       -- ^ Provided parameter is out of range
+                  | BLADERF_ERR_INVAL       -- ^ Invalid operation/parameter
+                  | BLADERF_ERR_MEM         -- ^ Memory allocation error
+                  | BLADERF_ERR_IO          -- ^ File/Device I/O error
+                  | BLADERF_ERR_TIMEOUT     -- ^ Operation timed out
+                  | BLADERF_ERR_NODEV       -- ^ No device(s) available
+                  | BLADERF_ERR_UNSUPPORTED -- ^ Operation not supported
+                  | BLADERF_ERR_MISALIGNED  -- ^ Misaligned flash access
+                  | BLADERF_ERR_CHECKSUM    -- ^ Invalid checksum
+                  | BLADERF_ERR_NO_FILE     -- ^ File not found
+                  | BLADERF_ERR_UPDATE_FPGA -- ^ An FPGA update is required
+                  | BLADERF_ERR_UPDATE_FW   -- ^ A firmware update is requied
+                  | BLADERF_ERR_TIME_PAST   -- ^ Requested timestamp is in the past
+                   deriving (Typeable)
+
+instance Show BladeRFError where
+  show BLADERF_ERR_UNEXPECTED  = "An unexpected failure occurred"
+  show BLADERF_ERR_RANGE       = "Provided parameter is out of range"
+  show BLADERF_ERR_INVAL       = "Invalid operation/parameter"
+  show BLADERF_ERR_MEM         = "Memory allocation error"
+  show BLADERF_ERR_IO          = "File/Device I/O error"
+  show BLADERF_ERR_TIMEOUT     = "Operation timed out"
+  show BLADERF_ERR_NODEV       = "No device(s) available"
+  show BLADERF_ERR_UNSUPPORTED = "Operation not supported"
+  show BLADERF_ERR_MISALIGNED  = "Misaligned flash access"
+  show BLADERF_ERR_CHECKSUM    = "Invalid checksum"
+  show BLADERF_ERR_NO_FILE     = "File not found"
+  show BLADERF_ERR_UPDATE_FPGA = "An FPGA update is required"
+  show BLADERF_ERR_UPDATE_FW   = "A firmware update is requied"
+  show BLADERF_ERR_TIME_PAST   = "Requested timestamp is in the past"
+
+instance Exception BladeRFError
+
+-- | DeviceHandle wrapper around C device descriptor pointer
+newtype DeviceHandle = DeviceHandle { unDeviceHandle :: Ptr C'bladerf }
+
+-- | Essential wrapper
+withBladeRF :: (DeviceHandle -> IO a) -> IO ()
+withBladeRF body = do
+  dev <- openBladeRF
+  body dev
+  closeBladeRF dev
+
+-- | Handy helper to wrap around Either results
+openBladeRF :: IO DeviceHandle
+openBladeRF = do
+  r <- openBladeRF'
+  case r of
+    Left e -> throwIO e
+    Right dev -> return dev
+
+-- Open specified device using a device identifier string.
+-- See bladerf_open_with_devinfo() if a device identifier string
+-- is not readily available.
+openBladeRF' :: IO (Either BladeRFError DeviceHandle)
+openBladeRF'  = alloca $ \ptr -> do
+  ret <- c'bladerf_open ptr nullPtr
+  if ret /= 0 then
+    return (Left BLADERF_ERR_NODEV) -- is this the right error in every case?
+  else do
+    pdev <- peek ptr
+    return (Right (DeviceHandle pdev))
+
+-- | Close device. Deallocates the memory allocated by openBladeRF when called.
+closeBladeRF :: DeviceHandle -> IO ()
+closeBladeRF d = c'bladerf_close $ unDeviceHandle d
diff --git a/src/LibBladeRF/Sampling.hs b/src/LibBladeRF/Sampling.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/Sampling.hs
@@ -0,0 +1,74 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module encapsulates sampling rate libbladeRF library functions.
+-}
+
+module LibBladeRF.Sampling ( bladeRFSetSampleRate
+                           , bladeRFSetRationalSampleRate
+                           , bladeRFSetBandwidth
+                           ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+
+import Bindings.LibBladeRF
+import LibBladeRF.LibBladeRF
+import LibBladeRF.Types
+
+
+-- | Configure the device's sample rate, in Hz.  Note this requires the sample
+--   rate is an integer value of Hz.  Use bladeRFSetRationalSampleRate
+--   for more arbitrary values.
+bladeRFSetSampleRate :: DeviceHandle  -- ^ Device handle
+                     -> BladeRFModule -- ^ Module to change
+                     -> Int           -- ^ Sample rate
+                     -> IO Int        -- ^ Actual sample rate achieved.
+bladeRFSetSampleRate dev m r = do
+  par <- malloc :: IO (Ptr CUInt)
+  c'bladerf_set_sample_rate (unDeviceHandle dev) ((fromIntegral . fromEnum) m) (fromIntegral r) par
+  actual <- peek par
+  free par
+  return $ fromIntegral actual
+
+-- | Configure the device's sample rate as a rational fraction of Hz.
+--   Sample rates are in the form of integer + num/denom.
+bladeRFSetRationalSampleRate :: DeviceHandle           -- ^ Device handle
+                             -> BladeRFModule          -- ^ Module to change
+                             -> BladeRFRationalRate    -- ^ Rational sample rate
+                             -> IO BladeRFRationalRate -- ^ Actual rational sample rate achieved.
+bladeRFSetRationalSampleRate dev m r = do
+  pr <- malloc :: IO (Ptr C'bladerf_rational_rate)
+  par <- malloc :: IO (Ptr C'bladerf_rational_rate)
+  let rate = C'bladerf_rational_rate { c'bladerf_rational_rate'integer = integer r
+                                     , c'bladerf_rational_rate'num     = num r
+                                     , c'bladerf_rational_rate'den     = den r
+                                     }
+  poke pr rate
+  c'bladerf_set_rational_sample_rate (unDeviceHandle dev) ((fromIntegral . fromEnum) m) pr par
+  ar <- peek par
+  let actual = BladeRFRationalRate { integer = c'bladerf_rational_rate'integer ar
+                                   , num     = c'bladerf_rational_rate'num ar
+                                   , den     = c'bladerf_rational_rate'den ar
+                                   }
+  free pr
+  free par
+  return actual
+
+-- | Set the bandwidth of the LMS LPF to specified value in Hz
+bladeRFSetBandwidth :: DeviceHandle  -- ^ Device handle
+                    -> BladeRFModule -- ^ Module for bandwidth request
+                    -> Int           -- ^ Desired bandwidth
+                    -> IO Int        -- ^ Actual bandwidth that the device was able to achieve.
+bladeRFSetBandwidth dev m b = do
+  ab <- malloc :: IO (Ptr CUInt)
+  c'bladerf_set_bandwidth (unDeviceHandle dev) ((fromIntegral . fromEnum) m) (fromIntegral b) ab
+  actual <- peek ab
+  free ab
+  return $ fromIntegral actual
diff --git a/src/LibBladeRF/Sync.hs b/src/LibBladeRF/Sync.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/Sync.hs
@@ -0,0 +1,110 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module encapsulates Synchronous data transmission and reception
+ 
+  This group of functions presents synchronous, blocking calls (with optional
+  timeouts) for transmitting and receiving samples.
+ 
+  The synchronous interface is built atop the asynchronous interface, and is
+  generally less complex and easier to work with.  It alleviates the need to
+  explicitly spawn threads (it is done under the hood) and manually manage
+  sample buffers.
+ 
+  Under the hood, this interface spawns worker threads to handle an
+  asynchronous stream and perform thread-safe buffer management.
+-}
+
+module LibBladeRF.Sync ( bladeRFSyncConfig
+                       , bladeRFSyncTx
+                       , bladeRFSyncRx
+                       ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+
+import qualified Data.ByteString as BS
+
+import Bindings.LibBladeRF
+import LibBladeRF.LibBladeRF
+import LibBladeRF.Types
+
+
+-- | (Re)Configure a device for synchronous transmission or reception
+bladeRFSyncConfig :: DeviceHandle  -- ^ Device handle
+                  -> BladeRFModule -- ^ Module to use with synchronous interface
+                  -> BladeRFFormat -- ^ Format to use in synchronous data transfers
+                  -> Int           -- ^ The number of buffers to use in the underlying data stream.
+                  -> Int           -- ^ The size of the underlying stream buffers, in samples. This value must be a multiple of 1024.
+                  -> Int           -- ^ The number of active USB transfers that may be in-flight at any given time.
+                  -> Int           -- ^ Timeout (milliseconds) for transfers in the underlying data stream.
+                  -> IO ()
+
+bladeRFSyncConfig dev m f nb sz tr to = do
+  c'bladerf_sync_config (unDeviceHandle dev) ((fromIntegral . fromEnum) m) ((fromIntegral . fromEnum) f) (fromIntegral nb) (fromIntegral sz) (fromIntegral tr) (fromIntegral to)
+  return () -- ignores ret
+
+-- | Transmit IQ samples.
+--
+-- Under the hood, this call starts up an underlying asynchronous stream as
+-- needed. This stream can be stopped by disabling the TX module. (See
+-- bladeRFEnableModule for more details.)
+--
+-- Samples will only be sent to the FPGA when a buffer have been filled. The
+-- number of samples required to fill a buffer corresponds to the `buffer_size`
+-- parameter passed to bladeRFSyncConfig.
+bladeRFSyncTx :: DeviceHandle    -- ^ Device handle
+              -> BS.ByteString   -- ^ Array of samples
+              -> Int             -- ^ Number of samples to write
+              -> BladeRFMetadata -- ^ Sample metadata. This must be provided when using
+                                 --   the ::BLADERF_FORMAT_SC16_Q11_META format, but may
+                                 --   be NULL when the interface is configured for
+                                 --   the ::BLADERF_FORMAT_SC16_Q11 format.
+              -> Int             -- ^ Timeout (milliseconds) for this call to complete. Zero implies infinite.
+              -> IO ()
+bladeRFSyncTx dev s n md t = do
+  pmd <- malloc :: IO (Ptr C'bladerf_metadata)
+-- Use the following instead when switching to ghc7.8 later..
+-- bladeRFMetadataToCBladeRFMetadata :: BladeRFMetadata -> C'bladerf_metadata
+  let meta = C'bladerf_metadata { c'bladerf_metadata'timestamp    = timestamp md
+                                , c'bladerf_metadata'flags        = flags     md
+                                , c'bladerf_metadata'status       = status    md
+                                , c'bladerf_metadata'actual_count = (fromIntegral . count) md
+                                , c'bladerf_metadata'reserved     = [0]
+                                }
+  poke pmd meta
+  BS.useAsCStringLen s $
+    \(p, _len) -> c'bladerf_sync_tx (unDeviceHandle dev) p (fromIntegral n) pmd (fromIntegral t)
+  free pmd
+
+-- | Receive IQ samples.
+--
+-- Underthe hood, this call starts up an underlying asynchronous stream as
+-- needed. This stream can be stopped by disabling the RX module. (See
+-- bladeRFEnableModule for more details.)
+bladeRFSyncRx :: DeviceHandle    -- ^ Device handle
+              -> Int             -- ^ Number of samples to read
+              -> Int             -- ^ Timeout (milliseconds) for this call to complete. Zero implies infinite.
+              -> IO (BS.ByteString, BladeRFMetadata)
+bladeRFSyncRx dev n t = do
+  pmd <- malloc :: IO (Ptr C'bladerf_metadata)
+  ptr <- mallocBytes (4 * n)
+  c'bladerf_sync_rx (unDeviceHandle dev) ptr (fromIntegral n) pmd (fromIntegral t)
+  par <- peekArray (4 * n) ptr
+  let bs = BS.pack par
+  cmd <- peek pmd
+ -- Use the following instead when switching to ghc7.8 later..
+ -- bladeRFMetadataFromCBladeRFMetadata :: C'bladerf_metadata -> BladeRFMetadata 
+  let meta = BladeRFMetadata { timestamp = c'bladerf_metadata'timestamp    cmd
+                             , flags     = c'bladerf_metadata'flags        cmd
+                             , status    = c'bladerf_metadata'status       cmd
+                             , count     = fromIntegral $ c'bladerf_metadata'actual_count cmd
+                             }
+  free pmd
+  return (bs, meta)
diff --git a/src/LibBladeRF/Types.hs b/src/LibBladeRF/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/Types.hs
@@ -0,0 +1,313 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module encapsulates types libbladeRF library functions.
+-}
+
+{-# LANGUAGE Trustworthy, DeriveGeneric #-}
+
+module LibBladeRF.Types ( BladeRFVersion(..)
+                        , BladeRFDeviceInfo(..)
+                        , BladeRFFPGASize(..)
+                        , BladeRFBackend(..)
+                        , BladeRFRationalRate(..)
+                        , BladeRFModule(..)
+                        , BladeRFFormat(..)
+                        , BladeRFLNAGain(..)
+                        , BladeRFVGAGainBounds(..)
+                        , BladeRFCorrection(..)
+                        , BladeRFSpeed(..)
+                        , BladeRFMetadata(..)
+--                        needs ghc >= 7.8
+--                        , bladeRFMetadataToCBladeRFMetadata
+--                        , bladeRFMetadataFromCBladeRFMetadata
+                        ) where
+
+
+import Bindings.LibBladeRF
+
+import Foreign.C.Types
+import Data.Word
+import Data.Maybe
+import Data.Tuple
+--import Data.Coerce
+--import GHC.Generics
+
+--
+-- | Version structure for FPGA, firmware, libbladeRF, and associated utilities
+data BladeRFVersion = BladeRFVersion { major :: Word16 -- ^ Major version
+                                     , minor :: Word16 -- ^ Minor version
+                                     , patch :: Word16 -- ^ Patch version
+                                     , descr :: String -- ^ Version string with any additional suffix information.
+                                     } deriving (Eq)
+
+instance Show BladeRFVersion where
+  show a = show (major a) ++ "." ++
+           show (minor a) ++ "." ++
+           show (patch a) ++ " (" ++
+                descr a ++ ")"
+
+--
+-- | Information about a bladeRF attached to the system
+data BladeRFDeviceInfo = BladeRFDeviceInfo { backend :: BladeRFBackend -- ^ Backend to use when connecting to device
+                                           , serial  :: String         -- ^ Device serial number string
+                                           , usbBus  :: Word8          -- ^ Bus number device is attached to
+                                           , usbAddr :: Word8          -- ^ Device address on bus
+                                           , inst    :: CUInt          -- ^ Device instance or ID
+                                           } deriving (Eq)
+
+instance Show BladeRFDeviceInfo where
+  show a = " Backend : " ++ show (backend a) ++ "\n" ++
+           " Serial #: " ++ serial a ++ "\n" ++
+           " USB bus: " ++ show (usbBus a) ++ "\n" ++
+           " USB address: " ++ show (usbAddr a) ++ "\n" ++
+           " Instance: " ++ show (inst a)
+
+--
+-- | FPGA device variant (size)
+data BladeRFFPGASize = FPGA_UNKNOWN -- ^ Unable to determine FPGA variant
+                     | FPGA_40KLE   -- ^ 40 kLE FPGA
+                     | FPGA_115KLE  -- ^ 115 kLE FPGA
+                     deriving (Eq)
+
+instance Show BladeRFFPGASize where
+  show FPGA_UNKNOWN = "Unable to determine FPGA variant"
+  show FPGA_40KLE   = "40 kLE FPGA"
+  show FPGA_115KLE  = "115 kLE FPGA"
+
+instance Enum BladeRFFPGASize where
+  fromEnum = fromJust . flip lookup sizes
+  toEnum   = fromJust . flip lookup (map swap sizes)
+
+sizes = [ (FPGA_UNKNOWN, c'BLADERF_FPGA_UNKNOWN)
+        , (FPGA_40KLE, c'BLADERF_FPGA_40KLE)
+        , (FPGA_115KLE, c'BLADERF_FPGA_115KLE)
+        ]
+
+-- | Backend by which the host communicates with the device
+data BladeRFBackend = BACKEND_ANY     -- ^ Don't Care, use any available backend
+                    | BACKEND_LINUX   -- ^ Linux kernel driver
+                    | BACKEND_LIBUSB  -- ^ libusb
+                    | BACKEND_CYPRESS -- ^ CyAPI
+                    | BACKEND_DUMMY   -- ^ Dummy used for development purposes
+                    deriving (Eq)
+
+instance Show BladeRFBackend where
+  show BACKEND_ANY     = "Don't Care, use any available backend"
+  show BACKEND_LINUX   = "Linux kernel driver"
+  show BACKEND_LIBUSB  = "libusb"
+  show BACKEND_CYPRESS = "CyAPI"
+  show BACKEND_DUMMY   = "Dummy used for development purposes"
+
+instance Enum BladeRFBackend where
+  fromEnum = fromJust . flip lookup backends
+  toEnum   = fromJust . flip lookup (map swap backends)
+
+backends = [ (BACKEND_ANY, c'BLADERF_BACKEND_ANY)
+           , (BACKEND_LINUX, c'BLADERF_BACKEND_LINUX)
+           , (BACKEND_LIBUSB, c'BLADERF_BACKEND_LIBUSB)
+           , (BACKEND_CYPRESS, c'BLADERF_BACKEND_CYPRESS)
+           , (BACKEND_DUMMY, c'BLADERF_BACKEND_DUMMY)
+           ]
+
+-- | Rational sample rate representation
+data BladeRFRationalRate = BladeRFRationalRate { integer :: Word64 -- ^ Integer portion
+                                               , num     :: Word64 -- ^ Numerator in fractional portion
+                                               , den     :: Word64 -- ^ Denominator in fractional portion. This must be > 0.
+                                               } deriving (Eq, Show)
+
+
+-- | Module selection for those which have both RX and TX constituents
+data BladeRFModule = MODULE_RX -- ^ Receive Module
+                   | MODULE_TX -- ^ Transmit Module
+                   deriving (Eq)
+
+instance Enum BladeRFModule where
+  fromEnum = fromJust . flip lookup modules
+  toEnum   = fromJust . flip lookup (map swap modules)
+
+modules = [ (MODULE_RX, c'BLADERF_MODULE_RX)
+          , (MODULE_TX, c'BLADERF_MODULE_TX)
+          ]
+
+
+-- | Sample format
+data BladeRFFormat
+  {-| Signed, Complex 16-bit Q11. This is the native format of the DAC data.
+
+      Values in the range [-2048, 2048) are used to represent [-1.0, 1.0).
+      Note that the lower bound here is inclusive, and the upper bound is
+      exclusive. Ensure that provided samples stay within [-2048, 2047].
+
+      Samples consist of interleaved IQ value pairs, with I being the first
+      value in the pair. Each value in the pair is a right-aligned,
+      little-endian int16_t. The FPGA ensures that these values are
+      sign-extended.
+
+      When using this format the minimum required buffer size, in bytes, is:
+
+      > buffer_size_min = [ 2 * num_samples * sizeof(int16_t) ]
+
+      For example, to hold 2048 samples, a buffer must be at least 8192 bytes
+      large.
+  -}
+  = FORMAT_SC16_Q11
+  {-| This format is the same as the 'FORMAT_SC16_Q11' format, except the
+    first 4 samples (16 bytes) in every block of 1024 samples are replaced
+    with metadata, organized as follows, with all fields being little endian
+    byte order:
+
+    @
+     0x00 [uint32_t:  Reserved]
+     0x04 [uint64_t:  64-bit Timestamp]
+     0x0c [uint32_t:  BLADERF_META_FLAG_* flags]
+    @
+
+    When using the 'bladeRFSyncRx' and 'bladeRFSyncTx' actions,
+    this detail is transparent to caller. These functions take care of
+    packing/unpacking the metadata into/from the data, via the
+    bladerf_metadata structure.
+
+    Currently, when using the asynchronous data transfer interface, the user
+    is responsible for manually packing/unpacking this metadata into/from
+    their sample data.
+  -}
+  | FORMAT_SC16_Q11_META
+   deriving (Eq)
+
+
+instance Enum BladeRFFormat where
+  fromEnum = fromJust . flip lookup formats
+  toEnum   = fromJust . flip lookup (map swap formats)
+
+formats = [ (FORMAT_SC16_Q11, c'BLADERF_FORMAT_SC16_Q11)
+          , (FORMAT_SC16_Q11_META, c'BLADERF_FORMAT_SC16_Q11_META)
+          ]
+
+
+-- | LNA gain options
+data BladeRFLNAGain = LNA_GAIN_UNKNOWN -- ^ Invalid LNA gain
+                    | LNA_GAIN_BYPASS  -- ^ LNA bypassed - 0dB gain
+                    | LNA_GAIN_MID     -- ^ LNA Mid Gain (MAX-6dB)
+                    | LNA_GAIN_MAX     -- ^ LNA Max Gain
+                    deriving (Eq)
+
+instance Enum BladeRFLNAGain where
+  fromEnum = fromJust . flip lookup lgains
+  toEnum   = fromJust . flip lookup (map swap lgains)
+
+lgains = [ (LNA_GAIN_UNKNOWN, c'BLADERF_LNA_GAIN_UNKNOWN)
+         , (LNA_GAIN_BYPASS, c'BLADERF_LNA_GAIN_BYPASS)
+         , (LNA_GAIN_MID, c'BLADERF_LNA_GAIN_MID)
+         , (LNA_GAIN_MAX, c'BLADERF_LNA_GAIN_MAX)
+         ]
+
+-- | Device control and configuration
+--
+-- This section provides functions pertaining to accessing, controlling, and
+-- configuring various device options and parameters.
+data BladeRFVGAGainBounds = RXVGA1_GAIN_MIN -- ^ Minimum RXVGA1 gain, in dB
+                          | RXVGA1_GAIN_MAX -- ^ Maximum RXVGA1 gain, in dB
+                          | RXVGA2_GAIN_MIN -- ^ Minimum RXVGA2 gain, in dB
+                          | RXVGA2_GAIN_MAX -- ^ Maximum RXVGA2 gain, in dB
+                          | TXVGA1_GAIN_MIN -- ^ Minimum TXVGA1 gain, in dB
+                          | TXVGA1_GAIN_MAX -- ^ Maximum TXVGA1 gain, in dB
+                          | TXVGA2_GAIN_MIN -- ^ Minimum TXVGA2 gain, in dB
+                          | TXVGA2_GAIN_MAX -- ^ Maximum TXVGA2 gain, in dB
+                          deriving (Eq)
+
+instance Enum BladeRFVGAGainBounds where
+  fromEnum = fromJust . flip lookup vgains
+  toEnum   = fromJust . flip lookup (map swap vgains)
+
+vgains = [ (RXVGA1_GAIN_MIN, c'BLADERF_RXVGA1_GAIN_MIN)
+         , (RXVGA1_GAIN_MAX, c'BLADERF_RXVGA1_GAIN_MAX)
+         , (RXVGA2_GAIN_MIN, c'BLADERF_RXVGA2_GAIN_MIN)
+         , (RXVGA2_GAIN_MAX, c'BLADERF_RXVGA2_GAIN_MAX)
+         , (TXVGA1_GAIN_MIN, c'BLADERF_TXVGA1_GAIN_MIN)
+         , (TXVGA1_GAIN_MAX, c'BLADERF_TXVGA1_GAIN_MAX)
+         , (TXVGA2_GAIN_MIN, c'BLADERF_TXVGA2_GAIN_MIN)
+         , (TXVGA2_GAIN_MAX, c'BLADERF_TXVGA2_GAIN_MAX)
+         ]
+
+-- | Correction parameter selection
+--
+-- These values specify the correction parameter to modify or query when
+-- calling bladerf_set_correction() or bladerf_get_correction(). Note that the
+-- meaning of the `value` parameter to these functions depends upon the
+-- correction parameter.
+data BladeRFCorrection = CORR_LMS_DCOFF_I -- ^ Adjusts the in-phase DC offset via controls provided by the LMS6002D
+                                          --   front end. Valid values are [-2048, 2048], which are scaled to the
+                                          --   available control bits in the LMS device.
+                       | CORR_LMS_DCOFF_Q -- ^ Adjusts the quadrature DC offset via controls provided the LMS6002D
+                                          --   front end. Valid values are [-2048, 2048], which are scaled to the
+                                          --   available control bits.
+                       | CORR_FPGA_PHASE  -- ^ Adjusts FPGA-based phase correction of [-10, 10] degrees, via a provided
+                                          --   count value of [-4096, 4096].
+                       | CORR_FPGA_GAIN   -- ^ Adjusts FPGA-based gain correction of [0.0, 2.0], via provided
+                                          --   values in the range of [-4096, 4096], where a value of 0 corresponds to
+                                          --   a gain of 1.0.
+                       deriving (Eq)
+
+instance Enum BladeRFCorrection where
+  fromEnum = fromJust . flip lookup corrections
+  toEnum   = fromJust . flip lookup (map swap corrections)
+
+corrections = [ (CORR_LMS_DCOFF_I, c'BLADERF_CORR_LMS_DCOFF_I)
+              , (CORR_LMS_DCOFF_Q, c'BLADERF_CORR_LMS_DCOFF_Q)
+              , (CORR_FPGA_PHASE, c'BLADERF_CORR_FPGA_PHASE)
+              , (CORR_FPGA_GAIN, c'BLADERF_CORR_FPGA_GAIN)
+              ]
+
+
+-- | This enum describes the USB Speed at which the bladeRF is connected.
+--
+-- Speeds not listed here are not supported.
+data BladeRFSpeed = DEVICE_SPEED_UNKNOWN -- ^ Unknown
+                  | DEVICE_SPEED_HIGH    -- ^ USB2.0
+                  | DEVICE_SPEED_SUPER   -- ^ USB3.0
+                   deriving (Eq)
+
+instance Show BladeRFSpeed where
+  show DEVICE_SPEED_UNKNOWN = "unknown speed"
+  show DEVICE_SPEED_HIGH    = "high speed"
+  show DEVICE_SPEED_SUPER   = "super speed"
+
+instance Enum BladeRFSpeed where
+  fromEnum = fromJust . flip lookup speeds
+  toEnum   = fromJust . flip lookup (map swap speeds)
+
+speeds = [ (DEVICE_SPEED_UNKNOWN, c'BLADERF_DEVICE_SPEED_UNKNOWN)
+         , (DEVICE_SPEED_HIGH, c'BLADERF_DEVICE_SPEED_HIGH)
+         , (DEVICE_SPEED_SUPER, c'BLADERF_DEVICE_SPEED_SUPER)
+         ]
+
+
+-- | Sample metadata
+--
+-- This structure is used in conjunction with the 'FORMAT_SC16_Q11_META'
+-- format to TX scheduled bursts or retrieve timestamp information about
+-- received samples.
+data BladeRFMetadata = BladeRFMetadata { timestamp :: Word64 -- ^ Free-running FPGA counter that monotonically increases
+                                                             --   at the sample rate of the associated module.
+                                       , flags     :: Word32 -- ^ Input bit field to control the behavior of the call
+                                                             --   that the metadata structure is passed to.
+                                       , status    :: Word32 -- ^ Output bit field to denoting the status of
+                                                             --   transmissions/receptions.
+                                       , count     :: Int    -- ^ This output parameter is updated to reflect the actual
+                                                             --   number of contiguous samples that have been populated
+                                                             --   in an RX buffer during a 'bladeRFSyncRx' call.
+                                       }
+
+
+-- | Isomorpishms
+--bladeRFMetadataToCBladeRFMetadata :: BladeRFMetadata -> C'bladerf_metadata
+--bladeRFMetadataToCBladeRFMetadata  = to . coerce . from
+--
+--bladeRFMetadataFromCBladeRFMetadata :: C'bladerf_metadata -> BladeRFMetadata
+--bladeRFMetadataFromCBladeRFMetadata  = to . coerce . from
diff --git a/src/LibBladeRF/Utils.hs b/src/LibBladeRF/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/LibBladeRF/Utils.hs
@@ -0,0 +1,154 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  This module encapsulates misc libbladeRF library functions.
+-}
+
+module LibBladeRF.Utils ( bladeRFLibVersion
+                        , bladeRFFwVersion
+                        , bladeRFFPGAVersion
+                        , bladeRFDeviceSpeed
+                        , bladeRFLoadFPGA
+                        , bladeRFGetDevInfo
+                        , bladeRFGetSerial
+                        , bladeRFGetFPGASize
+                        , bladeRFEnableModule
+                        ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+
+import Bindings.LibBladeRF
+import LibBladeRF.LibBladeRF
+import LibBladeRF.Types
+
+
+-- | Get libbladeRF version information
+-- bladeRFLibVersion :: IO BladeRFVersion
+bladeRFLibVersion = do
+  p <- malloc :: IO (Ptr C'bladerf_version)
+  c'bladerf_version p
+  brfv <- peek p
+  desc <- peekCString $ c'bladerf_version'describe brfv
+  let ver = BladeRFVersion { major = c'bladerf_version'major brfv
+                           , minor = c'bladerf_version'minor brfv
+                           , patch = c'bladerf_version'patch brfv
+                           , descr = desc
+                           }
+  free p
+  return ver
+
+-- | Query firmware version
+bladeRFFwVersion :: DeviceHandle      -- ^ Device handle
+                 -> IO BladeRFVersion -- ^ Returned firmware version
+bladeRFFwVersion dev = do
+  p <- malloc :: IO (Ptr C'bladerf_version)
+  c'bladerf_fw_version (unDeviceHandle dev) p
+  brfv <- peek p
+  desc <- peekCString $ c'bladerf_version'describe brfv
+  let ver = BladeRFVersion { major = c'bladerf_version'major brfv
+                           , minor = c'bladerf_version'minor brfv
+                           , patch = c'bladerf_version'patch brfv
+                           , descr = desc
+                           }
+  free p
+  return ver
+
+-- | Query FPGA version
+bladeRFFPGAVersion :: DeviceHandle      -- ^ Device handle
+                   -> IO BladeRFVersion -- ^ Returned firmware version
+bladeRFFPGAVersion dev = do
+  status <- c'bladerf_is_fpga_configured (unDeviceHandle dev)
+  if status > 0 then do
+    p <- malloc :: IO (Ptr C'bladerf_version)
+    c'bladerf_fpga_version (unDeviceHandle dev) p
+    brfv <- peek p
+    desc <- peekCString $ c'bladerf_version'describe brfv
+    let ver = BladeRFVersion { major = c'bladerf_version'major brfv
+                             , minor = c'bladerf_version'minor brfv
+                             , patch = c'bladerf_version'patch brfv
+                             , descr = desc
+                             }
+    free p
+    return ver
+  else
+    return    BladeRFVersion { major = 0
+                             , minor = 0
+                             , patch = 0
+                             , descr = "Unknown (FPGA not loaded)"
+                             }
+
+
+-- | Load device's FPGA. Note that this FPGA configuration will be reset
+--   at the next power cycle.
+-- pass Full path to FPGA bitstream
+bladeRFLoadFPGA :: DeviceHandle -- ^ Device handle
+                -> String       -- ^ Full path to FPGA bitstream
+                -> IO ()
+bladeRFLoadFPGA dev s = do
+  p <- newCString s
+  _ <- c'bladerf_load_fpga (unDeviceHandle dev) p
+  return ()
+
+-- | Obtain the bus speed at which the device is operating
+bladeRFDeviceSpeed :: DeviceHandle    -- ^ Device handle
+                   -> IO BladeRFSpeed -- ^ Device speed
+bladeRFDeviceSpeed dev = do
+  speed <- c'bladerf_device_speed (unDeviceHandle dev)
+  return $ (toEnum . fromEnum) speed
+
+-- | Fill out a provided bladerf_devinfo structure, given an open device handle.
+bladeRFGetDevInfo :: DeviceHandle         -- ^ Device handle
+                  -> IO BladeRFDeviceInfo -- ^ Device information populated by this function
+bladeRFGetDevInfo dev = do
+  p <- malloc :: IO (Ptr C'bladerf_devinfo)
+  c'bladerf_get_devinfo (unDeviceHandle dev) p
+-- XXX ^ handle status return error with Maybe monad???
+  brfv <- peek p
+  let info = BladeRFDeviceInfo { backend = toEnum . fromEnum . c'bladerf_devinfo'backend $ brfv
+                               , serial  = map castCCharToChar . c'bladerf_devinfo'serial $ brfv
+                               , usbBus  = c'bladerf_devinfo'usb_bus brfv
+                               , usbAddr = c'bladerf_devinfo'usb_addr brfv
+                               , inst    = c'bladerf_devinfo'instance brfv
+                               }
+  free p
+  return info
+
+-- | Query a device's serial number
+bladeRFGetSerial :: DeviceHandle -- ^ Device handle
+                 -> IO String    -- ^ Returned serial number.
+bladeRFGetSerial dev = do
+  cstring <- mallocBytes 34 -- device serial is 33 bytes long + null terminating byte.
+  -- API bug bladerf_get_serial() should be allocating the buffer itself, not the call site!
+  c'bladerf_get_serial (unDeviceHandle dev) cstring
+  serial <- peekCString cstring
+  free cstring
+  return serial
+
+-- | Query a device's FPGA size
+bladeRFGetFPGASize :: DeviceHandle       -- ^ Device handle
+                   -> IO BladeRFFPGASize -- ^ Returned on-board FPGA's size.
+bladeRFGetFPGASize dev = do
+  p <- malloc :: IO (Ptr C'bladerf_fpga_size)
+  c'bladerf_get_fpga_size (unDeviceHandle dev) p
+  sz <- peek p
+  free p
+  return $ (toEnum . fromEnum) sz
+
+
+-- | Enable or disable the specified RX/TX module.
+--   When a synchronous stream is associated with the specified module, this
+--   will shut down the underlying asynchronous stream when `enable` = false.
+bladeRFEnableModule :: DeviceHandle  -- ^ Device handle
+                    -> BladeRFModule -- ^ Device module
+                    -> Bool          -- ^ true to enable, false to disable
+                    -> IO ()
+bladeRFEnableModule dev m t = do
+  c'bladerf_enable_module (unDeviceHandle dev) ((fromIntegral . fromEnum) m) t
+  return () -- XXX ignore ret
diff --git a/src/inlines.c b/src/inlines.c
new file mode 100644
--- /dev/null
+++ b/src/inlines.c
@@ -0,0 +1,1 @@
+#include <libbladeRF.h>
diff --git a/test-suite/HLint.hs b/test-suite/HLint.hs
new file mode 100644
--- /dev/null
+++ b/test-suite/HLint.hs
@@ -0,0 +1,26 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  test-suite/HLint.hs
+-}
+
+module Main (main) where
+
+import Language.Haskell.HLint (hlint)
+import System.Exit (exitFailure, exitSuccess)
+
+arguments :: [String]
+arguments =
+    [ "src"
+    , "test-suite"
+    ]
+
+main :: IO ()
+main = do
+    hints <- hlint arguments
+    if null hints then exitSuccess else exitFailure
diff --git a/test-suite/Haddock.hs b/test-suite/Haddock.hs
new file mode 100644
--- /dev/null
+++ b/test-suite/Haddock.hs
@@ -0,0 +1,36 @@
+{-|
+  Module      : $Header$
+  Copyright   : (c) 2014 Edward O'Callaghan
+  License     : LGPL-2.1
+  Maintainer  : eocallaghan@alterapraxis.com
+  Stability   : provisional
+  Portability : portable
+
+  test-suite/Haddock.hs
+-}
+
+module Main (main) where
+
+import Data.List (genericLength)
+import Data.Maybe (catMaybes)
+import System.Exit (exitFailure, exitSuccess)
+import System.Process (readProcess)
+import Text.Regex (matchRegex, mkRegex)
+
+average :: (Fractional a, Real b) => [b] -> a
+average xs = realToFrac (sum xs) / genericLength xs
+
+expected :: Fractional a => a
+expected = 90
+
+main :: IO ()
+main = do
+    output <- readProcess "cabal" ["haddock"] ""
+    if average (match output) >= expected
+        then exitSuccess
+        else putStr output >> exitFailure
+
+match :: String -> [Int]
+match = fmap read . concat . catMaybes . fmap (matchRegex pattern) . lines
+  where
+    pattern = mkRegex "^ *([0-9]*)% "
