[PATCH] rtl-sdr/lib: normalize error return values

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/osmocom-sdr@lists.osmocom.org/.

Karl Semich 0xloem at gmail.com
Sun Sep 23 03:45:35 UTC 2018


All library functions updated to return error codes with consistent
value and meaning, selected from nine comprehensive conditions inferred
from context.

Bitwise combinations of return values changed to conditionals, to
preserve meaning.
---
 include/rtl-sdr.h      |  20 ++-
 include/tuner_fc2580.h |  23 +--
 src/librtlsdr.c        | 374 +++++++++++++++++++++++++----------------
 src/tuner_e4k.c        |  65 ++++----
 src/tuner_fc0012.c     |  24 ++-
 src/tuner_fc0013.c     |  47 ++++--
 src/tuner_fc2580.c     | 445 ++++++++++++++++++++++++++++++-------------------
 src/tuner_r82xx.c      |  29 ++--
 8 files changed, 626 insertions(+), 401 deletions(-)

diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h
index 3ed13ae..52d67e6 100644
--- a/include/rtl-sdr.h
+++ b/include/rtl-sdr.h
@@ -24,6 +24,7 @@
 extern "C" {
 #endif
 
+#include <errno.h>
 #include <stdint.h>
 #include <rtl-sdr_export.h>
 
@@ -34,6 +35,23 @@ RTLSDR_API uint32_t rtlsdr_get_device_count(void);
 RTLSDR_API const char* rtlsdr_get_device_name(uint32_t index);
 
 /*!
+ * Error codes. Most functions return 0 on success or one of these
+ * codes on failure.
+ */
+enum rtlsdr_error {
+  RTLSDR_SUCCESS        =  0, /* Success (no error) */
+  RTLSDR_ERROR_NULL     = -1, /* Passed handle is null pointer */
+  RTLSDR_ERROR_INVALID  = -EINVAL, /* Invalid argument provided */
+  RTLSDR_ERROR_NOTFOUND = -3, /* Device was not found */
+  RTLSDR_ERROR_SHORT    = -4, /* Less data transferred than requested */
+  RTLSDR_ERROR_NOOP     = -5, /* No action to take */
+  RTLSDR_ERROR_DEVTYPE  = -6, /* Function not available for device */
+  RTLSDR_ERROR_STATE    = -7, /* Device in wrong state for call */
+  RTLSDR_ERROR_NOMEM    = -8, /* Memory allocation failed */
+  RTLSDR_ERROR_USB      = -9 /* Error returned by libusb */
+};
+
+/*!
  * Get USB device strings.
  *
  * NOTE: The string arguments must provide space for up to 256 bytes.
@@ -261,7 +279,7 @@ RTLSDR_API int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int manual);
  * 		    225001 - 300000 Hz
  * 		    900001 - 3200000 Hz
  * 		    sample loss is to be expected for rates > 2400000
- * \return 0 on success, -EINVAL on invalid rate
+ * \return 0 on success, RTLSDR_ERROR_INVALID on invalid rate
  */
 RTLSDR_API int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t rate);
 
diff --git a/include/tuner_fc2580.h b/include/tuner_fc2580.h
index 9ebd935..72e9393 100644
--- a/include/tuner_fc2580.h
+++ b/include/tuner_fc2580.h
@@ -1,6 +1,8 @@
 #ifndef __TUNER_FC2580_H
 #define __TUNER_FC2580_H
 
+#include "rtl-sdr.h"
+
 #define	BORDER_FREQ	2600000	//2.6GHz : The border frequency which determines whether Low VCO or High VCO is used
 #define USE_EXT_CLK	0	//0 : Use internal XTAL Oscillator / 1 : Use External Clock input
 #define OFS_RSSI 57
@@ -16,21 +18,10 @@ typedef enum {
 	FC2580_NO_BAND
 } fc2580_band_type;
 
-typedef enum {
-	FC2580_FCI_FAIL,
-	FC2580_FCI_SUCCESS
-} fc2580_fci_result_type;
-
-enum FUNCTION_STATUS
-{
-	FUNCTION_SUCCESS,
-	FUNCTION_ERROR,
-};
-
 extern void fc2580_wait_msec(void *pTuner, int a);
 
-fc2580_fci_result_type fc2580_i2c_write(void *pTuner, unsigned char reg, unsigned char val);
-fc2580_fci_result_type fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned char *read_data);
+enum rtlsdr_error fc2580_i2c_write(void *pTuner, unsigned char reg, unsigned char val);
+enum rtlsdr_error fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned char *read_data);
 
 /*==============================================================================
        fc2580 initial setting
@@ -47,7 +38,7 @@ fc2580_fci_result_type fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned
 	2 : Voltage Control Mode
 
 ==============================================================================*/
-fc2580_fci_result_type fc2580_set_init(void *pTuner, int ifagc_mode, unsigned int freq_xtal );
+enum rtlsdr_error fc2580_set_init(void *pTuner, int ifagc_mode, unsigned int freq_xtal );
 
 /*==============================================================================
        fc2580 frequency setting
@@ -63,7 +54,7 @@ fc2580_fci_result_type fc2580_set_init(void *pTuner, int ifagc_mode, unsigned in
 	ex) 2.6GHz = 2600000
 
 ==============================================================================*/
-fc2580_fci_result_type fc2580_set_freq(void *pTuner, unsigned int f_lo, unsigned int freq_xtal );
+enum rtlsdr_error fc2580_set_freq(void *pTuner, unsigned int f_lo, unsigned int freq_xtal );
 
 
 /*==============================================================================
@@ -83,7 +74,7 @@ fc2580_fci_result_type fc2580_set_freq(void *pTuner, unsigned int f_lo, unsigned
 
 
 ==============================================================================*/
-fc2580_fci_result_type fc2580_set_filter( void *pTuner, unsigned char filter_bw, unsigned int freq_xtal );
+enum rtlsdr_error fc2580_set_filter( void *pTuner, unsigned char filter_bw, unsigned int freq_xtal );
 
 // The following context is FC2580 tuner API source code
 // Definitions
diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index 433ed5b..b83c54d 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -125,6 +125,7 @@ struct rtlsdr_dev {
 	int dev_lost;
 	int driver_active;
 	unsigned int xfer_errors;
+	int libusb_err;
 };
 
 void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val);
@@ -164,16 +165,16 @@ int e4000_set_gain(void *dev, int gain) {
 #if 0
 	int enhgain = (gain - 420);
 #endif
-	if(e4k_set_lna_gain(&devt->e4k_s, min(300, gain - mixgain * 10)) == -EINVAL)
-		return -1;
-	if(e4k_mixer_gain_set(&devt->e4k_s, mixgain) == -EINVAL)
-		return -1;
+	if(e4k_set_lna_gain(&devt->e4k_s, min(300, gain - mixgain * 10)) == RTLSDR_ERROR_INVALID)
+		return RTLSDR_ERROR_INVALID;
+	if(e4k_mixer_gain_set(&devt->e4k_s, mixgain) == RTLSDR_ERROR_INVALID)
+		return RTLSDR_ERROR_INVALID;
 #if 0 /* enhanced mixer gain seems to have no effect */
 	if(enhgain >= 0)
-		if(e4k_set_enh_gain(&devt->e4k_s, enhgain) == -EINVAL)
-			return -1;
+		if(e4k_set_enh_gain(&devt->e4k_s, enhgain) == RTLSDR_ERROR_INVALID)
+			return RTLSDR_ERROR_INVALID;
 #endif
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 int e4000_set_if_gain(void *dev, int stage, int gain) {
 	rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
@@ -416,7 +417,12 @@ int rtlsdr_read_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t *
 	if (r < 0)
 		fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r);
 #endif
-	return r;
+	if (r < 0) {
+		dev->libusb_err = r;
+		return RTLSDR_ERROR_USB;
+	} else {
+		return r;
+	}
 }
 
 int rtlsdr_write_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t *array, uint8_t len)
@@ -429,7 +435,12 @@ int rtlsdr_write_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t
 	if (r < 0)
 		fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r);
 #endif
-	return r;
+	if (r < 0) {
+		dev->libusb_err = r;
+		return RTLSDR_ERROR_USB;
+	} else {
+		return r;
+	}
 }
 
 int rtlsdr_i2c_write_reg(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t reg, uint8_t val)
@@ -458,7 +469,7 @@ int rtlsdr_i2c_write(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int l
 	uint16_t addr = i2c_addr;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	return rtlsdr_write_array(dev, IICB, addr, buffer, len);
 }
@@ -468,12 +479,12 @@ int rtlsdr_i2c_read(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int le
 	uint16_t addr = i2c_addr;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	return rtlsdr_read_array(dev, IICB, addr, buffer, len);
 }
 
-uint16_t rtlsdr_read_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t len)
+int32_t rtlsdr_read_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t len)
 {
 	int r;
 	unsigned char data[2];
@@ -482,8 +493,11 @@ uint16_t rtlsdr_read_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_
 
 	r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT);
 
-	if (r < 0)
+	if (r < 0) {
+		dev->libusb_err = r;
 		fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r);
+		return RTLSDR_ERROR_USB;
+	}
 
 	reg = (data[1] << 8) | data[0];
 
@@ -506,13 +520,16 @@ int rtlsdr_write_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint16_t v
 
 	r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, data, len, CTRL_TIMEOUT);
 
-	if (r < 0)
+	if (r < 0) {
 		fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r);
-
-	return r;
+		dev->libusb_err = r;
+		return RTLSDR_ERROR_USB;
+	} else {
+		return RTLSDR_SUCCESS;
+	}
 }
 
-uint16_t rtlsdr_demod_read_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint8_t len)
+int32_t rtlsdr_demod_read_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint8_t len)
 {
 	int r;
 	unsigned char data[2];
@@ -523,8 +540,11 @@ uint16_t rtlsdr_demod_read_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, u
 
 	r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT);
 
-	if (r < 0)
+	if (r < 0) {
 		fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r);
+		dev->libusb_err = r;
+		return RTLSDR_ERROR_USB;
+	}
 
 	reg = (data[1] << 8) | data[0];
 
@@ -547,12 +567,15 @@ int rtlsdr_demod_write_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint1
 
 	r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, data, len, CTRL_TIMEOUT);
 
-	if (r < 0)
+	if (r < 0) {
 		fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r);
+		dev->libusb_err = r;
+		return RTLSDR_ERROR_USB;
+	}
 
 	rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1);
 
-	return (r == len) ? 0 : -1;
+	return (r == len) ? RTLSDR_SUCCESS : RTLSDR_ERROR_SHORT;
 }
 
 void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val)
