diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2010-03-07 15:04:13 -0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-03-07 15:04:13 -0800 |
commit | 282542067c3a97d9b75468d6f4d401e09a2fcd50 (patch) | |
tree | 6e79eeadfb7c69d73592df57b44d3e05abb828b0 /gatchat | |
parent | a474ef1be8b76167b9d0ef8a9eb6fe24cc5eacc5 (diff) | |
download | connman-282542067c3a97d9b75468d6f4d401e09a2fcd50.tar.gz connman-282542067c3a97d9b75468d6f4d401e09a2fcd50.tar.bz2 connman-282542067c3a97d9b75468d6f4d401e09a2fcd50.zip |
Remove internal GAtChat library
Diffstat (limited to 'gatchat')
-rw-r--r-- | gatchat/gat.h | 36 | ||||
-rw-r--r-- | gatchat/gatchat.c | 1333 | ||||
-rw-r--r-- | gatchat/gatchat.h | 141 | ||||
-rw-r--r-- | gatchat/gatresult.c | 493 | ||||
-rw-r--r-- | gatchat/gatresult.h | 75 | ||||
-rw-r--r-- | gatchat/gatsyntax.c | 348 | ||||
-rw-r--r-- | gatchat/gatsyntax.h | 87 | ||||
-rw-r--r-- | gatchat/gattty.c | 262 | ||||
-rw-r--r-- | gatchat/gattty.h | 50 | ||||
-rw-r--r-- | gatchat/gatutil.c | 129 | ||||
-rw-r--r-- | gatchat/gatutil.h | 40 | ||||
-rw-r--r-- | gatchat/ringbuffer.c | 199 | ||||
-rw-r--r-- | gatchat/ringbuffer.h | 124 |
13 files changed, 0 insertions, 3317 deletions
diff --git a/gatchat/gat.h b/gatchat/gat.h deleted file mode 100644 index 6696e7d4..00000000 --- a/gatchat/gat.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GAT_H -#define __GAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*GAtDisconnectFunc)(gpointer user_data); -typedef void (*GAtDebugFunc)(const char *str, gpointer user_data); - -#ifdef __cplusplus -} -#endif - -#endif /* __GAT_H */ diff --git a/gatchat/gatchat.c b/gatchat/gatchat.c deleted file mode 100644 index 5dbd2832..00000000 --- a/gatchat/gatchat.c +++ /dev/null @@ -1,1333 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <assert.h> -#include <ctype.h> -#include <errno.h> - -#include <glib.h> - -#include "ringbuffer.h" -#include "gatchat.h" - -/* #define WRITE_SCHEDULER_DEBUG 1 */ - -static const char *none_prefix[] = { NULL }; - -static void g_at_chat_wakeup_writer(GAtChat *chat); - -struct at_command { - char *cmd; - char **prefixes; - gboolean expect_pdu; - guint id; - GAtResultFunc callback; - GAtNotifyFunc listing; - gpointer user_data; - GDestroyNotify notify; -}; - -struct at_notify_node { - guint id; - GAtNotifyFunc callback; - gpointer user_data; - GDestroyNotify notify; -}; - -struct at_notify { - GSList *nodes; - gboolean pdu; -}; - -struct _GAtChat { - gint ref_count; /* Ref count */ - guint next_cmd_id; /* Next command id */ - guint next_notify_id; /* Next notify id */ - guint read_watch; /* GSource read id, 0 if none */ - guint write_watch; /* GSource write id, 0 if none */ - gboolean use_write_watch; /* watch usage for non blocking */ - GIOChannel *channel; /* channel */ - GQueue *command_queue; /* Command queue */ - guint cmd_bytes_written; /* bytes written from cmd */ - GHashTable *notify_list; /* List of notification reg */ - GAtDisconnectFunc user_disconnect; /* user disconnect func */ - gpointer user_disconnect_data; /* user disconnect data */ - struct ring_buffer *buf; /* Current read buffer */ - guint read_so_far; /* Number of bytes processed */ - guint max_read_attempts; /* max number of read attempts */ - GAtDebugFunc debugf; /* debugging output function */ - gpointer debug_data; /* Data to pass to debug func */ - char *pdu_notify; /* Unsolicited Resp w/ PDU */ - GSList *response_lines; /* char * lines of the response */ - char *wakeup; /* command sent to wakeup modem */ - gint timeout_source; - gdouble inactivity_time; /* Period of inactivity */ - guint wakeup_timeout; /* How long to wait for resp */ - GTimer *wakeup_timer; /* Keep track of elapsed time */ - GAtSyntax *syntax; - gboolean destroyed; /* Re-entrancy guard */ - GSList *terminator_list; /* Non-standard terminator */ -}; - -struct terminator_info { - char *terminator; - int len; - gboolean success; -}; - -static gint at_notify_node_compare_by_id(gconstpointer a, gconstpointer b) -{ - const struct at_notify_node *node = a; - guint id = GPOINTER_TO_UINT(b); - - if (node->id < id) - return -1; - - if (node->id > id) - return 1; - - return 0; -} - -static void at_notify_node_destroy(struct at_notify_node *node) -{ - if (node->notify) - node->notify(node->user_data); - - g_free(node); -} - -static void at_notify_destroy(struct at_notify *notify) -{ - g_slist_foreach(notify->nodes, (GFunc) at_notify_node_destroy, NULL); - g_free(notify); -} - -static gint at_command_compare_by_id(gconstpointer a, gconstpointer b) -{ - const struct at_command *command = a; - guint id = GPOINTER_TO_UINT(b); - - if (command->id < id) - return -1; - - if (command->id > id) - return 1; - - return 0; -} - -static struct at_command *at_command_create(const char *cmd, - const char **prefix_list, - gboolean expect_pdu, - GAtNotifyFunc listing, - GAtResultFunc func, - gpointer user_data, - GDestroyNotify notify, - gboolean wakeup) -{ - struct at_command *c; - gsize len; - char **prefixes = NULL; - - if (prefix_list) { - int num_prefixes = 0; - int i; - - while (prefix_list[num_prefixes]) - num_prefixes += 1; - - prefixes = g_new(char *, num_prefixes + 1); - - for (i = 0; i < num_prefixes; i++) - prefixes[i] = strdup(prefix_list[i]); - - prefixes[num_prefixes] = NULL; - } - - c = g_try_new0(struct at_command, 1); - - if (!c) - return 0; - - len = strlen(cmd); - c->cmd = g_try_new(char, len + 2); - - if (!c->cmd) { - g_free(c); - return 0; - } - - memcpy(c->cmd, cmd, len); - - /* If we have embedded '\r' then this is a command expecting a prompt - * from the modem. Embed Ctrl-Z at the very end automatically - */ - if (wakeup == FALSE) { - if (strchr(cmd, '\r')) - c->cmd[len] = 26; - else - c->cmd[len] = '\r'; - - len += 1; - } - - c->cmd[len] = '\0'; - - c->expect_pdu = expect_pdu; - c->prefixes = prefixes; - c->callback = func; - c->listing = listing; - c->user_data = user_data; - c->notify = notify; - - return c; -} - -static void at_command_destroy(struct at_command *cmd) -{ - if (cmd->notify) - cmd->notify(cmd->user_data); - - g_strfreev(cmd->prefixes); - g_free(cmd->cmd); - g_free(cmd); -} - -static void free_terminator(struct terminator_info *info) -{ - g_free(info->terminator); - info->terminator = NULL; - g_free(info); - info = NULL; -} - -static void g_at_chat_cleanup(GAtChat *chat) -{ - struct at_command *c; - - ring_buffer_free(chat->buf); - chat->buf = NULL; - - /* Cleanup pending commands */ - while ((c = g_queue_pop_head(chat->command_queue))) - at_command_destroy(c); - - g_queue_free(chat->command_queue); - chat->command_queue = NULL; - - /* Cleanup any response lines we have pending */ - g_slist_foreach(chat->response_lines, (GFunc)g_free, NULL); - g_slist_free(chat->response_lines); - chat->response_lines = NULL; - - /* Cleanup registered notifications */ - g_hash_table_destroy(chat->notify_list); - chat->notify_list = NULL; - - if (chat->pdu_notify) { - g_free(chat->pdu_notify); - chat->pdu_notify = NULL; - } - - if (chat->wakeup) { - g_free(chat->wakeup); - chat->wakeup = NULL; - } - - if (chat->wakeup_timer) { - g_timer_destroy(chat->wakeup_timer); - chat->wakeup_timer = 0; - } - - if (chat->timeout_source) { - g_source_remove(chat->timeout_source); - chat->timeout_source = 0; - } - - g_at_syntax_unref(chat->syntax); - chat->syntax = NULL; - - chat->channel = NULL; - - if (chat->terminator_list) { - g_slist_foreach(chat->terminator_list, - (GFunc)free_terminator, NULL); - g_slist_free(chat->terminator_list); - chat->terminator_list = NULL; - } -} - -static void read_watcher_destroy_notify(GAtChat *chat) -{ - g_at_chat_cleanup(chat); - chat->read_watch = 0; - - if (chat->user_disconnect) - chat->user_disconnect(chat->user_disconnect_data); - - if (chat->destroyed) - g_free(chat); -} - -static void write_watcher_destroy_notify(GAtChat *chat) -{ - chat->write_watch = 0; -} - -static void at_notify_call_callback(gpointer data, gpointer user_data) -{ - struct at_notify_node *node = data; - GAtResult *result = user_data; - - node->callback(result, node->user_data); -} - -static gboolean g_at_chat_match_notify(GAtChat *chat, char *line) -{ - GHashTableIter iter; - struct at_notify *notify; - char *prefix; - gpointer key, value; - gboolean ret = FALSE; - GAtResult result; - - g_hash_table_iter_init(&iter, chat->notify_list); - result.lines = 0; - result.final_or_pdu = 0; - - while (g_hash_table_iter_next(&iter, &key, &value)) { - prefix = key; - notify = value; - - if (!g_str_has_prefix(line, key)) - continue; - - if (notify->pdu) { - chat->pdu_notify = line; - - if (chat->syntax->set_hint) - chat->syntax->set_hint(chat->syntax, - G_AT_SYNTAX_EXPECT_PDU); - return TRUE; - } - - if (!result.lines) - result.lines = g_slist_prepend(NULL, line); - - g_slist_foreach(notify->nodes, at_notify_call_callback, - &result); - ret = TRUE; - } - - if (ret) { - g_slist_free(result.lines); - g_free(line); - } - - return ret; -} - -static void g_at_chat_finish_command(GAtChat *p, gboolean ok, - char *final) -{ - struct at_command *cmd = g_queue_pop_head(p->command_queue); - GSList *response_lines; - - /* Cannot happen, but lets be paranoid */ - if (!cmd) - return; - - p->cmd_bytes_written = 0; - - if (g_queue_peek_head(p->command_queue)) - g_at_chat_wakeup_writer(p); - - response_lines = p->response_lines; - p->response_lines = NULL; - - if (cmd->callback) { - GAtResult result; - - response_lines = g_slist_reverse(response_lines); - - result.final_or_pdu = final; - result.lines = response_lines; - - cmd->callback(ok, &result, cmd->user_data); - } - - g_slist_foreach(response_lines, (GFunc)g_free, NULL); - g_slist_free(response_lines); - - g_free(final); - at_command_destroy(cmd); -} - -static struct terminator_info terminator_table[] = { - { "OK", -1, TRUE }, - { "ERROR", -1, FALSE }, - { "NO DIALTONE", -1, FALSE }, - { "BUSY", -1, FALSE }, - { "NO CARRIER", -1, FALSE }, - { "CONNECT", -1, TRUE }, - { "NO ANSWER", -1, FALSE }, - { "+CMS ERROR:", 11, FALSE }, - { "+CME ERROR:", 11, FALSE }, - { "+EXT ERROR:", 11, FALSE } -}; - -void g_at_chat_add_terminator(GAtChat *chat, char *terminator, - int len, gboolean success) -{ - struct terminator_info *info = g_new0(struct terminator_info, 1); - info->terminator = g_strdup(terminator); - info->len = len; - info->success = success; - chat->terminator_list = g_slist_prepend(chat->terminator_list, info); -} - -static gboolean check_terminator(struct terminator_info *info, char *line) -{ - if (info->len == -1 && !strcmp(line, info->terminator)) - return TRUE; - - if (info->len > 0 && !strncmp(line, info->terminator, info->len)) - return TRUE; - - return FALSE; -} - -static gboolean g_at_chat_handle_command_response(GAtChat *p, - struct at_command *cmd, - char *line) -{ - int i; - int size = sizeof(terminator_table) / sizeof(struct terminator_info); - int hint; - GSList *l; - - for (i = 0; i < size; i++) { - struct terminator_info *info = &terminator_table[i]; - if (check_terminator(info, line)) { - g_at_chat_finish_command(p, info->success, line); - return TRUE; - } - } - - for (l = p->terminator_list; l; l = l->next) { - struct terminator_info *info = l->data; - if (check_terminator(info, line)) { - g_at_chat_finish_command(p, info->success, line); - return TRUE; - } - } - - if (cmd->prefixes) { - int i; - - for (i = 0; cmd->prefixes[i]; i++) - if (g_str_has_prefix(line, cmd->prefixes[i])) - goto out; - - return FALSE; - } - -out: - if (cmd->listing && cmd->expect_pdu) - hint = G_AT_SYNTAX_EXPECT_PDU; - else - hint = G_AT_SYNTAX_EXPECT_MULTILINE; - - if (p->syntax->set_hint) - p->syntax->set_hint(p->syntax, hint); - - if (cmd->listing && cmd->expect_pdu) { - p->pdu_notify = line; - return TRUE; - } - - if (cmd->listing) { - GAtResult result; - - result.lines = g_slist_prepend(NULL, line); - result.final_or_pdu = NULL; - - cmd->listing(&result, cmd->user_data); - - g_slist_free(result.lines); - g_free(line); - } else - p->response_lines = g_slist_prepend(p->response_lines, line); - - return TRUE; -} - -static void have_line(GAtChat *p, char *str) -{ - /* We're not going to copy terminal <CR><LF> */ - struct at_command *cmd; - - if (!str) - return; - - /* Check for echo, this should not happen, but lets be paranoid */ - if (!strncmp(str, "AT", 2) == TRUE) - goto done; - - cmd = g_queue_peek_head(p->command_queue); - - if (cmd && p->cmd_bytes_written > 0) { - char c = cmd->cmd[p->cmd_bytes_written - 1]; - - /* We check that we have submitted a terminator, in which case - * a command might have failed or completed successfully - * - * In the generic case, \r is at the end of the command, so we - * know the entire command has been submitted. In the case of - * commands like CMGS, every \r or Ctrl-Z might result in a - * final response from the modem, so we check this as well. - */ - if ((c == '\r' || c == 26) && - g_at_chat_handle_command_response(p, cmd, str)) - return; - } - - if (g_at_chat_match_notify(p, str) == TRUE) - return; - -done: - /* No matches & no commands active, ignore line */ - g_free(str); -} - -static void have_notify_pdu(GAtChat *p, char *pdu, GAtResult *result) -{ - GHashTableIter iter; - struct at_notify *notify; - char *prefix; - gpointer key, value; - - g_hash_table_iter_init(&iter, p->notify_list); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - prefix = key; - notify = value; - - if (!g_str_has_prefix(p->pdu_notify, prefix)) - continue; - - if (!notify->pdu) - continue; - - g_slist_foreach(notify->nodes, at_notify_call_callback, result); - } -} - -static void have_pdu(GAtChat *p, char *pdu) -{ - struct at_command *cmd; - GAtResult result; - gboolean listing_pdu = FALSE; - - if (!pdu) - goto error; - - result.lines = g_slist_prepend(NULL, p->pdu_notify); - result.final_or_pdu = pdu; - - cmd = g_queue_peek_head(p->command_queue); - - if (cmd && cmd->expect_pdu && p->cmd_bytes_written > 0) { - char c = cmd->cmd[p->cmd_bytes_written - 1]; - - if (c == '\r') - listing_pdu = TRUE; - } - - if (listing_pdu) { - cmd->listing(&result, cmd->user_data); - - if (p->syntax->set_hint) - p->syntax->set_hint(p->syntax, - G_AT_SYNTAX_EXPECT_MULTILINE); - } else - have_notify_pdu(p, pdu, &result); - - g_slist_free(result.lines); - -error: - g_free(p->pdu_notify); - p->pdu_notify = NULL; - - if (pdu) - g_free(pdu); -} - -static char *extract_line(GAtChat *p) -{ - unsigned int wrap = ring_buffer_len_no_wrap(p->buf); - unsigned int pos = 0; - unsigned char *buf = ring_buffer_read_ptr(p->buf, pos); - int strip_front = 0; - int line_length = 0; - char *line; - - while (pos < p->read_so_far) { - if (*buf == '\r' || *buf == '\n') - if (!line_length) - strip_front += 1; - else - break; - else - line_length += 1; - - buf += 1; - pos += 1; - - if (pos == wrap) - buf = ring_buffer_read_ptr(p->buf, pos); - } - - line = g_try_new(char, line_length + 1); - - if (!line) { - ring_buffer_drain(p->buf, p->read_so_far); - return NULL; - } - - ring_buffer_drain(p->buf, strip_front); - ring_buffer_read(p->buf, line, line_length); - ring_buffer_drain(p->buf, p->read_so_far - strip_front - line_length); - - line[line_length] = '\0'; - - return line; -} - -static void new_bytes(GAtChat *p) -{ - unsigned int len = ring_buffer_len(p->buf); - unsigned int wrap = ring_buffer_len_no_wrap(p->buf); - unsigned char *buf = ring_buffer_read_ptr(p->buf, p->read_so_far); - - GAtSyntaxResult result; - - g_at_chat_ref(p); - - while (p->channel && (p->read_so_far < len)) { - gsize rbytes = MIN(len - p->read_so_far, wrap - p->read_so_far); - result = p->syntax->feed(p->syntax, (char *)buf, &rbytes); - - buf += rbytes; - p->read_so_far += rbytes; - - if (p->read_so_far == wrap) { - buf = ring_buffer_read_ptr(p->buf, p->read_so_far); - wrap = len; - } - - if (result == G_AT_SYNTAX_RESULT_UNSURE) - continue; - - switch (result) { - case G_AT_SYNTAX_RESULT_LINE: - case G_AT_SYNTAX_RESULT_MULTILINE: - have_line(p, extract_line(p)); - break; - - case G_AT_SYNTAX_RESULT_PDU: - have_pdu(p, extract_line(p)); - break; - - case G_AT_SYNTAX_RESULT_PROMPT: - g_at_chat_wakeup_writer(p); - ring_buffer_drain(p->buf, p->read_so_far); - break; - - default: - ring_buffer_drain(p->buf, p->read_so_far); - break; - } - - len -= p->read_so_far; - wrap -= p->read_so_far; - p->read_so_far = 0; - } - - /* We're overflowing the buffer, shutdown the socket */ - if (p->buf && ring_buffer_avail(p->buf) == 0) - g_source_remove(p->read_watch); - - g_at_chat_unref(p); -} - -static gboolean received_data(GIOChannel *channel, GIOCondition cond, - gpointer data) -{ - unsigned char *buf; - GAtChat *chat = data; - GIOError err; - gsize rbytes; - gsize toread; - gsize total_read = 0; - guint read_count = 0; - - if (cond & G_IO_NVAL) - return FALSE; - - /* Regardless of condition, try to read all the data available */ - do { - toread = ring_buffer_avail_no_wrap(chat->buf); - - if (toread == 0) - break; - - rbytes = 0; - buf = ring_buffer_write_ptr(chat->buf); - - err = g_io_channel_read(channel, (char *) buf, toread, &rbytes); - g_at_util_debug_chat(TRUE, (char *)buf, rbytes, - chat->debugf, chat->debug_data); - - read_count++; - - total_read += rbytes; - - if (rbytes > 0) - ring_buffer_write_advance(chat->buf, rbytes); - - } while (err == G_IO_ERROR_NONE && rbytes > 0 && - read_count < chat->max_read_attempts); - - if (total_read > 0) - new_bytes(chat); - - if (cond & (G_IO_HUP | G_IO_ERR)) - return FALSE; - - if (read_count > 0 && rbytes == 0 && err != G_IO_ERROR_AGAIN) - return FALSE; - - return TRUE; -} - -static void wakeup_cb(gboolean ok, GAtResult *result, gpointer user_data) -{ - GAtChat *chat = user_data; - - if (ok == FALSE) - return; - - if (chat->debugf) - chat->debugf("Finally woke up the modem\n", chat->debug_data); - - g_source_remove(chat->timeout_source); - chat->timeout_source = 0; -} - -static gboolean wakeup_no_response(gpointer user) -{ - GAtChat *chat = user; - struct at_command *cmd = g_queue_peek_head(chat->command_queue); - - if (chat->debugf) - chat->debugf("Wakeup got no response\n", chat->debug_data); - - g_at_chat_finish_command(chat, FALSE, NULL); - cmd = at_command_create(chat->wakeup, none_prefix, FALSE, - NULL, wakeup_cb, chat, NULL, TRUE); - - if (!cmd) { - chat->timeout_source = 0; - return FALSE; - } - - g_queue_push_head(chat->command_queue, cmd); - - return TRUE; -} - -static gboolean can_write_data(GIOChannel *channel, GIOCondition cond, - gpointer data) -{ - GAtChat *chat = data; - struct at_command *cmd; - GIOError err; - gsize bytes_written; - gsize towrite; - gsize len; - char *cr; - gboolean wakeup_first = FALSE; -#ifdef WRITE_SCHEDULER_DEBUG - int limiter; -#endif - - if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) - return FALSE; - - /* Grab the first command off the queue and write as - * much of it as we can - */ - cmd = g_queue_peek_head(chat->command_queue); - - /* For some reason command queue is empty, cancel write watcher */ - if (cmd == NULL) - return FALSE; - - len = strlen(cmd->cmd); - - /* For some reason write watcher fired, but we've already - * written the entire command out to the io channel, - * cancel write watcher - */ - if (chat->cmd_bytes_written >= len) - return FALSE; - - if (chat->wakeup) { - if (!chat->wakeup_timer) { - wakeup_first = TRUE; - chat->wakeup_timer = g_timer_new(); - - } else if (g_timer_elapsed(chat->wakeup_timer, NULL) > - chat->inactivity_time) - wakeup_first = TRUE; - } - - if (chat->cmd_bytes_written == 0 && wakeup_first == TRUE) { - cmd = at_command_create(chat->wakeup, none_prefix, FALSE, - NULL, wakeup_cb, chat, NULL, TRUE); - - if (!cmd) - return FALSE; - - g_queue_push_head(chat->command_queue, cmd); - - len = strlen(chat->wakeup); - - chat->timeout_source = g_timeout_add(chat->wakeup_timeout, - wakeup_no_response, chat); - } - - towrite = len - chat->cmd_bytes_written; - - cr = strchr(cmd->cmd + chat->cmd_bytes_written, '\r'); - - if (cr) - towrite = cr - (cmd->cmd + chat->cmd_bytes_written) + 1; - -#ifdef WRITE_SCHEDULER_DEBUG - limiter = towrite; - - if (limiter > 5) - limiter = 5; -#endif - - err = g_io_channel_write(chat->channel, - cmd->cmd + chat->cmd_bytes_written, -#ifdef WRITE_SCHEDULER_DEBUG - limiter, -#else - towrite, -#endif - &bytes_written); - - if (err != G_IO_ERROR_NONE) { - g_source_remove(chat->read_watch); - return FALSE; - } - - g_at_util_debug_chat(FALSE, cmd->cmd + chat->cmd_bytes_written, - bytes_written, chat->debugf, chat->debug_data); - chat->cmd_bytes_written += bytes_written; - - if (bytes_written < towrite) - return TRUE; - - /* Full command submitted, update timer */ - if (chat->wakeup_timer) - g_timer_start(chat->wakeup_timer); - - return FALSE; -} - -static void g_at_chat_wakeup_writer(GAtChat *chat) -{ - if (chat->write_watch != 0) - return; - - if (chat->use_write_watch == TRUE) { - chat->write_watch = g_io_add_watch_full(chat->channel, - G_PRIORITY_DEFAULT, - G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - can_write_data, chat, - (GDestroyNotify)write_watcher_destroy_notify); - } else { - while (can_write_data(chat->channel, G_IO_OUT, chat) == TRUE); - write_watcher_destroy_notify(chat); - } -} - -static GAtChat *create_chat(GIOChannel *channel, GIOFlags flags, - GAtSyntax *syntax) -{ - GAtChat *chat; - - if (!channel) - return NULL; - - if (!syntax) - return NULL; - - chat = g_try_new0(GAtChat, 1); - - if (!chat) - return chat; - - chat->ref_count = 1; - chat->next_cmd_id = 1; - chat->next_notify_id = 1; - chat->debugf = NULL; - - if (flags & G_IO_FLAG_NONBLOCK) { - chat->use_write_watch = TRUE; - chat->max_read_attempts = 3; - } else { - chat->use_write_watch = FALSE; - chat->max_read_attempts = 1; - } - - chat->buf = ring_buffer_new(4096); - - if (!chat->buf) - goto error; - - chat->command_queue = g_queue_new(); - - if (!chat->command_queue) - goto error; - - chat->notify_list = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, (GDestroyNotify)at_notify_destroy); - - if (!g_at_util_setup_io(channel, flags)) - goto error; - - chat->channel = channel; - chat->read_watch = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - received_data, chat, - (GDestroyNotify)read_watcher_destroy_notify); - - chat->syntax = g_at_syntax_ref(syntax); - - return chat; - -error: - if (chat->buf) - ring_buffer_free(chat->buf); - - if (chat->command_queue) - g_queue_free(chat->command_queue); - - if (chat->notify_list) - g_hash_table_destroy(chat->notify_list); - - g_free(chat); - return NULL; -} - -GAtChat *g_at_chat_new(GIOChannel *channel, GAtSyntax *syntax) -{ - return create_chat(channel, G_IO_FLAG_NONBLOCK, syntax); -} - -GAtChat *g_at_chat_new_blocking(GIOChannel *channel, GAtSyntax *syntax) -{ - return create_chat(channel, 0, syntax); -} - -GIOChannel *g_at_chat_get_channel(GAtChat *chat) -{ - if (chat == NULL) - return NULL; - - return chat->channel; -} - -GAtChat *g_at_chat_ref(GAtChat *chat) -{ - if (chat == NULL) - return NULL; - - g_atomic_int_inc(&chat->ref_count); - - return chat; -} - -void g_at_chat_unref(GAtChat *chat) -{ - gboolean is_zero; - - if (chat == NULL) - return; - - is_zero = g_atomic_int_dec_and_test(&chat->ref_count); - - if (is_zero == FALSE) - return; - - g_at_chat_shutdown(chat); - - /* glib delays the destruction of the watcher until it exits, this - * means we can't free the data just yet, even though we've been - * destroyed already. We have to wait until the read_watcher - * destroy function gets called - */ - if (chat->read_watch != 0) - chat->destroyed = TRUE; - else - g_free(chat); -} - -gboolean g_at_chat_shutdown(GAtChat *chat) -{ - if (chat->channel == NULL) - return FALSE; - - /* Don't trigger user disconnect on shutdown */ - chat->user_disconnect = NULL; - chat->user_disconnect_data = NULL; - - if (chat->read_watch) - g_source_remove(chat->read_watch); - - if (chat->write_watch) - g_source_remove(chat->write_watch); - - return TRUE; -} - -gboolean g_at_chat_set_syntax(GAtChat *chat, GAtSyntax *syntax) -{ - if (chat == NULL) - return FALSE; - - g_at_syntax_unref(chat->syntax); - - chat->syntax = g_at_syntax_ref(syntax); - - return TRUE; -} - -gboolean g_at_chat_set_disconnect_function(GAtChat *chat, - GAtDisconnectFunc disconnect, gpointer user_data) -{ - if (chat == NULL) - return FALSE; - - chat->user_disconnect = disconnect; - chat->user_disconnect_data = user_data; - - return TRUE; -} - -gboolean g_at_chat_set_debug(GAtChat *chat, GAtDebugFunc func, gpointer user) -{ - if (chat == NULL) - return FALSE; - - chat->debugf = func; - chat->debug_data = user; - - return TRUE; -} - -static guint send_common(GAtChat *chat, const char *cmd, - const char **prefix_list, - gboolean expect_pdu, - GAtNotifyFunc listing, GAtResultFunc func, - gpointer user_data, GDestroyNotify notify) -{ - struct at_command *c; - - if (chat == NULL || chat->command_queue == NULL) - return 0; - - c = at_command_create(cmd, prefix_list, expect_pdu, listing, func, - user_data, notify, FALSE); - - if (!c) - return 0; - - c->id = chat->next_cmd_id++; - - g_queue_push_tail(chat->command_queue, c); - - if (g_queue_get_length(chat->command_queue) == 1) - g_at_chat_wakeup_writer(chat); - - return c->id; -} - -guint g_at_chat_send(GAtChat *chat, const char *cmd, - const char **prefix_list, GAtResultFunc func, - gpointer user_data, GDestroyNotify notify) -{ - return send_common(chat, cmd, prefix_list, FALSE, NULL, func, - user_data, notify); -} - -guint g_at_chat_send_listing(GAtChat *chat, const char *cmd, - const char **prefix_list, - GAtNotifyFunc listing, GAtResultFunc func, - gpointer user_data, GDestroyNotify notify) -{ - if (listing == NULL) - return 0; - - return send_common(chat, cmd, prefix_list, FALSE, listing, func, - user_data, notify); -} - -guint g_at_chat_send_pdu_listing(GAtChat *chat, const char *cmd, - const char **prefix_list, - GAtNotifyFunc listing, GAtResultFunc func, - gpointer user_data, GDestroyNotify notify) -{ - if (listing == NULL) - return 0; - - return send_common(chat, cmd, prefix_list, TRUE, listing, func, - user_data, notify); -} - -gboolean g_at_chat_cancel(GAtChat *chat, guint id) -{ - GList *l; - - if (chat == NULL || chat->command_queue == NULL) - return FALSE; - - /* We use id 0 for wakeup commands */ - if (id == 0) - return FALSE; - - l = g_queue_find_custom(chat->command_queue, GUINT_TO_POINTER(id), - at_command_compare_by_id); - - if (!l) - return FALSE; - - if (l == g_queue_peek_head(chat->command_queue) && - chat->cmd_bytes_written > 0) { - struct at_command *c = l->data; - - /* We can't actually remove it since it is most likely - * already in progress, just null out the callback - * so it won't be called - */ - c->callback = NULL; - } else { - at_command_destroy(l->data); - g_queue_remove(chat->command_queue, l->data); - } - - return TRUE; -} - -gboolean g_at_chat_cancel_all(GAtChat *chat) -{ - int n = 0; - struct at_command *c; - - if (chat == NULL || chat->command_queue == NULL) - return FALSE; - - while ((c = g_queue_peek_nth(chat->command_queue, n)) != NULL) { - if (c->id == 0) { - n += 1; - continue; - } - - if (n == 0 && chat->cmd_bytes_written > 0) { - c->callback = NULL; - n += 1; - continue; - } - - at_command_destroy(c); - g_queue_remove(chat->command_queue, c); - } - - return TRUE; -} - -static struct at_notify *at_notify_create(GAtChat *chat, const char *prefix, - gboolean pdu) -{ - struct at_notify *notify; - char *key; - - key = g_strdup(prefix); - - if (!key) - return 0; - - notify = g_try_new0(struct at_notify, 1); - - if (!notify) { - g_free(key); - return 0; - } - - notify->pdu = pdu; - - g_hash_table_insert(chat->notify_list, key, notify); - - return notify; -} - -guint g_at_chat_register(GAtChat *chat, const char *prefix, - GAtNotifyFunc func, gboolean expect_pdu, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - struct at_notify *notify; - struct at_notify_node *node; - - if (chat == NULL || chat->notify_list == NULL) - return 0; - - if (func == NULL) - return 0; - - if (prefix == NULL || strlen(prefix) == 0) - return 0; - - notify = g_hash_table_lookup(chat->notify_list, prefix); - - if (!notify) - notify = at_notify_create(chat, prefix, expect_pdu); - - if (!notify || notify->pdu != expect_pdu) - return 0; - - node = g_try_new0(struct at_notify_node, 1); - - if (!node) - return 0; - - node->id = chat->next_notify_id++; - node->callback = func; - node->user_data = user_data; - node->notify = destroy_notify; - - notify->nodes = g_slist_prepend(notify->nodes, node); - - return node->id; -} - -gboolean g_at_chat_unregister(GAtChat *chat, guint id) -{ - GHashTableIter iter; - struct at_notify *notify; - char *prefix; - gpointer key, value; - GSList *l; - - if (chat == NULL || chat->notify_list == NULL) - return FALSE; - - g_hash_table_iter_init(&iter, chat->notify_list); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - prefix = key; - notify = value; - - l = g_slist_find_custom(notify->nodes, GUINT_TO_POINTER(id), - at_notify_node_compare_by_id); - - if (!l) - continue; - - at_notify_node_destroy(l->data); - notify->nodes = g_slist_remove(notify->nodes, l->data); - - if (notify->nodes == NULL) - g_hash_table_iter_remove(&iter); - - return TRUE; - } - - return TRUE; -} - -gboolean g_at_chat_unregister_all(GAtChat *chat) -{ - GHashTableIter iter; - struct at_notify *notify; - char *prefix; - gpointer key, value; - GSList *l; - - if (chat == NULL || chat->notify_list == NULL) - return FALSE; - - g_hash_table_iter_init(&iter, chat->notify_list); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - prefix = key; - notify = value; - - for (l = notify->nodes; l; l = l->next) - at_notify_node_destroy(l->data); - - g_slist_free(notify->nodes); - notify->nodes = NULL; - g_hash_table_iter_remove(&iter); - } - - return TRUE; -} - -gboolean g_at_chat_set_wakeup_command(GAtChat *chat, const char *cmd, - unsigned int timeout, unsigned int msec) -{ - if (chat == NULL) - return FALSE; - - if (chat->wakeup) - g_free(chat->wakeup); - - chat->wakeup = g_strdup(cmd); - chat->inactivity_time = (gdouble)msec / 1000; - chat->wakeup_timeout = timeout; - - return TRUE; -} diff --git a/gatchat/gatchat.h b/gatchat/gatchat.h deleted file mode 100644 index 6f4f0b95..00000000 --- a/gatchat/gatchat.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GATCHAT_H -#define __GATCHAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gatresult.h" -#include "gatsyntax.h" -#include "gatutil.h" - -struct _GAtChat; - -typedef struct _GAtChat GAtChat; - -typedef void (*GAtResultFunc)(gboolean success, GAtResult *result, - gpointer user_data); -typedef void (*GAtNotifyFunc)(GAtResult *result, gpointer user_data); - -GAtChat *g_at_chat_new(GIOChannel *channel, GAtSyntax *syntax); -GAtChat *g_at_chat_new_blocking(GIOChannel *channel, GAtSyntax *syntax); - -GIOChannel *g_at_chat_get_channel(GAtChat *chat); - -GAtChat *g_at_chat_ref(GAtChat *chat); -void g_at_chat_unref(GAtChat *chat); - -gboolean g_at_chat_shutdown(GAtChat *chat); - -gboolean g_at_chat_set_syntax(GAtChat *chat, GAtSyntax *syntax); - -gboolean g_at_chat_set_disconnect_function(GAtChat *chat, - GAtDisconnectFunc disconnect, gpointer user_data); - -/*! - * If the function is not NULL, then on every read/write from the GIOChannel - * provided to GAtChat the logging function will be called with the - * input/output string and user data - */ -gboolean g_at_chat_set_debug(GAtChat *chat, GAtDebugFunc func, gpointer user); - -/*! - * Queue an AT command for execution. The command contents are given - * in cmd. Once the command executes, the callback function given by - * func is called with user provided data in user_data. - * - * Returns an id of the queued command which can be canceled using - * g_at_chat_cancel. If an error occurred, an id of 0 is returned. - * - * This function can be used in three ways: - * - Send a simple command such as g_at_chat_send(p, "AT+CGMI?", ... - * - * - Send a compound command: g_at_chat_send(p, "AT+CMD1;+CMD2", ... - * - * - Send a command requiring a prompt. The command up to '\r' is sent - * after which time a '> ' prompt is expected from the modem. Further - * contents of the command are sent until a '\r' or end of string is - * encountered. If end of string is encountered, the Ctrl-Z character - * is sent automatically. There is no need to include the Ctrl-Z - * by the caller. - * - * The valid_resp field can be used to send an array of strings which will - * be accepted as a valid response for this command. This is treated as a - * simple prefix match. If a response line comes in from the modem and it - * does not match any of the prefixes in valid_resp, it is treated as an - * unsolicited notification. If valid_resp is NULL, then all response - * lines after command submission and final response line are treated as - * part of the command response. This can be used to get around broken - * modems which send unsolicited notifications during command processing. - */ -guint g_at_chat_send(GAtChat *chat, const char *cmd, - const char **valid_resp, GAtResultFunc func, - gpointer user_data, GDestroyNotify notify); - -/*! - * Same as the above command, except that the caller wishes to receive the - * intermediate responses immediately through the GAtNotifyFunc callback. - * The final response will still be sent to GAtResultFunc callback. The - * final GAtResult will not contain any lines from the intermediate responses. - * This is useful for listing commands such as CPBR. - */ -guint g_at_chat_send_listing(GAtChat *chat, const char *cmd, - const char **valid_resp, - GAtNotifyFunc listing, GAtResultFunc func, - gpointer user_data, GDestroyNotify notify); - -/*! - * Same as g_at_chat_send_listing except every response line in valid_resp - * is expected to be followed by a PDU. The listing function will be called - * with the intermediate response and the following PDU line. - * - * This is useful for PDU listing commands like the +CMGL - */ -guint g_at_chat_send_pdu_listing(GAtChat *chat, const char *cmd, - const char **valid_resp, - GAtNotifyFunc listing, GAtResultFunc func, - gpointer user_data, GDestroyNotify notify); - -gboolean g_at_chat_cancel(GAtChat *chat, guint id); -gboolean g_at_chat_cancel_all(GAtChat *chat); - -guint g_at_chat_register(GAtChat *chat, const char *prefix, - GAtNotifyFunc func, gboolean expect_pdu, - gpointer user_data, GDestroyNotify notify); - -gboolean g_at_chat_unregister(GAtChat *chat, guint id); -gboolean g_at_chat_unregister_all(GAtChat *chat); - -gboolean g_at_chat_set_wakeup_command(GAtChat *chat, const char *cmd, - guint timeout, guint msec); - -void g_at_chat_add_terminator(GAtChat *chat, char *terminator, - int len, gboolean success); - - -#ifdef __cplusplus -} -#endif - -#endif /* __GATCHAT_H */ diff --git a/gatchat/gatresult.c b/gatchat/gatresult.c deleted file mode 100644 index cd7ec716..00000000 --- a/gatchat/gatresult.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <stdio.h> - -#include <glib.h> - -#include "gatresult.h" - -void g_at_result_iter_init(GAtResultIter *iter, GAtResult *result) -{ - iter->result = result; - iter->pre.next = result->lines; - iter->pre.data = NULL; - iter->l = &iter->pre; - iter->line_pos = 0; -} - -gboolean g_at_result_iter_next(GAtResultIter *iter, const char *prefix) -{ - char *line; - int prefix_len = prefix ? strlen(prefix) : 0; - int linelen; - - while ((iter->l = iter->l->next)) { - line = iter->l->data; - linelen = strlen(line); - - if (linelen > G_AT_RESULT_LINE_LENGTH_MAX) - continue; - - if (prefix_len == 0) { - iter->line_pos = 0; - goto out; - } - - if (g_str_has_prefix(line, prefix) == FALSE) - continue; - - iter->line_pos = prefix_len; - - while (iter->line_pos < strlen(line) && - line[iter->line_pos] == ' ') - iter->line_pos += 1; - - goto out; - } - - return FALSE; - -out: - /* Already checked the length to be no more than buflen */ - strcpy(iter->buf, line); - return TRUE; -} - -const char *g_at_result_iter_raw_line(GAtResultIter *iter) -{ - const char *line; - - if (!iter) - return NULL; - - if (!iter->l) - return NULL; - - line = iter->l->data; - - line += iter->line_pos; - - return line; -} - -static inline int skip_to_next_field(const char *line, int pos, int len) -{ - if (pos < len && line[pos] == ',') - pos += 1; - - while (pos < len && line[pos] == ' ') - pos += 1; - - return pos; -} - -gboolean g_at_result_iter_next_unquoted_string(GAtResultIter *iter, - const char **str) -{ - unsigned int pos; - unsigned int end; - unsigned int len; - char *line; - - if (!iter) - return FALSE; - - if (!iter->l) - return FALSE; - - line = iter->l->data; - len = strlen(line); - - pos = iter->line_pos; - - /* Omitted string */ - if (line[pos] == ',') { - end = pos; - iter->buf[pos] = '\0'; - goto out; - } - - if (line[pos] == '"' || line[pos] == ')') - return FALSE; - - end = pos; - - while (end < len && line[end] != ',' && line[end] != ')') - end += 1; - - iter->buf[end] = '\0'; - -out: - iter->line_pos = skip_to_next_field(line, end, len); - - if (str) - *str = iter->buf + pos; - - return TRUE; -} - -gboolean g_at_result_iter_next_string(GAtResultIter *iter, const char **str) -{ - unsigned int pos; - unsigned int end; - unsigned int len; - char *line; - - if (!iter) - return FALSE; - - if (!iter->l) - return FALSE; - - line = iter->l->data; - len = strlen(line); - - pos = iter->line_pos; - - /* Omitted string */ - if (line[pos] == ',') { - end = pos; - iter->buf[pos] = '\0'; - goto out; - } - - if (line[pos++] != '"') - return FALSE; - - end = pos; - - while (end < len && line[end] != '"') - end += 1; - - if (line[end] != '"') - return FALSE; - - iter->buf[end] = '\0'; - - /* Skip " */ - end += 1; - -out: - iter->line_pos = skip_to_next_field(line, end, len); - - if (str) - *str = iter->buf + pos; - - return TRUE; -} - -gboolean g_at_result_iter_next_hexstring(GAtResultIter *iter, - const guint8 **str, gint *length) -{ - unsigned int pos; - unsigned int end; - unsigned int len; - char *line; - char *bufpos; - - if (!iter) - return FALSE; - - if (!iter->l) - return FALSE; - - line = iter->l->data; - len = strlen(line); - - pos = iter->line_pos; - bufpos = iter->buf + pos; - - /* Omitted string */ - if (line[pos] == ',') { - end = pos; - iter->buf[pos] = '\0'; - goto out; - } - - if (line[pos] == '"') - pos += 1; - - end = pos; - - while (end < len && g_ascii_isxdigit(line[end])) - end += 1; - - if ((end - pos) & 1) - return FALSE; - - *length = (end - pos) / 2; - - for (; pos < end; pos += 2) - sscanf(line + pos, "%02hhx", bufpos++); - - if (line[end] == '"') - end += 1; - -out: - iter->line_pos = skip_to_next_field(line, end, len); - - if (str) - *str = (guint8 *) bufpos - *length; - - return TRUE; -} - -gboolean g_at_result_iter_next_number(GAtResultIter *iter, gint *number) -{ - int pos; - int end; - int len; - int value = 0; - char *line; - - if (!iter) - return FALSE; - - if (!iter->l) - return FALSE; - - line = iter->l->data; - len = strlen(line); - - pos = iter->line_pos; - end = pos; - - while (line[end] >= '0' && line[end] <= '9') { - value = value * 10 + (int)(line[end] - '0'); - end += 1; - } - - if (pos == end) - return FALSE; - - iter->line_pos = skip_to_next_field(line, end, len); - - if (number) - *number = value; - - return TRUE; -} - -gboolean g_at_result_iter_next_range(GAtResultIter *iter, gint *min, gint *max) -{ - int pos; - int end; - int len; - int low = 0; - int high = 0; - char *line; - - if (!iter) - return FALSE; - - if (!iter->l) - return FALSE; - - line = iter->l->data; - len = strlen(line); - - pos = iter->line_pos; - - while (pos < len && line[pos] == ' ') - pos += 1; - - end = pos; - - while (line[end] >= '0' && line[end] <= '9') { - low = low * 10 + (int)(line[end] - '0'); - end += 1; - } - - if (pos == end) - return FALSE; - - if (line[end] != '-') { - high = low; - goto out; - } - - pos = end = end + 1; - - while (line[end] >= '0' && line[end] <= '9') { - high = high * 10 + (int)(line[end] - '0'); - end += 1; - } - - if (pos == end) - return FALSE; - -out: - iter->line_pos = skip_to_next_field(line, end, len); - - if (min) - *min = low; - - if (max) - *max = high; - - return TRUE; -} - -static gint skip_until(const char *line, int start, const char delim) -{ - int len = strlen(line); - int i = start; - - while (i < len) { - if (line[i] == delim) - return i; - - if (line[i] == '\"') { - i += 1; - while (i < len && line[i] != '\"') - i += 1; - - if (i < len) - i += 1; - - continue; - } - - if (line[i] != '(') { - i += 1; - continue; - } - - i = skip_until(line, i+1, ')'); - - if (i < len) - i += 1; - } - - return i; -} - -gboolean g_at_result_iter_skip_next(GAtResultIter *iter) -{ - unsigned int skipped_to; - char *line; - - if (!iter) - return FALSE; - - if (!iter->l) - return FALSE; - - line = iter->l->data; - - skipped_to = skip_until(line, iter->line_pos, ','); - - if (skipped_to == iter->line_pos && line[skipped_to] != ',') - return FALSE; - - iter->line_pos = skip_to_next_field(line, skipped_to, strlen(line)); - - return TRUE; -} - -gboolean g_at_result_iter_open_list(GAtResultIter *iter) -{ - char *line; - unsigned int len; - - if (!iter) - return FALSE; - - if (!iter->l) - return FALSE; - - line = iter->l->data; - len = strlen(line); - - if (iter->line_pos >= len) - return FALSE; - - if (line[iter->line_pos] != '(') - return FALSE; - - iter->line_pos += 1; - - while (iter->line_pos < strlen(line) && - line[iter->line_pos] == ' ') - iter->line_pos += 1; - - return TRUE; -} - -gboolean g_at_result_iter_close_list(GAtResultIter *iter) -{ - char *line; - unsigned int len; - - if (!iter) - return FALSE; - - if (!iter->l) - return FALSE; - - line = iter->l->data; - len = strlen(line); - - if (iter->line_pos >= len) - return FALSE; - - if (line[iter->line_pos] != ')') - return FALSE; - - iter->line_pos += 1; - - iter->line_pos = skip_to_next_field(line, iter->line_pos, len); - - return TRUE; -} - -const char *g_at_result_final_response(GAtResult *result) -{ - if (!result) - return NULL; - - return result->final_or_pdu; -} - -const char *g_at_result_pdu(GAtResult *result) -{ - if (!result) - return NULL; - - return result->final_or_pdu; -} - -gint g_at_result_num_response_lines(GAtResult *result) -{ - if (!result) - return 0; - - if (!result->lines) - return 0; - - return g_slist_length(result->lines); -} diff --git a/gatchat/gatresult.h b/gatchat/gatresult.h deleted file mode 100644 index a74741fb..00000000 --- a/gatchat/gatresult.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GATCHAT_RESULT_H -#define __GATCHAT_RESULT_H - -#ifdef __cplusplus -extern "C" { -#endif - -struct _GAtResult { - GSList *lines; - char *final_or_pdu; -}; - -typedef struct _GAtResult GAtResult; - -#define G_AT_RESULT_LINE_LENGTH_MAX 2048 - -struct _GAtResultIter { - GAtResult *result; - GSList *l; - char buf[G_AT_RESULT_LINE_LENGTH_MAX + 1]; - unsigned int line_pos; - GSList pre; -}; - -typedef struct _GAtResultIter GAtResultIter; - -void g_at_result_iter_init(GAtResultIter *iter, GAtResult *result); - -gboolean g_at_result_iter_next(GAtResultIter *iter, const char *prefix); -gboolean g_at_result_iter_open_list(GAtResultIter *iter); -gboolean g_at_result_iter_close_list(GAtResultIter *iter); - -gboolean g_at_result_iter_skip_next(GAtResultIter *iter); - -gboolean g_at_result_iter_next_range(GAtResultIter *iter, gint *min, gint *max); -gboolean g_at_result_iter_next_string(GAtResultIter *iter, const char **str); -gboolean g_at_result_iter_next_unquoted_string(GAtResultIter *iter, - const char **str); -gboolean g_at_result_iter_next_number(GAtResultIter *iter, gint *number); -gboolean g_at_result_iter_next_hexstring(GAtResultIter *iter, - const guint8 **str, gint *length); - -const char *g_at_result_iter_raw_line(GAtResultIter *iter); - -const char *g_at_result_final_response(GAtResult *result); -const char *g_at_result_pdu(GAtResult *result); - -gint g_at_result_num_response_lines(GAtResult *result); - -#ifdef __cplusplus -} -#endif - -#endif /* __GATCHAT_RESULT_H */ diff --git a/gatchat/gatsyntax.c b/gatchat/gatsyntax.c deleted file mode 100644 index 37344eac..00000000 --- a/gatchat/gatsyntax.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib.h> - -#include "gatsyntax.h" - -enum GSMV1_STATE { - GSMV1_STATE_IDLE = 0, - GSMV1_STATE_INITIAL_CR, - GSMV1_STATE_INITIAL_LF, - GSMV1_STATE_RESPONSE, - GSMV1_STATE_TERMINATOR_CR, - GSMV1_STATE_GUESS_MULTILINE_RESPONSE, - GSMV1_STATE_MULTILINE_RESPONSE, - GSMV1_STATE_MULTILINE_TERMINATOR_CR, - GSMV1_STATE_PDU_CHECK_EXTRA_CR, - GSMV1_STATE_PDU_CHECK_EXTRA_LF, - GSMV1_STATE_PDU, - GSMV1_STATE_PDU_CR, - GSMV1_STATE_PROMPT, - GSMV1_STATE_GARBAGE, - GSMV1_STATE_GARBAGE_CHECK_LF, -}; - -enum GSM_PERMISSIVE_STATE { - GSM_PERMISSIVE_STATE_IDLE = 0, - GSM_PERMISSIVE_STATE_RESPONSE, - GSM_PERMISSIVE_STATE_GUESS_PDU, - GSM_PERMISSIVE_STATE_PDU, - GSM_PERMISSIVE_STATE_PROMPT, -}; - -static void gsmv1_hint(GAtSyntax *syntax, GAtSyntaxExpectHint hint) -{ - switch (hint) { - case G_AT_SYNTAX_EXPECT_PDU: - syntax->state = GSMV1_STATE_PDU_CHECK_EXTRA_CR; - break; - case G_AT_SYNTAX_EXPECT_MULTILINE: - syntax->state = GSMV1_STATE_GUESS_MULTILINE_RESPONSE; - break; - default: - break; - }; -} - -static GAtSyntaxResult gsmv1_feed(GAtSyntax *syntax, - const char *bytes, gsize *len) -{ - gsize i = 0; - GAtSyntaxResult res = G_AT_SYNTAX_RESULT_UNSURE; - - while (i < *len) { - char byte = bytes[i]; - - switch (syntax->state) { - case GSMV1_STATE_IDLE: - if (byte == '\r') - syntax->state = GSMV1_STATE_INITIAL_CR; - else - syntax->state = GSMV1_STATE_GARBAGE; - break; - - case GSMV1_STATE_INITIAL_CR: - if (byte == '\n') - syntax->state = GSMV1_STATE_INITIAL_LF; - else - syntax->state = GSMV1_STATE_GARBAGE; - break; - - case GSMV1_STATE_INITIAL_LF: - if (byte == '\r') - syntax->state = GSMV1_STATE_TERMINATOR_CR; - else if (byte == '>') - syntax->state = GSMV1_STATE_PROMPT; - else - syntax->state = GSMV1_STATE_RESPONSE; - break; - - case GSMV1_STATE_RESPONSE: - if (byte == '\r') - syntax->state = GSMV1_STATE_TERMINATOR_CR; - break; - - case GSMV1_STATE_TERMINATOR_CR: - syntax->state = GSMV1_STATE_IDLE; - - if (byte == '\n') { - i += 1; - res = G_AT_SYNTAX_RESULT_LINE; - } else - res = G_AT_SYNTAX_RESULT_UNRECOGNIZED; - - goto out; - - case GSMV1_STATE_GUESS_MULTILINE_RESPONSE: - if (byte == '\r') - syntax->state = GSMV1_STATE_INITIAL_CR; - else - syntax->state = GSMV1_STATE_MULTILINE_RESPONSE; - break; - - case GSMV1_STATE_MULTILINE_RESPONSE: - if (byte == '\r') - syntax->state = GSMV1_STATE_MULTILINE_TERMINATOR_CR; - break; - - case GSMV1_STATE_MULTILINE_TERMINATOR_CR: - syntax->state = GSMV1_STATE_IDLE; - - if (byte == '\n') { - i += 1; - res = G_AT_SYNTAX_RESULT_MULTILINE; - } else - res = G_AT_SYNTAX_RESULT_UNRECOGNIZED; - - goto out; - - /* Some 27.007 compliant modems still get this wrong. They - * insert an extra CRLF between the command and he PDU, - * in effect making them two separate lines. We try to - * handle this case gracefully - */ - case GSMV1_STATE_PDU_CHECK_EXTRA_CR: - if (byte == '\r') - syntax->state = GSMV1_STATE_PDU_CHECK_EXTRA_LF; - else - syntax->state = GSMV1_STATE_PDU; - break; - - case GSMV1_STATE_PDU_CHECK_EXTRA_LF: - res = G_AT_SYNTAX_RESULT_UNRECOGNIZED; - syntax->state = GSMV1_STATE_PDU; - - if (byte == '\n') - i += 1; - - goto out; - - case GSMV1_STATE_PDU: - if (byte == '\r') - syntax->state = GSMV1_STATE_PDU_CR; - break; - - case GSMV1_STATE_PDU_CR: - syntax->state = GSMV1_STATE_IDLE; - - if (byte == '\n') { - i += 1; - res = G_AT_SYNTAX_RESULT_PDU; - } else - res = G_AT_SYNTAX_RESULT_UNRECOGNIZED; - - goto out; - - case GSMV1_STATE_PROMPT: - if (byte == ' ') { - syntax->state = GSMV1_STATE_IDLE; - i += 1; - res = G_AT_SYNTAX_RESULT_PROMPT; - goto out; - } - - syntax->state = GSMV1_STATE_RESPONSE; - return G_AT_SYNTAX_RESULT_UNSURE; - - case GSMV1_STATE_GARBAGE: - if (byte == '\r') - syntax->state = GSMV1_STATE_GARBAGE_CHECK_LF; - /* This handles the case of echo of the PDU terminated - * by CtrlZ character - */ - else if (byte == 26) { - syntax->state = GSMV1_STATE_IDLE; - res = G_AT_SYNTAX_RESULT_UNRECOGNIZED; - i += 1; - goto out; - } - - break; - - case GSMV1_STATE_GARBAGE_CHECK_LF: - syntax->state = GSMV1_STATE_IDLE; - res = G_AT_SYNTAX_RESULT_UNRECOGNIZED; - - if (byte == '\n') - i += 1; - - goto out; - - default: - break; - }; - - i += 1; - } - -out: - *len = i; - return res; -} - -static void gsm_permissive_hint(GAtSyntax *syntax, GAtSyntaxExpectHint hint) -{ - if (hint == G_AT_SYNTAX_EXPECT_PDU) - syntax->state = GSM_PERMISSIVE_STATE_GUESS_PDU; -} - -static GAtSyntaxResult gsm_permissive_feed(GAtSyntax *syntax, - const char *bytes, gsize *len) -{ - gsize i = 0; - GAtSyntaxResult res = G_AT_SYNTAX_RESULT_UNSURE; - - while (i < *len) { - char byte = bytes[i]; - - switch (syntax->state) { - case GSM_PERMISSIVE_STATE_IDLE: - if (byte == '\r' || byte == '\n') - /* ignore */; - else if (byte == '>') - syntax->state = GSM_PERMISSIVE_STATE_PROMPT; - else - syntax->state = GSM_PERMISSIVE_STATE_RESPONSE; - break; - - case GSM_PERMISSIVE_STATE_RESPONSE: - if (byte == '\r') { - syntax->state = GSM_PERMISSIVE_STATE_IDLE; - - i += 1; - res = G_AT_SYNTAX_RESULT_LINE; - goto out; - } - break; - - case GSM_PERMISSIVE_STATE_GUESS_PDU: - if (byte != '\r' && byte != '\n') - syntax->state = GSM_PERMISSIVE_STATE_PDU; - break; - - case GSM_PERMISSIVE_STATE_PDU: - if (byte == '\r') { - syntax->state = GSM_PERMISSIVE_STATE_IDLE; - - i += 1; - res = G_AT_SYNTAX_RESULT_PDU; - goto out; - } - break; - - case GSM_PERMISSIVE_STATE_PROMPT: - if (byte == ' ') { - syntax->state = GSM_PERMISSIVE_STATE_IDLE; - i += 1; - res = G_AT_SYNTAX_RESULT_PROMPT; - goto out; - } - - syntax->state = GSM_PERMISSIVE_STATE_RESPONSE; - return G_AT_SYNTAX_RESULT_UNSURE; - - default: - break; - }; - - i += 1; - } - -out: - *len = i; - return res; -} - -GAtSyntax *g_at_syntax_new_full(GAtSyntaxFeedFunc feed, - GAtSyntaxSetHintFunc hint, - int initial_state) -{ - GAtSyntax *syntax; - - syntax = g_new0(GAtSyntax, 1); - - syntax->feed = feed; - syntax->set_hint = hint; - syntax->state = initial_state; - syntax->ref_count = 1; - - return syntax; -} - - -GAtSyntax *g_at_syntax_new_gsmv1() -{ - return g_at_syntax_new_full(gsmv1_feed, gsmv1_hint, GSMV1_STATE_IDLE); -} - -GAtSyntax *g_at_syntax_new_gsm_permissive() -{ - return g_at_syntax_new_full(gsm_permissive_feed, gsm_permissive_hint, - GSM_PERMISSIVE_STATE_IDLE); -} - -GAtSyntax *g_at_syntax_ref(GAtSyntax *syntax) -{ - if (syntax == NULL) - return NULL; - - g_atomic_int_inc(&syntax->ref_count); - - return syntax; -} - -void g_at_syntax_unref(GAtSyntax *syntax) -{ - gboolean is_zero; - - if (syntax == NULL) - return; - - is_zero = g_atomic_int_dec_and_test(&syntax->ref_count); - - if (is_zero) - g_free(syntax); -} diff --git a/gatchat/gatsyntax.h b/gatchat/gatsyntax.h deleted file mode 100644 index d76cf6fa..00000000 --- a/gatchat/gatsyntax.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GATSYNTAX_H -#define __GATSYNTAX_H - -#ifdef __cplusplus -extern "C" { -#endif - -enum _GAtSyntaxExpectHint { - G_AT_SYNTAX_EXPECT_PDU, - G_AT_SYNTAX_EXPECT_MULTILINE, - G_AT_SYNTAX_EXPECT_PROMPT -}; - -typedef enum _GAtSyntaxExpectHint GAtSyntaxExpectHint; - -enum _GAtSyntaxResult { - G_AT_SYNTAX_RESULT_UNRECOGNIZED, - G_AT_SYNTAX_RESULT_UNSURE, - G_AT_SYNTAX_RESULT_LINE, - G_AT_SYNTAX_RESULT_MULTILINE, - G_AT_SYNTAX_RESULT_PDU, - G_AT_SYNTAX_RESULT_PROMPT, -}; - -typedef enum _GAtSyntaxResult GAtSyntaxResult; - -typedef struct _GAtSyntax GAtSyntax; - -typedef void (*GAtSyntaxSetHintFunc)(GAtSyntax *syntax, - GAtSyntaxExpectHint hint); -typedef GAtSyntaxResult (*GAtSyntaxFeedFunc)(GAtSyntax *syntax, - const char *bytes, gsize *len); - -struct _GAtSyntax { - gint ref_count; - int state; - GAtSyntaxSetHintFunc set_hint; - GAtSyntaxFeedFunc feed; -}; - - -GAtSyntax *g_at_syntax_new_full(GAtSyntaxFeedFunc feed, - GAtSyntaxSetHintFunc hint, - int initial_state); - -/* This syntax implements very strict checking of 27.007 standard, which means - * it might not work with a majority of modems. However, it does handle echo - * properly and can be used to detect a modem's deviations from the relevant - * standards. - */ -GAtSyntax *g_at_syntax_new_gsmv1(); - -/* This syntax implements an extremely lax parser that can handle a variety - * of modems. Unfortunately it does not deal with echo at all, so echo must - * be explicitly turned off before using the parser - */ -GAtSyntax *g_at_syntax_new_gsm_permissive(); - -GAtSyntax *g_at_syntax_ref(GAtSyntax *syntax); -void g_at_syntax_unref(GAtSyntax *syntax); - -#ifdef __cplusplus -} -#endif - -#endif /* __GATSYNTAX_H */ diff --git a/gatchat/gattty.c b/gatchat/gattty.c deleted file mode 100644 index 02ca389d..00000000 --- a/gatchat/gattty.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <termios.h> - -#include <glib.h> - -#include "gattty.h" - -static gboolean set_baud(const char *baud, struct termios *ti) -{ - speed_t speed; - - if (g_str_equal(baud, "300")) - speed = B300; - else if (g_str_equal(baud, "1200")) - speed = B1200; - else if (g_str_equal(baud, "2400")) - speed = B2400; - else if (g_str_equal(baud, "4800")) - speed = B4800; - else if (g_str_equal(baud, "9600")) - speed = B9600; - else if (g_str_equal(baud, "19200")) - speed = B19200; - else if (g_str_equal(baud, "38400")) - speed = B38400; - else if (g_str_equal(baud, "57600")) - speed = B57600; - else if (g_str_equal(baud, "115200")) - speed = B115200; - else if (g_str_equal(baud, "230400")) - speed = B230400; - else if (g_str_equal(baud, "460800")) - speed = B460800; - else if (g_str_equal(baud, "500000")) - speed = B500000; - else if (g_str_equal(baud, "576000")) - speed = B576000; - else if (g_str_equal(baud, "921600")) - speed = B921600; - else if (g_str_equal(baud, "1000000")) - speed = B1000000; - else if (g_str_equal(baud, "1152000")) - speed = B1152000; - else if (g_str_equal(baud, "1500000")) - speed = B1500000; - else if (g_str_equal(baud, "2000000")) - speed = B2000000; -#ifdef B2500000 - else if (g_str_equal(baud, "2500000")) - speed = B2500000; -#endif -#ifdef B3000000 - else if (g_str_equal(baud, "3000000")) - speed = B3000000; -#endif -#ifdef B3500000 - else if (g_str_equal(baud, "3500000")) - speed = B3500000; -#endif -#ifdef B4000000 - else if (g_str_equal(baud, "4000000")) - speed = B4000000; -#endif - else - return FALSE; - - cfsetospeed(ti, speed); - cfsetispeed(ti, speed); - - return TRUE; -} - -static gboolean set_read(const char *bits, struct termios *ti) -{ - if (g_str_equal(bits, "off")) - ti->c_cflag &= ~(CREAD); - else if (g_str_equal(bits, "on")) - ti->c_cflag |= CREAD; - else - return FALSE; - - return TRUE; -} - -static gboolean set_stop_bits(const char *bits, struct termios *ti) -{ - if (g_str_equal(bits, "1")) - ti->c_cflag &= ~(CSTOPB); - else if (g_str_equal(bits, "2")) - ti->c_cflag |= CSTOPB; - else - return FALSE; - - return TRUE; -} - -static gboolean set_data_bits(const char *bits, struct termios *ti) -{ - if (g_str_equal(bits, "7")) { - ti->c_cflag &= ~(CSIZE); - ti->c_cflag |= CS7; - } else if (g_str_equal(bits, "8")) { - ti->c_cflag &= ~(CSIZE); - ti->c_cflag |= CS8; - } else - return FALSE; - - return TRUE; -} - -static gboolean set_parity(const char *parity, struct termios *ti) -{ - if (g_str_equal(parity, "none")) - ti->c_cflag &= ~(PARENB); - else if (g_str_equal(parity, "even")) { - ti->c_cflag |= PARENB; - ti->c_cflag &= ~(PARODD); - } else if (g_str_equal(parity, "odd")) { - ti->c_cflag |= PARENB; - ti->c_cflag |= PARODD; - } else - return FALSE; - - return TRUE; -} - -static gboolean set_xonxoff(const char *xonxoff, struct termios *ti) -{ - if (g_str_equal(xonxoff, "on")) { - ti->c_iflag |= (IXON | IXOFF | IXANY); - ti->c_cc[VSTART] = 17; - ti->c_cc[VSTOP] = 19; - } else if (g_str_equal(xonxoff, "off")) - ti->c_iflag &= ~(IXON | IXOFF | IXANY); - else - return FALSE; - - return TRUE; -} - -static gboolean set_rtscts(const char *rtscts, struct termios *ti) -{ - if (g_str_equal(rtscts, "on")) - ti->c_cflag |= CRTSCTS; - else if (g_str_equal(rtscts, "off")) - ti->c_cflag &= ~(CRTSCTS); - else - return FALSE; - - return TRUE; -} - -static gboolean set_local(const char *local, struct termios *ti) -{ - if (g_str_equal(local, "on")) - ti->c_cflag |= CLOCAL; - else if (g_str_equal(local, "off")) - ti->c_cflag &= ~(CLOCAL); - else - return FALSE; - - return TRUE; -} - -static int open_device(const char *tty, GHashTable *options) -{ - struct termios ti; - int fd; - - /* Switch TTY to raw mode */ - memset(&ti, 0, sizeof(ti)); - cfmakeraw(&ti); - - if (options) { - GHashTableIter iter; - const char *key; - const char *value; - - g_hash_table_iter_init (&iter, options); - while (g_hash_table_iter_next(&iter, (void *) &key, - (void *) &value)) { - gboolean ok = FALSE; - - if (g_str_equal(key, "Baud")) - ok = set_baud(value, &ti); - else if (g_str_equal(key, "StopBits")) - ok = set_stop_bits(value, &ti); - else if (g_str_equal(key, "DataBits")) - ok = set_data_bits(value, &ti); - else if (g_str_equal(key, "Parity")) - ok = set_parity(value, &ti); - else if (g_str_equal(key, "XonXoff")) - ok = set_xonxoff(value, &ti); - else if (g_str_equal(key, "RtsCts")) - ok = set_rtscts(value, &ti); - else if (g_str_equal(key, "Local")) - ok = set_local(value, &ti); - else if (g_str_equal(key, "Read")) - ok = set_read(value, &ti); - - if (ok == FALSE) - return -1; - } - } - - fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK); - if (fd < 0) - return -1; - - tcflush(fd, TCIOFLUSH); - tcsetattr(fd, TCSANOW, &ti); - - return fd; -} - -GIOChannel *g_at_tty_open(const char *tty, GHashTable *options) -{ - GIOChannel *channel; - int fd; - - fd = open_device(tty, options); - if (fd < 0) - return NULL; - - channel = g_io_channel_unix_new(fd); - - if (channel == NULL) { - close(fd); - return NULL; - } - - g_io_channel_set_close_on_unref(channel, TRUE); - - return channel; -} diff --git a/gatchat/gattty.h b/gatchat/gattty.h deleted file mode 100644 index dc3fe160..00000000 --- a/gatchat/gattty.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GATTTY_H -#define __GATTTY_H - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - * Opens a serial port given by tty. If options is NULL, then the serial port - * is opened in raw mode. Otherwise the options are parsed and set accordingly - * - * The following keys / values are recognized (all strings) - * - * "Baud" - "300", "600", etc - * "Stopbits" - "1", "2" - * "Databits" - "7", "8" - * "Parity" - "none", "odd", "even" - * "XonXoff" - "on", "off" - * "RtsCts" - "on", "off" - * "Local" - "on", "off" - * "Read" - "on, "off" - */ -GIOChannel *g_at_tty_open(const char *tty, GHashTable *options); - -#ifdef __cplusplus -} -#endif - -#endif /* __GATTTY_H */ diff --git a/gatchat/gatutil.c b/gatchat/gatutil.c deleted file mode 100644 index 7ca1d3f9..00000000 --- a/gatchat/gatutil.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <ctype.h> - -#include <glib.h> - -#include "gatutil.h" - -void g_at_util_debug_chat(gboolean in, const char *str, gsize len, - GAtDebugFunc debugf, gpointer user_data) -{ - char type = in ? '<' : '>'; - gsize escaped = 2; /* Enough for '<', ' ' */ - char *escaped_str; - const char *esc = "<ESC>"; - gsize esc_size = strlen(esc); - const char *ctrlz = "<CtrlZ>"; - gsize ctrlz_size = strlen(ctrlz); - gsize i; - - if (!debugf || !len) - return; - - for (i = 0; i < len; i++) { - char c = str[i]; - - if (isprint(c)) - escaped += 1; - else if (c == '\r' || c == '\t' || c == '\n') - escaped += 2; - else if (c == 26) - escaped += ctrlz_size; - else if (c == 25) - escaped += esc_size; - else - escaped += 4; - } - - escaped_str = g_malloc(escaped + 1); - escaped_str[0] = type; - escaped_str[1] = ' '; - escaped_str[2] = '\0'; - escaped_str[escaped] = '\0'; - - for (escaped = 2, i = 0; i < len; i++) { - char c = str[i]; - - switch (c) { - case '\r': - escaped_str[escaped++] = '\\'; - escaped_str[escaped++] = 'r'; - break; - case '\t': - escaped_str[escaped++] = '\\'; - escaped_str[escaped++] = 't'; - break; - case '\n': - escaped_str[escaped++] = '\\'; - escaped_str[escaped++] = 'n'; - break; - case 26: - strncpy(&escaped_str[escaped], ctrlz, ctrlz_size); - escaped += ctrlz_size; - break; - case 25: - strncpy(&escaped_str[escaped], esc, esc_size); - escaped += esc_size; - break; - default: - if (isprint(c)) - escaped_str[escaped++] = c; - else { - escaped_str[escaped++] = '\\'; - escaped_str[escaped++] = '0' + ((c >> 6) & 07); - escaped_str[escaped++] = '0' + ((c >> 3) & 07); - escaped_str[escaped++] = '0' + (c & 07); - } - } - } - - debugf(escaped_str, user_data); - g_free(escaped_str); -} - -gboolean g_at_util_setup_io(GIOChannel *io, GIOFlags flags) -{ - GIOFlags io_flags; - - if (g_io_channel_set_encoding(io, NULL, NULL) != - G_IO_STATUS_NORMAL) - return FALSE; - - io_flags = g_io_channel_get_flags(io); - - io_flags |= (flags & G_IO_FLAG_SET_MASK); - - if (g_io_channel_set_flags(io, io_flags, NULL) != - G_IO_STATUS_NORMAL) - return FALSE; - - g_io_channel_set_close_on_unref(io, TRUE); - - return TRUE; -} - diff --git a/gatchat/gatutil.h b/gatchat/gatutil.h deleted file mode 100644 index 993db457..00000000 --- a/gatchat/gatutil.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GATUTIL_H -#define __GATUTIL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "gat.h" - -void g_at_util_debug_chat(gboolean in, const char *str, gsize len, - GAtDebugFunc debugf, gpointer user_data); - -gboolean g_at_util_setup_io(GIOChannel *io, GIOFlags flags); - -#ifdef __cplusplus -} -#endif - -#endif /* __GATUTIL_H */ diff --git a/gatchat/ringbuffer.c b/gatchat/ringbuffer.c deleted file mode 100644 index 42d5b680..00000000 --- a/gatchat/ringbuffer.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> - -#include <glib.h> - -#include "ringbuffer.h" - -#define MAX_SIZE 262144 - -struct ring_buffer *ring_buffer_new(unsigned int size) -{ - unsigned int real_size = 1; - struct ring_buffer *buffer; - - /* Find the next power of two for size */ - while (real_size < size && real_size < MAX_SIZE) - real_size = real_size << 1; - - if (real_size > MAX_SIZE) - return NULL; - - buffer = g_new(struct ring_buffer, 1); - - if (!buffer) - return NULL; - - buffer->buffer = g_new(unsigned char, real_size); - - if (!buffer->buffer) { - g_free(buffer); - return NULL; - } - - buffer->size = real_size; - buffer->in = 0; - buffer->out = 0; - - return buffer; -} - -int ring_buffer_write(struct ring_buffer *buf, const void *data, - unsigned int len) -{ - unsigned int end; - unsigned int offset; - const unsigned char *d = data; /* Needed to satisfy non-gcc compilers */ - - /* Determine how much we can actually write */ - len = MIN(len, buf->size - buf->in + buf->out); - - /* Determine how much to write before wrapping */ - offset = buf->in % buf->size; - end = MIN(len, buf->size - offset); - memcpy(buf->buffer+offset, d, end); - - /* Now put the remainder on the beginning of the buffer */ - memcpy(buf->buffer, d + end, len - end); - - buf->in += len; - - return len; -} - -unsigned char *ring_buffer_write_ptr(struct ring_buffer *buf) -{ - return buf->buffer + buf->in % buf->size; -} - -int ring_buffer_avail_no_wrap(struct ring_buffer *buf) -{ - unsigned int offset = buf->in % buf->size; - unsigned int len = buf->size - buf->in + buf->out; - - return MIN(len, buf->size - offset); -} - -int ring_buffer_write_advance(struct ring_buffer *buf, unsigned int len) -{ - len = MIN(len, buf->size - buf->in + buf->out); - buf->in += len; - - return len; -} - -int ring_buffer_read(struct ring_buffer *buf, void *data, unsigned int len) -{ - unsigned int end; - unsigned int offset; - unsigned char *d = data; - - len = MIN(len, buf->in - buf->out); - - /* Grab data from buffer starting at offset until the end */ - offset = buf->out % buf->size; - end = MIN(len, buf->size - offset); - memcpy(d, buf->buffer + offset, end); - - /* Now grab remainder from the beginning */ - memcpy(d + end, buf->buffer, len - end); - - buf->out += len; - - if (buf->out == buf->in) - buf->out = buf->in = 0; - - return len; -} - -int ring_buffer_drain(struct ring_buffer *buf, unsigned int len) -{ - len = MIN(len, buf->in - buf->out); - - buf->out += len; - - if (buf->out == buf->in) - buf->out = buf->in = 0; - - return len; -} - -int ring_buffer_len_no_wrap(struct ring_buffer *buf) -{ - unsigned int offset = buf->out % buf->size; - unsigned int len = buf->in - buf->out; - - return MIN(len, buf->size - offset); -} - -unsigned char *ring_buffer_read_ptr(struct ring_buffer *buf, - unsigned int offset) -{ - return buf->buffer + (buf->out + offset) % buf->size; -} - -int ring_buffer_len(struct ring_buffer *buf) -{ - if (!buf) - return -1; - - return buf->in - buf->out; -} - -void ring_buffer_reset(struct ring_buffer *buf) -{ - if (!buf) - return; - - buf->in = 0; - buf->out = 0; -} - -int ring_buffer_avail(struct ring_buffer *buf) -{ - if (!buf) - return -1; - - return buf->size - buf->in + buf->out; -} - -int ring_buffer_capacity(struct ring_buffer *buf) -{ - if (!buf) - return -1; - - return buf->size; -} - -void ring_buffer_free(struct ring_buffer *buf) -{ - if (!buf) - return; - - g_free(buf->buffer); - g_free(buf); -} diff --git a/gatchat/ringbuffer.h b/gatchat/ringbuffer.h deleted file mode 100644 index 826f9aaf..00000000 --- a/gatchat/ringbuffer.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - * AT chat library with GLib integration - * - * Copyright (C) 2008-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __GATCHAT_RINGBUFFER_H -#define __GATCHAT_RINGBUFFER_H - -#ifdef __cplusplus -extern "C" { -#endif - -struct ring_buffer { - unsigned char *buffer; - unsigned int size; - unsigned int in; - unsigned int out; -}; - -/*! - * Creates a new ring buffer with capacity size - */ -struct ring_buffer *ring_buffer_new(unsigned int size); - -/*! - * Frees the resources allocated for the ring buffer - */ -void ring_buffer_free(struct ring_buffer *buf); - -/*! - * Returns the capacity of the ring buffer - */ -int ring_buffer_capacity(struct ring_buffer *buf); - -/*! - * Resets the ring buffer, all data inside the buffer is lost - */ -void ring_buffer_reset(struct ring_buffer *buf); - -/*! - * Writes data of size len into the ring buffer buf. Returns -1 if the - * write failed or the number of bytes written - */ -int ring_buffer_write(struct ring_buffer *buf, const void *data, - unsigned int len); - -/*! - * Advances the write counter by len, this is meant to be used with - * the ring_buffer_write_ptr function. Returns the number of bytes - * actually advanced (the capacity of the buffer) - */ -int ring_buffer_write_advance(struct ring_buffer *buf, unsigned int len); - -/*! - * Returns the write pointer. Careful not to write past the end of the - * buffer. Use the ring_buffer_avail_no_wrap function, - * ring_buffer_write_advance. - */ -unsigned char *ring_buffer_write_ptr(struct ring_buffer *buf); - -/*! - * Returns the number of free bytes available in the buffer - */ -int ring_buffer_avail(struct ring_buffer *buf); - -/*! - * Returns the number of free bytes available in the buffer without wrapping - */ -int ring_buffer_avail_no_wrap(struct ring_buffer *buf); - -/*! - * Reads data from the ring buffer buf into memory region pointed to by data. - * A maximum of len bytes will be read. Returns -1 if the read failed or - * the number of bytes read - */ -int ring_buffer_read(struct ring_buffer *buf, void *data, - unsigned int len); - -/*! - * Returns the read pointer with read offset specified by offset. No bounds - * checking is performed. Be careful not to read past the end of the buffer. - * Use the ring_buffer_len_no_wrap function, and ring_buffer_drain. - */ -unsigned char *ring_buffer_read_ptr(struct ring_buffer *buf, - unsigned int offset); - -/*! - * Returns the number of bytes currently available to be read in the buffer - */ -int ring_buffer_len(struct ring_buffer *buf); - -/*! - * Returns the number of bytes currently available to be read in the buffer - * without wrapping. - */ -int ring_buffer_len_no_wrap(struct ring_buffer *buf); - -/*! - * Drains the ring buffer of len bytes. Returns the number of bytes the - * read counter was actually advanced. - */ -int ring_buffer_drain(struct ring_buffer *buf, unsigned int len); - -#ifdef __cplusplus -} -#endif - -#endif /* __GATCHAT_RINGBUFFER_H */ |