Merge remote-tracking branch 'cros/upstream' into 'cros/master'
diff --git a/.gitignore b/.gitignore
index 1c814dc..3737a42 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,56 +35,57 @@
 gtk-doc.make
 test-driver
 
-build-aux/mbim-codegen/*.pyc
-build-aux/mbim-codegen/__pycache__
+/build-aux/mbim-codegen/*.pyc
+/build-aux/mbim-codegen/__pycache__
 
-data/pkg-config/mbim-glib.pc
+/data/pkg-config/mbim-glib.pc
 
-docs/reference/libmbim-glib/version.xml
-docs/reference/libmbim-glib/libmbim-glib.args
-docs/reference/libmbim-glib/libmbim-glib.hierarchy
-docs/reference/libmbim-glib/libmbim-glib.interfaces
-docs/reference/libmbim-glib/libmbim-glib.prerequisites
-docs/reference/libmbim-glib/libmbim-glib.signals
-docs/reference/libmbim-glib/libmbim-glib.types
-docs/reference/libmbim-glib/*.mstamp
-docs/reference/libmbim-glib/*.stamp
-docs/reference/libmbim-glib/*.txt
-docs/reference/libmbim-glib/*.bak
-docs/reference/libmbim-glib/html
-docs/reference/libmbim-glib/tmpl
-docs/reference/libmbim-glib/xml
-docs/reference/libmbim-glib/.libs
+/docs/reference/libmbim-glib/version.xml
+/docs/reference/libmbim-glib/libmbim-glib.args
+/docs/reference/libmbim-glib/libmbim-glib.hierarchy
+/docs/reference/libmbim-glib/libmbim-glib.interfaces
+/docs/reference/libmbim-glib/libmbim-glib.prerequisites
+/docs/reference/libmbim-glib/libmbim-glib.signals
+/docs/reference/libmbim-glib/libmbim-glib.types
+/docs/reference/libmbim-glib/*.mstamp
+/docs/reference/libmbim-glib/*.stamp
+/docs/reference/libmbim-glib/*.txt
+/docs/reference/libmbim-glib/*.bak
+/docs/reference/libmbim-glib/html
+/docs/reference/libmbim-glib/tmpl
+/docs/reference/libmbim-glib/xml
+/docs/reference/libmbim-glib/.libs
 
-docs/man/mbimcli.1
-docs/man/mbim-network.1
+/docs/man/mbimcli.1
+/docs/man/mbim-network.1
 
-src/libmbim-glib/.deps
-src/libmbim-glib/.libs
-src/libmbim-glib/mbim-version.h
+/src/libmbim-glib/.deps
+/src/libmbim-glib/.libs
+/src/libmbim-glib/mbim-version.h
 
-src/libmbim-glib/test/.deps
-src/libmbim-glib/test/.libs
-src/libmbim-glib/test/test-uuid
-src/libmbim-glib/test/test-cid
-src/libmbim-glib/test/test-message
-src/libmbim-glib/test/test-fragment
-src/libmbim-glib/test/test-message-parser
-src/libmbim-glib/test/test-message-builder
-src/libmbim-glib/test/test-proxy-helpers
-src/libmbim-glib/test/*.log
-src/libmbim-glib/test/*.trs
+/src/libmbim-glib/test/.deps
+/src/libmbim-glib/test/.libs
+/src/libmbim-glib/test/test-uuid
+/src/libmbim-glib/test/test-cid
+/src/libmbim-glib/test/test-message
+/src/libmbim-glib/test/test-fragment
+/src/libmbim-glib/test/test-message-parser
+/src/libmbim-glib/test/test-message-builder
+/src/libmbim-glib/test/test-proxy-helpers
+/src/libmbim-glib/test/*.log
+/src/libmbim-glib/test/*.trs
 
-src/libmbim-glib/generated/.deps
-src/libmbim-glib/generated/.libs
-src/libmbim-glib/generated/*.c
-src/libmbim-glib/generated/*.h
-src/libmbim-glib/generated/*.sections
+/src/libmbim-glib/generated/.deps
+/src/libmbim-glib/generated/.libs
+/src/libmbim-glib/generated/*.c
+/src/libmbim-glib/generated/*.h
+/src/libmbim-glib/generated/*.sections
 
-src/mbimcli/.deps
-src/mbimcli/.libs
-src/mbimcli/mbimcli
+/src/mbimcli/.deps
+/src/mbimcli/.libs
+/src/mbimcli/mbimcli
 
-utils/mbim-network
+/utils/mbim-network
 
-src/mbim-proxy/mbim-proxy
+/src/mbim-proxy/mbim-proxy
+/src/mbim-proxy/76-mbim-proxy-device-ownership.rules
diff --git a/AUTHORS b/AUTHORS
index b366833..81a6de0 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,14 +1,17 @@
-Maintainers:
-Aleksander Morgado <aleksander@aleksander.es>
-Dan Williams       <dcbw@redhat.com>
+Current maintainers:
+  Aleksander Morgado <aleksander@aleksander.es>
+  Dan Williams       <dcbw@redhat.com>
 
-Other authors:
-Ben Chan
-Bjørn Mork
-Greg Suarez
-Prathmesh Prabhu
-Shawn J. Goff
-Arnaud Desmier
-Marius B. Kotsbak
-Nagaraju Kadiri
-Scott Lee
+Other contributors:
+  Ben Chan
+  Greg Suarez
+  Bjørn Mork
+  Roshan Pius
+  Prathmesh Prabhu
+  Yunlian Jiang
+  Shawn J. Goff
+  Scott Lee
+  Raju
+  Marius B. Kotsbak
+  Boris Egorov
+  Arnaud Desmier
diff --git a/Makefile.am b/Makefile.am
index bdef824..aefa985 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,7 +3,9 @@
 
 ACLOCAL_AMFLAGS = -I m4
 
-DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
+DISTCHECK_CONFIGURE_FLAGS = \
+	--with-udev-base-dir="$$dc_install_base" \
+	--enable-gtk-doc
 
 EXTRA_DIST = \
 	gtester.make \
diff --git a/NEWS b/NEWS
index 6b19cc9..a5e2cf9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,42 @@
 
+Overview of changes in libmbim 1.12
+----------------------------------------
+
+* New `--enable-mbim-username' option during configure, which allows specifying
+  which will be the user owning the /dev/cdc-wdm character devices of all MBIM
+  modems (udev rules are installed to change file ownership). If this option is
+  used, the mbim-proxy will only allow connections from processes running by the
+  specified user or by the root user.
+
+* Function error messages can now be returned by the MbimDevice as responses to
+  `Command', `Open' or `Close' messages. Users of the library should not assume
+  the type of message returned to the previous actions.
+
+* The MbimProxy will monitor for 'NotOpened' errors, and when one detected it
+  will directly close the internal MbimDevice. Any subsequent request sent by
+  clients to that specific device will be aborted with a proxy-generated
+  'NotOpened' error. Clients will need to explicitly reopen the ports in that
+  case.
+
+* The API now has a new mbim_message_response_get_result() method which allows
+  getting a GError from a message which may be of a specific type (e.g. a
+  `Command Done' message in response to a `Command' request) or instead the
+  generic `Function Error' message type. Users of the library can use this new
+  method to avoid assuming the type of message returned.
+
+      E.g. the following check:
+          mbim_message_command_done_get_result (response, &error);
+      Can be updated as:
+          mbim_message_response_get_result (response,
+                                            MBIM_MESSAGE_TYPE_COMMAND_DONE,
+                                            &error);
+      And the same logic can be applied to `Open' and `Close' messages.
+
+* Other bugfixes and minor improvements:
+  ** Attach timeout and idle events to the thread-default context.
+  ** Fix bashisms in the mbim-network script.
+
+
 Overview of changes in libmbim 1.10
 ----------------------------------------
 
diff --git a/configure.ac b/configure.ac
index ae04f5f..2b5e1c5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
 
 dnl The libmbim version number
 m4_define([mbim_major_version], [1])
-m4_define([mbim_minor_version], [11])
+m4_define([mbim_minor_version], [13])
 m4_define([mbim_micro_version], [0])
 m4_define([mbim_version],
           [mbim_major_version.mbim_minor_version.mbim_micro_version])
@@ -16,9 +16,9 @@
 dnl            with old code), increment a.
 dnl        If the interface has changed in an incompatible way (that is,
 dnl            functions have changed or been removed), then zero a.
-m4_define([mbim_glib_lt_current],  [4])
+m4_define([mbim_glib_lt_current],  [5])
 m4_define([mbim_glib_lt_revision], [0])
-m4_define([mbim_glib_lt_age],      [0])
+m4_define([mbim_glib_lt_age],      [1])
 
 
 AC_INIT([libmbim], [mbim_version], [libmbim-devel@lists.freedesktop.org])
@@ -97,10 +97,29 @@
 GTK_DOC_CHECK(1.0)
 
 # MBIM username
+MBIM_USERNAME="root"
 AC_ARG_ENABLE(mbim-username,
-              AS_HELP_STRING([--enable-mbim-username=<username>], [user allowed to access MBIM devices]),,
-              enable_mbim_username="root")
-AC_DEFINE_UNQUOTED(MBIM_USERNAME, "$enable_mbim_username", [Define the MBIM username])
+              AS_HELP_STRING([--enable-mbim-username=<username>], [user allowed to access MBIM devices]))
+if test -n "$enable_mbim_username" ; then
+    MBIM_USERNAME_ENABLED=yes
+    AC_DEFINE(MBIM_USERNAME_ENABLED, 1, [Define if we enable MBIM username])
+    MBIM_USERNAME="$enable_mbim_username"
+    AC_SUBST(MBIM_USERNAME)
+    AC_DEFINE_UNQUOTED(MBIM_USERNAME, "$MBIM_USERNAME", [Define the MBIM username])
+else
+    MBIM_USERNAME_ENABLED=no
+fi
+
+AM_CONDITIONAL([MBIM_USERNAME_ENABLED], [test "x$MBIM_USERNAME_ENABLED" = "xyes"])
+
+# udev base directory
+AC_ARG_WITH(udev-base-dir, AS_HELP_STRING([--with-udev-base-dir=DIR], [where udev base directory is]))
+if test -n "$with_udev_base_dir" ; then
+    UDEV_BASE_DIR="$with_udev_base_dir"
+else
+    UDEV_BASE_DIR="/lib/udev"
+fi
+AC_SUBST(UDEV_BASE_DIR)
 
 dnl Man page
 AC_PATH_PROG(HELP2MAN, help2man, false)
@@ -126,16 +145,21 @@
                  docs/reference/libmbim-glib/Makefile
                  docs/reference/libmbim-glib/version.xml
                  docs/man/Makefile])
+
+if test "x$MBIM_USERNAME_ENABLED" = "xyes"; then
+    AC_CONFIG_FILES([src/mbim-proxy/76-mbim-proxy-device-ownership.rules])
+fi
+
 AC_OUTPUT
 
 echo "
     libmbim $VERSION
     ==============================================
 
-    compiler:         ${CC}
-    cflags:           ${CFLAGS}
-    Maintainer mode:  ${USE_MAINTAINER_MODE}
-    Documentation:    ${enable_gtk_doc}
-    MBIM username:    ${enable_mbim_username}
-
+    compiler:             ${CC}
+    cflags:               ${CFLAGS}
+    Maintainer mode:      ${USE_MAINTAINER_MODE}
+    udev base directory:  ${UDEV_BASE_DIR}
+    Documentation:        ${enable_gtk_doc}
+    MBIM username:        ${MBIM_USERNAME_ENABLED} (${MBIM_USERNAME})
 "
diff --git a/docs/reference/libmbim-glib/libmbim-glib-common.sections b/docs/reference/libmbim-glib/libmbim-glib-common.sections
index 5c3af88..e316aed 100644
--- a/docs/reference/libmbim-glib/libmbim-glib-common.sections
+++ b/docs/reference/libmbim-glib/libmbim-glib-common.sections
@@ -136,6 +136,7 @@
 mbim_message_close_done_get_result
 <SUBSECTION MethodsError>
 mbim_message_error_new
+mbim_message_function_error_new
 mbim_message_error_get_error_status_code
 mbim_message_error_get_error
 <SUBSECTION MethodsCommand>
@@ -159,6 +160,8 @@
 mbim_message_indicate_status_get_service_id
 mbim_message_indicate_status_get_cid
 mbim_message_indicate_status_get_raw_information_buffer
+<SUBSECTION MethodsOtherHelpers>
+mbim_message_response_get_result
 <SUBSECTION Private>
 mbim_message_open_done_new
 mbim_message_close_done_new
diff --git a/src/libmbim-glib/mbim-device.c b/src/libmbim-glib/mbim-device.c
index 826fa3e..d434665 100644
--- a/src/libmbim-glib/mbim-device.c
+++ b/src/libmbim-glib/mbim-device.c
@@ -39,6 +39,7 @@
 #include "mbim-message.h"
 #include "mbim-message-private.h"
 #include "mbim-error-types.h"
+#include "mbim-enum-types.h"
 #include "mbim-proxy.h"
 #include "mbim-proxy-control.h"
 
@@ -139,6 +140,7 @@
 } TransactionWaitContext;
 
 typedef struct {
+    MbimDevice *self;
     MbimMessage *fragments;
     MbimMessageType type;
     guint32 transaction_id;
@@ -149,6 +151,22 @@
     TransactionWaitContext *wait_ctx;
 } Transaction;
 
+/* #define TRACE_TRANSACTION 1 */
+#ifdef TRACE_TRANSACTION
+static void
+trace_transaction (Transaction *tr,
+                   const gchar *state)
+{
+    g_debug ("[%s,%u] transaction %s: %s",
+             tr->self->priv->path_display,
+             tr->transaction_id,
+             mbim_message_type_get_string (tr->type),
+             state);
+}
+#else
+# define trace_transaction(...)
+#endif
+
 static Transaction *
 transaction_new (MbimDevice          *self,
                  MbimMessageType      type,
@@ -162,6 +180,7 @@
     tr = g_slice_new0 (Transaction);
     tr->type = type;
     tr->transaction_id = transaction_id;
+    tr->self = g_object_ref (self);
     tr->result = g_simple_async_result_new (G_OBJECT (self),
                                             callback,
                                             user_data,
@@ -169,6 +188,8 @@
     if (cancellable)
         tr->cancellable = g_object_ref (cancellable);
 
+    trace_transaction (tr, "new");
+
     return tr;
 }
 
@@ -189,10 +210,12 @@
         g_slice_free (TransactionWaitContext, tr->wait_ctx);
 
     if (error) {
+        trace_transaction (tr, "complete: response");
         g_simple_async_result_set_from_error (tr->result, error);
         if (tr->fragments)
             mbim_message_unref (tr->fragments);
     } else {
+        trace_transaction (tr, "complete: error");
         g_assert (tr->fragments != NULL);
         g_simple_async_result_set_op_res_gpointer (tr->result,
                                                    tr->fragments,
@@ -201,6 +224,7 @@
 
     g_simple_async_result_complete_in_idle (tr->result);
     g_object_unref (tr->result);
+    g_object_unref (tr->self);
     g_slice_free (Transaction, tr);
 }
 
@@ -212,14 +236,18 @@
 {
     Transaction *tr = NULL;
 
+    /* Only return transaction if it was released from the HT */
     if (self->priv->transactions[type]) {
         tr = g_hash_table_lookup (self->priv->transactions[type], GUINT_TO_POINTER (transaction_id));
-        if (tr && ((tr->type == expected_type) || (expected_type == MBIM_MESSAGE_TYPE_INVALID)))
+        if (tr && ((tr->type == expected_type) || (expected_type == MBIM_MESSAGE_TYPE_INVALID))) {
             /* If found, remove it from the HT */
+            trace_transaction (tr, "release");
             g_hash_table_remove (self->priv->transactions[type], GUINT_TO_POINTER (transaction_id));
+            return tr;
+        }
     }
 
-    return tr;
+    return NULL;
 }
 
 static gboolean
@@ -289,6 +317,8 @@
                           guint             timeout_ms,
                           GError          **error)
 {
+    trace_transaction (tr, "store");
+
     if (G_UNLIKELY (!self->priv->transactions[type]))
         self->priv->transactions[type] = g_hash_table_new (g_direct_hash, g_direct_equal);
 
@@ -567,8 +597,19 @@
     }
 
     case MBIM_MESSAGE_TYPE_FUNCTION_ERROR: {
+        Transaction *tr;
         GError *error_indication;
 
+        /* Try to match this transaction just per transaction ID */
+        tr = device_release_transaction (self,
+                                         TRANSACTION_TYPE_HOST,
+                                         MBIM_MESSAGE_TYPE_INVALID,
+                                         mbim_message_get_transaction_id (message));
+
+        if (!tr)
+            g_debug ("[%s] No transaction matched in received function error message",
+                     self->priv->path_display);
+
         if (mbim_utils_get_traces_enabled ()) {
             gchar *printable;
 
@@ -579,6 +620,14 @@
             g_free (printable);
         }
 
+        if (tr) {
+            if (tr->fragments)
+                mbim_message_unref (tr->fragments);
+            tr->fragments = mbim_message_dup (message);
+            transaction_complete_and_free (tr, NULL);
+        }
+
+        /* Signals are emitted regardless of whether the transaction matched or not */
         error_indication = mbim_message_error_get_error (message);
         g_signal_emit (self, signals[SIGNAL_ERROR], 0, error_indication);
         g_error_free (error_indication);
@@ -619,6 +668,11 @@
         /* Play with the received message */
         process_message (self, message);
 
+        /* If we were force-closed during the processing of a message, we'd be
+         * losing the response array directly, so check just in case */
+        if (!self->priv->response)
+            break;
+
         /* Remove message from buffer */
         g_byte_array_remove_range (self->priv->response, 0, in_length);
     } while (self->priv->response->len > 0);
@@ -1152,7 +1206,7 @@
         return;
     }
 
