Merge cros/upstream to cros/main - 1.31.2-dev

Part of an uprev that contains the following commits:

" 9c0309f build: unstable release version bump to 1.31.2 (Aleksander Morgado)"
" da12982 libmbim-glib,proxy: no need to block MBIM_DEVICE_SIGNAL_ERROR during open (Aleksander Morgado)"
" c445aee libmbim-glib,device: avoid emitting SIGNAL_ERROR if device closed (Aleksander Morgado)"
" f459174 libmbim-glib,device: set open_status to OPEN_STATUS_CLOSED in mbim_device_close_force (Maciej S. Szmigiero)"
" bdfcccc mbimcli,build: fix order of source files (Aleksander Morgado)"
" 9f385e8 mbimcli: Add sms functionality (Ulrich Mohr)"
" ef33322 mbim-codegen,struct: use internal struct free method on read failure (Aleksander Morgado)"
" 2fbe1cf libmbim-glib: ensure client is valid during message processing (Aleksander Morgado)"
" 22c99c8 docs,libmbim-glib: added 1.32 API index (Aleksander Morgado)"
" 482fc42 mbimcli,fibocom:add fibocom mbim service and cid 1 to send at command. (chenhaotian)"
" 3b61abb libmbim-glib,udev: remove GOTO in ownership change rule (Aleksander Morgado)"
" 658742a libmbim-glib,udev: avoid [0-9] as shell globbing pattern (Aleksander Morgado)"
" 36b9d60 libmbim-glib: the device ownership rules are not proxy specific (Aleksander Morgado)"
" 93ba75b libmbim-glib,tlv: ensure TLV header is aligned when reading it (Aleksander Morgado)"
" f38909c libmbim-glib,tlv: validate TLV header contents in new_from_raw() (Aleksander Morgado)"
" 42da4b2 data: Fix permissions on MS Basic Connect Extensions JSON (Eric Caruso)"
" 6fa33b4 libmbim-glib,fuzzer: attempt printable string build with other MBIMEx versions (Aleksander Morgado)"

BUG=b:309746013
FIXED=b:309746013

TEST=None

Change-Id: I94186407d4359243bfdf172a888c7b2ae332209c
diff --git a/build-aux/mbim-codegen/Struct.py b/build-aux/mbim-codegen/Struct.py
index 6aa0af6..74d9958 100644
--- a/build-aux/mbim-codegen/Struct.py
+++ b/build-aux/mbim-codegen/Struct.py
@@ -720,19 +720,8 @@
             '        g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,\n'
             '                     \"Read %u bytes from struct with size %u\", total_bytes_read, explicit_struct_size);\n'
             '    }\n'
-            '\n')
-
-        for field in self.contents:
-            translations['field_name_underscore'] = utils.build_underscore_name_from_camelcase(field['name'])
-            inner_template = ''
-            if field['format'] in ['ref-byte-array', 'ref-byte-array-no-offset', 'unsized-byte-array', 'byte-array', 'string']:
-                inner_template = ('    g_free (out->${field_name_underscore});\n')
-            elif field['format'] == 'string-array':
-                inner_template = ('    g_strfreev (out->${field_name_underscore});\n')
-            template += string.Template(inner_template).substitute(translations)
-
-        template += (
-            '    g_free (out);\n'
+            '\n'
+            '    _${name_underscore}_free (out);\n'
             '    return NULL;\n'
             '}\n')
         cfile.write(string.Template(template).substitute(translations))
diff --git a/data/mbim-service-fibocom.json b/data/mbim-service-fibocom.json
new file mode 100644
index 0000000..664789a
--- /dev/null
+++ b/data/mbim-service-fibocom.json
@@ -0,0 +1,16 @@
+[
+  // *********************************************************************************
+  { "type" : "Service",
+    "name" : "Fibocom" },
+
+  // *********************************************************************************
+
+  { "name"         : "AT Command",
+    "type"         : "Command",
+    "since"        : "1.32",
+    "set"          : [ { "name"          : "CommandReq",
+                         "format"        : "unsized-byte-array",
+                         "pad-array"     : "FALSE"} ],
+    "response"     : [ { "name"          : "CommandResp",
+                         "format"        : "unsized-byte-array"} ] }
+]
diff --git a/data/mbim-service-ms-basic-connect-extensions.json b/data/mbim-service-ms-basic-connect-extensions.json
old mode 100755
new mode 100644
diff --git a/docs/reference/libmbim-glib/libmbim-glib-common.sections b/docs/reference/libmbim-glib/libmbim-glib-common.sections
index e22acc3..98d845d 100644
--- a/docs/reference/libmbim-glib/libmbim-glib-common.sections
+++ b/docs/reference/libmbim-glib/libmbim-glib-common.sections
@@ -36,6 +36,7 @@
 MBIM_UUID_INTEL_MUTUAL_AUTHENTICATION
 MBIM_UUID_INTEL_TOOLS
 MBIM_UUID_GOOGLE
+MBIM_UUID_FIBOCOM
 <SUBSECTION Methods>
 mbim_service_get_string
 mbim_service_lookup_name
@@ -81,6 +82,7 @@
 MbimCidIntelMutualAuthentication
 MbimCidIntelTools
 MbimCidGoogle
+MbimCidFibocom
 <SUBSECTION Methods>
 mbim_cid_can_set
 mbim_cid_can_query
@@ -109,6 +111,7 @@
 mbim_cid_intel_mutual_authentication_get_string
 mbim_cid_intel_tools_get_string
 mbim_cid_google_get_string
+mbim_cid_fibocom_get_string
 <SUBSECTION Private>
 mbim_cid_atds_build_string_from_mask
 mbim_cid_basic_connect_build_string_from_mask
