static void handle_signals(const char *req, int *req_index)
{
    // No arguments
    (void) req;
    (void) req_index;

    if (!uart_is_open(uart)) {
        send_error_response("ebadf");
        return;
    }

    struct uart_signals sig;
    if (uart_get_signals(uart, &sig) >= 0) {
        char resp[128];
        int resp_index = sizeof(uint16_t);
        resp[resp_index++] = response_id;
        ei_encode_version(resp, &resp_index);
        ei_encode_tuple_header(resp, &resp_index, 2);
        ei_encode_atom(resp, &resp_index, "ok");
        ei_encode_map_header(resp, &resp_index, 8);
        encode_kv_bool(resp, &resp_index, "dsr", sig.dsr);
        encode_kv_bool(resp, &resp_index, "dtr", sig.dtr);
        encode_kv_bool(resp, &resp_index, "rts", sig.rts);
        encode_kv_bool(resp, &resp_index, "st", sig.st);
        encode_kv_bool(resp, &resp_index, "sr", sig.sr);
        encode_kv_bool(resp, &resp_index, "cts", sig.cts);
        encode_kv_bool(resp, &resp_index, "cd", sig.cd);
        encode_kv_bool(resp, &resp_index, "rng", sig.rng);
        erlcmd_send(resp, resp_index);
    } else
        send_error_response(uart_last_error());
}
Example #2
0
/**
 * @brief Send :ok back to Elixir
 */
static void send_ok_response()
{
    char resp[256];
    int resp_index = sizeof(uint16_t); // Space for payload size
    ei_encode_version(resp, &resp_index);
    ei_encode_atom(resp, &resp_index, "ok");
    erlcmd_send(resp, resp_index);
}
Example #3
0
/**
 * @brief Send a response of the form {:error, reason}
 *
 * @param reason a reason (sent back as an atom)
 */