-    if (!mbim_message_open_done_get_result (response, &error)) {
+    if (!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_OPEN_DONE, &error)) {
         g_debug ("getting open done result failed: closed");
         self->priv->open_status = OPEN_STATUS_CLOSED;
         device_open_context_complete_and_free (ctx, error);
@@ -1496,9 +1550,7 @@
     response = mbim_device_command_finish (self, res, &error);
     if (!response)
         g_simple_async_result_take_error (ctx->result, error);
-    else if (!mbim_message_close_done_get_result (response, &error))
-        g_simple_async_result_take_error (ctx->result, error);
-    else if (!destroy_iochannel (self, &error))
+    else if (!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_CLOSE_DONE, &error))
         g_simple_async_result_take_error (ctx->result, error);
     else
         g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
diff --git a/src/libmbim-glib/mbim-message.c b/src/libmbim-glib/mbim-message.c
index 48f6018..5ca8ef5 100644
--- a/src/libmbim-glib/mbim-message.c
+++ b/src/libmbim-glib/mbim-message.c
@@ -1702,7 +1702,34 @@
 
     self = _mbim_message_allocate (MBIM_MESSAGE_TYPE_HOST_ERROR,
                                    transaction_id,
-                                   sizeof (struct open_message));
+                                   sizeof (struct error_message));
+
+    /* Open header */
+    ((struct full_message *)(self->data))->message.error.error_status_code = GUINT32_TO_LE (error_status_code);
+
+    return (MbimMessage *)self;
+}
+
+/**
+ * mbim_message_function_error_new:
+ * @transaction_id: transaction ID.
+ * @error_status_code: a #MbimProtocolError.
+ *
+ * Create a new #MbimMessage of type %MBIM_MESSAGE_TYPE_FUNCTION_ERROR with the specified
+ * parameters.
+ *
+ * Returns: (transfer full): a newly created #MbimMessage. The returned value
+ * should be freed with mbim_message_unref().
+ */
+MbimMessage *
+mbim_message_function_error_new (guint32           transaction_id,
+                                 MbimProtocolError error_status_code)
+{
+    GByteArray *self;
+
+    self = _mbim_message_allocate (MBIM_MESSAGE_TYPE_FUNCTION_ERROR,
+                                   transaction_id,
+                                   sizeof (struct error_message));
 
     /* Open header */
     ((struct full_message *)(self->data))->message.error.error_status_code = GUINT32_TO_LE (error_status_code);
@@ -2120,3 +2147,73 @@
             ((struct full_message *)(self->data))->message.indicate_status.buffer :
             NULL);
 }
