Sunday, October 13, 2013

Architecture of the bladeRF-software


Before I bought the bladeRF-board I decided to make a program coded in python to control my bladeRF-board from the laptop. Furthermore I wanted to do the time-consuming calculations on the FPGA coded in VHDL. Quite challenging. Now I understand more of the bladeRF. There is a very good program bladeRF-cli that can do almost everything I want. There is C-coded program in the FX3-USB-chip. And there seems to be a NIOS-processor soft-programmed in the FPGA. That can be programmed in C too?


To understand/learn a device I define a goal and try to achieve that goal:

 "Try to code a python-program that gets some info from the bladeRF, eg. the bandwidth".

 Investigating the bladeRF-software

On my laptop the software is at C:\bladeRF-master.

Have a look at the source bladeRF.cli

The source for the basic funtions of bladeRF seems to be at


Doc for the libusb-API

I was desperately looking for the python-libusb-API on the internet. I did not find it!! However, the doc is in python itself, just type “help(usb)” and you get:

Help on package usb:

    usb - PyUSB - Easy USB access in Python


    This package exports the following modules and subpackages:
        core - the main USB implementation
        legacy - the compatibility layer with 0.x version
        backend - the support for backend implementations.
    Since version 1.0, main PyUSB implementation lives in the 'usb.core'
    module. New applications are encouraged to use it.

    backend (package)

    __all__ = ['legacy', 'core', 'backend', 'util']
    __author__ = 'Wander Lairson Costa'

    Wander Lairson Costa

>>> Help(usb.core):

Help on module usb.core in usb:
    usb.core - usb.core - Core USB features.


    This module exports:
    Device - a class representing a USB device.
    Configuration - a class representing a configuration descriptor.
    Interface - a class representing an interface descriptor.
    Endpoint - a class representing an endpoint descriptor.
    find() - a function to find USB devices.

Etcetera, so the doc is in python!!

My goal again

In order to set the bandwidth to 12.345 MHz what to program in python? After that, read back the bandwidth from bladeRF-cli.


C:\bladeRF-master\host\libraries\libbladeRF\src contains bladerf.c:

int bladerf_get_bandwidth(struct bladerf *dev, bladerf_module module,
                            unsigned int *bandwidth )
    /* TODO: Make return values for lms call and return it for failure */
    lms_bw_t bw = lms_get_bandwidth( dev, module );
    *bandwidth = lms_bw2uint(bw);
    return 0;

C:\bladeRF-master\host\libraries\libbladeRF\src contains lms.c:

// Get the bandwidth for the selected module
lms_bw_t lms_get_bandwidth(struct bladerf *dev, bladerf_module mod)
    uint8_t data;
    uint8_t reg = (mod == BLADERF_MODULE_RX) ? 0x54 : 0x34;
    bladerf_lms_read(dev, reg, &data);
    data &= 0x3c;
    data >>= 2;
    return (lms_bw_t)data;
So, search for bladerf_lms_read.


libbladeRF.h contains:

 * Read a LMS register
 * @param   dev         Device handle
 * @param   address     LMS register offset

 * @param   val         Pointer to variable the data should be read into
 * @return 0 on success, value from \ref RETCODES list on failure
API_EXPORT int bladerf_lms_read(struct bladerf *dev,
                                uint8_t address,
                                uint8_t *val);

 * Write a LMS register
 * @param   dev         Device handle
 * @param   address     LMS register offset
 * @param   val         Data to write to register
 * @return 0 on success, value from \ref RETCODES list on failure
API_EXPORT int bladerf_lms_write(struct bladerf *dev,
                                 uint8_t address,
                                 uint8_t val);

What is API_EXPORT? a macro?

 /** Marks an API routine to be made visible to dynamic loader  */
#if defined _WIN32 || defined _CYGWIN__
#   ifdef __GNUC__
#       define API_EXPORT __attribute__ ((dllexport))
#   else
#       define API_EXPORT __declspec(dllexport)
#   endif
#   define API_EXPORT __attribute__ ((visibility ("default")))


Search for lms_read and lms_write


 * LMS register read / write functions

int bladerf_lms_read(struct bladerf *dev, uint8_t address, uint8_t *val)
    return dev->fn->lms_read(dev,address,val);

int bladerf_lms_write(struct bladerf *dev, uint8_t address, uint8_t val)
    return dev->fn->lms_write(dev,address,val);

C:\bladeRF-master\host\libraries\libbladeRF\src bladerf_priv.h

   /* LMS6002D accessors */
    int (*lms_write)(struct bladerf *dev, uint8_t addr, uint8_t data);
    int (*lms_read)(struct bladerf *dev, uint8_t addr, uint8_t *data);

Where are lms_read and lms_write defined?

C:\bladeRF-master\hdl\fpga\ip\altera\nios_system\software\lms_spi_controller hello_world_small.c

