Пример #1
0
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());
}
Пример #2
0
static void handle_flush(const char *req, int *req_index)
{
    char dirstr[MAXATOMLEN];
    if (ei_decode_atom(req, req_index, dirstr) < 0) {
        send_error_response("einval");
        return;
    }

    enum uart_direction direction;
    if (strcmp(dirstr, "receive") == 0)
        direction = UART_DIRECTION_RECEIVE;
    else if (strcmp(dirstr, "transmit") == 0)
        direction = UART_DIRECTION_TRANSMIT;
    else if (strcmp(dirstr, "both") == 0)
        direction = UART_DIRECTION_BOTH;
    else {
        send_error_response("einval");
        return;
    }

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

    if (uart_flush(uart, direction) >= 0)
        send_ok_response();
    else
        send_error_response(uart_last_error());
}
Пример #3
0
static void handle_write_completed(int rc, const uint8_t *data)
{
    free((uint8_t *) data);

    if (rc == 0)
        send_ok_response();
    else
        send_error_response(uart_last_error());
}
Пример #4
0
static void handle_drain(const char *req, int *req_index)
{
    (void) req;
    (void) req_index;
    if (!uart_is_open(uart)) {
        send_error_response("ebadf");
        return;
    }

    if (uart_drain(uart) >= 0)
        send_ok_response();
    else
        send_error_response(uart_last_error());
}
Пример #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());
}
Пример #6
0
static void handle_configure(const char *req, int *req_index)
{
    struct uart_config config = current_config;
    if (parse_option_list(req, req_index, &config) < 0) {
        send_error_response("einval");
        return;
    }

    if (uart_configure(uart, &config) >= 0) {
        current_config = config;
        send_ok_response();
    } else {
        send_error_response(uart_last_error());
    }
}
Пример #7
0
static void handle_set_break(const char *req, int *req_index)
{
    int val;
    if (ei_decode_boolean(req, req_index, &val) < 0) {
        send_error_response("einval");
        return;
    }

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

    if (uart_set_break(uart, !!val) >= 0)
        send_ok_response();
    else
        send_error_response(uart_last_error());
}
Пример #8
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);
}
Пример #9
0
/*
 * Handle {name, kv_list}
 *
 *    name is the serial port name
 *    kv_list a list of configuration values (speed, parity, etc.)
 */