+
+/*****************************************************************************/
+/* Other helpers */
+
+/**
+ * mbim_message_response_get_result:
+ * @self: a #MbimMessage response message.
+ * @expected: expected #MbimMessageType if there isn't any error in the operation.
+ * @error: return location for error or %NULL.
+ *
+ * Gets the result of the operation from the response message, which
+ * can be either a %MBIM_MESSAGE_TYPE_FUNCTION_ERROR message or a message of the
+ * specified @expected type.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
+ */
+gboolean
+mbim_message_response_get_result (const MbimMessage  *self,
+                                  MbimMessageType     expected,
+                                  GError            **error)
+{
+    MbimStatusError status = MBIM_STATUS_ERROR_NONE;
+    MbimMessageType type;
+
+    g_return_val_if_fail (self != NULL, FALSE);
+    g_return_val_if_fail (expected == MBIM_MESSAGE_TYPE_OPEN_DONE  ||
+                          expected == MBIM_MESSAGE_TYPE_CLOSE_DONE ||
+                          expected == MBIM_MESSAGE_TYPE_COMMAND_DONE, FALSE);
+
+    type = MBIM_MESSAGE_GET_MESSAGE_TYPE (self);
+    if (type != MBIM_MESSAGE_TYPE_FUNCTION_ERROR && type != expected) {
+        g_set_error (error,
+                     MBIM_CORE_ERROR,
+                     MBIM_CORE_ERROR_INVALID_MESSAGE,
+                     "Unexpected response message type: 0x%04X", (guint32) type);
+        return FALSE;
+    }
+
+    switch (type) {
+    case MBIM_MESSAGE_TYPE_OPEN_DONE:
+        status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.open_done.status_code);
+        break;
+
+    case MBIM_MESSAGE_TYPE_CLOSE_DONE:
+        status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.close_done.status_code);
+        break;
+
+    case MBIM_MESSAGE_TYPE_COMMAND_DONE:
+        status = (MbimStatusError) GUINT32_FROM_LE (((struct full_message *)(self->data))->message.command_done.status_code);
+        break;
+
+    case MBIM_MESSAGE_TYPE_FUNCTION_ERROR:
+        if (error)
+            *error = mbim_message_error_get_error (self);
+        return FALSE;
+
+    default:
+        g_assert_not_reached ();
+    }
+
+    if (status == MBIM_STATUS_ERROR_NONE)
+        return TRUE;
+
+    /* Build error */
+    g_set_error_literal (error,
+                         MBIM_STATUS_ERROR,
+                         status,
+                         mbim_status_error_get_string (status));
+    return FALSE;
+}
diff --git a/src/libmbim-glib/mbim-message.h b/src/libmbim-glib/mbim-message.h
index f07a807..02154b7 100644
--- a/src/libmbim-glib/mbim-message.h
+++ b/src/libmbim-glib/mbim-message.h
@@ -156,6 +156,8 @@
 
 MbimMessage       *mbim_message_error_new                   (guint32            transaction_id,
                                                              MbimProtocolError  error_status_code);
