aboutsummaryrefslogtreecommitdiff
path: root/src/mm-qcdm-serial-port.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-qcdm-serial-port.c')
-rw-r--r--src/mm-qcdm-serial-port.c134
1 files changed, 85 insertions, 49 deletions
diff --git a/src/mm-qcdm-serial-port.c b/src/mm-qcdm-serial-port.c
index 1ce27e7..e467f2a 100644
--- a/src/mm-qcdm-serial-port.c
+++ b/src/mm-qcdm-serial-port.c
@@ -21,9 +21,9 @@
#include "mm-qcdm-serial-port.h"
#include "mm-errors.h"
-#include "mm-options.h"
#include "libqcdm/src/com.h"
#include "libqcdm/src/utils.h"
+#include "mm-log.h"
G_DEFINE_TYPE (MMQcdmSerialPort, mm_qcdm_serial_port, MM_TYPE_SERIAL_PORT)
@@ -37,22 +37,38 @@ typedef struct {
/*****************************************************************************/
static gboolean
-parse_response (MMSerialPort *port, GByteArray *response, GError **error)
+find_qcdm_start (GByteArray *response, gsize *start)
{
- int i;
+ int i, last = -1;
- /* Look for the QCDM packet termination character; if we found it, treat
- * the buffer as a qcdm command.
+ /* Look for 3 bytes and a QCDM frame marker, ie enough data for a valid
+ * frame. There will usually be three cases here; (1) a QCDM frame
+ * starting with data and terminated by 0x7E, and (2) a QCDM frame starting
+ * with 0x7E and ending with 0x7E, and (3) a non-QCDM frame that still
+ * uses HDLC framing (like Sierra CnS) that starts and ends with 0x7E.
*/
for (i = 0; i < response->len; i++) {
- if (response->data[i] == 0x7E)
- return TRUE;
+ if (response->data[i] == 0x7E) {
+ if (i > last + 3) {
+ /* Got a full QCDM frame; 3 non-0x7E bytes and a terminator */
+ if (start)
+ *start = last + 1;
+ return TRUE;
+ }
+
+ /* Save position of the last QCDM frame marker */
+ last = i;
+ }
}
-
- /* Otherwise, need more data from the device */
return FALSE;
}
+static gboolean
+parse_response (MMSerialPort *port, GByteArray *response, GError **error)
+{
+ return find_qcdm_start (response, NULL);
+}
+
static gsize
handle_response (MMSerialPort *port,
GByteArray *response,
@@ -64,41 +80,49 @@ handle_response (MMSerialPort *port,
GByteArray *unescaped = NULL;
GError *dm_error = NULL;
gsize used = 0;
+ gsize start = 0;
+ gboolean success = FALSE, more = FALSE;
+ gsize unescaped_len = 0;
+
+ if (error)
+ goto callback;
+
+ /* Get the offset into the buffer of where the QCDM frame starts */
+ if (!find_qcdm_start (response, &start)) {
+ g_set_error_literal (&dm_error,
+ MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Failed to parse QCDM packet.");
+ /* Discard the unparsable data */
+ used = response->len;
+ goto callback;
+ }
- /* Ignore empty frames */
- if (response->len > 0 && response->data[0] == 0x7E)
- return 1;
-
- if (!error) {
- gboolean more = FALSE, success;
- gsize unescaped_len = 0;
-
- /* FIXME: don't munge around with byte array internals */
- unescaped = g_byte_array_sized_new (1024);
- success = dm_decapsulate_buffer ((const char *) response->data,
- response->len,
- (char *) unescaped->data,
- 1024,
- &unescaped_len,
- &used,
- &more);
- if (!success) {
- g_set_error_literal (&dm_error,
- MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Failed to unescape QCDM packet.");
- g_byte_array_free (unescaped, TRUE);
- unescaped = NULL;
- } else if (more) {
- /* Need more data; we shouldn't have gotten here since the parse
- * function checks for the end-of-frame marker, but whatever.
- */
- return 0;
- } else {
- /* Successfully decapsulated the DM command */
- unescaped->len = (guint) unescaped_len;
- }
+ /* FIXME: don't munge around with byte array internals */
+ unescaped = g_byte_array_sized_new (1024);
+ success = dm_decapsulate_buffer ((const char *) (response->data + start),
+ response->len - start,
+ (char *) unescaped->data,
+ 1024,
+ &unescaped_len,
+ &used,
+ &more);
+ if (!success) {
+ g_set_error_literal (&dm_error,
+ MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Failed to unescape QCDM packet.");
+ g_byte_array_free (unescaped, TRUE);
+ unescaped = NULL;
+ } else if (more) {
+ /* Need more data; we shouldn't have gotten here since the parse
+ * function checks for the end-of-frame marker, but whatever.
+ */
+ return 0;
+ } else {
+ /* Successfully decapsulated the DM command */
+ unescaped->len = (guint) unescaped_len;
}
+callback:
response_callback (MM_QCDM_SERIAL_PORT (port),
unescaped,
dm_error ? dm_error : error,
@@ -106,8 +130,9 @@ handle_response (MMSerialPort *port,
if (unescaped)
g_byte_array_free (unescaped, TRUE);
+ g_clear_error (&dm_error);
- return used;
+ return start + used;
}
/*****************************************************************************/
@@ -157,7 +182,6 @@ debug_log (MMSerialPort *port, const char *prefix, const char *buf, gsize len)
{
static GString *debug = NULL;
const char *s = buf;
- GTimeVal tv;
if (!debug)
debug = g_string_sized_new (512);
@@ -167,12 +191,7 @@ debug_log (MMSerialPort *port, const char *prefix, const char *buf, gsize len)
while (len--)
g_string_append_printf (debug, " %02x", (guint8) (*s++ & 0xFF));
- g_get_current_time (&tv);
- g_debug ("<%ld.%ld> (%s): %s",
- tv.tv_sec,
- tv.tv_usec,
- mm_port_get_device (MM_PORT (port)),
- debug->str);
+ mm_dbg ("(%s): %s", mm_port_get_device (MM_PORT (port)), debug->str);
g_string_truncate (debug, 0);
}
@@ -196,6 +215,23 @@ mm_qcdm_serial_port_new (const char *name, MMPortType ptype)
NULL));
}
+MMQcdmSerialPort *
+mm_qcdm_serial_port_new_fd (int fd, MMPortType ptype)
+{
+ MMQcdmSerialPort *port;
+ char *name;
+
+ name = g_strdup_printf ("port%d", fd);
+ port = MM_QCDM_SERIAL_PORT (g_object_new (MM_TYPE_QCDM_SERIAL_PORT,
+ MM_PORT_DEVICE, name,
+ MM_PORT_SUBSYS, MM_PORT_SUBSYS_TTY,
+ MM_PORT_TYPE, ptype,
+ MM_SERIAL_PORT_FD, fd,
+ NULL));
+ g_free (name);
+ return port;
+}
+
static void
mm_qcdm_serial_port_init (MMQcdmSerialPort *self)
{