HackRF Racket Bindings: Update 2

It took me a while to produce one more function, which is hackrf-open. This delay was mainly because I had a shaky understanding of some of the Racket FFI concepts and functions, so I had to go back and relearn several things, especially relating to handling C pointers in Racket. Another thing that is interesting: In C you are expected to manually allocate and deallocate memory, and signal errors via an integer return value, whereas in Scheme we are expecting the memory management to happen automatically, with errors being signaled by exceptions, so there is some work to be done bridging between to two ideas.

Anyway, hackrf-open was a good step as it gives you access to the hackrf_device pointer, which has to be passed to most of the other hackrf control functions.

racket@hackrf.rkt> (define dev (hackrf-open))
racket@hackrf.rkt> dev
#<cpointer:hackrf_device>

If you run (exit) or assign something else to dev, the program will run hackrf_close on #<cpointer:hackrf_device>.

git clone git://git.librehacker.com/pub/git/hackrf-rkt.git

Hackrf Racket Bindings: Update

I code bindings for the info functions, the functions used to pull basic information about the HackRF devices that are plugged in to USB.

racket@hackrf.rkt> (hackrf-init)
0
racket@hackrf.rkt> (define dl (get-hackrf-device-list))
racket@hackrf.rkt> (hackrf-device-count dl)
1
racket@hackrf.rkt> (hackrf-serial-numbers dl)
'("000000000000000087c867dc29903e5f")
racket@hackrf.rkt> 
racket@hackrf.rkt> (hackrf-usb-board-ids dl)
'(USB_BOARD_ID_HACKRF_ONE)
racket@hackrf.rkt> (hackrf-usb-device-index dl)
'(0)
racket@hackrf.rkt> (hackrf-usb-devices dl)
'(#<cpointer>)

There are a few earlier boards that are also supported by this interface besides just the HackRF One.

I’m coding for the version of libhackrf in Debian Stretch, which I’ve discovered is a few years older than the master branch. Maybe after finishing these binds I’ll create a new Git branch for the newer library, and update the bindings for it.

Here is the repo:

git clone git://git.librehacker.com/pub/git/hackrf-rkt.git

hackrf-rkt git repo

My project wasn’t big enough yet for Savannah, and I don’t like any of the other hosting options I’m familiar with, so I set up a git daemon for my libhackrf Racket bindings project:

git clone git://git.librehacker.com/pub/hackrf-rkt.git

This was something of an adventure, as (1) I found, and had to fix myself, a bug in Debian Stretch’s git-daemon-run package, and (2) the git-daemon config syntax was not quite intuitive to me, such that I had to tweak my parameters about five times while watching the system log, in order to export my repo.

Anyway, the clone should work from any IPv4 or IPv6 address, though I only tested IPv6. Let me know if there is a problem with IPv4 access.

New Project: libhackrf Racket bindings

I’m fond of my HackRF radio, but lost interest in working through GnuRadio Companion, because I don’t want to do any Python programming to extend the blocks. So I started looking into scheme bindings for libhackrf. There is a learning curve, for sure, but it appears that this shouldn’t be too difficult, using the Racket FFI. Here is some code (minus some important error checking) that pulls the hackrf_device_list, i.e., the struct containing information about what HackRF devices are currently plugged in to your USB:

#lang racket/base

(require ffi/unsafe
         ffi/unsafe/define)
 
(define-ffi-definer define-hackrf (ffi-lib "libhackrf"))

(define-hackrf hackrf_init (_fun -> _int))
(define-hackrf hackrf_exit (_fun -> _int))

(define _hackrf_device_list_t-pointer (_cpointer 'hackrf_device_list_t))

(define-hackrf hackrf_device_list (_fun -> _hackrf_device_list_t-pointer))

(define-cstruct _hackrf_device_list_st ([serial_numbers _pointer]
                                        [usb_board_ids _pointer]
                                        [usb_device_index _pointer]
                                        [devicecount _int32]
                                        [usb_devices _pointer]
                                        [usb_devicecount _int32]))

This ties into the C API from hackrf.h (ADDAPI and ADDCALL are blank except in Windows):

struct hackrf_device_list {
	char **serial_numbers;
	enum hackrf_usb_board_id *usb_board_ids;
	int *usb_device_index;
	int devicecount;
	
	void **usb_devices;
	int usb_devicecount;
};
typedef struct hackrf_device_list hackrf_device_list_t;

extern ADDAPI int ADDCALL hackrf_init();
extern ADDAPI int ADDCALL hackrf_exit();

extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list();

And here is a demo function to get the device count:

(define (hackrf-device-count)
  (hackrf_device_list_st-devicecount
   (ptr-ref (hackrf_device_list)
    _hackrf_device_list_st)))

With my HackRF plugged in:

racket@hackrf-ffi.rkt> (hackrf_init)
 0
 racket@hackrf-ffi.rkt> (hackrf-device-count)
 1

After unplugging it:

racket@hackrf-ffi.rkt> (hackrf-device-count)
0