@@ -590,7 +613,7 @@ int rtlsdr_set_fir(rtlsdr_dev_t *dev)
 	for (i = 0; i < 8; ++i) {
 		const int val = dev->fir[i];
 		if (val < -128 || val > 127) {
-			return -1;
+			return RTLSDR_ERROR_INVALID;
 		}
 		fir[i] = val;
 	}
@@ -599,7 +622,7 @@ int rtlsdr_set_fir(rtlsdr_dev_t *dev)
 		const int val0 = dev->fir[8+i];
 		const int val1 = dev->fir[8+i+1];
 		if (val0 < -2048 || val0 > 2047 || val1 < -2048 || val1 > 2047) {
-			return -1;
+			return RTLSDR_ERROR_INVALID;
 		}
 		fir[8+i*3/2] = val0 >> 4;
 		fir[8+i*3/2+1] = (val0 << 4) | ((val1 >> 8) & 0x0f);
@@ -607,11 +630,10 @@ int rtlsdr_set_fir(rtlsdr_dev_t *dev)
 	}
 
 	for (i = 0; i < (int)sizeof(fir); i++) {
-		if (rtlsdr_demod_write_reg(dev, 1, 0x1c + i, fir[i], 1))
-				return -1;
+		return rtlsdr_demod_write_reg(dev, 1, 0x1c + i, fir[i], 1);
 	}
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 void rtlsdr_init_baseband(rtlsdr_dev_t *dev)
@@ -673,7 +695,7 @@ int rtlsdr_deinit_baseband(rtlsdr_dev_t *dev)
 	int r = 0;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (dev->tuner && dev->tuner->exit) {
 		rtlsdr_set_i2c_repeater(dev, 1);
@@ -693,57 +715,67 @@ static int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq)
 	int32_t if_freq;
 	uint8_t tmp;
 	int r;
+	int rfin;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	/* read corrected clock value */
-	if (rtlsdr_get_xtal_freq(dev, &rtl_xtal, NULL))
-		return -2;
+	r = rtlsdr_get_xtal_freq(dev, &rtl_xtal, NULL);
+	if (r < 0)
+		return r;
 
 	if_freq = ((freq * TWO_POW(22)) / rtl_xtal) * (-1);
 
 	tmp = (if_freq >> 16) & 0x3f;
-	r = rtlsdr_demod_write_reg(dev, 1, 0x19, tmp, 1);
+	rfin = rtlsdr_demod_write_reg(dev, 1, 0x19, tmp, 1);
 	tmp = (if_freq >> 8) & 0xff;
-	r |= rtlsdr_demod_write_reg(dev, 1, 0x1a, tmp, 1);
+	r = rtlsdr_demod_write_reg(dev, 1, 0x1a, tmp, 1);
+	if (r) rfin = r;
 	tmp = if_freq & 0xff;
-	r |= rtlsdr_demod_write_reg(dev, 1, 0x1b, tmp, 1);
+	r = rtlsdr_demod_write_reg(dev, 1, 0x1b, tmp, 1);
+	if (r) rfin = r;
 
-	return r;
+	return rfin;
 }
 
 int rtlsdr_set_sample_freq_correction(rtlsdr_dev_t *dev, int ppm)
 {
-	int r = 0;
+	int r;
+	int rfin = 0;
 	uint8_t tmp;
 	int16_t offs = ppm * (-1) * TWO_POW(24) / 1000000;
 
 	tmp = offs & 0xff;
-	r |= rtlsdr_demod_write_reg(dev, 1, 0x3f, tmp, 1);
+	r = rtlsdr_demod_write_reg(dev, 1, 0x3f, tmp, 1);
+	if (r) rfin = r;
 	tmp = (offs >> 8) & 0x3f;
-	r |= rtlsdr_demod_write_reg(dev, 1, 0x3e, tmp, 1);
+	r = rtlsdr_demod_write_reg(dev, 1, 0x3e, tmp, 1);
+	if (r) rfin = r;
 
-	return r;
+	return rfin;
 }
 
 int rtlsdr_set_xtal_freq(rtlsdr_dev_t *dev, uint32_t rtl_freq, uint32_t tuner_freq)
 {
-	int r = 0;
+	int rfin = 0;
+	int r;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (rtl_freq > 0 &&
 		(rtl_freq < MIN_RTL_XTAL_FREQ || rtl_freq > MAX_RTL_XTAL_FREQ))
-		return -2;
+		return RTLSDR_ERROR_INVALID;
 
 	if (rtl_freq > 0 && dev->rtl_xtal != rtl_freq) {
 		dev->rtl_xtal = rtl_freq;
 
 		/* update xtal-dependent settings */
-		if (dev->rate)
+		if (dev->rate) {
 			r = rtlsdr_set_sample_rate(dev, dev->rate);
+			if (r) rfin = r;
+		}
 	}
 
 	if (dev->tun_xtal != tuner_freq) {
@@ -753,22 +785,26 @@ int rtlsdr_set_xtal_freq(rtlsdr_dev_t *dev, uint32_t rtl_freq, uint32_t tuner_fr
 			dev->tun_xtal = tuner_freq;
 
 		/* read corrected clock value into e4k and r82xx structure */
-		if (rtlsdr_get_xtal_freq(dev, NULL, &dev->e4k_s.vco.fosc) ||
-		    rtlsdr_get_xtal_freq(dev, NULL, &dev->r82xx_c.xtal))
-			return -3;
+		r = rtlsdr_get_xtal_freq(dev, NULL, &dev->e4k_s.vco.fosc);
+		if (r == RTLSDR_SUCCESS)
+			r = rtlsdr_get_xtal_freq(dev, NULL, &dev->r82xx_c.xtal);
+		if (r != RTLSDR_SUCCESS)
+			return r;
 
 		/* update xtal-dependent settings */
-		if (dev->freq)
+		if (dev->freq) {
 			r = rtlsdr_set_center_freq(dev, dev->freq);
+			if (r) rfin = r;
+		}
 	}
 
-	return r;
+	return rfin;
 }
 
 int rtlsdr_get_xtal_freq(rtlsdr_dev_t *dev, uint32_t *rtl_freq, uint32_t *tuner_freq)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	#define APPLY_PPM_CORR(val,ppm) (((val) * (1.0 + (ppm) / 1e6)))
 
@@ -778,7 +814,7 @@ int rtlsdr_get_xtal_freq(rtlsdr_dev_t *dev, uint32_t *rtl_freq, uint32_t *tuner_
 	if (tuner_freq)
 		*tuner_freq = (uint32_t) APPLY_PPM_CORR(dev->tun_xtal, dev->corr);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 int rtlsdr_get_usb_strings(rtlsdr_dev_t *dev, char *manufact, char *product,
@@ -790,13 +826,15 @@ int rtlsdr_get_usb_strings(rtlsdr_dev_t *dev, char *manufact, char *product,
 	int r = 0;
 
 	if (!dev || !dev->devh)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	device = libusb_get_device(dev->devh);
 
 	r = libusb_get_device_descriptor(device, &dd);
-	if (r < 0)
-		return -1;
+	if (r < 0) {
+		dev->libusb_err = r;
+		return RTLSDR_ERROR_USB;
+	}
 
 	if (manufact) {
 		memset(manufact, 0, buf_max);
@@ -819,7 +857,7 @@ int rtlsdr_get_usb_strings(rtlsdr_dev_t *dev, char *manufact, char *product,
 						   buf_max);
 	}
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 int rtlsdr_write_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16_t len)
@@ -829,10 +867,10 @@ int rtlsdr_write_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16
 	uint8_t cmd[2];
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if ((len + offset) > 256)
-		return -2;
+		return RTLSDR_ERROR_INVALID;
 
 	for (i = 0; i < len; i++) {
 		cmd[0] = i + offset;
@@ -846,7 +884,7 @@ int rtlsdr_write_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16
 		cmd[1] = data[i];
 		r = rtlsdr_write_array(dev, IICB, EEPROM_ADDR, cmd, 2);
 		if (r != sizeof(cmd))
-			return -3;
+			return r < 0 ? r : RTLSDR_ERROR_SHORT;
 
 		/* for some EEPROMs (e.g. ATC 240LC02) we need a delay
 		 * between write operations, otherwise they will fail */
@@ -857,7 +895,7 @@ int rtlsdr_write_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16
 #endif
 	}
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16_t len)
@@ -866,20 +904,20 @@ int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16_
 	int i;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if ((len + offset) > 256)
-		return -2;
+		return RTLSDR_ERROR_INVALID;
 
 	r = rtlsdr_write_array(dev, IICB, EEPROM_ADDR, &offset, 1);
 	if (r < 0)
-		return -3;
+		return r;
 
 	for (i = 0; i < len; i++) {
 		r = rtlsdr_read_array(dev, IICB, EEPROM_ADDR, data + i, 1);
 
 		if (r < 0)
-			return -3;
+			return r;
 	}
 
 	return r;
@@ -887,10 +925,10 @@ int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16_
 
 int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq)
 {
-	int r = -1;
+	int r;
 
 	if (!dev || !dev->tuner)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (dev->direct_sampling) {
 		r = rtlsdr_set_if_freq(dev, freq);
@@ -898,6 +936,8 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq)
 		rtlsdr_set_i2c_repeater(dev, 1);
 		r = dev->tuner->set_freq(dev, freq - dev->offs_freq);
 		rtlsdr_set_i2c_repeater(dev, 0);
+	} else {
+		r = RTLSDR_ERROR_DEVTYPE;
 	}
 
 	if (!r)
@@ -918,27 +958,33 @@ uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev)
 
 int rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm)
 {
-	int r = 0;
+	int r;
+	int rfin;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (dev->corr == ppm)
-		return -2;
+		return RTLSDR_ERROR_NOOP;
 
 	dev->corr = ppm;
 
-	r |= rtlsdr_set_sample_freq_correction(dev, ppm);
+	rfin = rtlsdr_set_sample_freq_correction(dev, ppm);
 
 	/* read corrected clock value into e4k and r82xx structure */
-	if (rtlsdr_get_xtal_freq(dev, NULL, &dev->e4k_s.vco.fosc) ||
-	    rtlsdr_get_xtal_freq(dev, NULL, &dev->r82xx_c.xtal))
-		return -3;
+	r = rtlsdr_get_xtal_freq(dev, NULL, &dev->e4k_s.vco.fosc);
+	if (r == RTLSDR_SUCCESS)
+		r = rtlsdr_get_xtal_freq(dev, NULL, &dev->r82xx_c.xtal);
+	if (r != RTLSDR_SUCCESS)
+		return r;
 
-	if (dev->freq) /* retune to apply new correction value */
-		r |= rtlsdr_set_center_freq(dev, dev->freq);
+	if (dev->freq) {
+		/* retune to apply new correction value */
+		r = rtlsdr_set_center_freq(dev, dev->freq);
+		if (r) rfin = r;
+	}
 
-	return r;
+	return rfin;
 }
 
 int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev)