#define LMS_READ  0
#define LMS_WRITE  (1<<7 data-blogger-escaped-access="" data-blogger-escaped-address="" data-blogger-escaped-an="" data-blogger-escaped-backend="(struct" data-blogger-escaped-bladerf-master="" data-blogger-escaped-bladerf="" data-blogger-escaped-bladerf_linux="" data-blogger-escaped-c:="" data-blogger-escaped-definition="" data-blogger-escaped-dev-="" data-blogger-escaped-dev="" data-blogger-escaped-finally="" data-blogger-escaped-for="" data-blogger-escaped-fpga="" data-blogger-escaped-host="" data-blogger-escaped-in="" data-blogger-escaped-int="" data-blogger-escaped-ioctl="" data-blogger-escaped-is="" data-blogger-escaped-it="" data-blogger-escaped-libbladerf="" data-blogger-escaped-libraries="" data-blogger-escaped-linux.c="" data-blogger-escaped-linux_lms_read="" data-blogger-escaped-lms="" data-blogger-escaped-lms_read:="" data-blogger-escaped-nios="" data-blogger-escaped-processor="" data-blogger-escaped-register="" data-blogger-escaped-ret="" data-blogger-escaped-runs="" data-blogger-escaped-software="" data-blogger-escaped-src="" data-blogger-escaped-static="" data-blogger-escaped-struct="" data-blogger-escaped-that="" data-blogger-escaped-the="" data-blogger-escaped-this="" data-blogger-escaped-uart_cmd="" data-blogger-escaped-uc="" data-blogger-escaped-uint8_t="" data-blogger-escaped-val="" data-blogger-escaped-virtual="">backend;
    address &= 0x7f;
    uc.addr = address; = 0xff;
    ret = ioctl(backend->fd, BLADE_LMS_READ, &uc);
    *val =;
    return ret;

static int linux_lms_write(struct bladerf *dev, uint8_t address, uint8_t val)
    struct uart_cmd uc;
    struct bladerf_linux *backend = (struct bladerf_linux *)dev->backend;
    uc.addr = address; = val;
    return ioctl(backend->fd, BLADE_LMS_WRITE, &uc);


#define BLADE_LMS_WRITE         _IOR(BLADERF_IOCTL_BASE, 20, unsigned int)
#define BLADE_LMS_READ          _IOR(BLADERF_IOCTL_BASE, 21, unsigned int)

It looks like BLADE_LMS_WRITE and BLADE_LMS_READ are defined here. In the interface to the USB-FX3-chip!! IOR = Input Output Request??



  _IOR - General: Defines ioctl types for device control operations



   t );


  g   Specifies the group that this ioctl type belongs to. This argument must
      be a nonnegative 8-bit number (that is, in the range 0-255 inclusive).
      You can pass the value zero (0) to this argument if a new ioctl group
      is not being defined.

  n   Specifies the specific ioctl type within the group. These types should
      be sequentially assigned numbers for each different ioctl operation the
      driver supports. This argument must be a nonnegative 8-bit number (that
      is, in the range 0-255 inclusive).

  t   Specifies the data structure size, which cannot exceed 128 bytes. You
      use this argument to size how much data is passed from the kernel back
      to the user application. The kernel determines the number of bytes to
      transfer by passing the value in this argument to the sizeof operator.

The ioctl system call first appeared in Version 7 of Unix under that name. It is supported by most Unix and Unix-like systems, including Linux and Mac OS X, though the available request 

codes differ from system to system. Microsoft Windows provides a similar function, named "DeviceIoControl", in its Win32 API.
For example, on Win32 systems, ioctl calls can communicate with USB devices, or they can discover drive-geometry information for attached storage-devices.

35.10. fcntl — The fcntl() and ioctl() system calls¶
This module performs file control and I/O control on file descriptors. It is an interface to the fcntl() and ioctl() Unix routines.

All functions in this module take a file descriptor fd as their first argument. This can be an integer file descriptor, such as returned by sys.stdin.fileno(), or a file object, such as 

sys.stdin itself, which provides a fileno() which returns a genuine file descriptor.
The ioctl() Requests
Chapter 7. The USB Filesystem (usbfs)  
The ioctl() Requests
IOCTL_USB_DIAGNOSTIC_MODE_OFF 0x220404 inc\api\usbioctl.h 
0x220400 inc\api\usbioctl.h TheIOCTL_USB_DIAGNOSTIC_MODE_ONI/O control has been deprecated. Do not use.


0x2203fc inc\api\usbioctl.h TheIOCTL_USB_HCD_GET_STATS_1IOCTL has been deprecated. Do not use.
0x220428 inc\api\usbioctl.h TheIOCTL_USB_HCD_GET_STATS_2IOCTL has been deprecated. Do not use.
0x220444 inc\api\usbioctl.h TheIOCTL_USB_HUB_CYCLE_PORTI/O control request power cycles the port that is associated with the PDO that receives the request.
0x22044c inc\api\usbioctl.h TheIOCTL_USB_RESET_HUBIOCTL is used by the USB driver stack. Do not use.
0x220438 inc\api\usbuser.h Do not use this request.


I have to dig further in IOCTL and have a look at/in PYUSB. Somehow these two worlds should meet. I am sure the final Python-program to set the bandwidth will be remarkably simple! But I don't yet know how to do it. If there is any reader who knows the answer? Make a comment and I will be (almost eternally) grateful!

This is art. An artist put some stuff on a pillar,
paint it in nice bright colors and that's it! In 
Spain, Zarautz, in December 2012.


  1. You can enter bladerf-cli -i (as in interactive mode).
    Then type help , you will get a list of predefined options.
    Then using get or set functions you can get the bandwidth(or other parameters) or you
    can set the bandwidth.

  2. I tried help(usb). But, all I got was NameError: name 'usb' not defined. Any idea as to what to do?

    1. Abhijith, you have to import the module by first typing:
      import usb
      After that, help(usb) will give you a meaningful output.

      I am sorry I did not mention that in my blog.