3 * AT server library with GLib integration
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
32 #include "ringbuffer.h"
33 #include "gatserver.h"
37 /* <cr><lf> + the max length of information text + <cr><lf> */
38 #define MAX_TEXT_SIZE 2052
39 /* #define WRITE_SCHEDULER_DEBUG 1 */
49 PARSER_RESULT_COMMAND,
50 PARSER_RESULT_EMPTY_COMMAND,
51 PARSER_RESULT_REPEAT_LAST,
52 PARSER_RESULT_GARBAGE,
56 /* V.250 Table 1/V.250 Result codes */
57 static const char *server_result_to_string(GAtServerResult result)
60 case G_AT_SERVER_RESULT_OK:
62 case G_AT_SERVER_RESULT_CONNECT:
64 case G_AT_SERVER_RESULT_RING:
66 case G_AT_SERVER_RESULT_NO_CARRIER:
68 case G_AT_SERVER_RESULT_ERROR:
70 case G_AT_SERVER_RESULT_NO_DIALTONE:
72 case G_AT_SERVER_RESULT_BUSY:
74 case G_AT_SERVER_RESULT_NO_ANSWER:
81 /* Basic command setting for V.250 */
82 struct v250_settings {
83 char s0; /* set by S0=<val> */
84 char s3; /* set by S3=<val> */
85 char s4; /* set by S4=<val> */
86 char s5; /* set by S5=<val> */
87 int s6; /* set by S6=<val> */
88 int s7; /* set by S7=<val> */
89 int s8; /* set by S8=<val> */
90 int s10; /* set by S10=<val> */
91 gboolean echo; /* set by E<val> */
92 gboolean quiet; /* set by Q<val> */
93 gboolean is_v1; /* set by V<val>, v0 or v1 */
94 int res_format; /* set by X<val> */
95 int c109; /* set by &C<val> */
96 int c108; /* set by &D<val> */
97 char l; /* set by L<val> */
98 char m; /* set by M<val> */
99 char dial_mode; /* set by P or T */
102 /* AT command set that server supported */
104 GAtServerNotifyFunc notify;
106 GDestroyNotify destroy_notify;
110 gint ref_count; /* Ref count */
111 struct v250_settings v250; /* V.250 command setting */
112 GAtIO *io; /* Server IO */
113 guint read_so_far; /* Number of bytes processed */
114 GAtDisconnectFunc user_disconnect; /* User disconnect func */
115 gpointer user_disconnect_data; /* User disconnect data */
116 GAtDebugFunc debugf; /* Debugging output function */
117 gpointer debug_data; /* Data to pass to debug func */
118 GHashTable *command_list; /* List of AT commands */
119 GQueue *write_queue; /* Write buffer queue */
120 guint max_read_attempts; /* Max reads per select */
121 enum ParserState parser_state;
122 gboolean destroyed; /* Re-entrancy guard */
123 char *last_line; /* Last read line */
124 unsigned int cur_pos; /* Where we are on the line */
125 GAtServerResult last_result;
127 gboolean final_async;
128 gboolean in_read_handler;
129 GAtServerFinishFunc finishf; /* Callback when cmd finishes */
130 gpointer finish_data; /* Finish func data */
133 static void server_wakeup_writer(GAtServer *server);
134 static void server_parse_line(GAtServer *server);
136 static struct ring_buffer *allocate_next(GAtServer *server)
138 struct ring_buffer *buf = ring_buffer_new(BUF_SIZE);
143 g_queue_push_tail(server->write_queue, buf);
148 static void send_common(GAtServer *server, const char *buf, unsigned int len)
151 gsize bytes_written = 0;
152 struct ring_buffer *write_buf;
154 write_buf = g_queue_peek_tail(server->write_queue);
156 while (bytes_written < towrite) {
157 gsize wbytes = MIN((gsize)ring_buffer_avail(write_buf),
158 towrite - bytes_written);
160 bytes_written += ring_buffer_write(write_buf,
165 * Make sure we don't allocate a buffer if we've written
166 * everything out already
168 if (ring_buffer_avail(write_buf) == 0 &&
169 bytes_written < towrite)
170 write_buf = allocate_next(server);
173 server_wakeup_writer(server);
176 static void send_result_common(GAtServer *server, const char *result)
179 struct v250_settings v250 = server->v250;
180 char buf[MAX_TEXT_SIZE + 1];
191 if (strlen(result) > 2048)
195 len = sprintf(buf, "%c%c%s%c%c", t, r, result, t, r);
197 len = sprintf(buf, "%s%c", result, t);
199 send_common(server, buf, len);
202 static inline void send_final_common(GAtServer *server, const char *result)
204 send_result_common(server, result);
205 server->final_async = FALSE;
208 server->finishf(server, server->finish_data);
211 static inline void send_final_numeric(GAtServer *server, GAtServerResult result)
215 if (server->v250.is_v1)
216 sprintf(buf, "%s", server_result_to_string(result));
218 sprintf(buf, "%u", (unsigned int)result);
220 send_final_common(server, buf);
223 void g_at_server_send_final(GAtServer *server, GAtServerResult result)
228 if (server->final_sent != FALSE)
231 server->final_sent = TRUE;
232 server->last_result = result;
234 if (result == G_AT_SERVER_RESULT_OK) {
235 if (server->final_async)
236 server_parse_line(server);
241 send_final_numeric(server, result);
244 void g_at_server_send_ext_final(GAtServer *server, const char *result)
246 server->final_sent = TRUE;
247 server->last_result = G_AT_SERVER_RESULT_EXT_ERROR;
248 send_final_common(server, result);
251 void g_at_server_send_intermediate(GAtServer *server, const char *result)
253 send_result_common(server, result);
256 void g_at_server_send_unsolicited(GAtServer *server, const char *result)
258 send_result_common(server, result);
261 void g_at_server_send_info(GAtServer *server, const char *line, gboolean last)
263 char buf[MAX_TEXT_SIZE + 1];
264 char t = server->v250.s3;
265 char r = server->v250.s4;
268 if (strlen(line) > 2048)
272 len = sprintf(buf, "%c%c%s%c%c", t, r, line, t, r);
274 len = sprintf(buf, "%c%c%s", t, r, line);
276 send_common(server, buf, len);
279 static gboolean get_result_value(GAtServer *server, GAtResult *result,
280 int min, int max, int *value)
285 g_at_result_iter_init(&iter, result);
287 if (!g_at_result_iter_next(&iter, ""))
290 if (!g_at_result_iter_next_number(&iter, &val))
293 if (val < min || val > max)
302 static void v250_settings_create(struct v250_settings *v250)
315 v250->res_format = 0;
320 v250->dial_mode = 'T';
323 static void s_template_cb(GAtServerRequestType type, GAtResult *result,
324 GAtServer *server, char *sreg,
325 const char *prefix, int min, int max)
331 case G_AT_SERVER_REQUEST_TYPE_SET:
332 if (!get_result_value(server, result, min, max, &tmp)) {
333 g_at_server_send_final(server,
334 G_AT_SERVER_RESULT_ERROR);
339 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
342 case G_AT_SERVER_REQUEST_TYPE_QUERY:
344 sprintf(buf, "%03d", tmp);
345 g_at_server_send_info(server, buf, TRUE);
346 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
349 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
350 sprintf(buf, "%s: (%d-%d)", prefix, min, max);
351 g_at_server_send_info(server, buf, TRUE);
352 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
356 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
361 static void at_s0_cb(GAtServer *server, GAtServerRequestType type,
362 GAtResult *result, gpointer user_data)
364 s_template_cb(type, result, server, &server->v250.s0, "S0", 0, 7);
367 static void at_s3_cb(GAtServer *server, GAtServerRequestType type,
368 GAtResult *result, gpointer user_data)
370 s_template_cb(type, result, server, &server->v250.s3, "S3", 0, 127);
373 static void at_s4_cb(GAtServer *server, GAtServerRequestType type,
374 GAtResult *result, gpointer user_data)
376 s_template_cb(type, result, server, &server->v250.s4, "S4", 0, 127);
379 static void at_s5_cb(GAtServer *server, GAtServerRequestType type,
380 GAtResult *result, gpointer user_data)
382 s_template_cb(type, result, server, &server->v250.s5, "S5", 0, 127);
385 static void at_l_cb(GAtServer *server, GAtServerRequestType type,
386 GAtResult *result, gpointer user_data)
388 s_template_cb(type, result, server, &server->v250.l, "L", 0, 3);
391 static void at_m_cb(GAtServer *server, GAtServerRequestType type,
392 GAtResult *result, gpointer user_data)
394 s_template_cb(type, result, server, &server->v250.m, "M", 0, 2);
397 static void at_template_cb(GAtServerRequestType type, GAtResult *result,
398 GAtServer *server, int *value,
400 int min, int max, int deftval)
406 case G_AT_SERVER_REQUEST_TYPE_SET:
407 if (!get_result_value(server, result, min, max, &tmp)) {
408 g_at_server_send_final(server,
409 G_AT_SERVER_RESULT_ERROR);
414 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
417 case G_AT_SERVER_REQUEST_TYPE_QUERY:
419 sprintf(buf, "%s: %d", prefix, tmp);
420 g_at_server_send_info(server, buf, TRUE);
421 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
424 case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
425 sprintf(buf, "%s: (%d-%d)", prefix, min, max);
426 g_at_server_send_info(server, buf, TRUE);
427 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
430 case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
432 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
436 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
441 static void at_e_cb(GAtServer *server, GAtServerRequestType type,
442 GAtResult *result, gpointer user_data)
444 at_template_cb(type, result, server, &server->v250.echo, "E", 0, 1, 1);
447 static void at_q_cb(GAtServer *server, GAtServerRequestType type,
448 GAtResult *result, gpointer user_data)
450 at_template_cb(type, result, server, &server->v250.quiet, "Q", 0, 1, 0);
453 static void at_v_cb(GAtServer *server, GAtServerRequestType type,
454 GAtResult *result, gpointer user_data)
456 at_template_cb(type, result, server, &server->v250.is_v1, "V", 0, 1, 1);
459 static void at_x_cb(GAtServer *server, GAtServerRequestType type,
460 GAtResult *result, gpointer user_data)
462 at_template_cb(type, result, server, &server->v250.res_format,
466 static void at_s6_cb(GAtServer *server, GAtServerRequestType type,
467 GAtResult *result, gpointer user_data)
469 at_template_cb(type, result, server, &server->v250.s6, "S6", 0, 1, 1);
472 static void at_s7_cb(GAtServer *server, GAtServerRequestType type,
473 GAtResult *result, gpointer user_data)
475 at_template_cb(type, result, server, &server->v250.s7, "S7", 1, 255, 50);
478 static void at_s8_cb(GAtServer *server, GAtServerRequestType type,
479 GAtResult *result, gpointer user_data)
481 at_template_cb(type, result, server, &server->v250.s8, "S8", 1, 255, 2);
484 static void at_s10_cb(GAtServer *server, GAtServerRequestType type,
485 GAtResult *result, gpointer user_data)
487 at_template_cb(type, result, server, &server->v250.s10, "S10", 1, 254, 2);
490 static void at_c109_cb(GAtServer *server, GAtServerRequestType type,
491 GAtResult *result, gpointer user_data)
493 at_template_cb(type, result, server, &server->v250.c109, "&C", 0, 1, 1);
496 static void at_c108_cb(GAtServer *server, GAtServerRequestType type,
497 GAtResult *result, gpointer user_data)
499 at_template_cb(type, result, server, &server->v250.c108, "&D", 0, 2, 2);
502 /* According to ITU V.250 6.3.2 and 6.3.3: "Implementation of this command
503 * is mandatory; however, if DTMF or pulse dialling is not implemented,
504 * this command will have no effect"
506 static void at_t_cb(GAtServer *server, GAtServerRequestType type,
507 GAtResult *result, gpointer user_data)
510 case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
511 server->v250.dial_mode = 'T';
512 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
516 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
521 static void at_p_cb(GAtServer *server, GAtServerRequestType type,
522 GAtResult *result, gpointer user_data)
525 case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
526 server->v250.dial_mode = 'P';
527 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
531 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
536 static void at_f_cb(GAtServer *server, GAtServerRequestType type,
537 GAtResult *result, gpointer user_data)
540 case G_AT_SERVER_REQUEST_TYPE_SET:
541 if (!get_result_value(server, result, 0, 0, NULL)) {
542 g_at_server_send_final(server,
543 G_AT_SERVER_RESULT_ERROR);
546 /* intentional fallback here */
548 case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
549 /* default behavior on AT&F same as ATZ */
550 v250_settings_create(&server->v250);
551 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
555 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
560 static void at_z_cb(GAtServer *server, GAtServerRequestType type,
561 GAtResult *result, gpointer user_data)
564 case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
565 v250_settings_create(&server->v250);
566 g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
570 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
575 static inline gboolean is_extended_command_prefix(const char c)
588 static void at_command_notify(GAtServer *server, char *command,
589 char *prefix, GAtServerRequestType type)
591 struct at_command *node;
594 node = g_hash_table_lookup(server->command_list, prefix);
597 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
601 result.lines = g_slist_prepend(NULL, command);
602 result.final_or_pdu = 0;
604 node->notify(server, type, &result, node->user_data);
606 g_slist_free(result.lines);
609 static unsigned int parse_extended_command(GAtServer *server, char *buf)
611 const char *valid_extended_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
613 const char *separators = ";?=";
614 unsigned int prefix_len, i;
615 gboolean in_string = FALSE;
616 gboolean seen_equals = FALSE;
617 char prefix[18]; /* According to V250, 5.4.1 */
618 GAtServerRequestType type;
620 unsigned int cmd_start;
622 prefix_len = strcspn(buf, separators);
624 if (prefix_len > 17 || prefix_len < 2)
627 /* Convert to upper case, we will always use upper case naming */
628 for (i = 0; i < prefix_len; i++)
629 prefix[i] = g_ascii_toupper(buf[i]);
631 prefix[prefix_len] = '\0';
633 if (strspn(prefix + 1, valid_extended_chars) != (prefix_len - 1))
637 * V.250 Section 5.4.1: "The first character following "+" shall be
638 * an alphabetic character in the range "A" through "Z".
640 if (prefix[1] <= 'A' || prefix[1] >= 'Z')
643 if (buf[i] != '\0' && buf[i] != ';' && buf[i] != '?' && buf[i] != '=')
646 type = G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY;
647 cmd_start = prefix_len;
649 /* Continue until we hit eol or ';' */
650 while (buf[i] && !(buf[i] == ';' && in_string == FALSE)) {
652 in_string = !in_string;
656 if (in_string == TRUE)
660 if (seen_equals && buf[i-1] != '=')
663 if (buf[i + 1] != '\0' && buf[i + 1] != ';')
666 type = G_AT_SERVER_REQUEST_TYPE_QUERY;
670 type = G_AT_SERVER_REQUEST_TYPE_SUPPORT;
671 } else if (buf[i] == '=') {
676 type = G_AT_SERVER_REQUEST_TYPE_SET;
684 /* We can scratch in this buffer, so mark ';' as null */
687 at_command_notify(server, buf + cmd_start, prefix, type);
690 /* Also consume the terminating null */
694 static int get_basic_prefix_size(const char *buf)
696 if (g_ascii_isalpha(buf[0])) {
697 if (g_ascii_toupper(buf[0]) == 'S') {
700 /* V.250 5.3.2 'S' command follows with a parameter
703 for (size = 1; g_ascii_isdigit(buf[size]); size++)
707 * Do some basic sanity checking, don't accept 00, 01,
708 * etc or empty S values
713 if (size > 2 && buf[1] == '0')
719 /* All other cases it is a simple 1 character prefix */
724 if (g_ascii_isalpha(buf[1]) == FALSE)
733 static unsigned int parse_basic_command(GAtServer *server, char *buf)
735 gboolean seen_equals = FALSE;
737 unsigned int i, prefix_size;
738 GAtServerRequestType type;
739 unsigned int cmd_start;
741 prefix_size = get_basic_prefix_size(buf);
742 if (prefix_size == 0)
746 prefix[0] = g_ascii_toupper(buf[0]);
747 cmd_start = prefix_size;
749 if (prefix[0] == 'D') {
750 type = G_AT_SERVER_REQUEST_TYPE_SET;
752 /* All characters appearing on the same line, up to a
753 * semicolon character (IA5 3/11) or the end of the
754 * command line is the part of the call.
756 while (buf[i] != '\0' && buf[i] != ';')
765 type = G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY;
767 /* Match '?', '=', '=?' and '=xxx' */
779 type = G_AT_SERVER_REQUEST_TYPE_SUPPORT;
781 type = G_AT_SERVER_REQUEST_TYPE_QUERY;
785 /* V.250 5.3.1 The subparameter (if any) are all digits */
786 while (g_ascii_isdigit(buf[i]))
790 type = G_AT_SERVER_REQUEST_TYPE_SET;
794 if (prefix_size <= 3) {
795 memcpy(prefix + 1, buf + 1, prefix_size - 1);
796 prefix[prefix_size] = '\0';
800 at_command_notify(server, buf + cmd_start, prefix, type);
802 } else /* Handle S-parameter with 100+ */
803 g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
806 * Commands like ATA, ATZ cause the remainder linevto be ignored.
807 * In GSM/UMTS the ATD uses the separator ';' character as a voicecall
808 * modifier, so we ignore everything coming after that character
811 if (prefix[0] == 'A' || prefix[0] == 'Z' || prefix[0] == 'D')
814 /* Consume the seperator ';' */
821 static void server_parse_line(GAtServer *server)
823 char *line = server->last_line;
824 unsigned int pos = server->cur_pos;
825 unsigned int len = strlen(line);
828 unsigned int consumed;
830 server->final_sent = FALSE;
831 server->final_async = FALSE;
833 if (is_extended_command_prefix(line[pos]))
834 consumed = parse_extended_command(server, line + pos);
836 consumed = parse_basic_command(server, line + pos);
839 g_at_server_send_final(server,
840 G_AT_SERVER_RESULT_ERROR);
845 server->cur_pos = pos;
848 * We wait the callback until it finished processing
849 * the command and called the send_final.
851 if (server->final_sent == FALSE) {
852 server->final_async = TRUE;
856 if (server->last_result != G_AT_SERVER_RESULT_OK)
860 send_final_numeric(server, G_AT_SERVER_RESULT_OK);
863 static enum ParserResult server_feed(GAtServer *server,
864 const char *bytes, gsize *len)
867 enum ParserResult res = PARSER_RESULT_UNSURE;
868 char s3 = server->v250.s3;
871 char byte = bytes[i];
873 switch (server->parser_state) {
874 case PARSER_STATE_IDLE:
877 res = PARSER_RESULT_EMPTY_COMMAND;
879 } else if (byte == '\n') {
881 res = PARSER_RESULT_GARBAGE;
883 } else if (byte == 'A' || byte == 'a')
884 server->parser_state = PARSER_STATE_A;
885 else if (byte != ' ' && byte != '\t')
886 server->parser_state = PARSER_STATE_GARBAGE;
891 server->parser_state = PARSER_STATE_IDLE;
893 res = PARSER_RESULT_GARBAGE;
895 } else if (byte == '/') {
896 server->parser_state = PARSER_STATE_IDLE;
898 res = PARSER_RESULT_REPEAT_LAST;
900 } else if (byte == 'T' || byte == 't')
901 server->parser_state = PARSER_STATE_COMMAND;
903 server->parser_state = PARSER_STATE_GARBAGE;
907 case PARSER_STATE_COMMAND:
909 server->parser_state = PARSER_STATE_IDLE;
911 res = PARSER_RESULT_COMMAND;
916 case PARSER_STATE_GARBAGE:
917 /* Detect CR or HDLC frame marker flag */
918 if (byte == s3 || byte == '~') {
919 server->parser_state = PARSER_STATE_IDLE;
921 res = PARSER_RESULT_GARBAGE;
938 static char *extract_line(GAtServer *p, struct ring_buffer *rbuf)
940 unsigned int wrap = ring_buffer_len_no_wrap(rbuf);
941 unsigned int pos = 0;
942 unsigned char *buf = ring_buffer_read_ptr(rbuf, pos);
945 gboolean in_string = FALSE;
946 char s3 = p->v250.s3;
947 char s5 = p->v250.s5;
951 while (pos < p->read_so_far) {
953 in_string = !in_string;
955 if (in_string == FALSE && (*buf == ' ' || *buf == '\t')) {
956 if (line_length == 0)
965 buf = ring_buffer_read_ptr(rbuf, pos);
968 /* We will strip AT and S3 */
971 line = g_try_new(char, line_length + 1);
973 ring_buffer_drain(rbuf, p->read_so_far);
977 /* Strip leading whitespace + AT */
978 ring_buffer_drain(rbuf, strip_front + 2);
982 wrap = ring_buffer_len_no_wrap(rbuf);
983 buf = ring_buffer_read_ptr(rbuf, pos);
985 while (pos < (p->read_so_far - strip_front - 2)) {
987 in_string = !in_string;
992 } else if ((*buf == ' ' || *buf == '\t') && in_string == FALSE)
1001 buf = ring_buffer_read_ptr(rbuf, pos);
1005 ring_buffer_drain(rbuf, p->read_so_far - strip_front - 2);
1012 static void new_bytes(struct ring_buffer *rbuf, gpointer user_data)
1014 GAtServer *p = user_data;
1015 unsigned int len = ring_buffer_len(rbuf);
1016 unsigned int wrap = ring_buffer_len_no_wrap(rbuf);
1017 unsigned char *buf = ring_buffer_read_ptr(rbuf, p->read_so_far);
1018 enum ParserResult result;
1020 /* We do not support command abortion, so ignore input */
1021 if (p->final_async) {
1022 ring_buffer_drain(rbuf, len);
1026 p->in_read_handler = TRUE;
1028 while (p->io && (p->read_so_far < len)) {
1029 gsize rbytes = MIN(len - p->read_so_far, wrap - p->read_so_far);
1030 result = server_feed(p, (char *)buf, &rbytes);
1033 send_common(p, (char *)buf, rbytes);
1036 p->read_so_far += rbytes;
1038 if (p->read_so_far == wrap) {
1039 buf = ring_buffer_read_ptr(rbuf, p->read_so_far);
1044 case PARSER_RESULT_UNSURE:
1047 case PARSER_RESULT_EMPTY_COMMAND:
1049 * According to section 5.2.4 and 5.6 of V250,
1050 * Empty commands must be OK by the DCE
1052 g_at_server_send_final(p, G_AT_SERVER_RESULT_OK);
1053 ring_buffer_drain(rbuf, p->read_so_far);
1056 case PARSER_RESULT_COMMAND:
1058 g_free(p->last_line);
1060 p->last_line = extract_line(p, rbuf);
1064 server_parse_line(p);
1066 g_at_server_send_final(p,
1067 G_AT_SERVER_RESULT_ERROR);
1071 case PARSER_RESULT_REPEAT_LAST:
1073 ring_buffer_drain(rbuf, p->read_so_far);
1076 server_parse_line(p);
1078 g_at_server_send_final(p,
1079 G_AT_SERVER_RESULT_OK);
1082 case PARSER_RESULT_GARBAGE:
1083 ring_buffer_drain(rbuf, p->read_so_far);
1087 len -= p->read_so_far;
1088 wrap -= p->read_so_far;
1092 * Handle situations where we receive two command lines in
1093 * one read, which should not be possible (and implies the
1094 * earlier command should be canceled.
1096 * e.g. AT+CMD1\rAT+CMD2
1098 if (result != PARSER_RESULT_GARBAGE) {
1099 ring_buffer_drain(rbuf, len);
1104 p->in_read_handler = FALSE;
1110 static gboolean can_write_data(gpointer data)
1112 GAtServer *server = data;
1113 gsize bytes_written;
1115 struct ring_buffer *write_buf;
1117 #ifdef WRITE_SCHEDULER_DEBUG
1121 if (!server->write_queue)
1124 /* Write data out from the head of the queue */
1125 write_buf = g_queue_peek_head(server->write_queue);
1127 buf = ring_buffer_read_ptr(write_buf, 0);
1129 towrite = ring_buffer_len_no_wrap(write_buf);
1131 #ifdef WRITE_SCHEDULER_DEBUG
1138 bytes_written = g_at_io_write(server->io,
1140 #ifdef WRITE_SCHEDULER_DEBUG
1147 if (bytes_written == 0)
1150 ring_buffer_drain(write_buf, bytes_written);
1152 /* All data in current buffer is written, free it
1153 * unless it's the last buffer in the queue.
1155 if ((ring_buffer_len(write_buf) == 0) &&
1156 (g_queue_get_length(server->write_queue) > 1)) {
1157 write_buf = g_queue_pop_head(server->write_queue);
1158 ring_buffer_free(write_buf);
1159 write_buf = g_queue_peek_head(server->write_queue);
1162 if (ring_buffer_len(write_buf) > 0)
1168 static void write_queue_free(GQueue *write_queue)
1170 struct ring_buffer *write_buf;
1172 while ((write_buf = g_queue_pop_head(write_queue)))
1173 ring_buffer_free(write_buf);
1175 g_queue_free(write_queue);
1178 static void g_at_server_cleanup(GAtServer *server)
1180 /* Cleanup pending data to write */
1181 write_queue_free(server->write_queue);
1183 g_hash_table_destroy(server->command_list);
1184 server->command_list = NULL;
1186 g_free(server->last_line);
1188 g_at_io_unref(server->io);
1192 static void io_disconnect(gpointer user_data)
1194 GAtServer *server = user_data;
1196 g_at_server_cleanup(server);
1198 if (server->user_disconnect)
1199 server->user_disconnect(server->user_disconnect_data);
1202 static void server_wakeup_writer(GAtServer *server)
1204 g_at_io_set_write_handler(server->io, can_write_data, server);
1207 static void at_notify_node_destroy(gpointer data)
1209 struct at_command *node = data;
1211 if (node->destroy_notify)
1212 node->destroy_notify(node->user_data);
1217 static void basic_command_register(GAtServer *server)
1219 g_at_server_register(server, "S0", at_s0_cb, NULL, NULL);
1220 g_at_server_register(server, "S3", at_s3_cb, NULL, NULL);
1221 g_at_server_register(server, "S4", at_s4_cb, NULL, NULL);
1222 g_at_server_register(server, "S5", at_s5_cb, NULL, NULL);
1223 g_at_server_register(server, "E", at_e_cb, NULL, NULL);
1224 g_at_server_register(server, "Q", at_q_cb, NULL, NULL);
1225 g_at_server_register(server, "V", at_v_cb, NULL, NULL);
1226 g_at_server_register(server, "X", at_x_cb, NULL, NULL);
1227 g_at_server_register(server, "S6", at_s6_cb, NULL, NULL);
1228 g_at_server_register(server, "S7", at_s7_cb, NULL, NULL);
1229 g_at_server_register(server, "S8", at_s8_cb, NULL, NULL);
1230 g_at_server_register(server, "S10", at_s10_cb, NULL, NULL);
1231 g_at_server_register(server, "&C", at_c109_cb, NULL, NULL);
1232 g_at_server_register(server, "&D", at_c108_cb, NULL, NULL);
1233 g_at_server_register(server, "Z", at_z_cb, NULL, NULL);
1234 g_at_server_register(server, "&F", at_f_cb, NULL, NULL);
1235 g_at_server_register(server, "L", at_l_cb, NULL, NULL);
1236 g_at_server_register(server, "M", at_m_cb, NULL, NULL);
1237 g_at_server_register(server, "T", at_t_cb, NULL, NULL);
1238 g_at_server_register(server, "P", at_p_cb, NULL, NULL);
1241 GAtServer *g_at_server_new(GIOChannel *io)
1248 server = g_try_new0(GAtServer, 1);
1252 server->ref_count = 1;
1253 v250_settings_create(&server->v250);
1254 server->io = g_at_io_new(io);
1258 g_at_io_set_disconnect_function(server->io, io_disconnect, server);
1260 server->command_list = g_hash_table_new_full(g_str_hash, g_str_equal,
1262 at_notify_node_destroy);
1264 server->write_queue = g_queue_new();
1265 if (!server->write_queue)
1268 if (allocate_next(server) == NULL)
1271 server->max_read_attempts = 3;
1273 g_at_io_set_read_handler(server->io, new_bytes, server);
1275 basic_command_register(server);
1280 g_at_io_unref(server->io);
1282 if (server->command_list)
1283 g_hash_table_destroy(server->command_list);
1285 if (server->write_queue)
1286 write_queue_free(server->write_queue);
1294 GIOChannel *g_at_server_get_channel(GAtServer *server)
1296 if (server == NULL || server->io == NULL)
1299 return g_at_io_get_channel(server->io);
1302 GAtIO *g_at_server_get_io(GAtServer *server)
1310 GAtServer *g_at_server_ref(GAtServer *server)
1315 g_atomic_int_inc(&server->ref_count);
1320 void g_at_server_suspend(GAtServer *server)
1325 g_at_io_set_write_handler(server->io, NULL, NULL);
1326 g_at_io_set_read_handler(server->io, NULL, NULL);
1328 g_at_io_set_debug(server->io, NULL, NULL);
1331 void g_at_server_resume(GAtServer *server)
1336 if (g_at_io_get_channel(server->io) == NULL) {
1337 io_disconnect(server);
1341 g_at_io_set_disconnect_function(server->io, io_disconnect, server);
1343 g_at_io_set_debug(server->io, server->debugf, server->debug_data);
1344 g_at_io_set_read_handler(server->io, new_bytes, server);
1346 if (g_queue_get_length(server->write_queue) > 0)
1347 server_wakeup_writer(server);
1350 void g_at_server_unref(GAtServer *server)
1357 is_zero = g_atomic_int_dec_and_test(&server->ref_count);
1359 if (is_zero == FALSE)
1363 g_at_server_suspend(server);
1364 g_at_server_cleanup(server);
1367 g_at_server_shutdown(server);
1369 /* glib delays the destruction of the watcher until it exits, this
1370 * means we can't free the data just yet, even though we've been
1371 * destroyed already. We have to wait until the read_watcher
1372 * destroy function gets called
1374 if (server->in_read_handler)
1375 server->destroyed = TRUE;
1380 gboolean g_at_server_shutdown(GAtServer *server)
1385 /* Don't trigger user disconnect on shutdown */
1386 server->user_disconnect = NULL;
1387 server->user_disconnect_data = NULL;
1392 gboolean g_at_server_set_echo(GAtServer *server, gboolean echo)
1397 server->v250.echo = echo;
1402 gboolean g_at_server_set_disconnect_function(GAtServer *server,
1403 GAtDisconnectFunc disconnect,
1409 server->user_disconnect = disconnect;
1410 server->user_disconnect_data = user_data;
1415 gboolean g_at_server_set_debug(GAtServer *server, GAtDebugFunc func,
1421 server->debugf = func;
1422 server->debug_data = user_data;
1424 g_at_io_set_debug(server->io, server->debugf, server->debug_data);
1429 gboolean g_at_server_register(GAtServer *server, const char *prefix,
1430 GAtServerNotifyFunc notify,
1432 GDestroyNotify destroy_notify)
1434 struct at_command *node;
1436 if (server == NULL || server->command_list == NULL)
1442 if (prefix == NULL || strlen(prefix) == 0)
1445 node = g_try_new0(struct at_command, 1);
1449 node->notify = notify;
1450 node->user_data = user_data;
1451 node->destroy_notify = destroy_notify;
1453 g_hash_table_replace(server->command_list, g_strdup(prefix), node);
1458 gboolean g_at_server_unregister(GAtServer *server, const char *prefix)
1460 struct at_command *node;
1462 if (server == NULL || server->command_list == NULL)
1465 if (prefix == NULL || strlen(prefix) == 0)
1468 node = g_hash_table_lookup(server->command_list, prefix);
1472 g_hash_table_remove(server->command_list, prefix);
1477 gboolean g_at_server_set_finish_callback(GAtServer *server,
1478 GAtServerFinishFunc finishf,
1484 server->finishf = finishf;
1485 server->finish_data = user_data;
1490 gboolean g_at_server_command_pending(GAtServer *server)
1495 return server->final_async;