diff options
Diffstat (limited to 'erts/emulator/test/busy_port_SUITE_data/busy_drv.c')
-rw-r--r-- | erts/emulator/test/busy_port_SUITE_data/busy_drv.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/erts/emulator/test/busy_port_SUITE_data/busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c new file mode 100644 index 0000000000..1273d610ba --- /dev/null +++ b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c @@ -0,0 +1,97 @@ +/* + * Purpose: Provides a driver whose busy state can be controlled from Erlang. + * Author: Bjorn Gustavsson + */ + +#include "erl_driver.h" +#include <stdio.h> +#include <string.h> + +#define NO 0 +#define YES 1 + +static ErlDrvData busy_start(ErlDrvPort, char*); +static void busy_stop(ErlDrvData), busy_from_erlang(ErlDrvData, char*, int); + +ErlDrvEntry busy_driver_entry = +{ + NULL, + busy_start, + busy_stop, + busy_from_erlang, + NULL, + NULL, + "busy_drv", + NULL, + NULL +}; + +static ErlDrvPort master_port; +static ErlDrvPort slave_port; +static int next_slave_state; + +DRIVER_INIT(busy_drv) +{ + master_port = (ErlDrvPort)-1; + slave_port = (ErlDrvPort)-1; + return &busy_driver_entry; +} + +static ErlDrvData busy_start(ErlDrvPort port, char* buf) +{ + char *s; + int slave = YES; + + s = strchr(buf, ' '); + if (s && s[1] == 'm') { + /* This is the master port */ + if (master_port != (ErlDrvPort)-1) + return ERL_DRV_ERROR_GENERAL; /* Already open */ + if (slave_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + master_port = port; + next_slave_state = 1; + } else { + if (slave_port != (ErlDrvPort)-1) + return ERL_DRV_ERROR_GENERAL; /* Already open */ + if (master_port == (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + slave_port = port; + } + return (ErlDrvData)port; +} + +static void busy_stop(ErlDrvData port) +{ + if ((ErlDrvPort)port == master_port) { + master_port = (ErlDrvPort)-1; + } else if ((ErlDrvPort)port == slave_port) { + slave_port = (ErlDrvPort)-1; + } +} + +static void +busy_from_erlang(ErlDrvData port, char* buf, int count) +{ + if ((ErlDrvPort)port == slave_port) { + set_busy_port(slave_port, next_slave_state); + next_slave_state = 0; + return; + } + + if (slave_port == (ErlDrvPort)-1 || count < 1) { + driver_failure((ErlDrvPort)port, -1); + return; + } + + switch (buf[0]) { + case 'l': /* Lock port (set to busy) */ + set_busy_port(slave_port, 1); + break; + case 'u': /* Unlock port (not busy) */ + set_busy_port(slave_port, 0); + break; + } +} |