Add commands: dummy example (for developers)

Adding a new command and source files

This looks like a lot, but this is a really detailed step-by-step. The basics are:

  • Add your command and function to the commands struct in file commands.c
  • Include your source header in commands.c
  • Add your source files to bp5_common in CMakeLists.txt
  • Compile!

Add command to commands struct in commands.c

// command configuration
const struct _command_struct commands[]=
{  
    {"ls",true,&list_dir,T_CMDLN_LS}, //ls
    {"cd", true, &change_dir,T_CMDLN_CD},//cd
    {"mkdir", true, &make_dir, T_CMDLN_MKDIR},//mkdir
    {"rm", true, &storage_unlink, T_CMDLN_RM}, //rm
    {"cat", true, &cat, T_CMDLN_CAT}, //cat

First, let’s register our new command so the Bus Pirate knows what it is and what function to run.

  • Open [commands.c](https://github.com/DangerousPrototypes/BusPirate5-firmware/blob/main/commands.c#L30)
  • Find const struct _command_struct commands[]=
    {"logic", true, &la_test_args, T_CMDLN_LOGIC },                     // "logic" 
    {"hex", true, &hex, T_CMDLN_HEX },                                // "hex"
    {"pause", true, &helpers_pause_args, T_HELP_CMD_PAUSE },             // "pause"
    {"flash", true, &flash, 0x00 },                              // "dump"
};
  • Find the bottom of the commands struct, please always add new commands in the last position in the struct for easier merge requests.
{"dummy", true, &dummy_func, 0x00 } 

We’re going to add a new command dummy that demonstrates how to use the command line parser and other useful things.

  • "dummy" is the user command typed in the terminal to access this “program”. 8 characters max because we don’t support long file names.
  • true indicates the command can be used in HiZ mode. Use false for anything that might manipulate IO or power, it should only be used in a protocol mode
  • &dummy_func is a reference to the function to execute when the dummy command is typed in the terminal
  • 0x00 - the final position configures the help shown when the user enters dummy -h with the -(h)elp flag.
    – 0x00 - do nothing, help is handled in dummy_func
    – T_MODE_NO_HELP_AVAILABLE - displays the "no help available message in the currently configured language
    – You can add a custom help string to en-us.h, then run json2h.py, which will rebuild the translation files, adding defaults where translations are missing values. This is beyond the scope of this little demo
    {"logic", true, &la_test_args, T_CMDLN_LOGIC },                     // "logic" 
    {"hex", true, &hex, T_CMDLN_HEX },                                // "hex"
    {"pause", true, &helpers_pause_args, T_HELP_CMD_PAUSE },             // "pause"
    {"flash", true, &flash, 0x00 },                              // "dump"
    {"dummy", true, &dummy_func, 0x00 }                              // "dummy"
};

Here’s how it looks with our dummy command added to the end of the commands struct

include your source.h in commands.c

#include "helpers.h"
#include "storage.h"
#include "flash.h"
#include "mcu/rp2040.h"
#include "mode/logicanalyzer.h"

Find the include list at the top of commands.c. Add your source header to the bottom of the list.

#include "helpers.h"
#include "storage.h"
#include "flash.h"
#include "mcu/rp2040.h"
#include "mode/logicanalyzer.h"
#include "dummy.h"

Here’s what it looks like if our source is dummy.c and dummy.h. Only the .h file needs to be included.

Add source files to CMakeLists.txt

