:: Re: [maemo-leste] Grand plan to get…
Top Page
Delete this message
Reply to this message
Author: Tony Lindgren
Date:  
To: Pavel Machek
CC: maemo-leste, nekit1000, martin_rysavy, mpartap, sre
Subject: Re: [maemo-leste] Grand plan to get make phones... phone (for Motorola Droid 4)
* Tony Lindgren <tony@???> [200509 20:42]:
> Below are the initial v5.7 kernel based branches at [0][1][2][3][4].
>
> We now use the generic serdev-ngsm driver with the standard /dev/gsmtty*
> devices spun up by n_gsm instead of the custom /dev/motmdm* devices like
> we did earlier. This means all the commands must prefix the Motorola
> custom packet ID to the commands like:
>
> printf "U1234AT+CFUN?\r" > /dev/gsmtty1


I got the minimal ofono updates done for serdev-ngsm and pushed out the
changes into a new branc motmdm-serdev-ngsm on github at [5] below.

I ended up adding few more gatchat patches. It's still unsure if we
end up using any of those, that depends on the outcome of Pavel's work.
Anyways, the current gatchat related commits are now:

419b63fdc93b ("gatchat: Allow configuring a custom header length")
ba17d8002edf ("gatsyntax: Add handling for Motorola custom line header")
1049763ffd3e ("gatchat: Add support for optional terminator delimiter")
8ecd26be270e ("atutil: Handle custom suffix for OK on motorolamodem")

The rest of the code is pretty much the same as in the earlier
motmdm branch. I squashed the earlier bug fixes into the commits
adding motmdm support though.

The diff between motmdm..motmdm-serdev-ngsm branches is below for
reference.

Regards,

Tony

> droid4 kernel with serdev-ngsm patches (using /dev/gsmtty* instead of /dev/motmdm*):
> [0] git://git.kernel.org:/pub/scm/linux/kernel/git/tmlind/linux-omap droid4-pending-v5.7
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git/log/?h=droid4-pending-v5.7
>
> pvr hacks that ca be merged into droid4-pending-v5.7
> [2] https://github.com/tmlind/linux_openpvrsgx/tree/letux-pvrsrvkm-5.7-rc1-ddk-1.9.2253347-omapdrm-hacks
>
> serdev-ngsm patches only (not typically needed, already droid4-pending-v5.7)
> [3] git://git.kernel.org:/pub/scm/linux/kernel/git/tmlind/linux-omap serdev-ngsm-pending-v5.7
> [4] https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git/log/?h=serdev-ngsm-pending-v5.7


[5] https://github.com/tmlind/ofono/tree/motmdm-serdev-ngsm

8< ----------------------
diff --git a/drivers/motorolamodem/motorolamodem.c b/drivers/motorolamodem/motorolamodem.c
--- a/drivers/motorolamodem/motorolamodem.c
+++ b/drivers/motorolamodem/motorolamodem.c
@@ -25,6 +25,9 @@

#include <glib.h>
#include <gatchat.h>
+#include <stdio.h>
+
+#include <sys/time.h>

#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
@@ -32,6 +35,22 @@

#include "motorolamodem.h"

