Interpret last four bytes of EEPROM as value in Hz using network byte
order and use it as default if it is between MIN_RTL_XTAL_FREQ and
MAX_RTL_XTAL_FREQ.
---
 src/librtlsdr.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index 2f5d90a..c986018 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -25,6 +25,9 @@
 #ifndef _WIN32
 #include <unistd.h>
 #define min(a, b) (((a) < (b)) ? (a) : (b))
+#include <arpa/inet.h>
+#else
+#include <WinSock2.h>
 #endif
 
 #include <libusb.h>
@@ -279,6 +282,7 @@ static rtlsdr_dongle_t known_devices[] = {
 #define BULK_TIMEOUT   0
 
 #define EEPROM_ADDR    0xa0
+#define EEPROM_SIZE    256
 
 enum usb_reg {
        USB_SYSCTL              = 0x2000,
@@ -1365,14 +1369,27 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
                goto err;
        }
 
-       dev->rtl_xtal = DEF_RTL_XTAL_FREQ;
-
        /* perform a dummy write, if it fails, reset the device */
        if (rtlsdr_write_reg(dev, USBB, USB_SYSCTL, 0x09, 1) < 0) {
                fprintf(stderr, "Resetting device...\n");
                libusb_reset_device(dev->devh);
        }
 
+       dev->rtl_xtal = DEF_RTL_XTAL_FREQ;
+
+       /* Allow for the last four bytes of the EEPROM to contain a
+          calibration frequency. */
+       {
+         uint32_t rtl_freq;
+
+         if (0 < rtlsdr_read_eeprom(dev, (void *)&rtl_freq, EEPROM_SIZE-4, 4))
+           rtl_freq = ntohl(rtl_freq);
+           if (rtl_freq >= MIN_RTL_XTAL_FREQ && rtl_freq <= MAX_RTL_XTAL_FREQ) 
{
+             fprintf(stderr, "Found valid XTAL calibration in EEPROM: %u Hz\n",
+                     dev->rtl_xtal = rtl_freq);
+           }
+       }
+
        rtlsdr_init_baseband(dev);
        dev->dev_lost = 0;
 
-- 
1.7.10.4


Reply via email to