Damian Gabino / picoGW_hal
Committer:
dgabino
Date:
Wed Apr 11 14:38:42 2018 +0000
Revision:
0:102b50f941d0
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dgabino 0:102b50f941d0 1 /*
dgabino 0:102b50f941d0 2 / _____) _ | |
dgabino 0:102b50f941d0 3 ( (____ _____ ____ _| |_ _____ ____| |__
dgabino 0:102b50f941d0 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
dgabino 0:102b50f941d0 5 _____) ) ____| | | || |_| ____( (___| | | |
dgabino 0:102b50f941d0 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
dgabino 0:102b50f941d0 7 (C)2017 Semtech-Cycleo
dgabino 0:102b50f941d0 8
dgabino 0:102b50f941d0 9 Description:
dgabino 0:102b50f941d0 10 this file contains the USB commands to configure and communicate with the SX1308
dgabino 0:102b50f941d0 11 LoRA concentrator.
dgabino 0:102b50f941d0 12 A USB CDC drivers is required to establish the connection with the PicoCell
dgabino 0:102b50f941d0 13 board.
dgabino 0:102b50f941d0 14
dgabino 0:102b50f941d0 15 License: Revised BSD License, see LICENSE.TXT file include in the project
dgabino 0:102b50f941d0 16 */
dgabino 0:102b50f941d0 17
dgabino 0:102b50f941d0 18
dgabino 0:102b50f941d0 19 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 20 /* --- DEPENDANCIES --------------------------------------------------------- */
dgabino 0:102b50f941d0 21
dgabino 0:102b50f941d0 22 #include <stdint.h> /* C99 types */
dgabino 0:102b50f941d0 23 #include <stdio.h> /* printf fprintf */
dgabino 0:102b50f941d0 24 #include <stdlib.h> /* malloc free */
dgabino 0:102b50f941d0 25 #include <unistd.h> /* lseek, close */
dgabino 0:102b50f941d0 26 #include <fcntl.h> /* open */
dgabino 0:102b50f941d0 27 #include <string.h> /* memset */
dgabino 0:102b50f941d0 28 #include <errno.h> /* Error number definitions */
dgabino 0:102b50f941d0 29 #include <termios.h> /* POSIX terminal control definitions */
dgabino 0:102b50f941d0 30 #include <sys/ioctl.h>
dgabino 0:102b50f941d0 31 #include <pthread.h>
dgabino 0:102b50f941d0 32 #include <time.h>
dgabino 0:102b50f941d0 33 #include <sys/select.h>
dgabino 0:102b50f941d0 34
dgabino 0:102b50f941d0 35 #include "loragw_com.h"
dgabino 0:102b50f941d0 36 #include "loragw_com_linux.h"
dgabino 0:102b50f941d0 37 #include "loragw_aux.h"
dgabino 0:102b50f941d0 38 #include "loragw_reg.h"
dgabino 0:102b50f941d0 39 #include "loragw_mcu.h"
dgabino 0:102b50f941d0 40
dgabino 0:102b50f941d0 41 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 42 /* --- PRIVATE MACROS ------------------------------------------------------- */
dgabino 0:102b50f941d0 43
dgabino 0:102b50f941d0 44 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
dgabino 0:102b50f941d0 45 #if DEBUG_COM == 1
dgabino 0:102b50f941d0 46 #define DEBUG_MSG(str) fprintf(stderr, str)
dgabino 0:102b50f941d0 47 #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
dgabino 0:102b50f941d0 48 #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_COM_ERROR;}
dgabino 0:102b50f941d0 49 #else
dgabino 0:102b50f941d0 50 #define DEBUG_MSG(str)
dgabino 0:102b50f941d0 51 #define DEBUG_PRINTF(fmt, args...)
dgabino 0:102b50f941d0 52 #define CHECK_NULL(a) if(a==NULL){return LGW_COM_ERROR;}
dgabino 0:102b50f941d0 53 #endif
dgabino 0:102b50f941d0 54
dgabino 0:102b50f941d0 55 #define UNUSED(x) (void)(x)
dgabino 0:102b50f941d0 56
dgabino 0:102b50f941d0 57 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 58 /* --- PRIVATE SHARED VARIABLES (GLOBAL) ------------------------------------ */
dgabino 0:102b50f941d0 59
dgabino 0:102b50f941d0 60 extern pthread_mutex_t mx_usbbridgesync;
dgabino 0:102b50f941d0 61
dgabino 0:102b50f941d0 62 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 63 /* --- PRIVATE FUNCTIONS ---------------------------------------------------- */
dgabino 0:102b50f941d0 64
dgabino 0:102b50f941d0 65 int set_interface_attribs_linux(int fd, int speed) {
dgabino 0:102b50f941d0 66 struct termios tty;
dgabino 0:102b50f941d0 67
dgabino 0:102b50f941d0 68 memset(&tty, 0, sizeof tty);
dgabino 0:102b50f941d0 69
dgabino 0:102b50f941d0 70 /* Get current attributes */
dgabino 0:102b50f941d0 71 if (tcgetattr(fd, &tty) != 0) {
dgabino 0:102b50f941d0 72 DEBUG_PRINTF("ERROR: tcgetattr failed with %d - %s", errno, strerror(errno));
dgabino 0:102b50f941d0 73 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 74 }
dgabino 0:102b50f941d0 75
dgabino 0:102b50f941d0 76 cfsetospeed(&tty, speed);
dgabino 0:102b50f941d0 77 cfsetispeed(&tty, speed);
dgabino 0:102b50f941d0 78
dgabino 0:102b50f941d0 79 /* Control Modes */
dgabino 0:102b50f941d0 80 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; /* set 8-bit characters */
dgabino 0:102b50f941d0 81 tty.c_cflag |= CLOCAL; /* local connection, no modem control */
dgabino 0:102b50f941d0 82 tty.c_cflag |= CREAD; /* enable receiving characters */
dgabino 0:102b50f941d0 83 tty.c_cflag &= ~PARENB; /* no parity */
dgabino 0:102b50f941d0 84 tty.c_cflag &= ~CSTOPB; /* one stop bit */
dgabino 0:102b50f941d0 85 /* Input Modes */
dgabino 0:102b50f941d0 86 tty.c_iflag &= ~IGNBRK;
dgabino 0:102b50f941d0 87 tty.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL);
dgabino 0:102b50f941d0 88 /* Output Modes */
dgabino 0:102b50f941d0 89 tty.c_oflag &= ~IGNBRK;
dgabino 0:102b50f941d0 90 tty.c_oflag &= ~(IXON | IXOFF | IXANY | ICRNL);
dgabino 0:102b50f941d0 91 /* Local Modes */
dgabino 0:102b50f941d0 92 tty.c_lflag = 0;
dgabino 0:102b50f941d0 93 /* Settings for non-canonical mode */
dgabino 0:102b50f941d0 94 tty.c_cc[VMIN] = 0; /* non-blocking mode */
dgabino 0:102b50f941d0 95 tty.c_cc[VTIME] = 50; /* wait for (n * 0.1) seconds before returning */
dgabino 0:102b50f941d0 96
dgabino 0:102b50f941d0 97 /* Set attributes */
dgabino 0:102b50f941d0 98 if (tcsetattr(fd, TCSANOW, &tty) != 0) {
dgabino 0:102b50f941d0 99 DEBUG_PRINTF("ERROR: tcsetattr failed with %d - %s", errno, strerror(errno));
dgabino 0:102b50f941d0 100 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 101 }
dgabino 0:102b50f941d0 102
dgabino 0:102b50f941d0 103 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 104 }
dgabino 0:102b50f941d0 105
dgabino 0:102b50f941d0 106 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 107
dgabino 0:102b50f941d0 108 /* configure TTYACM0 read blocking or not*/
dgabino 0:102b50f941d0 109 int set_blocking_linux(int fd, bool blocking) {
dgabino 0:102b50f941d0 110 struct termios tty;
dgabino 0:102b50f941d0 111
dgabino 0:102b50f941d0 112 memset(&tty, 0, sizeof tty);
dgabino 0:102b50f941d0 113
dgabino 0:102b50f941d0 114 /* Get current attributes */
dgabino 0:102b50f941d0 115 if (tcgetattr(fd, &tty) != 0) {
dgabino 0:102b50f941d0 116 DEBUG_PRINTF("ERROR: tcgetattr failed with %d - %s", errno, strerror(errno));
dgabino 0:102b50f941d0 117 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 118 }
dgabino 0:102b50f941d0 119
dgabino 0:102b50f941d0 120 tty.c_cc[VMIN] = (blocking == true) ? 1 : 0; /* set blocking or non-blocking mode */
dgabino 0:102b50f941d0 121 tty.c_cc[VTIME] = 1; /* wait for (n * 0.1) seconds before returning */
dgabino 0:102b50f941d0 122
dgabino 0:102b50f941d0 123 /* Set attributes */
dgabino 0:102b50f941d0 124 if (tcsetattr(fd, TCSANOW, &tty) != 0) {
dgabino 0:102b50f941d0 125 DEBUG_PRINTF("ERROR: tcsetattr failed with %d - %s", errno, strerror(errno));
dgabino 0:102b50f941d0 126 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 127 }
dgabino 0:102b50f941d0 128
dgabino 0:102b50f941d0 129 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 130 }
dgabino 0:102b50f941d0 131
dgabino 0:102b50f941d0 132 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 133
dgabino 0:102b50f941d0 134 bool checkcmd_linux(uint8_t cmd) {
dgabino 0:102b50f941d0 135 switch (cmd) {
dgabino 0:102b50f941d0 136 case 'r': /* read register */
dgabino 0:102b50f941d0 137 case 's': /* read burst - first chunk */
dgabino 0:102b50f941d0 138 case 't': /* read burst - middle chunk */
dgabino 0:102b50f941d0 139 case 'u': /* read burst - end chunk */
dgabino 0:102b50f941d0 140 case 'p': /* read burst - atomic */
dgabino 0:102b50f941d0 141 case 'w': /* write register */
dgabino 0:102b50f941d0 142 case 'x': /* write burst - first chunk */
dgabino 0:102b50f941d0 143 case 'y': /* write burst - middle chunk */
dgabino 0:102b50f941d0 144 case 'z': /* write burst - end chunk */
dgabino 0:102b50f941d0 145 case 'a': /* write burst - atomic */
dgabino 0:102b50f941d0 146 case 'b': /* lgw_receive */
dgabino 0:102b50f941d0 147 case 'c': /* lgw_rxrf_setconf */
dgabino 0:102b50f941d0 148 case 'd': /* lgw_rxif_setconf */
dgabino 0:102b50f941d0 149 case 'f': /* lgw_send */
dgabino 0:102b50f941d0 150 case 'h': /* lgw_txgain_setconf */
dgabino 0:102b50f941d0 151 case 'q': /* lgw_get_trigcnt */
dgabino 0:102b50f941d0 152 case 'i': /* lgw_board_setconf */
dgabino 0:102b50f941d0 153 case 'j': /* lgw_calibration_snapshot */
dgabino 0:102b50f941d0 154 case 'l': /* lgw_check_fw_version */
dgabino 0:102b50f941d0 155 case 'm': /* reset STM32 */
dgabino 0:102b50f941d0 156 case 'n': /* Go to bootloader */
dgabino 0:102b50f941d0 157 return true;
dgabino 0:102b50f941d0 158 default:
dgabino 0:102b50f941d0 159 return false;
dgabino 0:102b50f941d0 160 }
dgabino 0:102b50f941d0 161 }
dgabino 0:102b50f941d0 162
dgabino 0:102b50f941d0 163 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 164
dgabino 0:102b50f941d0 165 int lgw_com_send_cmd_linux(lgw_com_cmd_t cmd, lgw_handle_t handle) {
dgabino 0:102b50f941d0 166 int i;
dgabino 0:102b50f941d0 167 uint8_t buffertx[CMD_HEADER_TX_SIZE + CMD_DATA_TX_SIZE];
dgabino 0:102b50f941d0 168 uint16_t Clen = cmd.len_lsb + (cmd.len_msb << 8);
dgabino 0:102b50f941d0 169 uint16_t Tlen = CMD_HEADER_TX_SIZE + Clen;
dgabino 0:102b50f941d0 170 ssize_t lencheck;
dgabino 0:102b50f941d0 171
dgabino 0:102b50f941d0 172 /* Initialize buffer */
dgabino 0:102b50f941d0 173 memset(buffertx, 0, sizeof buffertx);
dgabino 0:102b50f941d0 174
dgabino 0:102b50f941d0 175 /* Prepare command */
dgabino 0:102b50f941d0 176 buffertx[0] = (uint8_t)cmd.id;
dgabino 0:102b50f941d0 177 buffertx[1] = cmd.len_msb;
dgabino 0:102b50f941d0 178 buffertx[2] = cmd.len_lsb;
dgabino 0:102b50f941d0 179 buffertx[3] = cmd.address;
dgabino 0:102b50f941d0 180 for (i = 0; i < Clen; i++) {
dgabino 0:102b50f941d0 181 buffertx[i + 4] = cmd.cmd_data[i];
dgabino 0:102b50f941d0 182 }
dgabino 0:102b50f941d0 183
dgabino 0:102b50f941d0 184 /* Send command */
dgabino 0:102b50f941d0 185 lencheck = write(handle, buffertx, Tlen);
dgabino 0:102b50f941d0 186 if (lencheck < 0) {
dgabino 0:102b50f941d0 187 DEBUG_PRINTF("ERROR: failed to write cmd (%d - %s)\n", errno, strerror(errno));
dgabino 0:102b50f941d0 188 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 189 }
dgabino 0:102b50f941d0 190 if (lencheck != Tlen) {
dgabino 0:102b50f941d0 191 DEBUG_PRINTF("WARNING: incomplete cmd written (%d)\n", (int)lencheck);
dgabino 0:102b50f941d0 192 }
dgabino 0:102b50f941d0 193
dgabino 0:102b50f941d0 194 DEBUG_PRINTF("Note: sent cmd \'%c\', addr 0x%02X, length=%d\n", cmd.id, cmd.address, Clen);
dgabino 0:102b50f941d0 195
dgabino 0:102b50f941d0 196 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 197 }
dgabino 0:102b50f941d0 198
dgabino 0:102b50f941d0 199 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 200
dgabino 0:102b50f941d0 201 int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) {
dgabino 0:102b50f941d0 202 int i;
dgabino 0:102b50f941d0 203 uint8_t bufferrx[CMD_HEADER_RX_SIZE + CMD_DATA_RX_SIZE];
dgabino 0:102b50f941d0 204 unsigned int buffer_idx;
dgabino 0:102b50f941d0 205 size_t cmd_size;
dgabino 0:102b50f941d0 206 ssize_t buf_size = 0;
dgabino 0:102b50f941d0 207 ssize_t lencheck;
dgabino 0:102b50f941d0 208
dgabino 0:102b50f941d0 209 /* Initialize variables */
dgabino 0:102b50f941d0 210 memset(bufferrx, 0, sizeof bufferrx);
dgabino 0:102b50f941d0 211
dgabino 0:102b50f941d0 212 /* Wait for cmd answer header */
dgabino 0:102b50f941d0 213 buffer_idx = 0;
dgabino 0:102b50f941d0 214 while ((checkcmd_linux(bufferrx[0]) != true) || (buffer_idx < CMD_HEADER_RX_SIZE)) {
dgabino 0:102b50f941d0 215 lencheck = read(handle, &bufferrx[buffer_idx], CMD_HEADER_RX_SIZE - buffer_idx);
dgabino 0:102b50f941d0 216 if (lencheck < 0) {
dgabino 0:102b50f941d0 217 DEBUG_PRINTF("WARNING: failed to read from communication bridge (%d - %s), retry...\n", errno, strerror(errno));
dgabino 0:102b50f941d0 218 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 219 }
dgabino 0:102b50f941d0 220 buffer_idx += lencheck;
dgabino 0:102b50f941d0 221 }
dgabino 0:102b50f941d0 222
dgabino 0:102b50f941d0 223 cmd_size = (bufferrx[1] << 8) + bufferrx[2];
dgabino 0:102b50f941d0 224
dgabino 0:102b50f941d0 225 DEBUG_PRINTF("Note: received answer header for cmd \'%c\', length=%zd, ack=%u\n", bufferrx[0], cmd_size, bufferrx[3]);
dgabino 0:102b50f941d0 226
dgabino 0:102b50f941d0 227 /* Read answer Data */
dgabino 0:102b50f941d0 228 if (cmd_size > 0) {
dgabino 0:102b50f941d0 229 /* Determine how much we need to read */
dgabino 0:102b50f941d0 230 buf_size = cmd_size + CMD_HEADER_RX_SIZE;
dgabino 0:102b50f941d0 231 if ((buf_size % 64) == 0) {
dgabino 0:102b50f941d0 232 cmd_size = cmd_size + 1; /* one padding byte is added by USB driver, we need to read it */
dgabino 0:102b50f941d0 233 }
dgabino 0:102b50f941d0 234 /* Check that data size does not exceed buffer size */
dgabino 0:102b50f941d0 235 if (cmd_size > CMD_DATA_RX_SIZE) {
dgabino 0:102b50f941d0 236 DEBUG_PRINTF("ERROR: exceed read buffer size, abort. (%zd)\n", cmd_size);
dgabino 0:102b50f941d0 237 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 238 }
dgabino 0:102b50f941d0 239 /* Read the answer */
dgabino 0:102b50f941d0 240 buffer_idx = 0;
dgabino 0:102b50f941d0 241 while (buffer_idx < cmd_size) {
dgabino 0:102b50f941d0 242 lencheck = read(handle, &bufferrx[CMD_HEADER_RX_SIZE + buffer_idx], cmd_size - buffer_idx);
dgabino 0:102b50f941d0 243 if (lencheck < 0) {
dgabino 0:102b50f941d0 244 DEBUG_PRINTF("ERROR: failed to read cmd answer (%d - %s)\n", errno, strerror(errno));
dgabino 0:102b50f941d0 245 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 246 }
dgabino 0:102b50f941d0 247 buffer_idx += lencheck;
dgabino 0:102b50f941d0 248 }
dgabino 0:102b50f941d0 249 }
dgabino 0:102b50f941d0 250 ans->id = (char)bufferrx[0];
dgabino 0:102b50f941d0 251 ans->len_msb = bufferrx[1];
dgabino 0:102b50f941d0 252 ans->len_lsb = bufferrx[2];
dgabino 0:102b50f941d0 253 ans->status = bufferrx[3];
dgabino 0:102b50f941d0 254 for (i = 0; i < (int)cmd_size; i++) {
dgabino 0:102b50f941d0 255 ans->ans_data[i] = bufferrx[CMD_HEADER_RX_SIZE + i];
dgabino 0:102b50f941d0 256 }
dgabino 0:102b50f941d0 257
dgabino 0:102b50f941d0 258 DEBUG_PRINTF("Note: received answer for cmd \'%c\', length=%zd\n", bufferrx[0], cmd_size);
dgabino 0:102b50f941d0 259
dgabino 0:102b50f941d0 260 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 261 }
dgabino 0:102b50f941d0 262
dgabino 0:102b50f941d0 263 /* -------------------------------------------------------------------------- */
dgabino 0:102b50f941d0 264 /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
dgabino 0:102b50f941d0 265
dgabino 0:102b50f941d0 266 int lgw_com_open_linux(void **com_target_ptr, const char *com_path) {
dgabino 0:102b50f941d0 267
dgabino 0:102b50f941d0 268 int *usb_device = NULL;
dgabino 0:102b50f941d0 269 char portname[50];
dgabino 0:102b50f941d0 270 int x;
dgabino 0:102b50f941d0 271 int fd;
dgabino 0:102b50f941d0 272
dgabino 0:102b50f941d0 273 /*check input variables*/
dgabino 0:102b50f941d0 274 CHECK_NULL(com_target_ptr);
dgabino 0:102b50f941d0 275
dgabino 0:102b50f941d0 276 usb_device = malloc(sizeof(int));
dgabino 0:102b50f941d0 277 if (usb_device == NULL) {
dgabino 0:102b50f941d0 278 DEBUG_MSG("ERROR : MALLOC FAIL\n");
dgabino 0:102b50f941d0 279 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 280 }
dgabino 0:102b50f941d0 281
dgabino 0:102b50f941d0 282 /* open tty port */
dgabino 0:102b50f941d0 283 sprintf(portname, "%s", com_path);
dgabino 0:102b50f941d0 284 fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
dgabino 0:102b50f941d0 285 if (fd < 0) {
dgabino 0:102b50f941d0 286 printf("ERROR: failed to open COM port %s - %s\n", portname, strerror(errno));
dgabino 0:102b50f941d0 287 } else {
dgabino 0:102b50f941d0 288 x = set_interface_attribs_linux(fd, B115200);
dgabino 0:102b50f941d0 289 x |= set_blocking_linux(fd, true);
dgabino 0:102b50f941d0 290 if (x != 0) {
dgabino 0:102b50f941d0 291 printf("ERROR: failed to configure COM port %s\n", portname);
dgabino 0:102b50f941d0 292 free(usb_device);
dgabino 0:102b50f941d0 293 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 294 }
dgabino 0:102b50f941d0 295
dgabino 0:102b50f941d0 296 *usb_device = fd;
dgabino 0:102b50f941d0 297 *com_target_ptr = (void*)usb_device;
dgabino 0:102b50f941d0 298
dgabino 0:102b50f941d0 299 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 300 }
dgabino 0:102b50f941d0 301
dgabino 0:102b50f941d0 302 free(usb_device);
dgabino 0:102b50f941d0 303 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 304 }
dgabino 0:102b50f941d0 305
dgabino 0:102b50f941d0 306 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 307
dgabino 0:102b50f941d0 308 int lgw_com_close_linux(void *com_target) {
dgabino 0:102b50f941d0 309 int usb_device;
dgabino 0:102b50f941d0 310 int a;
dgabino 0:102b50f941d0 311
dgabino 0:102b50f941d0 312 /*check input variables*/
dgabino 0:102b50f941d0 313 CHECK_NULL(com_target);
dgabino 0:102b50f941d0 314
dgabino 0:102b50f941d0 315 /* close file & deallocate file descriptor */
dgabino 0:102b50f941d0 316 usb_device = *(int*)com_target;
dgabino 0:102b50f941d0 317 a = close(usb_device);
dgabino 0:102b50f941d0 318 free(com_target);
dgabino 0:102b50f941d0 319
dgabino 0:102b50f941d0 320 /* determine return code */
dgabino 0:102b50f941d0 321 if (a < 0) {
dgabino 0:102b50f941d0 322 printf("ERROR: failed to close COM port - %s\n", strerror(errno));
dgabino 0:102b50f941d0 323 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 324 } else {
dgabino 0:102b50f941d0 325 DEBUG_MSG("Note : USB port closed\n");
dgabino 0:102b50f941d0 326 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 327 }
dgabino 0:102b50f941d0 328 }
dgabino 0:102b50f941d0 329
dgabino 0:102b50f941d0 330 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 331
dgabino 0:102b50f941d0 332 int lgw_com_w_linux(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t data) {
dgabino 0:102b50f941d0 333 int fd;
dgabino 0:102b50f941d0 334 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 335 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 336 UNUSED(com_mux_mode);
dgabino 0:102b50f941d0 337 UNUSED(com_mux_target);
dgabino 0:102b50f941d0 338
dgabino 0:102b50f941d0 339 /*check input variables*/
dgabino 0:102b50f941d0 340 CHECK_NULL(com_target);
dgabino 0:102b50f941d0 341
dgabino 0:102b50f941d0 342 fd = *(int *)com_target; /* must check that com_target is not null beforehand */
dgabino 0:102b50f941d0 343
dgabino 0:102b50f941d0 344 cmd.id = 'w';
dgabino 0:102b50f941d0 345 cmd.len_msb = 0;
dgabino 0:102b50f941d0 346 cmd.len_lsb = 1;
dgabino 0:102b50f941d0 347 cmd.address = address;
dgabino 0:102b50f941d0 348 cmd.cmd_data[0] = data;
dgabino 0:102b50f941d0 349
dgabino 0:102b50f941d0 350 pthread_mutex_lock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 351 lgw_com_send_cmd_linux(cmd, fd);
dgabino 0:102b50f941d0 352 if (lgw_com_receive_ans_linux(&ans, fd) == LGW_COM_ERROR) {
dgabino 0:102b50f941d0 353 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 354 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 355 }
dgabino 0:102b50f941d0 356 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 357
dgabino 0:102b50f941d0 358 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 359 }
dgabino 0:102b50f941d0 360
dgabino 0:102b50f941d0 361 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 362
dgabino 0:102b50f941d0 363 int lgw_com_r_linux(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data) {
dgabino 0:102b50f941d0 364 int fd;
dgabino 0:102b50f941d0 365 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 366 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 367 UNUSED(com_mux_mode);
dgabino 0:102b50f941d0 368 UNUSED(com_mux_target);
dgabino 0:102b50f941d0 369
dgabino 0:102b50f941d0 370 /* check input variables */
dgabino 0:102b50f941d0 371 CHECK_NULL(com_target);
dgabino 0:102b50f941d0 372 CHECK_NULL(data);
dgabino 0:102b50f941d0 373
dgabino 0:102b50f941d0 374 fd = *(int *)com_target; /* must check that com_target is not null beforehand */
dgabino 0:102b50f941d0 375
dgabino 0:102b50f941d0 376 cmd.id = 'r';
dgabino 0:102b50f941d0 377 cmd.len_msb = 0;
dgabino 0:102b50f941d0 378 cmd.len_lsb = 1;
dgabino 0:102b50f941d0 379 cmd.address = address;
dgabino 0:102b50f941d0 380 cmd.cmd_data[0] = 0;
dgabino 0:102b50f941d0 381
dgabino 0:102b50f941d0 382 pthread_mutex_lock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 383 lgw_com_send_cmd_linux(cmd, fd);
dgabino 0:102b50f941d0 384 if (lgw_com_receive_ans_linux(&ans, fd) == LGW_COM_ERROR) {
dgabino 0:102b50f941d0 385 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 386 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 387 }
dgabino 0:102b50f941d0 388 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 389
dgabino 0:102b50f941d0 390 *data = ans.ans_data[0];
dgabino 0:102b50f941d0 391
dgabino 0:102b50f941d0 392 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 393 }
dgabino 0:102b50f941d0 394
dgabino 0:102b50f941d0 395 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 396
dgabino 0:102b50f941d0 397 int lgw_com_wb_linux(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data, uint16_t size) {
dgabino 0:102b50f941d0 398 int fd;
dgabino 0:102b50f941d0 399 int i;
dgabino 0:102b50f941d0 400 uint16_t chunk_size = size;
dgabino 0:102b50f941d0 401 int cptalc = 0;
dgabino 0:102b50f941d0 402 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 403 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 404 UNUSED(com_mux_mode);
dgabino 0:102b50f941d0 405 UNUSED(com_mux_target);
dgabino 0:102b50f941d0 406
dgabino 0:102b50f941d0 407 /* check input parameters */
dgabino 0:102b50f941d0 408 CHECK_NULL(com_target);
dgabino 0:102b50f941d0 409 CHECK_NULL(data);
dgabino 0:102b50f941d0 410
dgabino 0:102b50f941d0 411 fd = *(int *)com_target;
dgabino 0:102b50f941d0 412
dgabino 0:102b50f941d0 413 /* lock for complete burst */
dgabino 0:102b50f941d0 414 pthread_mutex_lock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 415
dgabino 0:102b50f941d0 416 /* Split burst in multiple chunks if necessary */
dgabino 0:102b50f941d0 417 while (chunk_size > ATOMICTX) {
dgabino 0:102b50f941d0 418 /* Prepare command */
dgabino 0:102b50f941d0 419 if (chunk_size == size) {
dgabino 0:102b50f941d0 420 cmd.id = 'x'; /* write burst - first */
dgabino 0:102b50f941d0 421 } else {
dgabino 0:102b50f941d0 422 cmd.id = 'y'; /* write burst - middle */
dgabino 0:102b50f941d0 423 }
dgabino 0:102b50f941d0 424 cmd.len_msb = (uint8_t)((ATOMICTX >> 8) & 0xFF);
dgabino 0:102b50f941d0 425 cmd.len_lsb = (uint8_t)((ATOMICTX >> 0) & 0xFF);
dgabino 0:102b50f941d0 426 cmd.address = address;
dgabino 0:102b50f941d0 427 for (i = 0; i < ATOMICTX; i++) {
dgabino 0:102b50f941d0 428 cmd.cmd_data[i] = data[i + cptalc];
dgabino 0:102b50f941d0 429 }
dgabino 0:102b50f941d0 430
dgabino 0:102b50f941d0 431 /* Send command */
dgabino 0:102b50f941d0 432 lgw_com_send_cmd_linux(cmd, fd);
dgabino 0:102b50f941d0 433 if (lgw_com_receive_ans_linux(&ans, fd) == LGW_COM_ERROR) {
dgabino 0:102b50f941d0 434 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 435 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 436 }
dgabino 0:102b50f941d0 437
dgabino 0:102b50f941d0 438 chunk_size = chunk_size - ATOMICTX;
dgabino 0:102b50f941d0 439 cptalc = cptalc + ATOMICTX;
dgabino 0:102b50f941d0 440 }
dgabino 0:102b50f941d0 441
dgabino 0:102b50f941d0 442 /* Complete multiple-chunk transfer, or send atomic one */
dgabino 0:102b50f941d0 443 if (chunk_size > 0) {
dgabino 0:102b50f941d0 444 /* Prepare command */
dgabino 0:102b50f941d0 445 if (size <= ATOMICTX) {
dgabino 0:102b50f941d0 446 cmd.id = 'a'; /* write burst - atomic */
dgabino 0:102b50f941d0 447 } else {
dgabino 0:102b50f941d0 448 cmd.id = 'z'; /* write burst - end */
dgabino 0:102b50f941d0 449 }
dgabino 0:102b50f941d0 450 cmd.len_msb = (uint8_t)((chunk_size >> 8) & 0xFF);
dgabino 0:102b50f941d0 451 cmd.len_lsb = (uint8_t)((chunk_size >> 0) & 0xFF);
dgabino 0:102b50f941d0 452 cmd.address = address;
dgabino 0:102b50f941d0 453 for (i = 0; i < ((cmd.len_msb << 8) + cmd.len_lsb); i++) {
dgabino 0:102b50f941d0 454 cmd.cmd_data[i] = data[i + cptalc];
dgabino 0:102b50f941d0 455 }
dgabino 0:102b50f941d0 456
dgabino 0:102b50f941d0 457 /* Send command */
dgabino 0:102b50f941d0 458 lgw_com_send_cmd_linux(cmd, fd);
dgabino 0:102b50f941d0 459 if (lgw_com_receive_ans_linux(&ans, fd) == LGW_COM_ERROR) {
dgabino 0:102b50f941d0 460 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 461 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 462 }
dgabino 0:102b50f941d0 463 } else {
dgabino 0:102b50f941d0 464 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 465 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 466 }
dgabino 0:102b50f941d0 467
dgabino 0:102b50f941d0 468 /* unlock burst */
dgabino 0:102b50f941d0 469 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 470
dgabino 0:102b50f941d0 471 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 472 }
dgabino 0:102b50f941d0 473
dgabino 0:102b50f941d0 474 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
dgabino 0:102b50f941d0 475
dgabino 0:102b50f941d0 476 int lgw_com_rb_linux(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data, uint16_t size) {
dgabino 0:102b50f941d0 477 int fd;
dgabino 0:102b50f941d0 478 int i;
dgabino 0:102b50f941d0 479 uint16_t chunk_size = size;
dgabino 0:102b50f941d0 480 int cptalc = 0;
dgabino 0:102b50f941d0 481 lgw_com_cmd_t cmd;
dgabino 0:102b50f941d0 482 lgw_com_ans_t ans;
dgabino 0:102b50f941d0 483 UNUSED(com_mux_mode);
dgabino 0:102b50f941d0 484 UNUSED(com_mux_target);
dgabino 0:102b50f941d0 485
dgabino 0:102b50f941d0 486 /* check input parameters */
dgabino 0:102b50f941d0 487 CHECK_NULL(com_target);
dgabino 0:102b50f941d0 488 CHECK_NULL(data);
dgabino 0:102b50f941d0 489
dgabino 0:102b50f941d0 490 fd = *(int *)com_target;
dgabino 0:102b50f941d0 491
dgabino 0:102b50f941d0 492 /* lock for complete burst */
dgabino 0:102b50f941d0 493 pthread_mutex_lock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 494
dgabino 0:102b50f941d0 495 /* Split burst in multiple chunks if necessary */
dgabino 0:102b50f941d0 496 while (chunk_size > ATOMICRX) {
dgabino 0:102b50f941d0 497 /* Prepare command */
dgabino 0:102b50f941d0 498 if (chunk_size == size) {
dgabino 0:102b50f941d0 499 cmd.id = 's'; /* read burst - first */
dgabino 0:102b50f941d0 500 } else {
dgabino 0:102b50f941d0 501 cmd.id = 't'; /* read burst - middle */
dgabino 0:102b50f941d0 502 }
dgabino 0:102b50f941d0 503 cmd.len_msb = 0;
dgabino 0:102b50f941d0 504 cmd.len_lsb = 2;
dgabino 0:102b50f941d0 505 cmd.cmd_data[0] = (uint8_t)((ATOMICRX >> 8) & 0xFF);
dgabino 0:102b50f941d0 506 cmd.cmd_data[1] = (uint8_t)((ATOMICRX >> 0) & 0xFF);
dgabino 0:102b50f941d0 507 cmd.address = address;
dgabino 0:102b50f941d0 508
dgabino 0:102b50f941d0 509 /* Send command */
dgabino 0:102b50f941d0 510 lgw_com_send_cmd_linux(cmd, fd);
dgabino 0:102b50f941d0 511 if (lgw_com_receive_ans_linux(&ans, fd) == LGW_COM_SUCCESS) {
dgabino 0:102b50f941d0 512 for (i = 0; i < ATOMICRX; i++) {
dgabino 0:102b50f941d0 513 data[i + cptalc] = ans.ans_data[i];
dgabino 0:102b50f941d0 514 }
dgabino 0:102b50f941d0 515 } else {
dgabino 0:102b50f941d0 516 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 517 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 518 }
dgabino 0:102b50f941d0 519
dgabino 0:102b50f941d0 520 chunk_size = chunk_size - ATOMICRX;
dgabino 0:102b50f941d0 521 cptalc = cptalc + ATOMICRX;
dgabino 0:102b50f941d0 522 }
dgabino 0:102b50f941d0 523
dgabino 0:102b50f941d0 524 /* Complete multiple-chunk transfer, or send atomic one */
dgabino 0:102b50f941d0 525 if (chunk_size > 0) {
dgabino 0:102b50f941d0 526 /* Prepare command */
dgabino 0:102b50f941d0 527 if (size <= ATOMICRX) {
dgabino 0:102b50f941d0 528 cmd.id = 'p'; /* read burst - atomic */
dgabino 0:102b50f941d0 529 } else {
dgabino 0:102b50f941d0 530 cmd.id = 'u'; /* read burst - end */
dgabino 0:102b50f941d0 531 }
dgabino 0:102b50f941d0 532 cmd.len_msb = 0;
dgabino 0:102b50f941d0 533 cmd.len_lsb = 2;
dgabino 0:102b50f941d0 534 cmd.cmd_data[0] = (uint8_t)((chunk_size >> 8) & 0xFF);
dgabino 0:102b50f941d0 535 cmd.cmd_data[1] = (uint8_t)((chunk_size >> 0) & 0xFF);
dgabino 0:102b50f941d0 536 cmd.address = address;
dgabino 0:102b50f941d0 537
dgabino 0:102b50f941d0 538 /* Send command */
dgabino 0:102b50f941d0 539 lgw_com_send_cmd_linux(cmd, fd);
dgabino 0:102b50f941d0 540 if (lgw_com_receive_ans_linux(&ans, fd) == LGW_COM_SUCCESS) {
dgabino 0:102b50f941d0 541 for (i = 0; i < chunk_size; i++) {
dgabino 0:102b50f941d0 542 data[i + cptalc] = ans.ans_data[i];
dgabino 0:102b50f941d0 543 }
dgabino 0:102b50f941d0 544 } else {
dgabino 0:102b50f941d0 545 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 546 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 547 }
dgabino 0:102b50f941d0 548 } else {
dgabino 0:102b50f941d0 549 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 550 return LGW_COM_ERROR;
dgabino 0:102b50f941d0 551 }
dgabino 0:102b50f941d0 552
dgabino 0:102b50f941d0 553 /* unlock burst */
dgabino 0:102b50f941d0 554 pthread_mutex_unlock(&mx_usbbridgesync);
dgabino 0:102b50f941d0 555
dgabino 0:102b50f941d0 556 return LGW_COM_SUCCESS;
dgabino 0:102b50f941d0 557 }
dgabino 0:102b50f941d0 558
dgabino 0:102b50f941d0 559 /* --- EOF ------------------------------------------------------------------ */