1-Wire API reference

brawl:device/onewire

All device APIs

Overview

The brawl:device/onewire interface defines a minimal, hardware-agnostic 1-Wire (Dallas/Maxim) API for WebAssembly (WASM) modules. It provides a consistent way to control and monitor 1-wire devices across diverse embedded targets - ranging from microcontrollers to emulators - while remaining fully compatible with the WASM MVP specification.

Each function follows a simple convention: it returns a signed 32-bit integer, where negative values represent standardized error codes and non-negative values represent valid results or success indicators. This design keeps the ABI deterministic, low-overhead, and portable between environments, enabling WASM applications to interact directly with physical or virtual 1-wire devices without callbacks, threads, or host-specific extensions.

Implementation Notes

This section outlines the expected behavior and conventions used by the brawl:device/onewire interface. It provides guidance for both host implementers and guest developers to ensure consistent behavior across WASM targets.

1-Wire Bus Enumeration

onewireCount() returns the total number of 1-wire buses available on the target. onewireList() populates a memory buffer with a list of available 1-Wire bus identifiers (uint8_t) in the host environment’s canonical order. Each 1-wire bus identifier can be passed directly to onewireOpen() to obtain a handle for further operations.

Interfacing With a 1-Wire Bus

Before reserving a pin, always call onewireCapabilities() to verify that it supports the desired modes. Use onewireOpen() to reserve the 1-wire bus and obtain a handle; this handle is passed to all subsequent operations. When the 1-wire bus is no longer needed, release it using onewireClose(). 1-Wire buses remain inactive and unpredictable until configured with onewireSetSpeed() to define their behavior and electrical characteristics.

Software 1-Wire (bit-banged on GPIO)

A 1-Wire bus may be emulated on a single GPIO pin using open-drain signalling and timing in software. The host reserves the selected pin and drives it low or releases it with a pull-up Strong-pullup after certain commands (e.g. DS18B20 Convert-T) may be emulated or unsupported depending on host capability. All normal 1-Wire commands are available on the resulting software bus handle.

To detect if the host supports a software implementation, call onewireModuleCapabilities() check for the ONEWIRE_CAPS_SW_PORT capability, a 1-Wire bus can then be created using the onewireOpenOnPins() function.

Error Codes

All brawl:device/onewire functions return a signed 32-bit integer (int32_t), which encodes both result and error information:

Value
ret < 0 an error occurred.
ret == 0 operation completed successfully (or no value to return).
ret > 0 operation succeeded and returned a value (e.g., a data value or handle).

All memory access operations are bounds-checked by the host; going outside will return a I2C_ERROR_MEMORY_OOB error.

Constants

ONEWIRE Errors

All functions return a signed 32-bit integer (int32_t). If the value is negative, it represents an error code from the table below:

Constant
ONEWIRE_ERROR_BUSY The 1-Wire bus is already in use or reserved by another handle.
ONEWIRE_ERROR_UNSUPPORTED The requested operation or capability is not supported on this 1-Wire bus.
ONEWIRE_ERROR_TIMEOUT The operation did not complete within the expected time.
ONEWIRE_ERROR_INVALID_HANDLE The handle provided was invalid for the operation requested.
ONEWIRE_ERROR_INVALID_ARG The argument provided was invalid for the operation requested.
ONEWIRE_ERROR_MEMORY_OOB The requested operation would result in a MEMORY_OOB Error.
ONEWIRE_ERROR_NO_DEVICE No device was found on the 1-Wire bus.
ONEWIRE_ERROR_CRC The operation resulted in a CRC error.

A return value >= 0 indicates success - either 0 for non-returning operations or a positive value for operations that produce a result.

GPIO Capabilities

Each 1-Wire bus can support one or more capabilities, reported by onewireModuleCapabilities() and onewireCapabilities(). These are bit-flags and may be combined using bitwise OR.

