port-serial-at: use GIO Async API like methods

This commit is contained in:
Aleksander Morgado
2013-11-17 01:11:12 +01:00
parent 81ee07832d
commit d4dfd661b9
10 changed files with 276 additions and 211 deletions

View File

@@ -76,25 +76,23 @@ cinterion_custom_init_finish (MMPortProbe *probe,
static void static void
sqport_ready (MMPortSerialAt *port, sqport_ready (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
CinterionCustomInitContext *ctx) CinterionCustomInitContext *ctx)
{ {
const gchar *response;
/* Ignore errors, just avoid tagging */ /* Ignore errors, just avoid tagging */
if (error) { response = mm_port_serial_at_command_finish (port, res, NULL);
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); if (response) {
cinterion_custom_init_context_complete_and_free (ctx); /* A valid reply to AT^SQPORT tells us this is an AT port already */
return; mm_port_probe_set_result_at (ctx->probe, TRUE);
if (strstr (response, "Application"))
g_object_set_data (G_OBJECT (ctx->probe), TAG_CINTERION_APP_PORT, GUINT_TO_POINTER (TRUE));
else if (strstr (response, "Modem"))
g_object_set_data (G_OBJECT (ctx->probe), TAG_CINTERION_MODEM_PORT, GUINT_TO_POINTER (TRUE));
} }
/* A valid reply to AT^SQPORT tells us this is an AT port already */
mm_port_probe_set_result_at (ctx->probe, TRUE);
if (strstr (response->str, "Application"))
g_object_set_data (G_OBJECT (ctx->probe), TAG_CINTERION_APP_PORT, GUINT_TO_POINTER (TRUE));
else if (strstr (response->str, "Modem"))
g_object_set_data (G_OBJECT (ctx->probe), TAG_CINTERION_MODEM_PORT, GUINT_TO_POINTER (TRUE));
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
cinterion_custom_init_context_complete_and_free (ctx); cinterion_custom_init_context_complete_and_free (ctx);
} }
@@ -117,13 +115,14 @@ cinterion_custom_init (MMPortProbe *probe,
ctx->port = g_object_ref (port); ctx->port = g_object_ref (port);
ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
mm_port_serial_at_queue_command ( mm_port_serial_at_command (
ctx->port, ctx->port,
"AT^SQPORT?", "AT^SQPORT?",
3, 3,
FALSE, /* raw */ FALSE, /* raw */
FALSE, /* allow cached */
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)sqport_ready, (GAsyncReadyCallback)sqport_ready,
ctx); ctx);
} }

View File