@@ -977,7 +1023,7 @@ int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains)
 	int len = 0;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	switch (dev->tuner_type) {
 	case RTLSDR_TUNER_E4000:
@@ -1016,7 +1062,7 @@ int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, uint32_t bw)
 	int r = 0;
 
 	if (!dev || !dev->tuner)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (dev->tuner->set_bw) {
 		rtlsdr_set_i2c_repeater(dev, 1);
@@ -1034,7 +1080,7 @@ int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain)
 	int r = 0;
 
 	if (!dev || !dev->tuner)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (dev->tuner->set_gain) {
 		rtlsdr_set_i2c_repeater(dev, 1);
@@ -1063,7 +1109,7 @@ int rtlsdr_set_tuner_if_gain(rtlsdr_dev_t *dev, int stage, int gain)
 	int r = 0;
 
 	if (!dev || !dev->tuner)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (dev->tuner->set_if_gain) {
 		rtlsdr_set_i2c_repeater(dev, 1);
@@ -1079,7 +1125,7 @@ int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode)
 	int r = 0;
 
 	if (!dev || !dev->tuner)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (dev->tuner->set_gain_mode) {
 		rtlsdr_set_i2c_repeater(dev, 1);
@@ -1092,19 +1138,20 @@ int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode)
 
 int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
 {
-	int r = 0;
+	int r;
+	int rfin = 0;
 	uint16_t tmp;
 	uint32_t rsamp_ratio, real_rsamp_ratio;
 	double real_rate;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	/* check if the rate is supported by the resampler */
 	if ((samp_rate <= 225000) || (samp_rate > 3200000) ||
 	   ((samp_rate > 300000) && (samp_rate <= 900000))) {
 		fprintf(stderr, "Invalid sample rate: %u Hz\n", samp_rate);
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 	}
 
 	rsamp_ratio = (dev->rtl_xtal * TWO_POW(22)) / samp_rate;
@@ -1125,21 +1172,26 @@ int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
 	}
 
 	tmp = (rsamp_ratio >> 16);
-	r |= rtlsdr_demod_write_reg(dev, 1, 0x9f, tmp, 2);
+	r = rtlsdr_demod_write_reg(dev, 1, 0x9f, tmp, 2);
+	if (r) rfin = r;
 	tmp = rsamp_ratio & 0xffff;
-	r |= rtlsdr_demod_write_reg(dev, 1, 0xa1, tmp, 2);
+	r = rtlsdr_demod_write_reg(dev, 1, 0xa1, tmp, 2);
+	if (r) rfin = r;
 
-	r |= rtlsdr_set_sample_freq_correction(dev, dev->corr);
+	r = rtlsdr_set_sample_freq_correction(dev, dev->corr);
+	if (r) rfin = r;
 
 	/* reset demod (bit 3, soft_rst) */
-	r |= rtlsdr_demod_write_reg(dev, 1, 0x01, 0x14, 1);
-	r |= rtlsdr_demod_write_reg(dev, 1, 0x01, 0x10, 1);
+	r = rtlsdr_demod_write_reg(dev, 1, 0x01, 0x14, 1);
+	if (r) rfin = r;
+	r = rtlsdr_demod_write_reg(dev, 1, 0x01, 0x10, 1);
+	if (r) rfin = r;
 
 	/* recalculate offset frequency if offset tuning is enabled */
 	if (dev->offs_freq)
 		rtlsdr_set_offset_tuning(dev, 1);
 
-	return r;
+	return rfin;
 }
 
 uint32_t rtlsdr_get_sample_rate(rtlsdr_dev_t *dev)
@@ -1153,7 +1205,7 @@ uint32_t rtlsdr_get_sample_rate(rtlsdr_dev_t *dev)
 int rtlsdr_set_testmode(rtlsdr_dev_t *dev, int on)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	return rtlsdr_demod_write_reg(dev, 0, 0x19, on ? 0x03 : 0x05, 1);
 }
@@ -1161,17 +1213,18 @@ int rtlsdr_set_testmode(rtlsdr_dev_t *dev, int on)
 int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	return rtlsdr_demod_write_reg(dev, 0, 0x19, on ? 0x25 : 0x05, 1);
 }
 
 int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on)
 {
-	int r = 0;
+	int r;
+	int rfin = 0;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (on) {
 		if (dev->tuner && dev->tuner->exit) {
@@ -1181,80 +1234,93 @@ int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on)
 		}
 
 		/* disable Zero-IF mode */
-		r |= rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1a, 1);
+		r = rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1a, 1);
+		if (r) rfin = r;
 
 		/* disable spectrum inversion */
-		r |= rtlsdr_demod_write_reg(dev, 1, 0x15, 0x00, 1);
+		r = rtlsdr_demod_write_reg(dev, 1, 0x15, 0x00, 1);
+		if (r) rfin = r;
 
 		/* only enable In-phase ADC input */
-		r |= rtlsdr_demod_write_reg(dev, 0, 0x08, 0x4d, 1);
+		r = rtlsdr_demod_write_reg(dev, 0, 0x08, 0x4d, 1);
+		if (r) rfin = r;
 
 		/* swap I and Q ADC, this allows to select between two inputs */
-		r |= rtlsdr_demod_write_reg(dev, 0, 0x06, (on > 1) ? 0x90 : 0x80, 1);
+		r = rtlsdr_demod_write_reg(dev, 0, 0x06, (on > 1) ? 0x90 : 0x80, 1);
+		if (r) rfin = r;
 
 		fprintf(stderr, "Enabled direct sampling mode, input %i\n", on);
 		dev->direct_sampling = on;
 	} else {
 		if (dev->tuner && dev->tuner->init) {
 			rtlsdr_set_i2c_repeater(dev, 1);
-			r |= dev->tuner->init(dev);
+			r = dev->tuner->init(dev);
+			if (r) rfin = r;
 			rtlsdr_set_i2c_repeater(dev, 0);
 		}
 
 		if ((dev->tuner_type == RTLSDR_TUNER_R820T) ||
 		    (dev->tuner_type == RTLSDR_TUNER_R828D)) {
-			r |= rtlsdr_set_if_freq(dev, R82XX_IF_FREQ);
+			r = rtlsdr_set_if_freq(dev, R82XX_IF_FREQ);
+			if (r) rfin = r;
 
 			/* enable spectrum inversion */
-			r |= rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1);
+			r = rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1);
+			if (r) rfin = r;
 		} else {
-			r |= rtlsdr_set_if_freq(dev, 0);
+			r = rtlsdr_set_if_freq(dev, 0);
+			if (r) rfin = r;
 
 			/* enable In-phase + Quadrature ADC input */
-			r |= rtlsdr_demod_write_reg(dev, 0, 0x08, 0xcd, 1);
+			r = rtlsdr_demod_write_reg(dev, 0, 0x08, 0xcd, 1);
+			if (r) rfin = r;
 
 			/* Enable Zero-IF mode */
-			r |= rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1b, 1);
+			r = rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1b, 1);
+			if (r) rfin = r;
 		}
 
 		/* opt_adc_iq = 0, default ADC_I/ADC_Q datapath */
-		r |= rtlsdr_demod_write_reg(dev, 0, 0x06, 0x80, 1);
+		r = rtlsdr_demod_write_reg(dev, 0, 0x06, 0x80, 1);
+		if (r) rfin = r;
 
 		fprintf(stderr, "Disabled direct sampling mode\n");
 		dev->direct_sampling = 0;
 	}
 
-	r |= rtlsdr_set_center_freq(dev, dev->freq);
+	r = rtlsdr_set_center_freq(dev, dev->freq);
+	if (r) rfin = r;
 
-	return r;
+	return rfin;
 }
 
 int rtlsdr_get_direct_sampling(rtlsdr_dev_t *dev)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	return dev->direct_sampling;
 }
 
 int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on)
 {
-	int r = 0;
+	int r;
+	int rfin = 0;
 	int bw;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if ((dev->tuner_type == RTLSDR_TUNER_R820T) ||
 	    (dev->tuner_type == RTLSDR_TUNER_R828D))
-		return -2;
+		return RTLSDR_ERROR_DEVTYPE;
 
 	if (dev->direct_sampling)
-		return -3;
+		return RTLSDR_ERROR_STATE;
 
 	/* based on keenerds 1/f noise measurements */
 	dev->offs_freq = on ? ((dev->rate / 2) * 170 / 100) : 0;
-	r |= rtlsdr_set_if_freq(dev, dev->offs_freq);
+	rfin = rtlsdr_set_if_freq(dev, dev->offs_freq);
 
 	if (dev->tuner && dev->tuner->set_bw) {
 		rtlsdr_set_i2c_repeater(dev, 1);
@@ -1269,16 +1335,18 @@ int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on)
 		rtlsdr_set_i2c_repeater(dev, 0);
 	}
 
-	if (dev->freq > dev->offs_freq)
-		r |= rtlsdr_set_center_freq(dev, dev->freq);
+	if (dev->freq > dev->offs_freq) {
+		r = rtlsdr_set_center_freq(dev, dev->freq);
+		if (r) rfin = r;
+	}
 
-	return r;
+	return rfin;
 }
 
 int rtlsdr_get_offset_tuning(rtlsdr_dev_t *dev)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	return (dev->offs_freq) ? 1 : 0;
 }