+MbimMessage       *mbim_message_function_error_new          (guint32            transaction_id,
+                                                             MbimProtocolError  error_status_code);
 MbimProtocolError  mbim_message_error_get_error_status_code (const MbimMessage *self);
 GError            *mbim_message_error_get_error             (const MbimMessage *self);
 
@@ -212,6 +214,13 @@
 const guint8    *mbim_message_indicate_status_get_raw_information_buffer (const MbimMessage  *self,
                                                                           guint32            *length);
 
+/*****************************************************************************/
+/* Other helpers */
+
+gboolean mbim_message_response_get_result (const MbimMessage  *self,
+                                           MbimMessageType     expected,
+                                           GError            **error);
+
 G_END_DECLS
 
 #endif /* _LIBMBIM_GLIB_MBIM_MESSAGE_H_ */
diff --git a/src/libmbim-glib/mbim-proxy.c b/src/libmbim-glib/mbim-proxy.c
index 4068487..fdbc7d9 100644
--- a/src/libmbim-glib/mbim-proxy.c
+++ b/src/libmbim-glib/mbim-proxy.c
@@ -126,6 +126,7 @@
 
     MbimDevice *device;
     guint indication_id;
+    guint function_error_id;
     gboolean service_subscriber_list_enabled;
     MbimEventEntry **mbim_event_entry_array;
     gsize mbim_event_entry_array_size;