@@ -128,10 +128,13 @@ cache_port_mode (MMDevice *device,
static void static void
getportmode_ready (MMPortSerialAt *port, getportmode_ready (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
HuaweiCustomInitContext *ctx) HuaweiCustomInitContext *ctx)
{ {
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
if (error) { if (error) {
mm_dbg ("(Huawei) couldn't get port mode: '%s'", mm_dbg ("(Huawei) couldn't get port mode: '%s'",
error->message); error->message);
@@ -141,11 +144,8 @@ getportmode_ready (MMPortSerialAt *port,
*/ */
if (!g_error_matches (error, if (!g_error_matches (error,
MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN)) { MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN))
/* Retry */ goto out;
huawei_custom_init_step (ctx);
return;
}
/* Port mode not supported */ /* Port mode not supported */
} else { } else {
@@ -155,10 +155,10 @@ getportmode_ready (MMPortSerialAt *port,
/* Results are cached in the parent device object */ /* Results are cached in the parent device object */
device = mm_port_probe_peek_device (ctx->probe); device = mm_port_probe_peek_device (ctx->probe);
cache_port_mode (device, response->str, "PCUI:", TAG_HUAWEI_PCUI_PORT); cache_port_mode (device, response, "PCUI:", TAG_HUAWEI_PCUI_PORT);
cache_port_mode (device, response->str, "MDM:", TAG_HUAWEI_MODEM_PORT); cache_port_mode (device, response, "MDM:", TAG_HUAWEI_MODEM_PORT);
cache_port_mode (device, response->str, "NDIS:", TAG_HUAWEI_NDIS_PORT); cache_port_mode (device, response, "NDIS:", TAG_HUAWEI_NDIS_PORT);
cache_port_mode (device, response->str, "DIAG:", TAG_HUAWEI_DIAG_PORT); cache_port_mode (device, response, "DIAG:", TAG_HUAWEI_DIAG_PORT);
g_object_set_data (G_OBJECT (device), TAG_GETPORTMODE_SUPPORTED, GUINT_TO_POINTER (TRUE)); g_object_set_data (G_OBJECT (device), TAG_GETPORTMODE_SUPPORTED, GUINT_TO_POINTER (TRUE));
/* Mark port as being AT already */ /* Mark port as being AT already */
@@ -166,23 +166,29 @@ getportmode_ready (MMPortSerialAt *port,
} }
ctx->getportmode_done = TRUE; ctx->getportmode_done = TRUE;
out:
if (error)
g_error_free (error);
huawei_custom_init_step (ctx); huawei_custom_init_step (ctx);
} }
static void static void
curc_ready (MMPortSerialAt *port, curc_ready (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
HuaweiCustomInitContext *ctx) HuaweiCustomInitContext *ctx)
{ {
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
if (error) { if (error) {
/* Retry if we get a timeout error */ /* Retry if we get a timeout error */
if (g_error_matches (error, if (g_error_matches (error,
MM_SERIAL_ERROR, MM_SERIAL_ERROR,
MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { MM_SERIAL_ERROR_RESPONSE_TIMEOUT))
huawei_custom_init_step (ctx); goto out;
return;
}
mm_dbg ("(Huawei) couldn't turn off unsolicited messages in" mm_dbg ("(Huawei) couldn't turn off unsolicited messages in"
"secondary ports: '%s'", "secondary ports: '%s'",
@@ -192,6 +198,11 @@ curc_ready (MMPortSerialAt *port,
mm_dbg ("(Huawei) unsolicited messages in secondary ports turned off"); mm_dbg ("(Huawei) unsolicited messages in secondary ports turned off");
ctx->curc_done = TRUE; ctx->curc_done = TRUE;
out:
if (error)
g_error_free (error);
huawei_custom_init_step (ctx); huawei_custom_init_step (ctx);
} }
@@ -263,13 +274,14 @@ huawei_custom_init_step (HuaweiCustomInitContext *ctx)
ctx->curc_retries--; ctx->curc_retries--;
/* Turn off unsolicited messages on secondary ports until needed */ /* Turn off unsolicited messages on secondary ports until needed */
mm_port_serial_at_queue_command ( mm_port_serial_at_command (
ctx->port, ctx->port,
"AT^CURC=0", "AT^CURC=0",
3, 3,
FALSE, /* raw */ FALSE, /* raw */
FALSE, /* allow_cached */
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)curc_ready, (GAsyncReadyCallback)curc_ready,
ctx); ctx);
return; return;
} }
@@ -283,13 +295,14 @@ huawei_custom_init_step (HuaweiCustomInitContext *ctx)
} }
ctx->getportmode_retries--; ctx->getportmode_retries--;
mm_port_serial_at_queue_command ( mm_port_serial_at_command (
ctx->port, ctx->port,
"AT^GETPORTMODE", "AT^GETPORTMODE",
3, 3,
FALSE, /* raw */ FALSE, /* raw */
FALSE, /* allow_cached */
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)getportmode_ready, (GAsyncReadyCallback)getportmode_ready,
ctx); ctx);
return; return;
} }

View File

@@ -67,20 +67,22 @@ static void longcheer_custom_init_step (LongcheerCustomInitContext *ctx);
static void static void
gmr_ready (MMPortSerialAt *port, gmr_ready (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
LongcheerCustomInitContext *ctx) LongcheerCustomInitContext *ctx)
{ {
const gchar *p; const gchar *p;
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
if (error) { if (error) {
/* Just retry... */ /* Just retry... */
longcheer_custom_init_step (ctx); longcheer_custom_init_step (ctx);
return; goto out;
} }
/* Note the lack of a ':' on the GMR; the X200 doesn't send one */ /* Note the lack of a ':' on the GMR; the X200 doesn't send one */
p = mm_strip_tag (response->str, "AT+GMR"); p = mm_strip_tag (response, "AT+GMR");
if (p && *p == 'L') { if (p && *p == 'L') {
/* X200 modems have a GMR firmware revision that starts with 'L', and /* X200 modems have a GMR firmware revision that starts with 'L', and
* as far as I can tell X060s devices have a revision starting with 'C'. * as far as I can tell X060s devices have a revision starting with 'C'.
@@ -98,6 +100,10 @@ gmr_ready (MMPortSerialAt *port,
} }
longcheer_custom_init_context_complete_and_free (ctx); longcheer_custom_init_context_complete_and_free (ctx);
out:
if (error)
g_error_free (error);
} }
static void static void
@@ -124,13 +130,14 @@ longcheer_custom_init_step (LongcheerCustomInitContext *ctx)
} }
ctx->retries--; ctx->retries--;
mm_port_serial_at_queue_command ( mm_port_serial_at_command (
ctx->port, ctx->port,
"AT+GMR", "AT+GMR",
3, 3,
FALSE, /* raw */ FALSE, /* raw */
FALSE, /* allow_cached */
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)gmr_ready, (GAsyncReadyCallback)gmr_ready,
ctx); ctx);
} }

View File

@@ -91,16 +91,19 @@ static void custom_init_step (CustomInitContext *ctx);
static void static void
nwdmat_ready (MMPortSerialAt *port, nwdmat_ready (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
CustomInitContext *ctx) CustomInitContext *ctx)
{ {
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
if (error) { if (error) {
if (g_error_matches (error, if (g_error_matches (error,
MM_SERIAL_ERROR, MM_SERIAL_ERROR,
MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) { MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) {
custom_init_step (ctx); custom_init_step (ctx);
return; goto out;
} }
mm_dbg ("(Novatel) Error flipping secondary ports to AT mode: %s", error->message); mm_dbg ("(Novatel) Error flipping secondary ports to AT mode: %s", error->message);
@@ -109,6 +112,10 @@ nwdmat_ready (MMPortSerialAt *port,
/* Finish custom_init */ /* Finish custom_init */
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
custom_init_context_complete_and_free (ctx); custom_init_context_complete_and_free (ctx);
out:
if (error)
g_error_free (error);
} }
static gboolean static gboolean
@@ -147,13 +154,14 @@ custom_init_step (CustomInitContext *ctx)
if (ctx->nwdmat_retries > 0) { if (ctx->nwdmat_retries > 0) {
ctx->nwdmat_retries--; ctx->nwdmat_retries--;
mm_port_serial_at_queue_command (ctx->port, mm_port_serial_at_command (ctx->port,
"$NWDMAT=1", "$NWDMAT=1",
3, 3,
FALSE, /* raw */ FALSE, /* raw */
ctx->cancellable, FALSE, /* allow_cached */
(MMPortSerialAtResponseFn)nwdmat_ready, ctx->cancellable,
ctx); (GAsyncReadyCallback)nwdmat_ready,
ctx);
return; return;
} }

View File

@@ -79,10 +79,13 @@ static void sierra_custom_init_step (SierraCustomInitContext *ctx);
static void static void
gcap_ready (MMPortSerialAt *port, gcap_ready (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
SierraCustomInitContext *ctx) SierraCustomInitContext *ctx)
{ {
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
if (error) { if (error) {
/* If consumed all tries and the last error was a timeout, assume the /* If consumed all tries and the last error was a timeout, assume the
* port is not AT */ * port is not AT */
@@ -106,7 +109,7 @@ gcap_ready (MMPortSerialAt *port,
/* Just retry... */ /* Just retry... */
sierra_custom_init_step (ctx); sierra_custom_init_step (ctx);
return; goto out;
} }
/* A valid reply to ATI tells us this is an AT port already */ /* A valid reply to ATI tells us this is an AT port already */
@@ -118,23 +121,25 @@ gcap_ready (MMPortSerialAt *port,
* or fail PPP. So we whitelist modems that are known to allow PPP on the * or fail PPP. So we whitelist modems that are known to allow PPP on the
* secondary APP ports. * secondary APP ports.
*/ */
if (strstr (response->str, "APP1")) { if (strstr (response, "APP1")) {
g_object_set_data (G_OBJECT (ctx->probe), TAG_SIERRA_APP_PORT, GUINT_TO_POINTER (TRUE)); g_object_set_data (G_OBJECT (ctx->probe), TAG_SIERRA_APP_PORT, GUINT_TO_POINTER (TRUE));
/* PPP-on-APP1-port whitelist */ /* PPP-on-APP1-port whitelist */
if (strstr (response->str, "C885") || strstr (response->str, "USB 306") || strstr (response->str, "MC8790")) if (strstr (response, "C885") ||
strstr (response, "USB 306") ||
strstr (response, "MC8790"))
g_object_set_data (G_OBJECT (ctx->probe), TAG_SIERRA_APP1_PPP_OK, GUINT_TO_POINTER (TRUE)); g_object_set_data (G_OBJECT (ctx->probe), TAG_SIERRA_APP1_PPP_OK, GUINT_TO_POINTER (TRUE));
/* For debugging: let users figure out if their device supports PPP /* For debugging: let users figure out if their device supports PPP
* on the APP1 port or not. * on the APP1 port or not.
*/ */
if (getenv ("MM_SIERRA_APP1_PPP_OK")) { if (getenv ("MM_SIERRA_APP1_PPP_OK")) {
mm_dbg ("Sierra: APP1 PPP OK '%s'", response->str); mm_dbg ("Sierra: APP1 PPP OK '%s'", response);
g_object_set_data (G_OBJECT (ctx->probe), TAG_SIERRA_APP1_PPP_OK, GUINT_TO_POINTER (TRUE)); g_object_set_data (G_OBJECT (ctx->probe), TAG_SIERRA_APP1_PPP_OK, GUINT_TO_POINTER (TRUE));
} }
} else if (strstr (response->str, "APP2") || } else if (strstr (response, "APP2") ||
strstr (response->str, "APP3") || strstr (response, "APP3") ||
strstr (response->str, "APP4")) { strstr (response, "APP4")) {
/* Additional APP ports don't support most AT commands, so they cannot /* Additional APP ports don't support most AT commands, so they cannot
* be used as the primary port. * be used as the primary port.
*/ */
@@ -143,6 +148,10 @@ gcap_ready (MMPortSerialAt *port,
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
sierra_custom_init_context_complete_and_free (ctx); sierra_custom_init_context_complete_and_free (ctx);
out:
if (error)
g_error_free (error);
} }
static void static void
@@ -166,13 +175,14 @@ sierra_custom_init_step (SierraCustomInitContext *ctx)
} }
ctx->retries--; ctx->retries--;
mm_port_serial_at_queue_command ( mm_port_serial_at_command (
ctx->port, ctx->port,
"ATI", "ATI",
3, 3,
FALSE, /* raw */ FALSE, /* raw */
FALSE, /* allow_cached */
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)gcap_ready, (GAsyncReadyCallback)gcap_ready,
ctx); ctx);
} }

View File

@@ -71,20 +71,22 @@ static void x22x_custom_init_step (X22xCustomInitContext *ctx);
static void static void
gmr_ready (MMPortSerialAt *port, gmr_ready (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
X22xCustomInitContext *ctx) X22xCustomInitContext *ctx)
{ {
const gchar *p; const gchar *p;
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
if (error) { if (error) {
/* Just retry... */ /* Just retry... */
x22x_custom_init_step (ctx); x22x_custom_init_step (ctx);
return; goto out;
} }
/* Note the lack of a ':' on the GMR; the X200 doesn't send one */ /* Note the lack of a ':' on the GMR; the X200 doesn't send one */
p = mm_strip_tag (response->str, "AT+GMR"); p = mm_strip_tag (response, "AT+GMR");
if (p && *p != 'L') { if (p && *p != 'L') {
/* X200 modems have a GMR firmware revision that starts with 'L', and /* X200 modems have a GMR firmware revision that starts with 'L', and
* as far as I can tell X060s devices have a revision starting with 'C'. * as far as I can tell X060s devices have a revision starting with 'C'.
@@ -101,6 +103,10 @@ gmr_ready (MMPortSerialAt *port,
} }
x22x_custom_init_context_complete_and_free (ctx); x22x_custom_init_context_complete_and_free (ctx);
out:
if (error)
g_error_free (error);
} }
static void static void
@@ -127,13 +133,14 @@ x22x_custom_init_step (X22xCustomInitContext *ctx)
} }
ctx->retries--; ctx->retries--;
mm_port_serial_at_queue_command ( mm_port_serial_at_command (
ctx->port, ctx->port,
"AT+GMR", "AT+GMR",
3, 3,
FALSE, /* raw */ FALSE, /* raw */
FALSE, /* allow_cached */
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)gmr_ready, (GAsyncReadyCallback)gmr_ready,
ctx); ctx);
} }

View File

@@ -154,14 +154,17 @@ mm_base_modem_at_sequence_full_finish (MMBaseModem *self,
static void static void
at_sequence_parse_response (MMPortSerialAt *port, at_sequence_parse_response (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
AtSequenceContext *ctx) AtSequenceContext *ctx)
{ {
GVariant *result = NULL; GVariant *result = NULL;
GError *result_error = NULL; GError *result_error = NULL;
gboolean continue_sequence; gboolean continue_sequence;
GSimpleAsyncResult *simple; GSimpleAsyncResult *simple;
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
/* Cancelled? */ /* Cancelled? */
if (g_cancellable_is_cancelled (ctx->cancellable)) { if (g_cancellable_is_cancelled (ctx->cancellable)) {
@@ -169,6 +172,8 @@ at_sequence_parse_response (MMPortSerialAt *port,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_CANCELLED, MM_CORE_ERROR_CANCELLED,
"AT sequence was cancelled"); "AT sequence was cancelled");
if (error)
g_error_free (error);
g_simple_async_result_complete (ctx->simple); g_simple_async_result_complete (ctx->simple);
at_sequence_context_free (ctx); at_sequence_context_free (ctx);
return; return;
@@ -185,7 +190,7 @@ at_sequence_parse_response (MMPortSerialAt *port,
ctx->self, ctx->self,
ctx->response_processor_context, ctx->response_processor_context,
ctx->current->command, ctx->current->command,
response ? response->str : NULL, response,
next->command ? FALSE : TRUE, /* Last command in sequence? */ next->command ? FALSE : TRUE, /* Last command in sequence? */
error, error,
&result, &result,
@@ -196,33 +201,29 @@ at_sequence_parse_response (MMPortSerialAt *port,
g_simple_async_result_take_error (ctx->simple, result_error); g_simple_async_result_take_error (ctx->simple, result_error);
g_simple_async_result_complete (ctx->simple); g_simple_async_result_complete (ctx->simple);
at_sequence_context_free (ctx); at_sequence_context_free (ctx);
if (error)
g_error_free (error);
return; return;
} }
} }
if (error)
g_error_free (error);
if (continue_sequence) { if (continue_sequence) {
g_assert (result == NULL); g_assert (result == NULL);
ctx->current++; ctx->current++;
if (ctx->current->command) { if (ctx->current->command) {
/* Schedule the next command in the probing group */ /* Schedule the next command in the probing group */
if (ctx->current->allow_cached) mm_port_serial_at_command (
mm_port_serial_at_queue_command_cached ( ctx->port,
ctx->port, ctx->current->command,
ctx->current->command, ctx->current->timeout,
ctx->current->timeout, FALSE,
FALSE, ctx->current->allow_cached,
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)at_sequence_parse_response, (GAsyncReadyCallback)at_sequence_parse_response,
ctx); ctx);
else
mm_port_serial_at_queue_command (
ctx->port,
ctx->current->command,
ctx->current->timeout,
FALSE,
ctx->cancellable,
(MMPortSerialAtResponseFn)at_sequence_parse_response,
ctx);
return; return;
} }
@@ -295,13 +296,14 @@ mm_base_modem_at_sequence_full (MMBaseModem *self,
} }
/* Go on with the first one in the sequence */ /* Go on with the first one in the sequence */
mm_port_serial_at_queue_command ( mm_port_serial_at_command (
ctx->port, ctx->port,
ctx->current->command, ctx->current->command,
ctx->current->timeout, ctx->current->timeout,
FALSE, FALSE,
FALSE,
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)at_sequence_parse_response, (GAsyncReadyCallback)at_sequence_parse_response,
ctx); ctx);
} }
@@ -470,32 +472,34 @@ mm_base_modem_at_command_full_finish (MMBaseModem *self,
} }
static void static void
at_command_parse_response (MMPortSerialAt *port, at_command_ready (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error, AtCommandContext *ctx)
AtCommandContext *ctx)
{ {
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
/* Cancelled? */ /* Cancelled? */
if (g_cancellable_is_cancelled (ctx->cancellable)) if (g_cancellable_is_cancelled (ctx->cancellable)) {
g_simple_async_result_set_error (ctx->result, g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR, MM_CORE_ERROR,
MM_CORE_ERROR_CANCELLED, MM_CORE_ERROR_CANCELLED,
"AT command was cancelled"); "AT command was cancelled");
if (error)
g_error_free (error);
}
/* Error coming from the serial port? */ /* Error coming from the serial port? */
else if (error) else if (error)
g_simple_async_result_set_from_error (ctx->result, error); g_simple_async_result_take_error (ctx->result, error);
/* Valid string response */ /* Valid string response */
else if (response && response->str) else if (response)
g_simple_async_result_set_op_res_gpointer (ctx->result, g_simple_async_result_set_op_res_gpointer (ctx->result, (gchar *)response, NULL);
g_strdup (response->str),
g_free);
/* No response */
else else
g_simple_async_result_set_op_res_gpointer (ctx->result, NULL, NULL); g_assert_not_reached ();
/* Never in idle! */
g_simple_async_result_complete (ctx->result); g_simple_async_result_complete (ctx->result);
at_command_context_free (ctx); at_command_context_free (ctx);
} }
@@ -542,24 +546,15 @@ mm_base_modem_at_command_full (MMBaseModem *self,
} }
/* Go on with the command */ /* Go on with the command */
if (allow_cached) mm_port_serial_at_command (
mm_port_serial_at_queue_command_cached ( port,
port, command,
command, timeout,
timeout, is_raw,
is_raw, allow_cached,
ctx->cancellable, ctx->cancellable,
(MMPortSerialAtResponseFn)at_command_parse_response, (GAsyncReadyCallback)at_command_ready,
ctx); ctx);
else
mm_port_serial_at_queue_command (
port,
command,
timeout,
is_raw,
ctx->cancellable,
(MMPortSerialAtResponseFn)at_command_parse_response,
ctx);
} }
const gchar * const gchar *