@@ -1369,7 +1437,7 @@ const char *rtlsdr_get_device_name(uint32_t index)
 int rtlsdr_get_device_usb_strings(uint32_t index, char *manufact,
 				   char *product, char *serial)
 {
-	int r = -2;
+	int r;
 	int i;
 	libusb_context *ctx;
 	libusb_device **list;
@@ -1381,7 +1449,7 @@ int rtlsdr_get_device_usb_strings(uint32_t index, char *manufact,
 
 	r = libusb_init(&ctx);
 	if(r < 0)
-		return r;
+		return RTLSDR_ERROR_USB;
 
 	cnt = libusb_get_device_list(ctx, &list);
 
@@ -1420,12 +1488,12 @@ int rtlsdr_get_index_by_serial(const char *serial)
 	char str[256];
 
 	if (!serial)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	cnt = rtlsdr_get_device_count();
 
 	if (!cnt)
-		return -2;
+		return RTLSDR_ERROR_NOTFOUND;
 
 	for (i = 0; i < cnt; i++) {
 		r = rtlsdr_get_device_usb_strings(i, NULL, NULL, str);
@@ -1433,7 +1501,7 @@ int rtlsdr_get_index_by_serial(const char *serial)
 			return i;
 	}
 
-	return -3;
+	return RTLSDR_ERROR_NOTFOUND;
 }
 
 int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
@@ -1450,7 +1518,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 
 	dev = malloc(sizeof(rtlsdr_dev_t));
 	if (NULL == dev)
-		return -ENOMEM;
+		return RTLSDR_ERROR_NOMEM;
 
 	memset(dev, 0, sizeof(rtlsdr_dev_t));
 	memcpy(dev->fir, fir_default, sizeof(fir_default));
@@ -1458,7 +1526,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 	r = libusb_init(&dev->ctx);
 	if(r < 0){
 		free(dev);
-		return -1;
+		return RTLSDR_ERROR_USB;
 	}
 
 	dev->dev_lost = 1;
@@ -1481,7 +1549,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 	}
 
 	if (!device) {
-		r = -1;
+		r = RTLSDR_ERROR_NOTFOUND;
 		goto err;
 	}
 
@@ -1492,6 +1560,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 		if(r == LIBUSB_ERROR_ACCESS)
 			fprintf(stderr, "Please fix the device permissions, e.g. "
 			"by installing the udev rules file rtl-sdr.rules\n");
+		r = RTLSDR_ERROR_USB;
 		goto err;
 	}
 
@@ -1505,6 +1574,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 			fprintf(stderr, "Detached kernel driver\n");
 		} else {
 			fprintf(stderr, "Detaching kernel driver failed!");
+			r = RTLSDR_ERROR_USB;
 			goto err;
 		}
 #else
@@ -1520,6 +1590,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
 	r = libusb_claim_interface(dev->devh, 0);
 	if (r < 0) {
 		fprintf(stderr, "usb_claim_interface error %d\n", r);
+		r = RTLSDR_ERROR_USB;
 		goto err;
 	}
 
@@ -1625,7 +1696,7 @@ found:
 
 	*out_dev = dev;
 
-	return 0;
+	return RTLSDR_SUCCESS;
 err:
 	if (dev) {
 		if (dev->ctx)
@@ -1640,7 +1711,7 @@ err:
 int rtlsdr_close(rtlsdr_dev_t *dev)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if(!dev->dev_lost) {
 		/* block until all async operations have been completed (if any) */
@@ -1672,26 +1743,34 @@ int rtlsdr_close(rtlsdr_dev_t *dev)
 
 	free(dev);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 int rtlsdr_reset_buffer(rtlsdr_dev_t *dev)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	rtlsdr_write_reg(dev, USBB, USB_EPA_CTL, 0x1002, 2);
 	rtlsdr_write_reg(dev, USBB, USB_EPA_CTL, 0x0000, 2);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 int rtlsdr_read_sync(rtlsdr_dev_t *dev, void *buf, int len, int *n_read)
 {
+	int r;
+
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
-	return libusb_bulk_transfer(dev->devh, 0x81, buf, len, n_read, BULK_TIMEOUT);
+	r = libusb_bulk_transfer(dev->devh, 0x81, buf, len, n_read, BULK_TIMEOUT);
+	if (r != 0) {
+		dev->libusb_err = r;
+		r = RTLSDR_ERROR_USB;
+	}
+
+	return r;
 }
 
 static void LIBUSB_CALL _libusb_callback(struct libusb_transfer *xfer)
@@ -1732,7 +1811,7 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev)
 	unsigned int i;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (!dev->xfer) {
 		dev->xfer = malloc(dev->xfer_buf_num *
@@ -1743,7 +1822,7 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev)
 	}
 
 	if (dev->xfer_buf)
-		return -2;
+		return RTLSDR_ERROR_STATE;
 
 	dev->xfer_buf = malloc(dev->xfer_buf_num * sizeof(unsigned char *));
 	memset(dev->xfer_buf, 0, dev->xfer_buf_num * sizeof(unsigned char *));
@@ -1783,11 +1862,11 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev)
 			dev->xfer_buf[i] = malloc(dev->xfer_buf_len);
 
 			if (!dev->xfer_buf[i])
-				return -ENOMEM;
+				return RTLSDR_ERROR_NOMEM;
 		}
 	}
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev)
@@ -1795,7 +1874,7 @@ static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev)
 	unsigned int i;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (dev->xfer) {
 		for(i = 0; i < dev->xfer_buf_num; ++i) {
@@ -1827,7 +1906,7 @@ static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev)
 		dev->xfer_buf = NULL;
 	}
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx,
@@ -1840,10 +1919,10 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx,
 	enum rtlsdr_async_status next_status = RTLSDR_INACTIVE;
 
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	if (RTLSDR_INACTIVE != dev->async_status)
-		return -2;
+		return RTLSDR_ERROR_STATE;
 
 	dev->async_status = RTLSDR_RUNNING;
 	dev->async_cancel = 0;
@@ -1882,6 +1961,8 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx,
 					"echo 0 > /sys/module/usbcore"
 					"/parameters/usbfs_memory_mb\n", i);
 			dev->async_status = RTLSDR_CANCELING;
+			dev->libusb_err = r;
+			r = RTLSDR_ERROR_USB;
 			break;
 		}
 	}
@@ -1891,6 +1972,8 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx,
 							   &dev->async_cancel);
 		if (r < 0) {
 			/*fprintf(stderr, "handle_events returned: %d\n", r);*/
+			dev->libusb_err = r;
+			r = RTLSDR_ERROR_USB;
 			if (r == LIBUSB_ERROR_INTERRUPTED) /* stray signal */
 				continue;
 			break;
@@ -1914,8 +1997,11 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx,
 					 * propagate */
 					libusb_handle_events_timeout_completed(dev->ctx,
 									       &zerotv, NULL);
-					if (r < 0)
+					if (r < 0) {
+						dev->libusb_err = r;
+						r = RTLSDR_ERROR_USB;
 						continue;
+					}
 
 					next_status = RTLSDR_CANCELING;
 				}
@@ -1942,13 +2028,13 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx,
 int rtlsdr_cancel_async(rtlsdr_dev_t *dev)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	/* if streaming, try to cancel gracefully */
 	if (RTLSDR_RUNNING == dev->async_status) {
 		dev->async_status = RTLSDR_CANCELING;
 		dev->async_cancel = 1;
-		return 0;
+		return RTLSDR_SUCCESS;
 	}
 
 	/* if called while in pending state, change the state forcefully */
@@ -1958,7 +2044,7 @@ int rtlsdr_cancel_async(rtlsdr_dev_t *dev)
 		return 0;
 	}
 #endif
-	return -2;
+	return RTLSDR_ERROR_STATE;
 }
 
 uint32_t rtlsdr_get_tuner_clock(void *dev)
@@ -1980,7 +2066,7 @@ int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
 	if (dev)
 		return rtlsdr_i2c_write(((rtlsdr_dev_t *)dev), addr, buf, len);
 
-	return -1;
+	return RTLSDR_ERROR_NULL;
 }
 
 int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
@@ -1988,16 +2074,16 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
 	if (dev)
 		return rtlsdr_i2c_read(((rtlsdr_dev_t *)dev), addr, buf, len);
 
-	return -1;
+	return RTLSDR_ERROR_NULL;
 }
 
 int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on)
 {
 	if (!dev)
-		return -1;
+		return RTLSDR_ERROR_NULL;
 
 	rtlsdr_set_gpio_output(dev, 0);
 	rtlsdr_set_gpio_bit(dev, 0, on);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
diff --git a/src/tuner_e4k.c b/src/tuner_e4k.c
index 400e745..fc2c63b 100644
--- a/src/tuner_e4k.c
+++ b/src/tuner_e4k.c
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <stdio.h>
 
+#include <rtl-sdr.h>
 #include <reg_field.h>
 #include <tuner_e4k.h>
 #include <rtlsdr_i2c.h>
@@ -70,7 +71,8 @@ static int e4k_reg_write(struct e4k_state *e4k, uint8_t reg, uint8_t val)
 	data[1] = val;
 
 	r = rtlsdr_i2c_write_fn(e4k->rtl_dev, e4k->i2c_addr, data, 2);
-	return r == 2 ? 0 : -1;
+	if (r < 0) return r;
+	return r == 2 ? RTLSDR_SUCCESS : RTLSDR_ERROR_SHORT;
 }
 
 /*! \brief Read a register of the tuner chip
@@ -81,12 +83,15 @@ static int e4k_reg_write(struct e4k_state *e4k, uint8_t reg, uint8_t val)
 static int e4k_reg_read(struct e4k_state *e4k, uint8_t reg)
 {
 	uint8_t data = reg;
+	int r;
 
-	if (rtlsdr_i2c_write_fn(e4k->rtl_dev, e4k->i2c_addr, &data, 1) < 1)
-		return -1;
+	r = rtlsdr_i2c_write_fn(e4k->rtl_dev, e4k->i2c_addr, &data, 1);
+	if (r < 0) return r;
+	if (r < 1) return RTLSDR_ERROR_SHORT;
 
-	if (rtlsdr_i2c_read_fn(e4k->rtl_dev, e4k->i2c_addr, &data, 1) < 1)
-		return -1;
+	r = rtlsdr_i2c_read_fn(e4k->rtl_dev, e4k->i2c_addr, &data, 1);
+	if (r < 0) return r;
+	if (r < 1) return RTLSDR_ERROR_SHORT;
 
 	return data;
 }
@@ -104,7 +109,7 @@ static int e4k_reg_set_mask(struct e4k_state *e4k, uint8_t reg,
 	uint8_t tmp = e4k_reg_read(e4k, reg);
 
 	if ((tmp & mask) == val)
-		return 0;
+		return RTLSDR_SUCCESS;
 
 	return e4k_reg_write(e4k, reg, (tmp & ~mask) | (val & mask));
 }
@@ -203,7 +208,7 @@ static int choose_rf_filter(enum e4k_band band, uint32_t freq)
 						 freq);
 			break;
 		default:
-			rc = -EINVAL;
+			rc = RTLSDR_ERROR_INVALID;
 			break;
 	}
 
@@ -277,7 +282,7 @@ static const struct reg_field if_filter_fields[] = {
 static int find_if_bw(enum e4k_if_filter filter, uint32_t bw)
 {
 	if (filter >= ARRAY_SIZE(if_filter_bw))
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 
 	return closest_arr_idx(if_filter_bw[filter],
 			       if_filter_bw_len[filter], bw);
@@ -296,7 +301,7 @@ int e4k_if_filter_bw_set(struct e4k_state *e4k, enum e4k_if_filter filter,
 	const struct reg_field *field;
 
 	if (filter >= ARRAY_SIZE(if_filter_bw))
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 
 	bw_idx = find_if_bw(filter, bandwidth);
 
@@ -323,7 +328,7 @@ int e4k_if_filter_bw_get(struct e4k_state *e4k, enum e4k_if_filter filter)
 	const struct reg_field *field;
 
 	if (filter >= ARRAY_SIZE(if_filter_bw))
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 
 	field = &if_filter_fields[filter];
 
@@ -443,7 +448,7 @@ static uint32_t compute_flo(uint32_t f_osc, uint8_t z, uint16_t x, uint8_t r)
 {
 	uint64_t fvco = compute_fvco(f_osc, z, x);
 	if (fvco == 0)
-		return -EINVAL;
+		return 0;
 
 	return fvco / r;
 }
@@ -579,7 +584,7 @@ int e4k_tune_freq(struct e4k_state *e4k, uint32_t freq)
 	/* determine PLL parameters */
 	rc = e4k_compute_pll_params(&p, e4k->vco.fosc, freq);
 	if (!rc)
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 
 	/* actually tune to those parameters */
 	rc = e4k_tune_params(e4k, &p);
