Search code examples
phpstructbinaryunpack

How to split binary data and convert it into numbers in PHP?


I'm reading keyboard events from /dev/input/. Those are input_event structs, respectively five numbers as 24 bytes in little endian format.

This is my current solution:

$hex = bin2hex(fread($dev, 24));
$time = floatval(unpack("Q", (pack('H*', substr($hex, 0, 16))))[1].".".unpack("Q", (pack('H*', substr($hex, 16, 16))))[1]);
$type = intval(unpack("S", (pack('H*', substr($hex, 32, 4))))[1]);
$code = intval(unpack("S", (pack('H*', substr($hex, 36, 4))))[1]);
$value = intval(unpack("l", (pack('H*', substr($hex, 40, 8))))[1]);

There must be a more efficient way to do this in PHP. Anyone? Bueller?

UPDATE:

An example blob would be:

$raw = hex2bin("f478cd5d0000000026680d000000000001002e0001000000");

This results in:

$time = 1573746932.8786;
$type = 1;
$code = 46;
$value = 1;

The actual structure looks like this:

struct input_event {
    timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

where timeval is:

struct timeval {
    __u64 sec;
    __u64 usec;
}

Solution

  • You could unpack it as a single value.

    <?php
    $raw = fread($dev, 24);
    $data = unpack("Ptime1/Ptime2/vtype/vcode/Vvalue", $raw);
    print_r($data);
    

    Output:

    Array
    (
        [time1] => 1573746932
        [time2] => 878630
        [type] => 1
        [code] => 46
        [value] => 1
    )