@@ -133,6 +136,7 @@
 mbim_cid_intel_mutual_authentication_build_string_from_mask
 mbim_cid_intel_tools_build_string_from_mask
 mbim_cid_google_build_string_from_mask
+mbim_cid_fibocom_build_string_from_mask
 <SUBSECTION Standard>
 MBIM_TYPE_CID_ATDS
 MBIM_TYPE_CID_AUTH
@@ -157,6 +161,7 @@
 MBIM_TYPE_CID_INTEL_MUTUAL_AUTHENTICATION
 MBIM_TYPE_CID_INTEL_TOOLS
 MBIM_TYPE_CID_GOOGLE
+MBIM_TYPE_CID_FIBOCOM
 mbim_cid_atds_get_type
 mbim_cid_auth_get_type
 mbim_cid_basic_connect_get_type
@@ -180,6 +185,7 @@
 mbim_cid_intel_mutual_authentication_get_type
 mbim_cid_intel_tools_get_type
 mbim_cid_google_get_type
+mbim_cid_fibocom_get_type
 </SECTION>
 
 <SECTION>
diff --git a/docs/reference/libmbim-glib/libmbim-glib-docs.xml b/docs/reference/libmbim-glib/libmbim-glib-docs.xml
index 84d322f..426d188 100644
--- a/docs/reference/libmbim-glib/libmbim-glib-docs.xml
+++ b/docs/reference/libmbim-glib/libmbim-glib-docs.xml
@@ -120,6 +120,11 @@
   </chapter>
 
   <chapter>
+    <title>Fibocom-defined Services</title>
+    <xi:include href="xml/mbim-fibocom.xml"/>
+  </chapter>
+
+  <chapter>
     <title>libmbim-defined Services</title>
     <xi:include href="xml/mbim-proxy-control.xml"/>
   </chapter>
@@ -201,6 +206,10 @@
     <title>Index of new symbols in 1.30</title>
     <xi:include href="xml/api-index-1.30.xml"></xi:include>
   </chapter>
+  <chapter id="api-index-1-32" role="1.32">
+    <title>Index of new symbols in 1.32</title>
+    <xi:include href="xml/api-index-1.32.xml"></xi:include>
+  </chapter>
 
   <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
 </book>
diff --git a/meson.build b/meson.build
index 2901eec..83d5187 100644
--- a/meson.build
+++ b/meson.build
@@ -3,7 +3,7 @@
 
 project(
   'libmbim', 'c',
-  version: '1.31.1',
+  version: '1.31.2',
   license: ['GPL-2.0-or-later', 'LGPL-2.1-or-later'],
   default_options: [
     'buildtype=debugoptimized',
diff --git a/src/libmbim-glib/76-mbim-device-ownership.rules.in b/src/libmbim-glib/76-mbim-device-ownership.rules.in
new file mode 100644
index 0000000..6b5526f
--- /dev/null
+++ b/src/libmbim-glib/76-mbim-device-ownership.rules.in
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add|change|move", GOTO="mbim_device_ownership_end"
+
+KERNEL=="cdc-wdm*", DRIVERS=="cdc_mbim", SUBSYSTEM=="usbmisc", OWNER="@MBIM_USERNAME@"
+
+LABEL="mbim_device_ownership_end"
diff --git a/src/libmbim-glib/generated/meson.build b/src/libmbim-glib/generated/meson.build
index 0153c22..46aa94b 100644
--- a/src/libmbim-glib/generated/meson.build
+++ b/src/libmbim-glib/generated/meson.build
@@ -147,6 +147,7 @@
   ['intel-mutual-authentication'],
   ['intel-tools'],
   ['google'],
+  ['fibocom'],
 ]
 
 foreach service_data: services_data
diff --git a/src/libmbim-glib/libmbim-glib.h b/src/libmbim-glib/libmbim-glib.h
index d096051..7ad8365 100644
--- a/src/libmbim-glib/libmbim-glib.h
+++ b/src/libmbim-glib/libmbim-glib.h
@@ -50,6 +50,7 @@
 #include "mbim-intel-mutual-authentication.h"
 #include "mbim-intel-tools.h"
 #include "mbim-google.h"
+#include "mbim-fibocom.h"
 
 /* backwards compatibility */
 #include "mbim-compat.h"
diff --git a/src/libmbim-glib/mbim-cid.c b/src/libmbim-glib/mbim-cid.c
index cb8ee6e..be51e8c 100644
--- a/src/libmbim-glib/mbim-cid.c
+++ b/src/libmbim-glib/mbim-cid.c
@@ -254,6 +254,12 @@
     { SET, QUERY, NOTIFY }, /* MBIM_CID_GOOGLE_CARRIER_LOCK */
 };
 