View File

@@ -865,17 +865,20 @@ serial_probe_at_result_processor (MMPortProbe *self,
static void static void
serial_probe_at_parse_response (MMPortSerialAt *port, serial_probe_at_parse_response (MMPortSerialAt *port,
GString *response, GAsyncResult *res,
GError *error,
MMPortProbe *self) MMPortProbe *self)
{ {
PortProbeRunTask *task = self->priv->task; PortProbeRunTask *task = self->priv->task;
GVariant *result = NULL; GVariant *result = NULL;
GError *result_error = NULL; GError *result_error = NULL;
const gchar *response;
GError *error = NULL;
response = mm_port_serial_at_command_finish (port, res, &error);
/* If already cancelled, do nothing else */ /* If already cancelled, do nothing else */
if (port_probe_run_is_cancelled (self)) if (port_probe_run_is_cancelled (self))
return; goto out;
/* If AT probing cancelled, end this partial probing */ /* If AT probing cancelled, end this partial probing */
if (g_cancellable_is_cancelled (task->at_probing_cancellable)) { if (g_cancellable_is_cancelled (task->at_probing_cancellable)) {
@@ -884,11 +887,11 @@ serial_probe_at_parse_response (MMPortSerialAt *port,
g_udev_device_get_name (self->priv->port)); g_udev_device_get_name (self->priv->port));
task->at_result_processor (self, NULL); task->at_result_processor (self, NULL);
serial_probe_schedule (self); serial_probe_schedule (self);
return; goto out;
} }
if (!task->at_commands->response_processor (task->at_commands->command, if (!task->at_commands->response_processor (task->at_commands->command,
response ? response->str : NULL, response,
!!task->at_commands[1].command, !!task->at_commands[1].command,
error, error,
&result, &result,
@@ -904,8 +907,7 @@ serial_probe_at_parse_response (MMPortSerialAt *port,
g_udev_device_get_subsystem (self->priv->port), g_udev_device_get_subsystem (self->priv->port),
g_udev_device_get_name (self->priv->port), g_udev_device_get_name (self->priv->port),
result_error->message)); result_error->message));
g_error_free (result_error); goto out;
return;
} }
/* Go on to next command */ /* Go on to next command */
@@ -916,22 +918,28 @@ serial_probe_at_parse_response (MMPortSerialAt *port,
task->at_result_processor (self, NULL); task->at_result_processor (self, NULL);
/* Reschedule */ /* Reschedule */
serial_probe_schedule (self); serial_probe_schedule (self);
return; goto out;
} }
/* Schedule the next command in the probing group */ /* Schedule the next command in the probing group */
task->source_id = g_idle_add ((GSourceFunc)serial_probe_at, self); task->source_id = g_idle_add ((GSourceFunc)serial_probe_at, self);
return; goto out;
} }
/* Run result processor. /* Run result processor.
* Note that custom init commands are allowed to not return anything */ * Note that custom init commands are allowed to not return anything */
task->at_result_processor (self, result); task->at_result_processor (self, result);
if (result)
g_variant_unref (result);
/* Reschedule probing */ /* Reschedule probing */
serial_probe_schedule (self); serial_probe_schedule (self);
out:
if (result)
g_variant_unref (result);
if (error)
g_error_free (error);
if (result_error)
g_error_free (result_error);
} }
static gboolean static gboolean
@@ -955,13 +963,14 @@ serial_probe_at (MMPortProbe *self)
return FALSE; return FALSE;
} }
mm_port_serial_at_queue_command ( mm_port_serial_at_command (
MM_PORT_SERIAL_AT (task->serial), MM_PORT_SERIAL_AT (task->serial),
task->at_commands->command, task->at_commands->command,
task->at_commands->timeout, task->at_commands->timeout,
FALSE, FALSE,
FALSE,
task->at_probing_cancellable, task->at_probing_cancellable,
(MMPortSerialAtResponseFn)serial_probe_at_parse_response, (GAsyncReadyCallback)serial_probe_at_parse_response,
self); self);
return FALSE; return FALSE;
} }

