/*====================================================================*
*
* Copyright (c) 2013 Qualcomm Atheros, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted (subject to the limitations
* in the disclaimer below) provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* * Neither the name of Qualcomm Atheros nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
* COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*--------------------------------------------------------------------*/
/*====================================================================*
*
* int6kbaud.c - Atheros Serial Line Device Manager;
*
*
* Contributor(s):
* Nathaniel Houghton <nhoughto@qca.qualcomm.com>
*
*--------------------------------------------------------------------*/
/*====================================================================*
* system header files;
*--------------------------------------------------------------------*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#if defined (WIN32)
#elif defined (__linux__)
# include <termios.h>
#elif defined (__APPLE__)
# include <termios.h>
#elif defined (__OpenBSD__)
# include <termios.h>
#else
#error "Unknown Environment"
#endif
/*====================================================================*
* custom header files;
*--------------------------------------------------------------------*/
#include "../tools/getoptv.h"
#include "../tools/putoptv.h"
#include "../tools/number.h"
#include "../tools/memory.h"
#include "../tools/endian.h"
#include "../tools/symbol.h"
#include "../tools/files.h"
#include "../tools/flags.h"
#include "../tools/error.h"
#include "../tools/types.h"
#include "../serial/serial.h"
#include "../plc/plc.h"
/*====================================================================*
* custom source files;
*--------------------------------------------------------------------*/
#ifndef MAKEFILE
#include "../tools/getoptv.c"
#include "../tools/putoptv.c"
#include "../tools/version.c"
#include "../tools/uintspec.c"
#include "../tools/basespec.c"
#include "../tools/synonym.c"
#include "../tools/todigit.c"
#include "../tools/error.c"
#include "../tools/checksum32.c"
#include "../tools/hexencode.c"
#include "../tools/hexdump.c"
#include "../tools/hexstring.c"
#include "../tools/hexdecode.c"
#include "../tools/synonym.c"
#include "../tools/error.c"
#endif
#ifndef MAKEFILE
#include "../serial/openport.c"
#include "../serial/closeport.c"
#include "../serial/serial.c"
#endif
/*====================================================================*
* program variables;
*--------------------------------------------------------------------*/
typedef struct uart
{
struct _file_ port;
char const * string;
byte mode;
uint64_t baudrate;
byte databits;
byte parity;
byte stopbits;
byte flowctrl;
unsigned flags;
}
uart;
/*====================================================================*
* program variables;
*--------------------------------------------------------------------*/
static const struct _term_ modes [] =
{
{
"command",
"2"
},
{
"transparent",
"1"
}
};
static const struct _term_ paritybits [] =
{
{
"even",
"2"
},
{
"none",
"0"
},
{
"odd",
"1"
}
};
static const struct _term_ flowctrls [] =
{
{
"none",
"0"
},
{
"off",
"0"
},
{
"on",
"1"
}
};
/*====================================================================*
* program constants;
*--------------------------------------------------------------------*/
#define MODES (sizeof (modes) / sizeof (struct _term_))
#define PARITYBITS (sizeof (paritybits) / sizeof (struct _term_))
#define FLOWCTRLS (sizeof (flowctrls) / sizeof (struct _term_))
/*====================================================================*
*
* void at_command (struct uart * uart);
*
*--------------------------------------------------------------------*/
static void at_command (struct uart * uart)
{
clearcommand ();
while (*uart->string)
{
insert (*uart->string++);
}
insert ('\r');
sendcommand (&uart->port, uart->flags);
readcommand (&uart->port, uart->flags);
return;
}
/*====================================================================*
*
* void at_wake (struct uart * uart);
*
* send wake command "+++" to enter command mode;
*
*--------------------------------------------------------------------*/
static void at_wake (struct uart * uart)
{
clearcommand ();
insert ('+');
insert ('+');
insert ('+');
sendcommand (&uart->port, uart->flags);
readcommand (&uart->port, uart->flags);
mustbe ('O');
mustbe ('K');
mustbe ('\r');
return;
}
/*====================================================================*
*
* void atbr (struct uart * uart);
*
* set serial line parameters;
*
*--------------------------------------------------------------------*/
static void atbr (struct uart * uart)
{
clearcommand ();
insert ('A');
insert ('T');
insert ('B');
insert ('R');
decode (&uart->mode, sizeof (uart->mode));
insert (',');
uart->baudrate = HTOBE64 (uart->baudrate);
decode (&uart->baudrate, sizeof (uart->baudrate));
uart->baudrate = BE64TOH (uart->baudrate);
insert (',');
decode (&uart->databits, sizeof (uart->databits));
insert (',');
decode (&uart->parity, sizeof (uart->parity));
insert (',');
decode (&uart->stopbits, sizeof (uart->stopbits));
insert (',');
decode (&uart->flowctrl, sizeof (uart->flowctrl));
insert ('\r');
sendcommand (&uart->port, uart->flags);
readcommand (&uart->port, uart->flags);
mustbe ('O');
mustbe ('K');
mustbe ('\r');
return;
}
/*====================================================================*
*
* void manager (struct uart * uart);
*
* examine flagword in struct uart and perform requested operations
* in the order that bits are tested; the order that bits are tested
* may be changed as needed;
*
*--------------------------------------------------------------------*/
static void manager (struct uart * uart)
{
if (_anyset (uart->flags, UART_WAKE))
{
at_wake (uart);
}
if (_anyset (uart->flags, UART_COMMAND))
{
at_command (uart);
}
if (_anyset (uart->flags, UART_ATBR))
{
atbr (uart);
}
return;
}
/*====================================================================*
*
* int main (int argc, char const * argv []);
*
*
*
*
*--------------------------------------------------------------------*/
int main (int argc, char const * argv [])
{
static char const * optv [] =
{
"B:c:D:F:m:p:P:q:S:uvw",
"",
"Atheros Serial Line Device Settings",
"B n\tbaud rate is (n) [" LITERAL (UART_BAUDRATE) "]",
"c s\tsend custom serial line command (s)",
"D n\tuse (n) data bits [" LITERAL (UART_DATABITS) "]",
"F n\tflow control is (n) ["LITERAL (UART_FLOWCTRL) "]",
"m n\tcommand mode is (n)",
"p f\tserial port is (f) [" DEVICE "]",
"P n\tuse (n) parity bits [" LITERAL (UART_PARITY) "]",
"q\tquiet mode",
"S n\tuse (n) stop bits [" LITERAL (UART_STOPBITS) "]",
"u\tforce default host port settings [115200 8N1]",
"v\tverbose mode",
"w\twake device [+++]",
(char const *) (0)
};
struct uart uart =
{
{
0,
DEVICE
},
(char *)(0),
UART_MODE,
UART_BAUDRATE,
UART_DATABITS,
UART_PARITY,
UART_STOPBITS,
UART_FLOWCTRL,
0
};
signed c;
if (getenv (UART_PORT))
{
uart.port.name = strdup (getenv (UART_PORT));
}
while ((c = getoptv (argc, argv, optv)) != -1)
{
switch (c)
{
case 'B':
_setbits (uart.flags, UART_ATBR);
uart.baudrate = (uint64_t)(uintspec (optarg, 1, ULONG_MAX));
break;
case 'c':
_setbits (uart.flags, UART_COMMAND);
uart.string = optarg;
break;
case 'D':
_setbits (uart.flags, UART_ATBR);
uart.databits = (byte)(uintspec (optarg, 7, 8));
break;
case 'F':
_setbits (uart.flags, UART_ATBR);
uart.flowctrl = (byte)(uintspec (synonym (optarg, flowctrls, FLOWCTRLS), 0, UCHAR_MAX));
break;
case 'm':
_setbits (uart.flags, UART_ATBR);
uart.mode = (byte)(uintspec (synonym (optarg, modes, MODES), 0, UCHAR_MAX));
case 'P':
_setbits (uart.flags, UART_ATBR);
uart.parity = (byte)(uintspec (synonym (optarg, paritybits, PARITYBITS), 0, UCHAR_MAX));
break;
case 'q':
_setbits (uart.flags, UART_SILENCE);
break;
case 'p':
uart.port.name = optarg;
break;
case 'S':
_setbits (uart.flags, UART_ATBR);
uart.stopbits = (unsigned)(uintspec (optarg, 1, 2));
break;
case 'u':
_setbits (uart.flags, UART_DEFAULT);
break;
case 'v':
_setbits (uart.flags, UART_VERBOSE);
break;
case 'w':
_setbits (uart.flags, UART_WAKE);
break;
default:
break;
}
}
argc -= optind;
argv += optind;
if (argc)
{
error (1, ENOTSUP, ERROR_TOOMANY);
}
openport (&uart.port, uart.flags);
manager (&uart);
closeport (&uart.port);
return (0);
}