@@ -155,6 +156,9 @@
 static void client_indication_cb (MbimDevice *device,
                                   MbimMessage *message,
                                   Client *client);
+static void client_error_cb      (MbimDevice *device,
+                                  GError     *error,
+                                  Client     *client);
 
 static void
 client_set_device (Client *client,
@@ -163,6 +167,8 @@
     if (client->device) {
         if (g_signal_handler_is_connected (client->device, client->indication_id))
             g_signal_handler_disconnect (client->device, client->indication_id);
+        if (g_signal_handler_is_connected (client->device, client->function_error_id))
+            g_signal_handler_disconnect (client->device, client->function_error_id);
         g_object_unref (client->device);
     }
 
@@ -172,9 +178,14 @@
                                                   MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
                                                   G_CALLBACK (client_indication_cb),
                                                   client);
+        client->function_error_id = g_signal_connect (client->device,
+                                                      MBIM_DEVICE_SIGNAL_ERROR,
+                                                      G_CALLBACK (client_error_cb),
+                                                      client);
     } else {
         client->device = NULL;
         client->indication_id = 0;
+        client->function_error_id = 0;
     }
 }
 
@@ -309,6 +320,20 @@
 }
 
 /*****************************************************************************/
+/* Handling generic function errors */
+
+static void
+client_error_cb (MbimDevice *device,
+                 GError     *error,
+                 Client     *client)
+{
+    if (g_error_matches (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_NOT_OPENED)) {
+        g_debug ("Device not opened error reported, forcing close");
+        mbim_device_close_force (device, NULL);
+    }
+}
+
+/*****************************************************************************/
 /* Request info */
 
 typedef struct {
@@ -365,6 +390,22 @@
 /*****************************************************************************/
 /* Internal proxy device opening operation */
 
+typedef struct {
+    MbimProxy          *self;
+    MbimDevice         *device;
+    guint32             timeout_secs;
+    GSimpleAsyncResult *result;
+} InternalDeviceOpenContext;
+
+static void
+internal_device_open_context_free (InternalDeviceOpenContext *ctx)
+{
+    g_object_unref (ctx->result);
+    g_object_unref (ctx->device);
+    g_object_unref (ctx->self);
+    g_slice_free (InternalDeviceOpenContext, ctx);
+}
+
 static gboolean
 internal_device_open_finish (MbimProxy     *self,
                              GAsyncResult  *res,
@@ -462,50 +503,121 @@
 }
 
 static void
+internal_open (InternalDeviceOpenContext *ctx)
+{
+    OpeningDevice *info;
+
+    /* If already being opened, queue it up */
+    info = peek_opening_device_info (ctx->self, ctx->device);
+    if (info) {
+        /* Propagate result object from context */
+        info->pending = g_list_append (info->pending, g_object_ref (ctx->result));
+        internal_device_open_context_free (ctx);
+        return;
+    }
+
+    /* First time opening, go on */
+    info = g_slice_new0 (OpeningDevice);
+    info->device = g_object_ref (ctx->device);
+    info->pending = g_list_append (info->pending, g_object_ref (ctx->result));
+    ctx->self->priv->opening_devices = g_list_prepend (ctx->self->priv->opening_devices, info);
+
+    /* Note: for now, only the first timeout request is taken into account */
+
+    /* Need to open the device; and we must make sure the proxy only does this once, even
+     * when multiple clients request it */
+    mbim_device_open (ctx->device,
+                      ctx->timeout_secs,
+                      NULL,
+                      (GAsyncReadyCallback)device_open_ready,
+                      g_object_ref (ctx->self));
+
+    internal_device_open_context_free (ctx);
+}
+
+static void
+internal_device_open_caps_query_ready (MbimDevice                *device,
+                                       GAsyncResult              *res,
+                                       InternalDeviceOpenContext *ctx)
+{
+    GError *error = NULL;
+    MbimMessage *response;
+    GList *l;
+
+    /* Always unblock all signals from all clients */
+    for (l = ctx->self->priv->clients; l; l = g_list_next (l))
+        g_signal_handlers_unblock_by_func (device, client_error_cb, l->data);
+
+    response = mbim_device_command_finish (device, res, &error);
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
+        /* If we get a not-opened error, well, force closing right away and reopen */
+        if (g_error_matches (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_NOT_OPENED)) {
+            g_debug ("device not-opened error reported, reopening");
+            mbim_device_close_force (device, NULL);
+            internal_open (ctx);
+            if (response)
+                mbim_message_unref (response);
+            g_error_free (error);
+            return;
+        }
+
+        /* Warn other (unlikely!) errors, but keep on anyway */
+        g_warning ("device caps query during internal open failed: %s", error->message);
+        g_error_free (error);
+    }
+
+    g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+    g_simple_async_result_complete (ctx->result);
+    internal_device_open_context_free (ctx);
+
+    if (response)
+        mbim_message_unref (response);
+}
+
+static void
 internal_device_open (MbimProxy           *self,
                       MbimDevice          *device,
                       guint32              timeout_secs,
                       GAsyncReadyCallback  callback,
                       gpointer             user_data)
 {
-    OpeningDevice *info;
-    GSimpleAsyncResult *simple;
+    InternalDeviceOpenContext *ctx;
 
-    simple = g_simple_async_result_new (G_OBJECT (self),
-                                        callback,
-                                        user_data,
-                                        internal_device_open);
+    ctx = g_slice_new0 (InternalDeviceOpenContext);
+    ctx->self         = g_object_ref (self);
+    ctx->device       = g_object_ref (device);
+    ctx->timeout_secs = timeout_secs;
+    ctx->result       = g_simple_async_result_new (G_OBJECT (self),
+                                                   callback,
+                                                   user_data,
+                                                   internal_device_open);
 
-    /* If the device is already open, we are done */
+    /* If the device is flagged as already open, we still want to check
+     * whether that's totally true, and we do that with a standard command
+     * (loading caps in this case). */
     if (mbim_device_is_open (device)) {
-        g_simple_async_result_set_op_res_gboolean (simple, TRUE);
-        g_simple_async_result_complete_in_idle (simple);
-        g_object_unref (simple);
+        MbimMessage *message;
+        GList *l;
+
+        /* Avoid getting notified of errors in this internal check, as we're
+         * already going to check for the NotOpened error ourselves in the
+         * ready callback, and we'll reopen silently if we find this. */
+        for (l = self->priv->clients; l; l = g_list_next (l))
+            g_signal_handlers_block_by_func (device, client_error_cb, l->data);
+
+        g_debug ("checking device caps during client device open...");
+        message = mbim_message_device_caps_query_new (NULL);
+        mbim_device_command (device,
+                             message,
+                             5,
+                             NULL,
+                             (GAsyncReadyCallback)internal_device_open_caps_query_ready,
+                             ctx);
+        mbim_message_unref (message);
         return;
     }
 
-    /* If already being opened, queue it up */
-    info = peek_opening_device_info (self, device);
-    if (info) {
-        info->pending = g_list_append (info->pending, simple);
-        return;
-    }
-
-    /* First time opening, go on */
-    info = g_slice_new0 (OpeningDevice);
-    info->device = g_object_ref (device);
-    info->pending = g_list_append (info->pending, simple);
-    self->priv->opening_devices = g_list_prepend (self->priv->opening_devices, info);
-
-    /* Note: for now, only the first timeout request is taken into account */
-
-    /* Need to open the device; and we must make sure the proxy only does this once, even
-     * when multiple clients request it */
-    mbim_device_open (device,
-                      timeout_secs,
-                      NULL,
-                      (GAsyncReadyCallback)device_open_ready,
-                      g_object_ref (self));
+    internal_open (ctx);
 }
 
 /*****************************************************************************/