View File

@@ -158,16 +158,9 @@ handle_response (MMPortSerial *port,
GCallback callback, GCallback callback,
gpointer callback_data) gpointer callback_data)
{ {
MMPortSerialAt *self = MM_PORT_SERIAL_AT (port); MMSerialResponseFn response_callback = (MMSerialResponseFn) callback;
MMPortSerialAtResponseFn response_callback = (MMPortSerialAtResponseFn) callback;
GString *string;
/* Convert to a string and call the callback */
string = g_string_sized_new (response->len + 1);
g_string_append_len (string, (const char *) response->data, response->len);
response_callback (self, string, error, callback_data);
g_string_free (string, TRUE);
response_callback (port, response, error, callback_data);
return response->len; return response->len;
} }
@@ -350,43 +343,61 @@ at_command_to_byte_array (const char *command, gboolean is_raw, gboolean send_lf
return buf; return buf;
} }
void const gchar *
mm_port_serial_at_queue_command (MMPortSerialAt *self, mm_port_serial_at_command_finish (MMPortSerialAt *self,
const char *command, GAsyncResult *res,
guint32 timeout_seconds, GError **error)
gboolean is_raw,
GCancellable *cancellable,
MMPortSerialAtResponseFn callback,
gpointer user_data)
{ {
GByteArray *buf; GString *str;
MMPortSerialAtPrivate *priv = MM_PORT_SERIAL_AT_GET_PRIVATE (self);
g_return_if_fail (self != NULL); if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
g_return_if_fail (MM_IS_PORT_SERIAL_AT (self)); return NULL;
g_return_if_fail (command != NULL);
buf = at_command_to_byte_array (command, is_raw, priv->send_lf); str = (GString *)g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
g_return_if_fail (buf != NULL); return str->str;
}
mm_port_serial_queue_command (MM_PORT_SERIAL (self), static void
buf, string_free (GString *str)
TRUE, {
timeout_seconds, g_string_free (str, TRUE);
cancellable, }
(MMSerialResponseFn) callback,
user_data); static void
serial_command_ready (MMPortSerial *port,
GByteArray *response,
GError *error,
GSimpleAsyncResult *simple)
{
if (error)
g_simple_async_result_set_from_error (simple, error);
else if (response) {
GString *str;
/* Build a GString just with the response we need, and clear the
* processed range from the response buffer */
str = g_string_new_len ((const gchar *)response->data, response->len);
g_simple_async_result_set_op_res_gpointer (simple,
str,
(GDestroyNotify)string_free);
} else
g_assert_not_reached ();
g_simple_async_result_complete (simple);
g_object_unref (simple);
} }
void void
mm_port_serial_at_queue_command_cached (MMPortSerialAt *self, mm_port_serial_at_command (MMPortSerialAt *self,
const char *command, const char *command,
guint32 timeout_seconds, guint32 timeout_seconds,
gboolean is_raw, gboolean is_raw,
GCancellable *cancellable, gboolean allow_cached,
MMPortSerialAtResponseFn callback, GCancellable *cancellable,
gpointer user_data) GAsyncReadyCallback callback,
gpointer user_data)
{ {
GSimpleAsyncResult *simple;
GByteArray *buf; GByteArray *buf;
MMPortSerialAtPrivate *priv = MM_PORT_SERIAL_AT_GET_PRIVATE (self); MMPortSerialAtPrivate *priv = MM_PORT_SERIAL_AT_GET_PRIVATE (self);
@@ -397,13 +408,27 @@ mm_port_serial_at_queue_command_cached (MMPortSerialAt *self,
buf = at_command_to_byte_array (command, is_raw, priv->send_lf); buf = at_command_to_byte_array (command, is_raw, priv->send_lf);
g_return_if_fail (buf != NULL); g_return_if_fail (buf != NULL);
mm_port_serial_queue_command_cached (MM_PORT_SERIAL (self), simple = g_simple_async_result_new (G_OBJECT (self),
buf, callback,
TRUE, user_data,
timeout_seconds, mm_port_serial_at_command);
cancellable,
(MMSerialResponseFn) callback, if (!allow_cached)
user_data); mm_port_serial_queue_command (MM_PORT_SERIAL (self),
buf,
TRUE,
timeout_seconds,
cancellable,
(MMSerialResponseFn)serial_command_ready,
simple);
else
mm_port_serial_queue_command_cached (MM_PORT_SERIAL (self),
buf,
TRUE,
timeout_seconds,
cancellable,
(MMSerialResponseFn)serial_command_ready,
simple);
} }
static void static void
@@ -474,13 +499,14 @@ mm_port_serial_at_run_init_sequence (MMPortSerialAt *self)
/* Just queue the init commands, don't wait for reply */ /* Just queue the init commands, don't wait for reply */
for (i = 0; priv->init_sequence[i]; i++) { for (i = 0; priv->init_sequence[i]; i++) {
mm_port_serial_at_queue_command (self, mm_port_serial_at_command (self,
priv->init_sequence[i], priv->init_sequence[i],
3, 3,
FALSE, FALSE,
NULL, FALSE,
NULL, NULL,
NULL); NULL,
NULL);
} }
} }