@@ -588,7 +593,7 @@ int e4k_tune_freq(struct e4k_state *e4k, uint32_t freq)
 	rc = e4k_reg_read(e4k, E4K_REG_SYNTH1);
 	if (!(rc & 0x01)) {
 		fprintf(stderr, "[E4K] PLL not locked for %u Hz!\n", freq);
-		return -1;
+		return RTLSDR_ERROR_INVALID;
 	}
 
 	return 0;
@@ -672,7 +677,7 @@ int e4k_set_lna_gain(struct e4k_state *e4k, int32_t gain)
 			return gain;
 		}
 	}
-	return -EINVAL;
+	return RTLSDR_ERROR_INVALID;
 }
 
 int e4k_set_enh_gain(struct e4k_state *e4k, int32_t gain)
@@ -688,9 +693,9 @@ int e4k_set_enh_gain(struct e4k_state *e4k, int32_t gain)
 
 	/* special case: 0 = off*/
 	if(0 == gain)
-		return 0;
+		return RTLSDR_SUCCESS;
 	else
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 }
 
 int e4k_enable_manual_gain(struct e4k_state *e4k, uint8_t manual)
@@ -710,7 +715,7 @@ int e4k_enable_manual_gain(struct e4k_state *e4k, uint8_t manual)
 		e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7, 0);
 	}
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 static int find_stage_gain(uint8_t stage, int8_t val)
@@ -719,7 +724,7 @@ static int find_stage_gain(uint8_t stage, int8_t val)
 	int i;
 
 	if (stage >= ARRAY_SIZE(if_stage_gain))
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 
 	arr = if_stage_gain[stage];
 
@@ -727,7 +732,7 @@ static int find_stage_gain(uint8_t stage, int8_t val)
 		if (arr[i] == val)
 			return i;
 	}
-	return -EINVAL;
+	return RTLSDR_ERROR_INVALID;
 }
 
 /*! \brief Set the gain of one of the IF gain stages
@@ -765,7 +770,7 @@ int e4k_mixer_gain_set(struct e4k_state *e4k, int8_t value)
 		bit = 1;
 		break;
 	default:
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 	}
 
 	return e4k_reg_set_mask(e4k, E4K_REG_GAIN2, 1, bit);
@@ -774,9 +779,9 @@ int e4k_mixer_gain_set(struct e4k_state *e4k, int8_t value)
 int e4k_commonmode_set(struct e4k_state *e4k, int8_t value)
 {
 	if(value < 0)
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 	else if(value > 7)
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 
 	return e4k_reg_set_mask(e4k, E4K_REG_DC7, 7, value);
 }
@@ -789,13 +794,13 @@ int e4k_manual_dc_offset(struct e4k_state *e4k, int8_t iofs, int8_t irange, int8
 	int res;
 
 	if((iofs < 0x00) || (iofs > 0x3f))
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 	if((irange < 0x00) || (irange > 0x03))
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 	if((qofs < 0x00) || (qofs > 0x3f))
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 	if((qrange < 0x00) || (qrange > 0x03))
-		return -EINVAL;
+		return RTLSDR_ERROR_INVALID;
 
 	res = e4k_reg_set_mask(e4k, E4K_REG_DC2, 0x3f, iofs);
 	if(res < 0)
@@ -886,7 +891,7 @@ int e4k_dc_offset_gen_table(struct e4k_state *e4k)
 			      TO_LUT(offs_i, range_i));
 	}
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 /***********************************************************************
@@ -899,7 +904,7 @@ int e4k_standby(struct e4k_state *e4k, int enable)
 	e4k_reg_set_mask(e4k, E4K_REG_MASTER1, E4K_MASTER1_NORM_STBY,
 			 enable ? 0 : E4K_MASTER1_NORM_STBY);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 /***********************************************************************
@@ -916,7 +921,7 @@ static int magic_init(struct e4k_state *e4k)
 	e4k_reg_write(e4k, 0x9f, 0x7f);
 	e4k_reg_write(e4k, 0xa0, 0x07);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 /*! \brief Initialize the E4K tuner
@@ -996,5 +1001,5 @@ int e4k_init(struct e4k_state *e4k)
 	e4k_reg_set_mask(e4k, E4K_REG_DCTIME1, 0x03, 0);
 	e4k_reg_set_mask(e4k, E4K_REG_DCTIME2, 0x03, 0);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
diff --git a/src/tuner_fc0012.c b/src/tuner_fc0012.c
index 768cf1c..4378273 100644
--- a/src/tuner_fc0012.c
+++ b/src/tuner_fc0012.c
@@ -24,34 +24,40 @@
 #include <stdint.h>
 #include <stdio.h>
 
+#include "rtl-sdr.h"
 #include "rtlsdr_i2c.h"
 #include "tuner_fc0012.h"
 
 static int fc0012_writereg(void *dev, uint8_t reg, uint8_t val)
 {
+	int r;
 	uint8_t data[2];
 	data[0] = reg;
 	data[1] = val;
 
-	if (rtlsdr_i2c_write_fn(dev, FC0012_I2C_ADDR, data, 2) < 0)
-		return -1;
+	r = rtlsdr_i2c_write_fn(dev, FC0012_I2C_ADDR, data, 2);
+	if (r < 0)
+		return r;
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 static int fc0012_readreg(void *dev, uint8_t reg, uint8_t *val)
 {
+	int r;
 	uint8_t data = reg;
 
-	if (rtlsdr_i2c_write_fn(dev, FC0012_I2C_ADDR, &data, 1) < 0)
-		return -1;
+	r = rtlsdr_i2c_write_fn(dev, FC0012_I2C_ADDR, &data, 1);
+	if (r < 0)
+		return r;
 
-	if (rtlsdr_i2c_read_fn(dev, FC0012_I2C_ADDR, &data, 1) < 0)
-		return -1;
+	r = rtlsdr_i2c_read_fn(dev, FC0012_I2C_ADDR, &data, 1);
+	if (r < 0)
+		return r;
 
 	*val = data;
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 /* Incomplete list of register settings:
@@ -230,7 +236,7 @@ int fc0012_set_params(void *dev, uint32_t freq, uint32_t bandwidth)
 	if ((reg[1] > 15) || (reg[2] < 0x0b)) {
 		fprintf(stderr, "[FC0012] no valid PLL combination "
 				"found for %u Hz!\n", freq);
-		return -1;
+		return RTLSDR_ERROR_INVALID;
 	}
 
 	/* fix clock out */
diff --git a/src/tuner_fc0013.c b/src/tuner_fc0013.c
index 78b696e..6df3afd 100644
--- a/src/tuner_fc0013.c
+++ b/src/tuner_fc0013.c
@@ -27,34 +27,40 @@
 #include <stdint.h>
 #include <stdio.h>
 
