2011-10-07 19:18:23 -03:00
|
|
|
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*-
|
|
|
|
//
|
|
|
|
// Interrupt-driven serial transmit/receive library.
|
|
|
|
//
|
|
|
|
// Copyright (c) 2010 Michael Smith. All rights reserved.
|
|
|
|
//
|
|
|
|
// Receive and baudrate calculations derived from the Arduino
|
|
|
|
// HardwareSerial driver:
|
|
|
|
//
|
|
|
|
// Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
|
|
|
//
|
|
|
|
// Transmit algorithm inspired by work:
|
|
|
|
//
|
|
|
|
// Code Jose Julio and Jordi Munoz. DIYDrones.com
|
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2.1 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
//#include "../AP_Common/AP_Common.h"
|
|
|
|
#include "FastSerial.h"
|
|
|
|
#include "WProgram.h"
|
|
|
|
#include <unistd.h>
|
2011-10-09 01:55:02 -03:00
|
|
|
#include <pty.h>
|
2011-10-09 06:40:51 -03:00
|
|
|
#include <fcntl.h>
|
2011-10-07 19:18:23 -03:00
|
|
|
|
2011-10-12 20:25:30 -03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int list_s; /* listening socket */
|
|
|
|
int conn_s; /* connection socket */
|
|
|
|
short int port = 5760; /* port number */
|
|
|
|
struct sockaddr_in servaddr, cli_addr; /* socket address structure */
|
|
|
|
char buffer[256]; /* character buffer */
|
|
|
|
socklen_t clilen;
|
|
|
|
|
|
|
|
|
|
|
|
int myread(void)
|
|
|
|
{
|
|
|
|
return read(conn_s,buffer,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int mywrite(uint8_t c)
|
|
|
|
{
|
|
|
|
return write(conn_s,(char *) &c,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-07 19:18:23 -03:00
|
|
|
#if defined(UDR3)
|
|
|
|
# define FS_MAX_PORTS 4
|
|
|
|
#elif defined(UDR2)
|
|
|
|
# define FS_MAX_PORTS 3
|
|
|
|
#elif defined(UDR1)
|
|
|
|
# define FS_MAX_PORTS 2
|
|
|
|
#else
|
|
|
|
# define FS_MAX_PORTS 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
FastSerial::Buffer __FastSerial__rxBuffer[FS_MAX_PORTS];
|
|
|
|
FastSerial::Buffer __FastSerial__txBuffer[FS_MAX_PORTS];
|
|
|
|
|
|
|
|
// Constructor /////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
FastSerial::FastSerial(const uint8_t portNumber, volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
|
|
|
|
volatile uint8_t *ucsra, volatile uint8_t *ucsrb, const uint8_t u2x,
|
|
|
|
const uint8_t portEnableBits, const uint8_t portTxBits) :
|
|
|
|
_ubrrh(ubrrh),
|
|
|
|
_ubrrl(ubrrl),
|
|
|
|
_ucsra(ucsra),
|
|
|
|
_ucsrb(ucsrb),
|
2011-10-09 06:40:51 -03:00
|
|
|
_u2x(portNumber),
|
2011-10-07 19:18:23 -03:00
|
|
|
_portEnableBits(portEnableBits),
|
|
|
|
_portTxBits(portTxBits),
|
|
|
|
_rxBuffer(&__FastSerial__rxBuffer[portNumber]),
|
|
|
|
_txBuffer(&__FastSerial__txBuffer[portNumber])
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Public Methods //////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void FastSerial::begin(long baud)
|
|
|
|
{
|
2011-10-09 06:40:51 -03:00
|
|
|
if (_u2x == 0) {
|
|
|
|
unsigned v;
|
|
|
|
v = fcntl(0, F_GETFL, 0);
|
|
|
|
fcntl(0, F_SETFL, v | O_NONBLOCK);
|
|
|
|
v = fcntl(1, F_GETFL, 0);
|
|
|
|
fcntl(1, F_SETFL, v | O_NONBLOCK);
|
2011-10-12 20:25:30 -03:00
|
|
|
|
|
|
|
/* Create the listening socket */
|
|
|
|
|
|
|
|
if ( (list_s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
|
|
|
|
fprintf(stderr, "ECHOSERV: Error creating listening socket.\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int val = 1;
|
|
|
|
|
|
|
|
setsockopt(list_s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
|
|
|
|
|
|
|
|
/* Set all bytes in socket address structure to
|
|
|
|
zero, and fill in the relevant data members */
|
|
|
|
|
|
|
|
memset(&servaddr, 0, sizeof(servaddr));
|
|
|
|
|
|
|
|
servaddr.sin_family = AF_INET;
|
|
|
|
servaddr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
servaddr.sin_port = htons(port + _u2x);
|
|
|
|
|
|
|
|
|
|
|
|
/* Bind our socket addresss to the
|
|
|
|
listening socket, and call listen() */
|
|
|
|
|
|
|
|
if ( bind(list_s, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 ) {
|
|
|
|
fprintf(stderr, "ECHOSERV: Error calling bind()\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( listen(list_s, 5) < 0 ) {
|
|
|
|
fprintf(stderr, "ECHOSERV: Error calling listen()\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
clilen = sizeof(cli_addr);
|
|
|
|
|
|
|
|
fprintf(stdout, "Listerning on port %i\n",port + _u2x);
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
if ( (conn_s = accept(list_s, NULL, NULL) ) < 0 ) {
|
|
|
|
fprintf(stderr, "ECHOSERV: Error calling accept()\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
fcntl(conn_s, F_SETFL, O_NONBLOCK);
|
|
|
|
}
|
|
|
|
|
2011-10-07 19:18:23 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void FastSerial::begin(long baud, unsigned int rxSpace, unsigned int txSpace)
|
|
|
|
{
|
2011-10-09 01:55:02 -03:00
|
|
|
begin(baud);
|
2011-10-07 19:18:23 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void FastSerial::end()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int FastSerial::available(void)
|
|
|
|
{
|
2011-10-09 06:40:51 -03:00
|
|
|
if (_u2x != 0) return 0;
|
|
|
|
int num_ready;
|
2011-10-12 20:25:30 -03:00
|
|
|
|
|
|
|
fd_set socks;
|
|
|
|
struct timeval t;
|
|
|
|
FD_ZERO(&socks);
|
|
|
|
FD_SET(conn_s, &socks);
|
|
|
|
t.tv_sec = 0;
|
|
|
|
t.tv_usec = 500;
|
|
|
|
if (int ans = select(conn_s + 1, &socks, NULL, NULL,&t))
|
|
|
|
{
|
|
|
|
|
|
|
|
//FD_ZERO(&socks);
|
|
|
|
//FD_SET(conn_s, &socks);
|
|
|
|
//if (FD_ISSET(conn_s, &socks)) {
|
|
|
|
return 1;
|
|
|
|
// }
|
|
|
|
}
|
2011-10-07 19:18:23 -03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int FastSerial::txspace(void)
|
|
|
|
{
|
|
|
|
return 128;
|
|
|
|
}
|
|
|
|
|
|
|
|
int FastSerial::read(void)
|
|
|
|
{
|
2011-10-09 06:40:51 -03:00
|
|
|
if (_u2x != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2011-10-07 19:18:23 -03:00
|
|
|
char c;
|
2011-10-12 20:25:30 -03:00
|
|
|
int n = myread();
|
|
|
|
if (n == 0) {
|
|
|
|
|
|
|
|
if ( (conn_s = accept(list_s, NULL, NULL) ) < 0 ) {
|
|
|
|
fprintf(stderr, "ECHOSERV: Error calling accept()\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
fcntl(conn_s, F_SETFL, O_NONBLOCK);
|
|
|
|
}
|
|
|
|
return (int)buffer[0];
|
2011-10-07 19:18:23 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
int FastSerial::peek(void)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FastSerial::flush(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void FastSerial::write(uint8_t c)
|
|
|
|
{
|
2011-10-09 06:40:51 -03:00
|
|
|
if (_u2x != 0) {
|
|
|
|
return;
|
|
|
|
}
|
2011-10-12 20:25:30 -03:00
|
|
|
mywrite(c);
|
|
|
|
if (c >= '\n' && c <= 128) {
|
|
|
|
fwrite(&c, 1, 1, stdout);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
2011-10-07 19:18:23 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Buffer management ///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
bool FastSerial::_allocBuffer(Buffer *buffer, unsigned int size)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FastSerial::_freeBuffer(Buffer *buffer)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|