+/* Note: index of the array is CID-1 */
+#define MBIM_CID_FIBOCOM_LAST MBIM_CID_FIBOCOM_AT_COMMAND
+static const CidConfig cid_fibocom_config [MBIM_CID_FIBOCOM_LAST] = {
+    { SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_FIBOCOM_AT_COMMAND */
+};
+
 
 gboolean
 mbim_cid_can_set (MbimService service,
@@ -312,6 +318,8 @@
         return cid_intel_tools_config[cid - 1].set;
     case MBIM_SERVICE_GOOGLE:
         return cid_google_config[cid - 1].set;
+    case MBIM_SERVICE_FIBOCOM:
+        return cid_fibocom_config[cid - 1].set;
     case MBIM_SERVICE_INVALID:
     case MBIM_SERVICE_LAST:
     default:
@@ -377,6 +385,8 @@
         return cid_intel_tools_config[cid - 1].query;
     case MBIM_SERVICE_GOOGLE:
         return cid_google_config[cid - 1].query;
+    case MBIM_SERVICE_FIBOCOM:
+        return cid_fibocom_config[cid - 1].query;
     case MBIM_SERVICE_INVALID:
     case MBIM_SERVICE_LAST:
     default:
@@ -442,6 +452,8 @@
         return cid_intel_tools_config[cid - 1].notify;
     case MBIM_SERVICE_GOOGLE:
         return cid_google_config[cid - 1].notify;
+    case MBIM_SERVICE_FIBOCOM:
+        return cid_fibocom_config[cid - 1].notify;
     case MBIM_SERVICE_INVALID:
     case MBIM_SERVICE_LAST:
     default:
@@ -508,6 +520,9 @@
         return mbim_cid_intel_tools_get_string (cid);
     case MBIM_SERVICE_GOOGLE:
         return mbim_cid_google_get_string (cid);
+    case MBIM_SERVICE_FIBOCOM:
+        return mbim_cid_fibocom_get_string (cid);
+
     case MBIM_SERVICE_LAST:
     default:
         g_assert_not_reached ();
diff --git a/src/libmbim-glib/mbim-cid.h b/src/libmbim-glib/mbim-cid.h
index 0666be0..7526b57 100644
--- a/src/libmbim-glib/mbim-cid.h
+++ b/src/libmbim-glib/mbim-cid.h
@@ -486,6 +486,20 @@
 } MbimCidGoogle;
 
 /**
+ * MbimCidFibocom:
+ * @MBIM_CID_FIBOCOM_UNKNOWN: Unknown command.
+ * @MBIM_CID_FIBOCOM_AT_COMMAND: AT over MBIM message.
+ *
+ * MBIM commands in the %MBIM_SERVICE_FIBOCOM service.
+ *
+ * Since: 1.32
+ */
+typedef enum { /*< since=1.32 >*/
+    MBIM_CID_FIBOCOM_UNKNOWN      = 0,
+    MBIM_CID_FIBOCOM_AT_COMMAND   = 1,
+} MbimCidFibocom;
+
+/**
  * mbim_cid_can_set:
  * @service: a #MbimService.
  * @cid: a command ID.
diff --git a/src/libmbim-glib/mbim-device.c b/src/libmbim-glib/mbim-device.c
index 89aa921..be9c6a5 100644
--- a/src/libmbim-glib/mbim-device.c
+++ b/src/libmbim-glib/mbim-device.c
@@ -97,10 +97,11 @@
 
     /* I/O channel, set when the file is open */
     GIOChannel *iochannel;
-    GSource *iochannel_source;
+    GSource    *iochannel_source;
     GByteArray *response;
-    OpenStatus open_status;
-    guint32 open_transaction_id;
+    OpenStatus  open_status;
+    guint32     open_transaction_id;
+    GError     *pending_error_indication;
 
     /* Support for mbim-proxy */
     GSocketClient *socket_client;
@@ -1079,8 +1080,10 @@
         }
 
         /* Build indication error before task completion, to ensure the message
-         * is valid */
-        error_indication = mbim_message_error_get_error (message);
+         * is valid by the time it is sent. This error will be cleared if the device
+         * gets closed while the transaction response is processed. */
+        g_assert (!self->priv->pending_error_indication);
+        self->priv->pending_error_indication = mbim_message_error_get_error (message);
 
         /* Try to match this transaction just per transaction ID */
         task = device_release_transaction (self,
@@ -1103,11 +1106,12 @@
             transaction_task_complete_and_free (task, NULL);
         }
 
-        /* Signals are emitted regardless of whether the transaction matched or not;
-         * and emitted after the task completion, because the listeners of this
-         * signal may decide to force-close the device, which in turn clears the
-         * internal buffer and the MbimMessage. */
-        g_signal_emit (self, signals[SIGNAL_ERROR], 0, error_indication);
+        /* Signals are emitted regardless of whether the transaction matched or not,
+         * and emitted after the task completion. If the device is forced closed during
+         * the transaction response processing, no error signal will be emitted. */
+        error_indication = g_steal_pointer (&self->priv->pending_error_indication);
+        if (error_indication)
+            g_signal_emit (self, signals[SIGNAL_ERROR], 0, error_indication);
         return;
     }
 
@@ -2148,6 +2152,10 @@
     g_clear_object (&self->priv->socket_connection);
     g_clear_object (&self->priv->socket_client);
 
+    /* Pending error indications are always cleared if the channel is
+     * closed */
+    g_clear_error (&self->priv->pending_error_indication);
+
     if (self->priv->iochannel_source) {
         g_source_destroy (self->priv->iochannel_source);
         g_source_unref (self->priv->iochannel_source);
@@ -2173,6 +2181,8 @@
 {
     g_return_val_if_fail (MBIM_IS_DEVICE (self), FALSE);
 
+    self->priv->open_status = OPEN_STATUS_CLOSED;
+
     return destroy_iochannel (self, error);
 }
 
diff --git a/src/libmbim-glib/mbim-message.c b/src/libmbim-glib/mbim-message.c
index 76d4a1f..5cd9995 100644
--- a/src/libmbim-glib/mbim-message.c
+++ b/src/libmbim-glib/mbim-message.c
@@ -44,6 +44,7 @@
 #include "mbim-intel-mutual-authentication.h"
 #include "mbim-intel-tools.h"
 #include "mbim-google.h"
+#include "mbim-fibocom.h"
 
 /*****************************************************************************/
 
@@ -2234,6 +2235,9 @@
         case MBIM_SERVICE_GOOGLE:
             fields_printable = __mbim_message_google_get_printable_fields (self, line_prefix, &inner_error);
             break;
+        case MBIM_SERVICE_FIBOCOM:
+            fields_printable = __mbim_message_fibocom_get_printable_fields (self, line_prefix, &inner_error);
+            break;
         case MBIM_SERVICE_INVALID:
         case MBIM_SERVICE_LAST:
             g_assert_not_reached ();
diff --git a/src/libmbim-glib/mbim-proxy.c b/src/libmbim-glib/mbim-proxy.c
index e9ff36a..e3304ef 100644
--- a/src/libmbim-glib/mbim-proxy.c
+++ b/src/libmbim-glib/mbim-proxy.c
@@ -503,10 +503,6 @@
                       g_object_ref (self));
 }
 