+#include "rtl-sdr.h"
 #include "rtlsdr_i2c.h"
 #include "tuner_fc0013.h"
 
 static int fc0013_writereg(void *dev, uint8_t reg, uint8_t val)
 {
+	int r;
 	uint8_t data[2];
 	data[0] = reg;
 	data[1] = val;
 
-	if (rtlsdr_i2c_write_fn(dev, FC0013_I2C_ADDR, data, 2) < 0)
-		return -1;
+	r = rtlsdr_i2c_write_fn(dev, FC0013_I2C_ADDR, data, 2);
+	if (r < 0)
+		return r;
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 static int fc0013_readreg(void *dev, uint8_t reg, uint8_t *val)
 {
+	int r;
 	uint8_t data = reg;
 
-	if (rtlsdr_i2c_write_fn(dev, FC0013_I2C_ADDR, &data, 1) < 0)
-		return -1;
+	r = rtlsdr_i2c_write_fn(dev, FC0013_I2C_ADDR, &data, 1);
+	if (r < 0)
+		return r;
 
-	if (rtlsdr_i2c_read_fn(dev, FC0013_I2C_ADDR, &data, 1) < 0)
-		return -1;
+	r = rtlsdr_i2c_read_fn(dev, FC0013_I2C_ADDR, &data, 1);
+	if (r < 0)
+		return r;
 
 	*val = data;
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 int fc0013_init(void *dev)
@@ -335,7 +341,7 @@ int fc0013_set_params(void *dev, uint32_t freq, uint32_t bandwidth)
 	if ((reg[1] > 15) || (reg[2] < 0x0b)) {
 		fprintf(stderr, "[FC0013] no valid PLL combination "
 				"found for %u Hz!\n", freq);
-		return -1;
+		return RTLSDR_ERROR_INVALID;
 	}
 
 	/* fix clock out */
@@ -428,22 +434,25 @@ exit:
 
 int fc0013_set_gain_mode(void *dev, int manual)
 {
-	int ret = 0;
+	int ret;
+	int fret = 0;
 	uint8_t tmp = 0;
 
-	ret |= fc0013_readreg(dev, 0x0d, &tmp);
+	fret = fc0013_readreg(dev, 0x0d, &tmp);
 
 	if (manual)
 		tmp |= (1 << 3);
 	else
 		tmp &= ~(1 << 3);
 
-	ret |= fc0013_writereg(dev, 0x0d, tmp);
+	ret = fc0013_writereg(dev, 0x0d, tmp);
+	if (ret) fret = ret;
 
 	/* set a fixed IF-gain for now */
-	ret |= fc0013_writereg(dev, 0x13, 0x0a);
+	ret = fc0013_writereg(dev, 0x13, 0x0a);
+	if (ret) fret = ret;
 
-	return ret;
+	return fret;
 }
 
 int fc0013_lna_gains[] ={
@@ -477,11 +486,12 @@ int fc0013_lna_gains[] ={
 
 int fc0013_set_lna_gain(void *dev, int gain)
 {
-	int ret = 0;
+	int ret;
+	int fret = 0;
 	unsigned int i;
 	uint8_t tmp = 0;
 
-	ret |= fc0013_readreg(dev, 0x14, &tmp);
+	fret = fc0013_readreg(dev, 0x14, &tmp);
 
 	/* mask bits off */
 	tmp &= 0xe0;
@@ -494,7 +504,8 @@ int fc0013_set_lna_gain(void *dev, int gain)
 	}
 
 	/* set gain */
-	ret |= fc0013_writereg(dev, 0x14, tmp);
+	ret = fc0013_writereg(dev, 0x14, tmp);
+	if (ret) fret = ret;
 
-	return ret;
+	return fret;
 }
diff --git a/src/tuner_fc2580.c b/src/tuner_fc2580.c
index d2eeba5..9aa9ff7 100644
--- a/src/tuner_fc2580.c
+++ b/src/tuner_fc2580.c
@@ -8,6 +8,7 @@
 
 #include <stdint.h>
 
+#include "rtl-sdr.h"
 #include "rtlsdr_i2c.h"
 #include "tuner_fc2580.h"
 
@@ -16,32 +17,32 @@
 
 /* glue functions to rtl-sdr code */
 
-fc2580_fci_result_type fc2580_i2c_write(void *pTuner, unsigned char reg, unsigned char val)
+enum rtlsdr_error fc2580_i2c_write(void *pTuner, unsigned char reg, unsigned char val)
 {
 	uint8_t data[2];
 
 	data[0] = reg;
 	data[1] = val;
 
-	if (rtlsdr_i2c_write_fn(pTuner, FC2580_I2C_ADDR, data, 2) < 0)
-		return FC2580_FCI_FAIL;
-
-	return FC2580_FCI_SUCCESS;
+	return rtlsdr_i2c_write_fn(pTuner, FC2580_I2C_ADDR, data, 2);
 }
 
-fc2580_fci_result_type fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned char *read_data)
+enum rtlsdr_error fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned char *read_data)
 {
+	int r;
 	uint8_t data = reg;
 
-	if (rtlsdr_i2c_write_fn(pTuner, FC2580_I2C_ADDR, &data, 1) < 0)
-		return FC2580_FCI_FAIL;
+	r = rtlsdr_i2c_write_fn(pTuner, FC2580_I2C_ADDR, &data, 1);
+	if (r < 0)
+		return r;
 
-	if (rtlsdr_i2c_read_fn(pTuner, FC2580_I2C_ADDR, &data, 1) < 0)
-		return FC2580_FCI_FAIL;
+	r = rtlsdr_i2c_read_fn(pTuner, FC2580_I2C_ADDR, &data, 1);
+	if (r < 0)
+		return r;
 
 	*read_data = data;
 
-	return FC2580_FCI_SUCCESS;
+	return RTLSDR_SUCCESS;
 }
 
 int
@@ -59,15 +60,7 @@ fc2580_Initialize(
 	// Note: CrystalFreqKhz = round(CrystalFreqHz / 1000)
 	CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000);
 
-	if(fc2580_set_init(pTuner, AgcMode, CrystalFreqKhz) != FC2580_FCI_SUCCESS)
-		goto error_status_initialize_tuner;
-
-
-	return FUNCTION_SUCCESS;
-
-
-error_status_initialize_tuner:
-	return FUNCTION_ERROR;
+	return fc2580_set_init(pTuner, AgcMode, CrystalFreqKhz);
 }
 
 int
@@ -85,13 +78,7 @@ fc2580_SetRfFreqHz(
 	RfFreqKhz = (unsigned int)((RfFreqHz + 500) / 1000);
 	CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000);
 
-	if(fc2580_set_freq(pTuner, RfFreqKhz, CrystalFreqKhz) != FC2580_FCI_SUCCESS)
-		goto error_status_set_tuner_rf_frequency;
-
-	return FUNCTION_SUCCESS;
-
-error_status_set_tuner_rf_frequency:
-	return FUNCTION_ERROR;
+	return fc2580_set_freq(pTuner, RfFreqKhz, CrystalFreqKhz);
 }
 
 /**
@@ -111,14 +98,7 @@ fc2580_SetBandwidthMode(
 	// Note: CrystalFreqKhz = round(CrystalFreqHz / 1000)
 	CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000);
 
-	if(fc2580_set_filter(pTuner, (unsigned char)BandwidthMode, CrystalFreqKhz) != FC2580_FCI_SUCCESS)
-		goto error_status_set_tuner_bandwidth_mode;
-
-	return FUNCTION_SUCCESS;
-
-
-error_status_set_tuner_bandwidth_mode:
-	return FUNCTION_ERROR;
+	return fc2580_set_filter(pTuner, (unsigned char)BandwidthMode, CrystalFreqKhz);
 }
 
 void fc2580_wait_msec(void *pTuner, int a)
@@ -143,37 +123,57 @@ void fc2580_wait_msec(void *pTuner, int a)
 	2 : Voltage Control Mode
 
 ==============================================================================*/
-fc2580_fci_result_type fc2580_set_init( void *pTuner, int ifagc_mode, unsigned int freq_xtal )
+enum rtlsdr_error fc2580_set_init( void *pTuner, int ifagc_mode, unsigned int freq_xtal )
 {
-	fc2580_fci_result_type result = FC2580_FCI_SUCCESS;
-
-	result &= fc2580_i2c_write(pTuner, 0x00, 0x00);	/*** Confidential ***/
-	result &= fc2580_i2c_write(pTuner, 0x12, 0x86);
-	result &= fc2580_i2c_write(pTuner, 0x14, 0x5C);
-	result &= fc2580_i2c_write(pTuner, 0x16, 0x3C);
-	result &= fc2580_i2c_write(pTuner, 0x1F, 0xD2);
-	result &= fc2580_i2c_write(pTuner, 0x09, 0xD7);
-	result &= fc2580_i2c_write(pTuner, 0x0B, 0xD5);
-	result &= fc2580_i2c_write(pTuner, 0x0C, 0x32);
-	result &= fc2580_i2c_write(pTuner, 0x0E, 0x43);
-	result &= fc2580_i2c_write(pTuner, 0x21, 0x0A);
-	result &= fc2580_i2c_write(pTuner, 0x22, 0x82);
+	enum rtlsdr_error result;
+	enum rtlsdr_error fresult = RTLSDR_SUCCESS;
+
+	result = fc2580_i2c_write(pTuner, 0x00, 0x00);	/*** Confidential ***/
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x12, 0x86);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x14, 0x5C);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x16, 0x3C);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x1F, 0xD2);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x09, 0xD7);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x0B, 0xD5);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x0C, 0x32);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x0E, 0x43);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x21, 0x0A);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x22, 0x82);
+	if (result) fresult = result;
 	if( ifagc_mode == 1 )
 	{
-		result &= fc2580_i2c_write(pTuner, 0x45, 0x10);	//internal AGC
-		result &= fc2580_i2c_write(pTuner, 0x4C, 0x00);	//HOLD_AGC polarity
+		result = fc2580_i2c_write(pTuner, 0x45, 0x10);	//internal AGC
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x4C, 0x00);	//HOLD_AGC polarity
+		if (result) fresult = result;
 	}
 	else if( ifagc_mode == 2 )
 	{
-		result &= fc2580_i2c_write(pTuner, 0x45, 0x20);	//Voltage Control Mode
-		result &= fc2580_i2c_write(pTuner, 0x4C, 0x02);	//HOLD_AGC polarity
+		result = fc2580_i2c_write(pTuner, 0x45, 0x20);	//Voltage Control Mode
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x4C, 0x02);	//HOLD_AGC polarity
+		if (result) fresult = result;
 	}
-	result &= fc2580_i2c_write(pTuner, 0x3F, 0x88);
-	result &= fc2580_i2c_write(pTuner, 0x02, 0x0E);
-	result &= fc2580_i2c_write(pTuner, 0x58, 0x14);
-	result &= fc2580_set_filter(pTuner, 8, freq_xtal);	//BW = 7.8MHz
-
-	return result;
+	result = fc2580_i2c_write(pTuner, 0x3F, 0x88);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x02, 0x0E);
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x58, 0x14);
+	if (result) fresult = result;
+	result = fc2580_set_filter(pTuner, 8, freq_xtal);	//BW = 7.8MHz
+	if (result) fresult = result;
+
+	return fresult;
 }
 
 
@@ -192,7 +192,7 @@ fc2580_fci_result_type fc2580_set_init( void *pTuner, int ifagc_mode, unsigned i
 	ex) 2.6GHz = 2600000
 
 ==============================================================================*/
