DLL wrapper for RTL-SDR

Just starting out? Need help? Post your questions and find answers here.
User avatar
vertexview
User
User
Posts: 28
Joined: Thu Jan 25, 2024 8:33 am
Location: France

DLL wrapper for RTL-SDR

Post by vertexview »

Hello,
I am trying to create a librtlsdr.dll wrapper to control a USB SDR (Software Defined Radio) dongle radio receiver
Many open source applications exist regarding the use of this type of receiver, but for the moment I have not yet seen any in Purebasic.

I was able to successfully test an ADSB receiver (synchronous mode reception, terminal type) in Free Pascal, initially developed in Delphi XE, after converting the files in the Lazarus 3.0 IDE.
This project includes a relatively simple wrapper file for the hardware access dll. This main DLL, associated with two other dependent ones (libusb-1.0.dll, libwinpthread-1.dll), is used for the majority of SDR applications using RTL-SDR receivers.
I want to make a similar wrapper for Purebasic.

. RTL-SDR information: https://www.rtl-sdr.com/about-rtl-sdr/
. Osmocom project: https://osmocom.org/projects/rtl-sdr/wiki
. Github driver sources: https://github.com/osmocom/rtl-sdr
. ADSB receiver example in DELPHI/PASCAL: https://sourceforge.net/projects/rtl-ad ... -xe8-port/
. Last Windows drivers builds: https://ftp.osmocom.org/binaries/windows/rtl-sdr/

From several posts, read in the French and English forums, I was able to create a wrapper framework, but I mainly stumble on the use of pointers to have a functional set.
On the other hand, I was able to test and use a wrapper for the VLC DLL in a simplified Purebasic player application, but my understanding of the source files remains problematic...

Here is the current development for SDR hardware. The wrapper compiles without anomaly, but it only allows processing 2 functions of the DLL, counting the RTL-SDR keys inserted on USB ports and retrieving the key name.
I welcome any information to move forward on this subject in order to unlock the main SDR control functions (frequency, bandwidth, gain, data buffer, etc.).

Libsdr.pbi wrapper file

Code: Select all

EnableExplicit

; -------  Structure for SDR device from C header rtlsdr.h
; struct rtlsdr_dev {
; 	libusb_context *ctx;
; 	struct libusb_device_handle *devh;
; 	uint32_t xfer_buf_num;
; 	uint32_t xfer_buf_len;
; 	struct libusb_transfer **xfer;
; 	unsigned char **xfer_buf;
; 	rtlsdr_read_async_cb_t cb;
; 	void *cb_ctx;
; 	enum rtlsdr_async_status async_status;
; 	int async_cancel;
; 	int use_zerocopy;
; 	/* rtl demod context */
; 	uint32_t rate; /* Hz */
; 	uint32_t rtl_xtal; /* Hz */
; 	int fir[FIR_LEN];
; 	int direct_sampling;
; 	/* tuner context */
; 	enum rtlsdr_tuner tuner_type;
; 	rtlsdr_tuner_iface_t *tuner;
; 	uint32_t tun_xtal; /* Hz */
; 	uint32_t freq; /* Hz */
; 	uint32_t bw;
; 	uint32_t offs_freq; /* Hz */
; 	int corr; /* ppm */
; 	int gain; /* tenth dB */
; 	struct e4k_state e4k_s;
; 	struct r82xx_config r82xx_c;
; 	struct r82xx_priv r82xx_p;
; 	/* status */
; 	int dev_lost;
; 	int driver_active;
; 	unsigned int xfer_errors;
; 	char manufact[256];
; 	char product[256];
; };

Structure rtlsdr_dev_t 
  ; content
EndStructure 

Structure rtlsdr_read_async_cb_t
  ; content
EndStructure

Enumeration rtlsdr_tuner_t
	#RTLSDR_TUNER_UNKNOWN = 0
	#RTLSDR_TUNER_E4000   = 1
	#RTLSDR_TUNER_FC0012  = 2
	#RTLSDR_TUNER_FC0013  = 3
	#RTLSDR_TUNER_FC2580  = 4
	#RTLSDR_TUNER_R820T   = 5
	#RTLSDR_TUNER_R828D   = 6
EndEnumeration 

; -------  Variable definitions
Global dev.rtlsdr_dev_t
Global *dev
Global cb.rtlsdr_read_async_cb_t
Global manufact.s
Global *manufact
Global product.s
Global *product
Global serial.s
Global *serial
Global *gains
Global *rtl_freq
Global *tuner_freq
Global *data
Global *ctx
Global index.l=0
Global freq.l=0
Global on.i=0
Global buf_num.l=0
Global buf_len.l=0
Global *data=0
Global offset.l=0
Global len.i=0
Global gpio.i=0
Global ppm.i=0
Global rate.l=0
Global bw.l=0
Global gain.i=0
Global manual.i=0
Global stage.i=0
Global rtl_freq.i=0
Global tuner_freq.i=0
Global n_read.i=0

; ------- Prototype parameters specifications
; RTLSDR_API int rtlsdr_cancel_async(rtlsdr_dev_t *dev);  
  Prototype.l proto_rtlsdr_cancel_async(*dev)
; RTLSDR_API int rtlsdr_close(rtlsdr_dev_t *dev);
  Prototype.l proto_rtlsdr_close(*dev)
; RTLSDR_API uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev);
  Prototype.l proto_rtlsdr_get_center_freq(*dev)
; RTLSDR_API uint32_t rtlsdr_get_device_count(void);
  Prototype.l proto_rtlsdr_get_device_count()
; RTLSDR_API const char* rtlsdr_get_device_name(uint32_t index);
  Prototype proto_rtlsdr_get_device_name(index.l)
; RTLSDR_API int rtlsdr_get_device_usb_strings(uint32_t index, char *manufact, char *product, char *serial);
  Prototype.l proto_rtlsdr_get_device_usb_strings(index.l, *manufact, *product, *serial)
; RTLSDR_API int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on);
  Prototype.l proto_rtlsdr_get_direct_sampling(*dev, on.i)
; RTLSDR_API int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev);
  Prototype.l proto_rtlsdr_get_freq_correction(*dev)
; RTLSDR_API int rtlsdr_get_index_by_serial(const char *serial);
  Prototype.l proto_rtlsdr_get_index_by_serial(*serial)
; RTLSDR_API int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on);
  Prototype.l proto_rtlsdr_get_offset_tuning(*dev, on.i)
; RTLSDR_API uint32_t rtlsdr_get_sample_rate(rtlsdr_dev_t *dev);
  Prototype.l proto_rtlsdr_get_sample_rate(*dev)
; RTLSDR_API int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev);
  Prototype.l proto_rtlsdr_get_tuner_gain(*dev)
; RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains);
  Prototype.l proto_rtlsdr_get_tuner_gains(*dev, *gains)
; RTLSDR_API enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev);
  Prototype proto_rtlsdr_get_tuner_type(*dev)
; RTLSDR_API int rtlsdr_get_usb_strings(rtlsdr_dev_t *dev, char *manufact, char *product, char *serial);
  Prototype.l proto_rtlsdr_get_usb_strings(*dev, *manufact, *product, *serial)
; RTLSDR_API int rtlsdr_get_xtal_freq(rtlsdr_dev_t *dev, uint32_t *rtl_freq, uint32_t *tuner_freq);
  Prototype.l proto_rtlsdr_get_xtal_freq(*dev, *rtl_freq, *tuner_freq)
; RTLSDR_API int rtlsdr_open(rtlsdr_dev_t **dev, uint32_t index);
  Prototype.l proto_rtlsdr_open(*dev, index.l)
; RTLSDR_API int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, uint32_t buf_num, uint32_t buf_len);
  Prototype.l proto_rtlsdr_read_async(*dev, cb, *ctx, buf_num.l, buf_len.i)
; RTLSDR_API int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16_t len);
  Prototype.l proto_rtlsdr_read_eeprom(*dev, *data, offset.l, len.i)
; RTLSDR_API int rtlsdr_read_sync(rtlsdr_dev_t *dev, void *buf, int len, int *n_read);
  Prototype.l proto_rtlsdr_read_sync(*dev, *buf, len.i, *n_read)
; RTLSDR_API int rtlsdr_reset_buffer(rtlsdr_dev_t *dev);
  Prototype.l proto_rtlsdr_reset_buffer(*dev)
; RTLSDR_API int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on);
  Prototype.l proto_rtlsdr_set_agc_mode(*dev, on.i)
; RTLSDR_API int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on);
  Prototype.l proto_rtlsdr_set_bias_tee(*dev, on.i)
; RTLSDR_API int rtlsdr_set_bias_tee_gpio(rtlsdr_dev_t *dev, int gpio, int on);
  Prototype.l proto_rtlsdr_set_bias_tee_gpio(*dev, gpio.i, on.i)
; RTLSDR_API int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq);
  Prototype.l proto_rtlsdr_set_center_freq(*dev, freq.l)
; RTLSDR_API int rtlsdr_get_direct_sampling(rtlsdr_dev_t *dev);
  Prototype.l proto_rtlsdr_set_direct_sampling(*dev)
; RTLSDR_API int rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm);
  Prototype.l proto_rtlsdr_set_freq_correction(*dev, ppm.i)
; RTLSDR_API int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on);
  Prototype.l proto_rtlsdr_set_offset_tuning(*dev, on.i)
