1/* Copyright (C) 2007-2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10** GNU General Public License for more details.
11*/
12#include "android_modem.h"
13#include "sysdeps.h"
14#include <stdio.h>
15#include <stdlib.h>
16#include <errno.h>
17#include <string.h>
18
19#define  DEFAULT_PORT  6703
20
21static AModem  modem;
22
23typedef struct {
24    SysChannel   channel;
25    char         in_buff[ 128 ];
26    int          in_pos;
27
28    char         out_buff[ 128 ];
29    int          out_pos;
30    int          out_size;
31} ClientRec, *Client;
32
33static Client
34client_alloc( SysChannel  channel )
35{
36    Client  client = calloc( sizeof(*client), 1 );
37
38    client->channel = channel;
39    return client;
40}
41
42static void
43client_free( Client  client )
44{
45    sys_channel_close( client->channel );
46    client->channel = NULL;
47    free( client );
48}
49
50static void
51client_append( Client  client, const char*  str, int len );
52
53static void
54dump_line( const char*  line, const char*  prefix )
55{
56    if (prefix)
57        printf( "%s", prefix );
58
59    for ( ; *line; line++ ) {
60        int  c = line[0];
61
62        if (c >= 32 && c < 127)
63            printf( "%c", c );
64        else if (c == '\r')
65            printf( "<CR>" );
66        else if (c == '\n')
67            printf( "<LF>" );
68        else
69            printf( "\\x%02x", c );
70    }
71    printf( "\n" );
72}
73
74static void
75client_handle_line( Client  client, const char*  cmd )
76{
77    const char*  answer;
78
79    dump_line( cmd, "<< " );
80    answer = amodem_send( modem, cmd );
81    if (answer == NULL)  /* not an AT command, ignored */ {
82        printf( "-- NO ANSWER\n" );
83        return;
84    }
85
86    dump_line( answer, ">> " );
87    client_append( client, answer, -1 );
88    client_append( client, "\r", 1 );
89}
90
91static void
92client_handler( void* _client, int  events )
93{
94    Client  client = _client;
95
96    if (events & SYS_EVENT_READ) {
97        int  ret;
98        /* read into buffer, one character at a time */
99        ret = sys_channel_read( client->channel, client->in_buff + client->in_pos, 1 );
100        if (ret != 1) {
101            fprintf(stderr, "client %p could not read byte, result = %d, error: %s\n",
102                    client, ret, strerror(errno) );
103            goto ExitClient;
104        }
105        if (client->in_buff[client->in_pos] == '\r' ||
106            client->in_buff[client->in_pos] == '\n' ) {
107            const char*  cmd = client->in_buff;
108            client->in_buff[client->in_pos] = 0;
109
110            if (client->in_pos > 0) {
111                client_handle_line( client, cmd );
112                client->in_pos = 0;
113            }
114        } else
115            client->in_pos += 1;
116    }
117
118    if (events & SYS_EVENT_WRITE) {
119        int  ret;
120        /* write from output buffer, one char at a time */
121        ret = sys_channel_write( client->channel, client->out_buff + client->out_pos, 1 );
122        if (ret != 1) {
123            fprintf(stderr, "client %p could not write byte, result = %d, error: %s\n",
124                    client, ret, strerror(errno) );
125            goto ExitClient;
126        }
127        client->out_pos += 1;
128        if (client->out_pos == client->out_size) {
129            client->out_size = 0;
130            client->out_pos  = 0;
131            /* we don't need to write */
132            sys_channel_on( client->channel, SYS_EVENT_READ, client_handler, client );
133        }
134    }
135    return;
136
137ExitClient:
138    printf( "client %p exiting\n", client );
139    client_free( client );
140}
141
142
143static void
144client_append( Client  client, const char*  str, int len )
145{
146    int  avail;
147
148    if (len < 0)
149        len = strlen(str);
150
151    avail = sizeof(client->out_buff) - client->out_size;
152    if (len > avail)
153        len = avail;
154
155    memcpy( client->out_buff + client->out_size, str, len );
156    if (client->out_size == 0) {
157        sys_channel_on( client->channel, SYS_EVENT_READ | SYS_EVENT_WRITE, client_handler, client );
158    }
159    client->out_size += len;
160}
161
162
163static void
164accept_func( void*  _server, int  events )
165{
166    SysChannel  server  = _server;
167    SysChannel  handler;
168    Client      client;
169
170    printf( "connection accepted for server channel, getting handler socket\n" );
171    handler = sys_channel_create_tcp_handler( server );
172    client  = client_alloc( handler );
173    printf( "got one. created client %p\n", client );
174
175    events=events;
176    sys_channel_on( handler, SYS_EVENT_READ, client_handler, client );
177}
178
179
180int  main( void )
181{
182    int  port = DEFAULT_PORT;
183    SysChannel  server;
184
185    sys_main_init();
186    modem = amodem_create( NULL, NULL );
187
188    server = sys_channel_create_tcp_server( port );
189    printf( "GSM simulator listening on local port %d\n", port );
190
191    sys_channel_on( server, SYS_EVENT_READ, accept_func, server );
192    sys_main_loop();
193    printf( "GSM simulator exiting\n" );
194    return 0;
195}
196