-static void proxy_device_error_cb (MbimDevice *device,
-                                   GError     *error,
-                                   MbimProxy  *self);
-
 static void
 internal_device_open_caps_query_ready (MbimDevice   *device,
                                        GAsyncResult *res,
@@ -518,9 +514,6 @@
 
     self = g_task_get_source_object (task);
 
-    /* Always unblock error signals */
-    g_signal_handlers_unblock_by_func (device, proxy_device_error_cb, self);
-
     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 */
@@ -567,11 +560,6 @@
     if (mbim_device_is_open (device)) {
         MbimMessage *message;
 
-        /* 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. */
-        g_signal_handlers_block_by_func (device, proxy_device_error_cb, self);
-
         g_debug ("[%s] checking device caps during client device open...",
                  mbim_device_get_path (device));
         message = mbim_message_device_caps_query_new (NULL);
diff --git a/src/libmbim-glib/mbim-uuid.c b/src/libmbim-glib/mbim-uuid.c
index d212831..cefb580 100644
--- a/src/libmbim-glib/mbim-uuid.c
+++ b/src/libmbim-glib/mbim-uuid.c
@@ -281,6 +281,14 @@
     .e = { 0xa8, 0x6a, 0xd9, 0xe1, 0x22, 0x45 }
 };
 
+static const MbimUuid uuid_fibocom = {
+    .a = { 0xff, 0xff, 0xff, 0xff },
+    .b = { 0xab, 0xca },
+    .c = { 0x4b, 0x11 },
+    .d = { 0xa4, 0xe2 },
+    .e = { 0xf2, 0xfc, 0x87, 0xf9, 0x44, 0x88 }
+};
+
 static GList *mbim_custom_service_list = NULL;
 
 typedef struct {
@@ -422,6 +430,8 @@
         return &uuid_intel_tools;
     case MBIM_SERVICE_GOOGLE:
         return &uuid_google;
+    case MBIM_SERVICE_FIBOCOM:
+        return &uuid_fibocom;
     case MBIM_SERVICE_LAST:
         g_assert_not_reached ();
     default:
@@ -507,6 +517,9 @@
     if (mbim_uuid_cmp (uuid, &uuid_google))
         return MBIM_SERVICE_GOOGLE;
 
+    if (mbim_uuid_cmp (uuid, &uuid_fibocom))
+        return MBIM_SERVICE_FIBOCOM;
+
     for (l = mbim_custom_service_list; l != NULL; l = l->next) {
         if (mbim_uuid_cmp (&((MbimCustomService *)l->data)->uuid, uuid))
             return ((MbimCustomService *)l->data)->service_id;
diff --git a/src/libmbim-glib/mbim-uuid.h b/src/libmbim-glib/mbim-uuid.h
index e329183..bc59508 100644
--- a/src/libmbim-glib/mbim-uuid.h
+++ b/src/libmbim-glib/mbim-uuid.h
@@ -117,6 +117,7 @@
  * @MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION: Intel mutual authentication commands. Since 1.30.
  * @MBIM_SERVICE_INTEL_TOOLS: Intel tools service. Since 1.30.
  * @MBIM_SERVICE_GOOGLE: Google specific service. Since 1.30
+ * @MBIM_SERVICE_FIBOCOM: Fibocom specific service. Since 1.32.
  * @MBIM_SERVICE_LAST: Internal value.
  *
  * Enumeration of the generic MBIM services.
@@ -148,6 +149,7 @@
     MBIM_SERVICE_INTEL_MUTUAL_AUTHENTICATION = 21,
     MBIM_SERVICE_INTEL_TOOLS                 = 22,
     MBIM_SERVICE_GOOGLE                      = 23,
+    MBIM_SERVICE_FIBOCOM                     = 24,
 #if defined LIBMBIM_GLIB_COMPILATION
     MBIM_SERVICE_LAST /*< skip >*/
 #endif
@@ -418,6 +420,17 @@
 #define MBIM_UUID_GOOGLE mbim_uuid_from_service (MBIM_SERVICE_GOOGLE)
 
 /**
+ * MBIM_UUID_FIBOCOM:
+ *
+ * Get the UUID of the %MBIM_SERVICE_FIBOCOM service.
+ *
+ * Returns: (transfer none): a #MbimUuid.
+ *
+ * Since: 1.32
+ */
+#define MBIM_UUID_FIBOCOM mbim_uuid_from_service (MBIM_SERVICE_FIBOCOM)
+
+/**
  * mbim_service_lookup_name:
  * @service: a MbimService or custom service.
  *
diff --git a/src/libmbim-glib/meson.build b/src/libmbim-glib/meson.build
index 148935c..0489548 100644
--- a/src/libmbim-glib/meson.build
+++ b/src/libmbim-glib/meson.build
@@ -139,4 +139,14 @@
   )
 endif
 
+if enable_mbim_username
+  configure_file(
+    input: '76-mbim-device-ownership.rules.in',
+    output: '@BASENAME@',
+    configuration: {'MBIM_USERNAME': mbim_username},
+    install_dir: udev_udevdir / 'rules.d',
+  )
+endif
+
+
 subdir('test')
diff --git a/src/libmbim-glib/test/test-message-fuzzer.c b/src/libmbim-glib/test/test-message-fuzzer.c
index 9c0731c..657c0a3 100644
--- a/src/libmbim-glib/test/test-message-fuzzer.c
+++ b/src/libmbim-glib/test/test-message-fuzzer.c
@@ -15,9 +15,9 @@
 LLVMFuzzerTestOneInput (const uint8_t *data,
                         size_t         size)
 {
-    g_autofree gchar       *printable = NULL;
-    g_autoptr(MbimMessage)  message = NULL;
-    g_autoptr(GError)       error = NULL;
+    g_autoptr(MbimMessage) message = NULL;
+    g_autoptr(GError)      error = NULL;
+    guint                  mbimex_version_major;
 
     if (!size)
       return 0;
@@ -28,12 +28,16 @@
         return 0;
     }
 
-    printable = mbim_message_get_printable_full (message, 1, 0, "---- ", FALSE, &error);
-    if (!printable) {
-        g_printerr ("error: %s\n", error->message);
-        return 0;
-    }
+    /* We support printing as MBIMEx 1, 2 and 3 */
+    for (mbimex_version_major = 1; mbimex_version_major <= 3; mbimex_version_major++) {
+        g_autofree gchar  *printable = NULL;
+        g_autoptr(GError) inner_error = NULL;
 
-    g_print ("%s\n", printable);
+        printable = mbim_message_get_printable_full (message, mbimex_version_major, 0, "---- ", FALSE, &inner_error);
+        if (!printable)
+            g_printerr ("error: %s\n", inner_error->message);
+        else
+            g_print ("%s\n", printable);
+    }
     return 0;
 }
diff --git a/src/mbim-proxy/76-mbim-proxy-device-ownership.rules.in b/src/mbim-proxy/76-mbim-proxy-device-ownership.rules.in
deleted file mode 100644
index 81755f2..0000000
--- a/src/mbim-proxy/76-mbim-proxy-device-ownership.rules.in
+++ /dev/null
@@ -1,14 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-# 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/meson.build b/src/mbim-proxy/meson.build
index c316aa6..7469a71 100644
--- a/src/mbim-proxy/meson.build
+++ b/src/mbim-proxy/meson.build
@@ -11,12 +11,3 @@
   install: true,
   install_dir: mbim_libexecdir,
 )
-
-if enable_mbim_username
-  configure_file(
-    input: '76-mbim-proxy-device-ownership.rules.in',
-    output: '@BASENAME@',
-    configuration: {'MBIM_USERNAME': mbim_username},
-    install_dir: udev_udevdir / 'rules.d',
-  )
-endif
diff --git a/src/mbimcli/mbimcli-fibocom.c b/src/mbimcli/mbimcli-fibocom.c
new file mode 100644
index 0000000..23f8f5b
--- /dev/null
+++ b/src/mbimcli/mbimcli-fibocom.c
@@ -0,0 +1,158 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * mbimcli -- Command line interface to control MBIM devices
+ *
+ * Copyright (C) 2023 chenhaotian <rick.chen@fibocom.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libmbim-glib.h>
+
+#include "mbimcli.h"
+#include "mbimcli-helpers.h"
+
+/* Context */
+typedef struct {
+    MbimDevice *device;
+    GCancellable *cancellable;
+} Context;
+static Context *ctx;
+
+/* Options */
+static gchar *set_at_command_str;
+
+static GOptionEntry entries[] = {
+    { "fibocom-set-at-command", 0, 0, G_OPTION_ARG_STRING, &set_at_command_str,
+      "send AT command to modem, and receive AT response",
+      "\"<AT command>\""
+    },
+    { NULL, 0, 0, 0, NULL, NULL, NULL }
+};
+
+GOptionGroup *
+mbimcli_fibocom_get_option_group (void)
+{
+   GOptionGroup *group;
+
+   group = g_option_group_new ("fibocom",
+                               "FIbocom options:",
+                               "Show Fibocom Service options",
+                               NULL,
+                               NULL);
+   g_option_group_add_entries (group, entries);
+   return group;
+}
+
+gboolean
+mbimcli_fibocom_options_enabled (void)
+{
+    static guint n_actions = 0;
+    static gboolean checked = FALSE;
+
+    if (checked)
+        return !!n_actions;
+
+    n_actions = !!set_at_command_str;
+
+    if (n_actions > 1) {
+        g_printerr ("error: too many fibocom actions requested\n");
+        exit (EXIT_FAILURE);
+    }
+
+    checked = TRUE;
+    return !!n_actions;
+}
+
+static void
+context_free (Context *context)
+{
+    if (!context)
+        return;
+
+    if (context->cancellable)
+        g_object_unref (context->cancellable);
+    if (context->device)
+        g_object_unref (context->device);
+    g_slice_free (Context, context);
+}
+
+static void
+shutdown (gboolean operation_status)
+{
+    /* Cleanup context and finish async operation */
+    context_free (ctx);
+    mbimcli_async_operation_done (operation_status);
+}
+
+static void
+fibocom_ready (MbimDevice   *device,
+              GAsyncResult *res)
+{
+    g_autoptr(GError)      error     = NULL;
+    guint32                ret_size  = 0;
+    const guint8           *ret_str  = NULL;
+    g_autoptr(MbimMessage) response  = NULL;
+
+    response = mbim_device_command_finish (device, res, &error);
+
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
+        g_printerr ("error: operation failed: %s\n", error->message);
+        shutdown (FALSE);
+        return;
+    }
+
+    if (!mbim_message_fibocom_at_command_response_parse (
+            response,
+            &ret_size,
+            &ret_str,
+            &error)) {
+        g_printerr ("error: couldn't parse response message: %s\n", error->message);
+        shutdown (FALSE);
+        return;
+    }
+
+    g_print ("%.*s\n", ret_size, ret_str);
+
+    shutdown (TRUE);
+}
+
+void
+mbimcli_fibocom_run (MbimDevice   *device,
+                    GCancellable  *cancellable)
+{
+    g_autoptr(MbimMessage) request  = NULL;
+    g_autofree gchar       *req_str = NULL;
+    guint32                req_size = 0;
+
+    /* Initialize context */
+    ctx = g_slice_new (Context);
+    ctx->device = g_object_ref (device);
+    ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+    /* Request to send AT command */
+    if (set_at_command_str) {
+        req_str = g_strdup_printf ("%s\r\n", set_at_command_str);
+        req_size = strlen (req_str);
+
+        request = mbim_message_fibocom_at_command_set_new (req_size, (const guint8 *)req_str, NULL);
+        mbim_device_command (ctx->device,
+                             request,
+                             10,
+                             ctx->cancellable,
+                             (GAsyncReadyCallback)fibocom_ready,
+                             NULL);
+        return;
+    }
+
+    g_warn_if_reached ();
+}
diff --git a/src/mbimcli/mbimcli-helpers.h b/src/mbimcli/mbimcli-helpers.h
index 91410e8..b8c4fa4 100644
--- a/src/mbimcli/mbimcli-helpers.h
+++ b/src/mbimcli/mbimcli-helpers.h
@@ -71,7 +71,8 @@
     MBIMCLI_ENUM_LIST_ITEM (MbimUiccClassByteType,        uicc_class_byte_type,        "uicc class byte type")        \
     MBIMCLI_ENUM_LIST_ITEM (MbimUiccPassThroughAction,    uicc_pass_through_action,    "uicc pass through action")    \
     MBIMCLI_ENUM_LIST_ITEM (MbimIntelBootMode,            intel_boot_mode,             "intel boot mode")             \