static void handle_open(const char *req, int *req_index)
{
    int term_type;
    int term_size;

    if (ei_decode_tuple_header(req, req_index, &term_size) < 0 ||
            term_size != 2)
        errx(EXIT_FAILURE, ":open requires a 2-tuple");

    char name[32];
    long binary_len;
    if (ei_get_type(req, req_index, &term_type, &term_size) < 0 ||
            term_type != ERL_BINARY_EXT ||
            term_size >= (int) sizeof(name) ||
            ei_decode_binary(req, req_index, name, &binary_len) < 0) {
        // The name is almost certainly too long, so report that it
        // doesn't exist.
        send_error_response("enoent");
        return;
    }
    name[term_size] = '\0';

    struct uart_config config = current_config;
    if (parse_option_list(req, req_index, &config) < 0) {
        send_error_response("einval");
        return;
    }

    // If the uart was already open, close and open it again
    if (uart_is_open(uart))
        uart_close(uart);

    if (uart_open(uart, name, &config) >= 0) {
        current_config = config;
        send_ok_response();
    } else {
        send_error_response(uart_last_error());
    }
}
Пример #10
0
//--------------------------------------------------------------------------
// Transmit message over the bus. Message is readed from the given
// buffer position. While transmitting we check if bus is free and if
// same bit was recieved as transmitted. This ensures correct handling
// This method is time critical and interrupts will be disabled.
//--------------------------------------------------------------------------
posptr_t ibus_transmit_msg(posptr_t from, posptr_t len)
{
    posptr_t oldFrom = from;


#ifdef RXTX_COMPARE
    if (g_ibus_State != IBUS_STATE_TRANSMITTING) return from;
    IBUS_RX_DIS_INT();
#else
    if (IBUS_SENSTA_VALUE()) return from;
    // we currently disable interrupt of TH3122, we will ask it manually here
    IBUS_SENSTA_DIS_INT();
#endif

    while(len > 0)
    {
        // load byte to transmit
        uint8_t byte = g_ibus_TxBuffer[from];
        uint8_t sent = byte;
        uint8_t par  = 0;

        // transmit start bit and check if collision happens
        bit_clear(IBUS_TX_PORT, IBUS_TX_PIN);
        #ifdef RXTX_COMPARE
            IBUS_BAUD_HDELAY();
            if (IBUS_RX_VALUE() != 0) goto collision;
            IBUS_BAUD_HDELAY();
        #else
            IBUS_BAUD_DELAY();
            if (IBUS_SENSTA_VALUE()) goto collision;
        #endif

        // transmit bitwise and compute parity bit
        // while transmitting check if collision was detected
        int8_t i;
        for (i = 0; i < 8; i++, byte>>=1)
        {
            par ^= (byte & 1);
            if (byte & 1)
                bit_set(IBUS_TX_PORT, IBUS_TX_PIN);
            else
                bit_clear(IBUS_TX_PORT, IBUS_TX_PIN);

            #ifdef RXTX_COMPARE
                IBUS_BAUD_HDELAY();
                if (IBUS_RX_VALUE() != (byte & 1)) goto collision;
                IBUS_BAUD_HDELAY();
            #else
                IBUS_BAUD_DELAY();
                if (IBUS_SENSTA_VALUE()) goto collision;
            #endif
        }

        // send parity bit
        if (par & 1)
            bit_set(IBUS_TX_PORT, IBUS_TX_PIN);
        else
            bit_clear(IBUS_TX_PORT, IBUS_TX_PIN);

        #ifdef RXTX_COMPARE
            IBUS_BAUD_HDELAY();
            if (IBUS_RX_VALUE() != (par & 1)) goto collision;
            IBUS_BAUD_HDELAY();
        #else
            IBUS_BAUD_DELAY();
            if (IBUS_SENSTA_VALUE()) goto collision;
        #endif

        // send stop bit
        bit_set(IBUS_TX_PORT, IBUS_TX_PIN);
        #ifdef RXTX_COMPARE
            IBUS_BAUD_HDELAY();
            if (IBUS_RX_VALUE() != 1) goto collision;
            IBUS_BAUD_HDELAY();
        #else
            IBUS_BAUD_DELAY();
            if (IBUS_SENSTA_VALUE()) goto collision;
        #endif

        // update current pointers
        from = inc_posptr_tx(from);
        len--;

        // we should have now received the same byte through uart rx
        // check if there was no frame error and if the received byte is the right one
        if (!uart_available()) goto collision;
        if (uart_lastc() != sent) goto collision;
        if (uart_last_error()) goto collision;
    }

    // if everything went fine, then we will return new from position
    oldFrom = from;


// return on failure
collision:

    IBUS_TX_SETUP();
    #ifdef RXTX_COMPARE
        IBUS_RX_ENA_INT();
    #else
        IBUS_SENSTA_ENA_INT();
    #endif
    //END_ATOMAR;
    return oldFrom;
}
Пример #11
0
//--------------------------------------------------------------------------
void ibus_tick()
{
    // if we have data in the receive buffer, then handle it
    while(uart_available())
    {
        uint8_t data = uart_getc();

        if (uart_last_error())
        {
            uart_clear_error();
            g_ibus_State = IBUS_STATE_WAIT_FREE_BUS;
            IBUS_TIMEOUT_RECEIVE_ERROR();
            break;
        }else
            ibus_recieveCallback(data);
    }

    // if no data in the buffer or we are not idle, then do nothing
    if (!ibus_readyToTransmit()) return;
    
    // ok we are idle and we have data in the buffer, then first, wait for free buffer
    #ifndef RXTX_COMPARE
    if (IBUS_SENSTA_VALUE())
    {
        g_ibus_State = IBUS_STATE_WAIT_FREE_BUS;
        IBUS_TIMEOUT_WAIT_FREE_BUS();
        return;
    }
    #endif

    g_ibus_State = IBUS_STATE_TRANSMITTING;
    uart_clear_error(); // start fresh :)
    
    // ok bus is free, we can submit a message
    posptr_t tryCounterPos = g_ibus_TxReadPos;
    int8_t numberOfTries = g_ibus_TxBuffer[g_ibus_TxReadPos]; g_ibus_TxReadPos = inc_posptr_tx(g_ibus_TxReadPos);
    posptr_t len = (posptr_t)g_ibus_TxBuffer[(g_ibus_TxReadPos + 1) & IBUS_MSG_TX_BUFFER_SIZE_MASK];

    // transmit message
    posptr_t oldTxPos = g_ibus_TxReadPos;
    posptr_t newTxPos = ibus_transmit_msg(g_ibus_TxReadPos,  len + 2);
    
    // from here we are free to clear all errors
    uart_clear_error();

    // if there was a collision, then resend message if we still have trials
    if (newTxPos == oldTxPos)
    {
        numberOfTries--;
        if (numberOfTries >= 0)
        {
            g_ibus_TxBuffer[tryCounterPos] = numberOfTries;
            g_ibus_TxReadPos = tryCounterPos;

            g_ibus_State = IBUS_STATE_WAIT_FREE_BUS;
            IBUS_TIMEOUT_COLLISION();

            return;
        }
        newTxPos = (posptr_t)(oldTxPos + len + 2) & IBUS_MSG_TX_BUFFER_SIZE_MASK;

    // if there was no collision, then we have received the same message as sent, so just flush it
    }else
        uart_flush(0);

    // ok message was either submitted successfully or message trials
    // counter is elapsed, we flush tx buffer and continue
    g_ibus_TxReadPos = newTxPos;

    g_ibus_State = IBUS_STATE_WAIT_FREE_BUS;
    IBUS_TIMEOUT_AFTER_TRANSMIT();
}