/* Copyright (C) 2007-2008 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program 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 General Public License for more details.
*/
#include "android_modem.h"
#include "sysdeps.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define DEFAULT_PORT 6703
static AModem modem;
typedef struct {
SysChannel channel;
char in_buff[ 128 ];
int in_pos;
char out_buff[ 128 ];
int out_pos;
int out_size;
} ClientRec, *Client;
static Client
client_alloc( SysChannel channel )
{
Client client = calloc( sizeof(*client), 1 );
client->channel = channel;
return client;
}
static void
client_free( Client client )
{
sys_channel_close( client->channel );
client->channel = NULL;
free( client );
}
static void
client_append( Client client, const char* str, int len );
static void
dump_line( const char* line, const char* prefix )
{
if (prefix)
printf( "%s", prefix );
for ( ; *line; line++ ) {
int c = line[0];
if (c >= 32 && c < 127)
printf( "%c", c );
else if (c == '\r')
printf( "<CR>" );
else if (c == '\n')
printf( "<LF>" );
else
printf( "\\x%02x", c );
}
printf( "\n" );
}
static void
client_handle_line( Client client, const char* cmd )
{
const char* answer;
dump_line( cmd, "<< " );
answer = amodem_send( modem, cmd );
if (answer == NULL) /* not an AT command, ignored */ {
printf( "-- NO ANSWER\n" );
return;
}
dump_line( answer, ">> " );
client_append( client, answer, -1 );
client_append( client, "\r", 1 );
}
static void
client_handler( void* _client, int events )
{
Client client = _client;
if (events & SYS_EVENT_READ) {
int ret;
/* read into buffer, one character at a time */
ret = sys_channel_read( client->channel, client->in_buff + client->in_pos, 1 );
if (ret != 1) {
fprintf(stderr, "client %p could not read byte, result = %d, error: %s\n",
client, ret, strerror(errno) );
goto ExitClient;
}
if (client->in_buff[client->in_pos] == '\r' ||
client->in_buff[client->in_pos] == '\n' ) {
const char* cmd = client->in_buff;
client->in_buff[client->in_pos] = 0;
if (client->in_pos > 0) {
client_handle_line( client, cmd );
client->in_pos = 0;
}
} else
client->in_pos += 1;
}
if (events & SYS_EVENT_WRITE) {
int ret;
/* write from output buffer, one char at a time */
ret = sys_channel_write( client->channel, client->out_buff + client->out_pos, 1 );
if (ret != 1) {
fprintf(stderr, "client %p could not write byte, result = %d, error: %s\n",
client, ret, strerror(errno) );
goto ExitClient;
}
client->out_pos += 1;
if (client->out_pos == client->out_size) {
client->out_size = 0;
client->out_pos = 0;
/* we don't need to write */
sys_channel_on( client->channel, SYS_EVENT_READ, client_handler, client );
}
}
return;
ExitClient:
printf( "client %p exiting\n", client );
client_free( client );
}
static void
client_append( Client client, const char* str, int len )
{
int avail;
if (len < 0)
len = strlen(str);
avail = sizeof(client->out_buff) - client->out_size;
if (len > avail)
len = avail;
memcpy( client->out_buff + client->out_size, str, len );
if (client->out_size == 0) {
sys_channel_on( client->channel, SYS_EVENT_READ | SYS_EVENT_WRITE, client_handler, client );
}
client->out_size += len;
}
static void
accept_func( void* _server, int events )
{
SysChannel server = _server;
SysChannel handler;
Client client;
printf( "connection accepted for server channel, getting handler socket\n" );
handler = sys_channel_create_tcp_handler( server );
client = client_alloc( handler );
printf( "got one. created client %p\n", client );
events=events;
sys_channel_on( handler, SYS_EVENT_READ, client_handler, client );
}
int main( void )
{
int port = DEFAULT_PORT;
SysChannel server;
sys_main_init();
modem = amodem_create( NULL, NULL );
server = sys_channel_create_tcp_server( port );
printf( "GSM simulator listening on local port %d\n", port );
sys_channel_on( server, SYS_EVENT_READ, accept_func, server );
sys_main_loop();
printf( "GSM simulator exiting\n" );
return 0;
}