/** Method to update the readbuf of the serial communication, * as well as the connection itself. * @param connection * the serial struct * @note * the packets will be read in the following format: * data\n * however, the \n will be cut off */ static void _serial_update(serial_t *connection) { int numAvailable; int totalBytes; /* dynamically reconnect the device */ if (access(connection->port, F_OK) == -1) { if (connection->connected) { connection->connected = 0; connection->fd = -1; } } else { if (!connection->connected) { if ((connection->fd = open(connection->port, O_RDWR | O_NOCTTY | O_NDELAY)) != -1) { if (_serial_setattr(connection) == 0) { connection->connected = 1; } else { close(connection->fd); connection->fd = -1; } } } } if (!connection->connected) return; /* update buffer */ if ((numAvailable = read(connection->fd, tempbuf, SWREADMAX)) > 0) { char *start_index, *end_index; tempbuf[numAvailable] = '\0'; if ((totalBytes = strlen(connection->buffer) + numAvailable) >= SWBUFMAX) { totalBytes -= SWREADMAX; memmove(connection->buffer, &connection->buffer[totalBytes], (SWBUFMAX - totalBytes) * sizeof(char)); connection->buffer[SWBUFMAX - totalBytes] = '\0'; } strcat(connection->buffer, tempbuf); if ((end_index = strrchr(connection->buffer, '\n'))) { end_index[0] = '\0'; end_index = &end_index[1]; start_index = strrchr(connection->buffer, '\n'); start_index = start_index ? &start_index[1] : connection->buffer; memcpy(connection->readbuf, start_index, (strlen(start_index) + 1) * sizeof(char)); memmove(connection->buffer, end_index, (strlen(end_index) + 1) * sizeof(char)); connection->readAvailable = 1; } } }
/** Connect to a serial device. * @param connection * a pointer to the serial struct * @param port * a portname; if NULL, will open a random port * @param baudrate * the bits per second of information to transmit/receive * @return 0 on success, -1 on failure */ int serial_connect(serial_t *connection, char *port, int baudrate) { connection->connected = 0; if (port) { connection->port = (char *)malloc((strlen(port) + 1) * sizeof(char)); strcpy(connection->port, port); if ((connection->fd = open(connection->port, O_RDWR)) == -1) { goto error; } } else { DIR *dp; struct dirent *ent; char hasPossibleSerial; if (!(dp = opendir(INPUT_DIR))) { fprintf(stderr, "Cannot find directory %s to open serial connection\n", INPUT_DIR); return -1; } while ((ent = readdir(dp))) { const char *prefix; int i; hasPossibleSerial = 0; for (prefix = PREFIXES[(i = 0)]; prefix != NULL; prefix = PREFIXES[++i]) { if (strstr(ent->d_name, prefix)) { connection->port = (char *)malloc((strlen(INPUT_DIR) + strlen(ent->d_name) + 1) * sizeof(char)); sprintf(connection->port, "%s%s", INPUT_DIR, ent->d_name); if ((connection->fd = open(connection->port, O_RDWR | O_NOCTTY | O_NONBLOCK)) == -1) { free(connection->port); connection->port = NULL; } else { hasPossibleSerial = 1; break; } } } if (hasPossibleSerial) { break; } } if (!hasPossibleSerial) { fprintf(stderr, "Cannot find a serial device to open\n"); return -1; } } /* set connection attributes */ connection->baudrate = baudrate; connection->parity = 0; if (_serial_setattr(connection) == -1) { goto error; /* possible bad behavior */ } tcflush(connection->fd, TCIFLUSH); tcflush(connection->fd, TCOFLUSH); connection->connected = 1; memset(connection->buffer, 0, SWBUFMAX); memset(connection->readbuf, 0, SWREADMAX); connection->readAvailable = 0; printf("Connected to %s\n", connection->port); return 0; error: fprintf(stderr, "Cannot connect to the device on %s\n", connection->port); connection->connected = 0; if (connection->fd != -1) { close(connection->fd); } connection->fd = -1; if (connection->port) { free(connection->port); } connection->port = NULL; return -1; }
/** Method to update the readbuf of the serial communication, * as well as the connection itself. * @param connection * the serial struct * @note * the packets will be read in the following format: * data\n */ static void _serial_update(serial_t *connection) { int bytesRead; int bytesStored; unsigned char analyzeBuffer; /* dynamically reconnect the device */ if (access(connection->port, F_OK) == -1) { if (connection->connected) { connection->connected = 0; connection->fd = -1; } } else { if (!connection->connected) { if ((connection->fd = open(connection->port, O_RDWR | O_NOCTTY | O_NDELAY)) != -1) { if (_serial_setattr(connection) == 0) { connection->connected = 1; } else { close(connection->fd); connection->fd = -1; } } } } if (!connection->connected) { return; } /* update buffer constantly (be careful of overflow!) */ analyzeBuffer = 0; while ((bytesRead = read(connection->fd, tempbuf, SWREADMAX)) > 0) { if (bytesRead > 0) { analyzeBuffer = 1; /* turn on buffer analysis signal */ } tempbuf[bytesRead] = '\0'; bytesStored = strlen(connection->buffer); /* no \0 */ while (bytesStored + bytesRead >= SWBUFMAX) { /* shorten it by only half of the readmax value */ bytesStored -= SWREADMAX / 2; memmove(connection->buffer, &connection->buffer[SWREADMAX / 2], (bytesStored + 1) * sizeof(char)); } strcat(connection->buffer, tempbuf); } if (analyzeBuffer) { char *start_index, *end_index; size_t nbytes; if ((end_index = strrchr(connection->buffer, '\n'))) { end_index[0] = '\0'; end_index = &end_index[1]; start_index = strrchr(connection->buffer, '\n'); start_index = start_index ? &start_index[1] : connection->buffer; nbytes = (size_t)end_index - (size_t)start_index; memcpy(connection->readbuf, start_index, nbytes * sizeof(char)); connection->readbuf[nbytes + 1] = '\n'; /* put the \n back */ connection->readbuf[nbytes + 2] = '\0'; memmove(connection->buffer, end_index, (strlen(end_index) + 1) * sizeof(char)); connection->readAvailable = 1; } } }