Constant (Flag)
ONEWIRE_CAPS_CONTROLLER Supports master role.
ONEWIRE_CAPS_MULTIDROP Supports multi-devices.
ONEWIRE_CAPS_OVERDRIVE Supports 1-Wire overdrive speed.
ONEWIRE_CAPS_STRONG_PULLUP Host can source strong pullup.
ONEWIRE_CAPS_SEARCH_HW Host can accelerate ROM search.
ONEWIRE_CAPS_SW_PORT Supports creating a 1-Wire bus on an arbitrary GPIO pin.

Combine capability flags with the bitwise OR operator (|) to describe a pin that supports multiple features.

Speed Options

Possible speed settings.

Constant
ONEWIRE_SPEED_STANDARD Standard speed.
ONEWIRE_SPEED_OVERDRIVE Overdrive speed.

Search Options

Possible search settings.

Constant
ONEWIRE_SEARCH_NORMAL Normal search.
ONEWIRE_SEARCH_ALARM_ONLY

Application Programming Interface (API)

//--------------------------------------------------------------------------
// brawl:device/onewire

// ONEWIRE errors
enum ONEWIRE_ERROR {
                         // >= 0              no error
  ONEWIRE_ERROR_BUSY         = -1,         // 1-Wire bus busy
  ONEWIRE_ERROR_UNSUPPORTED  = -2,         // 1-Wire bus operation unsupported
  ONEWIRE_ERROR_TIMEOUT      = -3,         // 1-Wire bus operation timed out
  ONEWIRE_ERROR_INVALID_ARG  = -4,         // invalid argument
  ONEWIRE_ERROR_MEMORY_OOB   = -5,         // memory OOB
  ONEWIRE_ERROR_NO_DEVICE    = -6,         // no presence pulse, or search found none
  ONEWIRE_ERROR_CRC          = -7          // optional: used by helper ops that verify CRC
};

// ONEWIRE capabilities (flags)
enum ONEWIRE_CAPS {
  ONEWIRE_CAPS_CONTROLLER    = (1u << 0),  // master role
  ONEWIRE_CAPS_MULTIDROP     = (1u << 1),  // multi-device bus
  ONEWIRE_CAPS_OVERDRIVE     = (1u << 2),  // support 1-Wire overdrive speed
  ONEWIRE_CAPS_STRONG_PULLUP = (1u << 3),  // host can source strong pullup
  ONEWIRE_CAPS_SEARCH_HW     = (1u << 4),  // host can accelerate ROM search
  ONEWIRE_CAPS_SW_PORT       = (1u << 5)   // supports creating a 1-Wire bus on an arbitrary GPIO pin
};

// ONEWIRE speed
enum ONEWIRE_SPEED {
  ONEWIRE_SPEED_STANDARD     = 0,
  ONEWIRE_SPEED_OVERDRIVE    = 1
};

// ONEWIRE search
enum ONEWIRE_SEARCH {
  ONEWIRE_SEARCH_NORMAL      = 0,
  ONEWIRE_SEARCH_ALARM_ONLY  = 1
};

int32_t // ONEWIRE_ERROR|ONEWIRE_CAPS
onewireModuleCapabilities(void);

Discovery

int32_t // ONEWIRE_ERROR|int32_t
onewireCount(void);

int32_t // ONEWIRE_ERROR|int32_t
onewireList(int32_t mem_ptr, int32_t max_items);

int32_t // ONEWIRE_ERROR|ONEWIRE_CAPS
onewireCapabilities(int32_t owBus);

Operation

int32_t // ONEWIRE_ERROR|int32_t
onewireOpen(int32_t owBus);

int32_t // ONEWIRE_ERROR|int32_t
onewireOpenOnPin(int32_t pinNum);

int32_t // ONEWIRE_ERROR|void
onewireSetSpeed(int32_t handle, enum ONEWIRE_SPEED speed);

int32_t // ONEWIRE_ERROR|void
onewireClose(int32_t handle);

Bus Primitives

int32_t // ONEWIRE_ERROR|void
onewireReset(int32_t handle);

int32_t // ONEWIRE_ERROR|void
onewireStrongPullup(int32_t handle, int32_t duration_us);

