You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
9.1 KiB
373 lines
9.1 KiB
/*
|
|
* $Id: sys.c,v 1.17 2006/10/12 14:21:22 desrod Exp $
|
|
*
|
|
* sys.c: Pilot System Protocol
|
|
*
|
|
* (c) 1996, Kenneth Albanowski.
|
|
* Derived from padp.c.
|
|
*
|
|
* This library is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Library General Public License as published by
|
|
* the Free Software Foundation; either version 2 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 Library
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "pi-debug.h"
|
|
#include "pi-source.h"
|
|
#include "pi-slp.h"
|
|
#include "pi-sys.h"
|
|
#include "pi-error.h"
|
|
|
|
/* Declare function prototypes */
|
|
static int sys_flush(pi_socket_t *ps, int flags);
|
|
static int sys_getsockopt(pi_socket_t *ps, int level, int option_name,
|
|
void *option_value, size_t *option_len);
|
|
static int sys_setsockopt(pi_socket_t *ps, int level, int option_name,
|
|
const void *option_value, size_t *option_len);
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_protocol_dup
|
|
*
|
|
* Summary: clones an existing pi_protocol struct
|
|
*
|
|
* Parameters: pi_protocol*
|
|
*
|
|
* Returns: pi_protocol_t* or NULL if operation failed
|
|
*
|
|
***********************************************************************/
|
|
static pi_protocol_t *
|
|
sys_protocol_dup (pi_protocol_t *prot)
|
|
{
|
|
pi_protocol_t *new_prot = NULL;
|
|
pi_sys_data_t *data = NULL,
|
|
*new_data = NULL;
|
|
|
|
new_prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
|
|
if (new_prot != NULL) {
|
|
new_data = (pi_sys_data_t *)malloc (sizeof (pi_sys_data_t));
|
|
if (new_data == NULL) {
|
|
free(new_prot);
|
|
new_prot = NULL;
|
|
}
|
|
}
|
|
|
|
if (new_prot != NULL && new_data != NULL) {
|
|
new_prot->level = prot->level;
|
|
new_prot->dup = prot->dup;
|
|
new_prot->free = prot->free;
|
|
new_prot->read = prot->read;
|
|
new_prot->write = prot->write;
|
|
new_prot->flush = prot->flush;
|
|
new_prot->getsockopt = prot->getsockopt;
|
|
new_prot->setsockopt = prot->setsockopt;
|
|
|
|
data = (pi_sys_data_t *)prot->data;
|
|
new_data->txid = data->txid;
|
|
new_prot->data = new_data;
|
|
}
|
|
|
|
return new_prot;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_protocol_free
|
|
*
|
|
* Summary: frees an existing pi_protocol struct
|
|
*
|
|
* Parameters: pi_protocol*
|
|
*
|
|
* Returns: void
|
|
*
|
|
***********************************************************************/
|
|
static void
|
|
sys_protocol_free (pi_protocol_t *prot)
|
|
{
|
|
|
|
ASSERT (prot != NULL);
|
|
if (prot != NULL) {
|
|
if (prot->data != NULL)
|
|
free(prot->data);
|
|
free(prot);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_protocol
|
|
*
|
|
* Summary: creates and inits pi_protocol struct instance
|
|
*
|
|
* Parameters: void
|
|
*
|
|
* Returns: pi_protocol_t* or NULL if operation failed
|
|
*
|
|
***********************************************************************/
|
|
pi_protocol_t *
|
|
sys_protocol (void)
|
|
{
|
|
pi_protocol_t *prot = NULL;
|
|
pi_sys_data_t *data = NULL;
|
|
|
|
prot = (pi_protocol_t *)malloc (sizeof (pi_protocol_t));
|
|
if (prot != NULL) {
|
|
data = (pi_sys_data_t *)malloc (sizeof (pi_sys_data_t));
|
|
if (data == NULL) {
|
|
free(prot);
|
|
prot = NULL;
|
|
}
|
|
}
|
|
|
|
if (prot != NULL && data != NULL) {
|
|
prot->level = PI_LEVEL_SYS;
|
|
prot->dup = sys_protocol_dup;
|
|
prot->free = sys_protocol_free;
|
|
prot->read = sys_rx;
|
|
prot->write = sys_tx;
|
|
prot->flush = sys_flush;
|
|
prot->getsockopt = sys_getsockopt;
|
|
prot->setsockopt = sys_setsockopt;
|
|
|
|
data->txid = 0x00;
|
|
prot->data = data;
|
|
}
|
|
|
|
return prot;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_tx
|
|
*
|
|
* Summary: Send a system message
|
|
*
|
|
* Parameters: pi_socket_t*, char* to buffer, buffer length, flags
|
|
*
|
|
* Returns: 0 if success, nonzero otherwise
|
|
*
|
|
***********************************************************************/
|
|
ssize_t
|
|
sys_tx(pi_socket_t *ps, const unsigned char *buf, size_t len, int flags)
|
|
{
|
|
pi_protocol_t *prot,
|
|
*next;
|
|
|
|
pi_sys_data_t *data;
|
|
|
|
int type,
|
|
socket;
|
|
|
|
size_t size;
|
|
|
|
prot = pi_protocol(ps->sd, PI_LEVEL_SYS);
|
|
if (prot == NULL)
|
|
return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
|
|
|
|
data = (pi_sys_data_t *)prot->data;
|
|
|
|
next = pi_protocol_next(ps->sd, PI_LEVEL_SYS);
|
|
if (next == NULL)
|
|
return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
|
|
|
|
if (!data->txid || data->txid == 0xff)
|
|
data->txid = 0x11; /* some random # */
|
|
data->txid++;
|
|
if (!data->txid || data->txid == 0xff)
|
|
data->txid = 0x11; /* some random # */
|
|
|
|
type = PI_SLP_TYPE_RDCP;
|
|
|
|
/* Fix me, allow socket type */
|
|
socket = PI_SLP_SOCK_CON;
|
|
size = sizeof(type);
|
|
pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_TYPE,
|
|
&type, &size);
|
|
pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_DEST,
|
|
&socket, &size);
|
|
pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_SRC,
|
|
&socket, &size);
|
|
size = sizeof(data->txid);
|
|
pi_setsockopt(ps->sd, PI_LEVEL_SLP, PI_SLP_TXID,
|
|
&data->txid, &size);
|
|
|
|
len = next->write(ps, buf, len, flags);
|
|
if (len >= 0) {
|
|
CHECK(PI_DBG_SYS, PI_DBG_LVL_INFO, sys_dump_header(buf, 1));
|
|
CHECK(PI_DBG_SYS, PI_DBG_LVL_DEBUG, sys_dump(buf, len));
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_rx
|
|
*
|
|
* Summary: Receive system message
|
|
*
|
|
* Parameters: pi_socket_t*, char* to buffer, buffer length, flags
|
|
*
|
|
* Returns: Length of read or negative on error
|
|
*
|
|
***********************************************************************/
|
|
ssize_t
|
|
sys_rx(pi_socket_t *ps, pi_buffer_t *buf, size_t len, int flags)
|
|
{
|
|
pi_protocol_t *next,
|
|
*prot;
|
|
|
|
pi_sys_data_t *data;
|
|
size_t data_len;
|
|
|
|
prot = pi_protocol(ps->sd, PI_LEVEL_SYS);
|
|
if (prot == NULL)
|
|
return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
|
|
|
|
data = (pi_sys_data_t *)prot->data;
|
|
next = pi_protocol_next(ps->sd, PI_LEVEL_SYS);
|
|
if (next == NULL)
|
|
return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
|
|
|
|
data_len = next->read(ps, buf, len, flags);
|
|
|
|
CHECK(PI_DBG_SYS, PI_DBG_LVL_INFO, sys_dump_header(buf->data, 0));
|
|
CHECK(PI_DBG_SYS, PI_DBG_LVL_DEBUG, sys_dump(buf->data, data_len));
|
|
|
|
return data_len;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_flush
|
|
*
|
|
* Summary: Flush input and output buffers
|
|
*
|
|
* Parameters: pi_socket_t*, flags
|
|
*
|
|
* Returns: A negative number on error, 0 otherwise
|
|
*
|
|
***********************************************************************/
|
|
static int
|
|
sys_flush(pi_socket_t *ps, int flags)
|
|
{
|
|
pi_protocol_t *prot,
|
|
*next;
|
|
|
|
prot = pi_protocol(ps->sd, PI_LEVEL_SYS);
|
|
if (prot == NULL)
|
|
return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
|
|
|
|
next = pi_protocol_next(ps->sd, PI_LEVEL_SYS);
|
|
if (next == NULL)
|
|
return pi_set_error(ps->sd, PI_ERR_SOCK_INVALID);
|
|
|
|
return next->flush(ps, flags);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_getsockopt
|
|
*
|
|
* Summary: get options on socket
|
|
*
|
|
* Parameters: pi_socket*, level, option name, option value, option length
|
|
*
|
|
* Returns: 0 for success
|
|
*
|
|
***********************************************************************/
|
|
static int
|
|
sys_getsockopt(pi_socket_t *ps, int level, int option_name,
|
|
void *option_value, size_t *option_len)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_setsockopt
|
|
*
|
|
* Summary: get options on socket
|
|
*
|
|
* Parameters: pi_socket*, level, option name, option value, option length
|
|
*
|
|
* Returns: 0 for success
|
|
*
|
|
***********************************************************************/
|
|
static int
|
|
sys_setsockopt(pi_socket_t *ps, int level, int option_name,
|
|
const void *option_value, size_t *option_len)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_dump_header
|
|
*
|
|
* Summary: Dump SYS packet header
|
|
*
|
|
* Parameters: char* to data, RXTX boolean
|
|
*
|
|
* Returns: void
|
|
*
|
|
***********************************************************************/
|
|
void
|
|
sys_dump_header(const unsigned char *data, int rxtx)
|
|
{
|
|
LOG((PI_DBG_SYS, PI_DBG_LVL_NONE,
|
|
"SYS %s\n", rxtx ? "TX" : "RX"));
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Function: sys_dump
|
|
*
|
|
* Summary: Dump SYS packet
|
|
*
|
|
* Parameters: char* to data, length
|
|
*
|
|
* Returns: void
|
|
*
|
|
***********************************************************************/
|
|
void
|
|
sys_dump(const unsigned char *data, size_t len)
|
|
{
|
|
pi_dumpdata((char *)&data[PI_SYS_HEADER_LEN], len);
|
|
}
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
|
|
/* ex: set tabstop=4 expandtab: */
|
|
/* Local Variables: */
|
|
/* indent-tabs-mode: t */
|
|
/* c-basic-offset: 8 */
|
|
/* End: */
|
|
|