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
21 static AModem modem;
22
23 typedef 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
33 static Client
client_alloc(SysChannel channel)34 client_alloc( SysChannel channel )
35 {
36 Client client = calloc( sizeof(*client), 1 );
37
38 client->channel = channel;
39 return client;
40 }
41
42 static void
client_free(Client client)43 client_free( Client client )
44 {
45 sys_channel_close( client->channel );
46 client->channel = NULL;
47 free( client );
48 }
49
50 static void
51 client_append( Client client, const char* str, int len );
52
53 static void
dump_line(const char * line,const char * prefix)54 dump_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
74 static void
client_handle_line(Client client,const char * cmd)75 client_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
91 static void
client_handler(void * _client,int events)92 client_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
137 ExitClient:
138 printf( "client %p exiting\n", client );
139 client_free( client );
140 }
141
142
143 static void
client_append(Client client,const char * str,int len)144 client_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
163 static void
accept_func(void * _server,int events)164 accept_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
main(void)180 int 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