; RTLSDR_API int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t rate);
  Prototype.l proto_rtlsdr_set_sample_rate(*dev, rate.l)
; RTLSDR_API int rtlsdr_set_testmode(rtlsdr_dev_t *dev, int on);
  Prototype.l proto_rtlsdr_set_testmode(*dev, on.i)
; RTLSDR_API int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, uint32_t bw);
  Prototype.l proto_rtlsdr_set_tuner_bandwidth(*dev, bw.l)
; RTLSDR_API int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain);
  Prototype.l proto_rtlsdr_set_tuner_gain(*dev, gain.i)
; RTLSDR_API int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int manual);
  Prototype.l proto_rtlsdr_set_tuner_gain_mode(*dev, manual.i)
; RTLSDR_API int rtlsdr_set_tuner_if_gain(rtlsdr_dev_t *dev, int stage, int gain);
  Prototype.l proto_rtlsdr_set_tuner_if_gain(*dev, stage.i, gain.i)
; RTLSDR_API int rtlsdr_set_xtal_freq(rtlsdr_dev_t *dev, uint32_t rtl_freq, uint32_t tuner_freq);
  Prototype.l proto_rtlsdr_set_xtal_freq(*dev, rtl_freq.l, tuner_freq.l)
; RTLSDR_API int rtlsdr_wait_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx);
  Prototype.l proto_rtlsdr_wait_async(*dev, cb, *ctx)
; RTLSDR_API int rtlsdr_write_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16_t len);
  Prototype.l proto_rtlsdr_write_eeprom(*dev, *data, offset.l, len.i)
  
; ------- Function pointer declaration with prototype type specification  
Global rtlsdr_cancel_async.proto_rtlsdr_cancel_async
Global rtlsdr_close.proto_rtlsdr_close
Global rtlsdr_get_center_freq.proto_rtlsdr_get_center_freq
Global rtlsdr_get_device_count.proto_rtlsdr_get_device_count
Global rtlsdr_get_device_name.proto_rtlsdr_get_device_name
Global rtlsdr_get_device_usb_strings.proto_rtlsdr_get_device_usb_strings
Global rtlsdr_get_direct_sampling.proto_rtlsdr_get_direct_sampling
Global rtlsdr_get_freq_correction.proto_rtlsdr_get_freq_correction
Global rtlsdr_get_index_by_serial.proto_rtlsdr_get_index_by_serial
Global rtlsdr_get_offset_tuning.proto_rtlsdr_get_offset_tuning
Global rtlsdr_get_sample_rate.proto_rtlsdr_get_sample_rate
Global rtlsdr_get_tuner_gain.proto_rtlsdr_get_tuner_gain
Global rtlsdr_get_tuner_gains.proto_rtlsdr_get_tuner_gains
Global rtlsdr_get_tuner_type.proto_rtlsdr_get_tuner_type
Global rtlsdr_get_usb_strings.proto_rtlsdr_get_usb_strings
Global rtlsdr_get_xtal_freq.proto_rtlsdr_get_xtal_freq
Global rtlsdr_open.proto_rtlsdr_open
Global rtlsdr_read_async.proto_rtlsdr_read_async
Global rtlsdr_read_eeprom.proto_rtlsdr_read_eeprom
Global rtlsdr_read_sync.proto_rtlsdr_read_sync
Global rtlsdr_reset_buffer.proto_rtlsdr_reset_buffer
Global rtlsdr_set_agc_mode.proto_rtlsdr_set_agc_mode
Global rtlsdr_set_bias_tee.proto_rtlsdr_set_bias_tee
Global rtlsdr_set_bias_tee_gpio.proto_rtlsdr_set_bias_tee_gpio
Global rtlsdr_set_center_freq.proto_rtlsdr_set_center_freq
Global rtlsdr_set_direct_sampling.proto_rtlsdr_set_direct_sampling
Global rtlsdr_set_freq_correction.proto_rtlsdr_set_freq_correction
Global rtlsdr_set_offset_tuning.proto_rtlsdr_set_offset_tuning
Global rtlsdr_set_sample_rate.proto_rtlsdr_set_sample_rate
Global rtlsdr_set_testmode.proto_rtlsdr_set_testmode
Global rtlsdr_set_tuner_bandwidth.proto_rtlsdr_set_tuner_bandwidth
Global rtlsdr_set_tuner_gain.proto_rtlsdr_set_tuner_gain
Global rtlsdr_set_tuner_gain_mode.proto_rtlsdr_set_tuner_gain_mode
Global rtlsdr_set_tuner_if_gain.proto_rtlsdr_set_tuner_if_gain
Global rtlsdr_set_xtal_freq.proto_rtlsdr_set_xtal_freq
Global rtlsdr_wait_async.proto_rtlsdr_wait_async
Global rtlsdr_write_eeprom.proto_rtlsdr_write_eeprom