int32_t // ONEWIRE_ERROR|void
onewireSkipRom(int32_t handle);

int32_t // ONEWIRE_ERROR|int32_t
onewireMatchRom(int32_t handle, int32_t rom8_ptr);

Buffered I/O (linear memory)

int32_t // ONEWIRE_ERROR|int32_t
onewireRead(int32_t handle, int32_t rx_ptr, int32_t len, int32_t timeout_us);

int32_t // ONEWIRE_ERROR|int32_t
onewireWrite(int32_t handle, int32_t tx_ptr, int32_t len, int32_t strong_pullup_us);
int32_t // ONEWIRE_ERROR|int32_t
onewireSearch(int32_t handle, int32_t dst_ptr, int32_t max_roms, enum ONEWIRE_SEARCH opts);

Example - DS18B20 (single-drop) (C)

#include <stdint.h>
#include <stdio.h>

#include "brawl-device-onewire.h"

static void onewire_err(int32_t rc, const char *what) {
    if (rc < 0) fprintf(stderr, "%s failed: %d\n", what, rc);
}

#define MAX_ONEWIRE 4

int main(void) {

    int32_t n, rc;
    uint8_t ids[MAX_ONEWIRE];
    int32_t ow_h;
    uint8_t cmd, scratch[9];
    int16_t raw;

    // enumerate 1-Wire buses (WASM MVP: caller-allocated buffer)
    n = onewireCount();
    if (n < 0) { onewire_err(n, "onewireCount"); return 1; }
    if (n > MAX_ONEWIRE) n = MAX_ONEWIRE;

    rc = onewireList((int32_t)(uintptr_t)ids, n);
    if (rc < 0) { onewire_err(rc, "onewireList"); return 1; }

    // did we find an 1-Wire bus?
    if (rc >= 0) {

        // pick first bust
        ow_h = onewireOpen(ids[0]);
        if (ow_h < 0) { onewire_err(led_h, "onewireOpen"); return 1; }

        // set he speed and reset to check presence
        rc = onewireSetSpeed(ow_h, ONEWIRE_SPEED_STANDARD);
        if (rc < 0) { onewire_err(rc, "onewireSetSpeed"); onewireClose(ow_h); return 1; }
        rc = onewireReset(ow_h);
        if (rc < 0) { onewire_err(rc, "onewireReset"); onewireClose(ow_h); return 1; }

        // start temperature conversion (0x44) with strong pullup (e.g. 750ms)
        cmd = 0x44;
        rc = onewireWrite(ow_h, (int32_t)(uintptr_t)&cmd, 1, 750000);
        if (rc < 0) { onewire_err(rc, "onewireWrite"); onewireClose(ow_h); return 1; }

        // read scratchpad: reset + skip + (0xBE, read 9 bytes)
        rc = onewireReset(ow_h);
        if (rc < 0) { onewire_err(rc, "onewireWrite"); onewireClose(ow_h); return 1; }
        rc = onewireSkipRom(ow_h);
        if (rc < 0) { onewire_err(rc, "onewireSkipRom"); onewireClose(ow_h); return 1; }
        cmd = 0xBE;
        rc = onewireWrite(ow_h, (int32_t)(uintptr_t)&cmd, 1, 0);
        if (rc < 0) { onewire_err(rc, "onewireWrite"); onewireClose(ow_h); return 1; }
        rc = onewireRead(ow_h, (int32_t)(uintptr_t)scratch, 9, 100000);
        if (rc < 0) { onewire_err(rc, "onewireRead"); onewireClose(ow_h); return 1; }

        // we should have received 9 bytes
        if (rc == 9) {

            // temperature in little-endian 16-bit
            raw  = (int16_t)((scratch[1] << 8) | scratch[0]);

            // TODO convert per sensor resolution
        }

        // close access to the 1-Wire bus
        rc = onewireClose(ow_h);
        if (rc < 0) onewire_err(rc, "onewireClose");
    }

    return 0;
}

Revision

2025-10 (draft)