PHP-Controllable SPI Extension

Maintainers

Package info

github.com/php-io-extensions/spi

Language:C

Type:php-ext

Ext name:ext-spi

pkg:composer/php-io-extensions/spi

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.7 2026-05-13 03:39 UTC

This package is auto-updated.

Last update: 2026-05-13 03:39:38 UTC


README

PHP Zephir Platform

PHP-controllable Linux SPI extension built with Zephir.

The SPI extension allows PHP to communicate with SPI devices on Linux by configuring a spidev file descriptor and performing read, write, and full-duplex transfer operations. Useful for sensors, DACs, ADCs, displays, EEPROMs, and other peripherals connected over SPI.

git clone https://github.com/DeptOfScrapyardRobotics/SPI
cd SPI
bash install.sh

Requirements

  • PHP 8.3+ with development headers (php-dev / php-devel)
  • Zephir 0.19+
  • FD extension — provides raw integer file descriptors via Fd\FD::open()
  • Linux with SPI userspace support (/dev/spidevB.C)
  • spidev kernel support enabled

Installation

Install Zephir if you haven't already:

composer global require phalcon/zephir

Install the FD extension first. SPI methods in this extension expect a raw integer file descriptor, which PHP's normal stream APIs do not provide:

git clone https://github.com/DeptOfScrapyardRobotics/FD
cd FD && bash install.sh

Make sure the spidev device exists on your system:

ls /dev/spidev*

Then clone and build this extension:

git clone https://github.com/DeptOfScrapyardRobotics/SPI
cd SPI
bash install.sh

install.sh handles the full workflow: clean → build → copy .so → write 30-spi.ini into detected conf.d directories → verify php -m → reload php-fpm if present.

To use a specific Zephir binary:

ZEPHIR_BIN=/path/to/zephir bash install.sh

API

All methods are static. File descriptors are plain integers. Use the FD extension to open and close them.

use Fd\FD;
use Spi\SPIRead;
use Spi\SPIWrite;

$fd = FD::open('/dev/spidev0.0', 2); // O_RDWR = 2
// ... use $fd with SPIRead and SPIWrite methods ...
FD::close($fd);

Spi\SPIWrite

Configuration setters and transfer methods for an SPI file descriptor.

wrMode(int $fd, int $value): int

Writes the 8-bit SPI mode flags using SPI_IOC_WR_MODE. Returns 0 on success, -1 on failure.

wrMode32(int $fd, int $value): int

Writes the 32-bit SPI mode flags using SPI_IOC_WR_MODE32. Returns 0 on success, -1 on failure.

wrMaxSpeedHz(int $fd, int $value): int

Sets the SPI clock speed in Hz. Returns 0 on success, -1 on failure.

wrBitsPerWord(int $fd, int $value): int

Sets bits per word, commonly 8. Returns 0 on success, -1 on failure.

wrLsbFirst(int $fd, int $value): int

Sets bit order. Use 0 for MSB-first and 1 for LSB-first. Returns 0 on success, -1 on failure.

write(int $fd, string $payload): int

Performs a half-duplex write using the standard write(2) syscall. Returns the number of bytes written, or -1 on failure.

message(int $fd, string $tx): array

Performs a single full-duplex SPI transfer using SPI_IOC_MESSAGE(1).

Returns an associative array:

Key Type Description
success int ioctl() return value; negative means failure
data string Bytes received during the transfer

The number of bytes received matches the length of $tx. If your device needs clock pulses to return data, include dummy bytes in $tx.

Spi\SPIRead

Configuration getters and half-duplex read operations for an SPI file descriptor.

rdMode(int $fd): int

Reads the current 8-bit SPI mode via SPI_IOC_RD_MODE. Returns the mode value, or -1 on failure.

rdMode32(int $fd): int

Reads the current 32-bit SPI mode via SPI_IOC_RD_MODE32. Returns the mode value, or -1 on failure.

rdMaxSpeedHz(int $fd): int

Reads the configured SPI clock speed in Hz. Returns the value, or -1 on failure.

rdBitsPerWord(int $fd): int

Reads the configured bits-per-word value. Returns the value, or -1 on failure.

rdLsbFirst(int $fd): int

Reads the configured bit order. Returns 0 for MSB-first, 1 for LSB-first, or -1 on failure.

read(int $fd, int $num_bytes): string

Performs a half-duplex read using the standard read(2) syscall. Returns the bytes read as a binary string, or "" on failure.

Usage

use Fd\FD;
use Spi\SPIRead;
use Spi\SPIWrite;

Common mode values:

Mode Value
SPI_MODE_0 0
SPI_MODE_1 1
SPI_MODE_2 2
SPI_MODE_3 3

Configure a device

$fd = FD::open('/dev/spidev0.0', 2); // O_RDWR

SPIWrite::wrMode($fd, 0);            // SPI mode 0
SPIWrite::wrMaxSpeedHz($fd, 500000); // 500 kHz
SPIWrite::wrBitsPerWord($fd, 8);
SPIWrite::wrLsbFirst($fd, 0);        // MSB first

echo "Mode: " . SPIRead::rdMode($fd) . PHP_EOL;
echo "Speed: " . SPIRead::rdMaxSpeedHz($fd) . PHP_EOL;

FD::close($fd);

Half-duplex write

$fd = FD::open('/dev/spidev0.0', 2);

SPIWrite::wrMode($fd, 0);
SPIWrite::wrMaxSpeedHz($fd, 1000000);
SPIWrite::wrBitsPerWord($fd, 8);

$written = SPIWrite::write($fd, "\x9A\xBC\xDE");
echo "Bytes written: {$written}\n";

FD::close($fd);

Half-duplex read

$fd = FD::open('/dev/spidev0.0', 2);

SPIWrite::wrMode($fd, 0);
SPIWrite::wrMaxSpeedHz($fd, 1000000);
SPIWrite::wrBitsPerWord($fd, 8);

$data = SPIRead::read($fd, 4);
echo bin2hex($data) . PHP_EOL;

FD::close($fd);

Full-duplex transfer

$fd = FD::open('/dev/spidev0.0', 2);

SPIWrite::wrMode($fd, 0);
SPIWrite::wrMaxSpeedHz($fd, 1000000);
SPIWrite::wrBitsPerWord($fd, 8);

$result = SPIWrite::message($fd, "\x9F\x00\x00\x00");

if ($result['success'] >= 0) {
    echo "RX: " . bin2hex($result['data']) . PHP_EOL;
}

FD::close($fd);

Query current configuration

$fd = FD::open('/dev/spidev0.0', 2);

echo "Mode: " . SPIRead::rdMode($fd) . PHP_EOL;
echo "Mode32: " . SPIRead::rdMode32($fd) . PHP_EOL;
echo "Max speed: " . SPIRead::rdMaxSpeedHz($fd) . PHP_EOL;
echo "Bits/word: " . SPIRead::rdBitsPerWord($fd) . PHP_EOL;
echo "LSB first: " . SPIRead::rdLsbFirst($fd) . PHP_EOL;

FD::close($fd);

Notes

  • This extension operates on Linux spidev device files such as /dev/spidev0.0.
  • message() performs a single transfer whose RX length matches the TX length.
  • Some SPI devices do not support plain read() and instead require command bytes or dummy bytes through message().
  • This extension does not open device files itself; use the FD extension for that.

License

Copyright © Project Saturn Studios, LLC. All rights reserved.