-    MBIMCLI_ENUM_LIST_ITEM (MbimTraceCommand,             trace_command,               "trace command")
+    MBIMCLI_ENUM_LIST_ITEM (MbimTraceCommand,             trace_command,               "trace command")               \
+    MBIMCLI_ENUM_LIST_ITEM (MbimSmsFlag,                  sms_flag,                    "sms flag")
 
 #define MBIMCLI_ENUM_LIST_ITEM(TYPE,TYPE_UNDERSCORE,DESCR)        \
     gboolean mbimcli_read_## TYPE_UNDERSCORE ##_from_string (const gchar *str, TYPE *out);
diff --git a/src/mbimcli/mbimcli-sms.c b/src/mbimcli/mbimcli-sms.c
new file mode 100644
index 0000000..e8d82c5
--- /dev/null
+++ b/src/mbimcli/mbimcli-sms.c
@@ -0,0 +1,279 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * mbimcli -- Command line interface to control MBIM devices
+ *
+ * Copyright (C) 2022 Ulrich Mohr
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libmbim-glib.h>
+
+#include "mbimcli.h"
+#include "mbimcli-helpers.h"
+
+/* Context */
+typedef struct {
+    MbimDevice   *device;
+    GCancellable *cancellable;
+} Context;
+static Context *ctx;
+
+/* Options */
+static gchar *delete_str = NULL;
+static gchar *read_str = NULL;
+
+static GOptionEntry entries[] = {
+    { "sms-delete", 0, 0, G_OPTION_ARG_STRING, &delete_str,
+      "Delete all SMS matching a given filter",
+      "[(all|new|old|sent|draft|index=N)]"
+    },
+    { "sms-read", 0, 0, G_OPTION_ARG_STRING, &read_str,
+      "Read all SMS matching a given filter",
+      "[(all|new|old|sent|draft|index=N)]"
+    },
+    { NULL }
+};
+
+GOptionGroup *
+mbimcli_sms_get_option_group (void)
+{
+    GOptionGroup *group;
+
+    group = g_option_group_new ("sms",
+                                "Simple message service options:",
+                                "Show SMS service options",
+                                NULL,
+                                NULL);
+    g_option_group_add_entries (group, entries);
+
+    return group;
+}
+
+gboolean
+mbimcli_sms_options_enabled (void)
+{
+    static guint n_actions = 0;
+    static gboolean checked = FALSE;
+
+    if (checked)
+        return !!n_actions;
+
+    n_actions = (!!delete_str +
+                 !!read_str);
+    if (n_actions > 1) {
+        g_printerr ("error: too many SIM actions requested\n");
+        exit (EXIT_FAILURE);
+    }
+    checked = TRUE;
+
+    return !!n_actions;
+}
+
+static void
+context_free (Context *context)
+{
+    if (!context)
+        return;
+
+    if (context->cancellable)
+        g_object_unref (context->cancellable);
+    if (context->device)
+        g_object_unref (context->device);
+    g_slice_free (Context, context);
+}
+
+static void
+shutdown (gboolean operation_status)
+{
+    /* Cleanup context and finish async operation */
+    context_free (ctx);
+    mbimcli_async_operation_done (operation_status);
+}
+
+static void
+delete_sms_ready (MbimDevice   *device,
+                  GAsyncResult *res,
+                  gpointer      user_data)
+{
+    g_autoptr(MbimMessage) response = NULL;
+    g_autoptr(GError)      error = NULL;
+    MbimSmsFlag            filter = GPOINTER_TO_INT (user_data);
+
+    response = mbim_device_command_finish (device, res, &error);
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
+        g_printerr ("error: operation failed: %s\n", error->message);
+        shutdown (FALSE);
+        return;
+    }
+
+    if (!mbim_message_sms_delete_response_parse (response, &error)) {
+        g_printerr ("error: couldn't parse response message: %s\n", error->message);
+        shutdown (FALSE);
+        return;
+    }
+
+    if (filter != MBIM_SMS_FLAG_INDEX)
+        g_print ("Successfully deleted %s sms\n", mbim_sms_flag_get_string (filter));
+    else
+        g_print ("Successfully deleted sms\n");
+
+    shutdown (TRUE);
+    return;
+}
+
+static void
+read_sms_ready (MbimDevice   *device,
+                GAsyncResult *res,
+                gpointer      user_data)
+{
+    g_autoptr(MbimMessage)               response = NULL;
+    g_autoptr(GError)                    error = NULL;
+    g_autoptr(MbimSmsPduReadRecordArray) pdu_messages = NULL;
+    guint32                              num_messages = 0;
+    MbimSmsFlag                          filter = GPOINTER_TO_INT (user_data);
+
+    response = mbim_device_command_finish (device, res, &error);
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
+        g_printerr ("error: operation failed: %s\n", error->message);
+        shutdown (FALSE);
+        return;
+    }
+
+    if (!mbim_message_sms_read_response_parse (response, NULL, &num_messages, &pdu_messages, NULL, &error)) {
+        g_printerr ("error: couldn't parse response message: %s\n", error->message);
+        shutdown (FALSE);
+        return;
+    }
+
+    if (num_messages && pdu_messages) {
+        guint32 i = 0;
+
+        g_print ("Successfully read sms\n");
+        if (filter != MBIM_SMS_FLAG_INDEX)
+            g_print ("Got %d messages\n", num_messages);
+        while (pdu_messages[i]) {
+            g_print ("  PDU on index %u, status %s\n", pdu_messages[i]->message_index, mbim_sms_status_get_string (pdu_messages[i]->message_status));
+            i++;
+        }
+    } else {
+        if (filter == MBIM_SMS_FLAG_ALL)
+            g_print ("No messages found\n");
+        else if (filter != MBIM_SMS_FLAG_INDEX)
+            g_print ("No %s messages found\n", mbim_sms_flag_get_string (filter) );
+        else
+            g_print ("Message not found\n");
+    }
+
+    shutdown (TRUE);
+    return;
+}
+
+static gboolean
+op_parse (const gchar *str,
+          MbimSmsFlag *filter,
+          guint32     *index)
+{
+    gboolean   status       = FALSE;
+    gchar    **filter_parts = NULL;
+
+    g_assert (filter != NULL);
+
+    /* according to the mbim specification, index must be > 0 and 0 is used when not needed */
+    *index = 0;
+
+    filter_parts = g_strsplit (str, "=", -1);
+    if (filter_parts[0])
+        status = mbimcli_read_sms_flag_from_string (filter_parts[0], filter);
+    if (status) {
+        if (*filter == MBIM_SMS_FLAG_INDEX) {
+            status = filter_parts[1] && mbimcli_read_uint_from_string (filter_parts[1], index);
+            if (!status) {
+                if (!filter_parts[1])
+                    g_printerr ("error: required index not given\n");
+                else
+                    g_printerr ("error: couln't parse sms index, should be a number\n");
+            }
+            if (*index == 0)
+                g_printerr ("error: index must be > 0\n");
+        } else if (filter_parts[1]) {
+            g_printerr ("error: unexpected assignment for the given operation\n");
+            status = FALSE;
+        }
+    } else
+        status = FALSE;
+
+    g_strfreev (filter_parts);
+    return status;
+}
+
+void
+mbimcli_sms_run (MbimDevice   *device,
+                 GCancellable *cancellable)
+{
+    g_autoptr(MbimMessage) request = NULL;
+    g_autoptr(GError)      error = NULL;
+
+    /* Initialize context */
+    ctx = g_slice_new (Context);
+    ctx->device = g_object_ref (device);
+    ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+    if (delete_str) {
+        MbimSmsFlag filter;
+        guint32 index;
+
+        if (!op_parse (delete_str, &filter, &index)) {
+            shutdown (FALSE);
+            return;
+        }
+        request = mbim_message_sms_delete_set_new (filter, index, &error);
+        if (!request) {
+            g_printerr ("error: couldn't create request: %s\n", error->message);
+            shutdown (FALSE);
+            return;
+        }
+        mbim_device_command (ctx->device,
+                             request,
+                             10,
+                             ctx->cancellable,
+                             (GAsyncReadyCallback)delete_sms_ready,
+                             GINT_TO_POINTER (filter));
+        return;
+    }
+
+    if (read_str) {
+        MbimSmsFlag filter;
+        guint32 index;
+
+        if (!op_parse (read_str, &filter, &index)) {
+            shutdown (FALSE);
+            return;
+        }
+        request = mbim_message_sms_read_query_new (MBIM_SMS_FORMAT_PDU, filter, index, &error);
+        if (!request) {
+            g_printerr ("error: couldn't create request: %s\n", error->message);
+            shutdown (FALSE);
+            return;
+        }
+        mbim_device_command (ctx->device,
+                             request,
+                             10,
+                             ctx->cancellable,
+                             (GAsyncReadyCallback)read_sms_ready,
+                             GINT_TO_POINTER (filter));
+        return;
+    }
+
+    g_warn_if_reached ();
+}
diff --git a/src/mbimcli/mbimcli.c b/src/mbimcli/mbimcli.c
index bf08bd0..43b991b 100644
--- a/src/mbimcli/mbimcli.c
+++ b/src/mbimcli/mbimcli.c
@@ -358,6 +358,8 @@
         mbimcli_google_run (dev, cancellable);
         return;
     case MBIM_SERVICE_SMS:
