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