3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
34 #include <glib/gprintf.h>
39 static int do_connect(const char *address, unsigned short port)
41 struct sockaddr_in addr;
44 sk = socket(PF_INET, SOCK_STREAM, 0);
48 memset(&addr, 0, sizeof(addr));
49 addr.sin_family = AF_INET;
50 addr.sin_addr.s_addr = inet_addr(address);
51 addr.sin_port = htons(port);
53 err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
62 static GMainLoop *mainloop;
65 static gboolean cleanup_callback(gpointer data)
69 g_main_loop_quit(mainloop);
74 static gboolean chat_cleanup(gpointer data)
78 g_at_chat_unref(chat);
83 static void chat_callback(gboolean ok, GAtResult *result, gpointer user_data)
87 g_at_result_iter_init(&iter, result);
89 g_print("chat: callback [ok %d]\n", ok);
91 g_print("%s\n", g_at_result_final_response(result));
93 g_idle_add(chat_cleanup, user_data);
96 static void mux_debug(const char *str, void *data)
98 g_print("%s: %s\n", (char *) data, str);
101 static void mux_setup(GAtMux *m, gpointer data)
103 GAtChat *chat = data;
109 g_print("mux_setup: %p\n", mux);
112 g_at_chat_unref(chat);
113 g_main_loop_quit(mainloop);
119 io = g_at_mux_create_channel(mux);
120 syntax = g_at_syntax_new_gsm_permissive();
121 chat = g_at_chat_new(io, syntax);
122 g_at_syntax_unref(syntax);
123 g_io_channel_unref(io);
125 g_at_chat_set_debug(chat, mux_debug, "CHAT1");
126 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
127 g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
128 g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
130 io = g_at_mux_create_channel(mux);
131 syntax = g_at_syntax_new_gsm_permissive();
132 chat = g_at_chat_new(io, syntax);
133 g_at_syntax_unref(syntax);
134 g_io_channel_unref(io);
136 g_at_chat_set_debug(chat, mux_debug, "CHAT2");
137 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
138 g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
139 g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
141 io = g_at_mux_create_channel(mux);
142 syntax = g_at_syntax_new_gsm_permissive();
143 chat = g_at_chat_new(io, syntax);
144 g_at_syntax_unref(syntax);
145 g_io_channel_unref(io);
147 g_at_chat_set_debug(chat, mux_debug, "CHAT3");
148 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
149 g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
150 g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
152 io = g_at_mux_create_channel(mux);
153 syntax = g_at_syntax_new_gsm_permissive();
154 chat = g_at_chat_new(io, syntax);
155 g_at_syntax_unref(syntax);
156 g_io_channel_unref(io);
158 g_at_chat_set_debug(chat, mux_debug, "CHAT4");
159 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
160 g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
161 g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
163 g_timeout_add_seconds(7, cleanup_callback, NULL);
166 static void mux_init(gboolean ok, GAtResult *result, gpointer data)
168 GAtChat *chat = data;
170 g_print("mux_init: %d\n", ok);
173 g_at_chat_unref(chat);
174 g_main_loop_quit(mainloop);
178 g_at_mux_setup_gsm0710(chat, mux_setup, chat, NULL);
181 static void test_mux(void)
188 sk = do_connect("192.168.0.202", 2000);
190 g_printerr("connect failed\n");
195 io = g_io_channel_unix_new(sk);
196 g_io_channel_set_close_on_unref(io, TRUE);
198 syntax = g_at_syntax_new_gsm_permissive();
199 chat = g_at_chat_new(io, syntax);
200 g_at_syntax_unref(syntax);
202 g_io_channel_unref(io);
205 g_printerr("Chat creation failed\n");
209 g_at_chat_set_debug(chat, mux_debug, "MUX");
210 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
211 g_at_chat_send(chat, "ATE0", NULL, mux_init, chat, NULL);
213 mainloop = g_main_loop_new(NULL, FALSE);
215 g_main_loop_run(mainloop);
216 g_main_loop_unref(mainloop);
219 static void test_basic(void)
221 if (g_test_trap_fork(60 * 1000 * 1000, 0) == TRUE) {
226 g_test_trap_assert_passed();
227 //g_test_trap_assert_stderr("failed");
230 /* DLC 1, Open Channel */
231 static const guint8 basic_open[] = { 0xF9, 0x07, 0x3F, 0x01, 0xDE, 0xF9 };
233 /* DLC 1, Close Channel */
234 static char const basic_close[] = { 0xF9, 0x07, 0x53, 0x01, 0x3F, 0xF9 };
237 static const guint8 basic_data[] = { 0x12, 0x34, 0x56 };
238 static const guint8 basic_data_result[] =
239 { 0xF9, 0x07, 0xEF, 0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9 };
241 /* DLC 1, Long Data */
242 static const guint8 basic_long_frame[] =
243 { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
244 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
245 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
246 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
247 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
248 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
249 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
250 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
251 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
252 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
253 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
254 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
255 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
256 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
257 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
258 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
259 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
262 static const guint8 basic_long_frame_result[] =
263 { 0xF9, 0x07, 0xEF, 0x10, 0x01, 0x12, 0x34, 0x56,
264 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
265 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
266 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
267 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
268 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
269 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
270 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
271 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
272 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
273 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
274 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
275 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
276 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
277 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
278 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
279 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
280 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x88, 0xF9
283 static void test_fill_basic(void)
285 guint8 control_frame[6];
286 guint8 data_frame[128];
287 guint8 long_frame[256];
290 s = gsm0710_basic_fill_frame(control_frame, 1, GSM0710_OPEN_CHANNEL,
292 g_assert(s == sizeof(basic_open));
293 g_assert(memcmp(basic_open, control_frame, s) == 0);
295 s = gsm0710_basic_fill_frame(control_frame, 1, GSM0710_CLOSE_CHANNEL,
297 g_assert(s == sizeof(basic_close));
298 g_assert(memcmp(basic_close, control_frame, s) == 0);
300 s = gsm0710_basic_fill_frame(data_frame, 1, GSM0710_DATA,
301 basic_data, sizeof(basic_data));
302 g_assert(s == sizeof(basic_data_result));
303 g_assert(memcmp(basic_data_result, data_frame, s) == 0);
305 s = gsm0710_basic_fill_frame(long_frame, 1, GSM0710_DATA,
307 sizeof(basic_long_frame));
308 g_assert(s == sizeof(basic_long_frame_result));
309 g_assert(memcmp(basic_long_frame_result, long_frame, s) == 0);
312 /* DLC 1, Open Channel */
313 static const guint8 advanced_open[] = { 0x7E, 0x07, 0x3F, 0x89, 0x7E };
315 /* DLC 1, Close Channel */
316 static const guint8 advanced_close[] = { 0x7E, 0x07, 0x53, 0xC8, 0x7E };
319 static const guint8 advanced_data[] = { 0x12, 0x34, 0x56 };
320 static const guint8 advanced_data_result[] =
321 { 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
323 /* DLC 1, Quoted data */
324 static const guint8 advanced_quoted_data[] =
325 { 0x12, 0x34, 0x56, 0x7E, 0x78, 0x7D };
326 static const guint8 advanced_quoted_data_result[] =
327 { 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x7D, 0x5E, 0x78,
328 0x7D, 0x5D, 0x05, 0x7E };
330 static void test_fill_advanced(void)
332 guint8 control_frame[8];
333 guint8 data_frame[128];
336 s = gsm0710_advanced_fill_frame(control_frame, 1, GSM0710_OPEN_CHANNEL,
338 g_assert(s == sizeof(advanced_open));
339 g_assert(memcmp(advanced_open, control_frame, s) == 0);
341 s = gsm0710_advanced_fill_frame(control_frame, 1, GSM0710_CLOSE_CHANNEL,
343 g_assert(s == sizeof(advanced_close));
344 g_assert(memcmp(advanced_close, control_frame, s) == 0);
346 s = gsm0710_advanced_fill_frame(data_frame, 1, GSM0710_DATA,
347 advanced_data, sizeof(advanced_data));
348 g_assert(s == sizeof(advanced_data_result));
349 g_assert(memcmp(advanced_data_result, data_frame, s) == 0);
351 s = gsm0710_advanced_fill_frame(data_frame, 1, GSM0710_DATA,
352 advanced_quoted_data,
353 sizeof(advanced_quoted_data));
354 g_assert(s == sizeof(advanced_quoted_data_result));
355 g_assert(memcmp(advanced_quoted_data_result, data_frame, s) == 0);
358 static guint8 basic_input[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x07, 0xEF,
359 0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9, 0x07, 0xEF, 0x07, 0x12, 0x34, 0x56,
362 static guint8 basic_input2[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x07, 0xEF,
363 0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9, 0xF9, 0x07, 0xEF, 0x07, 0x12,
364 0x34, 0x56, 0xD3, 0xF9 };
366 static int basic_garbage_size = 4;
367 static int basic_frame_size = 7;
369 static const guint8 basic_output[] = { 0x12, 0x34, 0x56 };
371 static void test_extract_basic(void)
383 nread = gsm0710_basic_extract_frame(basic_input + total,
384 basic_garbage_size, &dlc, &ctrl,
385 &frame, &frame_size);
387 g_assert(frame == NULL);
388 g_assert(frame_size == 0);
392 /* Try to read with just the open flag */
393 nread = gsm0710_basic_extract_frame(basic_input + total,
394 basic_frame_size + 1,
396 &frame, &frame_size);
398 g_assert(nread == 0);
399 g_assert(frame == NULL);
401 /* Now read with the close flag as well */
402 nread = gsm0710_basic_extract_frame(basic_input + total,
403 basic_frame_size + 2,
405 &frame, &frame_size);
407 /* Extracted the open flag + frame */
408 g_assert(nread == basic_frame_size + 1);
409 g_assert(frame_size == sizeof(basic_output));
410 g_assert(memcmp(basic_output, frame, frame_size) == 0);
414 nread = gsm0710_basic_extract_frame(basic_input + total,
415 sizeof(basic_input) - total,
417 &frame, &frame_size);
419 g_assert(nread == (int)(sizeof(basic_input) - total - 1));
420 g_assert(frame_size == sizeof(basic_output));
421 g_assert(memcmp(basic_output, frame, frame_size) == 0);
425 nread = gsm0710_basic_extract_frame(basic_input + total,
426 sizeof(basic_input) - total,
428 &frame, &frame_size);
429 g_assert(nread == 0);
433 nread = gsm0710_basic_extract_frame(basic_input2 + total,
434 sizeof(basic_input2) - total,
436 &frame, &frame_size);
438 g_assert(nread == basic_garbage_size + basic_frame_size + 1);
439 g_assert(frame_size == sizeof(basic_output));
440 g_assert(memcmp(basic_output, frame, frame_size) == 0);
444 nread = gsm0710_basic_extract_frame(basic_input2 + total,
445 sizeof(basic_input2) - total,
447 &frame, &frame_size);
449 g_assert(frame_size == sizeof(basic_output));
450 g_assert(memcmp(basic_output, frame, frame_size) == 0);
454 g_assert(total == sizeof(basic_input2) - 1);
457 static guint8 advanced_input[] =
458 { 0xFF, 0xFF, 0xFF, 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E,
459 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
461 static guint8 advanced_input2[] =
462 { 0xFF, 0xFF, 0xFF, 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E,
463 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
465 static int advanced_garbage_size = 3;
466 static int advanced_frame_size = 6;
468 static const guint8 advanced_output[] = { 0x12, 0x34, 0x56 };
470 static void test_extract_advanced(void)
482 nread = gsm0710_advanced_extract_frame(advanced_input + total,
483 advanced_garbage_size,
485 &frame, &frame_size);
487 g_assert(frame == NULL);
488 g_assert(frame_size == 0);
492 /* Try to read with just the open flag */
493 nread = gsm0710_advanced_extract_frame(advanced_input + total,
494 advanced_frame_size + 1,
496 &frame, &frame_size);
498 g_assert(nread == 0);
499 g_assert(frame == NULL);
501 /* Now read with the close flag as well */
502 nread = gsm0710_advanced_extract_frame(advanced_input + total,
503 advanced_frame_size + 2,
505 &frame, &frame_size);
507 /* Extracted the open flag + frame */
508 g_assert(nread == advanced_frame_size + 1);
509 g_assert(frame_size == sizeof(advanced_output));
510 g_assert(memcmp(advanced_output, frame, frame_size) == 0);
514 nread = gsm0710_advanced_extract_frame(advanced_input + total,
515 sizeof(advanced_input) - total,
517 &frame, &frame_size);
519 g_assert(nread == (int)(sizeof(advanced_input) - total - 1));
520 g_assert(frame_size == sizeof(advanced_output));
521 g_assert(memcmp(advanced_output, frame, frame_size) == 0);
525 nread = gsm0710_advanced_extract_frame(advanced_input + total,
526 sizeof(advanced_input) - total,
528 &frame, &frame_size);
529 g_assert(nread == 0);
533 nread = gsm0710_advanced_extract_frame(advanced_input2 + total,
534 sizeof(advanced_input2) - total,
536 &frame, &frame_size);
538 g_assert(nread == advanced_garbage_size + advanced_frame_size + 1);
539 g_assert(frame_size == sizeof(advanced_output));
540 g_assert(memcmp(advanced_output, frame, frame_size) == 0);
544 nread = gsm0710_advanced_extract_frame(advanced_input2 + total,
545 sizeof(advanced_input2) - total,
547 &frame, &frame_size);
549 g_assert(frame_size == sizeof(advanced_output));
550 g_assert(memcmp(advanced_output, frame, frame_size) == 0);
554 g_assert(total == sizeof(advanced_input2) - 1);
557 int main(int argc, char **argv)
559 g_test_init(&argc, &argv, NULL);
561 g_test_add_func("/testmux/fill_basic", test_fill_basic);
562 g_test_add_func("/testmux/fill_advanced", test_fill_advanced);
563 g_test_add_func("/testmux/extract_basic", test_extract_basic);
564 g_test_add_func("/testmux/extract_advanced", test_extract_advanced);
565 g_test_add_func("/testmux/basic", test_basic);