+        mbimcli_sms_run (dev, cancellable);
+        return;
     case MBIM_SERVICE_USSD:
     case MBIM_SERVICE_STK:
     case MBIM_SERVICE_AUTH:
@@ -367,6 +369,10 @@
     case MBIM_SERVICE_INTEL_TOOLS:
         mbimcli_intel_tools_run (dev, cancellable);
         return;
+    case MBIM_SERVICE_FIBOCOM:
+        mbimcli_fibocom_run (dev, cancellable);
+        return;
+
         /* unsupported actions in the CLI */
     case MBIM_SERVICE_INVALID:
     default:
@@ -511,6 +517,16 @@
         actions_enabled++;
     }
 
+    if (mbimcli_fibocom_options_enabled ()) {
+        service = MBIM_SERVICE_FIBOCOM;
+        actions_enabled++;
+    }
+
+    if (mbimcli_sms_options_enabled()) {
+        service = MBIM_SERVICE_SMS;
+        actions_enabled++;
+    }
+
     /* Noop */
     if (noop_flag)
         actions_enabled++;
@@ -562,6 +578,9 @@
     g_option_context_add_group (context, mbimcli_intel_mutual_authentication_get_option_group ());
     g_option_context_add_group (context, mbimcli_intel_tools_get_option_group ());
     g_option_context_add_group (context, mbimcli_google_get_option_group());