set(bp5_common 
        pirate.c pirate.h commands.h commands.c 
        mode/sump.c mode/sump.h        
        ui/ui_lcd.c ui/ui_lcd.h rgb.c rgb.h bio.h bio.c
	msc_disk.c usb_descriptors.c

Open CMakeLists.txt and add your files to the project:

  • Find the bottom of set(bp5_common
  • Add the name of any .c and .h source files you need
        mode/logicanalyzer.h mode/logicanalyzer.c
        mode/hw2wire.h mode/hw2wire.c mode/hw2wire_pio.h mode/hw2wire_pio.c
        dummy.c dummy.h
        )

Here we’ve added dummy.c and dummy.h to the project at the end of the bp5_common files.

Using the command line arguments parser

HiZ> dummy -h
usage:
dummy [init|test]
[-b(utton)] [-i(nteger) ] [-f ]
Initialize: dummy init
Test: dummy test
Test, require button press: dummy test -b
Integer, value required: dummy -i 123
Create/write/read file: dummy -f dummy.txt
Kitchen sink: dummy test -b -i 123 -f dummy.txt

Dummy commands valid in position 1
init Dummy init command
test Dummy test command

Dummy flags
-b -b require Bus Pirate button to be pushed. Takes no parameters
-i -i {integer}. Requires integer number parameter
-f -f {file}. Create/write/read {file}. Requires file string parameter

The dummy command is a fast way to get started writing a Bus Pirate command. It walks through command line parsing, file storage, and the button. More to come in the future. Start your project right in this template if you have problems installing your own command.

Type dummy -h to print the help menu in the latest firmware. Be sure to try in in different modes with the power supply & pull-up resistors on and off.

Command chaining

The Bus Pirate supports command chaining:

  • ; - execute commands in order typed, seperated by ;
  • && - execute the next command if the previous finished with success
  • || - execute the next command if the previous failed

As a developer you do not need to be aware of multiple commands entered on a single command line. The parsing libraries won’t overrun the current command bounds (this is the big huge major update the new command line parser brings).

Now outdated, but still slightly informative

This part is already outdated. I suggest you head straight to the dummy.c template for the latest and greatest.

it is moderately easy to add commands/programs to the bus pirate firmware, and work with command line arguments and parameters and flags. I looked at several ways to do this, I think this is far from the best solution. But, I can get it done without a major code overhaul and it should be easy for a range of skill levels.

Command line structure

HiZ> command text1 text2 -v -f test.tmp

Command line options/arguments/flags can be accessed by position or flag name

Accessing command line by position

bool cmdln_args_string_by_position(uint32_t pos, uint32_t max_len, char *str)
bool cmdln_args_uint32_by_position(uint32_t pos, uint32_t *value)

Values can be extracted by position. This is for commands like mkdir {dir} or cp test.tmp test2.tmp. a uint32t version of the function parses the argument and returns a uint32_t.

  • command is position 0
  • text1 is position 1
  • text 2 is position 2
  • -v if position 3, but it is MUCH easier to use the flag search function to retrieve flags.

More after I write the dummy.c example :slight_smile:

Find by flag and optional value

cmdln_args_find_flag(char flag);

Find a flag without requiring a string or integer parameter.

bool cmdln_args_find_flag_uint32(char flag, command_var_t *arg, uint32_t *value);
bool cmdln_args_find_flag_string(char flag, command_var_t *arg, uint32_t max_len, char *str);

Search for a flag and return string or integer values (required).

2 Likes

Nice idea. Make sure you have an example beginners can use as a template.

I’m eager to see this fleshed out, as I think an easier “on-ramp” to developing tools and functions for the BP5 would be of great benefit to the community. I was actually looking into trying to add some functions to the firmware a couple weeks back, but when I started browsing through the code I couldn’t really wrap my head around it.

As @grymoire said, some nice examples would be of great help here. Would love to see not only some examples for command line tools, but also some boilerplate code for how to show text/images on the screen, read from the button, etc.

Please refer to the first post on this thread, I completely rewrote it for the new dummy.c scaffolding.


You read my mind. My final project for the day is a dummy command that shows how to write a command and use various hardware features.

dummy -h
dummy text -b -i 32 -f dummy.txt

In the latest autobuild there’s a new dummy command demonstrating the command line parser, button, and storage.

I know there’s stuff still not demoed. I will add these as I clean the code into stable libraries:

  • voltage and current measurement
  • pull-up resistors
  • vreg (voltage/current)
  • LEDs
  • buffered IO pins
  • prompt and parse/menus
  • raw protocol hardware (I2C, SPI, 1Wire, etc)
  • PWM
  • freq
  • interacting with the status bar
  • changing LCD labels/claiming pins (though this is mostly for modes)

If anyone is interested in making a custom protocol mode, there’s a similar /mode/dummy1.c scaffolding for mode integration.

1 Like