@@ -811,6 +923,13 @@
 
     tmp_response = mbim_device_command_finish (device, res, &error);
     if (!tmp_response) {
+        /* Translate a MbimDevice wrong state error into a Not-Opened function error. */
+        if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE)) {
+            request->response = mbim_message_function_error_new (mbim_message_get_transaction_id (request->message), MBIM_PROTOCOL_ERROR_NOT_OPENED);
+            request_complete_and_free (request);
+            return;
+        }
+
         g_debug ("sending request to device failed: %s", error->message);
         g_error_free (error);
         /* Don't disconnect client, just let the request timeout in its side */
@@ -885,6 +1004,13 @@
 
     request->response = mbim_device_command_finish (device, res, &error);
     if (!request->response) {
+        /* Translate a MbimDevice wrong state error into a Not-Opened function error. */
+        if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE)) {
+            request->response = mbim_message_function_error_new (request->original_transaction_id, MBIM_PROTOCOL_ERROR_NOT_OPENED);
+            request_complete_and_free (request);
+            return;
+        }
+
         g_debug ("sending request to device failed: %s", error->message);
         g_error_free (error);
         /* Don't disconnect client, just let the request timeout in its side */
diff --git a/src/libmbim-glib/mbim-utils.c b/src/libmbim-glib/mbim-utils.c
index f5a766b..a7541ae 100644
--- a/src/libmbim-glib/mbim-utils.c
+++ b/src/libmbim-glib/mbim-utils.c
@@ -79,15 +79,22 @@
 __mbim_user_allowed (uid_t uid,
                      GError **error)
 {
+#ifndef MBIM_USERNAME_ENABLED
+    if (uid == 0)
+        return TRUE;
+#else
+# ifndef MBIM_USERNAME
+#  error MBIM username not defined
+# endif
+
     struct passwd *expected_usr = NULL;
 
+    /* Root user is always allowed, regardless of the specified MBIM_USERNAME */
+    if (uid == 0)
+        return TRUE;
+
     expected_usr = getpwnam (MBIM_USERNAME);
     if (!expected_usr) {
-        g_warning ("Unknown user configured: %s", MBIM_USERNAME);
-        /* Falling back to check for root user if the configured user is unknown */
-        if (uid == 0)
-            return TRUE;
-
         g_set_error (error,
                      MBIM_CORE_ERROR,
                      MBIM_CORE_ERROR_FAILED,
@@ -97,6 +104,7 @@
 
     if (uid == expected_usr->pw_uid)
         return TRUE;
+#endif
 
     g_set_error (error,
                  MBIM_CORE_ERROR,
diff --git a/src/mbim-proxy/76-mbim-proxy-device-ownership.rules.in b/src/mbim-proxy/76-mbim-proxy-device-ownership.rules.in
new file mode 100644
index 0000000..cea5c87
--- /dev/null
+++ b/src/mbim-proxy/76-mbim-proxy-device-ownership.rules.in
@@ -0,0 +1,12 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add|change|move", GOTO="mbim_proxy_device_ownership_end"
+
+# A 'cdc-wdm' device is from a MBIM and MBIM-based modems.
+KERNEL=="cdc-wdm[0-9]", DRIVERS=="cdc_mbim", SUBSYSTEM=="usbmisc", GOTO="mbim_proxy_device_ownership_change"
+GOTO="mbim_proxy_device_ownership_end"
+
+LABEL="mbim_proxy_device_ownership_change"
+OWNER="@MBIM_USERNAME@"
+
+LABEL="mbim_proxy_device_ownership_end"
diff --git a/src/mbim-proxy/Makefile.am b/src/mbim-proxy/Makefile.am
index 83a8ce4..33425e0 100644
--- a/src/mbim-proxy/Makefile.am
+++ b/src/mbim-proxy/Makefile.am
@@ -14,3 +14,12 @@
 mbim_proxy_LDADD = \
 	$(MBIMPROXY_LIBS) \
 	$(top_builddir)/src/libmbim-glib/libmbim-glib.la
+
+#Install udev rules only if configured with --enable-mbim-username
+if MBIM_USERNAME_ENABLED
+udevrulesdir = $(UDEV_BASE_DIR)/rules.d
+udevrules_DATA = 76-mbim-proxy-device-ownership.rules
+endif
+
+EXTRA_DIST = \
+	76-mbim-proxy-device-ownership.rules.in
diff --git a/src/mbimcli/Makefile.am b/src/mbimcli/Makefile.am
index 22313a4..4d77ebd 100644
--- a/src/mbimcli/Makefile.am
+++ b/src/mbimcli/Makefile.am
@@ -21,3 +21,15 @@
 mbimcli_LDADD = \
 	$(MBIMCLI_LIBS) \
 	$(top_builddir)/src/libmbim-glib/libmbim-glib.la
+
+
+completiondir = $(datadir)/bash-completion/completions
+
+install-data-hook:
+	$(mkinstalldirs) $(DESTDIR)$(completiondir)
+	$(INSTALL_DATA) $(srcdir)/mbimcli-completion $(DESTDIR)$(completiondir)/mbimcli
+
+uninstall-hook:
+	rm -f $(DESTDIR)$(completiondir)/mbimcli
+
+EXTRA_DIST = mbimcli-completion
diff --git a/src/mbimcli/mbimcli-basic-connect.c b/src/mbimcli/mbimcli-basic-connect.c
index a3e32f6..088d5db 100644
--- a/src/mbimcli/mbimcli-basic-connect.c
+++ b/src/mbimcli/mbimcli-basic-connect.c
@@ -271,7 +271,7 @@
     gchar *hardware_info;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -367,7 +367,7 @@
     gchar *telephone_numbers_str;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -430,7 +430,7 @@
     const gchar *software_radio_state_str;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -475,7 +475,7 @@
     guint32 max_dss_sessions;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -567,7 +567,7 @@
     guint32 remaining_attempts;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -671,7 +671,7 @@
     guint32 nw_error;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -802,7 +802,7 @@
     gchar *cellular_class_str;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -858,7 +858,7 @@
     guint i;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -928,7 +928,7 @@
     guint i;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -1007,7 +1007,7 @@
     gchar *registration_flag_str;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -1087,7 +1087,7 @@
     guint32 error_rate_threshold;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -1150,7 +1150,7 @@
     guint64 downlink_speed;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -1222,7 +1222,7 @@
     guint32 out_discards;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
diff --git a/src/mbimcli/mbimcli-completion b/src/mbimcli/mbimcli-completion
new file mode 100644
index 0000000..a458cef
--- /dev/null
+++ b/src/mbimcli/mbimcli-completion
@@ -0,0 +1,83 @@
+# mbimcli(1) completion                                      -*- shell-script -*-
+
+_mbimcli()
+{
+    local cur prev words cword split
+    _init_completion -s || return
+
+    case $prev in
+        '-d'|'--device')
+            _filedir
+            return 0
+            ;;
+        '--no-open')
+            COMPREPLY=( $(compgen -W "[Transaction-ID]" -- $cur) )
+            return 0
+            ;;
+        '--set-radio-state')
+            COMPREPLY=( $(compgen -W "[(on|off)]" -- $cur) )
+            return 0
+            ;;
+        '--enter-pin')
+            COMPREPLY=( $(compgen -W "[current-PIN]" -- $cur) )
+            return 0
+            ;;
+        '--change-pin')
+            COMPREPLY=( $(compgen -W "[(current-PIN),(new-PIN)]" -- $cur) )
+            return 0
+            ;;
+        '--enable-pin')
+            COMPREPLY=( $(compgen -W "[current-PIN]" -- $cur) )
+            return 0
+            ;;
+        '--disable-pin')
+            COMPREPLY=( $(compgen -W "[current-PIN]" -- $cur) )
+            return 0
+            ;;
+        '--enter-puk')
+            COMPREPLY=( $(compgen -W "[(PUK),(new-PIN)]" -- $cur) )
+            return 0
+            ;;
+        '--connect')
+            COMPREPLY=( $(compgen -W "[(APN),(PAP|CHAP|MSCHAPV2),(Username),(Password)]" -- $cur) )
+            return 0
+            ;;
+        '--phonebook-read')
+            COMPREPLY=( $(compgen -W "[(Phonebook-index)]" -- $cur) )
+            return 0
+            ;;
+        '--phonebook-write')
+            COMPREPLY=( $(compgen -W "[(Name),(Number)[,(Index)]]" -- $cur) )
+            return 0
+            ;;
+        '--phonebook-delete')
+            COMPREPLY=( $(compgen -W "[(Phonebook-index)]" -- $cur) )
+            return 0
+            ;;
+        '--dss-connect')
+            COMPREPLY=( $(compgen -W "[(UUID),(Session-ID)]" -- $cur) )
+            return 0
+            ;;
+        '--dss-disconnect')
+            COMPREPLY=( $(compgen -W "[(UUID),(Session-ID)]" -- $cur) )
+            return 0
+            ;;
+        '-V'|'--version')
+            return 0
+            ;;
+        '-h'|'--help'|'--help-all'|'--help-basic-connect'|'--help-phonebook'|'--help-dss'|'--help-ms-firmware-id'|'--help-ms-host-shutdown')
+            return 0
+            ;;
+    esac
+
+    $split && return 0
+
+    if [[ $cur == -* ]]; then
+        COMPREPLY=( $( compgen -W '$( _parse_help "$1" --help-all )' -- "$cur" ) )
+        [[ $COMPREPLY == *= ]] && compopt -o nospace
+        return 0
+    fi
+} &&
+complete -F _mbimcli mbimcli
+
+# ex: ts=4 sw=4 et filetype=sh
diff --git a/src/mbimcli/mbimcli-dss.c b/src/mbimcli/mbimcli-dss.c
index 5b1c83f..8144b0b 100644
--- a/src/mbimcli/mbimcli-dss.c
+++ b/src/mbimcli/mbimcli-dss.c
@@ -128,7 +128,7 @@
     GError *error = NULL;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         shutdown (FALSE);
