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>
33 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
36 #include <glib/gprintf.h>
41 static int do_connect(const char *address, unsigned short port)
43 struct sockaddr_in addr;
46 sk = socket(PF_INET, SOCK_STREAM, 0);
50 memset(&addr, 0, sizeof(addr));
51 addr.sin_family = AF_INET;
52 addr.sin_addr.s_addr = inet_addr(address);
53 addr.sin_port = htons(port);
55 err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
64 static GMainLoop *mainloop;
67 static gboolean cleanup_callback(gpointer data)
71 g_main_loop_quit(mainloop);
76 static gboolean chat_cleanup(gpointer data)
80 g_at_chat_unref(chat);
85 static void chat_callback(gboolean ok, GAtResult *result, gpointer user_data)
89 g_at_result_iter_init(&iter, result);
91 g_print("chat: callback [ok %d]\n", ok);
93 g_print("%s\n", g_at_result_final_response(result));
95 g_idle_add(chat_cleanup, user_data);
98 static void mux_debug(const char *str, void *data)
100 g_print("%s: %s\n", (char *) data, str);
103 static void mux_setup(GAtMux *m, gpointer data)
105 GAtChat *chat = data;
111 g_print("mux_setup: %p\n", mux);
114 g_at_chat_unref(chat);
115 g_main_loop_quit(mainloop);
121 io = g_at_mux_create_channel(mux);
122 syntax = g_at_syntax_new_gsm_permissive();
123 chat = g_at_chat_new(io, syntax);
124 g_at_syntax_unref(syntax);
125 g_io_channel_unref(io);
127 g_at_chat_set_debug(chat, mux_debug, "CHAT1");
128 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
129 g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
130 g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
132 io = g_at_mux_create_channel(mux);
133 syntax = g_at_syntax_new_gsm_permissive();
134 chat = g_at_chat_new(io, syntax);
135 g_at_syntax_unref(syntax);
136 g_io_channel_unref(io);
138 g_at_chat_set_debug(chat, mux_debug, "CHAT2");
139 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
140 g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
141 g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
143 io = g_at_mux_create_channel(mux);
144 syntax = g_at_syntax_new_gsm_permissive();
145 chat = g_at_chat_new(io, syntax);
146 g_at_syntax_unref(syntax);
147 g_io_channel_unref(io);
149 g_at_chat_set_debug(chat, mux_debug, "CHAT3");
150 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
151 g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
152 g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
154 io = g_at_mux_create_channel(mux);
155 syntax = g_at_syntax_new_gsm_permissive();
156 chat = g_at_chat_new(io, syntax);
157 g_at_syntax_unref(syntax);
158 g_io_channel_unref(io);
160 g_at_chat_set_debug(chat, mux_debug, "CHAT4");
161 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
162 g_at_chat_send(chat, "AT+CGMI", NULL, NULL, NULL, NULL);
163 g_at_chat_send(chat, "AT+CGMR", NULL, chat_callback, chat, NULL);
165 g_timeout_add_seconds(7, cleanup_callback, NULL);
168 static void mux_init(gboolean ok, GAtResult *result, gpointer data)
170 GAtChat *chat = data;
172 g_print("mux_init: %d\n", ok);
175 g_at_chat_unref(chat);
176 g_main_loop_quit(mainloop);
180 g_at_mux_setup_gsm0710(chat, mux_setup, chat, NULL);
183 static void test_mux(void)
190 sk = do_connect("192.168.0.202", 2000);
192 g_printerr("connect failed\n");
197 io = g_io_channel_unix_new(sk);
198 g_io_channel_set_close_on_unref(io, TRUE);
200 syntax = g_at_syntax_new_gsm_permissive();
201 chat = g_at_chat_new(io, syntax);
202 g_at_syntax_unref(syntax);
204 g_io_channel_unref(io);
207 g_printerr("Chat creation failed\n");
211 g_at_chat_set_debug(chat, mux_debug, "MUX");
212 g_at_chat_set_wakeup_command(chat, "\r", 1000, 5000);
213 g_at_chat_send(chat, "ATE0", NULL, mux_init, chat, NULL);
215 mainloop = g_main_loop_new(NULL, FALSE);
217 g_main_loop_run(mainloop);
218 g_main_loop_unref(mainloop);
221 static void test_basic(void)
223 if (g_test_trap_fork(60 * 1000 * 1000, 0) == TRUE) {
228 g_test_trap_assert_passed();
229 //g_test_trap_assert_stderr("failed");
232 /* DLC 1, Open Channel */
233 static const guint8 basic_open[] = { 0xF9, 0x07, 0x3F, 0x01, 0xDE, 0xF9 };
235 /* DLC 1, Close Channel */
236 static char const basic_close[] = { 0xF9, 0x07, 0x53, 0x01, 0x3F, 0xF9 };
239 static const guint8 basic_data[] = { 0x12, 0x34, 0x56 };
240 static const guint8 basic_data_result[] =
241 { 0xF9, 0x07, 0xEF, 0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9 };
243 /* DLC 1, Long Data */
244 static const guint8 basic_long_frame[] =
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,
260 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
261 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
264 static const guint8 basic_long_frame_result[] =
265 { 0xF9, 0x07, 0xEF, 0x10, 0x01, 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, 0x12, 0x34, 0x56,
281 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56,
282 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x88, 0xF9
285 static void test_fill_basic(void)
287 guint8 control_frame[6];
288 guint8 data_frame[128];
289 guint8 long_frame[256];
292 s = gsm0710_basic_fill_frame(control_frame, 1, GSM0710_OPEN_CHANNEL,
294 g_assert(s == sizeof(basic_open));
295 g_assert(memcmp(basic_open, control_frame, s) == 0);
297 s = gsm0710_basic_fill_frame(control_frame, 1, GSM0710_CLOSE_CHANNEL,
299 g_assert(s == sizeof(basic_close));
300 g_assert(memcmp(basic_close, control_frame, s) == 0);
302 s = gsm0710_basic_fill_frame(data_frame, 1, GSM0710_DATA,
303 basic_data, sizeof(basic_data));
304 g_assert(s == sizeof(basic_data_result));
305 g_assert(memcmp(basic_data_result, data_frame, s) == 0);
307 s = gsm0710_basic_fill_frame(long_frame, 1, GSM0710_DATA,
309 sizeof(basic_long_frame));
310 g_assert(s == sizeof(basic_long_frame_result));
311 g_assert(memcmp(basic_long_frame_result, long_frame, s) == 0);
314 /* DLC 1, Open Channel */
315 static const guint8 advanced_open[] = { 0x7E, 0x07, 0x3F, 0x89, 0x7E };
317 /* DLC 1, Close Channel */
318 static const guint8 advanced_close[] = { 0x7E, 0x07, 0x53, 0xC8, 0x7E };
321 static const guint8 advanced_data[] = { 0x12, 0x34, 0x56 };
322 static const guint8 advanced_data_result[] =
323 { 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
325 /* DLC 1, Quoted data */
326 static const guint8 advanced_quoted_data[] =
327 { 0x12, 0x34, 0x56, 0x7E, 0x78, 0x7D };
328 static const guint8 advanced_quoted_data_result[] =
329 { 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x7D, 0x5E, 0x78,
330 0x7D, 0x5D, 0x05, 0x7E };
332 static void test_fill_advanced(void)
334 guint8 control_frame[8];
335 guint8 data_frame[128];
338 s = gsm0710_advanced_fill_frame(control_frame, 1, GSM0710_OPEN_CHANNEL,
340 g_assert(s == sizeof(advanced_open));
341 g_assert(memcmp(advanced_open, control_frame, s) == 0);
343 s = gsm0710_advanced_fill_frame(control_frame, 1, GSM0710_CLOSE_CHANNEL,
345 g_assert(s == sizeof(advanced_close));
346 g_assert(memcmp(advanced_close, control_frame, s) == 0);
348 s = gsm0710_advanced_fill_frame(data_frame, 1, GSM0710_DATA,
349 advanced_data, sizeof(advanced_data));
350 g_assert(s == sizeof(advanced_data_result));
351 g_assert(memcmp(advanced_data_result, data_frame, s) == 0);
353 s = gsm0710_advanced_fill_frame(data_frame, 1, GSM0710_DATA,
354 advanced_quoted_data,
355 sizeof(advanced_quoted_data));
356 g_assert(s == sizeof(advanced_quoted_data_result));
357 g_assert(memcmp(advanced_quoted_data_result, data_frame, s) == 0);
360 static guint8 basic_input[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x07, 0xEF,
361 0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9, 0x07, 0xEF, 0x07, 0x12, 0x34, 0x56,
364 static guint8 basic_input2[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x07, 0xEF,
365 0x07, 0x12, 0x34, 0x56, 0xD3, 0xF9, 0xF9, 0x07, 0xEF, 0x07, 0x12,
366 0x34, 0x56, 0xD3, 0xF9 };
368 static int basic_garbage_size = 4;
369 static int basic_frame_size = 7;
371 static const guint8 basic_output[] = { 0x12, 0x34, 0x56 };
373 static void test_extract_basic(void)
385 nread = gsm0710_basic_extract_frame(basic_input + total,
386 basic_garbage_size, &dlc, &ctrl,
387 &frame, &frame_size);
389 g_assert(frame == NULL);
390 g_assert(frame_size == 0);
394 /* Try to read with just the open flag */
395 nread = gsm0710_basic_extract_frame(basic_input + total,
396 basic_frame_size + 1,
398 &frame, &frame_size);
400 g_assert(nread == 0);
401 g_assert(frame == NULL);
403 /* Now read with the close flag as well */
404 nread = gsm0710_basic_extract_frame(basic_input + total,
405 basic_frame_size + 2,
407 &frame, &frame_size);
409 /* Extracted the open flag + frame */
410 g_assert(nread == basic_frame_size + 1);
411 g_assert(frame_size == sizeof(basic_output));
412 g_assert(memcmp(basic_output, frame, frame_size) == 0);
416 nread = gsm0710_basic_extract_frame(basic_input + total,
417 sizeof(basic_input) - total,
419 &frame, &frame_size);
421 g_assert(nread == (int)(sizeof(basic_input) - total - 1));
422 g_assert(frame_size == sizeof(basic_output));
423 g_assert(memcmp(basic_output, frame, frame_size) == 0);
427 nread = gsm0710_basic_extract_frame(basic_input + total,
428 sizeof(basic_input) - total,
430 &frame, &frame_size);
431 g_assert(nread == 0);
435 nread = gsm0710_basic_extract_frame(basic_input2 + total,
436 sizeof(basic_input2) - total,
438 &frame, &frame_size);
440 g_assert(nread == basic_garbage_size + basic_frame_size + 1);
441 g_assert(frame_size == sizeof(basic_output));
442 g_assert(memcmp(basic_output, frame, frame_size) == 0);
446 nread = gsm0710_basic_extract_frame(basic_input2 + total,
447 sizeof(basic_input2) - total,
449 &frame, &frame_size);
451 g_assert(frame_size == sizeof(basic_output));
452 g_assert(memcmp(basic_output, frame, frame_size) == 0);
456 g_assert(total == sizeof(basic_input2) - 1);
459 static guint8 advanced_input[] =
460 { 0xFF, 0xFF, 0xFF, 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E,
461 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
463 static guint8 advanced_input2[] =
464 { 0xFF, 0xFF, 0xFF, 0x7E, 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E,
465 0x07, 0xEF, 0x12, 0x34, 0x56, 0x05, 0x7E };
467 static int advanced_garbage_size = 3;
468 static int advanced_frame_size = 6;
470 static const guint8 advanced_output[] = { 0x12, 0x34, 0x56 };
472 static void test_extract_advanced(void)
484 nread = gsm0710_advanced_extract_frame(advanced_input + total,
485 advanced_garbage_size,
487 &frame, &frame_size);
489 g_assert(frame == NULL);
490 g_assert(frame_size == 0);
494 /* Try to read with just the open flag */
495 nread = gsm0710_advanced_extract_frame(advanced_input + total,
496 advanced_frame_size + 1,
498 &frame, &frame_size);
500 g_assert(nread == 0);
501 g_assert(frame == NULL);
503 /* Now read with the close flag as well */
504 nread = gsm0710_advanced_extract_frame(advanced_input + total,
505 advanced_frame_size + 2,
507 &frame, &frame_size);
509 /* Extracted the open flag + frame */
510 g_assert(nread == advanced_frame_size + 1);
511 g_assert(frame_size == sizeof(advanced_output));
512 g_assert(memcmp(advanced_output, frame, frame_size) == 0);
516 nread = gsm0710_advanced_extract_frame(advanced_input + total,
517 sizeof(advanced_input) - total,
519 &frame, &frame_size);
521 g_assert(nread == (int)(sizeof(advanced_input) - total - 1));
522 g_assert(frame_size == sizeof(advanced_output));
523 g_assert(memcmp(advanced_output, frame, frame_size) == 0);
527 nread = gsm0710_advanced_extract_frame(advanced_input + total,
528 sizeof(advanced_input) - total,
530 &frame, &frame_size);
531 g_assert(nread == 0);
535 nread = gsm0710_advanced_extract_frame(advanced_input2 + total,
536 sizeof(advanced_input2) - total,
538 &frame, &frame_size);
540 g_assert(nread == advanced_garbage_size + advanced_frame_size + 1);
541 g_assert(frame_size == sizeof(advanced_output));
542 g_assert(memcmp(advanced_output, frame, frame_size) == 0);
546 nread = gsm0710_advanced_extract_frame(advanced_input2 + total,
547 sizeof(advanced_input2) - total,
549 &frame, &frame_size);
551 g_assert(frame_size == sizeof(advanced_output));
552 g_assert(memcmp(advanced_output, frame, frame_size) == 0);
556 g_assert(total == sizeof(advanced_input2) - 1);
559 int main(int argc, char **argv)
561 g_test_init(&argc, &argv, NULL);
563 g_test_add_func("/testmux/fill_basic", test_fill_basic);
564 g_test_add_func("/testmux/fill_advanced", test_fill_advanced);
565 g_test_add_func("/testmux/extract_basic", test_extract_basic);
566 g_test_add_func("/testmux/extract_advanced", test_extract_advanced);
567 g_test_add_func("/testmux/basic", test_basic);