; ------- DLL Loading with functions pointers
Procedure.i rtlsdr_LoadDLL()
  Protected hDLL.i

  hDLL = OpenLibrary(#PB_Any, "librtlsdr.dll")
  If hDLL <> 0
    rtlsdr_cancel_async = GetFunction(hDLL, "rtlsdr_cancel_async")
    rtlsdr_close = GetFunction(hDLL, "rtlsdr_close")
    rtlsdr_get_center_freq = GetFunction(hDLL, "rtlsdr_get_center_freq")
    rtlsdr_get_device_count = GetFunction(hDLL, "rtlsdr_get_device_count")
    rtlsdr_get_device_name = GetFunction(hDLL, "rtlsdr_get_device_name")
    rtlsdr_get_device_usb_strings = GetFunction(hDLL, "rtlsdr_get_device_usb_strings")
    rtlsdr_get_direct_sampling = GetFunction(hDLL, "rtlsdr_get_direct_sampling")
    rtlsdr_get_freq_correction = GetFunction(hDLL, "rtlsdr_get_freq_correction")
    rtlsdr_get_index_by_serial = GetFunction(hDLL, "rtlsdr_get_index_by_serial")
    rtlsdr_get_offset_tuning = GetFunction(hDLL, "rtlsdr_get_offset_tuning")
    rtlsdr_get_sample_rate = GetFunction(hDLL, "rtlsdr_get_sample_rate")
    rtlsdr_get_tuner_gain = GetFunction(hDLL, "rtlsdr_get_tuner_gain")
    rtlsdr_get_tuner_gains = GetFunction(hDLL, "rtlsdr_get_tuner_gains")
    rtlsdr_get_tuner_type = GetFunction(hDLL, "rtlsdr_get_tuner_type")
    rtlsdr_get_usb_strings = GetFunction(hDLL, "rtlsdr_get_usb_strings")
    rtlsdr_get_xtal_freq = GetFunction(hDLL, "rtlsdr_get_xtal_freq")
    rtlsdr_open = GetFunction(hDLL, "rtlsdr_open")
    rtlsdr_read_async = GetFunction(hDLL, "rtlsdr_read_async")
    rtlsdr_read_eeprom = GetFunction(hDLL, "rtlsdr_read_eeprom")
    rtlsdr_read_sync = GetFunction(hDLL, "rtlsdr_read_sync")
    rtlsdr_reset_buffer = GetFunction(hDLL, "rtlsdr_reset_buffer")
    rtlsdr_set_agc_mode = GetFunction(hDLL, "rtlsdr_set_agc_mode")
    rtlsdr_set_bias_tee = GetFunction(hDLL, "rtlsdr_set_bias_tee")
    rtlsdr_set_bias_tee_gpio = GetFunction(hDLL, "rtlsdr_set_bias_tee_gpio")
    rtlsdr_set_center_freq = GetFunction(hDLL, "rtlsdr_set_center_freq")
    rtlsdr_set_direct_sampling = GetFunction(hDLL, "rtlsdr_set_direct_sampling")
    rtlsdr_set_freq_correction = GetFunction(hDLL, "rtlsdr_set_freq_correction")
    rtlsdr_set_offset_tuning = GetFunction(hDLL, "rtlsdr_set_offset_tuning")
    rtlsdr_set_sample_rate = GetFunction(hDLL, "rtlsdr_set_sample_rate")
    rtlsdr_set_testmode = GetFunction(hDLL, "rtlsdr_set_testmode")
    rtlsdr_set_tuner_bandwidth = GetFunction(hDLL, "rtlsdr_set_tuner_bandwidth")
    rtlsdr_set_tuner_gain = GetFunction(hDLL, "rtlsdr_set_tuner_gain")
    rtlsdr_set_tuner_gain_mode = GetFunction(hDLL, "rtlsdr_set_tuner_gain_mode")
    rtlsdr_set_tuner_if_gain = GetFunction(hDLL, "rtlsdr_set_tuner_if_gain")
    rtlsdr_set_xtal_freq = GetFunction(hDLL, "rtlsdr_set_xtal_freq")
    rtlsdr_wait_async = GetFunction(hDLL, "rtlsdr_wait_async")
    rtlsdr_write_eeprom = GetFunction(hDLL, "rtlsdr_write_eeprom")
    ProcedureReturn hDLL
  EndIf
  ProcedureReturn #False
EndProcedure
FunctionCall.pb test program.

Code: Select all

IncludeFile "libsdr.pbi"
EnableExplicit

CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
    CompilerError "Windows only compilation"
  CompilerEndIf
  
; -------  Structures
  Structure info_tuner_t
    manufact.s
    Product.s
    serial.s
  EndStructure  
  
; -------  Variable definitions
  Global counter.l=0
  Global sdr_Name.s=""
  Global myfreq.l
  Global rtl_sdr_tuner.s
  Global mytuner.info_tuner_t
  Global tuner_type.l=0

; ------- Functions list inside DLL
; If OpenLibrary(1,"librtlsdr.dll")
;   ExamineLibraryFunctions(1)
;   While NextLibraryFunction()
;     Debug LibraryFunctionName()
;   Wend
; EndIf

; ------- SDR Helpers procedures
Procedure.s safePeekS(ps, len=-1)
	If ps:ProcedureReturn PeekS(ps, len, #PB_UTF8):EndIf
EndProcedure

Procedure.l open_sdr(index.l)
  rtlsdr_open(dev, index.l)
EndProcedure

Procedure.l get_device_count()
  counter.l=rtlsdr_get_device_count()
EndProcedure

Procedure.s get_device_name(index.l)
  sdr_name.s=safePeekS(rtlsdr_get_device_name(index.l), -1)
EndProcedure

Procedure.l get_tuner_type()
  tuner_type.l=rtlsdr_get_tuner_type(*dev)
EndProcedure

Procedure set_center_frequency(freq.l)
  rtlsdr_set_center_freq(*dev, freq.l)
EndProcedure

Procedure.l get_center_frequency()
  myfreq.l=rtlsdr_get_center_freq(*dev)
EndProcedure

Procedure close_sdr()
  rtlsdr_close(*dev)
EndProcedure

Procedure get_usb_strings(index.l)
  rtlsdr_get_device_usb_strings(index.l, *manufact, *product, *serial)
  manufact.s=safePeekS(*manufact, -1)
  product.s=safePeekS(*product, -1)
  serial.s=safePeekS(*serial, -1)
EndProcedure

; ------- SDR Tests access
  If rtlsdr_LoadDll()
    open_sdr(0)
    get_device_count()
    get_device_name(0)
    get_tuner_type()
    set_center_frequency(92200000)
    get_center_frequency()
    get_usb_strings(0)
    MessageRequester ("SDR Info", "SDR Count: "+ Str(counter.l) + Chr(10) + Chr(13) + "SDR Name: " + sdr_name.s, #PB_MessageRequester_Ok)
    MessageRequester ("SDR Info", "SDR Type: "+ tuner_type.l, #PB_MessageRequester_Ok)
    MessageRequester ("SDR Info", "Frequency: "+ myfreq.l +Chr(10) + Chr(13) + "Device: " + manufact.s + "/" + product.s + "/" + serial.s, #PB_MessageRequester_Ok)
    close_sdr()
  EndIf
End   
Thanks
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DLL wrapper for RTL-SDR

Post by infratec »

You need

Code: Select all

PrototypeC
rtlsdr_read_async_cb_t is not a structure, it is a prototype for a callback

Code: Select all

PrototypeC rtlsdr_read_async_cb_t(*buf, len.l, *ctx)
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DLL wrapper for RTL-SDR

Post by infratec »

You can try this:

Code: Select all

;
; Osmocom project: https://osmocom.org/projects/rtl-sdr/wiki
; Github driver sources: https://github.com/osmocom/rtl-sdr
; Last Windows drivers builds: https://ftp.osmocom.org/binaries/windows/rtl-sdr/
;


CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf


Enumeration e4k_band
  #E4K_BAND_VHF2
  #E4K_BAND_VHF3
  #E4K_BAND_UHF
  #E4K_BAND_L
EndEnumeration
Macro e4k_band
  i
EndMacro


#NUM_REGS	= 30

Enumeration r82xx_chip
  #CHIP_R820T
  #CHIP_R620D
  #CHIP_R828D
  #CHIP_R828
  #CHIP_R828S
  #CHIP_R820C
EndEnumeration
Macro r82xx_chip
  i
EndMacro

Enumeration r82xx_xtal_cap_value
  #XTAL_LOW_CAP_30P
  #XTAL_LOW_CAP_20P
  #XTAL_LOW_CAP_10P
  #XTAL_LOW_CAP_0P
  #XTAL_HIGH_CAP_0P
EndEnumeration
Macro r82xx_xtal_cap_value
  i
EndMacro

Enumeration r82xx_tuner_type
  #TUNER_RADIO = 1
  #TUNER_ANALOG_TV
  #TUNER_DIGITAL_TV
EndEnumeration
Macro r82xx_tuner_type
  i
EndMacro



Enumeration rtlsdr_tuner
  #RTLSDR_TUNER_UNKNOWN
  #RTLSDR_TUNER_E4000
  #RTLSDR_TUNER_FC0012
  #RTLSDR_TUNER_FC0013
  #RTLSDR_TUNER_FC2580
  #RTLSDR_TUNER_R820T
  #RTLSDR_TUNER_R828D
EndEnumeration
Macro rtlsdr_tuner_t
  i
EndMacro

Enumeration rtlsdr_async_status
  #RTLSDR_INACTIVE
  #RTLSDR_CANCELING
  #RTLSDR_RUNNING
EndEnumeration
Macro rtlsdr_async_status
  i
EndMacro


#FIR_LEN = 16

PrototypeC.l Prototype_init()
PrototypeC.l Prototype_exit()
PrototypeC.l Prototype_set_freq(*p, freq.l)
PrototypeC.l Prototype_set_bw(*p, bw.l)
PrototypeC.l Prototype_set_gain(*p, gain.l)
PrototypeC.l Prototype_set_if_gain(*p, stage.l, gain.l)
PrototypeC.l Prototype_set_gain_mode(*p, manual.l)


Structure rtlsdr_tuner_iface Align #PB_Structure_AlignC
  ; tuner Interface
  init.Prototype_init
  exit.Prototype_exit
  set_freq.Prototype_set_freq
  set_bw.Prototype_set_bw
  set_gain.Prototype_set_gain
  set_if_gain.Prototype_set_if_gain
  set_gain_mode.Prototype_set_gain_mode
EndStructure
Macro rtlsdr_tuner_iface_t
  rtlsdr_tuner_iface
EndMacro


Structure e4k_pll_params Align #PB_Structure_AlignC
  fosc.l
  intended_flo.l
  flo.l
  x.u
  z.a
  r.a
  r_idx.a
  threephase.a
EndStructure


Structure e4k_state Align #PB_Structure_AlignC
  *i2c_dev
  i2c_addr.a
  band.e4k_band
  vco.e4k_pll_params
  *rtl_dev
EndStructure


Structure r82xx_config Align #PB_Structure_AlignC
  i2c_addr.a
  xtal.l
  rafael_chip.r82xx_chip
  max_i2c_msg_len.l
  use_predetect.l
EndStructure


Structure r82xx_priv Align #PB_Structure_AlignC
  *cfg.r82xx_config
  
  regs.a[#NUM_REGS]
  buf.a[#NUM_REGS + 1]
  xtal_cap_sel.r82xx_xtal_cap_value
  pll.u           ;	kHz
  int_freq.l
  fil_cal_code.a
  input.a
  has_lock.l
  init_done.l
  
  ; Store current mode
  delsys.l
  type.r82xx_tuner_type
  
  bw.l  ;	in MHz
  
  *rtl_dev
EndStructure



PrototypeC rtlsdr_read_async_cb_t(*buf, len.l, *ctx)

Structure rtlsdr_dev Align #PB_Structure_AlignC
  *ctx
  *devh
  xfer_buf_num.l
  xfer_buf_len.l
  *xfer
  *xfer_buf
  cb.rtlsdr_read_async_cb_t
  *cb_ctx
  async_status.rtlsdr_async_status
  async_cancel.l
  use_zerocopy.l
  ; rtl demod context
  rate.l      ; Hz
  rtl_xtal.l  ; Hz
  fir.l[#FIR_LEN]
  direct_sampling.l
  ; tuner context
  tuner_type.rtlsdr_tuner_t
  *tuner.rtlsdr_tuner_iface_t
  tun_xtal.l  ; Hz
  freq.l      ; Hz
  bw.l
  offs_freq.l ; Hz
  corr.l      ; ppm
  gain.l      ; tenth dB
  e4k_s.e4k_state
  r82xx_c.r82xx_config
  r82xx_p.r82xx_priv
  ; status
  dev_lost.l
  driver_active.l
  xfer_errors.l
  manufact.a[256]
  product.a[256]
EndStructure 
Macro rtlsdr_dev_t
  rtlsdr_dev
EndMacro


; ------- Prototype parameters specifications
PrototypeC.l proto_rtlsdr_cancel_async(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_close(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_get_center_freq(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_get_device_count()
PrototypeC proto_rtlsdr_get_device_name(index.l)
PrototypeC.l proto_rtlsdr_get_device_usb_strings(index.l, *manufact, *product, *serial)
PrototypeC.l proto_rtlsdr_get_direct_sampling(*dev.rtlsdr_dev_t, on.l)
PrototypeC.l proto_rtlsdr_get_freq_correction(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_get_index_by_serial(serial.p-utf8)
PrototypeC.l proto_rtlsdr_get_offset_tuning(*dev.rtlsdr_dev_t, on.l)
PrototypeC.l proto_rtlsdr_get_sample_rate(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_get_tuner_gain(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_get_tuner_gains(*dev.rtlsdr_dev_t, *gains)
PrototypeC proto_rtlsdr_get_tuner_type(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_get_usb_strings(*dev.rtlsdr_dev_t, *manufact, *product, *serial)
PrototypeC.l proto_rtlsdr_get_xtal_freq(*dev.rtlsdr_dev_t, *rtl_freq, *tuner_freq)
PrototypeC.l proto_rtlsdr_open(*pdev, index.l)
PrototypeC.l proto_rtlsdr_read_async(*dev.rtlsdr_dev_t, cb.rtlsdr_read_async_cb_t, *ctx, buf_num.l, buf_len.l)
PrototypeC.l proto_rtlsdr_read_eeprom(*dev.rtlsdr_dev_t, *data, offset.a, len.l)
PrototypeC.l proto_rtlsdr_read_sync(*dev.rtlsdr_dev_t, *buf, len.l, *n_read)
PrototypeC.l proto_rtlsdr_reset_buffer(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_set_agc_mode(*dev.rtlsdr_dev_t, on.l)
PrototypeC.l proto_rtlsdr_set_bias_tee(*dev.rtlsdr_dev_t, on.l)
PrototypeC.l proto_rtlsdr_set_bias_tee_gpio(*dev.rtlsdr_dev_t, gpio.l, on.l)
PrototypeC.l proto_rtlsdr_set_center_freq(*dev.rtlsdr_dev_t, freq.l)
PrototypeC.l proto_rtlsdr_set_direct_sampling(*dev.rtlsdr_dev_t)
PrototypeC.l proto_rtlsdr_set_freq_correction(*dev.rtlsdr_dev_t, ppm.l)
PrototypeC.l proto_rtlsdr_set_offset_tuning(*dev.rtlsdr_dev_t, on.l)
PrototypeC.l proto_rtlsdr_set_sample_rate(*dev.rtlsdr_dev_t, rate.l)
PrototypeC.l proto_rtlsdr_set_testmode(*dev.rtlsdr_dev_t, on.l)
PrototypeC.l proto_rtlsdr_set_tuner_bandwidth(*dev.rtlsdr_dev_t, bw.l)
PrototypeC.l proto_rtlsdr_set_tuner_gain(*dev.rtlsdr_dev_t, gain.l)
PrototypeC.l proto_rtlsdr_set_tuner_gain_mode(*dev.rtlsdr_dev_t, manual.l)
PrototypeC.l proto_rtlsdr_set_tuner_if_gain(*dev.rtlsdr_dev_t, stage.l, gain.l)
PrototypeC.l proto_rtlsdr_set_xtal_freq(*dev.rtlsdr_dev_t, rtl_freq.l, tuner_freq.l)
PrototypeC.l proto_rtlsdr_wait_async(*dev.rtlsdr_dev_t, cb.rtlsdr_read_async_cb_t, *ctx)
PrototypeC.l proto_rtlsdr_write_eeprom(*dev.rtlsdr_dev_t, *data, offset.a, len.u)

; ------- Function pointer declaration with prototype type specification  
Global rtlsdr_cancel_async.proto_rtlsdr_cancel_async
Global rtlsdr_close.proto_rtlsdr_close
Global rtlsdr_get_center_freq.proto_rtlsdr_get_center_freq
Global rtlsdr_get_device_count.proto_rtlsdr_get_device_count
Global rtlsdr_get_device_name.proto_rtlsdr_get_device_name
Global rtlsdr_get_device_usb_strings.proto_rtlsdr_get_device_usb_strings
Global rtlsdr_get_direct_sampling.proto_rtlsdr_get_direct_sampling
Global rtlsdr_get_freq_correction.proto_rtlsdr_get_freq_correction
Global rtlsdr_get_index_by_serial.proto_rtlsdr_get_index_by_serial
Global rtlsdr_get_offset_tuning.proto_rtlsdr_get_offset_tuning
Global rtlsdr_get_sample_rate.proto_rtlsdr_get_sample_rate
Global rtlsdr_get_tuner_gain.proto_rtlsdr_get_tuner_gain
Global rtlsdr_get_tuner_gains.proto_rtlsdr_get_tuner_gains
Global rtlsdr_get_tuner_type.proto_rtlsdr_get_tuner_type
Global rtlsdr_get_usb_strings.proto_rtlsdr_get_usb_strings
Global rtlsdr_get_xtal_freq.proto_rtlsdr_get_xtal_freq
Global rtlsdr_open.proto_rtlsdr_open
Global rtlsdr_read_async.proto_rtlsdr_read_async
Global rtlsdr_read_eeprom.proto_rtlsdr_read_eeprom
Global rtlsdr_read_sync.proto_rtlsdr_read_sync
Global rtlsdr_reset_buffer.proto_rtlsdr_reset_buffer
Global rtlsdr_set_agc_mode.proto_rtlsdr_set_agc_mode
Global rtlsdr_set_bias_tee.proto_rtlsdr_set_bias_tee
Global rtlsdr_set_bias_tee_gpio.proto_rtlsdr_set_bias_tee_gpio
Global rtlsdr_set_center_freq.proto_rtlsdr_set_center_freq
Global rtlsdr_set_direct_sampling.proto_rtlsdr_set_direct_sampling
Global rtlsdr_set_freq_correction.proto_rtlsdr_set_freq_correction
Global rtlsdr_set_offset_tuning.proto_rtlsdr_set_offset_tuning
Global rtlsdr_set_sample_rate.proto_rtlsdr_set_sample_rate
Global rtlsdr_set_testmode.proto_rtlsdr_set_testmode
Global rtlsdr_set_tuner_bandwidth.proto_rtlsdr_set_tuner_bandwidth
Global rtlsdr_set_tuner_gain.proto_rtlsdr_set_tuner_gain
Global rtlsdr_set_tuner_gain_mode.proto_rtlsdr_set_tuner_gain_mode
Global rtlsdr_set_tuner_if_gain.proto_rtlsdr_set_tuner_if_gain
Global rtlsdr_set_xtal_freq.proto_rtlsdr_set_xtal_freq
Global rtlsdr_wait_async.proto_rtlsdr_wait_async
Global rtlsdr_write_eeprom.proto_rtlsdr_write_eeprom

Global librtlsdr.i

; ------- DLL Loading with functions pointers
Procedure.i UseLibrtlsdr()
  
  If Not IsLibrary(librtlsdr)
    
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        librtlsdr = OpenLibrary(#PB_Any, "librtlsdr.dll")
      CompilerCase #PB_OS_Linux
        librtlsdr = OpenLibrary(#PB_Any, "librtlsdr.so")
      CompilerCase #PB_OS_MacOS
        librtlsdr = OpenLibrary(#PB_Any, "librtlsdr.dylib")
    CompilerEndSelect
    If librtlsdr <> 0
      rtlsdr_cancel_async = GetFunction(librtlsdr, "rtlsdr_cancel_async")
      rtlsdr_close = GetFunction(librtlsdr, "rtlsdr_close")
      rtlsdr_get_center_freq = GetFunction(librtlsdr, "rtlsdr_get_center_freq")
      rtlsdr_get_device_count = GetFunction(librtlsdr, "rtlsdr_get_device_count")
      rtlsdr_get_device_name = GetFunction(librtlsdr, "rtlsdr_get_device_name")
      rtlsdr_get_device_usb_strings = GetFunction(librtlsdr, "rtlsdr_get_device_usb_strings")
      rtlsdr_get_direct_sampling = GetFunction(librtlsdr, "rtlsdr_get_direct_sampling")
      rtlsdr_get_freq_correction = GetFunction(librtlsdr, "rtlsdr_get_freq_correction")
      rtlsdr_get_index_by_serial = GetFunction(librtlsdr, "rtlsdr_get_index_by_serial")
      rtlsdr_get_offset_tuning = GetFunction(librtlsdr, "rtlsdr_get_offset_tuning")
      rtlsdr_get_sample_rate = GetFunction(librtlsdr, "rtlsdr_get_sample_rate")
      rtlsdr_get_tuner_gain = GetFunction(librtlsdr, "rtlsdr_get_tuner_gain")
      rtlsdr_get_tuner_gains = GetFunction(librtlsdr, "rtlsdr_get_tuner_gains")
      rtlsdr_get_tuner_type = GetFunction(librtlsdr, "rtlsdr_get_tuner_type")
      rtlsdr_get_usb_strings = GetFunction(librtlsdr, "rtlsdr_get_usb_strings")
      rtlsdr_get_xtal_freq = GetFunction(librtlsdr, "rtlsdr_get_xtal_freq")
      rtlsdr_open = GetFunction(librtlsdr, "rtlsdr_open")
      rtlsdr_read_async = GetFunction(librtlsdr, "rtlsdr_read_async")
      rtlsdr_read_eeprom = GetFunction(librtlsdr, "rtlsdr_read_eeprom")
      rtlsdr_read_sync = GetFunction(librtlsdr, "rtlsdr_read_sync")
      rtlsdr_reset_buffer = GetFunction(librtlsdr, "rtlsdr_reset_buffer")
      rtlsdr_set_agc_mode = GetFunction(librtlsdr, "rtlsdr_set_agc_mode")
      rtlsdr_set_bias_tee = GetFunction(librtlsdr, "rtlsdr_set_bias_tee")
      rtlsdr_set_bias_tee_gpio = GetFunction(librtlsdr, "rtlsdr_set_bias_tee_gpio")
      rtlsdr_set_center_freq = GetFunction(librtlsdr, "rtlsdr_set_center_freq")
      rtlsdr_set_direct_sampling = GetFunction(librtlsdr, "rtlsdr_set_direct_sampling")
      rtlsdr_set_freq_correction = GetFunction(librtlsdr, "rtlsdr_set_freq_correction")
      rtlsdr_set_offset_tuning = GetFunction(librtlsdr, "rtlsdr_set_offset_tuning")
      rtlsdr_set_sample_rate = GetFunction(librtlsdr, "rtlsdr_set_sample_rate")
      rtlsdr_set_testmode = GetFunction(librtlsdr, "rtlsdr_set_testmode")
      rtlsdr_set_tuner_bandwidth = GetFunction(librtlsdr, "rtlsdr_set_tuner_bandwidth")
      rtlsdr_set_tuner_gain = GetFunction(librtlsdr, "rtlsdr_set_tuner_gain")
      rtlsdr_set_tuner_gain_mode = GetFunction(librtlsdr, "rtlsdr_set_tuner_gain_mode")
      rtlsdr_set_tuner_if_gain = GetFunction(librtlsdr, "rtlsdr_set_tuner_if_gain")
      rtlsdr_set_xtal_freq = GetFunction(librtlsdr, "rtlsdr_set_xtal_freq")
      rtlsdr_wait_async = GetFunction(librtlsdr, "rtlsdr_wait_async")
      rtlsdr_write_eeprom = GetFunction(librtlsdr, "rtlsdr_write_eeprom")
    EndIf
    
  EndIf
  
  ProcedureReturn librtlsdr
  
EndProcedure


Procedure.l verbose_device_search(s.s="")
  
  Protected.l i, device_count, device, offset
  Protected Dim vendor.a(256)
  Protected Dim product.a(256)
  Protected Dim serial.a(256)
  
  
  device = -1
  
  device_count = rtlsdr_get_device_count()
  If device_count = 0
    Debug "No supported devices found."
    ProcedureReturn -1
  EndIf
  
  Debug "Found " + Str(device_count) + " device(s):"
  For i = 0 To device_count - 1
    rtlsdr_get_device_usb_strings(i, @vendor(0), @product(0), @serial(0))
    Debug "  " + Str(i) + ":  " + PeekS(@vendor(0), -1, #PB_UTF8) + ", " + PeekS(@product(0), -1, #PB_UTF8) + ", " + PeekS(@serial(0), -1, #PB_UTF8)
  Next i
  Debug ""
  
  If s <> ""
    ; does string look like raw id number
    device = Val(s)
    If Len(s) = Len(Str(device)) And device >= 0 And device < device_count
      Debug "Using device " + Str(device) + ": " + PeekS(rtlsdr_get_device_name(device), -1, #PB_UTF8)
    EndIf
  EndIf
  
  If device = -1
    ; does string exact match a serial
    For i = 0 To device_count - 1
      rtlsdr_get_device_usb_strings(i, @vendor(0), @product(0), @serial(0))
      If s <> PeekS(@serial(0), -1, #PB_UTF8)
        Continue
      EndIf
      device = i
      Debug "Using device " + Str(device) + ": " + PeekS(rtlsdr_get_device_name(device), -1, #PB_UTF8)
    Next i
  EndIf
  
  If device = -1
    ; does string prefix match a serial
    For i = 0 To device_count - 1
      rtlsdr_get_device_usb_strings(i, @vendor(0), @product(0), @serial(0))
      If FindString(PeekS(@serial(0), -1, #PB_UTF8), s) = 0
        Continue
      EndIf
      device = i
      Debug "Using device " + Str(device) + ": " + PeekS(rtlsdr_get_device_name(device), -1, #PB_UTF8)
      ProcedureReturn device
    Next i
  EndIf
  
  If device = -1
    Debug "No matching devices found."
  EndIf
  
  ProcedureReturn device
  
EndProcedure




;-Demo
CompilerIf #PB_Compiler_IsMainFile
  
  ; -------  Variable definitions
  Define.l counter, myfreq, tuner_type, dev_index
  Define sdr_Name.s
  Define *dev.rtlsdr_dev_t
  Define *manufact, *product, *serial
  
  
  ;   Debug SizeOf(rtlsdr_dev)
  ;   Debug OffsetOf(rtlsdr_dev\direct_sampling)
  ;   Debug OffsetOf(rtlsdr_dev\gain)
  ;   Debug OffsetOf(rtlsdr_dev\e4k_s)
  ;   Debug OffsetOf(rtlsdr_dev\r82xx_c)
  ;   Debug OffsetOf(rtlsdr_dev\r82xx_p)
  ;   Debug OffsetOf(rtlsdr_dev\dev_lost)
  
  ; ------- SDR Tests access
  If UseLibrtlsdr()
    
    dev_index = verbose_device_search("")
    
    If rtlsdr_open(@*dev, dev_index) > 0
      counter = rtlsdr_get_device_count()
      sdr_name = PeekS(rtlsdr_get_device_name(dev_index), -1, #PB_UTF8)
      tuner_type = rtlsdr_get_tuner_type(*dev)
      
      MessageRequester ("SDR Info", "SDR Count: "+ Str(counter) + #LF$ + "SDR Name: " + sdr_name + #LF$ + "SDR Type: "+ Str(tuner_type))
      
      
      *manufact = AllocateMemory(256)
      *product = AllocateMemory(256)
      *serial = AllocateMemory(256)
      rtlsdr_get_device_usb_strings(dev_index, *manufact, *product, *serial)
      
      MessageRequester ("SDR Info", "Frequency: "+ Str(myfreq) + #CRLF$ + "Device: " + PeekS(*manufact, -1, #PB_UTF8) + "/" + PeekS(*product, -1, #PB_UTF8) + "/" + PeekS(*serial, -1, #PB_UTF8))
      
      FreeMemory(*serial)
      FreeMemory(*product)
      FreeMemory(*manufact)
      
      rtlsdr_set_center_freq(*dev, 92200000)
      myfreq = rtlsdr_get_center_freq(*dev)
      Debug "MyFreq: " + Str(myfreq)
      
      rtlsdr_close(*dev)
    Else
      Debug "Was not able to open a device"
    EndIf
  EndIf
  
CompilerEndIf
But I don't own a DVB stick and can not test it.
Last edited by infratec on Thu Jan 25, 2024 9:13 pm, edited 3 times in total.
User avatar
vertexview
User
User
Posts: 28
Joined: Thu Jan 25, 2024 8:33 am
Location: France

Re: DLL wrapper for RTL-SDR

Post by vertexview »

Thank you very much infratec for all your work.
Il will have a lot to analyze, understand, and learn about your code.

I tried it,... but something seems blocking the device initalization with the function rtlsdr_open(@*dev, 0).
No compilation error or warning message, but Debug box send "Was not able to open a device".

In the rtlsdr.h file (https://github.com/osmocom/rtl-sdr/blob ... /rtl-sdr.h) the API for opening a device is:
RTLSDR_API int rtlsdr_open(rtlsdr_dev_t **dev, uint32_t index);

I suppose that this ** syntax is related to multiple context management, depending on different USB connected devices.
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DLL wrapper for RTL-SDR

Post by infratec »

** is a pointer to a pointer

I use *dev (pointer) and use @*dev as parameter which is the address of the pointer aka pointer to the pointer.
This should be Ok.

Do you use the right dll? (x86 or x64)
Have you a working device connected?
User avatar
vertexview
User
User
Posts: 28
Joined: Thu Jan 25, 2024 8:33 am
Location: France

Re: DLL wrapper for RTL-SDR

Post by vertexview »

I realized new tests with two SDR sticks (RTL-SDR Blog v3 and RTL-SDR Blog v4) changing index value for SDR initialization: rtlsdr_open(@*dev, index.l)
. No initialization if index.l =0
. Ok if index.l equal or superior to 1 and one SDR is connected
. No initialization if index.l=1 and 2 SDR are connected
. OK if index.l=2 or superior with 2 SDR connected.

If initialization step is passed,
. rtlsdr_get_device_count() is OK
. rtlsdr_get_device_name(index.l) is OK. Index.l must be 0 if one SDR is connected. 0 or 1 if two SDR are connected
. rtlsdr_get_device_usb_strings(index.l, *manufact, *product, *serial) is now operational. Index.l must be 0 if one SDR is connected. 0 or 1 if two SDR are connected. *manufact, *product, *serial informations are found.

For now, rtlsdr_get_tuner_type(*dev)=0 and rtlsdr_get_center_freq(*dev)=0
I continue to test...
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DLL wrapper for RTL-SDR

Post by infratec »

Maybe the structure is not 100% correct.
I will check it.
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DLL wrapper for RTL-SDR

Post by infratec »

I missed one

Code: Select all

Align #PB_Structure_AlignC
added automatic device detection.

I modified the listing above.
User avatar
vertexview
User
User
Posts: 28
Joined: Thu Jan 25, 2024 8:33 am
Location: France

Re: DLL wrapper for RTL-SDR

Post by vertexview »

I tested the new code, and disabled the verbose_device_search procedure.
This one is not operative.
The "serial" information is not a serial number, or a unique device identifier. In my case it's the same value for the two sticks: 00000001.

Modification with 2 actives devices

Code: Select all

dev_index=2
    If rtlsdr_open(@*dev, dev_index) > 0
        .....
       sdr_name = PeekS(rtlsdr_get_device_name(dev_index-1), -1, #PB_UTF8)
       .....
       rtlsdr_get_device_usb_strings(dev_index-1, *manufact, *product, *serial) 

Same result with rtlsdr_get_tuner_type(*dev)=0 and rtlsdr_get_center_freq(*dev)=0
User avatar
vertexview
User
User
Posts: 28
Joined: Thu Jan 25, 2024 8:33 am
Location: France

Re: DLL wrapper for RTL-SDR

Post by vertexview »

SDR Serial is user-defined for third-party applications.
By default, it is set to 00000001 on all devices.

Example of SDR Serial number modification with the osmocom utility (rtl_eeprom.exe) provided in the dll package
https://www.youtube.com/watch?v=xGEDglwOHng
User avatar
vertexview
User
User
Posts: 28
Joined: Thu Jan 25, 2024 8:33 am
Location: France

Re: DLL wrapper for RTL-SDR

Post by vertexview »

The verbose_device_search procedure was modified and tested successfully for identification with one and two SDR units connected.
Also, I changed the serial information in eeprom for the RTL-SDR Blog v4, replacing "00000001" by "00000011" with the osmocom utility.
Partial serial string search case is OK.

Code: Select all

Procedure.l verbose_device_search(s.s="")
  
  Protected.l i, device_count, device
  Protected Dim manufact.a(256)
  Protected Dim product.a(256)
  Protected Dim serial.a(256)
  
  device =-1
  
  device_count = rtlsdr_get_device_count()
  If device_count = 0
    ; No supported devices found
    ProcedureReturn -1
  EndIf

  ; 1 or more SDR connected
  Debug "   Found " + Str(device_count) + " device(s):"
  For i = 0 To device_count - 1
    rtlsdr_get_device_usb_strings(i, @manufact(i), @product(i), @serial(i))
    Debug "   " + Str(i) + ":  " + PeekS(@manufact(i), -1, #PB_UTF8) + ", " + PeekS(@product(i), -1, #PB_UTF8) + ", " + PeekS(@serial(i), -1, #PB_UTF8)
  Next i

  If s <> ""
    ; does string look like raw id number
    device = Val(s)
    Debug "Device check: " + device
    If device >= 0 And device <= device_count  
      Debug "   " + "Raw ID check. Using device " + Str(device) + ": " + PeekS(rtlsdr_get_device_name(device-1), -1, #PB_UTF8)
      ProcedureReturn device-1
    EndIf
  EndIf

  ; does string exact match a serial
  For i = 0 To device_count-1
    rtlsdr_get_device_usb_strings(i, @manufact(i), @product(i), @serial(i))
    If s <> PeekS(@serial(i), -1, #PB_UTF8)
      Continue
    EndIf
    device = i
    ProcedureReturn device
  Next i

  ; does string prefix match a serial
  For i = 0 To device_count - 1
    rtlsdr_get_device_usb_strings(i, @manufact(i), @product(i), @serial(i))
    If FindString(PeekS(@serial(i), -1, #PB_UTF8), s) = 0
      Continue
    EndIf
    device = i
    Debug "   " + "String prefix match. Using device " + Str(device) + ": " + PeekS(rtlsdr_get_device_name(device), -1, #PB_UTF8)
    ProcedureReturn device
  Next i
  
  If device = -1
    Debug "No matching devices found."
  EndIf
  
  ProcedureReturn device
  
EndProcedure

;-Demo
CompilerIf #PB_Compiler_IsMainFile
  
  ; -------  Variable definitions
  Define.l counter, myfreq, tuner_type, dev_index
  Define sdr_Name.s
  Define *dev.rtlsdr_dev_t
  Define *manufact, *product, *serial
  
;   Debug SizeOf(rtlsdr_dev)
;   Debug OffsetOf(rtlsdr_dev\direct_sampling)
;   Debug OffsetOf(rtlsdr_dev\gain)
;   Debug OffsetOf(rtlsdr_dev\e4k_s)
;   Debug OffsetOf(rtlsdr_dev\r82xx_c)
;   Debug OffsetOf(rtlsdr_dev\r82xx_p)
;   Debug OffsetOf(rtlsdr_dev\dev_lost)
  
  ; ------- SDR Tests access
  If UseLibrtlsdr()
    
    ; Test with device search - Partial serial string
    dev_index = verbose_device_search("00011")
    counter = rtlsdr_get_device_count()
    
    If rtlsdr_open(@*dev, counter) > 0
      
      sdr_name = PeekS(rtlsdr_get_device_name(dev_index), -1, #PB_UTF8)
      *manufact = AllocateMemory(256)
      *product = AllocateMemory(256)
      *serial = AllocateMemory(256)
      rtlsdr_get_device_usb_strings(dev_index, *manufact, *product, *serial)
      rtlsdr_set_center_freq(*dev, 92200000)
      myfreq = rtlsdr_get_center_freq(*dev)
      tuner_type = rtlsdr_get_tuner_type(*dev)

      MessageRequester ("SDR Info", "SDR Count: "+ Str(counter) + #LF$ + "SDR Name: " + sdr_name + #LF$ + "SDR Type: "+ Str(tuner_type))
      MessageRequester ("SDR Info", "Frequency: "+ Str(myfreq) + #CRLF$ + "Device: " + PeekS(*manufact, -1, #PB_UTF8) + "/" + PeekS(*product, -1, #PB_UTF8) + "/" + PeekS(*serial, -1, #PB_UTF8))
      FreeMemory(*serial)
      FreeMemory(*product)
      FreeMemory(*manufact)
      
      rtlsdr_close(*dev)
    Else
      Debug "Was not able to open a device"
    EndIf
  EndIf
  
CompilerEndIf
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DLL wrapper for RTL-SDR

Post by infratec »

This:

Code: Select all

 ; 1 or more SDR connected
  Debug "   Found " + Str(device_count) + " device(s):"
  For i = 0 To device_count - 1
    rtlsdr_get_device_usb_strings(i, @manufact(i), @product(i), @serial(i))
    Debug "   " + Str(i) + ":  " + PeekS(@manufact(i), -1, #PB_UTF8) + ", " + PeekS(@product(i), -1, #PB_UTF8) + ", " + PeekS(@serial(i), -1, #PB_UTF8)
  Next i
is definately wrong.
It should be

Code: Select all

 ; 1 or more SDR connected
  Debug "   Found " + Str(device_count) + " device(s):"
  For i = 0 To device_count - 1
    rtlsdr_get_device_usb_strings(i, @manufact(0), @product(0), @serial(0))
    Debug "   " + Str(i) + ":  " + PeekS(@manufact(0), -1, #PB_UTF8) + ", " + PeekS(@product(0), -1, #PB_UTF8) + ", " + PeekS(@serial(0), -1, #PB_UTF8)
  Next i
Because it is the start of the array and has nothing to do with the devices.
User avatar
vertexview
User
User
Posts: 28
Joined: Thu Jan 25, 2024 8:33 am
Location: France

Re: DLL wrapper for RTL-SDR

Post by vertexview »

Thank you infratec.
I corrected rtlsdr_get_device_usb_strings in other lines as follow:

Code: Select all

Procedure.l verbose_device_search(s.s="")
  
  Protected.l i, device_count, device
  Protected Dim manufact.a(256)
  Protected Dim product.a(256)
  Protected Dim serial.a(256)
  
  device =-1
  
  device_count = rtlsdr_get_device_count()
  If device_count = 0
    ; No supported devices found
    ProcedureReturn -1
  EndIf

  ; 1 or more SDR connected
  Debug "   Found " + Str(device_count) + " device(s):"
  For i = 0 To device_count - 1
    rtlsdr_get_device_usb_strings(i, @manufact(0), @product(0), @serial(0))
    Debug "   " + Str(i) + ":  " + PeekS(@manufact(0), -1, #PB_UTF8) + ", " + PeekS(@product(0), -1, #PB_UTF8) + ", " + PeekS(@serial(0), -1, #PB_UTF8)
  Next i

  If s <> ""
    ; does string look like raw id number
    device = Val(s)
    Debug "Device check: " + device
    If device >= 0 And device <= device_count  
      Debug "   " + "Raw ID check. Using device " + Str(device) + ": " + PeekS(rtlsdr_get_device_name(device-1), -1, #PB_UTF8)
      ProcedureReturn device-1
    EndIf
  EndIf

  ; does string exact match a serial
  For i = 0 To device_count-1
    rtlsdr_get_device_usb_strings(i, @manufact(0), @product(0), @serial(0))
    If s <> PeekS(@serial(0), -1, #PB_UTF8)
      Continue
    EndIf
    device = i
    Debug "   " + "String exact match. Using device " + Str(device) + ": " + PeekS(rtlsdr_get_device_name(device), -1, #PB_UTF8)
    ProcedureReturn device
  Next i

  ; does string prefix match a serial
  For i = 0 To device_count - 1
    rtlsdr_get_device_usb_strings(i, @manufact(0), @product(0), @serial(0))
    If FindString(PeekS(@serial(0), -1, #PB_UTF8), s) = 0
      Continue
    EndIf
    device = i
    Debug "   " + "String prefix match. Using device " + Str(device) + ": " + PeekS(rtlsdr_get_device_name(device), -1, #PB_UTF8)
    ProcedureReturn device
  Next i
  
  If device = -1
    Debug "No matching devices found."
  EndIf
  
  ProcedureReturn device
  
EndProcedure
SDR identification tests are OK.
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DLL wrapper for RTL-SDR

Post by infratec »

Something to test:
rtl-eeprom.pb

Code: Select all

EnableExplicit

IncludeFile "librtlsdr.pbi"

#EEPROM_SIZE = 256
#MAX_STR_SIZE =	256
#STR_OFFSET = $09


Structure AsciiArray
  a.a[0]
EndStructure


Define *dev.rtlsdr_dev_t

Structure rtlsdr_config Align #PB_Structure_AlignC
  vendor_id.u
  product_id.u
  manufacturer.a[#MAX_STR_SIZE]
  product.a[#MAX_STR_SIZE]
  serial.a[#MAX_STR_SIZE]
  have_serial.l
  enable_ir.l
  remote_wakeup.l
EndStructure
Macro rtlsdr_config_t
  rtlsdr_config
EndMacro

Procedure dump_config(*conf.rtlsdr_config_t)
  PrintN("__________________________________________")
  PrintN("Vendor ID:" + #TAB$ + #TAB$ + "$" + RSet(Hex(*conf\vendor_id), 4, "0"))
  PrintN("Product ID:" + #TAB$ + #TAB$ + "$" + RSet(Hex(*conf\product_id), 4, "0"))
  PrintN("Manufacturer:" + #TAB$ + #TAB$ + PeekS(@*conf\manufacturer[0], -1, #PB_UTF8))
  PrintN("Product:" + #TAB$ + #TAB$ + PeekS(@*conf\product[0], -1, #PB_UTF8))
  PrintN("Serial number:" + #TAB$ + #TAB$ + PeekS(@*conf\serial[0], -1, #PB_UTF8))
  Print("Serial number enabled:" + #TAB$)
  If *conf\have_serial
    PrintN("yes")
  Else
    PrintN("no")
  EndIf
  Print("IR endpoint enabled:" + #TAB$)
  If *conf\enable_ir
    PrintN("yes")
  Else
    PrintN("no")
  EndIf
  Print("Remote wakeup enabled:" + #TAB$)
  If *conf\remote_wakeup
    PrintN("yes")
  Else
    PrintN("no")
  EndIf
  PrintN("__________________________________________")
EndProcedure

Procedure usage()
  
  Protected Usage$
  
  
  Usage$ = ~"rtl_eeprom, an EEPROM programming tool for "
  Usage$ + ~"RTL2832 based DVB-T receivers\n\n"
  Usage$ + ~"Usage:\n"
  Usage$ + ~"\t[-d device_index (default: 0)]\n"
  Usage$ + ~"\t[-m <str> set manufacturer string]\n"
  Usage$ + ~"\t[-p <str> set product string]\n"
  Usage$ + ~"\t[-s <str> set serial number string]\n"
  Usage$ + ~"\t[-i <0,1> disable/enable IR-endpoint]\n"
  Usage$ + ~"\t[-g <conf> generate default config and write to device]\n"
  Usage$ + ~"\t[   <conf> can be one of:]\n"
  Usage$ + ~"\t[   realtek\t\tRealtek default (as without EEPROM)]\n"
  Usage$ + ~"\t[   realtek_oem\t\tRealtek default OEM with EEPROM]\n"
  Usage$ + ~"\t[   noxon\t\tTerratec NOXON DAB Stick]\n"
  Usage$ + ~"\t[   terratec_black\tTerratec T Stick Black]\n"
  Usage$ + ~"\t[   terratec_plus\tTerratec T Stick+ (DVB-T/DAB)]\n"
  Usage$ + ~"\t[-w <filename> write dumped file to device]\n"
  Usage$ + ~"\t[-r <filename> dump EEPROM to file]\n"
  Usage$ + ~"\t[-h display this help text]\n"
  Usage$ + ~"\nUse on your own risk, especially -w!\n"
  Print(Usage$)
  
  CompilerIf #PB_Compiler_Debugger
    Input()
  CompilerEndIf
  CloseConsole()
  
  End 1
  
EndProcedure


Procedure.i get_string_descriptor(pos.i, *Data.AsciiArray, *str.AsciiArray)
  
  Protected.i len, i, j
  
  
  len = *Data\a[pos]
  
  If *Data\a[pos + 1] <> $03
    Print(~"Error: invalid string descriptor!\n")
  EndIf
  
  For i = 2 To len - 1 Step 2
    *str\a[j] = *Data\a[pos + i]
    j + 1
  Next i
  
  *str\a[j] = $00
  
  ProcedureReturn pos + i
  
EndProcedure


Procedure.i set_string_descriptor(pos.i, *Data.AsciiArray, *str.AsciiArray)
  
  Protected.i i, j
  
  
  j = 2
  
  If pos < 0
    ProcedureReturn -1
  EndIf
  
  *Data\a[pos + 1] = $03
  
  While *str\a[i] <> $00
    If pos + j >= 78
      Print(~"Error: string too long, truncated!\n")
      ProcedureReturn -1
    EndIf
    *Data\a[pos + j] = *str\a[i]
    j + 1
    i + 1
    *Data\a[pos + j] = $00
    j + 1
  Wend
  
  *Data\a[pos] = j
  
  ProcedureReturn pos + j
  
EndProcedure


Procedure.i parse_eeprom_to_conf(*conf.rtlsdr_config_t, *dat.AsciiArray)
  
  Protected.i pos
  
  
  If *dat\a[0] <> $28 Or *dat\a[1] <> $32
    Print(~"Error: invalid RTL2832 EEPROM header!\n")
  EndIf
  
  *conf\vendor_id = *dat\a[2] | (*dat\a[3] << 8)
  *conf\product_id = *dat\a[4] | (*dat\a[5] << 8)
  If *dat\a[6] = $a5
    *conf\have_serial = 1
  Else
    *conf\have_serial = 0
  EndIf
  If *dat\a[7] & $01
    *conf\remote_wakeup = 1
  Else
    *conf\remote_wakeup = 0
  EndIf
  If *dat\a[7] & $02
    *conf\enable_ir = 1
  Else
    *conf\enable_ir = 0
  EndIf
  pos = get_string_descriptor(#STR_OFFSET, *dat, @*conf\manufacturer[0])
  pos = get_string_descriptor(pos, *dat, @*conf\product[0])
  get_string_descriptor(pos, *dat, @*conf\serial[0])
  
  ProcedureReturn 0
  
EndProcedure


Procedure.i gen_eeprom_from_conf(*conf.rtlsdr_config_t, *dat.AsciiArray)
  
  Protected.i pos
  
  *dat\a[0] = $28
  *dat\a[1] = $32
  *dat\a[2] = *conf\vendor_id & $ff
  *dat\a[3] = (*conf\vendor_id >> 8) & $ff
  *dat\a[4] = *conf\product_id & $ff
  *dat\a[5] = (*conf\product_id >> 8) & $ff
  If *conf\have_serial
    *dat\a[6] = $a5
  Else
    *dat\a[6] = $00
  EndIf
  *dat\a[7] = $14
  If *conf\remote_wakeup
    *dat\a[7] | $01
  EndIf
  If *conf\enable_ir
    *dat\a[7] | $02
  EndIf
  *dat\a[8] = $02
  
  pos = set_string_descriptor(#STR_OFFSET, *dat, @*conf\manufacturer[0])
  pos = set_string_descriptor(pos, *dat, @*conf\product[0])
  pos = set_string_descriptor(pos, *dat, @*conf\serial[0])
  
  *dat\a[78] = $00    ; length of IR config
  
  ProcedureReturn pos
  
EndProcedure


Enumeration configs
  #CONF_NONE
  #REALTEK
  #REALTEK_EEPROM
  #TERRATEC_NOXON
  #TERRATEC_T_BLACK
  #TERRATEC_T_PLUS
EndEnumeration

Procedure gen_default_conf(*conf.rtlsdr_config_t, config.i)
  
  Select config
    Case #REALTEK
      Print(~"Realtek default (as without EEPROM)\n")
      *conf\vendor_id = $0bda
      *conf\product_id = $2832
      PokeS(@*conf\manufacturer[0], "Generic", -1, #PB_UTF8)
      PokeS(@*conf\product[0], "RTL2832U DVB-T", -1, #PB_UTF8)
      PokeS(@*conf\serial[0], "0", -1, #PB_UTF8)
      *conf\have_serial = 1
      *conf\enable_ir = 0
      *conf\remote_wakeup = 1
      
    Case #REALTEK_EEPROM
      Print(~"Realtek default OEM with EEPROM\n")
      *conf\vendor_id = $0bda
      *conf\product_id = $2838
      PokeS(@*conf\manufacturer[0], "Realtek", -1, #PB_UTF8)
      PokeS(@*conf\product[0], "RTL2838UHIDIR", -1, #PB_UTF8)
      PokeS(@*conf\serial[0], "00000001", -1, #PB_UTF8)
      *conf\have_serial = 1
      *conf\enable_ir = 1
      *conf\remote_wakeup = 0
      
    Case #TERRATEC_NOXON
      Print(~"Terratec NOXON DAB Stick\n")
      *conf\vendor_id = $0ccd
      *conf\product_id = $00b3
      PokeS(@*conf\manufacturer[0], "NOXON", -1, #PB_UTF8)
      PokeS(@*conf\product[0], "DAB Stick", -1, #PB_UTF8)
      PokeS(@*conf\serial[0], "0", -1, #PB_UTF8)
      *conf\have_serial = 1
      *conf\enable_ir = 0
      *conf\remote_wakeup = 1
      
    Case #TERRATEC_T_BLACK
      Print(~"Terratec T Stick Black\n")
      *conf\vendor_id = $0ccd
      *conf\product_id = $00a9
      PokeS(@*conf\manufacturer[0], "Realtek", -1, #PB_UTF8)
      PokeS(@*conf\product[0], "RTL2838UHIDIR", -1, #PB_UTF8)
      PokeS(@*conf\serial[0], "00000001", -1, #PB_UTF8)
      *conf\have_serial = 1
      *conf\enable_ir = 1
      *conf\remote_wakeup = 0
      
    Case #TERRATEC_T_PLUS
      Print(~"Terratec ran T Stick+\n")
      *conf\vendor_id = $0ccd
      *conf\product_id = $00d7
      PokeS(@*conf\manufacturer[0], "Realtek")
      PokeS(@*conf\product[0], "RTL2838UHIDIR")
      PokeS(@*conf\serial[0], "00000001")
      *conf\have_serial = 1
      *conf\enable_ir = 1
      *conf\remote_wakeup = 0
      
  EndSelect
  
EndProcedure


;-main
Define.i i, r, opt
Define.l dev_index
Define.i device_count
Define.s filename
Define.i file
Define *manuf_str
Define *product_str
Define *serial_str
Dim buf.a(#EEPROM_SIZE - 1)
Define.rtlsdr_config_t conf
Define.i flash_file
Define.i default_config
Define.i change
Define.i ir_endpoint
Define.s ch


OpenConsole()

If UseLibrtlsdr()
  
  For i = 0 To CountProgramParameters() - 1
    Select ProgramParameter(i)
      Case "-d"
        i + 1
        dev_index = Val(ProgramParameter(i))
        
      Case "-m"
        i + 1
        *manuf_str = UTF8(ProgramParameter(i))
        change = 1
        
      Case "-p"
        i + 1
        *product_str = UTF8(ProgramParameter(i))
        change = 1
        
      Case "-s"
        i + 1
        *serial_str = UTF8(ProgramParameter(i))
        change = 1
        
      Case "-i"
        i + 1
        If Val(ProgramParameter(i)) > 0
          ir_endpoint = 1
        Else
          ir_endpoint = -1
        EndIf
        change = 1
        
      Case "-g"
        i + 1
        If ProgramParameter(i) = "realtek"
          default_config = #REALTEK
        ElseIf ProgramParameter(i) = "realtek_oem"
          default_config = #REALTEK_EEPROM
        ElseIf ProgramParameter(i) = "noxon"
          default_config = #TERRATEC_NOXON
        ElseIf ProgramParameter(i) = "terratec_black"
          default_config = #TERRATEC_T_BLACK
        ElseIf ProgramParameter(i) = "terratec_plus"
          default_config = #TERRATEC_T_PLUS
        EndIf
        
        If default_config <> #CONF_NONE
          change = 1
        EndIf
        
      Case "-w"
        flash_file = 1
        change = 1
        i + 1
        filename = ProgramParameter(i)
        
      Case "-r"
        i + 1
        filename = ProgramParameter(i)
        
      Case "-h"
        usage()
        
      Default
        usage()
        
    EndSelect
  Next i
  
  device_count = rtlsdr_get_device_count()
  If Not device_count
    Print(~"No supported devices found.\n")
    End 1
  EndIf
  
  Print(~"Found " + Str(device_count) + ~"device(s):\n")
  For i = 0 To device_count - 1
    PrintN("  " + Str(i) + ":  " + PeekS(rtlsdr_get_device_name(i), -1, #PB_UTF8))
  Next i
  Print(~"\n")
  
  PrintN(~"Using device " + Str(dev_index) + ": " + PeekS(rtlsdr_get_device_name(dev_index), -1, #PB_UTF8))
  
  r = rtlsdr_open(@*dev, dev_index)
  If r < 0
    PrintN(~"Failed to open rtlsdr device #" + Str(dev_index))
    End 1
  EndIf
  
  Print(~"\n")
  
  r = rtlsdr_read_eeprom(*dev, @buf(0), 0, #EEPROM_SIZE)
  If r < 0
    If r = -3
      Print(~"No EEPROM has been found.\n")
    Else
      PrintN(~"Failed to read EEPROM, err " + Str(r))
      Goto exit
    EndIf
  EndIf
  
  If r < 0
    End -1
  EndIf
  
  Print(~"Current configuration:\n")
  parse_eeprom_to_conf(@conf, @buf(0))
  dump_config(@conf)
  
  If filename
    If flash_file
      file = ReadFile(#PB_Any, filename)
    Else
      file = OpenFile(#PB_Any, filename)
    EndIf
    If Not file
      Print(~"Error opening file!\n")
      Goto exit
    EndIf
    If flash_file
      If ReadData(file, @buf(0), #EEPROM_SIZE) <> #EEPROM_SIZE
        Print(~"Error reading file!\n")
      EndIf
    Else
      If WriteData(file, @buf(0), #EEPROM_SIZE) <> #EEPROM_SIZE
        Print(~"Short write, exiting!\n")
      Else
        Print(~"\nDump to " + filename + ~" successful.\n")
      EndIf
    EndIf
  EndIf
  
  If *manuf_str
    If MemorySize(*manuf_str) < #MAX_STR_SIZE - 1
      CopyMemory(*manuf_str, @conf\manufacturer[0], MemorySize(*manuf_str))
    EndIf
  EndIf
  
  If *product_str
    If MemorySize(*product_str) < #MAX_STR_SIZE - 1
      CopyMemory(*product_str, @conf\product[0], MemorySize(*product_str))
    EndIf
  EndIf
  
  If *serial_str
    If MemorySize(*serial_str) < #MAX_STR_SIZE - 1
      conf\have_serial = 1
      CopyMemory(*serial_str, @conf\serial[0], MemorySize(*serial_str))
    EndIf
  EndIf
  
  If ir_endpoint
    If ir_endpoint > 0
      conf\enable_ir = 1
    EndIf
  EndIf
  
  If Not change
    Goto exit
  EndIf
  
  Print(~"\nNew configuration:\n")
  
  If default_config <> #CONF_NONE
    gen_default_conf(@conf, default_config)
  EndIf
  
  If Not flash_file
    If gen_eeprom_from_conf(@conf, @buf(0)) < 0
      Goto exit
    EndIf
  EndIf
  
  parse_eeprom_to_conf(@conf, @buf(0))
  dump_config(@conf)
  
  Print(~"Write new configuration to device [y/n]? ")
  
  Repeat
    ch = Inkey()
    Delay(10)
  Until ch
  
  If ch <> "y"
    Goto exit
  EndIf
  
  If flash_file
    r = rtlsdr_write_eeprom(*dev, @buf(0), 0, #EEPROM_SIZE)
  Else
    r = rtlsdr_write_eeprom(*dev, @buf(0), 0, 128)
  EndIf
  If r < 0
    PrintN(~"Error while writing EEPROM: " + Str(r))
  Else
    Print(~"\nConfiguration successfully written.\nPlease replug the device For changes to take effect.\n")
  EndIf
  
  exit:
  If IsFile(file)
    CloseFile(file)
  EndIf
  
  rtlsdr_close(*dev)
  
  If r >= 0
    End r
  Else
    End -r
  EndIf
  
EndIf

CompilerIf #PB_Compiler_Debugger
  Input()
CompilerEndIf

CloseConsole()
Last edited by infratec on Sat Jan 27, 2024 7:18 pm, edited 1 time in total.
User avatar
vertexview
User
User
Posts: 28
Joined: Thu Jan 25, 2024 8:33 am
Location: France

Re: DLL wrapper for RTL-SDR

Post by vertexview »

rtl_eeprom.exe test. I tried with 2 SDR (RTL-SDR v3 and v4 models).
The application found device, Vendor ID, Product ID, and blocks on Manufacturer information.

[15:11:01] [ERROR] rtl_eeprom.pb (Line: 35)
[15:11:01] [ERROR] Invalid memory access. (read error at address 82)
PrintN("Manufacturer:" + #TAB$ + #TAB$ + PeekS(*conf\manufacturer, -1, #PB_UTF8))


If i comment blocking lines 35, same error for 36 (*conf/product) and 37 (*conf/serial)

[15:53:28] Waiting for executable to start...
[15:53:28] Executable type: Windows - x64 (64bit, Unicode, Thread)
[15:53:28] Executable started.
[15:53:35] [ERROR] rtl_eeprom.pb (Line: 35)
[15:53:35] [ERROR] Invalid memory access. (read error at address 82)
[15:53:42] The Program was killed.
[15:53:49] Waiting for executable to start...
[15:53:49] Executable type: Windows - x64 (64bit, Unicode, Thread)
[15:53:49] Executable started.
[15:53:56] [ERROR] rtl_eeprom.pb (Line: 36)
[15:53:56] [ERROR] Invalid memory access. (read error at address 66)
[15:54:03] The Program was killed.
[15:54:30] Waiting for executable to start...
[15:54:30] Executable type: Windows - x64 (64bit, Unicode, Thread)
[15:54:30] Executable started.
[15:54:37] [ERROR] rtl_eeprom.pb (Line: 37)
[15:54:37] [ERROR] Invalid memory access. (read error at address 48)
Post Reply