From 9ce17594596e09332de68927dbe3ee7d082e8aeb Mon Sep 17 00:00:00 2001 From: Suresh Kumar N Date: Wed, 9 Apr 2014 21:03:59 +0530 Subject: [PATCH] Added support for Abortable commands Change-Id: I1ee796a82f34f36ea2c2ce56cd0116030cb9e49a --- include/at.h | 7 +++ include/queue.h | 5 ++ src/at.c | 158 ++++++++++++++++++++++++++++++++++++++++++++------------ src/queue.c | 79 ++++++++++++++++++++++++---- 4 files changed, 207 insertions(+), 42 deletions(-) diff --git a/include/at.h b/include/at.h index b50baad..b7bbacb 100644 --- a/include/at.h +++ b/include/at.h @@ -92,6 +92,13 @@ TelReturn tcore_at_prepare_and_send_request(CoreObject *co, TcorePendingResponseCallback resp_cb, void *resp_cb_data, TcorePendingSendCallback send_cb, void *send_cb_data, guint timeout, TcorePendingTimeoutCallback timeout_cb, void *timeout_cb_data); +TelReturn tcore_at_prepare_and_send_request_ex(CoreObject *co, + const gchar *cmd, const gchar *prefix, TcoreAtCommandType type, + TcorePendingPriority priority, void *request, + TcorePendingResponseCallback resp_cb, void *resp_cb_data, + TcorePendingSendCallback send_cb, void *send_cb_data, + guint timeout, TcorePendingTimeoutCallback timeout_cb, void *timeout_cb_data, + gboolean auto_free, gboolean abortable); #ifdef __cplusplus } diff --git a/include/queue.h b/include/queue.h index 3a05489..970166c 100644 --- a/include/queue.h +++ b/include/queue.h @@ -48,6 +48,10 @@ TelReturn tcore_pending_set_auto_free_status_after_sent(TcorePending *pending, gboolean flag); gboolean tcore_pending_get_auto_free_status_after_sent(TcorePending *pending); +TelReturn tcore_pending_set_abortable(TcorePending *pending, + gboolean abortable); +gboolean tcore_pending_get_abortable(TcorePending *pending); + TelReturn tcore_pending_set_request_data(TcorePending *pending, guint data_len, void *data); void *tcore_pending_ref_request_data(TcorePending *pending, guint *data_len); @@ -90,6 +94,7 @@ TcorePending *tcore_queue_pop(TcoreQueue *queue); TcorePending *tcore_queue_pop_by_id(TcoreQueue *queue, guint id); TcorePending *tcore_queue_pop_by_pending(TcoreQueue *queue, TcorePending *pending); +TcorePending *tcore_queue_pop_abortable_pending(TcoreQueue *queue); TcorePending *tcore_queue_pop_timeout_pending(TcoreQueue *queue); TcorePending *tcore_queue_ref_head(TcoreQueue *queue); diff --git a/src/at.c b/src/at.c index cffb171..a297e75 100644 --- a/src/at.c +++ b/src/at.c @@ -97,7 +97,8 @@ typedef enum { */ static const gchar *at_final_responses_success[] = { "OK", - "CONNECT" + "CONNECT", + "ABORTED" }; /** @@ -149,7 +150,7 @@ static gchar *_find_next_EOL(gchar *cur) return *cur == '\0' ? NULL : cur; } -static TcoreAtResponse *__response_new() +static TcoreAtResponse *__at_response_new() { TcoreAtResponse *at_resp; @@ -162,7 +163,7 @@ static TcoreAtResponse *__response_new() return at_resp; } -static void __response_free(TcoreAtResponse *at_resp) +static void __at_response_free(TcoreAtResponse *at_resp) { if (at_resp == NULL) { err("Response is NULL"); @@ -174,8 +175,23 @@ static void __response_free(TcoreAtResponse *at_resp) tcore_free(at_resp); } +static gboolean __at_is_abort(TcoreAtResponse *at_resp) +{ + gboolean aborted = FALSE; + if (at_resp == NULL) { + err("at_resp is NULL"); + return FALSE; + } + + /* Request is ABORTED */ + if (g_strcmp0(at_resp->final_response, "ABORTED") == 0) + aborted = TRUE; + dbg("Aborted: [%s]", (aborted ? "YES" : "NO")); -static void __response_add(TcoreAtResponse *at_resp, const gchar *line) + return aborted; +} + +static void __at_response_add(TcoreAtResponse *at_resp, const gchar *line) { if ((at_resp == NULL) || (line == NULL)) { err("at_resp: [%p] line: [%p]", at_resp, line); @@ -187,9 +203,10 @@ static void __response_add(TcoreAtResponse *at_resp, const gchar *line) at_resp->lines = g_slist_append(at_resp->lines, tcore_strdup(line)); } -static void __emit_pending_response(TcoreAT *at) +static void __at_emit_pending_response(TcoreAT *at, gboolean abort) { TcorePending *p; + TcoreQueue *at_queue; if (at == NULL) { err("at is NULL"); @@ -199,20 +216,36 @@ static void __emit_pending_response(TcoreAT *at) tcore_at_request_free(at->req); at->req = NULL; - p = tcore_queue_pop(tcore_hal_ref_queue(at->hal)); - if (p == NULL) { - warn("NO pending request!!!"); - return; + at_queue = tcore_hal_ref_queue(at->hal); + + /* + * If 'abort' is TRUE, + * then Pop the first Abortable Request from Queue + */ + if (abort) { + p = tcore_queue_pop_abortable_pending(at_queue); + if (p == NULL) { + warn("No Abortable requests!!!"); + goto out; + } + } + else { + p = tcore_queue_pop(at_queue); + if (p == NULL) { + warn("NO pending request!!!"); + goto out; + } } tcore_pending_emit_response_callback(p, sizeof(TcoreAtResponse), at->resp); tcore_pending_free(p); - __response_free(at->resp); +out: + __at_response_free(at->resp); at->resp = NULL; } -static void __emit_unsolicited_message(TcoreAT *at, const gchar *line) +static void __at_emit_unsolicited_message(TcoreAT *at, const gchar *line) { struct _notification *noti = NULL; struct _notification_callback *item = NULL; @@ -634,7 +667,7 @@ void tcore_at_process_binary_data(TcoreAT *at, gchar *position, guint data_len) } if (data_len_final == actual_buffer_size) { - __emit_unsolicited_message(at, position); + __at_emit_unsolicited_message(at, position); at->data_mode = MODE_HEX; at->buf_read_pos = at->buf_read_pos + (actual_buffer_size + 1); data_len_final = ZERO; @@ -681,11 +714,11 @@ gboolean tcore_at_process(TcoreAT *at, guint data_len, const gchar *data) /* Check request */ if (at->req == NULL) { - dbg(" Not AT request " ); - __emit_unsolicited_message(at, pos); + dbg("Not AT request" ); + __at_emit_unsolicited_message(at, pos); } else { - dbg(" AT request " ); + dbg("AT request" ); if (g_strcmp0(pos, "> ") == 0) { if (at->req->next_send_pos) { dbg("send next: [%s]", at->req->next_send_pos); @@ -700,7 +733,7 @@ gboolean tcore_at_process(TcoreAT *at, guint data_len, const gchar *data) } if (at->resp == NULL) - at->resp = __response_new(); + at->resp = __at_response_new(); ret = __check_final_response(pos); switch (ret) { @@ -712,7 +745,7 @@ gboolean tcore_at_process(TcoreAT *at, guint data_len, const gchar *data) at->resp->final_response = tcore_strdup(pos); - __emit_pending_response(at); + __at_emit_pending_response(at, __at_is_abort(at->resp)); at->buf_read_pos = next_pos + 1; return TRUE; @@ -721,14 +754,14 @@ gboolean tcore_at_process(TcoreAT *at, guint data_len, const gchar *data) case TCORE_AT_RECV_MSG_TYPE_NOTI: { switch (at->req->type) { case TCORE_AT_COMMAND_TYPE_NO_RESULT: - __emit_unsolicited_message(at, pos); + __at_emit_unsolicited_message(at, pos); break; case TCORE_AT_COMMAND_TYPE_NUMERIC: if (at->resp->lines == NULL && isdigit(pos[0])) - __response_add(at->resp, pos); + __at_response_add(at->resp, pos); else - __emit_unsolicited_message(at, pos); + __at_emit_unsolicited_message(at, pos); break; case TCORE_AT_COMMAND_TYPE_SINGLELINE: @@ -736,43 +769,43 @@ gboolean tcore_at_process(TcoreAT *at, guint data_len, const gchar *data) if (at->resp->lines == NULL) if (at->req->prefix) if (g_str_has_prefix(pos, at->req->prefix)) - __response_add(at->resp, pos); + __at_response_add(at->resp, pos); else - __emit_unsolicited_message(at, pos); + __at_emit_unsolicited_message(at, pos); else - __response_add(at->resp, pos); + __at_response_add(at->resp, pos); else - __emit_unsolicited_message(at, pos); + __at_emit_unsolicited_message(at, pos); break; case TCORE_AT_COMMAND_TYPE_MULTILINE: dbg("MULTILINE"); if (at->req->prefix) if (g_str_has_prefix(pos, at->req->prefix)) - __response_add(at->resp, pos); + __at_response_add(at->resp, pos); else - __emit_unsolicited_message(at, pos); + __at_emit_unsolicited_message(at, pos); else - __response_add(at->resp, pos); + __at_response_add(at->resp, pos); break; case TCORE_AT_COMMAND_TYPE_PDU: dbg("PDU"); if (at->req->prefix) if (g_str_has_prefix(pos, at->req->prefix)) - __response_add(at->resp, pos); + __at_response_add(at->resp, pos); else if (at->resp->lines != NULL) - __response_add(at->resp, pos); + __at_response_add(at->resp, pos); else - __emit_unsolicited_message(at, pos); + __at_emit_unsolicited_message(at, pos); else - __response_add(at->resp, pos); + __at_response_add(at->resp, pos); break; default: warn("UNKNOWN"); - __emit_unsolicited_message(at, pos); + __at_emit_unsolicited_message(at, pos); break; } /* switch (at->req->type) */ } break; @@ -1037,3 +1070,64 @@ TelReturn tcore_at_prepare_and_send_request(CoreObject *co, return ret; } + +TelReturn tcore_at_prepare_and_send_request_ex(CoreObject *co, + const gchar *cmd, const gchar *prefix, TcoreAtCommandType type, + TcorePendingPriority priority, void *request, + TcorePendingResponseCallback resp_cb, void *resp_cb_data, + TcorePendingSendCallback send_cb, void *send_cb_data, + guint timeout, TcorePendingTimeoutCallback timeout_cb, void *timeout_cb_data, + gboolean auto_free, gboolean abortable) +{ + TcorePending *pending; + TcoreAtRequest *at_req; + TcoreHal *hal; + TelReturn ret = TEL_RETURN_FAILURE; + + hal = tcore_object_get_hal(co); + if (hal == NULL) { + err("HAL is NULL"); + return ret; + } + dbg("hal: [%p]", hal); + + /* Create Pending Request */ + pending = tcore_pending_new(co, 0); + if (pending == NULL) { + err("Pending is NULL"); + return ret; + } + + /* Create AT-Command Request */ + at_req = tcore_at_request_new(cmd, prefix, type); + if (at_req == NULL) { + err("Request is NULL"); + + tcore_pending_free(pending); + return ret; + } + + tcore_pending_set_request_data(pending, 0, at_req); + tcore_pending_link_request(pending, request); + + tcore_pending_set_priority(pending, priority); + + tcore_pending_set_response_callback(pending, resp_cb, resp_cb_data); + tcore_pending_set_send_callback(pending, send_cb, send_cb_data); + + if (timeout > 0) + tcore_pending_set_timeout(pending, timeout); + tcore_pending_set_timeout_callback(pending, timeout_cb, timeout_cb_data); + + if (auto_free) + tcore_pending_set_auto_free_status_after_sent(pending, auto_free); + + if (abortable) + tcore_pending_set_abortable(pending, abortable); + + ret = tcore_hal_send_request(hal, pending); + dbg("ret: [0x%x]", ret); + + return ret; +} + diff --git a/src/queue.c b/src/queue.c index b286932..21ab861 100644 --- a/src/queue.c +++ b/src/queue.c @@ -54,6 +54,9 @@ struct tcore_pending_type { gboolean flag_received_response; /**< Received response: Response received from modem */ gboolean flag_auto_free_after_sent; /**< Auto free: Not expecting Response */ + /**< Abortable Request */ + gboolean abortable; + /**< Essential references */ void *request; TcorePlugin *plugin; @@ -272,6 +275,29 @@ gboolean tcore_pending_get_auto_free_status_after_sent(TcorePending *pending) return pending->flag_auto_free_after_sent; } +TelReturn tcore_pending_set_abortable(TcorePending *pending, + gboolean abortable) +{ + if (pending == NULL) { + err("pending is NULL"); + return TEL_RETURN_INVALID_PARAMETER; + } + + pending->abortable = abortable; + + return TEL_RETURN_SUCCESS; +} + +gboolean tcore_pending_get_abortable(TcorePending *pending) +{ + if (pending == NULL) { + err("pending is NULL"); + return FALSE; + } + + return pending->abortable; +} + TelReturn tcore_pending_set_request_data(TcorePending *pending, guint data_len, void *data) { @@ -606,6 +632,39 @@ TcorePending *tcore_queue_pop_by_pending(TcoreQueue *queue, return NULL; } +TcorePending *tcore_queue_pop_abortable_pending(TcoreQueue *queue) +{ + TcorePending *pending = NULL; + gint i = 0; + + if (queue == NULL) { + err("queue is NULL"); + return NULL; + } + + /* + * Scan through the list of 'pending' Requests and + * get the first Abortable Request + */ + do { + pending = g_queue_peek_nth(queue->gq, i); + if (pending == NULL) { + err("pending is NULL"); + return NULL; + } + else if (tcore_pending_get_abortable(pending) == TRUE) { + dbg("Found Abrotable 'pending' request: [%p]", pending); + + /* Pop the Abortable 'pending' Request */ + g_queue_pop_nth(queue->gq, i); + break; + } + + i++; + } while (pending != NULL); + + return pending; +} TcorePending *tcore_queue_pop_timeout_pending(TcoreQueue *queue) { guint i = 0; @@ -671,16 +730,6 @@ TcorePending *tcore_queue_pop_by_id(TcoreQueue *queue, guint id) return __queue_search_full(queue, id, 0, SEARCH_FIELD_ID_ALL, TRUE); } -TcorePending *tcore_queue_ref_pending_by_id(TcoreQueue *queue, guint id) -{ - if (queue == NULL) { - err("queue is NULL"); - return NULL; - } - - return __queue_search_full(queue, id, 0, SEARCH_FIELD_ID_ALL, FALSE); -} - TcorePending *tcore_queue_ref_next_pending(TcoreQueue *queue) { TcorePending *pending = NULL; @@ -718,6 +767,16 @@ TcorePending *tcore_queue_ref_next_pending(TcoreQueue *queue) return pending; } +TcorePending *tcore_queue_ref_pending_by_id(TcoreQueue *queue, guint id) +{ + if (queue == NULL) { + err("queue is NULL"); + return NULL; + } + + return __queue_search_full(queue, id, 0, SEARCH_FIELD_ID_ALL, FALSE); +} + guint tcore_queue_get_length(TcoreQueue *queue) { if (queue == NULL) { -- 2.7.4