qmi-codegen in libqmi-glib

Dan Williams dcbw at redhat.com
Wed May 23 12:22:14 PDT 2012


On Wed, 2012-05-23 at 19:49 +0200, Aleksander Morgado wrote:
> Hey hey,
> 
> I've been playing a bit more with the idea of automatically generating
> code for message handling from input JSON files, and got already
> something working in the 'qmi-codegen' branch of my libqmi-glib tree:
>   git://gitorious.org/lanedo/libqmi-glib.git
> 
> The current set of supported messages are defined in the following JSON
> files:
> 
> https://gitorious.org/lanedo/libqmi-glib/blobs/qmi-codegen/data/qmi-common.json
> 
> https://gitorious.org/lanedo/libqmi-glib/blobs/qmi-codegen/data/qmi-service-ctl.json
> 
> https://gitorious.org/lanedo/libqmi-glib/blobs/qmi-codegen/data/qmi-service-dms.json
> 
> https://gitorious.org/lanedo/libqmi-glib/blobs/qmi-codegen/data/qmi-service-wds.json
> 
> And adding new messages should need, ideally, just updating these JSON
> files. I guess the qmi-codegen will need updates from time to time when
> new basic types are found in the QMI messages. Currently the following
> types are supported:
>  * integers (uint8/uint16/uint32/int8/int16/int32)
>  * strings
>  * structs with integer contents
>  * arrays of structs

At some point we'll need unions too, where the member of the union
that's actually used depends on a specific value from earlier in the
struct.  That's how stuff like "get the access technology and status"
works where you've got a big struct like:

struct {
    bool 3gpp;  // true = 3gpp, false = 3gpp2
    union {
        struct {
            uint mcc;
            uint mnc;
            uint lac;
            uint cid;
            enum rat_type;
        } 3gpp;
        struct {
            bool is_1x_or_hdr;
            union {
                struct {
                    1x junk;
                } 1x;
                struct {
                    evdo junk;
                } hdr;
            } u2;
        } 3gpp2;
    } u;
}

that's some evil stuff, but basically  normal protocol packet parsing :(
Anyway, I do like the idea of doing this with JSON.  I despair of
actually being able to use the Gobi database except for reference since
generating the code out of them is horrendously complicated.

Dan

> 
> The new qmi-codegen python program will read the per-service input JSON
> files, and for each request/response, we will define GIO Async methods,
> like:
> 
> void qmi_client_ctl_allocate_cid (
>     QmiClientCtl *self,
>     QmiMessageCtlAllocateCidInput *input,
>     guint timeout,
>     GCancellable *cancellable,
>     GAsyncReadyCallback callback,
>     gpointer user_data);
> QmiMessageCtlAllocateCidOutput *qmi_client_ctl_allocate_cid_finish (
>     QmiClientCtl *self,
>     GAsyncResult *res,
>     GError **error);
> 
> We then provide methods to create/ref/unref the
> QmiMessageCtlAllocateCidInput bundle, as well as methods to get/set
> specific TLVs, like:
> 
> gboolean qmi_message_ctl_allocate_cid_input_get_service (
>     QmiMessageCtlAllocateCidInput *self,
>     QmiService *value,
>     GError **error);
> gboolean qmi_message_ctl_allocate_cid_input_set_service (
>     QmiMessageCtlAllocateCidInput *self,
>     QmiService value,
>     GError **error);
> QmiMessageCtlAllocateCidInput *qmi_message_ctl_allocate_cid_input_ref
>     (QmiMessageCtlAllocateCidInput *self);
> void qmi_message_ctl_allocate_cid_input_unref
>     (QmiMessageCtlAllocateCidInput *self);
> QmiMessageCtlAllocateCidInput *qmi_message_ctl_allocate_cid_input_new
>     (void);
> 
> And the same for output bundles like the QmiMessageCtlAllocateCidOutput:
> 
> typedef struct _QmiMessageCtlAllocateCidOutputAllocationInfo {
>     QmiService service;
>     guint8 cid;
> } QmiMessageCtlAllocateCidOutputAllocationInfo;
> 
> gboolean qmi_message_ctl_allocate_cid_output_get_result (
>     QmiMessageCtlAllocateCidOutput *self,
>     GError **error);
> gboolean qmi_message_ctl_allocate_cid_output_get_allocation_info (
>     QmiMessageCtlAllocateCidOutput *self,
>     QmiMessageCtlAllocateCidOutputAllocationInfo *value,
>     GError **error);
> QmiMessageCtlAllocateCidOutput *qmi_message_ctl_allocate_cid_output_ref
>     (QmiMessageCtlAllocateCidOutput *self);
> void qmi_message_ctl_allocate_cid_output_unref
>     (QmiMessageCtlAllocateCidOutput *self);
> 
> 
> In order to keep API/ABI compatibility whenever the QMI protocol is
> updated, all input TLVs and output TLVs are packed into the input and
> output 'bundles'. Here I'm assuming that QMI protocol updates are either
> new messages or full new TLVs in already existing messages; or in other
> words, assuming that existing TLVs are not supposed to get modified
> (which is why for struct TLVs we define the struct itself in the public
> interface).
> 
> When compiling with -DMESSAGE_ENABLE_TRACE, it enables tracing of the
> ongoing messages, which now also includes properly printing the TLV
> values (when known), like:
> 
> <<<<<< QMUX:
> <<<<<<   length  = 16
> <<<<<<   flags   = 0x00
> <<<<<<   service = "ctl"
> <<<<<<   client  = 0
> <<<<<< QMI:
> <<<<<<   flags       = "none"
> <<<<<<   transaction = 3
> <<<<<<   tlv_length  = 5
> <<<<<<   message     = "Release CID" (0x0023)
> <<<<<< TLV:
> <<<<<<   type       = "Release Info" (0x01)
> <<<<<<   length     = 2
> <<<<<<   value      = 02:13
> <<<<<<   translated =
> <<<<<<      [Service = 2]
> <<<<<<      [Cid = 19]
> 
> 
> Tests with this branch are highly appreciated, as I would like to merge
> it to libqmi-glib master sooner than later.

Neato.

Dan



More information about the libqmi-devel mailing list