-fc2580_fci_result_type fc2580_set_freq( void *pTuner, unsigned int f_lo, unsigned int freq_xtal )
+enum rtlsdr_error fc2580_set_freq( void *pTuner, unsigned int f_lo, unsigned int freq_xtal )
 {
 	unsigned int f_diff, f_diff_shifted, n_val, k_val;
 	unsigned int f_vco, r_val, f_comp;
@@ -202,7 +202,8 @@ fc2580_fci_result_type fc2580_set_freq( void *pTuner, unsigned int f_lo, unsigne
 	
 	fc2580_band_type band = ( f_lo > 1000000 )? FC2580_L_BAND : ( f_lo > 400000 )? FC2580_UHF_BAND : FC2580_VHF_BAND;
 
-	fc2580_fci_result_type result = FC2580_FCI_SUCCESS;
+	enum rtlsdr_error result;
+	enum rtlsdr_error fresult = RTLSDR_SUCCESS;
 
 	f_vco = ( band == FC2580_UHF_BAND )? f_lo * 4 : (( band == FC2580_L_BAND )? f_lo * 2 : f_lo * 12);
 	r_val = ( f_vco >= 2*76*freq_xtal )? 1 : ( f_vco >= 76*freq_xtal )? 2 : 4;
@@ -227,102 +228,176 @@ fc2580_fci_result_type fc2580_set_freq( void *pTuner, unsigned int f_lo, unsigne
 			case FC2580_UHF_BAND:
 				data_0x02 = (data_0x02 & 0x3F);
 
-				result &= fc2580_i2c_write(pTuner, 0x25, 0xF0);
-				result &= fc2580_i2c_write(pTuner, 0x27, 0x77);
-				result &= fc2580_i2c_write(pTuner, 0x28, 0x53);
-				result &= fc2580_i2c_write(pTuner, 0x29, 0x60);
-				result &= fc2580_i2c_write(pTuner, 0x30, 0x09);
-				result &= fc2580_i2c_write(pTuner, 0x50, 0x8C);
-				result &= fc2580_i2c_write(pTuner, 0x53, 0x50);
+				result = fc2580_i2c_write(pTuner, 0x25, 0xF0);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x27, 0x77);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x28, 0x53);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x29, 0x60);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x30, 0x09);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x50, 0x8C);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x53, 0x50);
+				if (result) fresult = result;
 
 				if( f_lo < 538000 )
-					result &= fc2580_i2c_write(pTuner, 0x5F, 0x13);
+					result = fc2580_i2c_write(pTuner, 0x5F, 0x13);
 				else					
-					result &= fc2580_i2c_write(pTuner, 0x5F, 0x15);
+					result = fc2580_i2c_write(pTuner, 0x5F, 0x15);
+				if (result) fresult = result;
 
 				if( f_lo < 538000 )
 				{
-					result &= fc2580_i2c_write(pTuner, 0x61, 0x07);
-					result &= fc2580_i2c_write(pTuner, 0x62, 0x06);
-					result &= fc2580_i2c_write(pTuner, 0x67, 0x06);
-					result &= fc2580_i2c_write(pTuner, 0x68, 0x08);
-					result &= fc2580_i2c_write(pTuner, 0x69, 0x10);
-					result &= fc2580_i2c_write(pTuner, 0x6A, 0x12);
+					result = fc2580_i2c_write(pTuner, 0x61, 0x07);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x62, 0x06);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x67, 0x06);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x68, 0x08);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x69, 0x10);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x6A, 0x12);
+					if (result) fresult = result;
 				}
 				else if( f_lo < 794000 )
 				{
-					result &= fc2580_i2c_write(pTuner, 0x61, 0x03);
-					result &= fc2580_i2c_write(pTuner, 0x62, 0x03);
-					result &= fc2580_i2c_write(pTuner, 0x67, 0x03);  //ACI improve
-					result &= fc2580_i2c_write(pTuner, 0x68, 0x05);  //ACI improve
-					result &= fc2580_i2c_write(pTuner, 0x69, 0x0C);
-					result &= fc2580_i2c_write(pTuner, 0x6A, 0x0E);
+					result = fc2580_i2c_write(pTuner, 0x61, 0x03);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x62, 0x03);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x67, 0x03);  //ACI improve
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x68, 0x05);  //ACI improve
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x69, 0x0C);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x6A, 0x0E);
+					if (result) fresult = result;
 				}
 				else
 				{
-					result &= fc2580_i2c_write(pTuner, 0x61, 0x07);
-					result &= fc2580_i2c_write(pTuner, 0x62, 0x06);
-					result &= fc2580_i2c_write(pTuner, 0x67, 0x07);
-					result &= fc2580_i2c_write(pTuner, 0x68, 0x09);
-					result &= fc2580_i2c_write(pTuner, 0x69, 0x10);
-					result &= fc2580_i2c_write(pTuner, 0x6A, 0x12);
+					result = fc2580_i2c_write(pTuner, 0x61, 0x07);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x62, 0x06);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x67, 0x07);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x68, 0x09);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x69, 0x10);
+					if (result) fresult = result;
+					result = fc2580_i2c_write(pTuner, 0x6A, 0x12);
+					if (result) fresult = result;
 				}
 
-				result &= fc2580_i2c_write(pTuner, 0x63, 0x15);
-
-				result &= fc2580_i2c_write(pTuner, 0x6B, 0x0B);
-				result &= fc2580_i2c_write(pTuner, 0x6C, 0x0C);
-				result &= fc2580_i2c_write(pTuner, 0x6D, 0x78);
-				result &= fc2580_i2c_write(pTuner, 0x6E, 0x32);
-				result &= fc2580_i2c_write(pTuner, 0x6F, 0x14);
-				result &= fc2580_set_filter(pTuner, 8, freq_xtal);	//BW = 7.8MHz
+				result = fc2580_i2c_write(pTuner, 0x63, 0x15);
+				if (result) fresult = result;
+
+				result = fc2580_i2c_write(pTuner, 0x6B, 0x0B);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6C, 0x0C);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6D, 0x78);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6E, 0x32);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6F, 0x14);
+				if (result) fresult = result;
+				result = fc2580_set_filter(pTuner, 8, freq_xtal);	//BW = 7.8MHz
+				if (result) fresult = result;
 				break;
 			case FC2580_VHF_BAND:
 				data_0x02 = (data_0x02 & 0x3F) | 0x80;
-				result &= fc2580_i2c_write(pTuner, 0x27, 0x77);
-				result &= fc2580_i2c_write(pTuner, 0x28, 0x33);
-				result &= fc2580_i2c_write(pTuner, 0x29, 0x40);
-				result &= fc2580_i2c_write(pTuner, 0x30, 0x09);
-				result &= fc2580_i2c_write(pTuner, 0x50, 0x8C);
-				result &= fc2580_i2c_write(pTuner, 0x53, 0x50);
-				result &= fc2580_i2c_write(pTuner, 0x5F, 0x0F);
-				result &= fc2580_i2c_write(pTuner, 0x61, 0x07);
-				result &= fc2580_i2c_write(pTuner, 0x62, 0x00);
-				result &= fc2580_i2c_write(pTuner, 0x63, 0x15);
-				result &= fc2580_i2c_write(pTuner, 0x67, 0x03);
-				result &= fc2580_i2c_write(pTuner, 0x68, 0x05);
-				result &= fc2580_i2c_write(pTuner, 0x69, 0x10);
-				result &= fc2580_i2c_write(pTuner, 0x6A, 0x12);
-				result &= fc2580_i2c_write(pTuner, 0x6B, 0x08);
-				result &= fc2580_i2c_write(pTuner, 0x6C, 0x0A);
-				result &= fc2580_i2c_write(pTuner, 0x6D, 0x78);
-				result &= fc2580_i2c_write(pTuner, 0x6E, 0x32);
-				result &= fc2580_i2c_write(pTuner, 0x6F, 0x54);
-				result &= fc2580_set_filter(pTuner, 7, freq_xtal);	//BW = 6.8MHz
+				result = fc2580_i2c_write(pTuner, 0x27, 0x77);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x28, 0x33);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x29, 0x40);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x30, 0x09);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x50, 0x8C);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x53, 0x50);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x5F, 0x0F);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x61, 0x07);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x62, 0x00);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x63, 0x15);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x67, 0x03);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x68, 0x05);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x69, 0x10);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6A, 0x12);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6B, 0x08);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6C, 0x0A);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6D, 0x78);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6E, 0x32);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6F, 0x54);
+				if (result) fresult = result;
+				result = fc2580_set_filter(pTuner, 7, freq_xtal);	//BW = 6.8MHz
+				if (result) fresult = result;
 				break;
 			case FC2580_L_BAND:
 				data_0x02 = (data_0x02 & 0x3F) | 0x40;
-				result &= fc2580_i2c_write(pTuner, 0x2B, 0x70);
-				result &= fc2580_i2c_write(pTuner, 0x2C, 0x37);
-				result &= fc2580_i2c_write(pTuner, 0x2D, 0xE7);
-				result &= fc2580_i2c_write(pTuner, 0x30, 0x09);
-				result &= fc2580_i2c_write(pTuner, 0x44, 0x20);
-				result &= fc2580_i2c_write(pTuner, 0x50, 0x8C);
-				result &= fc2580_i2c_write(pTuner, 0x53, 0x50);
-				result &= fc2580_i2c_write(pTuner, 0x5F, 0x0F);
-				result &= fc2580_i2c_write(pTuner, 0x61, 0x0F);
-				result &= fc2580_i2c_write(pTuner, 0x62, 0x00);
-				result &= fc2580_i2c_write(pTuner, 0x63, 0x13);
-				result &= fc2580_i2c_write(pTuner, 0x67, 0x00);
-				result &= fc2580_i2c_write(pTuner, 0x68, 0x02);
-				result &= fc2580_i2c_write(pTuner, 0x69, 0x0C);
-				result &= fc2580_i2c_write(pTuner, 0x6A, 0x0E);
-				result &= fc2580_i2c_write(pTuner, 0x6B, 0x08);
-				result &= fc2580_i2c_write(pTuner, 0x6C, 0x0A);
-				result &= fc2580_i2c_write(pTuner, 0x6D, 0xA0);
-				result &= fc2580_i2c_write(pTuner, 0x6E, 0x50);
-				result &= fc2580_i2c_write(pTuner, 0x6F, 0x14);
-				result &= fc2580_set_filter(pTuner, 1, freq_xtal);	//BW = 1.53MHz
+				result = fc2580_i2c_write(pTuner, 0x2B, 0x70);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x2C, 0x37);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x2D, 0xE7);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x30, 0x09);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x44, 0x20);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x50, 0x8C);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x53, 0x50);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x5F, 0x0F);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x61, 0x0F);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x62, 0x00);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x63, 0x13);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x67, 0x00);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x68, 0x02);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x69, 0x0C);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6A, 0x0E);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6B, 0x08);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6C, 0x0A);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6D, 0xA0);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6E, 0x50);
+				if (result) fresult = result;
+				result = fc2580_i2c_write(pTuner, 0x6F, 0x14);
+				if (result) fresult = result;
+				result = fc2580_set_filter(pTuner, 1, freq_xtal);	//BW = 1.53MHz
+				if (result) fresult = result;
 				break;
 			default:
 				break;