+    g_option_context_add_group (context, mbimcli_fibocom_get_option_group());
+    g_option_context_add_group (context, mbimcli_sms_get_option_group ());
+
     g_option_context_add_main_entries (context, main_entries, NULL);
     if (!g_option_context_parse (context, &argc, &argv, &error)) {
         g_printerr ("error: %s\n", error->message);
diff --git a/src/mbimcli/mbimcli.h b/src/mbimcli/mbimcli.h
index 7bd23b6..c7f3859 100644
--- a/src/mbimcli/mbimcli.h
+++ b/src/mbimcli/mbimcli.h
@@ -34,6 +34,8 @@
 GOptionGroup *mbimcli_intel_mutual_authentication_get_option_group (void);
 GOptionGroup *mbimcli_intel_tools_get_option_group                 (void);
 GOptionGroup *mbimcli_google_get_option_group                      (void);
+GOptionGroup *mbimcli_fibocom_get_option_group                     (void);
+GOptionGroup *mbimcli_sms_get_option_group                         (void);
 
 gboolean      mbimcli_basic_connect_options_enabled               (void);
 gboolean      mbimcli_phonebook_options_enabled                   (void);
@@ -51,6 +53,8 @@
 gboolean      mbimcli_intel_mutual_authentication_options_enabled (void);
 gboolean      mbimcli_intel_tools_options_enabled                 (void);
 gboolean      mbimcli_google_options_enabled                      (void);
+gboolean      mbimcli_fibocom_options_enabled                     (void);
+gboolean      mbimcli_sms_options_enabled                         (void);
 
 void          mbimcli_basic_connect_run                 (MbimDevice   *device,
                                                          GCancellable *cancellable);
@@ -84,7 +88,10 @@
                                                          GCancellable *cancellable);
 void          mbimcli_google_run                        (MbimDevice   *device,
                                                          GCancellable *cancellable);