diff --git a/src/mbimcli/mbimcli-ms-firmware-id.c b/src/mbimcli/mbimcli-ms-firmware-id.c
index 3563684..9cbd255 100644
--- a/src/mbimcli/mbimcli-ms-firmware-id.c
+++ b/src/mbimcli/mbimcli-ms-firmware-id.c
@@ -116,7 +116,7 @@
     gchar *firmware_id_str;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
diff --git a/src/mbimcli/mbimcli-ms-host-shutdown.c b/src/mbimcli/mbimcli-ms-host-shutdown.c
index 459b64d..3fa7869 100644
--- a/src/mbimcli/mbimcli-ms-host-shutdown.c
+++ b/src/mbimcli/mbimcli-ms-host-shutdown.c
@@ -114,7 +114,7 @@
     GError *error = NULL;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
diff --git a/src/mbimcli/mbimcli-phonebook.c b/src/mbimcli/mbimcli-phonebook.c
index f006fd4..bb4e1c0 100644
--- a/src/mbimcli/mbimcli-phonebook.c
+++ b/src/mbimcli/mbimcli-phonebook.c
@@ -196,7 +196,7 @@
     GError *error = NULL;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -226,7 +226,7 @@
     GError *error = NULL;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -258,7 +258,7 @@
     gint i = 0;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
@@ -306,7 +306,7 @@
     guint32 max_name;
 
     response = mbim_device_command_finish (device, res, &error);
-    if (!response || !mbim_message_command_done_get_result (response, &error)) {
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         g_printerr ("error: operation failed: %s\n", error->message);
         g_error_free (error);
         if (response)
diff --git a/utils/mbim-network.in b/utils/mbim-network.in
index e58a148..5ea8dd6 100755
--- a/utils/mbim-network.in
+++ b/utils/mbim-network.in
@@ -50,10 +50,10 @@
 }
 
 if [ $# -ne 2 ]; then
-    if [ $1 == "--help" ]; then
+    if [ "$1" = "--help" ]; then
         help
         exit 0
-    elif [ $1 == "--version" ]; then
+    elif [ "$1" = "--version" ]; then
         version
         exit 0
     fi