+guint mot_at_chat_send(GAtChat *chat, const char *cmd,
+                const char **valid_resp, GAtResultFunc func,
+                gpointer user_data, GDestroyNotify notify)
+{
+    struct timeval now;
+    char buf[256];
+    uint16_t id;
+
+    gettimeofday(&now, NULL);
+    id = (now.tv_sec % 100) * 100;
+    id += (now.tv_usec / 1000) / 10;
+    snprintf(buf, sizeof(buf), "U%04u%s", id, cmd);
+
+    return g_at_chat_send(chat, buf, valid_resp, func, user_data, notify);
+}
+
 static int motorolamodem_init(void)
 {
     motorola_voicecall_init();
diff --git a/drivers/motorolamodem/motorolamodem.h b/drivers/motorolamodem/motorolamodem.h
--- a/drivers/motorolamodem/motorolamodem.h
+++ b/drivers/motorolamodem/motorolamodem.h
@@ -22,6 +22,10 @@
 extern void motorola_voicecall_init(void);
 extern void motorola_voicecall_exit(void);


+extern guint mot_at_chat_send(GAtChat *chat, const char *cmd,
+                const char **valid_resp, GAtResultFunc func,
+                gpointer user_data, GDestroyNotify notify);
+
 extern void motorola_sms_init(void);
 extern void motorola_sms_exit(void);


diff --git a/drivers/motorolamodem/sms.c b/drivers/motorolamodem/sms.c
--- a/drivers/motorolamodem/sms.c
+++ b/drivers/motorolamodem/sms.c
@@ -85,7 +85,7 @@ static inline void motorola_ack_delivery(struct ofono_sms *sms)
     if (!motorola_qmi_sms_available(data))
         return;


-    g_at_chat_send(data->recv, "AT+GCNMA=1\n", none_prefix,
+    mot_at_chat_send(data->recv, "AT+GCNMA=1\n", none_prefix,
                         at_cnma_cb, NULL, NULL);
 }


diff --git a/drivers/motorolamodem/voicecall.c b/drivers/motorolamodem/voicecall.c
--- a/drivers/motorolamodem/voicecall.c
+++ b/drivers/motorolamodem/voicecall.c
@@ -259,7 +259,7 @@ static void motorola_dial(struct ofono_voicecall *vc,
         break;
     }


-    if (g_at_chat_send(vd->chat, buf, atd_prefix,
+    if (mot_at_chat_send(vd->chat, buf, atd_prefix,
                 atd_cb, cbd, g_free) > 0)
         return;


@@ -283,7 +283,7 @@ static void motorola_template(const char *cmd, struct ofono_voicecall *vc,
     req->data = data;
     req->affected_types = affected_types;


-    if (g_at_chat_send(vd->chat, cmd, none_prefix,
+    if (mot_at_chat_send(vd->chat, cmd, none_prefix,
                 result_cb, req, g_free) > 0)
         return;


@@ -351,7 +351,7 @@ static void motorola_release_specific(struct ofono_voicecall *vc, int id,

     snprintf(buf, sizeof(buf), "AT+CHLD=1%d", id);


-    if (g_at_chat_send(vd->chat, buf, none_prefix,
+    if (mot_at_chat_send(vd->chat, buf, none_prefix,
                 release_id_cb, req, g_free) > 0)
         return;


@@ -460,7 +460,7 @@ static void motorola_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,

     vd->vts_delay = vd->tone_duration * len;


-    s = g_at_chat_send(vd->chat, buf, none_prefix,
+    s = mot_at_chat_send(vd->chat, buf, none_prefix,
                 vts_cb, cbd, NULL);


     g_free(buf);
@@ -916,9 +916,9 @@ static int motorola_voicecall_probe(struct ofono_voicecall *vc, unsigned int ven


     ofono_voicecall_set_data(vc, vd);


-    g_at_chat_send(vd->chat, "AT+CLIP=1", NULL, NULL, NULL, NULL);
+    mot_at_chat_send(vd->chat, "AT+CLIP=1", NULL, NULL, NULL, NULL);


-    g_at_chat_send(vd->chat, "AT+CCWA=1", NULL,
+    mot_at_chat_send(vd->chat, "AT+CCWA=1", NULL,
                 motorola_voicecall_initialized, vc, NULL);


     return 0;
diff --git a/gatchat/gatchat.c b/gatchat/gatchat.c
--- a/gatchat/gatchat.c
+++ b/gatchat/gatchat.c
@@ -101,6 +101,7 @@ struct at_chat {
     gboolean destroyed;            /* Re-entrancy guard */
     gboolean in_read_handler;        /* Re-entrancy guard */
     gboolean in_notify;
+    guint hdrlen;                /* Non-standard header length */
     GSList *terminator_list;        /* Non-standard terminator */
     char *delimiter;            /* Non-standard delimiter */
     guint16 terminator_blacklist;        /* Blacklisted terinators */
@@ -505,6 +506,11 @@ static void at_chat_add_delimiter(struct at_chat *chat, char *delimiter)
     chat->delimiter = g_strdup(delimiter);
 }


+static void at_chat_add_hdrlen(struct at_chat *chat, guint len)
+{
+    chat->hdrlen = len;
+}
+
 static gboolean check_terminator(struct terminator_info *info, char *line,
                     char *resp)
 {
@@ -741,6 +747,11 @@ static char *extract_line(struct at_chat *p, struct ring_buffer *rbuf)
             buf = ring_buffer_read_ptr(rbuf, pos);
     }


+    if (p->hdrlen && p->hdrlen < line_length) {
+        strip_front += p->hdrlen;
+        line_length -= p->hdrlen;
+    }
+
     line = g_try_new(char, line_length + 1);
     if (line == NULL) {
         ring_buffer_drain(rbuf, p->read_so_far);
@@ -1537,6 +1548,14 @@ void g_at_chat_add_delimiter(GAtChat *chat, char *delimiter)
     at_chat_add_delimiter(chat->parent, delimiter);
 }


+void g_at_chat_add_hdrlen(GAtChat *chat, guint len)
+{
+    if (chat == NULL || chat->group != 0)
+        return;
+
+    at_chat_add_hdrlen(chat->parent, len);
+}
+
 void g_at_chat_blacklist_terminator(GAtChat *chat,
                         GAtChatTerminator terminator)
 {
diff --git a/gatchat/gatchat.h b/gatchat/gatchat.h
--- a/gatchat/gatchat.h
+++ b/gatchat/gatchat.h
@@ -174,6 +174,7 @@ void g_at_chat_add_terminator(GAtChat *chat, char *terminator,
 void g_at_chat_blacklist_terminator(GAtChat *chat,
                         GAtChatTerminator terminator);
 void g_at_chat_add_delimiter(GAtChat *chat, char *delimiter);
+void g_at_chat_add_hdrlen(GAtChat *chat, guint len);


 #ifdef __cplusplus
 }
diff --git a/gatchat/gatsyntax.c b/gatchat/gatsyntax.c
--- a/gatchat/gatsyntax.c
+++ b/gatchat/gatsyntax.c
@@ -376,6 +376,35 @@ out:
     return res;
 }


+/* Some Motorola modems have a U1234 style custom header */
+static GAtSyntaxResult motmdm_permissive_feed(GAtSyntax *syntax,
+                        const char *bytes, gsize *len)
+{
+    GAtSyntaxResult res;
+    const int hdrlen = 5;
+    const char *mbytes;
+    gsize mlen;
+
+    if (*len < hdrlen || (*len > 0 && bytes[0] != 'U'))
+        return gsm_permissive_feed(syntax, bytes, len);
+
+    mbytes = bytes + hdrlen;;
+    mlen = *len - hdrlen;
+
+    res = gsm_permissive_feed(syntax, mbytes, &mlen);
+
+    *len = mlen + hdrlen;
+
+    /* At least xt875 is quirky and not using '\r' like xt894 */
+    if (*len > 0 && res == G_AT_SYNTAX_RESULT_UNSURE &&
+            bytes[*len - 1] == '\n') {
+        syntax->state = GSM_PERMISSIVE_STATE_IDLE;
+        res = G_AT_SYNTAX_RESULT_LINE;
+    }
+
+    return res;
+}
+
 GAtSyntax *g_at_syntax_new_full(GAtSyntaxFeedFunc feed,
                     GAtSyntaxSetHintFunc hint,
                     int initial_state)
@@ -404,6 +433,12 @@ GAtSyntax *g_at_syntax_new_gsm_permissive(void)
                     GSM_PERMISSIVE_STATE_IDLE);
 }


+GAtSyntax *g_at_syntax_new_motmdm_permissive(void)
+{
+    return g_at_syntax_new_full(motmdm_permissive_feed, gsm_permissive_hint,
+                    GSM_PERMISSIVE_STATE_IDLE);
+}
+
 GAtSyntax *g_at_syntax_ref(GAtSyntax *syntax)
 {
     if (syntax == NULL)
diff --git a/gatchat/gatsyntax.h b/gatchat/gatsyntax.h
--- a/gatchat/gatsyntax.h
+++ b/gatchat/gatsyntax.h
@@ -78,6 +78,11 @@ GAtSyntax *g_at_syntax_new_gsmv1(void);
  */
 GAtSyntax *g_at_syntax_new_gsm_permissive(void);


+/* This syntax implements handling for the custom header on some Motorola
+ * mapphone modems such as Droid 4 using g_at_syntax_new_gsm_permissive()
+ */
+GAtSyntax *g_at_syntax_new_motmdm_permissive(void);
+
GAtSyntax *g_at_syntax_ref(GAtSyntax *syntax);
void g_at_syntax_unref(GAtSyntax *syntax);

diff --git a/plugins/motmdm.c b/plugins/motmdm.c
--- a/plugins/motmdm.c
+++ b/plugins/motmdm.c
@@ -72,9 +72,9 @@ enum motmdm_chat {
 #define NUM_DLC        (DLC_SMS_XMIT + 1)


 static const char *devices[] = {
-    "/dev/motmdm1",
-    "/dev/motmdm9",
-    "/dev/motmdm3",
+    "/dev/gsmtty1",
+    "/dev/gsmtty9",
+    "/dev/gsmtty3",
 };


 struct motmdm_data {
@@ -301,7 +301,11 @@ static int motmdm_open_device(struct ofono_modem *modem, const char *device,
     if (channel == NULL)
         return -EIO;


-    syntax = g_at_syntax_new_gsm_permissive();
+    if (index == USB_AT)
+        syntax = g_at_syntax_new_gsm_permissive();
+    else
+        syntax = g_at_syntax_new_motmdm_permissive();
+
     chat = g_at_chat_new(channel, syntax);
     g_at_syntax_unref(syntax);
     g_io_channel_unref(channel);
@@ -334,10 +338,12 @@ static int motmdm_open_dlc_devices(struct ofono_modem *modem)
         switch(i) {
         case DLC_VOICE:
             g_at_chat_add_delimiter(*chat, ":");
+            g_at_chat_add_hdrlen(*chat, 5);
             g_at_chat_add_terminator(*chat, "ERROR=", 6, FALSE);
             g_at_chat_add_terminator(*chat, "+CLCC:", -1, TRUE);
             break;
         case DLC_SMS_RECV:
+            g_at_chat_add_hdrlen(*chat, 5);
             g_at_chat_add_terminator(*chat, "+GCNMA=OK", 9, TRUE);
             g_at_chat_add_terminator(*chat, "+GCNMA=305", 10, FALSE);
             break;