aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2019-03-23 00:03:29 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2019-03-23 00:03:29 +0100
commit2cf0eaffddab2457fc81d672599c0f58eb6950f9 (patch)
treef1964cdc4d9a4f7ff8ffa15b2a359cdad55a58d8
parenteb11e68412b49b0945ab6bb332ac9486f1ebeb9e (diff)
parentdf33203db5007218384e6724748be52a1d4fdb25 (diff)
downloadosmo-fl2k-interleaved_rg.tar.gz
osmo-fl2k-interleaved_rg.tar.bz2
osmo-fl2k-interleaved_rg.zip
Merge remote-tracking branch 'upstream/master' into interleaved_rgHEADinterleaved_rg
-rw-r--r--CMakeLists.txt4
-rw-r--r--debian/changelog18
-rw-r--r--debian/compat1
-rw-r--r--debian/control50
-rw-r--r--debian/copyright97
-rw-r--r--debian/libosmo-fl2k-dev.install4
-rw-r--r--debian/libosmo-fl2k0.install1
-rw-r--r--debian/osmo-fl2k.install1
-rwxr-xr-xdebian/rules11
-rw-r--r--debian/source/format1
-rw-r--r--debian/watch3
-rw-r--r--include/osmo-fl2k.h35
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/fl2k_file.c26
-rw-r--r--src/fl2k_tcp.c18
-rw-r--r--src/fl2k_test.c14
-rw-r--r--src/libosmo-fl2k.c144
17 files changed, 386 insertions, 48 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b6bcb5b..5fb110f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,6 +22,8 @@
cmake_minimum_required(VERSION 2.6)
project(libosmo-fl2k C)
+include(GNUInstallDirs)
+
#select the release build type by default to get optimization flags
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
@@ -157,7 +159,7 @@ CONFIGURE_FILE(
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/libosmo-fl2k.pc
- DESTINATION ${LIB_INSTALL_DIR}/pkgconfig
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
########################################################################
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..40e26ef
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,18 @@
+osmo-fl2k (0.1.0git) unstable; urgency=medium
+
+ * Osmocom debian recipes for nightly builds
+
+ -- Harald Welte <laforge@gnumonks.org> Sun, 03 Jun 2018 16:13:07 +0200
+
+osmo-fl2k (0.1.0+20180423git9e79bde-2) unstable; urgency=medium
+
+ * debian/control: set team as maintainer
+ * debian/copyright: add some entries (Closes: #896832)
+
+ -- Thorsten Alteholz <debian@alteholz.de> Wed, 25 Apr 2018 19:28:07 +0200
+
+osmo-fl2k (0.1.0+20180423git9e79bde-1) unstable; urgency=medium
+
+ * Initial release.
+
+ -- Thorsten Alteholz <debian@alteholz.de> Tue, 24 Apr 2018 18:28:07 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..751034c
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,50 @@
+Source: osmo-fl2k
+Section: libs
+Priority: optional
+Maintainer: Debian Mobcom Maintainers <Debian-mobcom-maintainers@lists.alioth.debian.org>
+Uploaders: Thorsten Alteholz <debian@alteholz.de>
+Build-Depends: debhelper (>= 9.0.0~), dh-autoreconf
+ , pkg-config
+ , cmake
+ , libusb-1.0-0-dev
+Standards-Version: 4.1.4
+Vcs-Browser: https://salsa.debian.org/debian-mobcom-team/osmo-fl2k
+Vcs-Git: https://salsa.debian.org/debian-mobcom-team/osmo-fl2k.git
+Homepage: https://projects.osmocom.org/projects/osmo-fl2k
+
+Package: osmo-fl2k
+Section: net
+Architecture: any
+Multi-Arch: no
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: use a VGA USB adapter as DAC and SDR transmitter
+ This software allows one to use USB 3.0 to VGA adapters based on the
+ Fresco Logic FL2000 chip as general purpose DACs and SDR transmitter
+ generating a continuous stream of samples by avoiding the HSYNC and
+ VSYNC blanking intervals.
+
+Package: libosmo-fl2k0
+Architecture: any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: use a VGA USB adapter as DAC and SDR transmitter - library
+ This software allows one to use USB 3.0 to VGA adapters based on the
+ Fresco Logic FL2000 chip as general purpose DACs and SDR transmitter
+ generating a continuous stream of samples by avoiding the HSYNC and
+ VSYNC blanking intervals.
+ .
+ This package provides the shared library.
+
+Package: libosmo-fl2k-dev
+Section: libdevel
+Architecture: any
+Depends: libosmo-fl2k0 (= ${binary:Version}), ${misc:Depends}
+Description: use a VGA USB adapter as DAC and SDR transmitter - development
+ This software allows one to use USB 3.0 to VGA adapters based on the
+ Fresco Logic FL2000 chip as general purpose DACs and SDR transmitter
+ generating a continuous stream of samples by avoiding the HSYNC and
+ VSYNC blanking intervals.
+ .
+ This package provides the development files.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..a1949b6
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,97 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: osmo-fl2k
+Source: git://git.osmocom.org/
+
+Files: *
+Copyright: 2012-2018 Steve Markgraf <steve@steve-m.de>
+ 2009 Bartek Kania <mbk@gnarf.org>
+ 2012-2014 Kyle Keen <keenerd@gmail.com>
+ 2014 Michael Tatarinov <kukabu@gmail.com>
+License: GPL-2.0+
+
+Files: src/rds_mod.c include/rds_mod.h
+Copyright: 2018 Steve Markgraf <steve@steve-m.de>
+ 2014 Christophe Jacquet, F8FTK
+License: GPL-3.0+
+
+Files: src/rds_waveforms.c
+Copyright: 2014 Christophe Jacquet.
+License: GPL-3.0
+
+Files: src/getopt/*
+Copyright: 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001 Free Software Foundation, Inc.
+License: LGPL-2.1+
+Comment: This file is part of the GNU C Library.
+
+License: LGPL-2.1+
+ The GNU C 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.
+ .
+ The GNU C 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 the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+ .
+ On Debian systems, the complete text of the GNU Lesser General Public
+ License Version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'.
+
+Files: debian/*
+Copyright: 2018 Thorsten Alteholz <debian@alteholz.de>
+License: GPL-2.0+
+
+License: GPL-2.0+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+ .
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General Public License
+ Version 2 can be found in `/usr/share/common-licenses/GPL-2'.
+
+License: GPL-3.0+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ .
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General Public License
+ Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
+
+License: GPL-3.0
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation in version 3 of the License.
+ .
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General Public License
+ Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
diff --git a/debian/libosmo-fl2k-dev.install b/debian/libosmo-fl2k-dev.install
new file mode 100644
index 0000000..e1bb00c
--- /dev/null
+++ b/debian/libosmo-fl2k-dev.install
@@ -0,0 +1,4 @@
+usr/include/*
+usr/lib/*/pkgconfig/libosmo-fl2k.pc
+usr/lib/*/libosmo-fl2k.a
+usr/lib/*/*.so
diff --git a/debian/libosmo-fl2k0.install b/debian/libosmo-fl2k0.install
new file mode 100644
index 0000000..3de3b10
--- /dev/null
+++ b/debian/libosmo-fl2k0.install
@@ -0,0 +1 @@
+usr/lib/*/*.so.*
diff --git a/debian/osmo-fl2k.install b/debian/osmo-fl2k.install
new file mode 100644
index 0000000..1df36c6
--- /dev/null
+++ b/debian/osmo-fl2k.install
@@ -0,0 +1 @@
+usr/bin/*
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..74833df
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,11 @@
+#!/usr/bin/make -f
+
+#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+%:
+ dh $@ --with autoreconf
+
+# Print test results in case of a failure
+override_dh_auto_test:
+ dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..f48ad27
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,3 @@
+version=4
+opts="mode=git, dversionmangle=s/\+ds//" https://git.osmocom.org/osmo-fl2k refs/tags/([\d\.]+) debian uupdate
+
diff --git a/include/osmo-fl2k.h b/include/osmo-fl2k.h
index 6a1b3ee..aefbb8c 100644
--- a/include/osmo-fl2k.h
+++ b/include/osmo-fl2k.h
@@ -37,6 +37,7 @@ enum fl2k_error {
FL2K_ERROR_NO_DEVICE = -2,
FL2K_ERROR_NOT_FOUND = -5,
FL2K_ERROR_BUSY = -6,
+ FL2K_ERROR_TIMEOUT = -7,
FL2K_ERROR_NO_MEM = -11,
};
@@ -124,6 +125,40 @@ FL2K_API int fl2k_start_tx(fl2k_dev_t *dev, fl2k_tx_cb_t cb,
*/
FL2K_API int fl2k_stop_tx(fl2k_dev_t *dev);
+/*!
+ * Read 4 bytes via the FL2K I2C bus
+ *
+ * \param dev the device handle given by fl2k_open()
+ * \param i2c_addr address of the I2C device
+ * \param reg_addr start address of the 4 bytes to be read
+ * \param data pointer to byte array of size 4
+ * \return 0 on success
+ * \note A read operation will look like this on the bus:
+ * START, I2C_ADDR(W), REG_ADDR, REP_START, I2C_ADDR(R), DATA[0], STOP
+ * START, I2C_ADDR(W), REG_ADDR+1, REP_START, I2C_ADDR(R), DATA[1], STOP
+ * START, I2C_ADDR(W), REG_ADDR+2, REP_START, I2C_ADDR(R), DATA[2], STOP
+ * START, I2C_ADDR(W), REG_ADDR+3, REP_START, I2C_ADDR(R), DATA[3], STOP
+ */
+FL2K_API int fl2k_i2c_read(fl2k_dev_t *dev, uint8_t i2c_addr,
+ uint8_t reg_addr, uint8_t *data);
+
+/*!
+ * Write 4 bytes via the FL2K I2C bus
+ *
+ * \param dev the device handle given by fl2k_open()
+ * \param i2c_addr address of the I2C device
+ * \param reg_addr start address of the 4 bytes to be written
+ * \param data pointer to byte array of size 4
+ * \return 0 on success
+ * \note A write operation will look like this on the bus:
+ * START, I2C_ADDR(W), REG_ADDR, DATA[0], STOP
+ * START, I2C_ADDR(W), REG_ADDR+1, DATA[1], STOP
+ * START, I2C_ADDR(W), REG_ADDR+2, DATA[2], STOP
+ * START, I2C_ADDR(W), REG_ADDR+3, DATA[3], STOP
+ */
+FL2K_API int fl2k_i2c_write(fl2k_dev_t *dev, uint8_t i2c_addr,
+ uint8_t reg_addr, uint8_t *data);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1d788de..f63780a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -15,6 +15,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+include(GNUInstallDirs)
+
MACRO(LIBFL2K_APPEND_SRCS)
LIST(APPEND libosmo-fl2k_srcs ${ARGV})
ENDMACRO(LIBFL2K_APPEND_SRCS)
@@ -124,7 +126,7 @@ endif()
# Install built library files & utilities
########################################################################
install(TARGETS ${INSTALL_TARGETS}
- LIBRARY DESTINATION ${LIB_INSTALL_DIR} # .so/.dylib file
- ARCHIVE DESTINATION ${LIB_INSTALL_DIR} # .lib file
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # .so/.dylib file
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # .lib file
RUNTIME DESTINATION bin # .dll file
)
diff --git a/src/fl2k_file.c b/src/fl2k_file.c
index 0da1cbc..2cea6ff 100644
--- a/src/fl2k_file.c
+++ b/src/fl2k_file.c
@@ -28,11 +28,13 @@
#ifndef _WIN32
#include <unistd.h>
+#define sleep_ms(ms) usleep(ms*1000)
#else
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include "getopt/getopt.h"
+#define sleep_ms(ms) Sleep(ms)
#endif
#include "osmo-fl2k.h"
@@ -156,10 +158,17 @@ int main(int argc, char **argv)
if (dev_index < 0)
exit(1);
- file = fopen(filename, "rb");
- if (!file) {
- fprintf(stderr, "Failed to open %s\n", filename);
- goto out;
+ if (strcmp(filename, "-") == 0) { /* Read samples from stdin */
+ file = stdin;
+#ifdef _WIN32
+ _setmode(_fileno(stdin), _O_BINARY);
+#endif
+ } else {
+ file = fopen(filename, "rb");
+ if (!file) {
+ fprintf(stderr, "Failed to open %s\n", filename);
+ return -ENOENT;
+ }
}
txbuf = malloc(FL2K_BUF_LEN * (interleaved ? 2 : 1));
@@ -195,13 +204,8 @@ int main(int argc, char **argv)
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
#endif
- while (!do_exit) {
-#ifndef _WIN32
- usleep(500000);
-#else
- Sleep(0.5);
-#endif
- }
+ while (!do_exit)
+ sleep_ms(500);
fl2k_close(dev);
diff --git a/src/fl2k_tcp.c b/src/fl2k_tcp.c
index ad0aa18..bd01758 100644
--- a/src/fl2k_tcp.c
+++ b/src/fl2k_tcp.c
@@ -36,9 +36,12 @@
#include <netinet/in.h>
#include <netinet/tcp.h> /* for TCP_NODELAY */
#include <fcntl.h>
+#define sleep_ms(ms) usleep(ms*1000)
#else
+#include <windows.h>
#include <winsock2.h>
#include "getopt/getopt.h"
+#define sleep_ms(ms) Sleep(ms)
#endif
#include "osmo-fl2k.h"
@@ -217,11 +220,7 @@ int main(int argc, char **argv)
fprintf(stderr, "Connecting to %s:%d...\n", addr, port);
while (connect(sock, (struct sockaddr *)&remote, sizeof(remote)) != 0) {
-#ifndef _WIN32
- usleep(500000);
-#else
- Sleep(0.5);
-#endif
+ sleep_ms(500);
if (do_exit)
goto out;
}
@@ -230,13 +229,8 @@ int main(int argc, char **argv)
fprintf(stderr, "Connected\n");
connected = 1;
- while (!do_exit) {
-#ifndef _WIN32
- usleep(500000);
-#else
- Sleep(0.5);
-#endif
- }
+ while (!do_exit)
+ sleep_ms(500);
out:
free(txbuf);
diff --git a/src/fl2k_test.c b/src/fl2k_test.c
index c9a6048..6d82922 100644
--- a/src/fl2k_test.c
+++ b/src/fl2k_test.c
@@ -41,9 +41,11 @@
#ifndef _WIN32
#include <unistd.h>
+#define sleep_ms(ms) usleep(ms*1000)
#else
#include <windows.h>
#include "getopt/getopt.h"
+#define sleep_ms(ms) Sleep(ms)
#endif
#include "osmo-fl2k.h"
@@ -290,17 +292,11 @@ int main(int argc, char **argv)
fprintf(stderr, "Reporting PPM error measurement every %u seconds...\n", ppm_duration);
fprintf(stderr, "Press ^C after a few minutes.\n");
- while (!do_exit) {
-#ifndef _WIN32
- usleep(500000);
-#else
- Sleep(0.5);
-#endif
- }
+ while (!do_exit)
+ sleep_ms(500);
- if (do_exit) {
+ if (do_exit)
fprintf(stderr, "\nUser cancel, exiting...\n");
- }
exit:
fl2k_close(dev);
diff --git a/src/libosmo-fl2k.c b/src/libosmo-fl2k.c
index 09380b6..c5959c3 100644
--- a/src/libosmo-fl2k.c
+++ b/src/libosmo-fl2k.c
@@ -25,15 +25,18 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <math.h>
+#include <libusb.h>
+#include <pthread.h>
#ifndef _WIN32
#include <unistd.h>
+#define sleep_ms(ms) usleep(ms*1000)
+#else
+#include <windows.h>
+#define sleep_ms(ms) Sleep(ms)
#endif
-#include <math.h>
-#include <libusb.h>
-#include <pthread.h>
-
/*
* All libusb callback functions should be marked with the LIBUSB_CALL macro
* to ensure that they are compiled with the same calling convention as libusb.
@@ -381,7 +384,11 @@ int fl2k_open(fl2k_dev_t **out_dev, uint32_t index)
return -1;
}
+#if LIBUSB_API_VERSION >= 0x01000106
+ libusb_set_option(dev->ctx, LIBUSB_OPTION_LOG_LEVEL, 3);
+#else
libusb_set_debug(dev->ctx, 3);
+#endif
dev->dev_lost = 1;
@@ -472,13 +479,8 @@ int fl2k_close(fl2k_dev_t *dev)
if(!dev->dev_lost) {
/* block until all async operations have been completed (if any) */
- while (FL2K_INACTIVE != dev->async_status) {
-#ifdef _WIN32
- Sleep(1);
-#else
- usleep(1000);
-#endif
- }
+ while (FL2K_INACTIVE != dev->async_status)
+ sleep_ms(100);
fl2k_deinit_device(dev);
}
@@ -589,11 +591,26 @@ static int fl2k_alloc_submit_transfers(fl2k_dev_t *dev)
for (i = 0; i < dev->xfer_buf_num; ++i) {
dev->xfer_buf[i] = libusb_dev_mem_alloc(dev->devh, dev->xfer_buf_len);
- if (!dev->xfer_buf[i]) {
+ if (dev->xfer_buf[i]) {
+ /* Check if Kernel usbfs mmap() bug is present: if the
+ * mapping is correct, the buffers point to memory that
+ * was memset to 0 by the Kernel, otherwise, they point
+ * to random memory. We check if the buffers are zeroed
+ * and otherwise fall back to buffers in userspace.
+ */
+ if (dev->xfer_buf[i][0] || memcmp(dev->xfer_buf[i],
+ dev->xfer_buf[i] + 1,
+ dev->xfer_buf_len - 1)) {
+ fprintf(stderr, "Detected Kernel usbfs mmap() "
+ "bug, falling back to buffers "
+ "in userspace\n");
+ dev->use_zerocopy = 0;
+ break;
+ }
+ } else {
fprintf(stderr, "Failed to allocate zero-copy "
"buffer for transfer %d\nFalling "
"back to buffers in userspace\n", i);
-
dev->use_zerocopy = 0;
break;
}
@@ -1020,3 +1037,104 @@ int fl2k_stop_tx(fl2k_dev_t *dev)
return FL2K_ERROR_BUSY;
}
+
+int fl2k_i2c_read(fl2k_dev_t *dev, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *data)
+{
+ int i, r, timeout = 1;
+ uint32_t reg;
+
+ if (!dev)
+ return FL2K_ERROR_INVALID_PARAM;
+
+ r = fl2k_read_reg(dev, 0x8020, &reg);
+ if (r < 0)
+ return r;
+
+ /* apply mask, clearing bit 30 disables periodic repetition of read */
+ reg &= 0x3ffc0000;
+
+ /* set I2C register and address, select I2C read (bit 7) */
+ reg |= (1 << 28) | (reg_addr << 8) | (1 << 7) | (i2c_addr & 0x7f);
+
+ r = fl2k_write_reg(dev, 0x8020, reg);
+ if (r < 0)
+ return r;
+
+ for (i = 0; i < 10; i++) {
+ sleep_ms(10);
+
+ r = fl2k_read_reg(dev, 0x8020, &reg);
+ if (r < 0)
+ return r;
+
+ /* check if operation completed */
+ if (reg & (1 << 31)) {
+ timeout = 0;
+ break;
+ }
+ }
+
+ if (timeout)
+ return FL2K_ERROR_TIMEOUT;
+
+ /* check if slave responded and all data was read */
+ if (reg & (0x0f << 24))
+ return FL2K_ERROR_NOT_FOUND;
+
+ /* read data from register 0x8024 */
+ return libusb_control_transfer(dev->devh, CTRL_IN, 0x40,
+ 0, 0x8024, data, 4, CTRL_TIMEOUT);
+}
+
+int fl2k_i2c_write(fl2k_dev_t *dev, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *data)
+{
+ int i, r, timeout = 1;
+ uint32_t reg;
+
+ if (!dev)
+ return FL2K_ERROR_INVALID_PARAM;
+
+ /* write data to register 0x8028 */
+ r = libusb_control_transfer(dev->devh, CTRL_OUT, 0x41,
+ 0, 0x8028, data, 4, CTRL_TIMEOUT);
+
+ if (r < 0)
+ return r;
+
+ r = fl2k_read_reg(dev, 0x8020, &reg);
+ if (r < 0)
+ return r;
+
+ /* apply mask, clearing bit 30 disables periodic repetition of read */
+ reg &= 0x3ffc0000;
+
+ /* set I2C register and address */
+ reg |= (1 << 28) | (reg_addr << 8) | (i2c_addr & 0x7f);
+
+ r = fl2k_write_reg(dev, 0x8020, reg);
+ if (r < 0)
+ return r;
+
+ for (i = 0; i < 10; i++) {
+ sleep_ms(10);
+
+ r = fl2k_read_reg(dev, 0x8020, &reg);
+ if (r < 0)
+ return r;
+
+ /* check if operation completed */
+ if (reg & (1 << 31)) {
+ timeout = 0;
+ break;
+ }
+ }
+
+ if (timeout)
+ return FL2K_ERROR_TIMEOUT;
+
+ /* check if slave responded and all data was written */
+ if (reg & (0x0f << 24))
+ return FL2K_ERROR_NOT_FOUND;
+
+ return FL2K_SUCCESS;
+}