static void send_error_response(const char *reason)
{
    char resp[256];
    int resp_index = sizeof(uint16_t); // Space for payload size
    ei_encode_version(resp, &resp_index);
    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "error");
    ei_encode_atom(resp, &resp_index, reason);
    erlcmd_send(resp, resp_index);
}
static void enumerate_ports()
{
    struct serial_info *port_list = find_serialports();
    int port_list_len = 0;
    for (struct serial_info *port = port_list;
         port != NULL;
         port = port->next)
        port_list_len++;

    debug("Found %d ports", port_list_len);
    char resp[4096];
    int resp_index = sizeof(uint16_t); // Space for payload size
    resp[resp_index++] = response_id;
    ei_encode_version(resp, &resp_index);

    ei_encode_map_header(resp, &resp_index, port_list_len);

    for (struct serial_info *port = port_list;
         port != NULL;
         port = port->next) {
        ei_encode_binary(resp, &resp_index, port->name, strlen(port->name));

        int info_count = (port->description ? 1 : 0) +
                (port->manufacturer ? 1 : 0) +
                (port->serial_number ? 1 : 0) +
                (port->vid > 0 ? 1 : 0) +
                (port->pid > 0 ? 1 : 0);

        ei_encode_map_header(resp, &resp_index, info_count);
        if (port->description) {
            ei_encode_atom(resp, &resp_index, "description");
            ei_encode_binary(resp, &resp_index, port->description, strlen(port->description));
        }
        if (port->manufacturer) {
            ei_encode_atom(resp, &resp_index, "manufacturer");
            ei_encode_binary(resp, &resp_index, port->manufacturer, strlen(port->manufacturer));
        }
        if (port->serial_number) {
            ei_encode_atom(resp, &resp_index, "serial_number");
            ei_encode_binary(resp, &resp_index, port->serial_number, strlen(port->serial_number));
        }
        if (port->vid > 0) {
            ei_encode_atom(resp, &resp_index, "vendor_id");
            ei_encode_ulong(resp, &resp_index, port->vid);
        }
        if (port->pid > 0) {
            ei_encode_atom(resp, &resp_index, "product_id");
            ei_encode_ulong(resp, &resp_index, port->pid);
        }
    }
    erlcmd_send(resp, resp_index);
    serial_info_free_list(port_list);
}
Example #5
0
/* Called when uart_read completes or fails */
static void handle_read_completed(int rc, const uint8_t *data, size_t len)
{
    if (rc >= 0) {
        char *resp = malloc(32 + len);
        int resp_index = sizeof(uint16_t);
        ei_encode_version(resp, &resp_index);
        ei_encode_tuple_header(resp, &resp_index, 2);
        ei_encode_atom(resp, &resp_index, "ok");
        ei_encode_binary(resp, &resp_index, data, len);
        erlcmd_send(resp, resp_index);
        free(resp);
    } else
        send_error_response(uart_last_error());
}
static void handle_configuration(const char *req, int *req_index)
{
    char resp[256];
    int resp_index = sizeof(uint16_t); // Space for payload size
    resp[resp_index++] = response_id;
    ei_encode_version(resp, &resp_index);

    ei_encode_list_header(resp, &resp_index, 5);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "speed");
    ei_encode_long(resp, &resp_index, current_config.speed);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "data_bits");
    ei_encode_long(resp, &resp_index, current_config.data_bits);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "stop_bits");
    ei_encode_long(resp, &resp_index, current_config.stop_bits);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "parity");
    switch (current_config.parity) {
    default:
    case UART_PARITY_NONE: ei_encode_atom(resp, &resp_index, "none"); break;
    case UART_PARITY_EVEN: ei_encode_atom(resp, &resp_index, "even"); break;
    case UART_PARITY_ODD: ei_encode_atom(resp, &resp_index, "odd"); break;
    case UART_PARITY_SPACE: ei_encode_atom(resp, &resp_index, "space"); break;
    case UART_PARITY_MARK: ei_encode_atom(resp, &resp_index, "mark"); break;
    case UART_PARITY_IGNORE: ei_encode_atom(resp, &resp_index, "ignore"); break;
    }

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "flow_control");
    switch (current_config.parity) {
    default:
    case UART_FLOWCONTROL_NONE: ei_encode_atom(resp, &resp_index, "none"); break;
    case UART_FLOWCONTROL_HARDWARE: ei_encode_atom(resp, &resp_index, "hardware"); break;
    case UART_FLOWCONTROL_SOFTWARE: ei_encode_atom(resp, &resp_index, "software"); break;
    }

    ei_encode_empty_list(resp, &resp_index);

    erlcmd_send(resp, resp_index);
}
Example #7
0
/* Called in active mode when there's a read or an error */
static void handle_notify_read(int error_reason, const uint8_t *data, size_t len)
{
    char *resp = malloc(64 + len);
    int resp_index = sizeof(uint16_t);
    ei_encode_version(resp, &resp_index);

    ei_encode_tuple_header(resp, &resp_index, 2);
    ei_encode_atom(resp, &resp_index, "notif");

    if (error_reason == 0) {
        // Normal receive
        ei_encode_binary(resp, &resp_index, data, len);
    } else {
        // Error notification
        ei_encode_tuple_header(resp, &resp_index, 2);
        ei_encode_atom(resp, &resp_index, "error");
        ei_encode_atom(resp, &resp_index, uart_last_error());
    }
    erlcmd_send(resp, resp_index);
    free(resp);
}
Example #8
0
static void i2c_handle_request(const char *req, void *cookie)
{
    struct i2c_info *i2c = (struct i2c_info *) cookie;

    // Commands are of the form {Command, Arguments}:
    // { atom(), term() }
    int req_index = sizeof(uint16_t);
    if (ei_decode_version(req, &req_index, NULL) < 0)
        errx(EXIT_FAILURE, "Message version issue?");

    int arity;
    if (ei_decode_tuple_header(req, &req_index, &arity) < 0 ||
            arity != 2)
        errx(EXIT_FAILURE, "expecting {cmd, args} tuple");

    char cmd[MAXATOMLEN];
    if (ei_decode_atom(req, &req_index, cmd) < 0)
        errx(EXIT_FAILURE, "expecting command atom");

    char resp[256];
    int resp_index = sizeof(uint16_t); // Space for payload size
    ei_encode_version(resp, &resp_index);
    if (strcmp(cmd, "read") == 0) {
        long int len;
        if (ei_decode_long(req, &req_index, &len) < 0 ||
                len < 1 ||
                len > I2C_SMBUS_BLOCK_MAX)
            errx(EXIT_FAILURE, "read amount: min=1, max=%d", I2C_SMBUS_BLOCK_MAX);

        char data[I2C_SMBUS_BLOCK_MAX];

        if (i2c_transfer(i2c, 0, 0, data, len))
            ei_encode_binary(resp, &resp_index, data,len);
        else {
            ei_encode_tuple_header(resp, &resp_index, 2);
            ei_encode_atom(resp, &resp_index, "error");
            ei_encode_atom(resp, &resp_index, "i2c_read_failed");
        }
    } else if (strcmp(cmd, "write") == 0) {
        char data[I2C_SMBUS_BLOCK_MAX];
        int len;
        int type;
        long llen;
        if (ei_get_type(req, &req_index, &type, &len) < 0 ||
                type != ERL_BINARY_EXT ||
                len < 1 ||
                len > I2C_SMBUS_BLOCK_MAX ||
                ei_decode_binary(req, &req_index, &data, &llen) < 0)
            errx(EXIT_FAILURE, "write: need a binary between 1 and %d bytes", I2C_SMBUS_BLOCK_MAX);

        if (i2c_transfer(i2c, data, len, 0, 0))
            ei_encode_atom(resp, &resp_index, "ok");
        else {
            ei_encode_tuple_header(resp, &resp_index, 2);
            ei_encode_atom(resp, &resp_index, "error");
            ei_encode_atom(resp, &resp_index, "i2c_write_failed");
        }
    } else if (strcmp(cmd, "wrrd") == 0) {
        char write_data[I2C_SMBUS_BLOCK_MAX];
        char read_data[I2C_SMBUS_BLOCK_MAX];
        int write_len;
        long int read_len;
        int type;
        long llen;

        if (ei_decode_tuple_header(req, &req_index, &arity) < 0 ||
            arity != 2)
            errx(EXIT_FAILURE, "wrrd: expecting {write_data, read_count} tuple");

        if (ei_get_type(req, &req_index, &type, &write_len) < 0 ||
                type != ERL_BINARY_EXT ||
                write_len < 1 ||
                write_len > I2C_SMBUS_BLOCK_MAX ||
                ei_decode_binary(req, &req_index, &write_data, &llen) < 0)
            errx(EXIT_FAILURE, "wrrd: need a binary between 1 and %d bytes", I2C_SMBUS_BLOCK_MAX);
        if (ei_decode_long(req, &req_index, &read_len) < 0 ||
                read_len < 1 ||
                read_len > I2C_SMBUS_BLOCK_MAX)
            errx(EXIT_FAILURE, "wrrd: read amount: min=1, max=%d", I2C_SMBUS_BLOCK_MAX);

        if (i2c_transfer(i2c, write_data, write_len, read_data, read_len))
            ei_encode_binary(resp, &resp_index, read_data, read_len);
        else {
            ei_encode_tuple_header(resp, &resp_index, 2);
            ei_encode_atom(resp, &resp_index, "error");
            ei_encode_atom(resp, &resp_index, "i2c_wrrd_failed");
        }
    } else
        errx(EXIT_FAILURE, "unknown command: %s", cmd);

    debug("sending response: %d bytes", resp_index);
    erlcmd_send(resp, resp_index);
}