-
+void          mbimcli_fibocom_run                       (MbimDevice   *device,
+                                                         GCancellable *cancellable);
+void          mbimcli_sms_run                           (MbimDevice *device,
+                                                         GCancellable *cancellable);
 
 /* link management */
 GOptionGroup *mbimcli_link_management_get_option_group (void);
diff --git a/src/mbimcli/meson.build b/src/mbimcli/meson.build
index 9dc8cc3..41d3adc 100644
--- a/src/mbimcli/meson.build
+++ b/src/mbimcli/meson.build
@@ -2,23 +2,25 @@
 # Copyright (C) 2021 Iñigo Martinez <inigomartinez@gmail.com>
 
 mbimcli_sources = files(
+  'mbimcli.c',
   'mbimcli-atds.c',
   'mbimcli-basic-connect.c',
-  'mbimcli.c',
   'mbimcli-dss.c',
+  'mbimcli-fibocom.c',
+  'mbimcli-google.c',
   'mbimcli-intel-firmware-update.c',
+  'mbimcli-intel-mutual-authentication.c',
   'mbimcli-intel-thermal-rf.c',
+  'mbimcli-intel-tools.c',
   'mbimcli-ms-basic-connect-extensions.c',
   'mbimcli-ms-firmware-id.c',
-  'mbimcli-google.c',
   'mbimcli-ms-host-shutdown.c',
   'mbimcli-ms-sar.c',
   'mbimcli-ms-uicc-low-level-access.c',
   'mbimcli-ms-voice-extensions.c',
   'mbimcli-phonebook.c',
   'mbimcli-quectel.c',
-  'mbimcli-intel-mutual-authentication.c',
-  'mbimcli-intel-tools.c',
+  'mbimcli-sms.c',
 )
 
 sources = mbimcli_sources + files(