View File

@@ -60,11 +60,6 @@ typedef void (*MMPortSerialAtUnsolicitedMsgFn) (MMPortSerialAt *port,
GMatchInfo *match_info, GMatchInfo *match_info,
gpointer user_data); gpointer user_data);
typedef void (*MMPortSerialAtResponseFn) (MMPortSerialAt *port,
GString *response,
GError *error,
gpointer user_data);
#define MM_PORT_SERIAL_AT_REMOVE_ECHO "remove-echo" #define MM_PORT_SERIAL_AT_REMOVE_ECHO "remove-echo"
#define MM_PORT_SERIAL_AT_INIT_SEQUENCE_ENABLED "init-sequence-enabled" #define MM_PORT_SERIAL_AT_INIT_SEQUENCE_ENABLED "init-sequence-enabled"
#define MM_PORT_SERIAL_AT_INIT_SEQUENCE "init-sequence" #define MM_PORT_SERIAL_AT_INIT_SEQUENCE "init-sequence"
@@ -97,21 +92,17 @@ void mm_port_serial_at_set_response_parser (MMPortSerialAt *self,
gpointer user_data, gpointer user_data,
GDestroyNotify notify); GDestroyNotify notify);
void mm_port_serial_at_queue_command (MMPortSerialAt *self, void mm_port_serial_at_command (MMPortSerialAt *self,
const char *command, const char *command,
guint32 timeout_seconds, guint32 timeout_seconds,
gboolean is_raw, gboolean is_raw,
GCancellable *cancellable, gboolean allow_cached,
MMPortSerialAtResponseFn callback, GCancellable *cancellable,
gpointer user_data); GAsyncReadyCallback callback,
gpointer user_data);
void mm_port_serial_at_queue_command_cached (MMPortSerialAt *self, const gchar *mm_port_serial_at_command_finish (MMPortSerialAt *self,
const char *command, GAsyncResult *res,
guint32 timeout_seconds, GError **error);
gboolean is_raw,
GCancellable *cancellable,
MMPortSerialAtResponseFn callback,
gpointer user_data);
/* /*
* Convert a string into a quoted and escaped string. Returns a new * Convert a string into a quoted and escaped string. Returns a new