123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694 |
- /*
- / _____) _ | |
- ( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
- (______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2020 Semtech
- Description:
- Host specific functions to address the LoRa concentrator registers through
- a USB interface.
- Single-byte read/write and burst read/write.
- License: Revised BSD License, see LICENSE.TXT file include in the project
- */
- /* -------------------------------------------------------------------------- */
- /* --- DEPENDANCIES --------------------------------------------------------- */
- #include <stdint.h> /* C99 types */
- #include <stdbool.h> /* bool type */
- #include <stdio.h> /* printf fprintf */
- #include <stdlib.h> /* rand */
- #include <unistd.h> /* lseek, close */
- #include <string.h> /* memset */
- #include <errno.h> /* Error number definitions */
- #include <termios.h> /* POSIX terminal control definitions */
- #include "loragw_mcu.h"
- #include "loragw_aux.h"
- /* -------------------------------------------------------------------------- */
- /* --- PRIVATE MACROS ------------------------------------------------------- */
- #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
- #if DEBUG_MCU == 1
- #define DEBUG_MSG(str) fprintf(stdout, str)
- #define DEBUG_PRINTF(fmt, args...) fprintf(stdout, fmt, args)
- #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return -1;}
- #else
- #define DEBUG_MSG(str)
- #define DEBUG_PRINTF(fmt, args...)
- #define CHECK_NULL(a) if(a==NULL){return -1;}
- #endif
- /* -------------------------------------------------------------------------- */
- /* --- PRIVATE CONSTANTS ---------------------------------------------------- */
- #if DEBUG_MCU == 1
- #define DEBUG_VERBOSE 0
- #endif
- #define HEADER_CMD_SIZE 4
- /* -------------------------------------------------------------------------- */
- /* --- PRIVATE TYPES -------------------------------------------------------- */
- typedef struct spi_req_bulk_s {
- uint16_t size;
- uint8_t nb_req;
- uint8_t buffer[LGW_USB_BURST_CHUNK];
- } spi_req_bulk_t;
- /* -------------------------------------------------------------------------- */
- /* --- PRIVATE VARIABLES --------------------------------------------------- */
- static uint8_t buf_hdr[HEADER_CMD_SIZE];
- static spi_req_bulk_t spi_bulk_buffer = {
- .size = 0,
- .nb_req = 0,
- .buffer = { 0 }
- };
- /* -------------------------------------------------------------------------- */
- /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
- int spi_req_bulk_insert(spi_req_bulk_t * bulk_buffer, uint8_t * req, uint16_t req_size) {
- /* Check input parameters */
- CHECK_NULL(bulk_buffer);
- CHECK_NULL(req);
- if (bulk_buffer->nb_req == 255) {
- printf("ERROR: cannot insert a new SPI request in bulk buffer - too many requests\n");
- return -1;
- }
- if ((bulk_buffer->size + req_size) > LGW_USB_BURST_CHUNK) {
- printf("ERROR: cannot insert a new SPI request in bulk buffer - buffer full\n");
- return -1;
- }
- /* Add a new request entry in storage buffer */
- memcpy(bulk_buffer->buffer + bulk_buffer->size, req, req_size);
- bulk_buffer->nb_req += 1;
- bulk_buffer->size += req_size;
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- uint32_t bytes_be_to_uint32_le(const uint8_t * bytes) {
- uint32_t val = 0;
- if (bytes != NULL) {
- /* Big endian to Little Endian */
- val = (uint32_t)(bytes[0] << 24);
- val |= (uint32_t)(bytes[1] << 16);
- val |= (uint32_t)(bytes[2] << 8);
- val |= (uint32_t)(bytes[3] << 0);
- }
- return val;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int32_t bytes_be_to_int32_le(const uint8_t * bytes) {
- int32_t val = 0;
- if (bytes != NULL) {
- /* Big endian to Little Endian */
- val = (int32_t)(bytes[0] << 24);
- val |= (int32_t)(bytes[1] << 16);
- val |= (int32_t)(bytes[2] << 8);
- val |= (int32_t)(bytes[3] << 0);
- }
- return val;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- const char * cmd_get_str(const uint8_t cmd) {
- switch (cmd) {
- case ORDER_ID__REQ_PING:
- return "REQ_PING";
- case ORDER_ID__REQ_GET_STATUS:
- return "REQ_GET_STATUS";
- case ORDER_ID__REQ_BOOTLOADER_MODE:
- return "REQ_BOOTLOADER_MODE";
- case ORDER_ID__REQ_RESET:
- return "REQ_RESET";
- case ORDER_ID__REQ_WRITE_GPIO:
- return "REQ_WRITE_GPIO";
- case ORDER_ID__REQ_MULTIPLE_SPI:
- return "REQ_MULTIPLE_SPI";
- default:
- return "UNKNOWN";
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- uint8_t cmd_get_id(const uint8_t * bytes) {
- return bytes[0];
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- uint16_t cmd_get_size(const uint8_t * bytes) {
- return (uint16_t)(bytes[1] << 8) | bytes[2];
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- uint8_t cmd_get_type(const uint8_t * bytes) {
- return bytes[3];
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- const char * spi_status_get_str(const uint8_t status) {
- switch (status) {
- case SPI_STATUS_OK:
- return "SPI_STATUS_OK";
- case SPI_STATUS_FAIL:
- return "SPI_STATUS_FAIL";
- case SPI_STATUS_WRONG_PARAM:
- return "SPI_STATUS_WRONG_PARAM";
- case SPI_STATUS_TIMEOUT:
- return "SPI_STATUS_TIMEOUT";
- default:
- return "SPI_STATUS_UNKNOWN";
- }
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int write_req(int fd, order_id_t cmd, const uint8_t * payload, uint16_t payload_size ) {
- uint8_t buf_w[HEADER_CMD_SIZE];
- int n;
- /* performances variables */
- struct timeval tm;
- /* debug variables */
- #if DEBUG_MCU == 1
- struct timeval write_tv;
- #endif
- /* Record function start time */
- _meas_time_start(&tm);
- /* Check input params */
- if (payload_size > MAX_SIZE_COMMAND) {
- printf("ERROR: payload size exceeds maximum transfer size (req:%u, max:%d)\n", payload_size, MAX_SIZE_COMMAND);
- return -1;
- }
- /* Write command header */
- buf_w[0] = rand() % 255;
- buf_w[1] = (uint8_t)(payload_size >> 8); /* MSB */
- buf_w[2] = (uint8_t)(payload_size >> 0); /* LSB */
- buf_w[3] = cmd;
- n = write(fd, buf_w, HEADER_CMD_SIZE);
- if (n < 0) {
- printf("ERROR: failed to write command header to com port\n");
- return -1;
- }
- /* Write command payload */
- if (payload_size > 0) {
- if (payload == NULL) {
- printf("ERROR: invalid payload\n");
- return -1;
- }
- n = write(fd, payload, payload_size);
- if (n < 0) {
- printf("ERROR: failed to write command payload to com port\n");
- return -1;
- }
- }
- #if DEBUG_MCU == 1
- gettimeofday(&write_tv, NULL);
- #endif
- DEBUG_PRINTF("\nINFO: %ld.%ld: write_req 0x%02X (%s) done, id:0x%02X, size:%u\n", write_tv.tv_sec, write_tv.tv_usec, cmd, cmd_get_str(cmd), buf_w[0], payload_size);
- #if DEBUG_VERBOSE
- int i;
- for (i = 0; i < 4; i++) {
- printf("%02X ", buf_w[i]);
- }
- for (i = 0; i < payload_size; i++) {
- printf("%02X ", payload[i]);
- }
- printf("\n");
- #endif
- /* Compute time spent in this function */
- _meas_time_stop(5, tm, __FUNCTION__);
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int read_ack(int fd, uint8_t * hdr, uint8_t * buf, size_t buf_size) {
- #if DEBUG_VERBOSE
- int i;
- #endif
- int n;
- size_t size;
- int nb_read = 0;
- /* performances variables */
- struct timeval tm;
- /* debug variables */
- #if DEBUG_MCU == 1
- struct timeval read_tv;
- #endif
- /* Record function start time */
- _meas_time_start(&tm);
- /* Read message header first, handle EINTR as it is a blocking call */
- do {
- n = read(fd, &hdr[0], (size_t)HEADER_CMD_SIZE);
- } while (n == -1 && errno == EINTR);
- if (n == -1) {
- perror("ERROR: Unable to read /dev/ttyACMx - ");
- return -1;
- } else {
- #if DEBUG_MCU == 1
- gettimeofday(&read_tv, NULL);
- #endif
- DEBUG_PRINTF("INFO: %ld.%ld: read %d bytes for header from gateway\n", read_tv.tv_sec, read_tv.tv_usec, n);
- }
- /* Compute time spent in this function */
- _meas_time_stop(5, tm, "read_ack(hdr)");
- #if DEBUG_VERBOSE
- printf("read_ack(hdr):");
- /* debug print */
- for (i = 0; i < (int)(HEADER_CMD_SIZE); i++) {
- printf("%02X ", hdr[i]);
- }
- printf("\n");
- #endif
- /* Record function start time */
- _meas_time_start(&tm);
- /* Check if the command id is valid */
- if ((cmd_get_type(hdr) < 0x40) || (cmd_get_type(hdr) > 0x46)) {
- printf("ERROR: received wrong ACK type (0x%02X)\n", cmd_get_type(hdr));
- return -1;
- }
- /* Get remaining payload size (metadata + pkt payload) */
- size = (size_t)cmd_get_size(hdr);
- if (size > buf_size) {
- printf("ERROR: not enough memory to store all data (%zd)\n", size);
- return -1;
- }
- /* Read payload if any */
- if (size > 0) {
- do {
- /* handle EINTR as it is a blocking call */
- do {
- n = read(fd, &buf[nb_read], size - nb_read);
- } while (n == -1 && errno == EINTR);
- if (n == -1) {
- perror("ERROR: Unable to read /dev/ttyACMx - ");
- return -1;
- } else {
- #if DEBUG_MCU == 1
- gettimeofday(&read_tv, NULL);
- #endif
- DEBUG_PRINTF("INFO: %ld.%ld: read %d bytes from gateway\n", read_tv.tv_sec, read_tv.tv_usec, n);
- nb_read += n;
- }
- } while (nb_read < (int)size); /* we want to read only the expected payload, not more */
- #if DEBUG_VERBOSE
- /* debug print */
- printf("read_ack(pld):");
- for (i = 0; i < (int)size; i++) {
- printf("%02X ", buf[i]);
- }
- printf("\n");
- #endif
- }
- /* Compute time spent in this function */
- _meas_time_stop(5, tm, "read_ack(payload)");
- return nb_read;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int decode_ack_ping(const uint8_t * hdr, const uint8_t * payload, s_ping_info * info) {
- /* sanity checks */
- if ((hdr == NULL) || (payload == NULL) || (info == NULL)) {
- printf("ERROR: invalid parameter\n");
- return -1;
- }
- if (cmd_get_type(hdr) != ORDER_ID__ACK_PING) {
- printf("ERROR: wrong ACK type for PING (expected:0x%02X, got 0x%02X)\n", ORDER_ID__ACK_PING, cmd_get_type(hdr));
- return -1;
- }
- /* payload info */
- info->unique_id_high = bytes_be_to_uint32_le(&payload[ACK_PING__UNIQUE_ID_0]);
- info->unique_id_mid = bytes_be_to_uint32_le(&payload[ACK_PING__UNIQUE_ID_4]);
- info->unique_id_low = bytes_be_to_uint32_le(&payload[ACK_PING__UNIQUE_ID_8]);
- memcpy(info->version, &payload[ACK_PING__VERSION_0], (sizeof info->version) - 1);
- info->version[(sizeof info->version) - 1] = '\0'; /* terminate string */
- #if DEBUG_VERBOSE
- DEBUG_MSG ("## ACK_PING\n");
- DEBUG_PRINTF(" id: 0x%02X\n", cmd_get_id(hdr));
- DEBUG_PRINTF(" size: %u\n", cmd_get_size(hdr));
- DEBUG_PRINTF(" unique_id: 0x%08X%08X%08X\n", info->unique_id_high, info->unique_id_mid, info->unique_id_low);
- DEBUG_PRINTF(" FW version: %s\n", info->version);
- #endif
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int decode_ack_bootloader_mode(const uint8_t * hdr) {
- /* sanity checks */
- if (hdr == NULL) {
- printf("ERROR: invalid parameter\n");
- return -1;
- }
- if (cmd_get_type(hdr) != ORDER_ID__ACK_BOOTLOADER_MODE) {
- printf("ERROR: wrong ACK type for ACK_BOOTLOADER_MODE (expected:0x%02X, got 0x%02X)\n", ORDER_ID__ACK_BOOTLOADER_MODE, cmd_get_type(hdr));
- return -1;
- }
- #if DEBUG_VERBOSE
- DEBUG_MSG ("## ACK_BOOTLOADER_MODE\n");
- DEBUG_PRINTF(" id: 0x%02X\n", cmd_get_id(hdr));
- DEBUG_PRINTF(" size: %u\n", cmd_get_size(hdr));
- #endif
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int decode_ack_get_status(const uint8_t * hdr, const uint8_t * payload, s_status * status) {
- int16_t temperature_sensor;
- /* sanity checks */
- if ((payload == NULL) || (status == NULL)) {
- printf("ERROR: invalid parameter\n");
- return -1;
- }
- if (cmd_get_type(hdr) != ORDER_ID__ACK_GET_STATUS) {
- printf("ERROR: wrong ACK type for GET_STATUS (expected:0x%02X, got 0x%02X)\n", ORDER_ID__ACK_GET_STATUS, cmd_get_type(hdr));
- return -1;
- }
- /* payload info */
- status->system_time_ms = bytes_be_to_uint32_le(&payload[ACK_GET_STATUS__SYSTEM_TIME_31_24]);
- temperature_sensor = (int16_t)(payload[ACK_GET_STATUS__TEMPERATURE_15_8] << 8) |
- (int16_t)(payload[ACK_GET_STATUS__TEMPERATURE_7_0] << 0);
- status->temperature = (float)temperature_sensor / 100.0;
- #if DEBUG_VERBOSE
- DEBUG_MSG ("## ACK_GET_STATUS\n");
- DEBUG_PRINTF(" id: 0x%02X\n", cmd_get_id(hdr));
- DEBUG_PRINTF(" size: %u\n", cmd_get_size(hdr));
- DEBUG_PRINTF(" sys_time: %u\n", status->system_time_ms);
- DEBUG_PRINTF(" temperature: %.1f\n", status->temperature);
- #endif
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int decode_ack_gpio_access(const uint8_t * hdr, const uint8_t * payload, uint8_t * write_status) {
- if ((hdr == NULL) || (payload == NULL) || (write_status == NULL)) {
- printf("ERROR: invalid parameter\n");
- return -1;
- }
- if (cmd_get_type(hdr) != ORDER_ID__ACK_WRITE_GPIO) {
- printf("ERROR: wrong ACK type for WRITE_GPIO (expected:0x%02X, got 0x%02X)\n", ORDER_ID__ACK_WRITE_GPIO, cmd_get_type(hdr));
- return -1;
- }
- /* payload info */
- *write_status = payload[ACK_GPIO_WRITE__STATUS];
- #if DEBUG_VERBOSE
- DEBUG_MSG ("## ACK_WRITE_GPIO\n");
- DEBUG_PRINTF(" id: 0x%02X\n", cmd_get_id(hdr));
- DEBUG_PRINTF(" size: %u\n", cmd_get_size(hdr));
- DEBUG_PRINTF(" status: %u\n", *write_status);
- #endif
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int decode_ack_spi_bulk(const uint8_t * hdr, const uint8_t * payload) {
- uint8_t req_id, req_type, req_status;
- uint16_t frame_size;
- int i;
- /* sanity checks */
- if ((hdr == NULL) || (payload == NULL)) {
- printf("ERROR: invalid parameter\n");
- return -1;
- }
- if (cmd_get_type(hdr) != ORDER_ID__ACK_MULTIPLE_SPI) {
- printf("ERROR: wrong ACK type for ACK_MULTIPLE_SPI (expected:0x%02X, got 0x%02X)\n", ORDER_ID__ACK_MULTIPLE_SPI, cmd_get_type(hdr));
- return -1;
- }
- #if DEBUG_VERBOSE
- DEBUG_MSG ("## ACK_SPI_BULK\n");
- DEBUG_PRINTF(" id: 0x%02X\n", cmd_get_id(hdr));
- DEBUG_PRINTF(" size: %u\n", cmd_get_size(hdr));
- #endif
- i = 0;
- while (i < cmd_get_size(hdr)) {
- /* parse the request */
- req_id = payload[i + 0];
- req_type = payload[i + 1];
- if (req_type != MCU_SPI_REQ_TYPE_READ_WRITE && req_type != MCU_SPI_REQ_TYPE_READ_MODIFY_WRITE) {
- printf("ERROR: %s: wrong type for SPI request %u (0x%02X)\n", __FUNCTION__, req_id, req_type);
- return -1;
- }
- req_status = payload[i + 2];
- if (req_status != 0) {
- /* Exit if any of the requests failed */
- printf("ERROR: %s: SPI request %u failed with %u - %s\n", __FUNCTION__, req_id, req_status, spi_status_get_str(req_status));
- return -1;
- }
- #if DEBUG_VERBOSE
- DEBUG_PRINTF(" ----- REQ_SPI %u -----\n", req_id);
- DEBUG_PRINTF(" type %s\n", (req_type == MCU_SPI_REQ_TYPE_READ_WRITE) ? "read/write" : "read-modify-write");
- DEBUG_PRINTF(" status %u\n", req_status);
- #endif
- /* Move to the next REQ */
- if (req_type == MCU_SPI_REQ_TYPE_READ_WRITE) {
- frame_size = (uint16_t)(payload[i + 3] << 8) | (uint16_t)(payload[i + 4]);
- #if DEBUG_VERBOSE
- int j;
- DEBUG_PRINTF(" RAW SPI frame (sz:%u): ", frame_size);
- for (j = 0; j < frame_size; j++) {
- DEBUG_PRINTF(" %02X", payload[i + 5 + j]);
- }
- DEBUG_MSG("\n");
- #endif
- i += (5 + frame_size); /* REQ ACK metadata + SPI raw frame */
- } else {
- #if DEBUG_VERBOSE
- DEBUG_PRINTF(" read value 0x%02X\n", payload[i + 3]);
- DEBUG_PRINTF(" modified value 0x%02X\n", payload[i + 4]);
- #endif
- i += 5;
- }
- }
- return 0;
- }
- /* -------------------------------------------------------------------------- */
- /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
- int mcu_ping(int fd, s_ping_info * info) {
- uint8_t buf_ack[ACK_PING_SIZE];
- CHECK_NULL(info);
- if (write_req(fd, ORDER_ID__REQ_PING, NULL, 0) != 0) {
- printf("ERROR: failed to write PING request\n");
- return -1;
- }
- if (read_ack(fd, buf_hdr, buf_ack, sizeof buf_ack) < 0) {
- printf("ERROR: failed to read PING ack\n");
- return -1;
- }
- if (decode_ack_ping(buf_hdr, buf_ack, info) != 0) {
- printf("ERROR: invalid PING ack\n");
- return -1;
- }
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int mcu_boot(int fd) {
- if (write_req(fd, ORDER_ID__REQ_BOOTLOADER_MODE, NULL, 0) != 0) {
- printf("ERROR: failed to write BOOTLOADER_MODE request\n");
- return -1;
- }
- if (read_ack(fd, buf_hdr, NULL, 0) < 0) {
- printf("ERROR: failed to read BOOTLOADER_MODE ack\n");
- return -1;
- }
- if (decode_ack_bootloader_mode(buf_hdr) != 0) {
- printf("ERROR: invalid BOOTLOADER_MODE ack\n");
- return -1;
- }
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int mcu_get_status(int fd, s_status * status) {
- uint8_t buf_ack[ACK_GET_STATUS_SIZE];
- CHECK_NULL(status);
- if (write_req(fd, ORDER_ID__REQ_GET_STATUS, NULL, 0) != 0) {
- printf("ERROR: failed to write GET_STATUS request\n");
- return -1;
- }
- if (read_ack(fd, buf_hdr, buf_ack, sizeof buf_ack) < 0) {
- printf("ERROR: failed to read GET_STATUS ack\n");
- return -1;
- }
- if (decode_ack_get_status(buf_hdr, buf_ack, status) != 0) {
- printf("ERROR: invalid GET_STATUS ack\n");
- return -1;
- }
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int mcu_gpio_write(int fd, uint8_t gpio_port, uint8_t gpio_id, uint8_t gpio_value) {
- uint8_t status;
- uint8_t buf_req[REQ_WRITE_GPIO_SIZE];
- uint8_t buf_ack[ACK_GPIO_WRITE_SIZE];
- buf_req[REQ_WRITE_GPIO__PORT] = gpio_port;
- buf_req[REQ_WRITE_GPIO__PIN] = gpio_id;
- buf_req[REQ_WRITE_GPIO__STATE] = gpio_value;
- if (write_req(fd, ORDER_ID__REQ_WRITE_GPIO, buf_req, REQ_WRITE_GPIO_SIZE) != 0) {
- printf("ERROR: failed to write REQ_WRITE_GPIO request\n");
- return -1;
- }
- if (read_ack(fd, buf_hdr, buf_ack, sizeof buf_ack) < 0) {
- printf("ERROR: failed to read PING ack\n");
- return -1;
- }
- if (decode_ack_gpio_access(buf_hdr, buf_ack, &status) != 0) {
- printf("ERROR: invalid REQ_WRITE_GPIO ack\n");
- return -1;
- }
- if (status != 0) {
- printf("ERROR: Failed to write GPIO (port:%u id:%u value:%u)\n", gpio_port, gpio_id, gpio_value);
- return -1;
- }
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int mcu_spi_write(int fd, uint8_t * in_out_buf, size_t buf_size) {
- /* Check input parameters */
- CHECK_NULL(in_out_buf);
- if (write_req(fd, ORDER_ID__REQ_MULTIPLE_SPI, in_out_buf, buf_size) != 0) {
- printf("ERROR: failed to write REQ_MULTIPLE_SPI request\n");
- return -1;
- }
- if (read_ack(fd, buf_hdr, in_out_buf, buf_size) < 0) {
- printf("ERROR: failed to read REQ_MULTIPLE_SPI ack\n");
- return -1;
- }
- if (decode_ack_spi_bulk(buf_hdr, in_out_buf) != 0) {
- printf("ERROR: invalid REQ_MULTIPLE_SPI ack\n");
- return -1;
- }
- return 0;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int mcu_spi_store(uint8_t * in_out_buf, size_t buf_size) {
- CHECK_NULL(in_out_buf);
- return spi_req_bulk_insert(&spi_bulk_buffer, in_out_buf, buf_size);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int mcu_spi_flush(int fd) {
- /* Write pending SPI requests to MCU */
- if (mcu_spi_write(fd, spi_bulk_buffer.buffer, spi_bulk_buffer.size) != 0) {
- printf("ERROR: %s: failed to write SPI requests to MCU\n", __FUNCTION__);
- return -1;
- }
- /* Reset bulk storage buffer */
- spi_bulk_buffer.nb_req = 0;
- spi_bulk_buffer.size = 0;
- return 0;
- }
- /* --- EOF ------------------------------------------------------------------ */
|