@@ -331,23 +406,32 @@ fc2580_fci_result_type fc2580_set_freq( void *pTuner, unsigned int f_lo, unsigne
 //	}
 
 	//A command about AGC clock's pre-divide ratio
-	if( freq_xtal >= 28000 )
-		result &= fc2580_i2c_write(pTuner, 0x4B, 0x22 );
+	if( freq_xtal >= 28000 ) {
+		result = fc2580_i2c_write(pTuner, 0x4B, 0x22 );
+		if (result) fresult = result;
+	}
 
 	//Commands about VCO Band and PLL setting.
-	result &= fc2580_i2c_write(pTuner, 0x02, data_0x02);
+	result = fc2580_i2c_write(pTuner, 0x02, data_0x02);
+	if (result) fresult = result;
 	data_0x18 = ( ( r_val == 1 )? 0x00 : ( ( r_val == 2 )? 0x10 : 0x20 ) ) + (unsigned char)(k_val >> 16);
-	result &= fc2580_i2c_write(pTuner, 0x18, data_0x18);						//Load 'R' value and high part of 'K' values
-	result &= fc2580_i2c_write(pTuner, 0x1A, (unsigned char)( k_val >> 8 ) );	//Load middle part of 'K' value
-	result &= fc2580_i2c_write(pTuner, 0x1B, (unsigned char)( k_val ) );		//Load lower part of 'K' value
-	result &= fc2580_i2c_write(pTuner, 0x1C, (unsigned char)( n_val ) );		//Load 'N' value
+	result = fc2580_i2c_write(pTuner, 0x18, data_0x18);						//Load 'R' value and high part of 'K' values
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x1A, (unsigned char)( k_val >> 8 ) );	//Load middle part of 'K' value
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x1B, (unsigned char)( k_val ) );		//Load lower part of 'K' value
+	if (result) fresult = result;
+	result = fc2580_i2c_write(pTuner, 0x1C, (unsigned char)( n_val ) );		//Load 'N' value
+	if (result) fresult = result;
 
 	//A command about UHF LNA Load Cap
-	if( band == FC2580_UHF_BAND )
-		result &= fc2580_i2c_write(pTuner, 0x2D, ( f_lo <= (unsigned int)794000 )? 0x9F : 0x8F );	//LNA_OUT_CAP
+	if( band == FC2580_UHF_BAND ) {
+		result = fc2580_i2c_write(pTuner, 0x2D, ( f_lo <= (unsigned int)794000 )? 0x9F : 0x8F );	//LNA_OUT_CAP
+		if (result) fresult = result;
+	}
 	
 
-	return result;
+	return fresult;
 }
 
 
@@ -369,57 +453,78 @@ fc2580_fci_result_type fc2580_set_freq( void *pTuner, unsigned int f_lo, unsigne
 	
 
 ==============================================================================*/
-fc2580_fci_result_type fc2580_set_filter( void *pTuner, unsigned char filter_bw, unsigned int freq_xtal )
+enum rtlsdr_error fc2580_set_filter( void *pTuner, unsigned char filter_bw, unsigned int freq_xtal )
 {
 	unsigned char	cal_mon = 0, i;
-	fc2580_fci_result_type result = FC2580_FCI_SUCCESS;
+	enum rtlsdr_error result;
+	enum rtlsdr_error fresult = RTLSDR_SUCCESS;
 
 	if(filter_bw == 1)
 	{
-		result &= fc2580_i2c_write(pTuner, 0x36, 0x1C);
-		result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(4151*freq_xtal/1000000) );
-		result &= fc2580_i2c_write(pTuner, 0x39, 0x00);
-		result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		result = fc2580_i2c_write(pTuner, 0x36, 0x1C);
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x37, (unsigned char)(4151*freq_xtal/1000000) );
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x39, 0x00);
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		if (result) fresult = result;
 	}
 	if(filter_bw == 6)
 	{
-		result &= fc2580_i2c_write(pTuner, 0x36, 0x18);
-		result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(4400*freq_xtal/1000000) );
-		result &= fc2580_i2c_write(pTuner, 0x39, 0x00);
-		result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		result = fc2580_i2c_write(pTuner, 0x36, 0x18);
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x37, (unsigned char)(4400*freq_xtal/1000000) );
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x39, 0x00);
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		if (result) fresult = result;
 	}
 	else if(filter_bw == 7)
 	{
-		result &= fc2580_i2c_write(pTuner, 0x36, 0x18);
-		result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(3910*freq_xtal/1000000) );
-		result &= fc2580_i2c_write(pTuner, 0x39, 0x80);
-		result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		result = fc2580_i2c_write(pTuner, 0x36, 0x18);
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x37, (unsigned char)(3910*freq_xtal/1000000) );
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x39, 0x80);
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		if (result) fresult = result;
 	}
 	else if(filter_bw == 8)
 	{
-		result &= fc2580_i2c_write(pTuner, 0x36, 0x18);
-		result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(3300*freq_xtal/1000000) );
-		result &= fc2580_i2c_write(pTuner, 0x39, 0x80);
-		result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		result = fc2580_i2c_write(pTuner, 0x36, 0x18);
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x37, (unsigned char)(3300*freq_xtal/1000000) );
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x39, 0x80);
+		if (result) fresult = result;
+		result = fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		if (result) fresult = result;
 	}
 
 	
 	for(i=0; i<5; i++)
 	{
 		fc2580_wait_msec(pTuner, 5);//wait 5ms
-		result &= fc2580_i2c_read(pTuner, 0x2F, &cal_mon);
+		result = fc2580_i2c_read(pTuner, 0x2F, &cal_mon);
+		if (result) fresult = result;
 		if( (cal_mon & 0xC0) != 0xC0)
 		{
-			result &= fc2580_i2c_write(pTuner, 0x2E, 0x01);
-			result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+			result = fc2580_i2c_write(pTuner, 0x2E, 0x01);
+			if (result) fresult = result;
+			result = fc2580_i2c_write(pTuner, 0x2E, 0x09);
+			if (result) fresult = result;
 		}
 		else
 			break;
 	}
 
-	result &= fc2580_i2c_write(pTuner, 0x2E, 0x01);
+	result = fc2580_i2c_write(pTuner, 0x2E, 0x01);
+	if (result) fresult = result;
 
-	return result;
+	return fresult;
 }
 
 /*==============================================================================
diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c
index fe52bd9..9561c1f 100644
--- a/src/tuner_r82xx.c
+++ b/src/tuner_r82xx.c
@@ -26,6 +26,7 @@
 #include <stdint.h>
 #include <string.h>
 
+#include "rtl-sdr.h"
 #include "rtlsdr_i2c.h"
 #include "tuner_r82xx.h"
 
@@ -275,7 +276,7 @@ static int r82xx_write(struct r82xx_priv *priv, uint8_t reg, const uint8_t *val,
 				   __FUNCTION__, rc, reg, size);
 			if (rc < 0)
 				return rc;
-			return -1;
+			return RTLSDR_ERROR_SHORT;
 		}
 
 		reg += size;
@@ -283,7 +284,7 @@ static int r82xx_write(struct r82xx_priv *priv, uint8_t reg, const uint8_t *val,
 		pos += size;
 	} while (len > 0);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 static int r82xx_write_reg(struct r82xx_priv *priv, uint8_t reg, uint8_t val)
@@ -298,7 +299,7 @@ static int r82xx_read_cache_reg(struct r82xx_priv *priv, int reg)
 	if (reg >= 0 && reg < NUM_REGS)
 		return priv->regs[reg];
 	else
-		return -1;
+		return RTLSDR_ERROR_INVALID;
 }
 
 static int r82xx_write_reg_mask(struct r82xx_priv *priv, uint8_t reg, uint8_t val,
@@ -330,8 +331,10 @@ static int r82xx_read(struct r82xx_priv *priv, uint8_t reg, uint8_t *val, int le
 	priv->buf[0] = reg;
 
 	rc = rtlsdr_i2c_write_fn(priv->rtl_dev, priv->cfg->i2c_addr, priv->buf, 1);
-	if (rc < 1)
+	if (rc < 0)
 		return rc;
+	if (rc < 1)
+		return RTLSDR_ERROR_SHORT;
 
 	rc = rtlsdr_i2c_read_fn(priv->rtl_dev, priv->cfg->i2c_addr, p, len);
 
@@ -340,14 +343,14 @@ static int r82xx_read(struct r82xx_priv *priv, uint8_t reg, uint8_t *val, int le
 			   __FUNCTION__, rc, reg, len);
 		if (rc < 0)
 			return rc;
-		return -1;
+		return RTLSDR_ERROR_SHORT;
 	}
 
 	/* Copy data to the output buffer */
 	for (i = 0; i < len; i++)
 		val[i] = r82xx_bitrev(p[i]);
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 /*
@@ -490,7 +493,7 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
 
 	if (nint > ((128 / vco_power_ref) - 1)) {
 		fprintf(stderr, "[R82XX] No valid PLL values for %u Hz!\n", freq);
-		return -1;
+		return RTLSDR_ERROR_INVALID;
 	}
 
 	ni = (nint - 13) / 4;
@@ -549,7 +552,7 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
 	if (!(data[2] & 0x40)) {
 		fprintf(stderr, "[R82XX] PLL not locked!\n");
 		priv->has_lock = 0;
-		return 0;
+		return RTLSDR_SUCCESS;
 	}
 
 	priv->has_lock = 1;
@@ -754,7 +757,7 @@ static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq,
 		if (rc < 0)
 			return rc;
 	 }
-	 return 0;
+	 return RTLSDR_SUCCESS;
 }
 
 static int r82xx_set_tv_standard(struct r82xx_priv *priv,
@@ -911,7 +914,7 @@ static int r82xx_set_tv_standard(struct r82xx_priv *priv,
 	priv->type = type;
 	priv->bw = bw;
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 static int r82xx_read_gain(struct r82xx_priv *priv)
@@ -1010,7 +1013,7 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain)
 			return rc;
 	}
 
-	return 0;
+	return RTLSDR_SUCCESS;
 }
 
 /* Bandwidth contribution by low-pass filter. */
@@ -1131,7 +1134,7 @@ int r82xx_standby(struct r82xx_priv *priv)
 
 	/* If device was not initialized yet, don't need to standby */
 	if (!priv->init_done)
-		return 0;
+		return RTLSDR_ERROR_NOOP;
 
 	rc = r82xx_write_reg(priv, 0x06, 0xb1);
 	if (rc < 0)
@@ -1229,7 +1232,7 @@ static int r82xx_xtal_check(struct r82xx_priv *priv)
 	}
 
 	if (i == ARRAY_SIZE(r82xx_xtal_capacitor))
-		return -1;
+		return RTLSDR_ERROR_INVALID;
 
 	return r82xx_xtal_capacitor[i][1];
 }
-- 
2.11.0




More information about the osmocom-sdr mailing list